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