blob: 7c772f413cbab9ec48800632232d7940b0e80271 [file] [log] [blame]
[email protected]863e6472012-01-24 19:33:581// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]3f58d8552009-08-14 23:59:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]17c4f3c2009-07-04 16:36:255#include "chrome/browser/extensions/extension_browsertest.h"
[email protected]81e63782009-02-27 19:35:096
[email protected]3f58d8552009-08-14 23:59:377#include <vector>
8
[email protected]17c4f3c2009-07-04 16:36:259#include "base/command_line.h"
10#include "base/file_path.h"
[email protected]59e03362011-01-21 21:24:0811#include "base/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2312#include "base/files/scoped_temp_dir.h"
[email protected]17c4f3c2009-07-04 16:36:2513#include "base/path_service.h"
[email protected]528c56d2010-07-30 19:28:4414#include "base/string_number_conversions.h"
[email protected]3d43eef2012-10-09 23:17:5615#include "base/stringprintf.h"
[email protected]19da16a92012-05-23 17:11:2916#include "base/utf_string_conversions.h"
[email protected]178f8512012-02-09 01:49:3617#include "chrome/browser/extensions/app_shortcut_manager.h"
[email protected]d8c8f25f2011-11-02 18:18:0118#include "chrome/browser/extensions/component_loader.h"
[email protected]c70013bd2010-01-20 21:50:0319#include "chrome/browser/extensions/crx_installer.h"
[email protected]59e03362011-01-21 21:24:0820#include "chrome/browser/extensions/extension_creator.h"
[email protected]14a000d2010-04-29 21:44:2421#include "chrome/browser/extensions/extension_error_reporter.h"
[email protected]fad73672012-06-15 23:26:0622#include "chrome/browser/extensions/extension_host.h"
[email protected]c82da8c42012-06-08 19:49:1123#include "chrome/browser/extensions/extension_install_prompt.h"
[email protected]eaa7dd182010-12-14 11:09:0024#include "chrome/browser/extensions/extension_service.h"
[email protected]be93bba02012-10-24 16:44:0325#include "chrome/browser/extensions/extension_system.h"
[email protected]d8c8f25f2011-11-02 18:18:0126#include "chrome/browser/extensions/unpacked_installer.h"
[email protected]8ecad5e2010-12-02 21:18:3327#include "chrome/browser/profiles/profile.h"
[email protected]7b5dc002010-11-16 23:08:1028#include "chrome/browser/ui/browser.h"
[email protected]00070c732011-04-09 15:31:3329#include "chrome/browser/ui/browser_window.h"
[email protected]1b1989f52012-12-03 08:33:5430#include "chrome/browser/ui/extensions/native_app_window.h"
[email protected]99bfb2042012-12-01 07:16:4531#include "chrome/browser/ui/extensions/shell_window.h"
[email protected]6a3ec2312010-12-02 19:30:1932#include "chrome/browser/ui/omnibox/location_bar.h"
[email protected]91e51d612012-10-21 23:03:0533#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]432115822011-07-10 15:52:2734#include "chrome/common/chrome_notification_types.h"
[email protected]17c4f3c2009-07-04 16:36:2535#include "chrome/common/chrome_paths.h"
[email protected]7b5dc002010-11-16 23:08:1036#include "chrome/common/chrome_switches.h"
[email protected]d69d7b172012-08-09 04:17:2637#include "chrome/common/chrome_version_info.h"
[email protected]af44e7fb2011-07-29 18:32:3238#include "chrome/test/base/ui_test_utils.h"
[email protected]19da16a92012-05-23 17:11:2939#include "content/public/browser/navigation_controller.h"
40#include "content/public/browser/navigation_entry.h"
[email protected]6c2381d2011-10-19 02:52:5341#include "content/public/browser/notification_registrar.h"
[email protected]ad50def52011-10-19 23:17:0742#include "content/public/browser/notification_service.h"
[email protected]d1fe1352012-04-26 00:47:3243#include "content/public/browser/render_view_host.h"
[email protected]7d478cb2012-07-24 17:19:4244#include "content/public/test/browser_test_utils.h"
[email protected]36b643212012-09-07 12:53:0045#include "sync/api/string_ordinal.h"
[email protected]81e63782009-02-27 19:35:0946
[email protected]1c321ee2012-05-21 03:02:3447using extensions::Extension;
[email protected]6d777492012-07-11 17:33:4348using extensions::ExtensionCreator;
[email protected]00b5d0a52012-10-30 13:13:5349using extensions::FeatureSwitch;
[email protected]1c321ee2012-05-21 03:02:3450
[email protected]d818e07f2010-02-10 13:10:0351ExtensionBrowserTest::ExtensionBrowserTest()
[email protected]9931fbfc2010-07-23 09:15:5152 : loaded_(false),
53 installed_(false),
54 extension_installs_observed_(0),
[email protected]bbcde9102012-03-25 22:40:4955 extension_load_errors_observed_(0),
[email protected]9931fbfc2010-07-23 09:15:5156 target_page_action_count_(-1),
[email protected]2b5fdc32012-08-14 03:55:4357 target_visible_page_action_count_(-1),
[email protected]612a1cb12012-10-17 13:18:0358 current_channel_(chrome::VersionInfo::CHANNEL_DEV),
59 override_prompt_for_external_extensions_(
[email protected]00b5d0a52012-10-30 13:13:5360 FeatureSwitch::prompt_for_external_extensions(), false),
61 override_sideload_wipeout_(
62 FeatureSwitch::sideload_wipeout(), false) {
[email protected]3a305db2011-04-12 13:40:5363 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]178f8512012-02-09 01:49:3664}
65
[email protected]e66ba952012-10-09 09:59:4466ExtensionBrowserTest::~ExtensionBrowserTest() {}
[email protected]d818e07f2010-02-10 13:10:0367
[email protected]17c4f3c2009-07-04 16:36:2568void ExtensionBrowserTest::SetUpCommandLine(CommandLine* command_line) {
[email protected]17c4f3c2009-07-04 16:36:2569 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
70 test_data_dir_ = test_data_dir_.AppendASCII("extensions");
[email protected]856c8d72009-11-24 16:33:1271
[email protected]1172ba72010-05-21 22:21:1172#if defined(OS_CHROMEOS)
73 // This makes sure that we create the Default profile first, with no
[email protected]eaa7dd182010-12-14 11:09:0074 // ExtensionService and then the real profile with one, as we do when
[email protected]1172ba72010-05-21 22:21:1175 // running on chromeos.
[email protected]05076ba22010-07-30 05:59:5776 command_line->AppendSwitchASCII(switches::kLoginUser,
77 "[email protected]");
78 command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
[email protected]1172ba72010-05-21 22:21:1179#endif
[email protected]81e63782009-02-27 19:35:0980}
[email protected]653c9ea2009-05-06 16:58:5681
[email protected]24e04292012-08-10 21:08:0882const Extension* ExtensionBrowserTest::LoadExtensionWithFlags(
83 const FilePath& path, int flags) {
[email protected]06bdd2b2012-11-30 18:47:1384 ExtensionService* service = extensions::ExtensionSystem::Get(
85 browser()->profile())->extension_service();
[email protected]0c6da502009-08-14 22:32:3986 {
[email protected]6c2381d2011-10-19 02:52:5387 content::NotificationRegistrar registrar;
[email protected]432115822011-07-10 15:52:2788 registrar.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]ad50def52011-10-19 23:17:0789 content::NotificationService::AllSources());
[email protected]d8c8f25f2011-11-02 18:18:0190 scoped_refptr<extensions::UnpackedInstaller> installer(
91 extensions::UnpackedInstaller::Create(service));
92 installer->set_prompt_for_plugins(false);
[email protected]b7462f32012-09-02 15:18:1293 installer->set_require_modern_manifest_version(
94 (flags & kFlagAllowOldManifestVersions) == 0);
[email protected]d8c8f25f2011-11-02 18:18:0195 installer->Load(path);
[email protected]729eb632012-07-26 04:45:2696 content::RunMessageLoop();
[email protected]0c6da502009-08-14 22:32:3997 }
[email protected]19f358e2010-10-28 20:22:5098
[email protected]84df8332011-12-06 18:22:4699 // Find the loaded extension by its path. See crbug.com/59531 for why
100 // we cannot just use last_loaded_extension_id_.
[email protected]19f358e2010-10-28 20:22:50101 FilePath extension_path = path;
102 file_util::AbsolutePath(&extension_path);
[email protected]9adb9692010-10-29 23:14:02103 const Extension* extension = NULL;
[email protected]84df8332011-12-06 18:22:46104 for (ExtensionSet::const_iterator iter = service->extensions()->begin();
105 iter != service->extensions()->end(); ++iter) {
[email protected]19f358e2010-10-28 20:22:50106 if ((*iter)->path() == extension_path) {
107 extension = *iter;
108 break;
109 }
110 }
111 if (!extension)
[email protected]a964e112011-04-14 21:52:51112 return NULL;
[email protected]653c9ea2009-05-06 16:58:56113
[email protected]24e04292012-08-10 21:08:08114 if (!(flags & kFlagIgnoreManifestWarnings)) {
115 const Extension::InstallWarningVector& install_warnings =
116 extension->install_warnings();
117 if (!install_warnings.empty()) {
118 std::string install_warnings_message = StringPrintf(
119 "Unexpected warnings when loading test extension %s:\n",
120 path.AsUTF8Unsafe().c_str());
121
122 for (Extension::InstallWarningVector::const_iterator it =
123 install_warnings.begin(); it != install_warnings.end(); ++it) {
124 install_warnings_message += " " + it->message + "\n";
125 }
126
127 EXPECT_TRUE(extension->install_warnings().empty()) <<
128 install_warnings_message;
129 return NULL;
130 }
131 }
132
[email protected]d10f4602011-06-16 15:44:50133 const std::string extension_id = extension->id();
134
[email protected]c7c401d2011-03-16 10:20:01135 // The call to OnExtensionInstalled ensures the other extension prefs
136 // are set up with the defaults.
137 service->extension_prefs()->OnExtensionInstalled(
[email protected]26367b62012-10-04 23:03:32138 extension, Extension::ENABLED,
[email protected]36b643212012-09-07 12:53:00139 syncer::StringOrdinal::CreateInitialOrdinal());
[email protected]d10f4602011-06-16 15:44:50140
[email protected]c1bf62c72011-07-15 22:18:42141 // Toggling incognito or file access will reload the extension, so wait for
142 // the reload and grab the new extension instance. The default state is
143 // incognito disabled and file access enabled, so we don't wait in those
144 // cases.
145 {
[email protected]a7fe9112012-07-20 02:34:45146 content::WindowedNotificationObserver load_signal(
[email protected]c1bf62c72011-07-15 22:18:42147 chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]6c2381d2011-10-19 02:52:53148 content::Source<Profile>(browser()->profile()));
[email protected]c1bf62c72011-07-15 22:18:42149 CHECK(!service->IsIncognitoEnabled(extension_id));
[email protected]db7331a2010-02-25 22:10:50150
[email protected]24e04292012-08-10 21:08:08151 if (flags & kFlagEnableIncognito) {
152 service->SetIsIncognitoEnabled(extension_id, true);
[email protected]c1bf62c72011-07-15 22:18:42153 load_signal.Wait();
154 extension = service->GetExtensionById(extension_id, false);
155 CHECK(extension) << extension_id << " not found after reloading.";
156 }
157 }
158
159 {
[email protected]a7fe9112012-07-20 02:34:45160 content::WindowedNotificationObserver load_signal(
[email protected]c1bf62c72011-07-15 22:18:42161 chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]6c2381d2011-10-19 02:52:53162 content::Source<Profile>(browser()->profile()));
[email protected]cdfca9702011-08-08 16:07:01163 CHECK(service->AllowFileAccess(extension));
[email protected]24e04292012-08-10 21:08:08164 if (!(flags & kFlagEnableFileAccess)) {
165 service->SetAllowFileAccess(extension, false);
[email protected]c1bf62c72011-07-15 22:18:42166 load_signal.Wait();
167 extension = service->GetExtensionById(extension_id, false);
168 CHECK(extension) << extension_id << " not found after reloading.";
169 }
[email protected]d10f4602011-06-16 15:44:50170 }
171
[email protected]d1fe1352012-04-26 00:47:32172 if (!WaitForExtensionViewsToLoad())
[email protected]a964e112011-04-14 21:52:51173 return NULL;
174
175 return extension;
[email protected]653c9ea2009-05-06 16:58:56176}
[email protected]1bd54132009-06-11 00:05:34177
[email protected]a964e112011-04-14 21:52:51178const Extension* ExtensionBrowserTest::LoadExtension(const FilePath& path) {
[email protected]24e04292012-08-10 21:08:08179 return LoadExtensionWithFlags(path, kFlagEnableFileAccess);
[email protected]db7331a2010-02-25 22:10:50180}
181
[email protected]a964e112011-04-14 21:52:51182const Extension* ExtensionBrowserTest::LoadExtensionIncognito(
183 const FilePath& path) {
[email protected]24e04292012-08-10 21:08:08184 return LoadExtensionWithFlags(path,
185 kFlagEnableFileAccess | kFlagEnableIncognito);
[email protected]db7331a2010-02-25 22:10:50186}
187
[email protected]863e6472012-01-24 19:33:58188const Extension* ExtensionBrowserTest::LoadExtensionAsComponent(
189 const FilePath& path) {
[email protected]06bdd2b2012-11-30 18:47:13190 ExtensionService* service = extensions::ExtensionSystem::Get(
191 browser()->profile())->extension_service();
[email protected]61b55b62011-03-24 09:03:10192
193 std::string manifest;
194 if (!file_util::ReadFileToString(path.Append(Extension::kManifestFilename),
195 &manifest))
[email protected]863e6472012-01-24 19:33:58196 return NULL;
[email protected]61b55b62011-03-24 09:03:10197
[email protected]ee837d32012-10-02 22:25:49198 std::string extension_id = service->component_loader()->Add(manifest, path);
199 const Extension* extension = service->extensions()->GetByID(extension_id);
[email protected]863e6472012-01-24 19:33:58200 if (!extension)
201 return NULL;
202 last_loaded_extension_id_ = extension->id();
203 return extension;
[email protected]61b55b62011-03-24 09:03:10204}
205
[email protected]59e03362011-01-21 21:24:08206FilePath ExtensionBrowserTest::PackExtension(const FilePath& dir_path) {
[email protected]3a305db2011-04-12 13:40:53207 FilePath crx_path = temp_dir_.path().AppendASCII("temp.crx");
[email protected]59e03362011-01-21 21:24:08208 if (!file_util::Delete(crx_path, false)) {
209 ADD_FAILURE() << "Failed to delete crx: " << crx_path.value();
210 return FilePath();
211 }
212
[email protected]21a5ad62012-04-03 04:48:45213 // Look for PEM files with the same name as the directory.
214 FilePath pem_path = dir_path.ReplaceExtension(FILE_PATH_LITERAL(".pem"));
215 FilePath pem_path_out;
216
217 if (!file_util::PathExists(pem_path)) {
218 pem_path = FilePath();
219 pem_path_out = crx_path.DirName().AppendASCII("temp.pem");
220 if (!file_util::Delete(pem_path_out, false)) {
221 ADD_FAILURE() << "Failed to delete pem: " << pem_path_out.value();
222 return FilePath();
223 }
[email protected]59e03362011-01-21 21:24:08224 }
225
[email protected]21a5ad62012-04-03 04:48:45226 return PackExtensionWithOptions(dir_path, crx_path, pem_path, pem_path_out);
[email protected]f66a50a2011-11-02 23:53:46227}
228
229FilePath ExtensionBrowserTest::PackExtensionWithOptions(
230 const FilePath& dir_path,
231 const FilePath& crx_path,
232 const FilePath& pem_path,
233 const FilePath& pem_out_path) {
[email protected]19a906b2011-02-07 20:56:37234 if (!file_util::PathExists(dir_path)) {
235 ADD_FAILURE() << "Extension dir not found: " << dir_path.value();
236 return FilePath();
237 }
238
[email protected]f66a50a2011-11-02 23:53:46239 if (!file_util::PathExists(pem_path) && pem_out_path.empty()) {
240 ADD_FAILURE() << "Must specify a PEM file or PEM output path";
241 return FilePath();
242 }
243
[email protected]59e03362011-01-21 21:24:08244 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
245 if (!creator->Run(dir_path,
246 crx_path,
[email protected]f66a50a2011-11-02 23:53:46247 pem_path,
[email protected]93d973a2012-01-08 07:38:26248 pem_out_path,
249 ExtensionCreator::kOverwriteCRX)) {
[email protected]fc38935a2011-10-31 23:53:28250 ADD_FAILURE() << "ExtensionCreator::Run() failed: "
251 << creator->error_message();
[email protected]59e03362011-01-21 21:24:08252 return FilePath();
253 }
254
255 if (!file_util::PathExists(crx_path)) {
256 ADD_FAILURE() << crx_path.value() << " was not created.";
257 return FilePath();
258 }
259 return crx_path;
260}
261
[email protected]c70013bd2010-01-20 21:50:03262// This class is used to simulate an installation abort by the user.
[email protected]c82da8c42012-06-08 19:49:11263class MockAbortExtensionInstallPrompt : public ExtensionInstallPrompt {
[email protected]c70013bd2010-01-20 21:50:03264 public:
[email protected]91e51d612012-10-21 23:03:05265 MockAbortExtensionInstallPrompt() : ExtensionInstallPrompt(NULL) {
[email protected]619f86182012-07-03 21:30:18266 }
[email protected]c70013bd2010-01-20 21:50:03267
268 // Simulate a user abort on an extension installation.
[email protected]af6efb22012-10-12 02:23:05269 virtual void ConfirmInstall(Delegate* delegate,
270 const Extension* extension,
271 const ShowDialogCallback& show_dialog_callback) {
[email protected]d828fac2011-06-28 05:43:04272 delegate->InstallUIAbort(true);
[email protected]c70013bd2010-01-20 21:50:03273 MessageLoopForUI::current()->Quit();
274 }
275
[email protected]c8f00432011-02-22 01:30:26276 virtual void OnInstallSuccess(const Extension* extension, SkBitmap* icon) {}
[email protected]c70013bd2010-01-20 21:50:03277
[email protected]bf3d9df2012-07-24 23:20:27278 virtual void OnInstallFailure(const extensions::CrxInstallerError& error) {}
[email protected]c70013bd2010-01-20 21:50:03279};
280
[email protected]c82da8c42012-06-08 19:49:11281class MockAutoConfirmExtensionInstallPrompt : public ExtensionInstallPrompt {
[email protected]59e03362011-01-21 21:24:08282 public:
[email protected]619f86182012-07-03 21:30:18283 explicit MockAutoConfirmExtensionInstallPrompt(
[email protected]91e51d612012-10-21 23:03:05284 content::WebContents* web_contents)
285 : ExtensionInstallPrompt(web_contents) {}
[email protected]59e03362011-01-21 21:24:08286
287 // Proceed without confirmation prompt.
[email protected]af6efb22012-10-12 02:23:05288 virtual void ConfirmInstall(Delegate* delegate,
289 const Extension* extension,
290 const ShowDialogCallback& show_dialog_callback) {
[email protected]59e03362011-01-21 21:24:08291 delegate->InstallUIProceed();
292 }
293};
294
[email protected]84f4dc02011-11-29 21:58:26295const Extension* ExtensionBrowserTest::InstallExtensionFromWebstore(
296 const FilePath& path,
297 int expected_change) {
[email protected]cefa749d2011-08-11 22:21:48298 return InstallOrUpdateExtension("", path, INSTALL_UI_TYPE_NONE,
[email protected]7e7b782e2012-08-03 01:13:57299 expected_change, Extension::INTERNAL,
300 browser(), true);
[email protected]cefa749d2011-08-11 22:21:48301}
302
[email protected]84f4dc02011-11-29 21:58:26303const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
304 const std::string& id,
305 const FilePath& path,
306 InstallUIType ui_type,
307 int expected_change) {
[email protected]59e03362011-01-21 21:24:08308 return InstallOrUpdateExtension(id, path, ui_type, expected_change,
[email protected]7e7b782e2012-08-03 01:13:57309 Extension::INTERNAL, browser(), false);
[email protected]59e03362011-01-21 21:24:08310}
311
[email protected]84f4dc02011-11-29 21:58:26312const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
313 const std::string& id,
314 const FilePath& path,
315 InstallUIType ui_type,
316 int expected_change,
[email protected]32fc4ff72012-06-15 21:50:01317 Browser* browser,
[email protected]84f4dc02011-11-29 21:58:26318 bool from_webstore) {
[email protected]7e7b782e2012-08-03 01:13:57319 return InstallOrUpdateExtension(id, path, ui_type, expected_change,
320 Extension::INTERNAL, browser, from_webstore);
321}
322
323const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
324 const std::string& id,
325 const FilePath& path,
326 InstallUIType ui_type,
327 int expected_change,
328 Extension::Location install_source) {
329 return InstallOrUpdateExtension(id, path, ui_type, expected_change,
330 install_source, browser(), false);
331}
332
333const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
334 const std::string& id,
335 const FilePath& path,
336 InstallUIType ui_type,
337 int expected_change,
338 Extension::Location install_source,
339 Browser* browser,
340 bool from_webstore) {
[email protected]32fc4ff72012-06-15 21:50:01341 ExtensionService* service = browser->profile()->GetExtensionService();
[email protected]17c4f3c2009-07-04 16:36:25342 service->set_show_extensions_prompts(false);
343 size_t num_before = service->extensions()->size();
[email protected]1bd54132009-06-11 00:05:34344
[email protected]0c6da502009-08-14 22:32:39345 {
[email protected]c82da8c42012-06-08 19:49:11346 ExtensionInstallPrompt* install_ui = NULL;
[email protected]619f86182012-07-03 21:30:18347 if (ui_type == INSTALL_UI_TYPE_CANCEL) {
[email protected]c82da8c42012-06-08 19:49:11348 install_ui = new MockAbortExtensionInstallPrompt();
[email protected]619f86182012-07-03 21:30:18349 } else if (ui_type == INSTALL_UI_TYPE_NORMAL) {
[email protected]91e51d612012-10-21 23:03:05350 install_ui = new ExtensionInstallPrompt(
351 browser->tab_strip_model()->GetActiveWebContents());
[email protected]619f86182012-07-03 21:30:18352 } else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) {
[email protected]619f86182012-07-03 21:30:18353 install_ui = new MockAutoConfirmExtensionInstallPrompt(
[email protected]91e51d612012-10-21 23:03:05354 browser->tab_strip_model()->GetActiveWebContents());
[email protected]619f86182012-07-03 21:30:18355 }
[email protected]59e03362011-01-21 21:24:08356
357 // TODO(tessamac): Update callers to always pass an unpacked extension
358 // and then always pack the extension here.
359 FilePath crx_path = path;
360 if (crx_path.Extension() != FILE_PATH_LITERAL(".crx")) {
361 crx_path = PackExtension(path);
362 }
363 if (crx_path.empty())
[email protected]84f4dc02011-11-29 21:58:26364 return NULL;
[email protected]8fd16f502010-04-22 18:23:18365
[email protected]bf3d9df2012-07-24 23:20:27366 scoped_refptr<extensions::CrxInstaller> installer(
367 extensions::CrxInstaller::Create(service, install_ui));
[email protected]6dfbbf82010-03-12 23:09:16368 installer->set_expected_id(id);
[email protected]cefa749d2011-08-11 22:21:48369 installer->set_is_gallery_install(from_webstore);
[email protected]7e7b782e2012-08-03 01:13:57370 installer->set_install_source(install_source);
[email protected]d9039812012-06-09 06:05:48371 if (!from_webstore) {
372 installer->set_off_store_install_allow_reason(
[email protected]bf3d9df2012-07-24 23:20:27373 extensions::CrxInstaller::OffStoreInstallAllowedInTest);
[email protected]d9039812012-06-09 06:05:48374 }
[email protected]84f4dc02011-11-29 21:58:26375
376 content::NotificationRegistrar registrar;
377 registrar.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
[email protected]bf3d9df2012-07-24 23:20:27378 content::Source<extensions::CrxInstaller>(installer.get()));
[email protected]84f4dc02011-11-29 21:58:26379
[email protected]59e03362011-01-21 21:24:08380 installer->InstallCrx(crx_path);
[email protected]2a409532009-08-28 19:39:44381
[email protected]729eb632012-07-26 04:45:26382 content::RunMessageLoop();
[email protected]0c6da502009-08-14 22:32:39383 }
384
[email protected]17c4f3c2009-07-04 16:36:25385 size_t num_after = service->extensions()->size();
[email protected]84f4dc02011-11-29 21:58:26386 EXPECT_EQ(num_before + expected_change, num_after);
387 if (num_before + expected_change != num_after) {
[email protected]e99a88e92010-10-22 18:08:03388 VLOG(1) << "Num extensions before: " << base::IntToString(num_before)
389 << " num after: " << base::IntToString(num_after)
390 << " Installed extensions follow:";
[email protected]7d11cee2009-07-08 02:40:42391
[email protected]84df8332011-12-06 18:22:46392 for (ExtensionSet::const_iterator it = service->extensions()->begin();
393 it != service->extensions()->end(); ++it)
394 VLOG(1) << " " << (*it)->id();
[email protected]7d11cee2009-07-08 02:40:42395
[email protected]e99a88e92010-10-22 18:08:03396 VLOG(1) << "Errors follow:";
[email protected]fc670822011-12-17 09:33:49397 const std::vector<string16>* errors =
[email protected]7d11cee2009-07-08 02:40:42398 ExtensionErrorReporter::GetInstance()->GetErrors();
[email protected]fc670822011-12-17 09:33:49399 for (std::vector<string16>::const_iterator iter = errors->begin();
[email protected]e99a88e92010-10-22 18:08:03400 iter != errors->end(); ++iter)
401 VLOG(1) << *iter;
[email protected]7d11cee2009-07-08 02:40:42402
[email protected]84f4dc02011-11-29 21:58:26403 return NULL;
[email protected]9c73efa2009-07-08 00:18:36404 }
[email protected]1bd54132009-06-11 00:05:34405
[email protected]d1fe1352012-04-26 00:47:32406 if (!WaitForExtensionViewsToLoad())
[email protected]84f4dc02011-11-29 21:58:26407 return NULL;
408 return service->GetExtensionById(last_loaded_extension_id_, false);
[email protected]17c4f3c2009-07-04 16:36:25409}
[email protected]1bd54132009-06-11 00:05:34410
[email protected]e1725842009-10-20 06:40:15411void ExtensionBrowserTest::ReloadExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13412 ExtensionService* service = extensions::ExtensionSystem::Get(
413 browser()->profile())->extension_service();
[email protected]e1725842009-10-20 06:40:15414 service->ReloadExtension(extension_id);
[email protected]3e59bac2010-04-08 16:16:55415 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27416 chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]ad50def52011-10-19 23:17:07417 content::NotificationService::AllSources());
[email protected]e1725842009-10-20 06:40:15418}
419
[email protected]57f71b92009-09-11 19:31:38420void ExtensionBrowserTest::UnloadExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13421 ExtensionService* service = extensions::ExtensionSystem::Get(
422 browser()->profile())->extension_service();
[email protected]814a7bf0f2011-08-13 05:30:59423 service->UnloadExtension(extension_id, extension_misc::UNLOAD_REASON_DISABLE);
[email protected]57f71b92009-09-11 19:31:38424}
425
[email protected]17c4f3c2009-07-04 16:36:25426void ExtensionBrowserTest::UninstallExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13427 ExtensionService* service = extensions::ExtensionSystem::Get(
428 browser()->profile())->extension_service();
[email protected]d6ebc9792011-04-07 18:18:33429 service->UninstallExtension(extension_id, false, NULL);
[email protected]17c4f3c2009-07-04 16:36:25430}
431
[email protected]7d9ad0b32010-02-12 21:44:45432void ExtensionBrowserTest::DisableExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13433 ExtensionService* service = extensions::ExtensionSystem::Get(
434 browser()->profile())->extension_service();
[email protected]44d62b62012-04-11 00:06:03435 service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
[email protected]7d9ad0b32010-02-12 21:44:45436}
437
438void ExtensionBrowserTest::EnableExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13439 ExtensionService* service = extensions::ExtensionSystem::Get(
440 browser()->profile())->extension_service();
[email protected]7d9ad0b32010-02-12 21:44:45441 service->EnableExtension(extension_id);
442}
443
[email protected]57f71b92009-09-11 19:31:38444bool ExtensionBrowserTest::WaitForPageActionCountChangeTo(int count) {
[email protected]d818e07f2010-02-10 13:10:03445 LocationBarTesting* location_bar =
446 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]3e59bac2010-04-08 16:16:55447 if (location_bar->PageActionCount() != count) {
448 target_page_action_count_ = count;
449 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27450 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
[email protected]ad50def52011-10-19 23:17:07451 content::NotificationService::AllSources());
[email protected]3e59bac2010-04-08 16:16:55452 }
[email protected]d818e07f2010-02-10 13:10:03453 return location_bar->PageActionCount() == count;
[email protected]57f71b92009-09-11 19:31:38454}
455
456bool ExtensionBrowserTest::WaitForPageActionVisibilityChangeTo(int count) {
[email protected]d818e07f2010-02-10 13:10:03457 LocationBarTesting* location_bar =
458 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]3e59bac2010-04-08 16:16:55459 if (location_bar->PageActionVisibleCount() != count) {
460 target_visible_page_action_count_ = count;
461 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27462 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
[email protected]ad50def52011-10-19 23:17:07463 content::NotificationService::AllSources());
[email protected]3e59bac2010-04-08 16:16:55464 }
[email protected]d818e07f2010-02-10 13:10:03465 return location_bar->PageActionVisibleCount() == count;
[email protected]361b28a2009-07-09 21:30:53466}
467
[email protected]d1fe1352012-04-26 00:47:32468bool ExtensionBrowserTest::WaitForExtensionViewsToLoad() {
469 // Wait for all the extension render view hosts that exist to finish loading.
[email protected]6c2381d2011-10-19 02:52:53470 content::NotificationRegistrar registrar;
[email protected]d1fe1352012-04-26 00:47:32471 registrar.Add(this, content::NOTIFICATION_LOAD_STOP,
[email protected]ad50def52011-10-19 23:17:07472 content::NotificationService::AllSources());
[email protected]86c008e82009-08-28 20:26:05473
[email protected]17c4f3c2009-07-04 16:36:25474 ExtensionProcessManager* manager =
[email protected]be93bba02012-10-24 16:44:03475 extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
[email protected]d1fe1352012-04-26 00:47:32476 ExtensionProcessManager::ViewSet all_views = manager->GetAllViews();
477 for (ExtensionProcessManager::ViewSet::const_iterator iter =
478 all_views.begin();
479 iter != all_views.end();) {
480 if (!(*iter)->IsLoading()) {
[email protected]c290a6232009-09-25 17:45:16481 ++iter;
[email protected]bd618b4c2009-11-04 19:49:51482 } else {
[email protected]729eb632012-07-26 04:45:26483 content::RunMessageLoop();
[email protected]bd618b4c2009-11-04 19:49:51484
485 // Test activity may have modified the set of extension processes during
486 // message processing, so re-start the iteration to catch added/removed
487 // processes.
[email protected]d1fe1352012-04-26 00:47:32488 all_views = manager->GetAllViews();
489 iter = all_views.begin();
[email protected]bd618b4c2009-11-04 19:49:51490 }
[email protected]17c4f3c2009-07-04 16:36:25491 }
[email protected]17c4f3c2009-07-04 16:36:25492 return true;
493}
494
[email protected]f4ea11282009-10-14 00:19:31495bool ExtensionBrowserTest::WaitForExtensionInstall() {
496 int before = extension_installs_observed_;
[email protected]432115822011-07-10 15:52:27497 ui_test_utils::RegisterAndWait(this,
498 chrome::NOTIFICATION_EXTENSION_INSTALLED,
[email protected]ad50def52011-10-19 23:17:07499 content::NotificationService::AllSources());
[email protected]f4ea11282009-10-14 00:19:31500 return extension_installs_observed_ == (before + 1);
501}
502
503bool ExtensionBrowserTest::WaitForExtensionInstallError() {
504 int before = extension_installs_observed_;
[email protected]3e59bac2010-04-08 16:16:55505 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27506 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
[email protected]ad50def52011-10-19 23:17:07507 content::NotificationService::AllSources());
[email protected]f4ea11282009-10-14 00:19:31508 return extension_installs_observed_ == before;
509}
510
[email protected]1eb175082010-02-10 09:26:16511void ExtensionBrowserTest::WaitForExtensionLoad() {
[email protected]432115822011-07-10 15:52:27512 ui_test_utils::RegisterAndWait(this, chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]ad50def52011-10-19 23:17:07513 content::NotificationService::AllSources());
[email protected]d1fe1352012-04-26 00:47:32514 WaitForExtensionViewsToLoad();
[email protected]1eb175082010-02-10 09:26:16515}
516
[email protected]bbcde9102012-03-25 22:40:49517bool ExtensionBrowserTest::WaitForExtensionLoadError() {
518 int before = extension_load_errors_observed_;
519 ui_test_utils::RegisterAndWait(this,
520 chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
521 content::NotificationService::AllSources());
522 return extension_load_errors_observed_ != before;
523}
524
[email protected]1eb175082010-02-10 09:26:16525bool ExtensionBrowserTest::WaitForExtensionCrash(
526 const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13527 ExtensionService* service = extensions::ExtensionSystem::Get(
528 browser()->profile())->extension_service();
[email protected]1eb175082010-02-10 09:26:16529
530 if (!service->GetExtensionById(extension_id, true)) {
531 // The extension is already unloaded, presumably due to a crash.
532 return true;
533 }
[email protected]432115822011-07-10 15:52:27534 ui_test_utils::RegisterAndWait(
535 this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
[email protected]ad50def52011-10-19 23:17:07536 content::NotificationService::AllSources());
[email protected]1eb175082010-02-10 09:26:16537 return (service->GetExtensionById(extension_id, true) == NULL);
538}
539
[email protected]8c6af5b2012-06-15 20:10:26540bool ExtensionBrowserTest::WaitForCrxInstallerDone() {
541 int before = crx_installers_done_observed_;
542 ui_test_utils::RegisterAndWait(this,
543 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
544 content::NotificationService::AllSources());
545 return crx_installers_done_observed_ == (before + 1);
546}
547
[email protected]19da16a92012-05-23 17:11:29548void ExtensionBrowserTest::OpenWindow(content::WebContents* contents,
549 const GURL& url,
550 bool newtab_process_should_equal_opener,
551 content::WebContents** newtab_result) {
[email protected]a7fe9112012-07-20 02:34:45552 content::WindowedNotificationObserver observer(
[email protected]19da16a92012-05-23 17:11:29553 content::NOTIFICATION_LOAD_STOP,
554 content::NotificationService::AllSources());
[email protected]7d478cb2012-07-24 17:19:42555 ASSERT_TRUE(content::ExecuteJavaScript(
[email protected]06bc5d92013-01-02 22:44:13556 contents->GetRenderViewHost(),
557 "",
558 "window.open('" + url.spec() + "');"));
[email protected]19da16a92012-05-23 17:11:29559
560 // The above window.open call is not user-initiated, so it will create
561 // a popup window instead of a new tab in current window.
562 // The stop notification will come from the new tab.
563 observer.Wait();
564 content::NavigationController* controller =
565 content::Source<content::NavigationController>(observer.source()).ptr();
566 content::WebContents* newtab = controller->GetWebContents();
567 ASSERT_TRUE(newtab);
568 EXPECT_EQ(url, controller->GetLastCommittedEntry()->GetURL());
569 if (newtab_process_should_equal_opener)
570 EXPECT_EQ(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
571 else
572 EXPECT_NE(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
573
574 if (newtab_result)
575 *newtab_result = newtab;
576}
577
578void ExtensionBrowserTest::NavigateInRenderer(content::WebContents* contents,
579 const GURL& url) {
580 bool result = false;
[email protected]a7fe9112012-07-20 02:34:45581 content::WindowedNotificationObserver observer(
[email protected]19da16a92012-05-23 17:11:29582 content::NOTIFICATION_LOAD_STOP,
583 content::NotificationService::AllSources());
[email protected]7d478cb2012-07-24 17:19:42584 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractBool(
[email protected]06bc5d92013-01-02 22:44:13585 contents->GetRenderViewHost(),
586 "",
587 "window.addEventListener('unload', function() {"
588 " window.domAutomationController.send(true);"
589 "}, false);"
590 "window.location = '" + url.spec() + "';",
[email protected]19da16a92012-05-23 17:11:29591 &result));
592 ASSERT_TRUE(result);
593 observer.Wait();
594 EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL());
595}
596
[email protected]3a1dc572012-07-31 22:25:13597extensions::ExtensionHost* ExtensionBrowserTest::FindHostWithPath(
[email protected]fad73672012-06-15 23:26:06598 ExtensionProcessManager* manager,
599 const std::string& path,
600 int expected_hosts) {
[email protected]3a1dc572012-07-31 22:25:13601 extensions::ExtensionHost* host = NULL;
[email protected]fad73672012-06-15 23:26:06602 int num_hosts = 0;
603 ExtensionProcessManager::ExtensionHostSet background_hosts =
604 manager->background_hosts();
605 for (ExtensionProcessManager::const_iterator iter = background_hosts.begin();
606 iter != background_hosts.end(); ++iter) {
607 if ((*iter)->GetURL().path() == path) {
608 EXPECT_FALSE(host);
609 host = *iter;
610 }
611 num_hosts++;
612 }
613 EXPECT_EQ(expected_hosts, num_hosts);
614 return host;
615}
616
[email protected]6c2381d2011-10-19 02:52:53617void ExtensionBrowserTest::Observe(
618 int type,
619 const content::NotificationSource& source,
620 const content::NotificationDetails& details) {
[email protected]432115822011-07-10 15:52:27621 switch (type) {
622 case chrome::NOTIFICATION_EXTENSION_LOADED:
[email protected]6c2381d2011-10-19 02:52:53623 last_loaded_extension_id_ =
624 content::Details<const Extension>(details).ptr()->id();
[email protected]e99a88e92010-10-22 18:08:03625 VLOG(1) << "Got EXTENSION_LOADED notification.";
[email protected]7d11cee2009-07-08 02:40:42626 MessageLoopForUI::current()->Quit();
627 break;
628
[email protected]84f4dc02011-11-29 21:58:26629 case chrome::NOTIFICATION_CRX_INSTALLER_DONE:
630 VLOG(1) << "Got CRX_INSTALLER_DONE notification.";
631 {
632 const Extension* extension =
633 content::Details<const Extension>(details).ptr();
634 if (extension)
635 last_loaded_extension_id_ = extension->id();
636 else
637 last_loaded_extension_id_ = "";
638 }
[email protected]8c6af5b2012-06-15 20:10:26639 ++crx_installers_done_observed_;
[email protected]0c6da502009-08-14 22:32:39640 MessageLoopForUI::current()->Quit();
641 break;
642
[email protected]432115822011-07-10 15:52:27643 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
[email protected]e99a88e92010-10-22 18:08:03644 VLOG(1) << "Got EXTENSION_INSTALLED notification.";
[email protected]f4ea11282009-10-14 00:19:31645 ++extension_installs_observed_;
646 MessageLoopForUI::current()->Quit();
647 break;
648
[email protected]432115822011-07-10 15:52:27649 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR:
[email protected]e99a88e92010-10-22 18:08:03650 VLOG(1) << "Got EXTENSION_INSTALL_ERROR notification.";
[email protected]f4ea11282009-10-14 00:19:31651 MessageLoopForUI::current()->Quit();
652 break;
653
[email protected]432115822011-07-10 15:52:27654 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED:
[email protected]e99a88e92010-10-22 18:08:03655 VLOG(1) << "Got EXTENSION_PROCESS_TERMINATED notification.";
[email protected]1eb175082010-02-10 09:26:16656 MessageLoopForUI::current()->Quit();
657 break;
658
[email protected]bbcde9102012-03-25 22:40:49659 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR:
660 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification.";
661 ++extension_load_errors_observed_;
662 MessageLoopForUI::current()->Quit();
663 break;
664
[email protected]432115822011-07-10 15:52:27665 case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED: {
[email protected]d818e07f2010-02-10 13:10:03666 LocationBarTesting* location_bar =
667 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]e99a88e92010-10-22 18:08:03668 VLOG(1) << "Got EXTENSION_PAGE_ACTION_COUNT_CHANGED notification. Number "
669 "of page actions: " << location_bar->PageActionCount();
[email protected]d818e07f2010-02-10 13:10:03670 if (location_bar->PageActionCount() ==
671 target_page_action_count_) {
672 target_page_action_count_ = -1;
673 MessageLoopForUI::current()->Quit();
674 }
675 break;
676 }
677
[email protected]432115822011-07-10 15:52:27678 case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED: {
[email protected]d818e07f2010-02-10 13:10:03679 LocationBarTesting* location_bar =
680 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]e99a88e92010-10-22 18:08:03681 VLOG(1) << "Got EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED notification. "
682 "Number of visible page actions: "
683 << location_bar->PageActionVisibleCount();
[email protected]d818e07f2010-02-10 13:10:03684 if (location_bar->PageActionVisibleCount() ==
685 target_visible_page_action_count_) {
686 target_visible_page_action_count_ = -1;
687 MessageLoopForUI::current()->Quit();
688 }
689 break;
690 }
691
[email protected]d1fe1352012-04-26 00:47:32692 case content::NOTIFICATION_LOAD_STOP:
693 VLOG(1) << "Got LOAD_STOP notification.";
694 MessageLoopForUI::current()->Quit();
695 break;
696
[email protected]17c4f3c2009-07-04 16:36:25697 default:
698 NOTREACHED();
699 break;
700 }
[email protected]1bd54132009-06-11 00:05:34701}