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 #include "chrome/browser/download/download_crx_util.h"
6 #include "chrome/browser/extensions/crx_installer.h"
7 #include "chrome/browser/extensions/extension_browsertest.h"
8 #include "chrome/browser/extensions/extension_install_prompt.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_system.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/extensions/extension.h"
17 #include "chrome/common/extensions/extension_file_util.h"
18 #include "chrome/common/extensions/feature_switch.h"
19 #include "chrome/common/extensions/permissions/permission_set.h"
20 #include "chrome/test/base/ui_test_utils.h"
21 #include "content/public/browser/download_manager.h"
22 #include "content/public/test/download_test_observer.h"
23 #include "grit/generated_resources.h"
24 #include "ui/base/l10n/l10n_util.h"
28 namespace extensions
{
32 // Observer waits for exactly one download to finish.
34 class MockInstallPrompt
: public ExtensionInstallPrompt
{
36 explicit MockInstallPrompt(content::WebContents
* web_contents
) :
37 ExtensionInstallPrompt(web_contents
),
38 confirmation_requested_(false),
41 bool did_succeed() const { return !!extension_
; }
42 const Extension
* extension() const { return extension_
; }
43 bool confirmation_requested() const { return confirmation_requested_
; }
44 const string16
& error() const { return error_
; }
45 void set_record_oauth2_grant(bool record
) { record_oauth2_grant_
= record
; }
47 // Overriding some of the ExtensionInstallUI API.
48 virtual void ConfirmInstall(
50 const Extension
* extension
,
51 const ShowDialogCallback
& show_dialog_callback
) OVERRIDE
{
52 confirmation_requested_
= true;
53 delegate
->InstallUIProceed();
55 virtual void OnInstallSuccess(const Extension
* extension
,
56 SkBitmap
* icon
) OVERRIDE
{
57 extension_
= extension
;
58 base::MessageLoopForUI::current()->Quit();
60 virtual void OnInstallFailure(const CrxInstallerError
& error
) OVERRIDE
{
61 error_
= error
.message();
62 base::MessageLoopForUI::current()->Quit();
66 bool confirmation_requested_
;
68 const Extension
* extension_
;
71 MockInstallPrompt
* CreateMockInstallPromptForBrowser(Browser
* browser
) {
72 return new MockInstallPrompt(
73 browser
->tab_strip_model()->GetActiveWebContents());
78 class ExtensionCrxInstallerTest
: public ExtensionBrowserTest
{
80 // Installs a crx from |crx_relpath| (a path relative to the extension test
81 // data dir) with expected id |id|. Returns the installer.
82 scoped_refptr
<CrxInstaller
> InstallWithPrompt(
83 const std::string
& ext_relpath
,
84 const std::string
& id
,
85 MockInstallPrompt
* mock_install_prompt
) {
86 ExtensionService
* service
= extensions::ExtensionSystem::Get(
87 browser()->profile())->extension_service();
88 base::FilePath ext_path
= test_data_dir_
.AppendASCII(ext_relpath
);
91 base::DictionaryValue
* parsed_manifest
=
92 extension_file_util::LoadManifest(ext_path
, &error
);
94 return scoped_refptr
<CrxInstaller
>();
96 scoped_ptr
<WebstoreInstaller::Approval
> approval
;
98 approval
= WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
101 scoped_ptr
<base::DictionaryValue
>(parsed_manifest
));
104 scoped_refptr
<CrxInstaller
> installer(
105 CrxInstaller::Create(service
,
106 mock_install_prompt
, /* ownership transferred */
107 approval
.get() /* keep ownership */));
108 installer
->set_allow_silent_install(true);
109 installer
->set_is_gallery_install(true);
110 installer
->set_bypass_blacklist_for_test(true);
111 installer
->InstallCrx(PackExtension(ext_path
));
112 content::RunMessageLoop();
114 EXPECT_TRUE(mock_install_prompt
->did_succeed());
118 // Installs an extension and checks that it has scopes granted IFF
119 // |record_oauth2_grant| is true.
120 void CheckHasEmptyScopesAfterInstall(const std::string
& ext_relpath
,
121 bool record_oauth2_grant
) {
122 CommandLine::ForCurrentProcess()->AppendSwitch(
123 switches::kEnableExperimentalExtensionApis
);
125 ExtensionService
* service
= extensions::ExtensionSystem::Get(
126 browser()->profile())->extension_service();
128 MockInstallPrompt
* mock_prompt
=
129 CreateMockInstallPromptForBrowser(browser());
130 mock_prompt
->set_record_oauth2_grant(record_oauth2_grant
);
131 scoped_refptr
<CrxInstaller
> installer
=
132 InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt
);
134 scoped_refptr
<PermissionSet
> permissions
=
135 service
->extension_prefs()->GetGrantedPermissions(
136 mock_prompt
->extension()->id());
137 ASSERT_TRUE(permissions
.get());
141 #if defined(OS_CHROMEOS)
142 #define MAYBE_Whitelisting DISABLED_Whitelisting
144 #define MAYBE_Whitelisting Whitelisting
146 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest
, MAYBE_Whitelisting
) {
147 std::string id
= "hdgllgikmikobbofgnabhfimcfoopgnd";
148 ExtensionService
* service
= extensions::ExtensionSystem::Get(
149 browser()->profile())->extension_service();
151 // Even whitelisted extensions with NPAPI should not prompt.
152 MockInstallPrompt
* mock_prompt
=
153 CreateMockInstallPromptForBrowser(browser());
154 scoped_refptr
<CrxInstaller
> installer
=
155 InstallWithPrompt("uitest/plugins", id
, mock_prompt
);
156 EXPECT_FALSE(mock_prompt
->confirmation_requested());
157 EXPECT_TRUE(service
->GetExtensionById(id
, false));
160 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest
,
161 GalleryInstallGetsExperimental
) {
162 // We must modify the command line temporarily in order to pack an extension
163 // that requests the experimental permission.
164 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
165 CommandLine old_command_line
= *command_line
;
166 command_line
->AppendSwitch(switches::kEnableExperimentalExtensionApis
);
167 base::FilePath crx_path
= PackExtension(
168 test_data_dir_
.AppendASCII("experimental"));
169 ASSERT_FALSE(crx_path
.empty());
171 // Now reset the command line so that we are testing specifically whether
172 // installing from webstore enables experimental permissions.
173 *(CommandLine::ForCurrentProcess()) = old_command_line
;
175 EXPECT_FALSE(InstallExtension(crx_path
, 0));
176 EXPECT_TRUE(InstallExtensionFromWebstore(crx_path
, 1));
179 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest
, PlatformAppCrx
) {
180 CommandLine::ForCurrentProcess()->AppendSwitch(
181 switches::kEnableExperimentalExtensionApis
);
182 EXPECT_TRUE(InstallExtension(
183 test_data_dir_
.AppendASCII("minimal_platform_app.crx"), 1));
186 // http://crbug.com/136397
187 #if defined(OS_CHROMEOS)
188 #define MAYBE_PackAndInstallExtension DISABLED_PackAndInstallExtension
190 #define MAYBE_PackAndInstallExtension PackAndInstallExtension
192 IN_PROC_BROWSER_TEST_F(
193 ExtensionCrxInstallerTest
, MAYBE_PackAndInstallExtension
) {
194 if (!FeatureSwitch::easy_off_store_install()->IsEnabled())
197 const int kNumDownloadsExpected
= 1;
199 LOG(ERROR
) << "PackAndInstallExtension: Packing extension";
200 base::FilePath crx_path
= PackExtension(
201 test_data_dir_
.AppendASCII("common/background_page"));
202 ASSERT_FALSE(crx_path
.empty());
203 std::string
crx_path_string(crx_path
.value().begin(), crx_path
.value().end());
204 GURL url
= GURL(std::string("file:///").append(crx_path_string
));
206 MockInstallPrompt
* mock_prompt
=
207 CreateMockInstallPromptForBrowser(browser());
208 download_crx_util::SetMockInstallPromptForTesting(mock_prompt
);
210 LOG(ERROR
) << "PackAndInstallExtension: Getting download manager";
211 content::DownloadManager
* download_manager
=
212 content::BrowserContext::GetDownloadManager(browser()->profile());
214 LOG(ERROR
) << "PackAndInstallExtension: Setting observer";
215 scoped_ptr
<content::DownloadTestObserver
> observer(
216 new content::DownloadTestObserverTerminal(
217 download_manager
, kNumDownloadsExpected
,
218 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT
));
219 LOG(ERROR
) << "PackAndInstallExtension: Navigating to URL";
220 ui_test_utils::NavigateToURLWithDisposition(browser(), url
, CURRENT_TAB
,
221 ui_test_utils::BROWSER_TEST_NONE
);
223 EXPECT_TRUE(WaitForCrxInstallerDone());
224 LOG(ERROR
) << "PackAndInstallExtension: Extension install";
225 EXPECT_TRUE(mock_prompt
->confirmation_requested());
226 LOG(ERROR
) << "PackAndInstallExtension: Extension install confirmed";
229 // Tests that scopes are only granted if |record_oauth2_grant_| on the prompt is
232 #define MAYBE_GrantScopes DISABLED_GrantScopes
234 #define MAYBE_GrantScopes GrantScopes
236 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest
, MAYBE_GrantScopes
) {
237 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
241 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest
, DoNotGrantScopes
) {
242 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
246 // Off-store install cannot yet be disabled on Aura.
247 #if defined(USE_AURA)
248 #define MAYBE_AllowOffStore DISABLED_AllowOffStore
250 #define MAYBE_AllowOffStore AllowOffStore
252 // Crashy: http://crbug.com/140893
253 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest
, DISABLED_AllowOffStore
) {
254 ExtensionService
* service
= extensions::ExtensionSystem::Get(
255 browser()->profile())->extension_service();
256 const bool kTestData
[] = {false, true};
258 for (size_t i
= 0; i
< arraysize(kTestData
); ++i
) {
259 MockInstallPrompt
* mock_prompt
=
260 CreateMockInstallPromptForBrowser(browser());
261 scoped_refptr
<CrxInstaller
> crx_installer(
262 CrxInstaller::Create(service
, mock_prompt
));
263 crx_installer
->set_install_cause(
264 extension_misc::INSTALL_CAUSE_USER_DOWNLOAD
);
267 crx_installer
->set_off_store_install_allow_reason(
268 CrxInstaller::OffStoreInstallAllowedInTest
);
271 crx_installer
->InstallCrx(test_data_dir_
.AppendASCII("good.crx"));
272 EXPECT_EQ(kTestData
[i
], WaitForExtensionInstall()) << kTestData
[i
];
273 EXPECT_EQ(kTestData
[i
], mock_prompt
->did_succeed());
274 EXPECT_EQ(kTestData
[i
], mock_prompt
->confirmation_requested()) <<
277 EXPECT_EQ(string16(), mock_prompt
->error()) << kTestData
[i
];
279 EXPECT_EQ(l10n_util::GetStringUTF16(
280 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE
),
281 mock_prompt
->error()) << kTestData
[i
];
286 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest
, HiDpiThemeTest
) {
287 base::FilePath crx_path
= test_data_dir_
.AppendASCII("theme_hidpi_crx");
288 crx_path
= crx_path
.AppendASCII("theme_hidpi.crx");
290 ASSERT_TRUE(InstallExtension(crx_path
,1));
292 const std::string
extension_id("gllekhaobjnhgeagipipnkpmmmpchacm");
293 ExtensionService
* service
= extensions::ExtensionSystem::Get(
294 browser()->profile())->extension_service();
295 ASSERT_TRUE(service
);
296 const extensions::Extension
* extension
=
297 service
->GetExtensionById(extension_id
, false);
298 ASSERT_TRUE(extension
);
299 EXPECT_EQ(extension_id
, extension
->id());
301 UninstallExtension(extension_id
);
302 EXPECT_FALSE(service
->GetExtensionById(extension_id
, false));
305 } // namespace extensions