1 // Copyright (c) 2011 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 #pragma once 8 9 #include <string> 10 11 #include "base/file_path.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/version.h" 14 #include "chrome/browser/extensions/extension_install_ui.h" 15 #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" 16 #include "chrome/common/extensions/extension.h" 17 #include "chrome/common/web_apps.h" 18 19 class ExtensionService; 20 class SkBitmap; 21 22 // This class installs a crx file into a profile. 23 // 24 // Installing a CRX is a multi-step process, including unpacking the crx, 25 // validating it, prompting the user, and installing. Since many of these 26 // steps must occur on the file thread, this class contains a copy of all data 27 // necessary to do its job. (This also minimizes external dependencies for 28 // easier testing). 29 // 30 // Lifetime management: 31 // 32 // This class is ref-counted by each call it makes to itself on another thread, 33 // and by UtilityProcessHost. 34 // 35 // Additionally, we hold a reference to our own client so that it lives at least 36 // long enough to receive the result of unpacking. 37 // 38 // IMPORTANT: Callers should keep a reference to a CrxInstaller while they are 39 // working with it, eg: 40 // 41 // scoped_refptr<CrxInstaller> installer(new CrxInstaller(...)); 42 // installer->set_foo(); 43 // installer->set_bar(); 44 // installer->InstallCrx(...); 45 class CrxInstaller 46 : public SandboxedExtensionUnpackerClient, 47 public ExtensionInstallUI::Delegate { 48 public: 49 50 // This is pretty lame, but given the difficulty of connecting a particular 51 // ExtensionFunction to a resulting download in the download manager, it's 52 // currently necessary. This is the |id| of an extension to be installed 53 // *by the web store only* which should not get the permissions install 54 // prompt. This should only be called on the UI thread. 55 // crbug.com/54916 56 static void SetWhitelistedInstallId(const std::string& id); 57 58 // Exempt the next extension install with |id| from displaying a confirmation 59 // prompt, since the user already agreed to the install via 60 // beginInstallWithManifest. We require that the extension manifest matches 61 // |parsed_manifest| which is what was used to prompt with. Ownership of 62 // |parsed_manifest| is transferred here. 63 static void SetWhitelistedManifest(const std::string& id, 64 DictionaryValue* parsed_manifest); 65 66 // Returns the previously stored manifest from a call to 67 // SetWhitelistedManifest. 68 static const DictionaryValue* GetWhitelistedManifest(const std::string& id); 69 70 // Removes any whitelisted manifest for |id| and returns it. The caller owns 71 // the return value and is responsible for deleting it. 72 static DictionaryValue* RemoveWhitelistedManifest(const std::string& id); 73 74 // Returns whether |id| is whitelisted - only call this on the UI thread. 75 static bool IsIdWhitelisted(const std::string& id); 76 77 // Returns whether |id| was found and removed (was whitelisted). This should 78 // only be called on the UI thread. 79 static bool ClearWhitelistedInstallId(const std::string& id); 80 81 // Constructor. Extensions will be installed into 82 // frontend->install_directory() then registered with |frontend|. Any install 83 // UI will be displayed using |client|. Pass NULL for |client| for silent 84 // install. 85 CrxInstaller(ExtensionService* frontend, 86 ExtensionInstallUI* client); 87 88 // Install the crx in |source_file|. 89 void InstallCrx(const FilePath& source_file); 90 91 // Convert the specified user script into an extension and install it. 92 void InstallUserScript(const FilePath& source_file, 93 const GURL& original_url); 94 95 // Convert the specified web app into an extension and install it. 96 void InstallWebApp(const WebApplicationInfo& web_app); 97 98 // Overridden from ExtensionInstallUI::Delegate: 99 virtual void InstallUIProceed(); 100 virtual void InstallUIAbort(); 101 original_url()102 const GURL& original_url() const { return original_url_; } set_original_url(const GURL & val)103 void set_original_url(const GURL& val) { original_url_ = val; } 104 install_source()105 Extension::Location install_source() const { return install_source_; } set_install_source(Extension::Location source)106 void set_install_source(Extension::Location source) { 107 install_source_ = source; 108 } 109 expected_id()110 const std::string& expected_id() const { return expected_id_; } set_expected_id(const std::string & val)111 void set_expected_id(const std::string& val) { expected_id_ = val; } 112 set_expected_version(const Version & val)113 void set_expected_version(const Version& val) { 114 expected_version_.reset(val.Clone()); 115 } 116 delete_source()117 bool delete_source() const { return delete_source_; } set_delete_source(bool val)118 void set_delete_source(bool val) { delete_source_ = val; } 119 allow_silent_install()120 bool allow_silent_install() const { return allow_silent_install_; } set_allow_silent_install(bool val)121 void set_allow_silent_install(bool val) { allow_silent_install_ = val; } 122 is_gallery_install()123 bool is_gallery_install() const { return is_gallery_install_; } set_is_gallery_install(bool val)124 void set_is_gallery_install(bool val) { is_gallery_install_ = val; } 125 126 // If |apps_require_extension_mime_type_| is set to true, be sure to set 127 // |original_mime_type_| as well. set_apps_require_extension_mime_type(bool apps_require_extension_mime_type)128 void set_apps_require_extension_mime_type( 129 bool apps_require_extension_mime_type) { 130 apps_require_extension_mime_type_ = apps_require_extension_mime_type; 131 } 132 set_original_mime_type(const std::string & original_mime_type)133 void set_original_mime_type(const std::string& original_mime_type) { 134 original_mime_type_ = original_mime_type; 135 } 136 137 private: 138 ~CrxInstaller(); 139 140 // Converts the source user script to an extension. 141 void ConvertUserScriptOnFileThread(); 142 143 // Converts the source web app to an extension. 144 void ConvertWebAppOnFileThread(const WebApplicationInfo& web_app); 145 146 // Called after OnUnpackSuccess as a last check to see whether the install 147 // should complete. 148 bool AllowInstall(const Extension* extension, std::string* error); 149 150 // SandboxedExtensionUnpackerClient 151 virtual void OnUnpackFailure(const std::string& error_message); 152 virtual void OnUnpackSuccess(const FilePath& temp_dir, 153 const FilePath& extension_dir, 154 const Extension* extension); 155 156 // Returns true if we can skip confirmation because the install was 157 // whitelisted. 158 bool CanSkipConfirmation(); 159 160 // Runs on the UI thread. Confirms with the user (via ExtensionInstallUI) that 161 // it is OK to install this extension. 162 void ConfirmInstall(); 163 164 // Runs on File thread. Install the unpacked extension into the profile and 165 // notify the frontend. 166 void CompleteInstall(); 167 168 // Result reporting. 169 void ReportFailureFromFileThread(const std::string& error); 170 void ReportFailureFromUIThread(const std::string& error); 171 void ReportSuccessFromFileThread(); 172 void ReportSuccessFromUIThread(); 173 174 // The file we're installing. 175 FilePath source_file_; 176 177 // The URL the file was downloaded from. 178 GURL original_url_; 179 180 // The directory extensions are installed to. 181 FilePath install_directory_; 182 183 // The location the installation came from (bundled with Chromium, registry, 184 // manual install, etc). This metadata is saved with the installation if 185 // successful. Defaults to INTERNAL. 186 Extension::Location install_source_; 187 188 // For updates and external installs we have an ID we're expecting the 189 // extension to contain. 190 std::string expected_id_; 191 192 // If non-NULL, contains the expected version of the extension we're 193 // installing. Important for external sources, where claiming the wrong 194 // version could cause unnessisary unpacking of an extension at every 195 // restart. 196 scoped_ptr<Version> expected_version_; 197 198 // Whether manual extension installation is enabled. We can't just check this 199 // before trying to install because themes are special-cased to always be 200 // allowed. 201 bool extensions_enabled_; 202 203 // Whether we're supposed to delete the source file on destruction. Defaults 204 // to false. 205 bool delete_source_; 206 207 // Whether the install originated from the gallery. 208 bool is_gallery_install_; 209 210 // Whether to create an app shortcut after successful installation. This is 211 // set based on the user's selection in the UI and can only ever be true for 212 // apps. 213 bool create_app_shortcut_; 214 215 // The extension we're installing. We own this and either pass it off to 216 // ExtensionService on success, or delete it on failure. 217 scoped_refptr<const Extension> extension_; 218 219 // If non-empty, contains the current version of the extension we're 220 // installing (for upgrades). 221 std::string current_version_; 222 223 // The icon we will display in the installation UI, if any. 224 scoped_ptr<SkBitmap> install_icon_; 225 226 // The temp directory extension resources were unpacked to. We own this and 227 // must delete it when we are done with it. 228 FilePath temp_dir_; 229 230 // The frontend we will report results back to. 231 scoped_refptr<ExtensionService> frontend_; 232 233 // The client we will work with to do the installation. This can be NULL, in 234 // which case the install is silent. 235 // NOTE: we may be deleted on the file thread. To ensure the UI is deleted on 236 // the main thread we don't use a scoped_ptr here. 237 ExtensionInstallUI* client_; 238 239 // The root of the unpacked extension directory. This is a subdirectory of 240 // temp_dir_, so we don't have to delete it explicitly. 241 FilePath unpacked_extension_root_; 242 243 // True when the CRX being installed was just downloaded. 244 // Used to trigger extra checks before installing. 245 bool apps_require_extension_mime_type_; 246 247 // Allows for the possibility of a normal install (one in which a |client| 248 // is provided in the ctor) to procede without showing the permissions prompt 249 // dialog. Note that this will only take place if |allow_silent_install_| 250 // is true AND the unpacked id of the extension is whitelisted with 251 // SetWhitelistedInstallId(). 252 bool allow_silent_install_; 253 254 // The value of the content type header sent with the CRX. 255 // Ignorred unless |require_extension_mime_type_| is true. 256 std::string original_mime_type_; 257 258 DISALLOW_COPY_AND_ASSIGN(CrxInstaller); 259 }; 260 261 #endif // CHROME_BROWSER_EXTENSIONS_CRX_INSTALLER_H_ 262