blob: 152b244a4eaffc315146738efe5e3b64d513a57c [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]3d43eef2012-10-09 23:17:5614#include "base/stringprintf.h"
[email protected]3ea1b182013-02-08 22:38:4115#include "base/strings/string_number_conversions.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]fb17ddc2013-02-07 07:09:3628#include "chrome/browser/profiles/profile_manager.h"
[email protected]7b5dc002010-11-16 23:08:1029#include "chrome/browser/ui/browser.h"
[email protected]00070c732011-04-09 15:31:3330#include "chrome/browser/ui/browser_window.h"
[email protected]1b1989f52012-12-03 08:33:5431#include "chrome/browser/ui/extensions/native_app_window.h"
[email protected]99bfb2042012-12-01 07:16:4532#include "chrome/browser/ui/extensions/shell_window.h"
[email protected]6a3ec2312010-12-02 19:30:1933#include "chrome/browser/ui/omnibox/location_bar.h"
[email protected]91e51d612012-10-21 23:03:0534#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]432115822011-07-10 15:52:2735#include "chrome/common/chrome_notification_types.h"
[email protected]17c4f3c2009-07-04 16:36:2536#include "chrome/common/chrome_paths.h"
[email protected]7b5dc002010-11-16 23:08:1037#include "chrome/common/chrome_switches.h"
[email protected]d69d7b172012-08-09 04:17:2638#include "chrome/common/chrome_version_info.h"
[email protected]af44e7fb2011-07-29 18:32:3239#include "chrome/test/base/ui_test_utils.h"
[email protected]19da16a92012-05-23 17:11:2940#include "content/public/browser/navigation_controller.h"
41#include "content/public/browser/navigation_entry.h"
[email protected]6c2381d2011-10-19 02:52:5342#include "content/public/browser/notification_registrar.h"
[email protected]ad50def52011-10-19 23:17:0743#include "content/public/browser/notification_service.h"
[email protected]d1fe1352012-04-26 00:47:3244#include "content/public/browser/render_view_host.h"
[email protected]7d478cb2012-07-24 17:19:4245#include "content/public/test/browser_test_utils.h"
[email protected]36b643212012-09-07 12:53:0046#include "sync/api/string_ordinal.h"
[email protected]81e63782009-02-27 19:35:0947
[email protected]1c321ee2012-05-21 03:02:3448using extensions::Extension;
[email protected]6d777492012-07-11 17:33:4349using extensions::ExtensionCreator;
[email protected]00b5d0a52012-10-30 13:13:5350using extensions::FeatureSwitch;
[email protected]1d5e58b2013-01-31 08:41:4051using extensions::Manifest;
[email protected]1c321ee2012-05-21 03:02:3452
[email protected]d818e07f2010-02-10 13:10:0353ExtensionBrowserTest::ExtensionBrowserTest()
[email protected]9931fbfc2010-07-23 09:15:5154 : loaded_(false),
55 installed_(false),
56 extension_installs_observed_(0),
[email protected]bbcde9102012-03-25 22:40:4957 extension_load_errors_observed_(0),
[email protected]9931fbfc2010-07-23 09:15:5158 target_page_action_count_(-1),
[email protected]2b5fdc32012-08-14 03:55:4359 target_visible_page_action_count_(-1),
[email protected]612a1cb12012-10-17 13:18:0360 current_channel_(chrome::VersionInfo::CHANNEL_DEV),
61 override_prompt_for_external_extensions_(
[email protected]00b5d0a52012-10-30 13:13:5362 FeatureSwitch::prompt_for_external_extensions(), false),
[email protected]fb17ddc2013-02-07 07:09:3663 override_sideload_wipeout_(
64 FeatureSwitch::sideload_wipeout(), false),
65 profile_(NULL) {
[email protected]3a305db2011-04-12 13:40:5366 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]178f8512012-02-09 01:49:3667}
68
[email protected]e66ba952012-10-09 09:59:4469ExtensionBrowserTest::~ExtensionBrowserTest() {}
[email protected]d818e07f2010-02-10 13:10:0370
[email protected]fb17ddc2013-02-07 07:09:3671Profile* ExtensionBrowserTest::profile() {
72 if (!profile_) {
73 if (browser())
74 profile_ = browser()->profile();
75 else
76 profile_ = ProfileManager::GetDefaultProfile();
77 }
78 return profile_;
79}
80
[email protected]17c4f3c2009-07-04 16:36:2581void ExtensionBrowserTest::SetUpCommandLine(CommandLine* command_line) {
[email protected]17c4f3c2009-07-04 16:36:2582 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
83 test_data_dir_ = test_data_dir_.AppendASCII("extensions");
[email protected]856c8d72009-11-24 16:33:1284
[email protected]1172ba72010-05-21 22:21:1185#if defined(OS_CHROMEOS)
86 // This makes sure that we create the Default profile first, with no
[email protected]eaa7dd182010-12-14 11:09:0087 // ExtensionService and then the real profile with one, as we do when
[email protected]1172ba72010-05-21 22:21:1188 // running on chromeos.
[email protected]05076ba22010-07-30 05:59:5789 command_line->AppendSwitchASCII(switches::kLoginUser,
90 "[email protected]");
91 command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
[email protected]1172ba72010-05-21 22:21:1192#endif
[email protected]81e63782009-02-27 19:35:0993}
[email protected]653c9ea2009-05-06 16:58:5694
[email protected]24e04292012-08-10 21:08:0895const Extension* ExtensionBrowserTest::LoadExtensionWithFlags(
[email protected]650b2d52013-02-10 03:41:4596 const base::FilePath& path, int flags) {
[email protected]06bdd2b2012-11-30 18:47:1397 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:3698 profile())->extension_service();
[email protected]0c6da502009-08-14 22:32:3999 {
[email protected]6c2381d2011-10-19 02:52:53100 content::NotificationRegistrar registrar;
[email protected]432115822011-07-10 15:52:27101 registrar.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]ad50def52011-10-19 23:17:07102 content::NotificationService::AllSources());
[email protected]d8c8f25f2011-11-02 18:18:01103 scoped_refptr<extensions::UnpackedInstaller> installer(
104 extensions::UnpackedInstaller::Create(service));
105 installer->set_prompt_for_plugins(false);
[email protected]b7462f32012-09-02 15:18:12106 installer->set_require_modern_manifest_version(
107 (flags & kFlagAllowOldManifestVersions) == 0);
[email protected]d8c8f25f2011-11-02 18:18:01108 installer->Load(path);
[email protected]729eb632012-07-26 04:45:26109 content::RunMessageLoop();
[email protected]0c6da502009-08-14 22:32:39110 }
[email protected]19f358e2010-10-28 20:22:50111
[email protected]84df8332011-12-06 18:22:46112 // Find the loaded extension by its path. See crbug.com/59531 for why
113 // we cannot just use last_loaded_extension_id_.
[email protected]650b2d52013-02-10 03:41:45114 base::FilePath extension_path = path;
[email protected]19f358e2010-10-28 20:22:50115 file_util::AbsolutePath(&extension_path);
[email protected]9adb9692010-10-29 23:14:02116 const Extension* extension = NULL;
[email protected]84df8332011-12-06 18:22:46117 for (ExtensionSet::const_iterator iter = service->extensions()->begin();
118 iter != service->extensions()->end(); ++iter) {
[email protected]19f358e2010-10-28 20:22:50119 if ((*iter)->path() == extension_path) {
120 extension = *iter;
121 break;
122 }
123 }
124 if (!extension)
[email protected]a964e112011-04-14 21:52:51125 return NULL;
[email protected]653c9ea2009-05-06 16:58:56126
[email protected]24e04292012-08-10 21:08:08127 if (!(flags & kFlagIgnoreManifestWarnings)) {
[email protected]1d5e58b2013-01-31 08:41:40128 const std::vector<extensions::InstallWarning>& install_warnings =
[email protected]24e04292012-08-10 21:08:08129 extension->install_warnings();
130 if (!install_warnings.empty()) {
131 std::string install_warnings_message = StringPrintf(
132 "Unexpected warnings when loading test extension %s:\n",
133 path.AsUTF8Unsafe().c_str());
134
[email protected]1d5e58b2013-01-31 08:41:40135 for (std::vector<extensions::InstallWarning>::const_iterator it =
[email protected]24e04292012-08-10 21:08:08136 install_warnings.begin(); it != install_warnings.end(); ++it) {
137 install_warnings_message += " " + it->message + "\n";
138 }
139
140 EXPECT_TRUE(extension->install_warnings().empty()) <<
141 install_warnings_message;
142 return NULL;
143 }
144 }
145
[email protected]d10f4602011-06-16 15:44:50146 const std::string extension_id = extension->id();
147
[email protected]c7c401d2011-03-16 10:20:01148 // The call to OnExtensionInstalled ensures the other extension prefs
149 // are set up with the defaults.
150 service->extension_prefs()->OnExtensionInstalled(
[email protected]26367b62012-10-04 23:03:32151 extension, Extension::ENABLED,
[email protected]36b643212012-09-07 12:53:00152 syncer::StringOrdinal::CreateInitialOrdinal());
[email protected]d10f4602011-06-16 15:44:50153
[email protected]c1bf62c72011-07-15 22:18:42154 // Toggling incognito or file access will reload the extension, so wait for
155 // the reload and grab the new extension instance. The default state is
156 // incognito disabled and file access enabled, so we don't wait in those
157 // cases.
158 {
[email protected]a7fe9112012-07-20 02:34:45159 content::WindowedNotificationObserver load_signal(
[email protected]c1bf62c72011-07-15 22:18:42160 chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]fb17ddc2013-02-07 07:09:36161 content::Source<Profile>(profile()));
[email protected]c1bf62c72011-07-15 22:18:42162 CHECK(!service->IsIncognitoEnabled(extension_id));
[email protected]db7331a2010-02-25 22:10:50163
[email protected]24e04292012-08-10 21:08:08164 if (flags & kFlagEnableIncognito) {
165 service->SetIsIncognitoEnabled(extension_id, true);
[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 }
170 }
171
172 {
[email protected]a7fe9112012-07-20 02:34:45173 content::WindowedNotificationObserver load_signal(
[email protected]c1bf62c72011-07-15 22:18:42174 chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]fb17ddc2013-02-07 07:09:36175 content::Source<Profile>(profile()));
[email protected]cdfca9702011-08-08 16:07:01176 CHECK(service->AllowFileAccess(extension));
[email protected]24e04292012-08-10 21:08:08177 if (!(flags & kFlagEnableFileAccess)) {
178 service->SetAllowFileAccess(extension, false);
[email protected]c1bf62c72011-07-15 22:18:42179 load_signal.Wait();
180 extension = service->GetExtensionById(extension_id, false);
181 CHECK(extension) << extension_id << " not found after reloading.";
182 }
[email protected]d10f4602011-06-16 15:44:50183 }
184
[email protected]d1fe1352012-04-26 00:47:32185 if (!WaitForExtensionViewsToLoad())
[email protected]a964e112011-04-14 21:52:51186 return NULL;
187
188 return extension;
[email protected]653c9ea2009-05-06 16:58:56189}
[email protected]1bd54132009-06-11 00:05:34190
[email protected]650b2d52013-02-10 03:41:45191const Extension* ExtensionBrowserTest::LoadExtension(
192 const base::FilePath& path) {
[email protected]24e04292012-08-10 21:08:08193 return LoadExtensionWithFlags(path, kFlagEnableFileAccess);
[email protected]db7331a2010-02-25 22:10:50194}
195
[email protected]a964e112011-04-14 21:52:51196const Extension* ExtensionBrowserTest::LoadExtensionIncognito(
[email protected]650b2d52013-02-10 03:41:45197 const base::FilePath& path) {
[email protected]24e04292012-08-10 21:08:08198 return LoadExtensionWithFlags(path,
199 kFlagEnableFileAccess | kFlagEnableIncognito);
[email protected]db7331a2010-02-25 22:10:50200}
201
[email protected]863e6472012-01-24 19:33:58202const Extension* ExtensionBrowserTest::LoadExtensionAsComponent(
[email protected]650b2d52013-02-10 03:41:45203 const base::FilePath& path) {
[email protected]06bdd2b2012-11-30 18:47:13204 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:36205 profile())->extension_service();
[email protected]61b55b62011-03-24 09:03:10206
207 std::string manifest;
208 if (!file_util::ReadFileToString(path.Append(Extension::kManifestFilename),
209 &manifest))
[email protected]863e6472012-01-24 19:33:58210 return NULL;
[email protected]61b55b62011-03-24 09:03:10211
[email protected]ee837d32012-10-02 22:25:49212 std::string extension_id = service->component_loader()->Add(manifest, path);
213 const Extension* extension = service->extensions()->GetByID(extension_id);
[email protected]863e6472012-01-24 19:33:58214 if (!extension)
215 return NULL;
216 last_loaded_extension_id_ = extension->id();
217 return extension;
[email protected]61b55b62011-03-24 09:03:10218}
219
[email protected]650b2d52013-02-10 03:41:45220base::FilePath ExtensionBrowserTest::PackExtension(
221 const base::FilePath& dir_path) {
222 base::FilePath crx_path = temp_dir_.path().AppendASCII("temp.crx");
[email protected]59e03362011-01-21 21:24:08223 if (!file_util::Delete(crx_path, false)) {
224 ADD_FAILURE() << "Failed to delete crx: " << crx_path.value();
[email protected]650b2d52013-02-10 03:41:45225 return base::FilePath();
[email protected]59e03362011-01-21 21:24:08226 }
227
[email protected]21a5ad62012-04-03 04:48:45228 // Look for PEM files with the same name as the directory.
[email protected]650b2d52013-02-10 03:41:45229 base::FilePath pem_path =
230 dir_path.ReplaceExtension(FILE_PATH_LITERAL(".pem"));
231 base::FilePath pem_path_out;
[email protected]21a5ad62012-04-03 04:48:45232
233 if (!file_util::PathExists(pem_path)) {
[email protected]650b2d52013-02-10 03:41:45234 pem_path = base::FilePath();
[email protected]21a5ad62012-04-03 04:48:45235 pem_path_out = crx_path.DirName().AppendASCII("temp.pem");
236 if (!file_util::Delete(pem_path_out, false)) {
237 ADD_FAILURE() << "Failed to delete pem: " << pem_path_out.value();
[email protected]650b2d52013-02-10 03:41:45238 return base::FilePath();
[email protected]21a5ad62012-04-03 04:48:45239 }
[email protected]59e03362011-01-21 21:24:08240 }
241
[email protected]21a5ad62012-04-03 04:48:45242 return PackExtensionWithOptions(dir_path, crx_path, pem_path, pem_path_out);
[email protected]f66a50a2011-11-02 23:53:46243}
244
[email protected]650b2d52013-02-10 03:41:45245base::FilePath ExtensionBrowserTest::PackExtensionWithOptions(
246 const base::FilePath& dir_path,
247 const base::FilePath& crx_path,
248 const base::FilePath& pem_path,
249 const base::FilePath& pem_out_path) {
[email protected]19a906b2011-02-07 20:56:37250 if (!file_util::PathExists(dir_path)) {
251 ADD_FAILURE() << "Extension dir not found: " << dir_path.value();
[email protected]650b2d52013-02-10 03:41:45252 return base::FilePath();
[email protected]19a906b2011-02-07 20:56:37253 }
254
[email protected]f66a50a2011-11-02 23:53:46255 if (!file_util::PathExists(pem_path) && pem_out_path.empty()) {
256 ADD_FAILURE() << "Must specify a PEM file or PEM output path";
[email protected]650b2d52013-02-10 03:41:45257 return base::FilePath();
[email protected]f66a50a2011-11-02 23:53:46258 }
259
[email protected]59e03362011-01-21 21:24:08260 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
261 if (!creator->Run(dir_path,
262 crx_path,
[email protected]f66a50a2011-11-02 23:53:46263 pem_path,
[email protected]93d973a2012-01-08 07:38:26264 pem_out_path,
265 ExtensionCreator::kOverwriteCRX)) {
[email protected]fc38935a2011-10-31 23:53:28266 ADD_FAILURE() << "ExtensionCreator::Run() failed: "
267 << creator->error_message();
[email protected]650b2d52013-02-10 03:41:45268 return base::FilePath();
[email protected]59e03362011-01-21 21:24:08269 }
270
271 if (!file_util::PathExists(crx_path)) {
272 ADD_FAILURE() << crx_path.value() << " was not created.";
[email protected]650b2d52013-02-10 03:41:45273 return base::FilePath();
[email protected]59e03362011-01-21 21:24:08274 }
275 return crx_path;
276}
277
[email protected]c70013bd2010-01-20 21:50:03278// This class is used to simulate an installation abort by the user.
[email protected]c82da8c42012-06-08 19:49:11279class MockAbortExtensionInstallPrompt : public ExtensionInstallPrompt {
[email protected]c70013bd2010-01-20 21:50:03280 public:
[email protected]91e51d612012-10-21 23:03:05281 MockAbortExtensionInstallPrompt() : ExtensionInstallPrompt(NULL) {
[email protected]619f86182012-07-03 21:30:18282 }
[email protected]c70013bd2010-01-20 21:50:03283
284 // Simulate a user abort on an extension installation.
[email protected]49aeab62013-02-07 02:53:11285 virtual void ConfirmInstall(
286 Delegate* delegate,
287 const Extension* extension,
288 const ShowDialogCallback& show_dialog_callback) OVERRIDE {
[email protected]d828fac2011-06-28 05:43:04289 delegate->InstallUIAbort(true);
[email protected]c70013bd2010-01-20 21:50:03290 MessageLoopForUI::current()->Quit();
291 }
292
[email protected]49aeab62013-02-07 02:53:11293 virtual void OnInstallSuccess(const Extension* extension,
294 SkBitmap* icon) OVERRIDE {}
[email protected]c70013bd2010-01-20 21:50:03295
[email protected]49aeab62013-02-07 02:53:11296 virtual void OnInstallFailure(
297 const extensions::CrxInstallerError& error) OVERRIDE {}
[email protected]c70013bd2010-01-20 21:50:03298};
299
[email protected]c82da8c42012-06-08 19:49:11300class MockAutoConfirmExtensionInstallPrompt : public ExtensionInstallPrompt {
[email protected]59e03362011-01-21 21:24:08301 public:
[email protected]619f86182012-07-03 21:30:18302 explicit MockAutoConfirmExtensionInstallPrompt(
[email protected]91e51d612012-10-21 23:03:05303 content::WebContents* web_contents)
304 : ExtensionInstallPrompt(web_contents) {}
[email protected]59e03362011-01-21 21:24:08305
306 // Proceed without confirmation prompt.
[email protected]49aeab62013-02-07 02:53:11307 virtual void ConfirmInstall(
308 Delegate* delegate,
309 const Extension* extension,
310 const ShowDialogCallback& show_dialog_callback) OVERRIDE {
[email protected]59e03362011-01-21 21:24:08311 delegate->InstallUIProceed();
312 }
313};
314
[email protected]84f4dc02011-11-29 21:58:26315const Extension* ExtensionBrowserTest::InstallExtensionFromWebstore(
[email protected]650b2d52013-02-10 03:41:45316 const base::FilePath& path,
[email protected]84f4dc02011-11-29 21:58:26317 int expected_change) {
[email protected]cefa749d2011-08-11 22:21:48318 return InstallOrUpdateExtension("", path, INSTALL_UI_TYPE_NONE,
[email protected]1d5e58b2013-01-31 08:41:40319 expected_change, Manifest::INTERNAL,
[email protected]7e7b782e2012-08-03 01:13:57320 browser(), true);
[email protected]cefa749d2011-08-11 22:21:48321}
322
[email protected]84f4dc02011-11-29 21:58:26323const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
324 const std::string& id,
[email protected]650b2d52013-02-10 03:41:45325 const base::FilePath& path,
[email protected]84f4dc02011-11-29 21:58:26326 InstallUIType ui_type,
327 int expected_change) {
[email protected]59e03362011-01-21 21:24:08328 return InstallOrUpdateExtension(id, path, ui_type, expected_change,
[email protected]1d5e58b2013-01-31 08:41:40329 Manifest::INTERNAL, browser(), false);
[email protected]59e03362011-01-21 21:24:08330}
331
[email protected]84f4dc02011-11-29 21:58:26332const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
333 const std::string& id,
[email protected]650b2d52013-02-10 03:41:45334 const base::FilePath& path,
[email protected]84f4dc02011-11-29 21:58:26335 InstallUIType ui_type,
336 int expected_change,
[email protected]32fc4ff72012-06-15 21:50:01337 Browser* browser,
[email protected]84f4dc02011-11-29 21:58:26338 bool from_webstore) {
[email protected]7e7b782e2012-08-03 01:13:57339 return InstallOrUpdateExtension(id, path, ui_type, expected_change,
[email protected]1d5e58b2013-01-31 08:41:40340 Manifest::INTERNAL, browser, from_webstore);
[email protected]7e7b782e2012-08-03 01:13:57341}
342
343const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
344 const std::string& id,
[email protected]650b2d52013-02-10 03:41:45345 const base::FilePath& path,
[email protected]7e7b782e2012-08-03 01:13:57346 InstallUIType ui_type,
347 int expected_change,
[email protected]1d5e58b2013-01-31 08:41:40348 Manifest::Location install_source) {
[email protected]7e7b782e2012-08-03 01:13:57349 return InstallOrUpdateExtension(id, path, ui_type, expected_change,
350 install_source, browser(), false);
351}
352
353const Extension* ExtensionBrowserTest::InstallOrUpdateExtension(
354 const std::string& id,
[email protected]650b2d52013-02-10 03:41:45355 const base::FilePath& path,
[email protected]7e7b782e2012-08-03 01:13:57356 InstallUIType ui_type,
357 int expected_change,
[email protected]1d5e58b2013-01-31 08:41:40358 Manifest::Location install_source,
[email protected]7e7b782e2012-08-03 01:13:57359 Browser* browser,
360 bool from_webstore) {
[email protected]fb17ddc2013-02-07 07:09:36361 ExtensionService* service = profile()->GetExtensionService();
[email protected]17c4f3c2009-07-04 16:36:25362 service->set_show_extensions_prompts(false);
363 size_t num_before = service->extensions()->size();
[email protected]1bd54132009-06-11 00:05:34364
[email protected]0c6da502009-08-14 22:32:39365 {
[email protected]c82da8c42012-06-08 19:49:11366 ExtensionInstallPrompt* install_ui = NULL;
[email protected]619f86182012-07-03 21:30:18367 if (ui_type == INSTALL_UI_TYPE_CANCEL) {
[email protected]c82da8c42012-06-08 19:49:11368 install_ui = new MockAbortExtensionInstallPrompt();
[email protected]619f86182012-07-03 21:30:18369 } else if (ui_type == INSTALL_UI_TYPE_NORMAL) {
[email protected]91e51d612012-10-21 23:03:05370 install_ui = new ExtensionInstallPrompt(
371 browser->tab_strip_model()->GetActiveWebContents());
[email protected]619f86182012-07-03 21:30:18372 } else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) {
[email protected]619f86182012-07-03 21:30:18373 install_ui = new MockAutoConfirmExtensionInstallPrompt(
[email protected]91e51d612012-10-21 23:03:05374 browser->tab_strip_model()->GetActiveWebContents());
[email protected]619f86182012-07-03 21:30:18375 }
[email protected]59e03362011-01-21 21:24:08376
377 // TODO(tessamac): Update callers to always pass an unpacked extension
378 // and then always pack the extension here.
[email protected]650b2d52013-02-10 03:41:45379 base::FilePath crx_path = path;
[email protected]59e03362011-01-21 21:24:08380 if (crx_path.Extension() != FILE_PATH_LITERAL(".crx")) {
381 crx_path = PackExtension(path);
382 }
383 if (crx_path.empty())
[email protected]84f4dc02011-11-29 21:58:26384 return NULL;
[email protected]8fd16f502010-04-22 18:23:18385
[email protected]bf3d9df2012-07-24 23:20:27386 scoped_refptr<extensions::CrxInstaller> installer(
387 extensions::CrxInstaller::Create(service, install_ui));
[email protected]6dfbbf82010-03-12 23:09:16388 installer->set_expected_id(id);
[email protected]cefa749d2011-08-11 22:21:48389 installer->set_is_gallery_install(from_webstore);
[email protected]7e7b782e2012-08-03 01:13:57390 installer->set_install_source(install_source);
[email protected]d9039812012-06-09 06:05:48391 if (!from_webstore) {
392 installer->set_off_store_install_allow_reason(
[email protected]bf3d9df2012-07-24 23:20:27393 extensions::CrxInstaller::OffStoreInstallAllowedInTest);
[email protected]d9039812012-06-09 06:05:48394 }
[email protected]84f4dc02011-11-29 21:58:26395
396 content::NotificationRegistrar registrar;
397 registrar.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
[email protected]bf3d9df2012-07-24 23:20:27398 content::Source<extensions::CrxInstaller>(installer.get()));
[email protected]84f4dc02011-11-29 21:58:26399
[email protected]59e03362011-01-21 21:24:08400 installer->InstallCrx(crx_path);
[email protected]2a409532009-08-28 19:39:44401
[email protected]729eb632012-07-26 04:45:26402 content::RunMessageLoop();
[email protected]0c6da502009-08-14 22:32:39403 }
404
[email protected]17c4f3c2009-07-04 16:36:25405 size_t num_after = service->extensions()->size();
[email protected]84f4dc02011-11-29 21:58:26406 EXPECT_EQ(num_before + expected_change, num_after);
407 if (num_before + expected_change != num_after) {
[email protected]e99a88e92010-10-22 18:08:03408 VLOG(1) << "Num extensions before: " << base::IntToString(num_before)
409 << " num after: " << base::IntToString(num_after)
410 << " Installed extensions follow:";
[email protected]7d11cee2009-07-08 02:40:42411
[email protected]84df8332011-12-06 18:22:46412 for (ExtensionSet::const_iterator it = service->extensions()->begin();
413 it != service->extensions()->end(); ++it)
414 VLOG(1) << " " << (*it)->id();
[email protected]7d11cee2009-07-08 02:40:42415
[email protected]e99a88e92010-10-22 18:08:03416 VLOG(1) << "Errors follow:";
[email protected]fc670822011-12-17 09:33:49417 const std::vector<string16>* errors =
[email protected]7d11cee2009-07-08 02:40:42418 ExtensionErrorReporter::GetInstance()->GetErrors();
[email protected]fc670822011-12-17 09:33:49419 for (std::vector<string16>::const_iterator iter = errors->begin();
[email protected]e99a88e92010-10-22 18:08:03420 iter != errors->end(); ++iter)
421 VLOG(1) << *iter;
[email protected]7d11cee2009-07-08 02:40:42422
[email protected]84f4dc02011-11-29 21:58:26423 return NULL;
[email protected]9c73efa2009-07-08 00:18:36424 }
[email protected]1bd54132009-06-11 00:05:34425
[email protected]d1fe1352012-04-26 00:47:32426 if (!WaitForExtensionViewsToLoad())
[email protected]84f4dc02011-11-29 21:58:26427 return NULL;
428 return service->GetExtensionById(last_loaded_extension_id_, false);
[email protected]17c4f3c2009-07-04 16:36:25429}
[email protected]1bd54132009-06-11 00:05:34430
[email protected]e1725842009-10-20 06:40:15431void ExtensionBrowserTest::ReloadExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13432 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:36433 profile())->extension_service();
[email protected]e1725842009-10-20 06:40:15434 service->ReloadExtension(extension_id);
[email protected]3e59bac2010-04-08 16:16:55435 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27436 chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]ad50def52011-10-19 23:17:07437 content::NotificationService::AllSources());
[email protected]e1725842009-10-20 06:40:15438}
439
[email protected]57f71b92009-09-11 19:31:38440void ExtensionBrowserTest::UnloadExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13441 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:36442 profile())->extension_service();
[email protected]814a7bf0f2011-08-13 05:30:59443 service->UnloadExtension(extension_id, extension_misc::UNLOAD_REASON_DISABLE);
[email protected]57f71b92009-09-11 19:31:38444}
445
[email protected]17c4f3c2009-07-04 16:36:25446void ExtensionBrowserTest::UninstallExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13447 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:36448 profile())->extension_service();
[email protected]d6ebc9792011-04-07 18:18:33449 service->UninstallExtension(extension_id, false, NULL);
[email protected]17c4f3c2009-07-04 16:36:25450}
451
[email protected]7d9ad0b32010-02-12 21:44:45452void ExtensionBrowserTest::DisableExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13453 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:36454 profile())->extension_service();
[email protected]44d62b62012-04-11 00:06:03455 service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
[email protected]7d9ad0b32010-02-12 21:44:45456}
457
458void ExtensionBrowserTest::EnableExtension(const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13459 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:36460 profile())->extension_service();
[email protected]7d9ad0b32010-02-12 21:44:45461 service->EnableExtension(extension_id);
462}
463
[email protected]57f71b92009-09-11 19:31:38464bool ExtensionBrowserTest::WaitForPageActionCountChangeTo(int count) {
[email protected]d818e07f2010-02-10 13:10:03465 LocationBarTesting* location_bar =
466 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]3e59bac2010-04-08 16:16:55467 if (location_bar->PageActionCount() != count) {
468 target_page_action_count_ = count;
469 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27470 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
[email protected]ad50def52011-10-19 23:17:07471 content::NotificationService::AllSources());
[email protected]3e59bac2010-04-08 16:16:55472 }
[email protected]d818e07f2010-02-10 13:10:03473 return location_bar->PageActionCount() == count;
[email protected]57f71b92009-09-11 19:31:38474}
475
476bool ExtensionBrowserTest::WaitForPageActionVisibilityChangeTo(int count) {
[email protected]d818e07f2010-02-10 13:10:03477 LocationBarTesting* location_bar =
478 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]3e59bac2010-04-08 16:16:55479 if (location_bar->PageActionVisibleCount() != count) {
480 target_visible_page_action_count_ = count;
481 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27482 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
[email protected]ad50def52011-10-19 23:17:07483 content::NotificationService::AllSources());
[email protected]3e59bac2010-04-08 16:16:55484 }
[email protected]d818e07f2010-02-10 13:10:03485 return location_bar->PageActionVisibleCount() == count;
[email protected]361b28a2009-07-09 21:30:53486}
487
[email protected]d1fe1352012-04-26 00:47:32488bool ExtensionBrowserTest::WaitForExtensionViewsToLoad() {
489 // Wait for all the extension render view hosts that exist to finish loading.
[email protected]6c2381d2011-10-19 02:52:53490 content::NotificationRegistrar registrar;
[email protected]d1fe1352012-04-26 00:47:32491 registrar.Add(this, content::NOTIFICATION_LOAD_STOP,
[email protected]ad50def52011-10-19 23:17:07492 content::NotificationService::AllSources());
[email protected]86c008e82009-08-28 20:26:05493
[email protected]17c4f3c2009-07-04 16:36:25494 ExtensionProcessManager* manager =
[email protected]fb17ddc2013-02-07 07:09:36495 extensions::ExtensionSystem::Get(profile())->process_manager();
[email protected]d1fe1352012-04-26 00:47:32496 ExtensionProcessManager::ViewSet all_views = manager->GetAllViews();
497 for (ExtensionProcessManager::ViewSet::const_iterator iter =
498 all_views.begin();
499 iter != all_views.end();) {
500 if (!(*iter)->IsLoading()) {
[email protected]c290a6232009-09-25 17:45:16501 ++iter;
[email protected]bd618b4c2009-11-04 19:49:51502 } else {
[email protected]729eb632012-07-26 04:45:26503 content::RunMessageLoop();
[email protected]bd618b4c2009-11-04 19:49:51504
505 // Test activity may have modified the set of extension processes during
506 // message processing, so re-start the iteration to catch added/removed
507 // processes.
[email protected]d1fe1352012-04-26 00:47:32508 all_views = manager->GetAllViews();
509 iter = all_views.begin();
[email protected]bd618b4c2009-11-04 19:49:51510 }
[email protected]17c4f3c2009-07-04 16:36:25511 }
[email protected]17c4f3c2009-07-04 16:36:25512 return true;
513}
514
[email protected]f4ea11282009-10-14 00:19:31515bool ExtensionBrowserTest::WaitForExtensionInstall() {
516 int before = extension_installs_observed_;
[email protected]432115822011-07-10 15:52:27517 ui_test_utils::RegisterAndWait(this,
518 chrome::NOTIFICATION_EXTENSION_INSTALLED,
[email protected]ad50def52011-10-19 23:17:07519 content::NotificationService::AllSources());
[email protected]f4ea11282009-10-14 00:19:31520 return extension_installs_observed_ == (before + 1);
521}
522
523bool ExtensionBrowserTest::WaitForExtensionInstallError() {
524 int before = extension_installs_observed_;
[email protected]3e59bac2010-04-08 16:16:55525 ui_test_utils::RegisterAndWait(this,
[email protected]432115822011-07-10 15:52:27526 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
[email protected]ad50def52011-10-19 23:17:07527 content::NotificationService::AllSources());
[email protected]f4ea11282009-10-14 00:19:31528 return extension_installs_observed_ == before;
529}
530
[email protected]1eb175082010-02-10 09:26:16531void ExtensionBrowserTest::WaitForExtensionLoad() {
[email protected]432115822011-07-10 15:52:27532 ui_test_utils::RegisterAndWait(this, chrome::NOTIFICATION_EXTENSION_LOADED,
[email protected]ad50def52011-10-19 23:17:07533 content::NotificationService::AllSources());
[email protected]d1fe1352012-04-26 00:47:32534 WaitForExtensionViewsToLoad();
[email protected]1eb175082010-02-10 09:26:16535}
536
[email protected]bbcde9102012-03-25 22:40:49537bool ExtensionBrowserTest::WaitForExtensionLoadError() {
538 int before = extension_load_errors_observed_;
539 ui_test_utils::RegisterAndWait(this,
540 chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
541 content::NotificationService::AllSources());
542 return extension_load_errors_observed_ != before;
543}
544
[email protected]1eb175082010-02-10 09:26:16545bool ExtensionBrowserTest::WaitForExtensionCrash(
546 const std::string& extension_id) {
[email protected]06bdd2b2012-11-30 18:47:13547 ExtensionService* service = extensions::ExtensionSystem::Get(
[email protected]fb17ddc2013-02-07 07:09:36548 profile())->extension_service();
[email protected]1eb175082010-02-10 09:26:16549
550 if (!service->GetExtensionById(extension_id, true)) {
551 // The extension is already unloaded, presumably due to a crash.
552 return true;
553 }
[email protected]432115822011-07-10 15:52:27554 ui_test_utils::RegisterAndWait(
555 this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
[email protected]ad50def52011-10-19 23:17:07556 content::NotificationService::AllSources());
[email protected]1eb175082010-02-10 09:26:16557 return (service->GetExtensionById(extension_id, true) == NULL);
558}
559
[email protected]8c6af5b2012-06-15 20:10:26560bool ExtensionBrowserTest::WaitForCrxInstallerDone() {
561 int before = crx_installers_done_observed_;
562 ui_test_utils::RegisterAndWait(this,
563 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
564 content::NotificationService::AllSources());
565 return crx_installers_done_observed_ == (before + 1);
566}
567
[email protected]19da16a92012-05-23 17:11:29568void ExtensionBrowserTest::OpenWindow(content::WebContents* contents,
569 const GURL& url,
570 bool newtab_process_should_equal_opener,
571 content::WebContents** newtab_result) {
[email protected]a7fe9112012-07-20 02:34:45572 content::WindowedNotificationObserver observer(
[email protected]19da16a92012-05-23 17:11:29573 content::NOTIFICATION_LOAD_STOP,
574 content::NotificationService::AllSources());
[email protected]b6987e02013-01-04 18:30:43575 ASSERT_TRUE(content::ExecuteScript(contents,
576 "window.open('" + url.spec() + "');"));
[email protected]19da16a92012-05-23 17:11:29577
578 // The above window.open call is not user-initiated, so it will create
579 // a popup window instead of a new tab in current window.
580 // The stop notification will come from the new tab.
581 observer.Wait();
582 content::NavigationController* controller =
583 content::Source<content::NavigationController>(observer.source()).ptr();
584 content::WebContents* newtab = controller->GetWebContents();
585 ASSERT_TRUE(newtab);
586 EXPECT_EQ(url, controller->GetLastCommittedEntry()->GetURL());
587 if (newtab_process_should_equal_opener)
588 EXPECT_EQ(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
589 else
590 EXPECT_NE(contents->GetRenderProcessHost(), newtab->GetRenderProcessHost());
591
592 if (newtab_result)
593 *newtab_result = newtab;
594}
595
596void ExtensionBrowserTest::NavigateInRenderer(content::WebContents* contents,
597 const GURL& url) {
598 bool result = false;
[email protected]a7fe9112012-07-20 02:34:45599 content::WindowedNotificationObserver observer(
[email protected]19da16a92012-05-23 17:11:29600 content::NOTIFICATION_LOAD_STOP,
601 content::NotificationService::AllSources());
[email protected]b6987e02013-01-04 18:30:43602 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
603 contents,
[email protected]06bc5d92013-01-02 22:44:13604 "window.addEventListener('unload', function() {"
605 " window.domAutomationController.send(true);"
606 "}, false);"
607 "window.location = '" + url.spec() + "';",
[email protected]19da16a92012-05-23 17:11:29608 &result));
609 ASSERT_TRUE(result);
610 observer.Wait();
611 EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL());
612}
613
[email protected]3a1dc572012-07-31 22:25:13614extensions::ExtensionHost* ExtensionBrowserTest::FindHostWithPath(
[email protected]fad73672012-06-15 23:26:06615 ExtensionProcessManager* manager,
616 const std::string& path,
617 int expected_hosts) {
[email protected]3a1dc572012-07-31 22:25:13618 extensions::ExtensionHost* host = NULL;
[email protected]fad73672012-06-15 23:26:06619 int num_hosts = 0;
620 ExtensionProcessManager::ExtensionHostSet background_hosts =
621 manager->background_hosts();
622 for (ExtensionProcessManager::const_iterator iter = background_hosts.begin();
623 iter != background_hosts.end(); ++iter) {
624 if ((*iter)->GetURL().path() == path) {
625 EXPECT_FALSE(host);
626 host = *iter;
627 }
628 num_hosts++;
629 }
630 EXPECT_EQ(expected_hosts, num_hosts);
631 return host;
632}
633
[email protected]6c2381d2011-10-19 02:52:53634void ExtensionBrowserTest::Observe(
635 int type,
636 const content::NotificationSource& source,
637 const content::NotificationDetails& details) {
[email protected]432115822011-07-10 15:52:27638 switch (type) {
639 case chrome::NOTIFICATION_EXTENSION_LOADED:
[email protected]6c2381d2011-10-19 02:52:53640 last_loaded_extension_id_ =
641 content::Details<const Extension>(details).ptr()->id();
[email protected]e99a88e92010-10-22 18:08:03642 VLOG(1) << "Got EXTENSION_LOADED notification.";
[email protected]7d11cee2009-07-08 02:40:42643 MessageLoopForUI::current()->Quit();
644 break;
645
[email protected]84f4dc02011-11-29 21:58:26646 case chrome::NOTIFICATION_CRX_INSTALLER_DONE:
647 VLOG(1) << "Got CRX_INSTALLER_DONE notification.";
648 {
649 const Extension* extension =
650 content::Details<const Extension>(details).ptr();
651 if (extension)
652 last_loaded_extension_id_ = extension->id();
653 else
654 last_loaded_extension_id_ = "";
655 }
[email protected]8c6af5b2012-06-15 20:10:26656 ++crx_installers_done_observed_;
[email protected]0c6da502009-08-14 22:32:39657 MessageLoopForUI::current()->Quit();
658 break;
659
[email protected]432115822011-07-10 15:52:27660 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
[email protected]e99a88e92010-10-22 18:08:03661 VLOG(1) << "Got EXTENSION_INSTALLED notification.";
[email protected]f4ea11282009-10-14 00:19:31662 ++extension_installs_observed_;
663 MessageLoopForUI::current()->Quit();
664 break;
665
[email protected]432115822011-07-10 15:52:27666 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR:
[email protected]e99a88e92010-10-22 18:08:03667 VLOG(1) << "Got EXTENSION_INSTALL_ERROR notification.";
[email protected]f4ea11282009-10-14 00:19:31668 MessageLoopForUI::current()->Quit();
669 break;
670
[email protected]432115822011-07-10 15:52:27671 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED:
[email protected]e99a88e92010-10-22 18:08:03672 VLOG(1) << "Got EXTENSION_PROCESS_TERMINATED notification.";
[email protected]1eb175082010-02-10 09:26:16673 MessageLoopForUI::current()->Quit();
674 break;
675
[email protected]bbcde9102012-03-25 22:40:49676 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR:
677 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification.";
678 ++extension_load_errors_observed_;
679 MessageLoopForUI::current()->Quit();
680 break;
681
[email protected]432115822011-07-10 15:52:27682 case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED: {
[email protected]d818e07f2010-02-10 13:10:03683 LocationBarTesting* location_bar =
684 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]e99a88e92010-10-22 18:08:03685 VLOG(1) << "Got EXTENSION_PAGE_ACTION_COUNT_CHANGED notification. Number "
686 "of page actions: " << location_bar->PageActionCount();
[email protected]d818e07f2010-02-10 13:10:03687 if (location_bar->PageActionCount() ==
688 target_page_action_count_) {
689 target_page_action_count_ = -1;
690 MessageLoopForUI::current()->Quit();
691 }
692 break;
693 }
694
[email protected]432115822011-07-10 15:52:27695 case chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED: {
[email protected]d818e07f2010-02-10 13:10:03696 LocationBarTesting* location_bar =
697 browser()->window()->GetLocationBar()->GetLocationBarForTesting();
[email protected]e99a88e92010-10-22 18:08:03698 VLOG(1) << "Got EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED notification. "
699 "Number of visible page actions: "
700 << location_bar->PageActionVisibleCount();
[email protected]d818e07f2010-02-10 13:10:03701 if (location_bar->PageActionVisibleCount() ==
702 target_visible_page_action_count_) {
703 target_visible_page_action_count_ = -1;
704 MessageLoopForUI::current()->Quit();
705 }
706 break;
707 }
708
[email protected]d1fe1352012-04-26 00:47:32709 case content::NOTIFICATION_LOAD_STOP:
710 VLOG(1) << "Got LOAD_STOP notification.";
711 MessageLoopForUI::current()->Quit();
712 break;
713
[email protected]17c4f3c2009-07-04 16:36:25714 default:
715 NOTREACHED();
716 break;
717 }
[email protected]1bd54132009-06-11 00:05:34718}