Home | History | Annotate | Download | only in extensions
      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 
     28 class ExtensionService;
     29 class ExtensionServiceTest;
     30 class SkBitmap;
     31 struct WebApplicationInfo;
     32 
     33 namespace base {
     34 class SequencedTaskRunner;
     35 }
     36 
     37 namespace extensions {
     38 class CrxInstallerError;
     39 class ExtensionUpdaterTest;
     40 class 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.
     70 class 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