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