1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_EXTENSIONS_FORCED_EXTENSIONS_FORCE_INSTALLED_TRACKER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_FORCED_EXTENSIONS_FORCE_INSTALLED_TRACKER_H_ 7 8 #include <map> 9 10 #include "base/observer_list.h" 11 #include "base/observer_list_types.h" 12 #include "base/scoped_observer.h" 13 #include "chrome/browser/extensions/extension_management.h" 14 #include "chrome/browser/extensions/forced_extensions/install_stage_tracker.h" 15 #include "components/policy/core/common/policy_service.h" 16 #include "components/prefs/pref_change_registrar.h" 17 #include "extensions/browser/extension_registry.h" 18 #include "extensions/browser/extension_registry_observer.h" 19 #include "extensions/browser/updater/extension_downloader_delegate.h" 20 #include "extensions/common/extension.h" 21 22 class PrefService; 23 class Profile; 24 25 namespace content { 26 class BrowserContext; 27 } 28 29 namespace extensions { 30 31 // Used to track status of force-installed extensions for the profile: are they 32 // successfully loaded, failed to install, or neither happened yet. 33 // ExtensionService owns this class and outlives it. 34 class ForceInstalledTracker : public ExtensionRegistryObserver, 35 public InstallStageTracker::Observer, 36 public policy::PolicyService::Observer { 37 public: 38 class Observer : public base::CheckedObserver { 39 public: 40 // Called after every force-installed extension is loaded (not yet 41 // installed) or reported as failure. 42 // 43 // Called exactly once, during startup (may take several minutes). Use 44 // IsDoneLoading() to know if it has already been called. If there are no 45 // force-installed extensions configured, this method still gets called. OnForceInstalledExtensionsLoaded()46 virtual void OnForceInstalledExtensionsLoaded() {} 47 48 // Same as OnForceInstalledExtensionsLoaded(), but after they're ready 49 // instead of loaded. 50 // 51 // Called exactly once, during startup (may take several minutes). Use 52 // IsReady() to know if it has already been called. If there are no 53 // force-installed extensions configured, this method still gets called. OnForceInstalledExtensionsReady()54 virtual void OnForceInstalledExtensionsReady() {} 55 56 // Called when cache status is retrieved from InstallationStageTracker. OnExtensionDownloadCacheStatusRetrieved(const ExtensionId & id,ExtensionDownloaderDelegate::CacheStatus cache_status)57 virtual void OnExtensionDownloadCacheStatusRetrieved( 58 const ExtensionId& id, 59 ExtensionDownloaderDelegate::CacheStatus cache_status) {} 60 }; 61 62 ForceInstalledTracker(ExtensionRegistry* registry, Profile* profile); 63 64 ~ForceInstalledTracker() override; 65 66 ForceInstalledTracker(const ForceInstalledTracker&) = delete; 67 ForceInstalledTracker& operator=(const ForceInstalledTracker&) = delete; 68 69 // Returns true if all extensions loaded/failed loading. 70 bool IsDoneLoading() const; 71 72 // Returns true if all extensions installed/failed installing. 73 bool IsReady() const; 74 75 // Add/remove observers to this object, to get notified when installation is 76 // finished. 77 void AddObserver(Observer* observer); 78 void RemoveObserver(Observer* observer); 79 80 // ExtensionRegistryObserver overrides: 81 void OnExtensionLoaded(content::BrowserContext* browser_context, 82 const Extension* extension) override; 83 void OnExtensionReady(content::BrowserContext* browser_context, 84 const Extension* extension) override; 85 void OnShutdown(ExtensionRegistry*) override; 86 87 // InstallStageTracker::Observer overrides: 88 void OnExtensionInstallationFailed( 89 const ExtensionId& extension_id, 90 InstallStageTracker::FailureReason reason) override; 91 void OnExtensionDownloadCacheStatusRetrieved( 92 const ExtensionId& id, 93 ExtensionDownloaderDelegate::CacheStatus cache_status) override; 94 95 // policy::PolicyService::Observer overrides: 96 void OnPolicyUpdated(const policy::PolicyNamespace& ns, 97 const policy::PolicyMap& previous, 98 const policy::PolicyMap& current) override; 99 100 void OnPolicyServiceInitialized(policy::PolicyDomain domain) override; 101 102 enum class ExtensionStatus { 103 // Extension appears in force-install list, but it not installed yet. 104 PENDING, 105 106 // Extension was successfully loaded. 107 LOADED, 108 109 // Extension is ready. This happens after loading. 110 READY, 111 112 // Extension installation failure was reported. 113 FAILED 114 }; 115 116 // Helper struct with supplementary info for extensions from force-install 117 // list. 118 struct ExtensionInfo { 119 // Current status of the extension: loaded, failed, or still installing. 120 ExtensionStatus status; 121 122 // Additional info: whether extension is from Chrome Web Store, or 123 // self-hosted. 124 bool is_from_store; 125 }; 126 extensions()127 const std::map<ExtensionId, ExtensionInfo>& extensions() const { 128 return extensions_; 129 } 130 131 // Returns true only in case of some well-known admin side misconfigurations 132 // which are easy to detect. Can return false for misconfigurations which are 133 // hard to distinguish with other errors. 134 bool IsMisconfiguration( 135 const InstallStageTracker::InstallationData& installation_data, 136 const ExtensionId& id) const; 137 138 static bool IsExtensionFetchedFromCache( 139 const base::Optional<ExtensionDownloaderDelegate::CacheStatus>& status); 140 141 private: 142 policy::PolicyService* policy_service(); 143 144 // Fires OnForceInstallationFinished() on observers, then changes |status_| to 145 // kComplete. 146 void MaybeNotifyObservers(); 147 148 // Increment (or decrement) |load_pending_count_| and |install_pending_count_| 149 // by |delta|, depending on |status|. 150 void UpdateCounters(ExtensionStatus status, int delta); 151 152 // Helper method to modify |extensions_| and bounded counter, adds extension 153 // to the collection. 154 void AddExtensionInfo(const ExtensionId& extension_id, 155 ExtensionStatus status, 156 bool is_from_store); 157 158 // Helper method to modify |extensions_| and bounded counter, changes status 159 // of one extensions. 160 void ChangeExtensionStatus(const ExtensionId& extension_id, 161 ExtensionStatus status); 162 163 // Loads list of force-installed extensions if available. Only called once. 164 void OnForcedExtensionsPrefReady(); 165 166 const ExtensionManagement* extension_management_; 167 168 // Unowned, but guaranteed to outlive this object. 169 ExtensionRegistry* registry_; 170 Profile* profile_; 171 PrefService* pref_service_; 172 173 // Collection of all extensions we are interested in here. Don't update 174 // directly, use AddExtensionInfo/RemoveExtensionInfo/ChangeExtensionStatus 175 // methods, as |pending_extension_counter_| has to be in sync with contents of 176 // this collection. 177 std::map<ExtensionId, ExtensionInfo> extensions_; 178 179 // Number of extensions in |extensions_| with status |PENDING|. 180 size_t load_pending_count_ = 0; 181 // Number of extensions in |extensions_| with status |PENDING| or |LOADED|. 182 // (ie. could be loaded, but not ready yet). 183 size_t ready_pending_count_ = 0; 184 185 // Stores the current state of this tracker, to know when it's complete, and 186 // to perform sanity DCHECK()s. 187 enum Status { 188 // Waiting for PolicyService to finish initializing. Listening for 189 // OnPolicyServiceInitialized(). 190 kWaitingForPolicyService, 191 // Waiting for one or more extensions to finish loading. Listening for 192 // |ExtensionRegistryObserver| events. 193 kWaitingForExtensionLoads, 194 // Waiting for one or more extensions to finish loading. Listening for 195 // |ExtensionRegistryObserver| events. Extensions have already finished 196 // loading; we're still waiting for the "ready" state. IsDoneLoading() 197 // returns true, but IsReady() returns false. 198 kWaitingForExtensionReady, 199 // All extensions have finished installing (successfully or not); observers 200 // have been called exactly once, and IsDoneLoading() and IsReady() 201 // both return true. 202 kComplete, 203 }; 204 Status status_ = kWaitingForPolicyService; 205 206 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> 207 registry_observer_{this}; 208 ScopedObserver<InstallStageTracker, InstallStageTracker::Observer> 209 collector_observer_{this}; 210 211 base::ObserverList<Observer> observers_; 212 }; 213 214 } // namespace extensions 215 216 #endif // CHROME_BROWSER_EXTENSIONS_FORCED_EXTENSIONS_FORCE_INSTALLED_TRACKER_H_ 217