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_CRX_INSTALLER_H_
6#define CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
7
8#include <string>
9#include <vector>
10
11#include "base/compiler_specific.h"
12#include "base/files/file_path.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/weak_ptr.h"
15#include "base/version.h"
16#include "chrome/browser/extensions/blacklist.h"
17#include "chrome/browser/extensions/extension_install_checker.h"
18#include "chrome/browser/extensions/extension_install_prompt.h"
19#include "chrome/browser/extensions/extension_service.h"
20#include "chrome/browser/extensions/sandboxed_unpacker.h"
21#include "chrome/browser/extensions/webstore_installer.h"
22#include "chrome/common/extensions/extension_constants.h"
23#include "extensions/browser/install_flag.h"
24#include "extensions/common/extension.h"
25#include "extensions/common/manifest.h"
26#include "sync/api/string_ordinal.h"
27
28class ExtensionService;
29class ExtensionServiceTest;
30class SkBitmap;
31struct WebApplicationInfo;
32
33namespace base {
34class SequencedTaskRunner;
35}
36
37namespace extensions {
38class CrxInstallerError;
39class ExtensionUpdaterTest;
40class RequirementsChecker;
41
42// This class installs a crx file into a profile.
43//
44// Installing a CRX is a multi-step process, including unpacking the crx,
45// validating it, prompting the user, and installing. Since many of these
46// steps must occur on the file thread, this class contains a copy of all data
47// necessary to do its job. (This also minimizes external dependencies for
48// easier testing).
49//
50// Lifetime management:
51//
52// This class is ref-counted by each call it makes to itself on another thread,
53// and by UtilityProcessHost.
54//
55// Additionally, we hold a reference to our own client so that it lives at least
56// long enough to receive the result of unpacking.
57//
58// IMPORTANT: Callers should keep a reference to a CrxInstaller while they are
59// working with it, eg:
60//
61// scoped_refptr<CrxInstaller> installer(new CrxInstaller(...));
62// installer->set_foo();
63// installer->set_bar();
64// installer->InstallCrx(...);
65//
66// Installation is aborted if the extension service learns that Chrome is
67// terminating during the install. We can't listen for the app termination
68// notification here in this class because it can be destroyed on any thread
69// and won't safely be able to clean up UI thread notification listeners.
70class CrxInstaller
71    : public SandboxedUnpackerClient,
72      public ExtensionInstallPrompt::Delegate {
73 public:
74  // Used in histograms; do not change order.
75  enum OffStoreInstallAllowReason {
76    OffStoreInstallDisallowed,
77    OffStoreInstallAllowedFromSettingsPage,
78    OffStoreInstallAllowedBecausePref,
79    OffStoreInstallAllowedInTest,
80    NumOffStoreInstallAllowReasons
81  };
82
83  // Extensions will be installed into service->install_directory(), then
84  // registered with |service|. This does a silent install - see below for
85  // other options.
86  static scoped_refptr<CrxInstaller> CreateSilent(ExtensionService* service);
87
88  // Same as above, but use |client| to generate a confirmation prompt.
89  static scoped_refptr<CrxInstaller> Create(
90      ExtensionService* service,
91      scoped_ptr<ExtensionInstallPrompt> client);
92
93  // Same as the previous method, except use the |approval| to bypass the
94  // prompt. Note that the caller retains ownership of |approval|.
95  static scoped_refptr<CrxInstaller> Create(
96      ExtensionService* service,
97      scoped_ptr<ExtensionInstallPrompt> client,
98      const WebstoreInstaller::Approval* approval);
99
100  // Install the crx in |source_file|.
101  void InstallCrx(const base::FilePath& source_file);
102
103  // Convert the specified user script into an extension and install it.
104  void InstallUserScript(const base::FilePath& source_file,
105                         const GURL& download_url);
106
107  // Convert the specified web app into an extension and install it.
108  void InstallWebApp(const WebApplicationInfo& web_app);
109
110  // Overridden from ExtensionInstallPrompt::Delegate:
111  virtual void InstallUIProceed() OVERRIDE;
112  virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
113
114  int creation_flags() const { return creation_flags_; }
115  void set_creation_flags(int val) { creation_flags_ = val; }
116
117  const base::FilePath& source_file() const { return source_file_; }
118
119  Manifest::Location install_source() const {
120    return install_source_;
121  }
122  void set_install_source(Manifest::Location source) {
123    install_source_ = source;
124  }
125
126  const std::string& expected_id() const { return expected_id_; }
127  void set_expected_id(const std::string& val) { expected_id_ = val; }
128
129  void set_expected_version(const Version& val) {
130    expected_version_.reset(new Version(val));
131    expected_version_strict_checking_ = true;
132  }
133
134  bool delete_source() const { return delete_source_; }
135  void set_delete_source(bool val) { delete_source_ = val; }
136
137  bool allow_silent_install() const { return allow_silent_install_; }
138  void set_allow_silent_install(bool val) { allow_silent_install_ = val; }
139
140  bool grant_permissions() const { return grant_permissions_; }
141  void set_grant_permissions(bool val) { grant_permissions_ = val; }
142
143  bool is_gallery_install() const {
144    return (creation_flags_ & Extension::FROM_WEBSTORE) > 0;
145  }
146  void set_is_gallery_install(bool val) {
147    if (val)
148      creation_flags_ |= Extension::FROM_WEBSTORE;
149    else
150      creation_flags_ &= ~Extension::FROM_WEBSTORE;
151  }
152
153  // If |apps_require_extension_mime_type_| is set to true, be sure to set
154  // |original_mime_type_| as well.
155  void set_apps_require_extension_mime_type(
156      bool apps_require_extension_mime_type) {
157    apps_require_extension_mime_type_ = apps_require_extension_mime_type;
158  }
159
160  void set_original_mime_type(const std::string& original_mime_type) {
161    original_mime_type_ = original_mime_type;
162  }
163
164  extension_misc::CrxInstallCause install_cause() const {
165    return install_cause_;
166  }
167  void set_install_cause(extension_misc::CrxInstallCause install_cause) {
168    install_cause_ = install_cause;
169  }
170
171  OffStoreInstallAllowReason off_store_install_allow_reason() const {
172    return off_store_install_allow_reason_;
173  }
174  void set_off_store_install_allow_reason(OffStoreInstallAllowReason reason) {
175    off_store_install_allow_reason_ = reason;
176  }
177
178  void set_page_ordinal(const syncer::StringOrdinal& page_ordinal) {
179    page_ordinal_ = page_ordinal;
180  }
181
182  void set_error_on_unsupported_requirements(bool val) {
183    error_on_unsupported_requirements_ = val;
184  }
185
186  void set_install_immediately(bool val) {
187    set_install_flag(kInstallFlagInstallImmediately, val);
188  }
189  void set_is_ephemeral(bool val) {
190    set_install_flag(kInstallFlagIsEphemeral, val);
191  }
192  void set_do_not_sync(bool val) {
193    set_install_flag(kInstallFlagDoNotSync, val);
194  }
195
196  bool did_handle_successfully() const { return did_handle_successfully_; }
197
198  Profile* profile() { return install_checker_.profile(); }
199
200  const Extension* extension() { return install_checker_.extension().get(); }
201
202  const std::string& current_version() const { return current_version_; }
203
204 private:
205  friend class ::ExtensionServiceTest;
206  friend class ExtensionUpdaterTest;
207  friend class ExtensionCrxInstallerTest;
208
209  CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
210               scoped_ptr<ExtensionInstallPrompt> client,
211               const WebstoreInstaller::Approval* approval);
212  virtual ~CrxInstaller();
213
214  // Converts the source user script to an extension.
215  void ConvertUserScriptOnFileThread();
216
217  // Converts the source web app to an extension.
218  void ConvertWebAppOnFileThread(const WebApplicationInfo& web_app);
219
220  // Called after OnUnpackSuccess as a last check to see whether the install
221  // should complete.
222  CrxInstallerError AllowInstall(const Extension* extension);
223
224  // SandboxedUnpackerClient
225  virtual void OnUnpackFailure(const base::string16& error_message) OVERRIDE;
226  virtual void OnUnpackSuccess(const base::FilePath& temp_dir,
227                               const base::FilePath& extension_dir,
228                               const base::DictionaryValue* original_manifest,
229                               const Extension* extension,
230                               const SkBitmap& install_icon) OVERRIDE;
231
232  // Called on the UI thread to start the requirements, policy and blacklist
233  // checks on the extension.
234  void CheckInstall();
235
236  // Runs on the UI thread. Callback from ExtensionInstallChecker.
237  void OnInstallChecksComplete(int failed_checks);
238
239  // Runs on the UI thread. Callback from Blacklist.
240  void OnBlacklistChecked(
241      extensions::BlacklistState blacklist_state);
242
243  // Runs on the UI thread. Confirms the installation to the ExtensionService.
244  void ConfirmInstall();
245
246  // Runs on File thread. Install the unpacked extension into the profile and
247  // notify the frontend.
248  void CompleteInstall();
249
250  // Reloads extension on File thread and reports installation result back
251  // to UI thread.
252  void ReloadExtensionAfterInstall(const base::FilePath& version_dir);
253
254  // Result reporting.
255  void ReportFailureFromFileThread(const CrxInstallerError& error);
256  void ReportFailureFromUIThread(const CrxInstallerError& error);
257  void ReportSuccessFromFileThread();
258  void ReportSuccessFromUIThread();
259  void NotifyCrxInstallBegin();
260  void NotifyCrxInstallComplete(bool success);
261
262  // Deletes temporary directory and crx file if needed.
263  void CleanupTempFiles();
264
265  // Checks whether the current installation is initiated by the user from
266  // the extension settings page to update an existing extension or app.
267  void CheckUpdateFromSettingsPage();
268
269  // Show re-enable prompt if the update is initiated from the settings page
270  // and needs additional permissions.
271  void ConfirmReEnable();
272
273  void set_install_flag(int flag, bool val) {
274    if (val)
275      install_flags_ |= flag;
276    else
277      install_flags_ &= ~flag;
278  }
279
280  // The file we're installing.
281  base::FilePath source_file_;
282
283  // The URL the file was downloaded from.
284  GURL download_url_;
285
286  // The directory extensions are installed to.
287  const base::FilePath install_directory_;
288
289  // The location the installation came from (bundled with Chromium, registry,
290  // manual install, etc). This metadata is saved with the installation if
291  // successful. Defaults to INTERNAL.
292  Manifest::Location install_source_;
293
294  // Indicates whether the user has already approved the extension to be
295  // installed. If true, |expected_manifest_| and |expected_id_| must match
296  // those of the CRX.
297  bool approved_;
298
299  // For updates, external and webstore installs we have an ID we're expecting
300  // the extension to contain.
301  std::string expected_id_;
302
303  // A parsed copy of the expected manifest, before any transformations like
304  // localization have taken place. If |approved_| is true, then the
305  // extension's manifest must match this for the install to proceed.
306  scoped_ptr<Manifest> expected_manifest_;
307
308  // The level of checking when comparing the actual manifest against
309  // the |expected_manifest_|.
310  WebstoreInstaller::ManifestCheckLevel expected_manifest_check_level_;
311
312  // If non-NULL, contains the expected version of the extension we're
313  // installing.  Important for external sources, where claiming the wrong
314  // version could cause unnecessary unpacking of an extension at every
315  // restart.
316  scoped_ptr<Version> expected_version_;
317
318  // If true, the actual version should be same with the |expected_version_|,
319  // Otherwise the actual version should be equal to or newer than
320  // the |expected_version_|.
321  bool expected_version_strict_checking_;
322
323  // Whether manual extension installation is enabled. We can't just check this
324  // before trying to install because themes are special-cased to always be
325  // allowed.
326  bool extensions_enabled_;
327
328  // Whether we're supposed to delete the source file on destruction. Defaults
329  // to false.
330  bool delete_source_;
331
332  // Whether to create an app shortcut after successful installation. This is
333  // set based on the user's selection in the UI and can only ever be true for
334  // apps.
335  bool create_app_shortcut_;
336
337  // The ordinal of the NTP apps page |extension_| will be shown on.
338  syncer::StringOrdinal page_ordinal_;
339
340  // A parsed copy of the unmodified original manifest, before any
341  // transformations like localization have taken place.
342  scoped_ptr<Manifest> original_manifest_;
343
344  // If non-empty, contains the current version of the extension we're
345  // installing (for upgrades).
346  std::string current_version_;
347
348  // The icon we will display in the installation UI, if any.
349  scoped_ptr<SkBitmap> install_icon_;
350
351  // The temp directory extension resources were unpacked to. We own this and
352  // must delete it when we are done with it.
353  base::FilePath temp_dir_;
354
355  // The frontend we will report results back to.
356  base::WeakPtr<ExtensionService> service_weak_;
357
358  // The client we will work with to do the installation. This can be NULL, in
359  // which case the install is silent.
360  // NOTE: we may be deleted on the file thread. To ensure the UI is deleted on
361  // the main thread we don't use a scoped_ptr here.
362  ExtensionInstallPrompt* client_;
363
364  // The root of the unpacked extension directory. This is a subdirectory of
365  // temp_dir_, so we don't have to delete it explicitly.
366  base::FilePath unpacked_extension_root_;
367
368  // True when the CRX being installed was just downloaded.
369  // Used to trigger extra checks before installing.
370  bool apps_require_extension_mime_type_;
371
372  // Allows for the possibility of a normal install (one in which a |client|
373  // is provided in the ctor) to proceed without showing the permissions prompt
374  // dialog.
375  bool allow_silent_install_;
376
377  // Allows for the possibility of an installation without granting any
378  // permissions to the extension.
379  bool grant_permissions_;
380
381  // The value of the content type header sent with the CRX.
382  // Ignorred unless |require_extension_mime_type_| is true.
383  std::string original_mime_type_;
384
385  // What caused this install?  Used only for histograms that report
386  // on failure rates, broken down by the cause of the install.
387  extension_misc::CrxInstallCause install_cause_;
388
389  // Creation flags to use for the extension.  These flags will be used
390  // when calling Extenion::Create() by the crx installer.
391  int creation_flags_;
392
393  // Whether to allow off store installation.
394  OffStoreInstallAllowReason off_store_install_allow_reason_;
395
396  // Whether the installation was handled successfully. This is used to
397  // indicate to the client whether the file should be removed and any UI
398  // initiating the installation can be removed. This is different than whether
399  // there was an error; if there was an error that rejects installation we
400  // still consider the installation 'handled'.
401  bool did_handle_successfully_;
402
403  // Whether we should produce an error if the manifest declares requirements
404  // that are not met. If false and there is an unmet requirement, the install
405  // will continue but the extension will be distabled.
406  bool error_on_unsupported_requirements_;
407
408  // Sequenced task runner where file I/O operations will be performed.
409  scoped_refptr<base::SequencedTaskRunner> installer_task_runner_;
410
411  // Used to show the install dialog.
412  ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback_;
413
414  // Whether the update is initiated by the user from the extension settings
415  // page.
416  bool update_from_settings_page_;
417
418  // The flags for ExtensionService::OnExtensionInstalled.
419  int install_flags_;
420
421  // Performs requirements, policy and blacklist checks on the extension.
422  ExtensionInstallChecker install_checker_;
423
424  DISALLOW_COPY_AND_ASSIGN(CrxInstaller);
425};
426
427}  // namespace extensions
428
429#endif  // CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_
430