• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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