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 "base/bind.h" 6 #include "base/bind_helpers.h" 7 #include "base/memory/ref_counted.h" 8 #include "base/prefs/pref_service.h" 9 #include "base/prefs/scoped_user_pref_update.h" 10 #include "base/stl_util.h" 11 #include "chrome/browser/chrome_notification_types.h" 12 #include "chrome/browser/extensions/extension_browsertest.h" 13 #include "chrome/browser/extensions/extension_host.h" 14 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/extensions/extension_system.h" 16 #include "chrome/browser/extensions/extension_test_message_listener.h" 17 #include "chrome/browser/extensions/external_policy_loader.h" 18 #include "chrome/browser/extensions/updater/extension_downloader.h" 19 #include "chrome/browser/extensions/updater/extension_updater.h" 20 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/ui/browser.h" 22 #include "chrome/common/pref_names.h" 23 #include "chrome/common/url_constants.h" 24 #include "chrome/test/base/ui_test_utils.h" 25 #include "content/public/browser/notification_service.h" 26 #include "content/public/browser/render_view_host.h" 27 #include "content/public/test/browser_test_utils.h" 28 #include "content/test/net/url_request_prepackaged_interceptor.h" 29 #include "net/url_request/url_fetcher.h" 30 31 using extensions::Extension; 32 using extensions::Manifest; 33 34 class ExtensionManagementTest : public ExtensionBrowserTest { 35 protected: 36 // Helper method that returns whether the extension is at the given version. 37 // This calls version(), which must be defined in the extension's bg page, 38 // as well as asking the extension itself. 39 // 40 // Note that 'version' here means something different than the version field 41 // in the extension's manifest. We use the version as reported by the 42 // background page to test how overinstalling crx files with the same 43 // manifest version works. 44 bool IsExtensionAtVersion(const Extension* extension, 45 const std::string& expected_version) { 46 // Test that the extension's version from the manifest and reported by the 47 // background page is correct. This is to ensure that the processes are in 48 // sync with the Extension. 49 extensions::ProcessManager* manager = 50 extensions::ExtensionSystem::Get(browser()->profile())-> 51 process_manager(); 52 extensions::ExtensionHost* ext_host = 53 manager->GetBackgroundHostForExtension(extension->id()); 54 EXPECT_TRUE(ext_host); 55 if (!ext_host) 56 return false; 57 58 std::string version_from_bg; 59 bool exec = content::ExecuteScriptAndExtractString( 60 ext_host->render_view_host(), "version()", &version_from_bg); 61 EXPECT_TRUE(exec); 62 if (!exec) 63 return false; 64 65 if (version_from_bg != expected_version || 66 extension->VersionString() != expected_version) 67 return false; 68 return true; 69 } 70 }; 71 72 #if defined(OS_LINUX) 73 // Times out sometimes on Linux. http://crbug.com/89727 74 #define MAYBE_InstallSameVersion DISABLED_InstallSameVersion 75 #else 76 #define MAYBE_InstallSameVersion InstallSameVersion 77 #endif 78 79 // Tests that installing the same version overwrites. 80 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_InstallSameVersion) { 81 const Extension* extension = InstallExtension( 82 test_data_dir_.AppendASCII("install/install.crx"), 1); 83 ASSERT_TRUE(extension); 84 base::FilePath old_path = extension->path(); 85 86 // Install an extension with the same version. The previous install should be 87 // overwritten. 88 extension = InstallExtension( 89 test_data_dir_.AppendASCII("install/install_same_version.crx"), 0); 90 ASSERT_TRUE(extension); 91 base::FilePath new_path = extension->path(); 92 93 EXPECT_FALSE(IsExtensionAtVersion(extension, "1.0")); 94 EXPECT_NE(old_path.value(), new_path.value()); 95 } 96 97 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallOlderVersion) { 98 const Extension* extension = InstallExtension( 99 test_data_dir_.AppendASCII("install/install.crx"), 1); 100 ASSERT_TRUE(extension); 101 ASSERT_FALSE(InstallExtension( 102 test_data_dir_.AppendASCII("install/install_older_version.crx"), 0)); 103 EXPECT_TRUE(IsExtensionAtVersion(extension, "1.0")); 104 } 105 106 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallThenCancel) { 107 const Extension* extension = InstallExtension( 108 test_data_dir_.AppendASCII("install/install.crx"), 1); 109 ASSERT_TRUE(extension); 110 111 // Cancel this install. 112 ASSERT_FALSE(StartInstallButCancel( 113 test_data_dir_.AppendASCII("install/install_v2.crx"))); 114 EXPECT_TRUE(IsExtensionAtVersion(extension, "1.0")); 115 } 116 117 #if defined(OS_WIN) 118 // http://crbug.com/141913 119 #define MAYBE_InstallRequiresConfirm DISABLED_InstallRequiresConfirm 120 #else 121 #define MAYBE_InstallRequiresConfirm InstallRequiresConfirm 122 #endif 123 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_InstallRequiresConfirm) { 124 // Installing the extension without an auto confirming UI should result in 125 // it being disabled, since good.crx has permissions that require approval. 126 ExtensionService* service = extensions::ExtensionSystem::Get( 127 browser()->profile())->extension_service(); 128 std::string id = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; 129 ASSERT_FALSE(InstallExtension(test_data_dir_.AppendASCII("good.crx"), 0)); 130 ASSERT_TRUE(service->GetExtensionById(id, true)); 131 UninstallExtension(id); 132 133 // And the install should succeed when the permissions are accepted. 134 ASSERT_TRUE(InstallExtensionWithUIAutoConfirm( 135 test_data_dir_.AppendASCII("good.crx"), 1, browser())); 136 UninstallExtension(id); 137 } 138 139 // Tests that disabling and re-enabling an extension works. 140 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, DisableEnable) { 141 extensions::ProcessManager* manager = 142 extensions::ExtensionSystem::Get(browser()->profile())->process_manager(); 143 ExtensionService* service = extensions::ExtensionSystem::Get( 144 browser()->profile())->extension_service(); 145 const size_t size_before = service->extensions()->size(); 146 147 // Load an extension, expect the background page to be available. 148 std::string extension_id = "bjafgdebaacbbbecmhlhpofkepfkgcpa"; 149 ASSERT_TRUE(LoadExtension( 150 test_data_dir_.AppendASCII("good").AppendASCII("Extensions") 151 .AppendASCII(extension_id) 152 .AppendASCII("1.0"))); 153 ASSERT_EQ(size_before + 1, service->extensions()->size()); 154 EXPECT_EQ(0u, service->disabled_extensions()->size()); 155 EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension_id)); 156 157 // After disabling, the background page should go away. 158 DisableExtension(extension_id); 159 EXPECT_EQ(size_before, service->extensions()->size()); 160 EXPECT_EQ(1u, service->disabled_extensions()->size()); 161 EXPECT_FALSE(manager->GetBackgroundHostForExtension(extension_id)); 162 163 // And bring it back. 164 EnableExtension(extension_id); 165 EXPECT_EQ(size_before + 1, service->extensions()->size()); 166 EXPECT_EQ(0u, service->disabled_extensions()->size()); 167 EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension_id)); 168 } 169 170 // Used for testing notifications sent during extension updates. 171 class NotificationListener : public content::NotificationObserver { 172 public: 173 NotificationListener() : started_(false), finished_(false) { 174 int types[] = { 175 chrome::NOTIFICATION_EXTENSION_UPDATING_STARTED, 176 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND 177 }; 178 for (size_t i = 0; i < arraysize(types); i++) { 179 registrar_.Add( 180 this, types[i], content::NotificationService::AllSources()); 181 } 182 } 183 virtual ~NotificationListener() {} 184 185 bool started() { return started_; } 186 187 bool finished() { return finished_; } 188 189 const std::set<std::string>& updates() { return updates_; } 190 191 void Reset() { 192 started_ = false; 193 finished_ = false; 194 updates_.clear(); 195 } 196 197 // Implements content::NotificationObserver interface. 198 virtual void Observe(int type, 199 const content::NotificationSource& source, 200 const content::NotificationDetails& details) OVERRIDE { 201 switch (type) { 202 case chrome::NOTIFICATION_EXTENSION_UPDATING_STARTED: { 203 EXPECT_FALSE(started_); 204 started_ = true; 205 break; 206 } 207 case chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND: { 208 const std::string& id = 209 content::Details<extensions::UpdateDetails>(details)->id; 210 updates_.insert(id); 211 break; 212 } 213 default: 214 NOTREACHED(); 215 } 216 } 217 218 void OnFinished() { 219 EXPECT_FALSE(finished_); 220 finished_ = true; 221 } 222 223 private: 224 content::NotificationRegistrar registrar_; 225 226 // Did we see EXTENSION_UPDATING_STARTED? 227 bool started_; 228 229 // Did we see EXTENSION_UPDATING_FINISHED? 230 bool finished_; 231 232 // The set of extension id's we've seen via EXTENSION_UPDATE_FOUND. 233 std::set<std::string> updates_; 234 }; 235 236 #if defined(OS_WIN) 237 // Fails consistently on Windows XP, see: http://crbug.com/120640. 238 #define MAYBE_AutoUpdate DISABLED_AutoUpdate 239 #else 240 // See http://crbug.com/103371 and http://crbug.com/120640. 241 #if defined(ADDRESS_SANITIZER) 242 #define MAYBE_AutoUpdate DISABLED_AutoUpdate 243 #else 244 #define MAYBE_AutoUpdate AutoUpdate 245 #endif 246 #endif 247 248 // Tests extension autoupdate. 249 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_AutoUpdate) { 250 NotificationListener notification_listener; 251 base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); 252 // Note: This interceptor gets requests on the IO thread. 253 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 254 net::URLFetcher::SetEnableInterceptionForTests(true); 255 256 interceptor.SetResponseIgnoreQuery( 257 GURL("http://localhost/autoupdate/manifest"), 258 basedir.AppendASCII("manifest_v2.xml")); 259 interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"), 260 basedir.AppendASCII("v2.crx")); 261 262 // Install version 1 of the extension. 263 ExtensionTestMessageListener listener1("v1 installed", false); 264 ExtensionService* service = extensions::ExtensionSystem::Get( 265 browser()->profile())->extension_service(); 266 const size_t size_before = service->extensions()->size(); 267 ASSERT_TRUE(service->disabled_extensions()->is_empty()); 268 const Extension* extension = 269 InstallExtension(basedir.AppendASCII("v1.crx"), 1); 270 ASSERT_TRUE(extension); 271 listener1.WaitUntilSatisfied(); 272 ASSERT_EQ(size_before + 1, service->extensions()->size()); 273 ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extension->id()); 274 ASSERT_EQ("1.0", extension->VersionString()); 275 276 extensions::ExtensionUpdater::CheckParams params; 277 params.callback = 278 base::Bind(&NotificationListener::OnFinished, 279 base::Unretained(¬ification_listener)); 280 281 // Run autoupdate and make sure version 2 of the extension was installed. 282 ExtensionTestMessageListener listener2("v2 installed", false); 283 service->updater()->CheckNow(params); 284 ASSERT_TRUE(WaitForExtensionInstall()); 285 listener2.WaitUntilSatisfied(); 286 ASSERT_EQ(size_before + 1, service->extensions()->size()); 287 extension = service->GetExtensionById( 288 "ogjcoiohnmldgjemafoockdghcjciccf", false); 289 ASSERT_TRUE(extension); 290 ASSERT_EQ("2.0", extension->VersionString()); 291 ASSERT_TRUE(notification_listener.started()); 292 ASSERT_TRUE(notification_listener.finished()); 293 ASSERT_TRUE(ContainsKey(notification_listener.updates(), 294 "ogjcoiohnmldgjemafoockdghcjciccf")); 295 notification_listener.Reset(); 296 297 // Now try doing an update to version 3, which has been incorrectly 298 // signed. This should fail. 299 interceptor.SetResponseIgnoreQuery( 300 GURL("http://localhost/autoupdate/manifest"), 301 basedir.AppendASCII("manifest_v3.xml")); 302 interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v3.crx"), 303 basedir.AppendASCII("v3.crx")); 304 305 service->updater()->CheckNow(params); 306 ASSERT_TRUE(WaitForExtensionInstallError()); 307 ASSERT_TRUE(notification_listener.started()); 308 ASSERT_TRUE(notification_listener.finished()); 309 ASSERT_TRUE(ContainsKey(notification_listener.updates(), 310 "ogjcoiohnmldgjemafoockdghcjciccf")); 311 312 // Make sure the extension state is the same as before. 313 ASSERT_EQ(size_before + 1, service->extensions()->size()); 314 extension = service->GetExtensionById( 315 "ogjcoiohnmldgjemafoockdghcjciccf", false); 316 ASSERT_TRUE(extension); 317 ASSERT_EQ("2.0", extension->VersionString()); 318 } 319 320 #if defined(OS_WIN) 321 // Fails consistently on Windows XP, see: http://crbug.com/120640. 322 #define MAYBE_AutoUpdateDisabledExtensions DISABLED_AutoUpdateDisabledExtensions 323 #else 324 #if defined(ADDRESS_SANITIZER) 325 #define MAYBE_AutoUpdateDisabledExtensions DISABLED_AutoUpdateDisabledExtensions 326 #else 327 #define MAYBE_AutoUpdateDisabledExtensions AutoUpdateDisabledExtensions 328 #endif 329 #endif 330 331 // Tests extension autoupdate. 332 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, 333 MAYBE_AutoUpdateDisabledExtensions) { 334 NotificationListener notification_listener; 335 base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); 336 // Note: This interceptor gets requests on the IO thread. 337 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 338 net::URLFetcher::SetEnableInterceptionForTests(true); 339 340 interceptor.SetResponseIgnoreQuery( 341 GURL("http://localhost/autoupdate/manifest"), 342 basedir.AppendASCII("manifest_v2.xml")); 343 interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"), 344 basedir.AppendASCII("v2.crx")); 345 346 // Install version 1 of the extension. 347 ExtensionTestMessageListener listener1("v1 installed", false); 348 ExtensionService* service = extensions::ExtensionSystem::Get( 349 browser()->profile())->extension_service(); 350 const size_t enabled_size_before = service->extensions()->size(); 351 const size_t disabled_size_before = service->disabled_extensions()->size(); 352 const Extension* extension = 353 InstallExtension(basedir.AppendASCII("v1.crx"), 1); 354 ASSERT_TRUE(extension); 355 listener1.WaitUntilSatisfied(); 356 DisableExtension(extension->id()); 357 ASSERT_EQ(disabled_size_before + 1, service->disabled_extensions()->size()); 358 ASSERT_EQ(enabled_size_before, service->extensions()->size()); 359 ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extension->id()); 360 ASSERT_EQ("1.0", extension->VersionString()); 361 362 extensions::ExtensionUpdater::CheckParams params; 363 params.callback = 364 base::Bind(&NotificationListener::OnFinished, 365 base::Unretained(¬ification_listener)); 366 367 ExtensionTestMessageListener listener2("v2 installed", false); 368 // Run autoupdate and make sure version 2 of the extension was installed but 369 // is still disabled. 370 service->updater()->CheckNow(params); 371 ASSERT_TRUE(WaitForExtensionInstall()); 372 ASSERT_EQ(disabled_size_before + 1, service->disabled_extensions()->size()); 373 ASSERT_EQ(enabled_size_before, service->extensions()->size()); 374 extension = service->GetExtensionById( 375 "ogjcoiohnmldgjemafoockdghcjciccf", true); 376 ASSERT_TRUE(extension); 377 ASSERT_FALSE(service->GetExtensionById( 378 "ogjcoiohnmldgjemafoockdghcjciccf", false)); 379 ASSERT_EQ("2.0", extension->VersionString()); 380 381 // The extension should have not made the callback because it is disabled. 382 // When we enabled it, it should then make the callback. 383 ASSERT_FALSE(listener2.was_satisfied()); 384 EnableExtension(extension->id()); 385 listener2.WaitUntilSatisfied(); 386 ASSERT_TRUE(notification_listener.started()); 387 ASSERT_TRUE(notification_listener.finished()); 388 ASSERT_TRUE(ContainsKey(notification_listener.updates(), 389 "ogjcoiohnmldgjemafoockdghcjciccf")); 390 notification_listener.Reset(); 391 } 392 393 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalUrlUpdate) { 394 ExtensionService* service = extensions::ExtensionSystem::Get( 395 browser()->profile())->extension_service(); 396 const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf"; 397 extensions::ExtensionUpdater::CheckParams params; 398 399 base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); 400 401 // Note: This interceptor gets requests on the IO thread. 402 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 403 net::URLFetcher::SetEnableInterceptionForTests(true); 404 405 interceptor.SetResponseIgnoreQuery( 406 GURL("http://localhost/autoupdate/manifest"), 407 basedir.AppendASCII("manifest_v2.xml")); 408 interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"), 409 basedir.AppendASCII("v2.crx")); 410 411 const size_t size_before = service->extensions()->size(); 412 ASSERT_TRUE(service->disabled_extensions()->is_empty()); 413 414 extensions::PendingExtensionManager* pending_extension_manager = 415 service->pending_extension_manager(); 416 417 // The code that reads external_extensions.json uses this method to inform 418 // the ExtensionService of an extension to download. Using the real code 419 // is race-prone, because instantating the ExtensionService starts a read 420 // of external_extensions.json before this test function starts. 421 422 EXPECT_TRUE(pending_extension_manager->AddFromExternalUpdateUrl( 423 kExtensionId, GURL("http://localhost/autoupdate/manifest"), 424 Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS, false)); 425 426 // Run autoupdate and make sure version 2 of the extension was installed. 427 service->updater()->CheckNow(params); 428 ASSERT_TRUE(WaitForExtensionInstall()); 429 ASSERT_EQ(size_before + 1, service->extensions()->size()); 430 const Extension* extension = service->GetExtensionById(kExtensionId, false); 431 ASSERT_TRUE(extension); 432 ASSERT_EQ("2.0", extension->VersionString()); 433 434 // Uninstalling the extension should set a pref that keeps the extension from 435 // being installed again the next time external_extensions.json is read. 436 437 UninstallExtension(kExtensionId); 438 439 extensions::ExtensionPrefs* extension_prefs = service->extension_prefs(); 440 EXPECT_TRUE(extension_prefs->IsExternalExtensionUninstalled(kExtensionId)) 441 << "Uninstalling should set kill bit on externaly installed extension."; 442 443 // Try to install the extension again from an external source. It should fail 444 // because of the killbit. 445 EXPECT_FALSE(pending_extension_manager->AddFromExternalUpdateUrl( 446 kExtensionId, GURL("http://localhost/autoupdate/manifest"), 447 Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS, false)); 448 EXPECT_FALSE(pending_extension_manager->IsIdPending(kExtensionId)) 449 << "External reinstall of a killed extension shouldn't work."; 450 EXPECT_TRUE(extension_prefs->IsExternalExtensionUninstalled(kExtensionId)) 451 << "External reinstall of a killed extension should leave it killed."; 452 453 // Installing from non-external source. 454 ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v2.crx"), 1)); 455 456 EXPECT_FALSE(extension_prefs->IsExternalExtensionUninstalled(kExtensionId)) 457 << "Reinstalling should clear the kill bit."; 458 459 // Uninstalling from a non-external source should not set the kill bit. 460 UninstallExtension(kExtensionId); 461 462 EXPECT_FALSE(extension_prefs->IsExternalExtensionUninstalled(kExtensionId)) 463 << "Uninstalling non-external extension should not set kill bit."; 464 } 465 466 namespace { 467 468 const char* kForceInstallNotEmptyHelp = 469 "A policy may already be controlling the list of force-installed " 470 "extensions. Please remove all policy settings from your computer " 471 "before running tests. E.g. from /etc/chromium/policies Linux or " 472 "from the registry on Windows, etc."; 473 474 } 475 476 // See http://crbug.com/57378 for flakiness details. 477 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) { 478 ExtensionService* service = extensions::ExtensionSystem::Get( 479 browser()->profile())->extension_service(); 480 const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf"; 481 482 base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); 483 484 // Note: This interceptor gets requests on the IO thread. 485 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 486 net::URLFetcher::SetEnableInterceptionForTests(true); 487 488 interceptor.SetResponseIgnoreQuery( 489 GURL("http://localhost/autoupdate/manifest"), 490 basedir.AppendASCII("manifest_v2.xml")); 491 interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"), 492 basedir.AppendASCII("v2.crx")); 493 494 const size_t size_before = service->extensions()->size(); 495 ASSERT_TRUE(service->disabled_extensions()->is_empty()); 496 497 PrefService* prefs = browser()->profile()->GetPrefs(); 498 const base::DictionaryValue* forcelist = 499 prefs->GetDictionary(prefs::kExtensionInstallForceList); 500 ASSERT_TRUE(forcelist->empty()) << kForceInstallNotEmptyHelp; 501 502 { 503 // Set the policy as a user preference and fire notification observers. 504 DictionaryPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList); 505 base::DictionaryValue* forcelist = pref_update.Get(); 506 extensions::ExternalPolicyLoader::AddExtension( 507 forcelist, kExtensionId, "http://localhost/autoupdate/manifest"); 508 } 509 510 // Check if the extension got installed. 511 ASSERT_TRUE(WaitForExtensionInstall()); 512 ASSERT_EQ(size_before + 1, service->extensions()->size()); 513 const Extension* extension = service->GetExtensionById(kExtensionId, false); 514 ASSERT_TRUE(extension); 515 ASSERT_EQ("2.0", extension->VersionString()); 516 EXPECT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD, extension->location()); 517 518 // Try to disable and uninstall the extension which should fail. 519 DisableExtension(kExtensionId); 520 EXPECT_EQ(size_before + 1, service->extensions()->size()); 521 EXPECT_EQ(0u, service->disabled_extensions()->size()); 522 UninstallExtension(kExtensionId); 523 EXPECT_EQ(size_before + 1, service->extensions()->size()); 524 EXPECT_EQ(0u, service->disabled_extensions()->size()); 525 526 // Now try to disable it through the management api, again failing. 527 ExtensionTestMessageListener listener1("ready", false); 528 ASSERT_TRUE(LoadExtension( 529 test_data_dir_.AppendASCII("management/uninstall_extension"))); 530 ASSERT_TRUE(listener1.WaitUntilSatisfied()); 531 EXPECT_EQ(size_before + 2, service->extensions()->size()); 532 EXPECT_EQ(0u, service->disabled_extensions()->size()); 533 534 // Check that emptying the list triggers uninstall. 535 prefs->ClearPref(prefs::kExtensionInstallForceList); 536 EXPECT_EQ(size_before + 1, service->extensions()->size()); 537 EXPECT_FALSE(service->GetExtensionById(kExtensionId, true)); 538 } 539 540 // See http://crbug.com/103371 and http://crbug.com/120640. 541 #if defined(ADDRESS_SANITIZER) || defined(OS_WIN) 542 #define MAYBE_PolicyOverridesUserInstall DISABLED_PolicyOverridesUserInstall 543 #else 544 #define MAYBE_PolicyOverridesUserInstall PolicyOverridesUserInstall 545 #endif 546 547 IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, 548 MAYBE_PolicyOverridesUserInstall) { 549 ExtensionService* service = extensions::ExtensionSystem::Get( 550 browser()->profile())->extension_service(); 551 const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf"; 552 extensions::ExtensionUpdater::CheckParams params; 553 service->updater()->set_default_check_params(params); 554 const size_t size_before = service->extensions()->size(); 555 base::FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); 556 ASSERT_TRUE(service->disabled_extensions()->is_empty()); 557 558 // Note: This interceptor gets requests on the IO thread. 559 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 560 net::URLFetcher::SetEnableInterceptionForTests(true); 561 562 interceptor.SetResponseIgnoreQuery( 563 GURL("http://localhost/autoupdate/manifest"), 564 basedir.AppendASCII("manifest_v2.xml")); 565 interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"), 566 basedir.AppendASCII("v2.crx")); 567 568 // Check that the policy is initially empty. 569 PrefService* prefs = browser()->profile()->GetPrefs(); 570 const base::DictionaryValue* forcelist = 571 prefs->GetDictionary(prefs::kExtensionInstallForceList); 572 ASSERT_TRUE(forcelist->empty()) << kForceInstallNotEmptyHelp; 573 574 // User install of the extension. 575 ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v2.crx"), 1)); 576 ASSERT_EQ(size_before + 1, service->extensions()->size()); 577 const Extension* extension = service->GetExtensionById(kExtensionId, false); 578 ASSERT_TRUE(extension); 579 EXPECT_EQ(Manifest::INTERNAL, extension->location()); 580 EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId)); 581 582 // Setup the force install policy. It should override the location. 583 { 584 DictionaryPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList); 585 extensions::ExternalPolicyLoader::AddExtension( 586 pref_update.Get(), kExtensionId, 587 "http://localhost/autoupdate/manifest"); 588 } 589 ASSERT_TRUE(WaitForExtensionInstall()); 590 ASSERT_EQ(size_before + 1, service->extensions()->size()); 591 extension = service->GetExtensionById(kExtensionId, false); 592 ASSERT_TRUE(extension); 593 EXPECT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD, extension->location()); 594 EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId)); 595 596 // Remove the policy, and verify that the extension was uninstalled. 597 // TODO(joaodasilva): it would be nicer if the extension was kept instead, 598 // and reverted location to INTERNAL or whatever it was before the policy 599 // was applied. 600 prefs->ClearPref(prefs::kExtensionInstallForceList); 601 ASSERT_EQ(size_before, service->extensions()->size()); 602 extension = service->GetExtensionById(kExtensionId, true); 603 EXPECT_FALSE(extension); 604 605 // User install again, but have it disabled too before setting the policy. 606 ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v2.crx"), 1)); 607 ASSERT_EQ(size_before + 1, service->extensions()->size()); 608 extension = service->GetExtensionById(kExtensionId, false); 609 ASSERT_TRUE(extension); 610 EXPECT_EQ(Manifest::INTERNAL, extension->location()); 611 EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId)); 612 EXPECT_TRUE(service->disabled_extensions()->is_empty()); 613 614 DisableExtension(kExtensionId); 615 EXPECT_EQ(1u, service->disabled_extensions()->size()); 616 extension = service->GetExtensionById(kExtensionId, true); 617 EXPECT_TRUE(extension); 618 EXPECT_FALSE(service->IsExtensionEnabled(kExtensionId)); 619 620 // Install the policy again. It should overwrite the extension's location, 621 // and force enable it too. 622 { 623 DictionaryPrefUpdate pref_update(prefs, prefs::kExtensionInstallForceList); 624 base::DictionaryValue* forcelist = pref_update.Get(); 625 extensions::ExternalPolicyLoader::AddExtension( 626 forcelist, kExtensionId, "http://localhost/autoupdate/manifest"); 627 } 628 ASSERT_TRUE(WaitForExtensionInstall()); 629 ASSERT_EQ(size_before + 1, service->extensions()->size()); 630 extension = service->GetExtensionById(kExtensionId, false); 631 ASSERT_TRUE(extension); 632 EXPECT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD, extension->location()); 633 EXPECT_TRUE(service->IsExtensionEnabled(kExtensionId)); 634 EXPECT_TRUE(service->disabled_extensions()->is_empty()); 635 } 636