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 // Download code which handles CRX files (extensions, themes, apps, ...).
7 #include "chrome/browser/download/download_crx_util.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/crx_installer.h"
11 #include "chrome/browser/extensions/extension_install_prompt.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_system.h"
14 #include "chrome/browser/extensions/webstore_installer.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/host_desktop.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "content/public/browser/download_item.h"
20 #include "content/public/browser/notification_service.h"
21 #include "extensions/common/user_script.h"
23 using content::BrowserThread
;
24 using content::DownloadItem
;
25 using extensions::WebstoreInstaller
;
27 namespace download_crx_util
{
31 // Hold a mock ExtensionInstallPrompt object that will be used when the
32 // download system opens a CRX.
33 ExtensionInstallPrompt
* mock_install_prompt_for_testing
= NULL
;
35 // Called to get an extension install UI object. In tests, will return
36 // a mock if the test calls download_util::SetMockInstallPromptForTesting()
38 scoped_ptr
<ExtensionInstallPrompt
> CreateExtensionInstallPrompt(
40 const DownloadItem
& download_item
) {
41 // Use a mock if one is present. Otherwise, create a real extensions
43 if (mock_install_prompt_for_testing
) {
44 ExtensionInstallPrompt
* result
= mock_install_prompt_for_testing
;
45 mock_install_prompt_for_testing
= NULL
;
46 return scoped_ptr
<ExtensionInstallPrompt
>(result
);
48 content::WebContents
* web_contents
= download_item
.GetWebContents();
50 chrome::HostDesktopType active_desktop
= chrome::GetActiveDesktop();
51 Browser
* browser
= chrome::FindLastActiveWithProfile(profile
,
54 browser
= new Browser(Browser::CreateParams(Browser::TYPE_TABBED
,
55 profile
, active_desktop
));
56 web_contents
= browser
->tab_strip_model()->GetActiveWebContents();
58 return scoped_ptr
<ExtensionInstallPrompt
>(
59 new ExtensionInstallPrompt(web_contents
));
65 // Tests can call this method to inject a mock ExtensionInstallPrompt
66 // to be used to confirm permissions on a downloaded CRX.
67 void SetMockInstallPromptForTesting(
68 scoped_ptr
<ExtensionInstallPrompt
> mock_prompt
) {
69 mock_install_prompt_for_testing
= mock_prompt
.release();
72 scoped_refptr
<extensions::CrxInstaller
> OpenChromeExtension(
74 const DownloadItem
& download_item
) {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
77 ExtensionService
* service
= extensions::ExtensionSystem::Get(profile
)->
81 scoped_refptr
<extensions::CrxInstaller
> installer(
82 extensions::CrxInstaller::Create(
84 CreateExtensionInstallPrompt(profile
, download_item
),
85 WebstoreInstaller::GetAssociatedApproval(download_item
)));
87 installer
->set_error_on_unsupported_requirements(true);
88 installer
->set_delete_source(true);
89 installer
->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD
);
91 if (OffStoreInstallAllowedByPrefs(profile
, download_item
)) {
92 installer
->set_off_store_install_allow_reason(
93 extensions::CrxInstaller::OffStoreInstallAllowedBecausePref
);
96 if (extensions::UserScript::IsURLUserScript(download_item
.GetURL(),
97 download_item
.GetMimeType())) {
98 installer
->InstallUserScript(download_item
.GetFullPath(),
99 download_item
.GetURL());
101 bool is_gallery_download
=
102 WebstoreInstaller::GetAssociatedApproval(download_item
) != NULL
;
103 installer
->set_original_mime_type(download_item
.GetOriginalMimeType());
104 installer
->set_apps_require_extension_mime_type(true);
105 installer
->set_download_url(download_item
.GetURL());
106 installer
->set_is_gallery_install(is_gallery_download
);
107 if (is_gallery_download
)
108 installer
->set_original_download_url(download_item
.GetOriginalUrl());
109 installer
->set_allow_silent_install(is_gallery_download
);
110 installer
->InstallCrx(download_item
.GetFullPath());
116 bool IsExtensionDownload(const DownloadItem
& download_item
) {
117 if (download_item
.GetTargetDisposition() ==
118 DownloadItem::TARGET_DISPOSITION_PROMPT
)
121 if (download_item
.GetMimeType() == extensions::Extension::kMimeType
||
122 extensions::UserScript::IsURLUserScript(download_item
.GetURL(),
123 download_item
.GetMimeType())) {
130 bool OffStoreInstallAllowedByPrefs(Profile
* profile
, const DownloadItem
& item
) {
131 ExtensionService
* service
= extensions::ExtensionSystem::Get(
132 profile
)->extension_service();
136 extensions::ExtensionPrefs
* prefs
= service
->extension_prefs();
139 extensions::URLPatternSet url_patterns
= prefs
->GetAllowedInstallSites();
141 if (!url_patterns
.MatchesURL(item
.GetURL()))
144 // The referrer URL must also be whitelisted, unless the URL has the file
145 // scheme (there's no referrer for those URLs).
146 // TODO(aa): RefererURL is cleared in some cases, for example when going
147 // between secure and non-secure URLs. It would be better if DownloadItem
148 // tracked the initiating page explicitly.
149 return url_patterns
.MatchesURL(item
.GetReferrerUrl()) ||
150 item
.GetURL().SchemeIsFile();
153 } // namespace download_crx_util