Temporarily re-enabling SizeAfterPrefChange test with traces (this time for Linux...
[chromium-blink-merge.git] / chrome / browser / extensions / crx_installer_browsertest.cc
blob375b57e3b7a9f85995dd2aa5735528094bc7755a
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 "base/at_exit.h"
6 #include "base/memory/ref_counted.h"
7 #include "chrome/browser/download/download_crx_util.h"
8 #include "chrome/browser/extensions/browser_action_test_util.h"
9 #include "chrome/browser/extensions/crx_installer.h"
10 #include "chrome/browser/extensions/extension_browsertest.h"
11 #include "chrome/browser/extensions/extension_install_prompt.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/fake_safe_browsing_database_manager.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/download_manager.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "content/public/test/download_test_observer.h"
24 #include "extensions/browser/extension_prefs.h"
25 #include "extensions/browser/extension_system.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/feature_switch.h"
28 #include "extensions/common/file_util.h"
29 #include "extensions/common/permissions/permission_set.h"
30 #include "extensions/common/switches.h"
31 #include "grit/generated_resources.h"
32 #include "ui/base/l10n/l10n_util.h"
34 #if defined(OS_CHROMEOS)
35 #include "chrome/browser/chromeos/login/users/fake_user_manager.h"
36 #include "chrome/browser/chromeos/login/users/user_manager.h"
37 #include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
38 #include "chromeos/chromeos_switches.h"
39 #endif
41 class SkBitmap;
43 namespace extensions {
45 namespace {
47 class MockInstallPrompt;
49 // This class holds information about things that happen with a
50 // MockInstallPrompt. We create the MockInstallPrompt but need to pass
51 // ownership of it to CrxInstaller, so it isn't safe to hang this data on
52 // MockInstallPrompt itself becuase we can't guarantee it's lifetime.
53 class MockPromptProxy :
54 public base::RefCountedThreadSafe<MockPromptProxy> {
55 public:
56 explicit MockPromptProxy(content::WebContents* web_contents);
58 bool did_succeed() const { return !extension_id_.empty(); }
59 const std::string& extension_id() { return extension_id_; }
60 bool confirmation_requested() const { return confirmation_requested_; }
61 const base::string16& error() const { return error_; }
63 // To have any effect, this should be called before CreatePrompt.
64 void set_record_oauth2_grant(bool record_oauth2_grant) {
65 record_oauth2_grant_.reset(new bool(record_oauth2_grant));
68 void set_extension_id(const std::string& id) { extension_id_ = id; }
69 void set_confirmation_requested() { confirmation_requested_ = true; }
70 void set_error(const base::string16& error) { error_ = error; }
72 scoped_ptr<ExtensionInstallPrompt> CreatePrompt();
74 private:
75 friend class base::RefCountedThreadSafe<MockPromptProxy>;
76 virtual ~MockPromptProxy();
78 // Data used to create a prompt.
79 content::WebContents* web_contents_;
80 scoped_ptr<bool> record_oauth2_grant_;
82 // Data reported back to us by the prompt we created.
83 bool confirmation_requested_;
84 std::string extension_id_;
85 base::string16 error_;
88 class MockInstallPrompt : public ExtensionInstallPrompt {
89 public:
90 MockInstallPrompt(content::WebContents* web_contents,
91 MockPromptProxy* proxy) :
92 ExtensionInstallPrompt(web_contents),
93 proxy_(proxy) {}
95 void set_record_oauth2_grant(bool record) { record_oauth2_grant_ = record; }
97 // Overriding some of the ExtensionInstallUI API.
98 virtual void ConfirmInstall(
99 Delegate* delegate,
100 const Extension* extension,
101 const ShowDialogCallback& show_dialog_callback) OVERRIDE {
102 proxy_->set_confirmation_requested();
103 delegate->InstallUIProceed();
105 virtual void OnInstallSuccess(const Extension* extension,
106 SkBitmap* icon) OVERRIDE {
107 proxy_->set_extension_id(extension->id());
108 base::MessageLoopForUI::current()->Quit();
110 virtual void OnInstallFailure(const CrxInstallerError& error) OVERRIDE {
111 proxy_->set_error(error.message());
112 base::MessageLoopForUI::current()->Quit();
115 private:
116 scoped_refptr<MockPromptProxy> proxy_;
120 MockPromptProxy::MockPromptProxy(content::WebContents* web_contents) :
121 web_contents_(web_contents),
122 confirmation_requested_(false) {
125 MockPromptProxy::~MockPromptProxy() {}
127 scoped_ptr<ExtensionInstallPrompt> MockPromptProxy::CreatePrompt() {
128 scoped_ptr<MockInstallPrompt> prompt(
129 new MockInstallPrompt(web_contents_, this));
130 if (record_oauth2_grant_.get())
131 prompt->set_record_oauth2_grant(*record_oauth2_grant_.get());
132 return prompt.PassAs<ExtensionInstallPrompt>();
136 scoped_refptr<MockPromptProxy> CreateMockPromptProxyForBrowser(
137 Browser* browser) {
138 return new MockPromptProxy(
139 browser->tab_strip_model()->GetActiveWebContents());
142 } // namespace
144 class ExtensionCrxInstallerTest : public ExtensionBrowserTest {
145 public:
146 scoped_ptr<WebstoreInstaller::Approval> GetApproval(
147 const char* manifest_dir,
148 const std::string& id,
149 bool strict_manifest_checks) {
150 scoped_ptr<WebstoreInstaller::Approval> result;
152 base::FilePath ext_path = test_data_dir_.AppendASCII(manifest_dir);
153 std::string error;
154 scoped_ptr<base::DictionaryValue> parsed_manifest(
155 file_util::LoadManifest(ext_path, &error));
156 if (!parsed_manifest.get() || !error.empty())
157 return result.Pass();
159 return WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
160 browser()->profile(),
162 parsed_manifest.Pass(),
163 strict_manifest_checks);
166 void RunCrxInstaller(const WebstoreInstaller::Approval* approval,
167 scoped_ptr<ExtensionInstallPrompt> prompt,
168 const base::FilePath& crx_path) {
169 ExtensionService* service = extensions::ExtensionSystem::Get(
170 browser()->profile())->extension_service();
171 scoped_refptr<CrxInstaller> installer(
172 CrxInstaller::Create(service, prompt.Pass(), approval));
173 installer->set_allow_silent_install(true);
174 installer->set_is_gallery_install(true);
175 installer->InstallCrx(crx_path);
176 content::RunMessageLoop();
179 // Installs a crx from |crx_relpath| (a path relative to the extension test
180 // data dir) with expected id |id|.
181 void InstallWithPrompt(const char* ext_relpath,
182 const std::string& id,
183 scoped_refptr<MockPromptProxy> mock_install_prompt) {
184 base::FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath);
186 scoped_ptr<WebstoreInstaller::Approval> approval;
187 if (!id.empty())
188 approval = GetApproval(ext_relpath, id, true);
190 base::FilePath crx_path = PackExtension(ext_path);
191 EXPECT_FALSE(crx_path.empty());
192 RunCrxInstaller(approval.get(), mock_install_prompt->CreatePrompt(),
193 crx_path);
195 EXPECT_TRUE(mock_install_prompt->did_succeed());
198 // Installs an extension and checks that it has scopes granted IFF
199 // |record_oauth2_grant| is true.
200 void CheckHasEmptyScopesAfterInstall(const std::string& ext_relpath,
201 bool record_oauth2_grant) {
202 CommandLine::ForCurrentProcess()->AppendSwitch(
203 switches::kEnableExperimentalExtensionApis);
205 scoped_refptr<MockPromptProxy> mock_prompt =
206 CreateMockPromptProxyForBrowser(browser());
208 mock_prompt->set_record_oauth2_grant(record_oauth2_grant);
209 InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt);
211 scoped_refptr<PermissionSet> permissions =
212 ExtensionPrefs::Get(browser()->profile())
213 ->GetGrantedPermissions(mock_prompt->extension_id());
214 ASSERT_TRUE(permissions.get());
218 #if defined(OS_CHROMEOS)
219 #define MAYBE_Whitelisting DISABLED_Whitelisting
220 #else
221 #define MAYBE_Whitelisting Whitelisting
222 #endif
223 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, MAYBE_Whitelisting) {
224 std::string id = "hdgllgikmikobbofgnabhfimcfoopgnd";
225 ExtensionService* service = extensions::ExtensionSystem::Get(
226 browser()->profile())->extension_service();
228 // Even whitelisted extensions with NPAPI should not prompt.
229 scoped_refptr<MockPromptProxy> mock_prompt =
230 CreateMockPromptProxyForBrowser(browser());
231 InstallWithPrompt("uitest/plugins", id, mock_prompt);
232 EXPECT_FALSE(mock_prompt->confirmation_requested());
233 EXPECT_TRUE(service->GetExtensionById(id, false));
236 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
237 GalleryInstallGetsExperimental) {
238 // We must modify the command line temporarily in order to pack an extension
239 // that requests the experimental permission.
240 CommandLine* command_line = CommandLine::ForCurrentProcess();
241 CommandLine old_command_line = *command_line;
242 command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
243 base::FilePath crx_path = PackExtension(
244 test_data_dir_.AppendASCII("experimental"));
245 ASSERT_FALSE(crx_path.empty());
247 // Now reset the command line so that we are testing specifically whether
248 // installing from webstore enables experimental permissions.
249 *(CommandLine::ForCurrentProcess()) = old_command_line;
251 EXPECT_FALSE(InstallExtension(crx_path, 0));
252 EXPECT_TRUE(InstallExtensionFromWebstore(crx_path, 1));
255 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, PlatformAppCrx) {
256 CommandLine::ForCurrentProcess()->AppendSwitch(
257 switches::kEnableExperimentalExtensionApis);
258 EXPECT_TRUE(InstallExtension(
259 test_data_dir_.AppendASCII("minimal_platform_app.crx"), 1));
262 // http://crbug.com/136397
263 #if defined(OS_CHROMEOS)
264 #define MAYBE_PackAndInstallExtension DISABLED_PackAndInstallExtension
265 #else
266 #define MAYBE_PackAndInstallExtension PackAndInstallExtension
267 #endif
268 IN_PROC_BROWSER_TEST_F(
269 ExtensionCrxInstallerTest, MAYBE_PackAndInstallExtension) {
270 if (!FeatureSwitch::easy_off_store_install()->IsEnabled())
271 return;
273 const int kNumDownloadsExpected = 1;
275 LOG(ERROR) << "PackAndInstallExtension: Packing extension";
276 base::FilePath crx_path = PackExtension(
277 test_data_dir_.AppendASCII("common/background_page"));
278 ASSERT_FALSE(crx_path.empty());
279 std::string crx_path_string(crx_path.value().begin(), crx_path.value().end());
280 GURL url = GURL(std::string("file:///").append(crx_path_string));
282 scoped_refptr<MockPromptProxy> mock_prompt =
283 CreateMockPromptProxyForBrowser(browser());
284 download_crx_util::SetMockInstallPromptForTesting(
285 mock_prompt->CreatePrompt());
287 LOG(ERROR) << "PackAndInstallExtension: Getting download manager";
288 content::DownloadManager* download_manager =
289 content::BrowserContext::GetDownloadManager(browser()->profile());
291 LOG(ERROR) << "PackAndInstallExtension: Setting observer";
292 scoped_ptr<content::DownloadTestObserver> observer(
293 new content::DownloadTestObserverTerminal(
294 download_manager, kNumDownloadsExpected,
295 content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));
296 LOG(ERROR) << "PackAndInstallExtension: Navigating to URL";
297 ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB,
298 ui_test_utils::BROWSER_TEST_NONE);
300 EXPECT_TRUE(WaitForCrxInstallerDone());
301 LOG(ERROR) << "PackAndInstallExtension: Extension install";
302 EXPECT_TRUE(mock_prompt->confirmation_requested());
303 LOG(ERROR) << "PackAndInstallExtension: Extension install confirmed";
306 // Tests that scopes are only granted if |record_oauth2_grant_| on the prompt is
307 // true.
308 #if defined(OS_WIN)
309 #define MAYBE_GrantScopes DISABLED_GrantScopes
310 #else
311 #define MAYBE_GrantScopes GrantScopes
312 #endif
313 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, MAYBE_GrantScopes) {
314 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
315 true));
318 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, DoNotGrantScopes) {
319 EXPECT_NO_FATAL_FAILURE(CheckHasEmptyScopesAfterInstall("browsertest/scopes",
320 false));
323 // Off-store install cannot yet be disabled on Aura.
324 #if defined(USE_AURA)
325 #define MAYBE_AllowOffStore DISABLED_AllowOffStore
326 #else
327 #define MAYBE_AllowOffStore AllowOffStore
328 #endif
329 // Crashy: http://crbug.com/140893
330 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, DISABLED_AllowOffStore) {
331 ExtensionService* service = extensions::ExtensionSystem::Get(
332 browser()->profile())->extension_service();
333 const bool kTestData[] = {false, true};
335 for (size_t i = 0; i < arraysize(kTestData); ++i) {
336 scoped_refptr<MockPromptProxy> mock_prompt =
337 CreateMockPromptProxyForBrowser(browser());
339 scoped_refptr<CrxInstaller> crx_installer(
340 CrxInstaller::Create(service, mock_prompt->CreatePrompt()));
341 crx_installer->set_install_cause(
342 extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
344 if (kTestData[i]) {
345 crx_installer->set_off_store_install_allow_reason(
346 CrxInstaller::OffStoreInstallAllowedInTest);
349 crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx"));
350 EXPECT_EQ(kTestData[i],
351 WaitForExtensionInstall()) << kTestData[i];
352 EXPECT_EQ(kTestData[i], mock_prompt->did_succeed());
353 EXPECT_EQ(kTestData[i], mock_prompt->confirmation_requested()) <<
354 kTestData[i];
355 if (kTestData[i]) {
356 EXPECT_EQ(base::string16(), mock_prompt->error()) << kTestData[i];
357 } else {
358 EXPECT_EQ(l10n_util::GetStringUTF16(
359 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE),
360 mock_prompt->error()) << kTestData[i];
365 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, HiDpiThemeTest) {
366 base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx");
367 crx_path = crx_path.AppendASCII("theme_hidpi.crx");
369 ASSERT_TRUE(InstallExtension(crx_path,1));
371 const std::string extension_id("gllekhaobjnhgeagipipnkpmmmpchacm");
372 ExtensionService* service = extensions::ExtensionSystem::Get(
373 browser()->profile())->extension_service();
374 ASSERT_TRUE(service);
375 const extensions::Extension* extension =
376 service->GetExtensionById(extension_id, false);
377 ASSERT_TRUE(extension);
378 EXPECT_EQ(extension_id, extension->id());
380 UninstallExtension(extension_id);
381 EXPECT_FALSE(service->GetExtensionById(extension_id, false));
384 // See http://crbug.com/315299.
385 #if defined(OS_WIN)
386 #define MAYBE_InstallDelayedUntilNextUpdate \
387 DISABLED_InstallDelayedUntilNextUpdate
388 #else
389 #define MAYBE_InstallDelayedUntilNextUpdate InstallDelayedUntilNextUpdate
390 #endif // defined(OS_WIN)
391 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest,
392 MAYBE_InstallDelayedUntilNextUpdate) {
393 const std::string extension_id("ldnnhddmnhbkjipkidpdiheffobcpfmf");
394 base::FilePath crx_path = test_data_dir_.AppendASCII("delayed_install");
395 ExtensionSystem* extension_system = extensions::ExtensionSystem::Get(
396 browser()->profile());
397 ExtensionService* service = extension_system->extension_service();
398 ASSERT_TRUE(service);
400 // Install version 1 of the test extension. This extension does not have
401 // a background page but does have a browser action.
402 ASSERT_TRUE(InstallExtension(crx_path.AppendASCII("v1.crx"), 1));
403 const extensions::Extension* extension =
404 service->GetExtensionById(extension_id, false);
405 ASSERT_TRUE(extension);
406 ASSERT_EQ(extension_id, extension->id());
407 ASSERT_EQ("1.0", extension->version()->GetString());
409 // Make test extension non-idle by opening the extension's browser action
410 // popup. This should cause the installation to be delayed.
411 content::WindowedNotificationObserver loading_observer(
412 chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
413 content::Source<Profile>(profile()));
414 BrowserActionTestUtil util(browser());
415 // There is only one extension, so just click the first browser action.
416 ASSERT_EQ(1, util.NumberOfBrowserActions());
417 util.Press(0);
418 loading_observer.Wait();
419 ExtensionHost* extension_host =
420 content::Details<ExtensionHost>(loading_observer.details()).ptr();
422 // Install version 2 of the extension and check that it is indeed delayed.
423 ASSERT_TRUE(UpdateExtensionWaitForIdle(
424 extension_id, crx_path.AppendASCII("v2.crx"), 0));
426 ASSERT_EQ(1u, service->delayed_installs()->size());
427 extension = service->GetExtensionById(extension_id, false);
428 ASSERT_EQ("1.0", extension->version()->GetString());
430 // Make the extension idle again by closing the popup. This should not trigger
431 //the delayed install.
432 content::RenderProcessHostWatcher terminated_observer(
433 extension_host->render_process_host(),
434 content::RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
435 extension_host->render_view_host()->ClosePage();
436 terminated_observer.Wait();
437 ASSERT_EQ(1u, service->delayed_installs()->size());
439 // Install version 3 of the extension. Because the extension is idle,
440 // this install should succeed.
441 ASSERT_TRUE(UpdateExtensionWaitForIdle(
442 extension_id, crx_path.AppendASCII("v3.crx"), 0));
443 extension = service->GetExtensionById(extension_id, false);
444 ASSERT_EQ("3.0", extension->version()->GetString());
446 // The version 2 delayed install should be cleaned up, and finishing
447 // delayed extension installation shouldn't break anything.
448 ASSERT_EQ(0u, service->delayed_installs()->size());
449 service->MaybeFinishDelayedInstallations();
450 extension = service->GetExtensionById(extension_id, false);
451 ASSERT_EQ("3.0", extension->version()->GetString());
454 #if defined(FULL_SAFE_BROWSING)
455 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Blacklist) {
456 scoped_refptr<FakeSafeBrowsingDatabaseManager> blacklist_db(
457 new FakeSafeBrowsingDatabaseManager(true));
458 Blacklist::ScopedDatabaseManagerForTest scoped_blacklist_db(blacklist_db);
460 blacklist_db->SetUnsafe("gllekhaobjnhgeagipipnkpmmmpchacm");
462 base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx")
463 .AppendASCII("theme_hidpi.crx");
464 EXPECT_FALSE(InstallExtension(crx_path, 0));
466 #endif
468 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, NonStrictManifestCheck) {
469 scoped_refptr<MockPromptProxy> mock_prompt =
470 CreateMockPromptProxyForBrowser(browser());
472 // We want to simulate the case where the webstore sends a more recent
473 // version of the manifest, but the downloaded .crx file is old since
474 // the newly published version hasn't fully propagated to all the download
475 // servers yet. So load the v2 manifest, but then install the v1 crx file.
476 std::string id = "lhnaeclnpobnlbjbgogdanmhadigfnjp";
477 scoped_ptr<WebstoreInstaller::Approval> approval =
478 GetApproval("crx_installer/v2_no_permission_change/", id, false);
480 RunCrxInstaller(approval.get(), mock_prompt->CreatePrompt(),
481 test_data_dir_.AppendASCII("crx_installer/v1.crx"));
483 EXPECT_TRUE(mock_prompt->did_succeed());
486 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, KioskOnlyTest) {
487 base::FilePath crx_path =
488 test_data_dir_.AppendASCII("kiosk/kiosk_only.crx");
489 EXPECT_FALSE(InstallExtension(crx_path, 0));
490 #if defined(OS_CHROMEOS)
491 // Simulate ChromeOS kiosk mode. |scoped_user_manager| will take over
492 // lifetime of |user_manager|.
493 chromeos::FakeUserManager* fake_user_manager =
494 new chromeos::FakeUserManager();
495 fake_user_manager->AddKioskAppUser("example@example.com");
496 fake_user_manager->LoginUser("example@example.com");
497 chromeos::ScopedUserManagerEnabler scoped_user_manager(fake_user_manager);
498 EXPECT_TRUE(InstallExtension(crx_path, 1));
499 #endif
502 #if defined(OS_CHROMEOS)
503 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, InstallToSharedLocation) {
504 base::ShadowingAtExitManager at_exit_manager;
505 CommandLine::ForCurrentProcess()->AppendSwitch(
506 chromeos::switches::kEnableExtensionAssetsSharing);
507 base::ScopedTempDir cache_dir;
508 ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
509 ExtensionAssetsManagerChromeOS::SetSharedInstallDirForTesting(
510 cache_dir.path());
512 base::FilePath crx_path = test_data_dir_.AppendASCII("crx_installer/v1.crx");
513 const extensions::Extension* extension = InstallExtension(
514 crx_path, 1, extensions::Manifest::EXTERNAL_PREF);
515 base::FilePath extension_path = extension->path();
516 EXPECT_TRUE(cache_dir.path().IsParent(extension_path));
517 EXPECT_TRUE(base::PathExists(extension_path));
519 std::string extension_id = extension->id();
520 UninstallExtension(extension_id);
521 ExtensionService* service = extensions::ExtensionSystem::Get(
522 browser()->profile())->extension_service();
523 EXPECT_FALSE(service->GetExtensionById(extension_id, false));
525 // In the worst case you need to repeat this up to 3 times to make sure that
526 // all pending tasks we sent from UI thread to task runner and back to UI.
527 for (int i = 0; i < 3; i++) {
528 // Wait for background task completion that sends replay to UI thread.
529 content::BrowserThread::GetBlockingPool()->FlushForTesting();
530 // Wait for UI thread task completion.
531 base::RunLoop().RunUntilIdle();
534 EXPECT_FALSE(base::PathExists(extension_path));
536 #endif
538 } // namespace extensions