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