• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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_service.h"
24 #include "chrome/browser/extensions/extension_util.h"
25 #include "chrome/browser/extensions/unpacked_installer.h"
26 #include "chrome/browser/extensions/updater/extension_cache_fake.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/tabs/tab_strip_model.h"
32 #include "chrome/common/chrome_paths.h"
33 #include "chrome/common/chrome_switches.h"
34 #include "chrome/common/chrome_version_info.h"
35 #include "chrome/test/base/ui_test_utils.h"
36 #include "content/public/browser/navigation_controller.h"
37 #include "content/public/browser/navigation_entry.h"
38 #include "content/public/browser/notification_registrar.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/render_view_host.h"
41 #include "content/public/test/browser_test_utils.h"
42 #include "extensions/browser/extension_host.h"
43 #include "extensions/browser/extension_prefs.h"
44 #include "extensions/browser/extension_system.h"
45 #include "extensions/browser/notification_types.h"
46 #include "extensions/browser/uninstall_reason.h"
47 #include "extensions/common/constants.h"
48 #include "extensions/common/extension_set.h"
49 #include "sync/api/string_ordinal.h"
50 
51 #if defined(OS_CHROMEOS)
52 #include "chromeos/chromeos_switches.h"
53 #endif
54 
55 using extensions::Extension;
56 using extensions::ExtensionCreator;
57 using extensions::FeatureSwitch;
58 using extensions::Manifest;
59 
ExtensionBrowserTest()60 ExtensionBrowserTest::ExtensionBrowserTest()
61     : loaded_(false),
62       installed_(false),
63 #if defined(OS_CHROMEOS)
64       set_chromeos_user_(true),
65 #endif
66       // Default channel is STABLE but override with UNKNOWN so that unlaunched
67       // or incomplete APIs can write tests.
68       current_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN),
69       override_prompt_for_external_extensions_(
70           FeatureSwitch::prompt_for_external_extensions(),
71           false),
72 #if defined(OS_WIN)
73       user_desktop_override_(base::DIR_USER_DESKTOP),
74       common_desktop_override_(base::DIR_COMMON_DESKTOP),
75       user_quick_launch_override_(base::DIR_USER_QUICK_LAUNCH),
76       start_menu_override_(base::DIR_START_MENU),
77       common_start_menu_override_(base::DIR_COMMON_START_MENU),
78 #endif
79       profile_(NULL) {
80   EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
81 }
82 
~ExtensionBrowserTest()83 ExtensionBrowserTest::~ExtensionBrowserTest() {
84 }
85 
profile()86 Profile* ExtensionBrowserTest::profile() {
87   if (!profile_) {
88     if (browser())
89       profile_ = browser()->profile();
90     else
91       profile_ = ProfileManager::GetActiveUserProfile();
92   }
93   return profile_;
94 }
95 
96 // static
GetExtensionByPath(const extensions::ExtensionSet * extensions,const base::FilePath & path)97 const Extension* ExtensionBrowserTest::GetExtensionByPath(
98     const extensions::ExtensionSet* extensions, const base::FilePath& path) {
99   base::FilePath extension_path = base::MakeAbsoluteFilePath(path);
100   EXPECT_TRUE(!extension_path.empty());
101   for (extensions::ExtensionSet::const_iterator iter = extensions->begin();
102        iter != extensions->end(); ++iter) {
103     if ((*iter)->path() == extension_path) {
104       return iter->get();
105     }
106   }
107   return NULL;
108 }
109 
SetUp()110 void ExtensionBrowserTest::SetUp() {
111   test_extension_cache_.reset(new extensions::ExtensionCacheFake());
112   InProcessBrowserTest::SetUp();
113 }
114 
SetUpCommandLine(CommandLine * command_line)115 void ExtensionBrowserTest::SetUpCommandLine(CommandLine* command_line) {
116   PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
117   test_data_dir_ = test_data_dir_.AppendASCII("extensions");
118   observer_.reset(new ExtensionTestNotificationObserver(browser()));
119 
120 #if defined(OS_CHROMEOS)
121   if (set_chromeos_user_) {
122     // This makes sure that we create the Default profile first, with no
123     // ExtensionService and then the real profile with one, as we do when
124     // running on chromeos.
125     command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
126                                     "TestUser@gmail.com");
127     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
128   }
129 #endif
130 }
131 
SetUpOnMainThread()132 void ExtensionBrowserTest::SetUpOnMainThread() {
133   InProcessBrowserTest::SetUpOnMainThread();
134   observer_.reset(new ExtensionTestNotificationObserver(browser()));
135 }
136 
LoadExtension(const base::FilePath & path)137 const Extension* ExtensionBrowserTest::LoadExtension(
138     const base::FilePath& path) {
139   return LoadExtensionWithFlags(path, kFlagEnableFileAccess);
140 }
141 
LoadExtensionIncognito(const base::FilePath & path)142 const Extension* ExtensionBrowserTest::LoadExtensionIncognito(
143     const base::FilePath& path) {
144   return LoadExtensionWithFlags(path,
145                                 kFlagEnableFileAccess | kFlagEnableIncognito);
146 }
147 
LoadExtensionWithFlags(const base::FilePath & path,int flags)148 const Extension* ExtensionBrowserTest::LoadExtensionWithFlags(
149     const base::FilePath& path, int flags) {
150   return LoadExtensionWithInstallParam(path, flags, std::string());
151 }
152 
153 const extensions::Extension*
LoadExtensionWithInstallParam(const base::FilePath & path,int flags,const std::string & install_param)154 ExtensionBrowserTest::LoadExtensionWithInstallParam(
155     const base::FilePath& path,
156     int flags,
157     const std::string& install_param) {
158   ExtensionService* service = extensions::ExtensionSystem::Get(
159       profile())->extension_service();
160   {
161     observer_->Watch(extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
162                      content::NotificationService::AllSources());
163 
164     scoped_refptr<extensions::UnpackedInstaller> installer(
165         extensions::UnpackedInstaller::Create(service));
166     installer->set_prompt_for_plugins(false);
167     installer->set_require_modern_manifest_version(
168         (flags & kFlagAllowOldManifestVersions) == 0);
169     installer->Load(path);
170 
171     observer_->Wait();
172   }
173 
174   // Find the loaded extension by its path. See crbug.com/59531 for why
175   // we cannot just use last_loaded_extension_id().
176   const Extension* extension = GetExtensionByPath(service->extensions(), path);
177   if (!extension)
178     return NULL;
179 
180   if (!(flags & kFlagIgnoreManifestWarnings)) {
181     const std::vector<extensions::InstallWarning>& install_warnings =
182         extension->install_warnings();
183     if (!install_warnings.empty()) {
184       std::string install_warnings_message = base::StringPrintf(
185           "Unexpected warnings when loading test extension %s:\n",
186           path.AsUTF8Unsafe().c_str());
187 
188       for (std::vector<extensions::InstallWarning>::const_iterator it =
189           install_warnings.begin(); it != install_warnings.end(); ++it) {
190         install_warnings_message += "  " + it->message + "\n";
191       }
192 
193       EXPECT_EQ(0u, extension->install_warnings().size())
194           << install_warnings_message;
195       return NULL;
196     }
197   }
198 
199   const std::string extension_id = extension->id();
200 
201   if (!install_param.empty()) {
202     extensions::ExtensionPrefs::Get(profile())
203         ->SetInstallParam(extension_id, install_param);
204     // Re-enable the extension if needed.
205     if (service->extensions()->Contains(extension_id)) {
206       content::WindowedNotificationObserver load_signal(
207           extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
208           content::Source<Profile>(profile()));
209       // Reload the extension so that the
210       // NOTIFICATION_EXTENSION_LOADED_DEPRECATED
211       // observers may access |install_param|.
212       service->ReloadExtension(extension_id);
213       load_signal.Wait();
214       extension = service->GetExtensionById(extension_id, false);
215       CHECK(extension) << extension_id << " not found after reloading.";
216     }
217   }
218 
219   // Toggling incognito or file access will reload the extension, so wait for
220   // the reload and grab the new extension instance. The default state is
221   // incognito disabled and file access enabled, so we don't wait in those
222   // cases.
223   {
224     content::WindowedNotificationObserver load_signal(
225         extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
226         content::Source<Profile>(profile()));
227     CHECK(!extensions::util::IsIncognitoEnabled(extension_id, profile()));
228 
229     if (flags & kFlagEnableIncognito) {
230       extensions::util::SetIsIncognitoEnabled(extension_id, profile(), true);
231       load_signal.Wait();
232       extension = service->GetExtensionById(extension_id, false);
233       CHECK(extension) << extension_id << " not found after reloading.";
234     }
235   }
236 
237   {
238     content::WindowedNotificationObserver load_signal(
239         extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
240         content::Source<Profile>(profile()));
241     CHECK(extensions::util::AllowFileAccess(extension_id, profile()));
242     if (!(flags & kFlagEnableFileAccess)) {
243       extensions::util::SetAllowFileAccess(extension_id, profile(), false);
244       load_signal.Wait();
245       extension = service->GetExtensionById(extension_id, false);
246       CHECK(extension) << extension_id << " not found after reloading.";
247     }
248   }
249 
250   if (!observer_->WaitForExtensionViewsToLoad())
251     return NULL;
252 
253   return extension;
254 }
255 
LoadExtensionAsComponentWithManifest(const base::FilePath & path,const base::FilePath::CharType * manifest_relative_path)256 const Extension* ExtensionBrowserTest::LoadExtensionAsComponentWithManifest(
257     const base::FilePath& path,
258     const base::FilePath::CharType* manifest_relative_path) {
259   ExtensionService* service = extensions::ExtensionSystem::Get(
260       profile())->extension_service();
261 
262   std::string manifest;
263   if (!base::ReadFileToString(path.Append(manifest_relative_path), &manifest)) {
264     return NULL;
265   }
266 
267   std::string extension_id = service->component_loader()->Add(manifest, path);
268   const Extension* extension = service->extensions()->GetByID(extension_id);
269   if (!extension)
270     return NULL;
271   observer_->set_last_loaded_extension_id(extension->id());
272   return extension;
273 }
274 
LoadExtensionAsComponent(const base::FilePath & path)275 const Extension* ExtensionBrowserTest::LoadExtensionAsComponent(
276     const base::FilePath& path) {
277   return LoadExtensionAsComponentWithManifest(path,
278                                               extensions::kManifestFilename);
279 }
280 
PackExtension(const base::FilePath & dir_path)281 base::FilePath ExtensionBrowserTest::PackExtension(
282     const base::FilePath& dir_path) {
283   base::FilePath crx_path = temp_dir_.path().AppendASCII("temp.crx");
284   if (!base::DeleteFile(crx_path, false)) {
285     ADD_FAILURE() << "Failed to delete crx: " << crx_path.value();
286     return base::FilePath();
287   }
288 
289   // Look for PEM files with the same name as the directory.
290   base::FilePath pem_path =
291       dir_path.ReplaceExtension(FILE_PATH_LITERAL(".pem"));
292   base::FilePath pem_path_out;
293 
294   if (!base::PathExists(pem_path)) {
295     pem_path = base::FilePath();
296     pem_path_out = crx_path.DirName().AppendASCII("temp.pem");
297     if (!base::DeleteFile(pem_path_out, false)) {
298       ADD_FAILURE() << "Failed to delete pem: " << pem_path_out.value();
299       return base::FilePath();
300     }
301   }
302 
303   return PackExtensionWithOptions(dir_path, crx_path, pem_path, pem_path_out);
304 }
305 
PackExtensionWithOptions(const base::FilePath & dir_path,const base::FilePath & crx_path,const base::FilePath & pem_path,const base::FilePath & pem_out_path)306 base::FilePath ExtensionBrowserTest::PackExtensionWithOptions(
307     const base::FilePath& dir_path,
308     const base::FilePath& crx_path,
309     const base::FilePath& pem_path,
310     const base::FilePath& pem_out_path) {
311   if (!base::PathExists(dir_path)) {
312     ADD_FAILURE() << "Extension dir not found: " << dir_path.value();
313     return base::FilePath();
314   }
315 
316   if (!base::PathExists(pem_path) && pem_out_path.empty()) {
317     ADD_FAILURE() << "Must specify a PEM file or PEM output path";
318     return base::FilePath();
319   }
320 
321   scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
322   if (!creator->Run(dir_path,
323                     crx_path,
324                     pem_path,
325                     pem_out_path,
326                     ExtensionCreator::kOverwriteCRX)) {
327     ADD_FAILURE() << "ExtensionCreator::Run() failed: "
328                   << creator->error_message();
329     return base::FilePath();
330   }
331 
332   if (!base::PathExists(crx_path)) {
333     ADD_FAILURE() << crx_path.value() << " was not created.";
334     return base::FilePath();
335   }
336   return crx_path;
337 }
338 
339 // This class is used to simulate an installation abort by the user.
340 class MockAbortExtensionInstallPrompt : public ExtensionInstallPrompt {
341  public:
MockAbortExtensionInstallPrompt()342   MockAbortExtensionInstallPrompt() : ExtensionInstallPrompt(NULL) {
343   }
344 
345   // Simulate a user abort on an extension installation.
ConfirmInstall(Delegate * delegate,const Extension * extension,const ShowDialogCallback & show_dialog_callback)346   virtual void ConfirmInstall(
347       Delegate* delegate,
348       const Extension* extension,
349       const ShowDialogCallback& show_dialog_callback) OVERRIDE {
350     delegate->InstallUIAbort(true);
351     base::MessageLoopForUI::current()->Quit();
352   }
353 
OnInstallSuccess(const Extension * extension,SkBitmap * icon)354   virtual void OnInstallSuccess(const Extension* extension,
355                                 SkBitmap* icon) OVERRIDE {}
356 
OnInstallFailure(const extensions::CrxInstallerError & error)357   virtual void OnInstallFailure(
358       const extensions::CrxInstallerError& error) OVERRIDE {}
359 };
360 
361 class MockAutoConfirmExtensionInstallPrompt : public ExtensionInstallPrompt {
362  public:
MockAutoConfirmExtensionInstallPrompt(content::WebContents * web_contents)363   explicit MockAutoConfirmExtensionInstallPrompt(
364       content::WebContents* web_contents)
365     : ExtensionInstallPrompt(web_contents) {}
366 
367   // Proceed without confirmation prompt.
ConfirmInstall(Delegate * delegate,const Extension * extension,const ShowDialogCallback & show_dialog_callback)368   virtual void ConfirmInstall(
369       Delegate* delegate,
370       const Extension* extension,
371       const ShowDialogCallback& show_dialog_callback) OVERRIDE {
372     delegate->InstallUIProceed();
373   }
374 };
375 
UpdateExtensionWaitForIdle(const std::string & id,const base::FilePath & path,int expected_change)376 const Extension* ExtensionBrowserTest::UpdateExtensionWaitForIdle(
377     const std::string& id,
378     const base::FilePath& path,
379     int expected_change) {
380   return InstallOrUpdateExtension(id,
381                                   path,
382                                   INSTALL_UI_TYPE_NONE,
383                                   expected_change,
384                                   Manifest::INTERNAL,
385                                   browser(),
386                                   Extension::NO_FLAGS,
387                                   false,
388                                   false);
389 }
390 
InstallExtensionFromWebstore(const base::FilePath & path,int expected_change)391 const Extension* ExtensionBrowserTest::InstallExtensionFromWebstore(
392     const base::FilePath& path,
393     int expected_change) {
394   return InstallOrUpdateExtension(std::string(),
395                                   path,
396                                   INSTALL_UI_TYPE_NONE,
397                                   expected_change,
398                                   Manifest::INTERNAL,
399                                   browser(),
400                                   Extension::FROM_WEBSTORE,
401                                   true,
402                                   false);
403 }
404 
InstallOrUpdateExtension(const std::string & id,const base::FilePath & path,InstallUIType ui_type,int expected_change)405 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
406     const std::string& id,
407     const base::FilePath& path,
408     InstallUIType ui_type,
409     int expected_change) {
410   return InstallOrUpdateExtension(id,
411                                   path,
412                                   ui_type,
413                                   expected_change,
414                                   Manifest::INTERNAL,
415                                   browser(),
416                                   Extension::NO_FLAGS,
417                                   true,
418                                   false);
419 }
420 
InstallOrUpdateExtension(const std::string & id,const base::FilePath & path,InstallUIType ui_type,int expected_change,Browser * browser,Extension::InitFromValueFlags creation_flags)421 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
422     const std::string& id,
423     const base::FilePath& path,
424     InstallUIType ui_type,
425     int expected_change,
426     Browser* browser,
427     Extension::InitFromValueFlags creation_flags) {
428   return InstallOrUpdateExtension(id,
429                                   path,
430                                   ui_type,
431                                   expected_change,
432                                   Manifest::INTERNAL,
433                                   browser,
434                                   creation_flags,
435                                   true,
436                                   false);
437 }
438 
InstallOrUpdateExtension(const std::string & id,const base::FilePath & path,InstallUIType ui_type,int expected_change,Manifest::Location install_source)439 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
440     const std::string& id,
441     const base::FilePath& path,
442     InstallUIType ui_type,
443     int expected_change,
444     Manifest::Location install_source) {
445   return InstallOrUpdateExtension(id,
446                                   path,
447                                   ui_type,
448                                   expected_change,
449                                   install_source,
450                                   browser(),
451                                   Extension::NO_FLAGS,
452                                   true,
453                                   false);
454 }
455 
InstallOrUpdateExtension(const std::string & id,const base::FilePath & path,InstallUIType ui_type,int expected_change,Manifest::Location install_source,Browser * browser,Extension::InitFromValueFlags creation_flags,bool install_immediately,bool is_ephemeral)456 const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
457     const std::string& id,
458     const base::FilePath& path,
459     InstallUIType ui_type,
460     int expected_change,
461     Manifest::Location install_source,
462     Browser* browser,
463     Extension::InitFromValueFlags creation_flags,
464     bool install_immediately,
465     bool is_ephemeral) {
466   ExtensionService* service =
467       extensions::ExtensionSystem::Get(profile())->extension_service();
468   service->set_show_extensions_prompts(false);
469   size_t num_before = service->extensions()->size();
470 
471   {
472     scoped_ptr<ExtensionInstallPrompt> install_ui;
473     if (ui_type == INSTALL_UI_TYPE_CANCEL) {
474       install_ui.reset(new MockAbortExtensionInstallPrompt());
475     } else if (ui_type == INSTALL_UI_TYPE_NORMAL) {
476       install_ui.reset(new ExtensionInstallPrompt(
477           browser->tab_strip_model()->GetActiveWebContents()));
478     } else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) {
479       install_ui.reset(new MockAutoConfirmExtensionInstallPrompt(
480           browser->tab_strip_model()->GetActiveWebContents()));
481     }
482 
483     // TODO(tessamac): Update callers to always pass an unpacked extension
484     //                 and then always pack the extension here.
485     base::FilePath crx_path = path;
486     if (crx_path.Extension() != FILE_PATH_LITERAL(".crx")) {
487       crx_path = PackExtension(path);
488     }
489     if (crx_path.empty())
490       return NULL;
491 
492     scoped_refptr<extensions::CrxInstaller> installer(
493         extensions::CrxInstaller::Create(service, install_ui.Pass()));
494     installer->set_expected_id(id);
495     installer->set_creation_flags(creation_flags);
496     installer->set_install_source(install_source);
497     installer->set_install_immediately(install_immediately);
498     installer->set_is_ephemeral(is_ephemeral);
499     if (!installer->is_gallery_install()) {
500       installer->set_off_store_install_allow_reason(
501           extensions::CrxInstaller::OffStoreInstallAllowedInTest);
502     }
503 
504     observer_->Watch(
505         extensions::NOTIFICATION_CRX_INSTALLER_DONE,
506         content::Source<extensions::CrxInstaller>(installer.get()));
507 
508     installer->InstallCrx(crx_path);
509 
510     observer_->Wait();
511   }
512 
513   size_t num_after = service->extensions()->size();
514   EXPECT_EQ(num_before + expected_change, num_after);
515   if (num_before + expected_change != num_after) {
516     VLOG(1) << "Num extensions before: " << base::IntToString(num_before)
517             << " num after: " << base::IntToString(num_after)
518             << " Installed extensions follow:";
519 
520     for (extensions::ExtensionSet::const_iterator it =
521              service->extensions()->begin();
522          it != service->extensions()->end(); ++it)
523       VLOG(1) << "  " << (*it)->id();
524 
525     VLOG(1) << "Errors follow:";
526     const std::vector<base::string16>* errors =
527         ExtensionErrorReporter::GetInstance()->GetErrors();
528     for (std::vector<base::string16>::const_iterator iter = errors->begin();
529          iter != errors->end(); ++iter)
530       VLOG(1) << *iter;
531 
532     return NULL;
533   }
534 
535   if (!observer_->WaitForExtensionViewsToLoad())
536     return NULL;
537   return service->GetExtensionById(last_loaded_extension_id(), false);
538 }
539 
ReloadExtension(const std::string extension_id)540 void ExtensionBrowserTest::ReloadExtension(const std::string extension_id) {
541   observer_->Watch(extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
542                    content::NotificationService::AllSources());
543 
544   ExtensionService* service =
545       extensions::ExtensionSystem::Get(profile())->extension_service();
546   service->ReloadExtension(extension_id);
547 
548   observer_->Wait();
549   observer_->WaitForExtensionViewsToLoad();
550 }
551 
UnloadExtension(const std::string & extension_id)552 void ExtensionBrowserTest::UnloadExtension(const std::string& extension_id) {
553   ExtensionService* service = extensions::ExtensionSystem::Get(
554       profile())->extension_service();
555   service->UnloadExtension(extension_id,
556                            extensions::UnloadedExtensionInfo::REASON_DISABLE);
557 }
558 
UninstallExtension(const std::string & extension_id)559 void ExtensionBrowserTest::UninstallExtension(const std::string& extension_id) {
560   ExtensionService* service = extensions::ExtensionSystem::Get(
561       profile())->extension_service();
562   service->UninstallExtension(extension_id,
563                               extensions::UNINSTALL_REASON_FOR_TESTING,
564                               base::Bind(&base::DoNothing),
565                               NULL);
566 }
567 
DisableExtension(const std::string & extension_id)568 void ExtensionBrowserTest::DisableExtension(const std::string& extension_id) {
569   ExtensionService* service = extensions::ExtensionSystem::Get(
570       profile())->extension_service();
571   service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
572 }
573 
EnableExtension(const std::string & extension_id)574 void ExtensionBrowserTest::EnableExtension(const std::string& extension_id) {
575   ExtensionService* service = extensions::ExtensionSystem::Get(
576       profile())->extension_service();
577   service->EnableExtension(extension_id);
578 }
579 
OpenWindow(content::WebContents * contents,const GURL & url,bool newtab_process_should_equal_opener,content::WebContents ** newtab_result)580 void ExtensionBrowserTest::OpenWindow(content::WebContents* contents,
581                                       const GURL& url,
582                                       bool newtab_process_should_equal_opener,
583                                       content::WebContents** newtab_result) {
584   content::WindowedNotificationObserver windowed_observer(
585       content::NOTIFICATION_LOAD_STOP,
586       content::NotificationService::AllSources());
587   ASSERT_TRUE(content::ExecuteScript(contents,
588                                      "window.open('" + url.spec() + "');"));
589 
590   // The above window.open call is not user-initiated, so it will create
591   // a popup window instead of a new tab in current window.
592   // The stop notification will come from the new tab.
593   windowed_observer.Wait();
594   content::NavigationController* controller =
595       content::Source<content::NavigationController>(
596           windowed_observer.source()).ptr();
597   content::WebContents* newtab = controller->GetWebContents();
598   ASSERT_TRUE(newtab);
599   EXPECT_EQ(url, controller->GetLastCommittedEntry()->GetURL());
600   if (newtab_process_should_equal_opener)
601     EXPECT_EQ(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
602   else
603     EXPECT_NE(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
604 
605   if (newtab_result)
606     *newtab_result = newtab;
607 }
608 
NavigateInRenderer(content::WebContents * contents,const GURL & url)609 void ExtensionBrowserTest::NavigateInRenderer(content::WebContents* contents,
610                                               const GURL& url) {
611   bool result = false;
612   content::WindowedNotificationObserver windowed_observer(
613       content::NOTIFICATION_LOAD_STOP,
614       content::NotificationService::AllSources());
615   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
616       contents,
617       "window.addEventListener('unload', function() {"
618       "    window.domAutomationController.send(true);"
619       "}, false);"
620       "window.location = '" + url.spec() + "';",
621       &result));
622   ASSERT_TRUE(result);
623   windowed_observer.Wait();
624   EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL());
625 }
626 
FindHostWithPath(extensions::ProcessManager * manager,const std::string & path,int expected_hosts)627 extensions::ExtensionHost* ExtensionBrowserTest::FindHostWithPath(
628     extensions::ProcessManager* manager,
629     const std::string& path,
630     int expected_hosts) {
631   extensions::ExtensionHost* host = NULL;
632   int num_hosts = 0;
633   extensions::ProcessManager::ExtensionHostSet background_hosts =
634       manager->background_hosts();
635   for (extensions::ProcessManager::const_iterator iter =
636            background_hosts.begin();
637        iter != background_hosts.end();
638        ++iter) {
639     if ((*iter)->GetURL().path() == path) {
640       EXPECT_FALSE(host);
641       host = *iter;
642     }
643     num_hosts++;
644   }
645   EXPECT_EQ(expected_hosts, num_hosts);
646   return host;
647 }
648 
ExecuteScriptInBackgroundPage(const std::string & extension_id,const std::string & script)649 std::string ExtensionBrowserTest::ExecuteScriptInBackgroundPage(
650     const std::string& extension_id,
651     const std::string& script) {
652   return extensions::browsertest_util::ExecuteScriptInBackgroundPage(
653       profile(), extension_id, script);
654 }
655 
ExecuteScriptInBackgroundPageNoWait(const std::string & extension_id,const std::string & script)656 bool ExtensionBrowserTest::ExecuteScriptInBackgroundPageNoWait(
657     const std::string& extension_id,
658     const std::string& script) {
659   return extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait(
660       profile(), extension_id, script);
661 }
662