Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / extensions / extension_browsertest.cc
blob12e0c5371177a9e213099ed3fa249a9eb9f812cd
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/extensions/extension_browsertest.h"
7 #include <vector>
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/extensions/browsertest_util.h"
18 #include "chrome/browser/extensions/component_loader.h"
19 #include "chrome/browser/extensions/crx_installer.h"
20 #include "chrome/browser/extensions/extension_creator.h"
21 #include "chrome/browser/extensions/extension_error_reporter.h"
22 #include "chrome/browser/extensions/extension_install_prompt.h"
23 #include "chrome/browser/extensions/extension_install_prompt_show_params.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/extension_util.h"
26 #include "chrome/browser/extensions/unpacked_installer.h"
27 #include "chrome/browser/extensions/updater/extension_cache_fake.h"
28 #include "chrome/browser/extensions/updater/extension_updater.h"
29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/browser/profiles/profile_manager.h"
31 #include "chrome/browser/ui/browser.h"
32 #include "chrome/browser/ui/browser_window.h"
33 #include "chrome/browser/ui/extensions/application_launch.h"
34 #include "chrome/browser/ui/extensions/extension_message_bubble_factory.h"
35 #include "chrome/browser/ui/tabs/tab_strip_model.h"
36 #include "chrome/common/chrome_paths.h"
37 #include "chrome/common/chrome_switches.h"
38 #include "components/version_info/version_info.h"
39 #include "content/public/browser/navigation_controller.h"
40 #include "content/public/browser/navigation_entry.h"
41 #include "content/public/browser/notification_registrar.h"
42 #include "content/public/browser/notification_service.h"
43 #include "content/public/browser/render_view_host.h"
44 #include "content/public/test/browser_test_utils.h"
45 #include "content/public/test/test_utils.h"
46 #include "extensions/browser/extension_host.h"
47 #include "extensions/browser/extension_prefs.h"
48 #include "extensions/browser/extension_registry.h"
49 #include "extensions/browser/extension_system.h"
50 #include "extensions/browser/notification_types.h"
51 #include "extensions/browser/uninstall_reason.h"
52 #include "extensions/common/constants.h"
53 #include "extensions/common/extension_set.h"
54 #include "sync/api/string_ordinal.h"
56 #if defined(OS_CHROMEOS)
57 #include "chromeos/chromeos_switches.h"
58 #endif
60 using extensions::Extension;
61 using extensions::ExtensionCreator;
62 using extensions::ExtensionRegistry;
63 using extensions::FeatureSwitch;
64 using extensions::Manifest;
66 ExtensionBrowserTest::ExtensionBrowserTest()
67 : loaded_(false),
68 installed_(false),
69 #if defined(OS_CHROMEOS)
70 set_chromeos_user_(true),
71 #endif
72 // Default channel is STABLE but override with UNKNOWN so that unlaunched
73 // or incomplete APIs can write tests.
74 current_channel_(version_info::Channel::UNKNOWN),
75 override_prompt_for_external_extensions_(
76 FeatureSwitch::prompt_for_external_extensions(),
77 false),
78 #if defined(OS_WIN)
79 user_desktop_override_(base::DIR_USER_DESKTOP),
80 common_desktop_override_(base::DIR_COMMON_DESKTOP),
81 user_quick_launch_override_(base::DIR_USER_QUICK_LAUNCH),
82 start_menu_override_(base::DIR_START_MENU),
83 common_start_menu_override_(base::DIR_COMMON_START_MENU),
84 #endif
85 profile_(NULL) {
86 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
89 ExtensionBrowserTest::~ExtensionBrowserTest() {
92 Profile* ExtensionBrowserTest::profile() {
93 if (!profile_) {
94 if (browser())
95 profile_ = browser()->profile();
96 else
97 profile_ = ProfileManager::GetActiveUserProfile();
99 return profile_;
102 // static
103 const Extension* ExtensionBrowserTest::GetExtensionByPath(
104 const extensions::ExtensionSet& extensions,
105 const base::FilePath& path) {
106 base::FilePath extension_path = base::MakeAbsoluteFilePath(path);
107 EXPECT_TRUE(!extension_path.empty());
108 for (const scoped_refptr<const Extension>& extension : extensions) {
109 if (extension->path() == extension_path) {
110 return extension.get();
113 return NULL;
116 void ExtensionBrowserTest::SetUp() {
117 test_extension_cache_.reset(new extensions::ExtensionCacheFake());
118 InProcessBrowserTest::SetUp();
121 void ExtensionBrowserTest::SetUpCommandLine(base::CommandLine* command_line) {
122 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
123 test_data_dir_ = test_data_dir_.AppendASCII("extensions");
124 observer_.reset(new ExtensionTestNotificationObserver(browser()));
126 // We don't want any warning bubbles for, e.g., unpacked extensions.
127 ExtensionMessageBubbleFactory::set_override_for_tests(
128 ExtensionMessageBubbleFactory::OVERRIDE_DISABLED);
130 #if defined(OS_CHROMEOS)
131 if (set_chromeos_user_) {
132 // This makes sure that we create the Default profile first, with no
133 // ExtensionService and then the real profile with one, as we do when
134 // running on chromeos.
135 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
136 "TestUser@gmail.com");
137 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
139 #endif
142 void ExtensionBrowserTest::SetUpOnMainThread() {
143 InProcessBrowserTest::SetUpOnMainThread();
144 observer_.reset(new ExtensionTestNotificationObserver(browser()));
145 if (extension_service()->updater()) {
146 extension_service()->updater()->SetExtensionCacheForTesting(
147 test_extension_cache_.get());
151 void ExtensionBrowserTest::TearDownOnMainThread() {
152 ExtensionMessageBubbleFactory::set_override_for_tests(
153 ExtensionMessageBubbleFactory::NO_OVERRIDE);
154 InProcessBrowserTest::TearDownOnMainThread();
157 const Extension* ExtensionBrowserTest::LoadExtension(
158 const base::FilePath& path) {
159 return LoadExtensionWithFlags(path, kFlagEnableFileAccess);
162 const Extension* ExtensionBrowserTest::LoadExtensionIncognito(
163 const base::FilePath& path) {
164 return LoadExtensionWithFlags(path,
165 kFlagEnableFileAccess | kFlagEnableIncognito);
168 const Extension* ExtensionBrowserTest::LoadExtensionWithFlags(
169 const base::FilePath& path, int flags) {
170 return LoadExtensionWithInstallParam(path, flags, std::string());
173 const extensions::Extension*
174 ExtensionBrowserTest::LoadExtensionWithInstallParam(
175 const base::FilePath& path,
176 int flags,
177 const std::string& install_param) {
178 ExtensionService* service = extensions::ExtensionSystem::Get(
179 profile())->extension_service();
180 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
182 observer_->Watch(extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
183 content::NotificationService::AllSources());
185 scoped_refptr<extensions::UnpackedInstaller> installer(
186 extensions::UnpackedInstaller::Create(service));
187 installer->set_prompt_for_plugins(false);
188 installer->set_require_modern_manifest_version(
189 (flags & kFlagAllowOldManifestVersions) == 0);
190 installer->Load(path);
192 observer_->Wait();
195 // Find the loaded extension by its path. See crbug.com/59531 for why
196 // we cannot just use last_loaded_extension_id().
197 const Extension* extension =
198 GetExtensionByPath(registry->enabled_extensions(), path);
199 if (!extension)
200 return NULL;
202 if (!(flags & kFlagIgnoreManifestWarnings)) {
203 const std::vector<extensions::InstallWarning>& install_warnings =
204 extension->install_warnings();
205 if (!install_warnings.empty()) {
206 std::string install_warnings_message = base::StringPrintf(
207 "Unexpected warnings when loading test extension %s:\n",
208 path.AsUTF8Unsafe().c_str());
210 for (std::vector<extensions::InstallWarning>::const_iterator it =
211 install_warnings.begin(); it != install_warnings.end(); ++it) {
212 install_warnings_message += " " + it->message + "\n";
215 EXPECT_EQ(0u, extension->install_warnings().size())
216 << install_warnings_message;
217 return NULL;
221 const std::string extension_id = extension->id();
223 if (!install_param.empty()) {
224 extensions::ExtensionPrefs::Get(profile())
225 ->SetInstallParam(extension_id, install_param);
226 // Re-enable the extension if needed.
227 if (registry->enabled_extensions().Contains(extension_id)) {
228 content::WindowedNotificationObserver load_signal(
229 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
230 content::Source<Profile>(profile()));
231 // Reload the extension so that the
232 // NOTIFICATION_EXTENSION_LOADED_DEPRECATED
233 // observers may access |install_param|.
234 service->ReloadExtension(extension_id);
235 load_signal.Wait();
236 extension = service->GetExtensionById(extension_id, false);
237 CHECK(extension) << extension_id << " not found after reloading.";
241 // Toggling incognito or file access will reload the extension, so wait for
242 // the reload and grab the new extension instance. The default state is
243 // incognito disabled and file access enabled, so we don't wait in those
244 // cases.
246 content::WindowedNotificationObserver load_signal(
247 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
248 content::Source<Profile>(profile()));
249 CHECK(!extensions::util::IsIncognitoEnabled(extension_id, profile()))
250 << extension_id << " is enabled in incognito, but shouldn't be";
252 if (flags & kFlagEnableIncognito) {
253 extensions::util::SetIsIncognitoEnabled(extension_id, profile(), true);
254 load_signal.Wait();
255 extension = service->GetExtensionById(extension_id, false);
256 CHECK(extension) << extension_id << " not found after reloading.";
261 content::WindowedNotificationObserver load_signal(
262 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
263 content::Source<Profile>(profile()));
264 CHECK(extensions::util::AllowFileAccess(extension_id, profile()));
265 if (!(flags & kFlagEnableFileAccess)) {
266 extensions::util::SetAllowFileAccess(extension_id, profile(), false);
267 load_signal.Wait();
268 extension = service->GetExtensionById(extension_id, false);
269 CHECK(extension) << extension_id << " not found after reloading.";
273 if (!observer_->WaitForExtensionViewsToLoad())
274 return NULL;
276 return extension;
279 const Extension* ExtensionBrowserTest::LoadExtensionAsComponentWithManifest(
280 const base::FilePath& path,
281 const base::FilePath::CharType* manifest_relative_path) {
282 ExtensionService* service = extensions::ExtensionSystem::Get(
283 profile())->extension_service();
284 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
286 std::string manifest;
287 if (!base::ReadFileToString(path.Append(manifest_relative_path), &manifest)) {
288 return NULL;
291 service->component_loader()->set_ignore_whitelist_for_testing(true);
292 std::string extension_id = service->component_loader()->Add(manifest, path);
293 const Extension* extension =
294 registry->enabled_extensions().GetByID(extension_id);
295 if (!extension)
296 return NULL;
297 observer_->set_last_loaded_extension_id(extension->id());
298 return extension;
301 const Extension* ExtensionBrowserTest::LoadExtensionAsComponent(
302 const base::FilePath& path) {
303 return LoadExtensionAsComponentWithManifest(path,
304 extensions::kManifestFilename);
307 const Extension* ExtensionBrowserTest::LoadAndLaunchApp(
308 const base::FilePath& path) {
309 const Extension* app = LoadExtension(path);
310 CHECK(app);
311 content::WindowedNotificationObserver app_loaded_observer(
312 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
313 content::NotificationService::AllSources());
314 AppLaunchParams params(profile(), app, extensions::LAUNCH_CONTAINER_NONE,
315 NEW_WINDOW, extensions::SOURCE_TEST);
316 params.command_line = *base::CommandLine::ForCurrentProcess();
317 OpenApplication(params);
318 app_loaded_observer.Wait();
320 return app;
323 base::FilePath ExtensionBrowserTest::PackExtension(
324 const base::FilePath& dir_path) {
325 base::FilePath crx_path = temp_dir_.path().AppendASCII("temp.crx");
326 if (!base::DeleteFile(crx_path, false)) {
327 ADD_FAILURE() << "Failed to delete crx: " << crx_path.value();
328 return base::FilePath();
331 // Look for PEM files with the same name as the directory.
332 base::FilePath pem_path =
333 dir_path.ReplaceExtension(FILE_PATH_LITERAL(".pem"));
334 base::FilePath pem_path_out;
336 if (!base::PathExists(pem_path)) {
337 pem_path = base::FilePath();
338 pem_path_out = crx_path.DirName().AppendASCII("temp.pem");
339 if (!base::DeleteFile(pem_path_out, false)) {
340 ADD_FAILURE() << "Failed to delete pem: " << pem_path_out.value();
341 return base::FilePath();
345 return PackExtensionWithOptions(dir_path, crx_path, pem_path, pem_path_out);
348 base::FilePath ExtensionBrowserTest::PackExtensionWithOptions(
349 const base::FilePath& dir_path,
350 const base::FilePath& crx_path,
351 const base::FilePath& pem_path,
352 const base::FilePath& pem_out_path) {
353 if (!base::PathExists(dir_path)) {
354 ADD_FAILURE() << "Extension dir not found: " << dir_path.value();
355 return base::FilePath();
358 if (!base::PathExists(pem_path) && pem_out_path.empty()) {
359 ADD_FAILURE() << "Must specify a PEM file or PEM output path";
360 return base::FilePath();
363 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
364 if (!creator->Run(dir_path,
365 crx_path,
366 pem_path,
367 pem_out_path,
368 ExtensionCreator::kOverwriteCRX)) {
369 ADD_FAILURE() << "ExtensionCreator::Run() failed: "
370 << creator->error_message();
371 return base::FilePath();
374 if (!base::PathExists(crx_path)) {
375 ADD_FAILURE() << crx_path.value() << " was not created.";
376 return base::FilePath();
378 return crx_path;
381 // This class is used to simulate an installation abort by the user.
382 class MockAbortExtensionInstallPrompt : public ExtensionInstallPrompt {
383 public:
384 MockAbortExtensionInstallPrompt() : ExtensionInstallPrompt(NULL) {
387 // Simulate a user abort on an extension installation.
388 void ConfirmInstall(Delegate* delegate,
389 const Extension* extension,
390 const ShowDialogCallback& show_dialog_callback) override {
391 delegate->InstallUIAbort(true);
392 base::MessageLoopForUI::current()->Quit();
395 void OnInstallSuccess(const Extension* extension, SkBitmap* icon) override {}
397 void OnInstallFailure(const extensions::CrxInstallError& error) override {}
400 class MockAutoConfirmExtensionInstallPrompt : public ExtensionInstallPrompt {
401 public:
402 explicit MockAutoConfirmExtensionInstallPrompt(
403 content::WebContents* web_contents)
404 : ExtensionInstallPrompt(web_contents) {}
406 // Proceed without confirmation prompt.
407 void ConfirmInstall(Delegate* delegate,
408 const Extension* extension,
409 const ShowDialogCallback& show_dialog_callback) override {
410 delegate->InstallUIProceed();
414 const Extension* ExtensionBrowserTest::UpdateExtensionWaitForIdle(
415 const std::string& id,
416 const base::FilePath& path,
417 int expected_change) {
418 return InstallOrUpdateExtension(id,
419 path,
420 INSTALL_UI_TYPE_NONE,
421 expected_change,
422 Manifest::INTERNAL,
423 browser(),
424 Extension::NO_FLAGS,
425 false,
426 false);
429 const Extension* ExtensionBrowserTest::InstallExtensionFromWebstore(
430 const base::FilePath& path,
431 int expected_change) {
432 return InstallOrUpdateExtension(
433 std::string(), path, INSTALL_UI_TYPE_AUTO_CONFIRM, expected_change,
434 Manifest::INTERNAL, browser(), Extension::FROM_WEBSTORE, true, false);
437 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
438 const std::string& id,
439 const base::FilePath& path,
440 InstallUIType ui_type,
441 int expected_change) {
442 return InstallOrUpdateExtension(id,
443 path,
444 ui_type,
445 expected_change,
446 Manifest::INTERNAL,
447 browser(),
448 Extension::NO_FLAGS,
449 true,
450 false);
453 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
454 const std::string& id,
455 const base::FilePath& path,
456 InstallUIType ui_type,
457 int expected_change,
458 Browser* browser,
459 Extension::InitFromValueFlags creation_flags) {
460 return InstallOrUpdateExtension(id,
461 path,
462 ui_type,
463 expected_change,
464 Manifest::INTERNAL,
465 browser,
466 creation_flags,
467 true,
468 false);
471 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
472 const std::string& id,
473 const base::FilePath& path,
474 InstallUIType ui_type,
475 int expected_change,
476 Manifest::Location install_source) {
477 return InstallOrUpdateExtension(id,
478 path,
479 ui_type,
480 expected_change,
481 install_source,
482 browser(),
483 Extension::NO_FLAGS,
484 true,
485 false);
488 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
489 const std::string& id,
490 const base::FilePath& path,
491 InstallUIType ui_type,
492 int expected_change,
493 Manifest::Location install_source,
494 Browser* browser,
495 Extension::InitFromValueFlags creation_flags,
496 bool install_immediately,
497 bool is_ephemeral) {
498 ExtensionService* service =
499 extensions::ExtensionSystem::Get(profile())->extension_service();
500 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
501 service->set_show_extensions_prompts(false);
502 size_t num_before = registry->enabled_extensions().size();
505 scoped_ptr<ExtensionInstallPrompt> install_ui;
506 if (ui_type == INSTALL_UI_TYPE_CANCEL) {
507 install_ui.reset(new MockAbortExtensionInstallPrompt());
508 } else if (ui_type == INSTALL_UI_TYPE_NORMAL) {
509 install_ui.reset(new ExtensionInstallPrompt(
510 browser->tab_strip_model()->GetActiveWebContents()));
511 } else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) {
512 install_ui.reset(new MockAutoConfirmExtensionInstallPrompt(
513 browser->tab_strip_model()->GetActiveWebContents()));
516 // TODO(tessamac): Update callers to always pass an unpacked extension
517 // and then always pack the extension here.
518 base::FilePath crx_path = path;
519 if (crx_path.Extension() != FILE_PATH_LITERAL(".crx")) {
520 crx_path = PackExtension(path);
522 if (crx_path.empty())
523 return NULL;
525 scoped_refptr<extensions::CrxInstaller> installer(
526 extensions::CrxInstaller::Create(service, install_ui.Pass()));
527 installer->set_expected_id(id);
528 installer->set_creation_flags(creation_flags);
529 installer->set_install_source(install_source);
530 installer->set_install_immediately(install_immediately);
531 installer->set_is_ephemeral(is_ephemeral);
532 if (!installer->is_gallery_install()) {
533 installer->set_off_store_install_allow_reason(
534 extensions::CrxInstaller::OffStoreInstallAllowedInTest);
537 observer_->Watch(
538 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
539 content::Source<extensions::CrxInstaller>(installer.get()));
541 installer->InstallCrx(crx_path);
543 observer_->Wait();
546 size_t num_after = registry->enabled_extensions().size();
547 EXPECT_EQ(num_before + expected_change, num_after);
548 if (num_before + expected_change != num_after) {
549 VLOG(1) << "Num extensions before: " << base::IntToString(num_before)
550 << " num after: " << base::IntToString(num_after)
551 << " Installed extensions follow:";
553 for (const scoped_refptr<const Extension>& extension :
554 registry->enabled_extensions())
555 VLOG(1) << " " << extension->id();
557 VLOG(1) << "Errors follow:";
558 const std::vector<base::string16>* errors =
559 ExtensionErrorReporter::GetInstance()->GetErrors();
560 for (std::vector<base::string16>::const_iterator iter = errors->begin();
561 iter != errors->end(); ++iter)
562 VLOG(1) << *iter;
564 return NULL;
567 if (!observer_->WaitForExtensionViewsToLoad())
568 return NULL;
569 return service->GetExtensionById(last_loaded_extension_id(), false);
572 void ExtensionBrowserTest::ReloadExtension(const std::string extension_id) {
573 observer_->Watch(extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
574 content::NotificationService::AllSources());
576 ExtensionService* service =
577 extensions::ExtensionSystem::Get(profile())->extension_service();
578 service->ReloadExtension(extension_id);
580 observer_->Wait();
581 observer_->WaitForExtensionViewsToLoad();
584 void ExtensionBrowserTest::UnloadExtension(const std::string& extension_id) {
585 ExtensionService* service = extensions::ExtensionSystem::Get(
586 profile())->extension_service();
587 service->UnloadExtension(extension_id,
588 extensions::UnloadedExtensionInfo::REASON_DISABLE);
591 void ExtensionBrowserTest::UninstallExtension(const std::string& extension_id) {
592 ExtensionService* service = extensions::ExtensionSystem::Get(
593 profile())->extension_service();
594 service->UninstallExtension(extension_id,
595 extensions::UNINSTALL_REASON_FOR_TESTING,
596 base::Bind(&base::DoNothing),
597 NULL);
600 void ExtensionBrowserTest::DisableExtension(const std::string& extension_id) {
601 ExtensionService* service = extensions::ExtensionSystem::Get(
602 profile())->extension_service();
603 service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
606 void ExtensionBrowserTest::EnableExtension(const std::string& extension_id) {
607 ExtensionService* service = extensions::ExtensionSystem::Get(
608 profile())->extension_service();
609 service->EnableExtension(extension_id);
612 void ExtensionBrowserTest::OpenWindow(content::WebContents* contents,
613 const GURL& url,
614 bool newtab_process_should_equal_opener,
615 content::WebContents** newtab_result) {
616 content::WindowedNotificationObserver windowed_observer(
617 content::NOTIFICATION_LOAD_STOP,
618 content::NotificationService::AllSources());
619 ASSERT_TRUE(content::ExecuteScript(contents,
620 "window.open('" + url.spec() + "');"));
622 // The above window.open call is not user-initiated, so it will create
623 // a popup window instead of a new tab in current window.
624 // The stop notification will come from the new tab.
625 windowed_observer.Wait();
626 content::NavigationController* controller =
627 content::Source<content::NavigationController>(
628 windowed_observer.source()).ptr();
629 content::WebContents* newtab = controller->GetWebContents();
630 ASSERT_TRUE(newtab);
631 EXPECT_EQ(url, controller->GetLastCommittedEntry()->GetURL());
632 if (newtab_process_should_equal_opener)
633 EXPECT_EQ(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
634 else
635 EXPECT_NE(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
637 if (newtab_result)
638 *newtab_result = newtab;
641 void ExtensionBrowserTest::NavigateInRenderer(content::WebContents* contents,
642 const GURL& url) {
643 // Ensure any existing navigations complete before trying to navigate anew, to
644 // avoid triggering of the unload event for the wrong navigation.
645 content::WaitForLoadStop(contents);
646 bool result = false;
647 content::WindowedNotificationObserver windowed_observer(
648 content::NOTIFICATION_LOAD_STOP,
649 content::NotificationService::AllSources());
650 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
651 contents,
652 "window.addEventListener('unload', function() {"
653 " window.domAutomationController.send(true);"
654 "}, false);"
655 "window.location = '" + url.spec() + "';",
656 &result));
657 ASSERT_TRUE(result);
658 windowed_observer.Wait();
659 EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL());
662 extensions::ExtensionHost* ExtensionBrowserTest::FindHostWithPath(
663 extensions::ProcessManager* manager,
664 const std::string& path,
665 int expected_hosts) {
666 extensions::ExtensionHost* result_host = nullptr;
667 int num_hosts = 0;
668 for (extensions::ExtensionHost* host : manager->background_hosts()) {
669 if (host->GetURL().path() == path) {
670 EXPECT_FALSE(result_host);
671 result_host = host;
673 num_hosts++;
675 EXPECT_EQ(expected_hosts, num_hosts);
676 return result_host;
679 std::string ExtensionBrowserTest::ExecuteScriptInBackgroundPage(
680 const std::string& extension_id,
681 const std::string& script) {
682 return extensions::browsertest_util::ExecuteScriptInBackgroundPage(
683 profile(), extension_id, script);
686 bool ExtensionBrowserTest::ExecuteScriptInBackgroundPageNoWait(
687 const std::string& extension_id,
688 const std::string& script) {
689 return extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait(
690 profile(), extension_id, script);