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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_
6 #define CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_
11 #include "base/compiler_specific.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/supports_user_data.h"
15 #include "base/values.h"
16 #include "base/version.h"
17 #include "chrome/browser/extensions/extension_install_prompt.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/download_interrupt_reasons.h"
20 #include "content/public/browser/download_item.h"
21 #include "content/public/browser/notification_observer.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "content/public/browser/web_contents_observer.h"
24 #include "extensions/common/manifest_handlers/shared_module_info.h"
25 #include "ui/gfx/image/image_skia.h"
38 namespace extensions
{
43 // Downloads and installs extensions from the web store.
44 class WebstoreInstaller
: public content::NotificationObserver
,
45 public content::DownloadItem::Observer
,
46 public content::WebContentsObserver
,
47 public base::RefCountedThreadSafe
<
48 WebstoreInstaller
, content::BrowserThread::DeleteOnUIThread
> {
51 // Inline installs trigger slightly different behavior (install source
52 // is different, download referrers are the item's page in the gallery).
53 INSTALL_SOURCE_INLINE
,
54 INSTALL_SOURCE_APP_LAUNCHER
,
59 FAILURE_REASON_CANCELLED
,
60 FAILURE_REASON_DEPENDENCY_NOT_FOUND
,
61 FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE
,
65 enum ManifestCheckLevel
{
66 // Do not check for any manifest equality.
67 MANIFEST_CHECK_LEVEL_NONE
,
69 // Only check that the expected and actual permissions have the same
70 // effective permissions.
71 MANIFEST_CHECK_LEVEL_LOOSE
,
73 // All data in the expected and actual manifests must match.
74 MANIFEST_CHECK_LEVEL_STRICT
,
79 virtual void OnExtensionDownloadStarted(const std::string
& id
,
80 content::DownloadItem
* item
);
81 virtual void OnExtensionDownloadProgress(const std::string
& id
,
82 content::DownloadItem
* item
);
83 virtual void OnExtensionInstallSuccess(const std::string
& id
) = 0;
84 virtual void OnExtensionInstallFailure(const std::string
& id
,
85 const std::string
& error
,
86 FailureReason reason
) = 0;
89 virtual ~Delegate() {}
92 // Contains information about what parts of the extension install process can
93 // be skipped or modified. If one of these is present, it means that a CRX
94 // download was initiated by WebstoreInstaller. The Approval instance should
95 // be checked further for additional details.
96 struct Approval
: public base::SupportsUserData::Data
{
97 static scoped_ptr
<Approval
> CreateWithInstallPrompt(Profile
* profile
);
99 // Creates an Approval for installing a shared module.
100 static scoped_ptr
<Approval
> CreateForSharedModule(Profile
* profile
);
102 // Creates an Approval that will skip putting up an install confirmation
103 // prompt if the actual manifest from the extension to be installed matches
104 // |parsed_manifest|. The |strict_manifest_check| controls whether we want
105 // to require an exact manifest match, or are willing to tolerate a looser
106 // check just that the effective permissions are the same.
107 static scoped_ptr
<Approval
> CreateWithNoInstallPrompt(
109 const std::string
& extension_id
,
110 scoped_ptr
<base::DictionaryValue
> parsed_manifest
,
111 bool strict_manifest_check
);
115 // The extension id that was approved for installation.
116 std::string extension_id
;
118 // The profile the extension should be installed into.
121 // The expected manifest, before localization.
122 scoped_ptr
<Manifest
> manifest
;
124 // Whether to use a bubble notification when an app is installed, instead of
125 // the default behavior of transitioning to the new tab page.
126 bool use_app_installed_bubble
;
128 // Whether to skip the post install UI like the extension installed bubble.
129 bool skip_post_install_ui
;
131 // Whether to skip the install dialog once the extension has been downloaded
132 // and unpacked. One reason this can be true is that in the normal webstore
133 // installation, the dialog is shown earlier, before any download is done,
134 // so there's no need to show it again.
135 bool skip_install_dialog
;
137 // Whether we should enable the launcher before installing the app.
138 bool enable_launcher
;
140 // Manifest check level for checking actual manifest against expected
142 ManifestCheckLevel manifest_check_level
;
144 // Used to show the install dialog.
145 ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback
;
147 // The icon to use to display the extension while it is installing.
148 gfx::ImageSkia installing_icon
;
150 // A dummy extension created from |manifest|;
151 scoped_refptr
<Extension
> dummy_extension
;
153 // Required minimum version.
154 scoped_ptr
<Version
> minimum_version
;
156 // Ephemeral apps (experimental) are not permanently installed in Chrome.
163 // Gets the Approval associated with the |download|, or NULL if there's none.
164 // Note that the Approval is owned by |download|.
165 static const Approval
* GetAssociatedApproval(
166 const content::DownloadItem
& download
);
168 // Creates a WebstoreInstaller for downloading and installing the extension
169 // with the given |id| from the Chrome Web Store. If |delegate| is not NULL,
170 // it will be notified when the install succeeds or fails. The installer will
171 // use the specified |controller| to download the extension. Only one
172 // WebstoreInstaller can use a specific controller at any given time. This
173 // also associates the |approval| with this install.
174 // Note: the delegate should stay alive until being called back.
175 WebstoreInstaller(Profile
* profile
,
177 content::WebContents
* web_contents
,
178 const std::string
& id
,
179 scoped_ptr
<Approval
> approval
,
180 InstallSource source
);
182 // Starts downloading and installing the extension.
185 // content::NotificationObserver
186 virtual void Observe(int type
,
187 const content::NotificationSource
& source
,
188 const content::NotificationDetails
& details
) OVERRIDE
;
190 // Removes the reference to the delegate passed in the constructor. Used when
191 // the delegate object must be deleted before this object.
192 void InvalidateDelegate();
194 // Instead of using the default download directory, use |directory| instead.
195 // This does *not* transfer ownership of |directory|.
196 static void SetDownloadDirectoryForTests(base::FilePath
* directory
);
199 FRIEND_TEST_ALL_PREFIXES(WebstoreInstallerTest
, PlatformParams
);
200 friend struct content::BrowserThread::DeleteOnThread
<
201 content::BrowserThread::UI
>;
202 friend class base::DeleteHelper
<WebstoreInstaller
>;
203 virtual ~WebstoreInstaller();
205 // Helper to get install URL.
206 static GURL
GetWebstoreInstallURL(const std::string
& extension_id
,
207 InstallSource source
);
209 // DownloadManager::DownloadUrl callback.
210 void OnDownloadStarted(content::DownloadItem
* item
,
211 content::DownloadInterruptReason interrupt_reason
);
213 // DownloadItem::Observer implementation:
214 virtual void OnDownloadUpdated(content::DownloadItem
* download
) OVERRIDE
;
215 virtual void OnDownloadDestroyed(content::DownloadItem
* download
) OVERRIDE
;
217 // Downloads next pending module in |pending_modules_|.
218 void DownloadNextPendingModule();
220 // Downloads and installs a single Crx with the given |extension_id|.
221 // This function is used for both the extension Crx and dependences.
222 void DownloadCrx(const std::string
& extension_id
, InstallSource source
);
224 // Starts downloading the extension to |file_path|.
225 void StartDownload(const base::FilePath
& file_path
);
227 // Reports an install |error| to the delegate for the given extension if this
228 // managed its installation. This also removes the associated PendingInstall.
229 void ReportFailure(const std::string
& error
, FailureReason reason
);
231 // Reports a successful install to the delegate for the given extension if
232 // this managed its installation. This also removes the associated
234 void ReportSuccess();
236 // Records stats regarding an interrupted webstore download item.
237 void RecordInterrupt(const content::DownloadItem
* download
) const;
239 content::NotificationRegistrar registrar_
;
243 InstallSource install_source_
;
244 // The DownloadItem is owned by the DownloadManager and is valid from when
245 // OnDownloadStarted is called (with no error) until OnDownloadDestroyed().
246 content::DownloadItem
* download_item_
;
247 scoped_ptr
<Approval
> approval_
;
251 std::list
<SharedModuleInfo::ImportInfo
> pending_modules_
;
252 // Total extension modules we need download and install (the main module and
255 bool download_started_
;
258 } // namespace extensions
260 #endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_