1// Copyright (c) 2012 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_UPDATER_EXTENSION_UPDATER_H_
6#define CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_UPDATER_H_
7
8#include <list>
9#include <map>
10#include <set>
11#include <stack>
12#include <string>
13
14#include "base/callback_forward.h"
15#include "base/compiler_specific.h"
16#include "base/files/file_path.h"
17#include "base/gtest_prod_util.h"
18#include "base/memory/scoped_ptr.h"
19#include "base/memory/weak_ptr.h"
20#include "base/scoped_observer.h"
21#include "base/time/time.h"
22#include "base/timer/timer.h"
23#include "chrome/browser/extensions/updater/extension_downloader.h"
24#include "chrome/browser/extensions/updater/extension_downloader_delegate.h"
25#include "content/public/browser/notification_observer.h"
26#include "content/public/browser/notification_registrar.h"
27#include "extensions/browser/extension_registry_observer.h"
28#include "extensions/browser/updater/manifest_fetch_data.h"
29#include "url/gurl.h"
30
31class ExtensionServiceInterface;
32class PrefService;
33class Profile;
34
35namespace content {
36class BrowserContext;
37}
38
39namespace extensions {
40
41class ExtensionCache;
42class ExtensionPrefs;
43class ExtensionRegistry;
44class ExtensionSet;
45class ExtensionUpdaterTest;
46
47// A class for doing auto-updates of installed Extensions. Used like this:
48//
49// ExtensionUpdater* updater = new ExtensionUpdater(my_extensions_service,
50//                                                  extension_prefs,
51//                                                  pref_service,
52//                                                  profile,
53//                                                  update_frequency_secs,
54//                                                  downloader_factory);
55// updater->Start();
56// ....
57// updater->Stop();
58class ExtensionUpdater : public ExtensionDownloaderDelegate,
59                         public ExtensionRegistryObserver,
60                         public content::NotificationObserver {
61 public:
62  typedef base::Closure FinishedCallback;
63
64  struct CheckParams {
65    // Creates a default CheckParams instance that checks for all extensions.
66    CheckParams();
67    ~CheckParams();
68
69    // The set of extensions that should be checked for updates. If empty
70    // all extensions will be included in the update check.
71    std::list<std::string> ids;
72
73    // Normally extension updates get installed only when the extension is idle.
74    // Setting this to true causes any updates that are found to be installed
75    // right away.
76    bool install_immediately;
77
78    // Callback to call when the update check is complete. Can be null, if
79    // you're not interested in when this happens.
80    FinishedCallback callback;
81  };
82
83  // Holds a pointer to the passed |service|, using it for querying installed
84  // extensions and installing updated ones. The |frequency_seconds| parameter
85  // controls how often update checks are scheduled.
86  ExtensionUpdater(ExtensionServiceInterface* service,
87                   ExtensionPrefs* extension_prefs,
88                   PrefService* prefs,
89                   Profile* profile,
90                   int frequency_seconds,
91                   ExtensionCache* cache,
92                   const ExtensionDownloader::Factory& downloader_factory);
93
94  virtual ~ExtensionUpdater();
95
96  // Starts the updater running.  Should be called at most once.
97  void Start();
98
99  // Stops the updater running, cancelling any outstanding update manifest and
100  // crx downloads. Does not cancel any in-progress installs.
101  void Stop();
102
103  // Posts a task to do an update check.  Does nothing if there is
104  // already a pending task that has not yet run.
105  void CheckSoon();
106
107  // Starts an update check for the specified extension soon. If a check
108  // is already running, or finished too recently without an update being
109  // installed, this method returns false and the check won't be scheduled.
110  bool CheckExtensionSoon(const std::string& extension_id,
111                          const FinishedCallback& callback);
112
113  // Starts an update check right now, instead of waiting for the next
114  // regularly scheduled check or a pending check from CheckSoon().
115  void CheckNow(const CheckParams& params);
116
117  // Returns true iff CheckSoon() has been called but the update check
118  // hasn't been performed yet.  This is used mostly by tests; calling
119  // code should just call CheckSoon().
120  bool WillCheckSoon() const;
121
122  // Changes the params that are used for the automatic periodic update checks,
123  // as well as for explicit calls to CheckSoon.
124  void set_default_check_params(const CheckParams& params) {
125    default_params_ = params;
126  }
127
128 private:
129  friend class ExtensionUpdaterTest;
130  friend class ExtensionUpdaterFileHandler;
131
132  // FetchedCRXFile holds information about a CRX file we fetched to disk,
133  // but have not yet installed.
134  struct FetchedCRXFile {
135    FetchedCRXFile();
136    FetchedCRXFile(const std::string& id,
137                   const base::FilePath& path,
138                   bool file_ownership_passed,
139                   const std::set<int>& request_ids);
140    ~FetchedCRXFile();
141
142    std::string extension_id;
143    base::FilePath path;
144    bool file_ownership_passed;
145    std::set<int> request_ids;
146  };
147
148  struct InProgressCheck {
149    InProgressCheck();
150    ~InProgressCheck();
151
152    bool install_immediately;
153    FinishedCallback callback;
154    // The ids of extensions that have in-progress update checks.
155    std::list<std::string> in_progress_ids_;
156  };
157
158  struct ThrottleInfo;
159
160  // Callback used to continue CheckNow after determining which extensions
161  // should be force-updated.
162  void OnForcedUpdatesDetermined(const CheckParams& params,
163                                 const std::set<std::string>& forced_updates);
164
165  // Ensure that we have a valid ExtensionDownloader instance referenced by
166  // |downloader|.
167  void EnsureDownloaderCreated();
168
169  // Computes when to schedule the first update check.
170  base::TimeDelta DetermineFirstCheckDelay();
171
172  // Sets the timer to call TimerFired after roughly |target_delay| from now.
173  // To help spread load evenly on servers, this method adds some random
174  // jitter. It also saves the scheduled time so it can be reloaded on
175  // browser restart.
176  void ScheduleNextCheck(const base::TimeDelta& target_delay);
177
178  // Add fetch records for extensions that are installed to the downloader,
179  // ignoring |pending_ids| so the extension isn't fetched again.
180  void AddToDownloader(const ExtensionSet* extensions,
181                       const std::list<std::string>& pending_ids,
182                       int request_id);
183
184  // BaseTimer::ReceiverMethod callback.
185  void TimerFired();
186
187  // Posted by CheckSoon().
188  void DoCheckSoon();
189
190  // Implementation of ExtensionDownloaderDelegate.
191  virtual void OnExtensionDownloadFailed(
192      const std::string& id,
193      Error error,
194      const PingResult& ping,
195      const std::set<int>& request_ids) OVERRIDE;
196  virtual void OnExtensionDownloadFinished(
197      const std::string& id,
198      const base::FilePath& path,
199      bool file_ownership_passed,
200      const GURL& download_url,
201      const std::string& version,
202      const PingResult& ping,
203      const std::set<int>& request_id) OVERRIDE;
204  virtual bool GetPingDataForExtension(
205      const std::string& id,
206      ManifestFetchData::PingData* ping_data) OVERRIDE;
207  virtual std::string GetUpdateUrlData(const std::string& id) OVERRIDE;
208  virtual bool IsExtensionPending(const std::string& id) OVERRIDE;
209  virtual bool GetExtensionExistingVersion(const std::string& id,
210                                           std::string* version) OVERRIDE;
211  virtual bool ShouldForceUpdate(const std::string& extension_id,
212                                 std::string* source) OVERRIDE;
213
214  void UpdatePingData(const std::string& id, const PingResult& ping_result);
215
216  // Starts installing a crx file that has been fetched but not installed yet.
217  void MaybeInstallCRXFile();
218
219  // content::NotificationObserver implementation.
220  virtual void Observe(int type,
221                       const content::NotificationSource& source,
222                       const content::NotificationDetails& details) OVERRIDE;
223
224  // Implementation of ExtensionRegistryObserver.
225  virtual void OnExtensionWillBeInstalled(
226      content::BrowserContext* browser_context,
227      const Extension* extension,
228      bool is_update,
229      bool from_ephemeral,
230      const std::string& old_name) OVERRIDE;
231
232  // Send a notification that update checks are starting.
233  void NotifyStarted();
234
235  // Send a notification if we're finished updating.
236  void NotifyIfFinished(int request_id);
237
238  void ExtensionCheckFinished(const std::string& extension_id,
239                              const FinishedCallback& callback);
240
241  // Whether Start() has been called but not Stop().
242  bool alive_;
243
244  // Pointer back to the service that owns this ExtensionUpdater.
245  ExtensionServiceInterface* service_;
246
247  // A closure passed into the ExtensionUpdater to teach it how to construct
248  // new ExtensionDownloader instances.
249  const ExtensionDownloader::Factory downloader_factory_;
250
251  // Fetches the crx files for the extensions that have an available update.
252  scoped_ptr<ExtensionDownloader> downloader_;
253
254  base::OneShotTimer<ExtensionUpdater> timer_;
255  int frequency_seconds_;
256  bool will_check_soon_;
257
258  ExtensionPrefs* extension_prefs_;
259  PrefService* prefs_;
260  Profile* profile_;
261
262  std::map<int, InProgressCheck> requests_in_progress_;
263  int next_request_id_;
264
265  // Observes CRX installs we initiate.
266  content::NotificationRegistrar registrar_;
267
268  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
269      extension_registry_observer_;
270
271  // True when a CrxInstaller is doing an install.  Used in MaybeUpdateCrxFile()
272  // to keep more than one install from running at once.
273  bool crx_install_is_running_;
274
275  // Fetched CRX files waiting to be installed.
276  std::stack<FetchedCRXFile> fetched_crx_files_;
277  FetchedCRXFile current_crx_file_;
278
279  CheckParams default_params_;
280
281  ExtensionCache* extension_cache_;
282
283  // Keeps track of when an extension tried to update itself, so we can throttle
284  // checks to prevent too many requests from being made.
285  std::map<std::string, ThrottleInfo> throttle_info_;
286
287  // Keeps track of extensions (by ID) whose update should be forced during the
288  // next update check.
289  std::set<std::string> forced_updates_;
290
291  base::WeakPtrFactory<ExtensionUpdater> weak_ptr_factory_;
292
293  DISALLOW_COPY_AND_ASSIGN(ExtensionUpdater);
294};
295
296}  // namespace extensions
297
298#endif  // CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_UPDATER_H_
299