extension_browsertest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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. 4 5#include "chrome/browser/extensions/extension_browsertest.h" 6 7#include <vector> 8 9#include "base/command_line.h" 10#include "base/file_util.h" 11#include "base/files/file_path.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/chrome_notification_types.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_host.h" 23#include "chrome/browser/extensions/extension_install_prompt.h" 24#include "chrome/browser/extensions/extension_service.h" 25#include "chrome/browser/extensions/extension_system.h" 26#include "chrome/browser/extensions/unpacked_installer.h" 27#include "chrome/browser/profiles/profile.h" 28#include "chrome/browser/profiles/profile_manager.h" 29#include "chrome/browser/ui/browser.h" 30#include "chrome/browser/ui/browser_window.h" 31#include "chrome/browser/ui/omnibox/location_bar.h" 32#include "chrome/browser/ui/tabs/tab_strip_model.h" 33#include "chrome/common/chrome_paths.h" 34#include "chrome/common/chrome_switches.h" 35#include "chrome/common/chrome_version_info.h" 36#include "chrome/common/extensions/extension_manifest_constants.h" 37#include "chrome/common/extensions/extension_set.h" 38#include "chrome/test/base/ui_test_utils.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 "extensions/common/constants.h" 46#include "sync/api/string_ordinal.h" 47 48#if defined(OS_CHROMEOS) 49#include "chromeos/chromeos_switches.h" 50#endif 51 52using extensions::Extension; 53using extensions::ExtensionCreator; 54using extensions::FeatureSwitch; 55using extensions::Manifest; 56 57ExtensionBrowserTest::ExtensionBrowserTest() 58 : loaded_(false), 59 installed_(false), 60 extension_installs_observed_(0), 61 extension_load_errors_observed_(0), 62 target_page_action_count_(-1), 63 target_visible_page_action_count_(-1), 64 current_channel_(chrome::VersionInfo::CHANNEL_DEV), 65 override_prompt_for_external_extensions_( 66 FeatureSwitch::prompt_for_external_extensions(), false), 67 profile_(NULL) { 68 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); 69} 70 71ExtensionBrowserTest::~ExtensionBrowserTest() {} 72 73Profile* ExtensionBrowserTest::profile() { 74 if (!profile_) { 75 if (browser()) 76 profile_ = browser()->profile(); 77 else 78 profile_ = ProfileManager::GetDefaultProfile(); 79 } 80 return profile_; 81} 82 83// static 84const Extension* ExtensionBrowserTest::GetExtensionByPath( 85 const ExtensionSet* extensions, const base::FilePath& path) { 86 base::FilePath extension_path = base::MakeAbsoluteFilePath(path); 87 EXPECT_TRUE(!extension_path.empty()); 88 for (ExtensionSet::const_iterator iter = extensions->begin(); 89 iter != extensions->end(); ++iter) { 90 if ((*iter)->path() == extension_path) { 91 return iter->get(); 92 } 93 } 94 return NULL; 95} 96 97void ExtensionBrowserTest::SetUpCommandLine(CommandLine* command_line) { 98 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_); 99 test_data_dir_ = test_data_dir_.AppendASCII("extensions"); 100 101#if defined(OS_CHROMEOS) 102 // This makes sure that we create the Default profile first, with no 103 // ExtensionService and then the real profile with one, as we do when 104 // running on chromeos. 105 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, 106 "TestUser@gmail.com"); 107 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); 108#endif 109} 110 111void ExtensionBrowserTest::SetUpOnMainThread() { 112 InProcessBrowserTest::SetUpOnMainThread(); 113} 114 115const Extension* ExtensionBrowserTest::LoadExtensionWithFlags( 116 const base::FilePath& path, int flags) { 117 ExtensionService* service = extensions::ExtensionSystem::Get( 118 profile())->extension_service(); 119 { 120 content::NotificationRegistrar registrar; 121 registrar.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 122 content::NotificationService::AllSources()); 123 scoped_refptr<extensions::UnpackedInstaller> installer( 124 extensions::UnpackedInstaller::Create(service)); 125 installer->set_prompt_for_plugins(false); 126 installer->set_require_modern_manifest_version( 127 (flags & kFlagAllowOldManifestVersions) == 0); 128 installer->Load(path); 129 content::RunMessageLoop(); 130 } 131 132 // Find the loaded extension by its path. See crbug.com/59531 for why 133 // we cannot just use last_loaded_extension_id_. 134 const Extension* extension = GetExtensionByPath(service->extensions(), path); 135 if (!extension) 136 return NULL; 137 138 if (!(flags & kFlagIgnoreManifestWarnings)) { 139 const std::vector<extensions::InstallWarning>& install_warnings = 140 extension->install_warnings(); 141 if (!install_warnings.empty()) { 142 std::string install_warnings_message = base::StringPrintf( 143 "Unexpected warnings when loading test extension %s:\n", 144 path.AsUTF8Unsafe().c_str()); 145 146 for (std::vector<extensions::InstallWarning>::const_iterator it = 147 install_warnings.begin(); it != install_warnings.end(); ++it) { 148 install_warnings_message += " " + it->message + "\n"; 149 } 150 151 EXPECT_TRUE(extension->install_warnings().empty()) << 152 install_warnings_message; 153 return NULL; 154 } 155 } 156 157 const std::string extension_id = extension->id(); 158 159 // The call to OnExtensionInstalled ensures the other extension prefs 160 // are set up with the defaults. 161 service->extension_prefs()->OnExtensionInstalled( 162 extension, Extension::ENABLED, 163 syncer::StringOrdinal::CreateInitialOrdinal()); 164 165 // Toggling incognito or file access will reload the extension, so wait for 166 // the reload and grab the new extension instance. The default state is 167 // incognito disabled and file access enabled, so we don't wait in those 168 // cases. 169 { 170 content::WindowedNotificationObserver load_signal( 171 chrome::NOTIFICATION_EXTENSION_LOADED, 172 content::Source<Profile>(profile())); 173 CHECK(!service->IsIncognitoEnabled(extension_id) || 174 extension->force_incognito_enabled()); 175 176 if (flags & kFlagEnableIncognito) { 177 service->SetIsIncognitoEnabled(extension_id, true); 178 load_signal.Wait(); 179 extension = service->GetExtensionById(extension_id, false); 180 CHECK(extension) << extension_id << " not found after reloading."; 181 } 182 } 183 184 { 185 content::WindowedNotificationObserver load_signal( 186 chrome::NOTIFICATION_EXTENSION_LOADED, 187 content::Source<Profile>(profile())); 188 CHECK(service->AllowFileAccess(extension)); 189 if (!(flags & kFlagEnableFileAccess)) { 190 service->SetAllowFileAccess(extension, false); 191 load_signal.Wait(); 192 extension = service->GetExtensionById(extension_id, false); 193 CHECK(extension) << extension_id << " not found after reloading."; 194 } 195 } 196 197 if (!WaitForExtensionViewsToLoad()) 198 return NULL; 199 200 return extension; 201} 202 203const Extension* ExtensionBrowserTest::LoadExtension( 204 const base::FilePath& path) { 205 return LoadExtensionWithFlags(path, kFlagEnableFileAccess); 206} 207 208const Extension* ExtensionBrowserTest::LoadExtensionIncognito( 209 const base::FilePath& path) { 210 return LoadExtensionWithFlags(path, 211 kFlagEnableFileAccess | kFlagEnableIncognito); 212} 213 214const Extension* ExtensionBrowserTest::LoadExtensionAsComponentWithManifest( 215 const base::FilePath& path, 216 const base::FilePath::CharType* manifest_relative_path) { 217 ExtensionService* service = extensions::ExtensionSystem::Get( 218 profile())->extension_service(); 219 220 std::string manifest; 221 if (!file_util::ReadFileToString(path.Append(manifest_relative_path), 222 &manifest)) { 223 return NULL; 224 } 225 226 std::string extension_id = service->component_loader()->Add(manifest, path); 227 const Extension* extension = service->extensions()->GetByID(extension_id); 228 if (!extension) 229 return NULL; 230 last_loaded_extension_id_ = extension->id(); 231 return extension; 232} 233 234const Extension* ExtensionBrowserTest::LoadExtensionAsComponent( 235 const base::FilePath& path) { 236 return LoadExtensionAsComponentWithManifest(path, 237 extensions::kManifestFilename); 238} 239 240base::FilePath ExtensionBrowserTest::PackExtension( 241 const base::FilePath& dir_path) { 242 base::FilePath crx_path = temp_dir_.path().AppendASCII("temp.crx"); 243 if (!base::DeleteFile(crx_path, false)) { 244 ADD_FAILURE() << "Failed to delete crx: " << crx_path.value(); 245 return base::FilePath(); 246 } 247 248 // Look for PEM files with the same name as the directory. 249 base::FilePath pem_path = 250 dir_path.ReplaceExtension(FILE_PATH_LITERAL(".pem")); 251 base::FilePath pem_path_out; 252 253 if (!base::PathExists(pem_path)) { 254 pem_path = base::FilePath(); 255 pem_path_out = crx_path.DirName().AppendASCII("temp.pem"); 256 if (!base::DeleteFile(pem_path_out, false)) { 257 ADD_FAILURE() << "Failed to delete pem: " << pem_path_out.value(); 258 return base::FilePath(); 259 } 260 } 261 262 return PackExtensionWithOptions(dir_path, crx_path, pem_path, pem_path_out); 263} 264 265base::FilePath ExtensionBrowserTest::PackExtensionWithOptions( 266 const base::FilePath& dir_path, 267 const base::FilePath& crx_path, 268 const base::FilePath& pem_path, 269 const base::FilePath& pem_out_path) { 270 if (!base::PathExists(dir_path)) { 271 ADD_FAILURE() << "Extension dir not found: " << dir_path.value(); 272 return base::FilePath(); 273 } 274 275 if (!base::PathExists(pem_path) && pem_out_path.empty()) { 276 ADD_FAILURE() << "Must specify a PEM file or PEM output path"; 277 return base::FilePath(); 278 } 279 280 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator()); 281 if (!creator->Run(dir_path, 282 crx_path, 283 pem_path, 284 pem_out_path, 285 ExtensionCreator::kOverwriteCRX)) { 286 ADD_FAILURE() << "ExtensionCreator::Run() failed: " 287 << creator->error_message(); 288 return base::FilePath(); 289 } 290 291 if (!base::PathExists(crx_path)) { 292 ADD_FAILURE() << crx_path.value() << " was not created."; 293 return base::FilePath(); 294 } 295 return crx_path; 296} 297 298// This class is used to simulate an installation abort by the user. 299class MockAbortExtensionInstallPrompt : public ExtensionInstallPrompt { 300 public: 301 MockAbortExtensionInstallPrompt() : ExtensionInstallPrompt(NULL) { 302 } 303 304 // Simulate a user abort on an extension installation. 305 virtual void ConfirmInstall( 306 Delegate* delegate, 307 const Extension* extension, 308 const ShowDialogCallback& show_dialog_callback) OVERRIDE { 309 delegate->InstallUIAbort(true); 310 base::MessageLoopForUI::current()->Quit(); 311 } 312 313 virtual void OnInstallSuccess(const Extension* extension, 314 SkBitmap* icon) OVERRIDE {} 315 316 virtual void OnInstallFailure( 317 const extensions::CrxInstallerError& error) OVERRIDE {} 318}; 319 320class MockAutoConfirmExtensionInstallPrompt : public ExtensionInstallPrompt { 321 public: 322 explicit MockAutoConfirmExtensionInstallPrompt( 323 content::WebContents* web_contents) 324 : ExtensionInstallPrompt(web_contents) {} 325 326 // Proceed without confirmation prompt. 327 virtual void ConfirmInstall( 328 Delegate* delegate, 329 const Extension* extension, 330 const ShowDialogCallback& show_dialog_callback) OVERRIDE { 331 delegate->InstallUIProceed(); 332 } 333}; 334 335const Extension* ExtensionBrowserTest::InstallExtensionFromWebstore( 336 const base::FilePath& path, 337 int expected_change) { 338 return InstallOrUpdateExtension(std::string(), 339 path, 340 INSTALL_UI_TYPE_NONE, 341 expected_change, 342 Manifest::INTERNAL, 343 browser(), 344 true); 345} 346 347const Extension* ExtensionBrowserTest::InstallOrUpdateExtension( 348 const std::string& id, 349 const base::FilePath& path, 350 InstallUIType ui_type, 351 int expected_change) { 352 return InstallOrUpdateExtension(id, path, ui_type, expected_change, 353 Manifest::INTERNAL, browser(), false); 354} 355 356const Extension* ExtensionBrowserTest::InstallOrUpdateExtension( 357 const std::string& id, 358 const base::FilePath& path, 359 InstallUIType ui_type, 360 int expected_change, 361 Browser* browser, 362 bool from_webstore) { 363 return InstallOrUpdateExtension(id, path, ui_type, expected_change, 364 Manifest::INTERNAL, browser, from_webstore); 365} 366 367const Extension* ExtensionBrowserTest::InstallOrUpdateExtension( 368 const std::string& id, 369 const base::FilePath& path, 370 InstallUIType ui_type, 371 int expected_change, 372 Manifest::Location install_source) { 373 return InstallOrUpdateExtension(id, path, ui_type, expected_change, 374 install_source, browser(), false); 375} 376 377const Extension* ExtensionBrowserTest::InstallOrUpdateExtension( 378 const std::string& id, 379 const base::FilePath& path, 380 InstallUIType ui_type, 381 int expected_change, 382 Manifest::Location install_source, 383 Browser* browser, 384 bool from_webstore) { 385 ExtensionService* service = profile()->GetExtensionService(); 386 service->set_show_extensions_prompts(false); 387 size_t num_before = service->extensions()->size(); 388 389 { 390 ExtensionInstallPrompt* install_ui = NULL; 391 if (ui_type == INSTALL_UI_TYPE_CANCEL) { 392 install_ui = new MockAbortExtensionInstallPrompt(); 393 } else if (ui_type == INSTALL_UI_TYPE_NORMAL) { 394 install_ui = new ExtensionInstallPrompt( 395 browser->tab_strip_model()->GetActiveWebContents()); 396 } else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) { 397 install_ui = new MockAutoConfirmExtensionInstallPrompt( 398 browser->tab_strip_model()->GetActiveWebContents()); 399 } 400 401 // TODO(tessamac): Update callers to always pass an unpacked extension 402 // and then always pack the extension here. 403 base::FilePath crx_path = path; 404 if (crx_path.Extension() != FILE_PATH_LITERAL(".crx")) { 405 crx_path = PackExtension(path); 406 } 407 if (crx_path.empty()) 408 return NULL; 409 410 scoped_refptr<extensions::CrxInstaller> installer( 411 extensions::CrxInstaller::Create(service, install_ui)); 412 installer->set_expected_id(id); 413 installer->set_is_gallery_install(from_webstore); 414 installer->set_install_source(install_source); 415 installer->set_install_wait_for_idle(false); 416 if (!from_webstore) { 417 installer->set_off_store_install_allow_reason( 418 extensions::CrxInstaller::OffStoreInstallAllowedInTest); 419 } 420 421 content::NotificationRegistrar registrar; 422 registrar.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE, 423 content::Source<extensions::CrxInstaller>(installer.get())); 424 425 installer->InstallCrx(crx_path); 426 427 content::RunMessageLoop(); 428 } 429 430 size_t num_after = service->extensions()->size(); 431 EXPECT_EQ(num_before + expected_change, num_after); 432 if (num_before + expected_change != num_after) { 433 VLOG(1) << "Num extensions before: " << base::IntToString(num_before) 434 << " num after: " << base::IntToString(num_after) 435 << " Installed extensions follow:"; 436 437 for (ExtensionSet::const_iterator it = service->extensions()->begin(); 438 it != service->extensions()->end(); ++it) 439 VLOG(1) << " " << (*it)->id(); 440 441 VLOG(1) << "Errors follow:"; 442 const std::vector<string16>* errors = 443 ExtensionErrorReporter::GetInstance()->GetErrors(); 444 for (std::vector<string16>::const_iterator iter = errors->begin(); 445 iter != errors->end(); ++iter) 446 VLOG(1) << *iter; 447 448 return NULL; 449 } 450 451 if (!WaitForExtensionViewsToLoad()) 452 return NULL; 453 return service->GetExtensionById(last_loaded_extension_id_, false); 454} 455 456void ExtensionBrowserTest::ReloadExtension(const std::string extension_id) { 457 ExtensionService* service = extensions::ExtensionSystem::Get( 458 profile())->extension_service(); 459 service->ReloadExtension(extension_id); 460 ui_test_utils::RegisterAndWait(this, 461 chrome::NOTIFICATION_EXTENSION_LOADED, 462 content::NotificationService::AllSources()); 463} 464 465void ExtensionBrowserTest::UnloadExtension(const std::string& extension_id) { 466 ExtensionService* service = extensions::ExtensionSystem::Get( 467 profile())->extension_service(); 468 service->UnloadExtension(extension_id, extension_misc::UNLOAD_REASON_DISABLE); 469} 470 471void ExtensionBrowserTest::UninstallExtension(const std::string& extension_id) { 472 ExtensionService* service = extensions::ExtensionSystem::Get( 473 profile())->extension_service(); 474 service->UninstallExtension(extension_id, false, NULL); 475} 476 477void ExtensionBrowserTest::DisableExtension(const std::string& extension_id) { 478 ExtensionService* service = extensions::ExtensionSystem::Get( 479 profile())->extension_service(); 480 service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION); 481} 482 483void ExtensionBrowserTest::EnableExtension(const std::string& extension_id) { 484 ExtensionService* service = extensions::ExtensionSystem::Get( 485 profile())->extension_service(); 486 service->EnableExtension(extension_id); 487} 488 489bool ExtensionBrowserTest::WaitForPageActionCountChangeTo(int count) { 490 LocationBarTesting* location_bar = 491 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 492 if (location_bar->PageActionCount() != count) { 493 target_page_action_count_ = count; 494 ui_test_utils::RegisterAndWait(this, 495 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, 496 content::NotificationService::AllSources()); 497 } 498 return location_bar->PageActionCount() == count; 499} 500 501bool ExtensionBrowserTest::WaitForPageActionVisibilityChangeTo(int count) { 502 LocationBarTesting* location_bar = 503 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 504 if (location_bar->PageActionVisibleCount() != count) { 505 target_visible_page_action_count_ = count; 506 ui_test_utils::RegisterAndWait(this, 507 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, 508 content::NotificationService::AllSources()); 509 } 510 return location_bar->PageActionVisibleCount() == count; 511} 512 513bool ExtensionBrowserTest::WaitForExtensionViewsToLoad() { 514 // Wait for all the extension render view hosts that exist to finish loading. 515 content::NotificationRegistrar registrar; 516 registrar.Add(this, content::NOTIFICATION_LOAD_STOP, 517 content::NotificationService::AllSources()); 518 519 ExtensionProcessManager* manager = 520 extensions::ExtensionSystem::Get(profile())->process_manager(); 521 ExtensionProcessManager::ViewSet all_views = manager->GetAllViews(); 522 for (ExtensionProcessManager::ViewSet::const_iterator iter = 523 all_views.begin(); 524 iter != all_views.end();) { 525 if (!(*iter)->IsLoading()) { 526 ++iter; 527 } else { 528 content::RunMessageLoop(); 529 530 // Test activity may have modified the set of extension processes during 531 // message processing, so re-start the iteration to catch added/removed 532 // processes. 533 all_views = manager->GetAllViews(); 534 iter = all_views.begin(); 535 } 536 } 537 return true; 538} 539 540bool ExtensionBrowserTest::WaitForExtensionInstall() { 541 int before = extension_installs_observed_; 542 ui_test_utils::RegisterAndWait(this, 543 chrome::NOTIFICATION_EXTENSION_INSTALLED, 544 content::NotificationService::AllSources()); 545 return extension_installs_observed_ == (before + 1); 546} 547 548bool ExtensionBrowserTest::WaitForExtensionInstallError() { 549 int before = extension_installs_observed_; 550 ui_test_utils::RegisterAndWait(this, 551 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 552 content::NotificationService::AllSources()); 553 return extension_installs_observed_ == before; 554} 555 556void ExtensionBrowserTest::WaitForExtensionLoad() { 557 ui_test_utils::RegisterAndWait(this, chrome::NOTIFICATION_EXTENSION_LOADED, 558 content::NotificationService::AllSources()); 559 WaitForExtensionViewsToLoad(); 560} 561 562bool ExtensionBrowserTest::WaitForExtensionLoadError() { 563 int before = extension_load_errors_observed_; 564 ui_test_utils::RegisterAndWait(this, 565 chrome::NOTIFICATION_EXTENSION_LOAD_ERROR, 566 content::NotificationService::AllSources()); 567 return extension_load_errors_observed_ != before; 568} 569 570bool ExtensionBrowserTest::WaitForExtensionCrash( 571 const std::string& extension_id) { 572 ExtensionService* service = extensions::ExtensionSystem::Get( 573 profile())->extension_service(); 574 575 if (!service->GetExtensionById(extension_id, true)) { 576 // The extension is already unloaded, presumably due to a crash. 577 return true; 578 } 579 ui_test_utils::RegisterAndWait( 580 this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, 581 content::NotificationService::AllSources()); 582 return (service->GetExtensionById(extension_id, true) == NULL); 583} 584 585bool ExtensionBrowserTest::WaitForCrxInstallerDone() { 586 int before = crx_installers_done_observed_; 587 ui_test_utils::RegisterAndWait(this, 588 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 589 content::NotificationService::AllSources()); 590 return crx_installers_done_observed_ == (before + 1); 591} 592 593void ExtensionBrowserTest::OpenWindow(content::WebContents* contents, 594 const GURL& url, 595 bool newtab_process_should_equal_opener, 596 content::WebContents** newtab_result) { 597 content::WindowedNotificationObserver observer( 598 content::NOTIFICATION_LOAD_STOP, 599 content::NotificationService::AllSources()); 600 ASSERT_TRUE(content::ExecuteScript(contents, 601 "window.open('" + url.spec() + "');")); 602 603 // The above window.open call is not user-initiated, so it will create 604 // a popup window instead of a new tab in current window. 605 // The stop notification will come from the new tab. 606 observer.Wait(); 607 content::NavigationController* controller = 608 content::Source<content::NavigationController>(observer.source()).ptr(); 609 content::WebContents* newtab = controller->GetWebContents(); 610 ASSERT_TRUE(newtab); 611 EXPECT_EQ(url, controller->GetLastCommittedEntry()->GetURL()); 612 if (newtab_process_should_equal_opener) 613 EXPECT_EQ(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost()); 614 else 615 EXPECT_NE(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost()); 616 617 if (newtab_result) 618 *newtab_result = newtab; 619} 620 621void ExtensionBrowserTest::NavigateInRenderer(content::WebContents* contents, 622 const GURL& url) { 623 bool result = false; 624 content::WindowedNotificationObserver observer( 625 content::NOTIFICATION_LOAD_STOP, 626 content::NotificationService::AllSources()); 627 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 628 contents, 629 "window.addEventListener('unload', function() {" 630 " window.domAutomationController.send(true);" 631 "}, false);" 632 "window.location = '" + url.spec() + "';", 633 &result)); 634 ASSERT_TRUE(result); 635 observer.Wait(); 636 EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL()); 637} 638 639extensions::ExtensionHost* ExtensionBrowserTest::FindHostWithPath( 640 ExtensionProcessManager* manager, 641 const std::string& path, 642 int expected_hosts) { 643 extensions::ExtensionHost* host = NULL; 644 int num_hosts = 0; 645 ExtensionProcessManager::ExtensionHostSet background_hosts = 646 manager->background_hosts(); 647 for (ExtensionProcessManager::const_iterator iter = background_hosts.begin(); 648 iter != background_hosts.end(); ++iter) { 649 if ((*iter)->GetURL().path() == path) { 650 EXPECT_FALSE(host); 651 host = *iter; 652 } 653 num_hosts++; 654 } 655 EXPECT_EQ(expected_hosts, num_hosts); 656 return host; 657} 658 659void ExtensionBrowserTest::Observe( 660 int type, 661 const content::NotificationSource& source, 662 const content::NotificationDetails& details) { 663 switch (type) { 664 case chrome::NOTIFICATION_EXTENSION_LOADED: 665 last_loaded_extension_id_ = 666 content::Details<const Extension>(details).ptr()->id(); 667 VLOG(1) << "Got EXTENSION_LOADED notification."; 668 base::MessageLoopForUI::current()->Quit(); 669 break; 670 671 case chrome::NOTIFICATION_CRX_INSTALLER_DONE: 672 VLOG(1) << "Got CRX_INSTALLER_DONE notification."; 673 { 674 const Extension* extension = 675 content::Details<const Extension>(details).ptr(); 676 if (extension) 677 last_loaded_extension_id_ = extension->id(); 678 else 679 last_loaded_extension_id_ = ""; 680 } 681 ++crx_installers_done_observed_; 682 base::MessageLoopForUI::current()->Quit(); 683 break; 684 685 case chrome::NOTIFICATION_EXTENSION_INSTALLED: 686 VLOG(1) << "Got EXTENSION_INSTALLED notification."; 687 ++extension_installs_observed_; 688 base::MessageLoopForUI::current()->Quit(); 689 break; 690 691 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: 692 VLOG(1) << "Got EXTENSION_INSTALL_ERROR notification."; 693 base::MessageLoopForUI::current()->Quit(); 694 break; 695 696 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: 697 VLOG(1) << "Got EXTENSION_PROCESS_TERMINATED notification."; 698 base::MessageLoopForUI::current()->Quit(); 699 break; 700 701 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: 702 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification."; 703 ++extension_load_errors_observed_; 704 base::MessageLoopForUI::current()->Quit(); 705 break; 706 707 case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED: { 708 LocationBarTesting* location_bar = 709 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 710 VLOG(1) << "Got EXTENSION_PAGE_ACTION_COUNT_CHANGED notification. Number " 711 "of page actions: " << location_bar->PageActionCount(); 712 if (location_bar->PageActionCount() == 713 target_page_action_count_) { 714 target_page_action_count_ = -1; 715 base::MessageLoopForUI::current()->Quit(); 716 } 717 break; 718 } 719 720 case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED: { 721 LocationBarTesting* location_bar = 722 browser()->window()->GetLocationBar()->GetLocationBarForTesting(); 723 VLOG(1) << "Got EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED notification. " 724 "Number of visible page actions: " 725 << location_bar->PageActionVisibleCount(); 726 if (location_bar->PageActionVisibleCount() == 727 target_visible_page_action_count_) { 728 target_visible_page_action_count_ = -1; 729 base::MessageLoopForUI::current()->Quit(); 730 } 731 break; 732 } 733 734 case content::NOTIFICATION_LOAD_STOP: 735 VLOG(1) << "Got LOAD_STOP notification."; 736 base::MessageLoopForUI::current()->Quit(); 737 break; 738 739 default: 740 NOTREACHED(); 741 break; 742 } 743} 744