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