extension_management_browsertest.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2009 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/ref_counted.h" 6#include "chrome/browser/browser.h" 7#include "chrome/browser/renderer_host/render_view_host.h" 8#include "chrome/browser/extensions/autoupdate_interceptor.h" 9#include "chrome/browser/extensions/extension_browsertest.h" 10#include "chrome/browser/extensions/extension_host.h" 11#include "chrome/browser/extensions/extensions_service.h" 12#include "chrome/browser/extensions/extension_test_message_listener.h" 13#include "chrome/browser/extensions/extension_updater.h" 14#include "chrome/browser/profile.h" 15#include "chrome/common/url_constants.h" 16#include "chrome/test/ui_test_utils.h" 17 18class ExtensionManagementTest : public ExtensionBrowserTest { 19 protected: 20 // Helper method that returns whether the extension is at the given version. 21 // This calls version(), which must be defined in the extension's bg page, 22 // as well as asking the extension itself. 23 // 24 // Note that 'version' here means something different than the version field 25 // in the extension's manifest. We use the version as reported by the 26 // background page to test how overinstalling crx files with the same 27 // manifest version works. 28 bool IsExtensionAtVersion(Extension* extension, 29 const std::string& expected_version) { 30 // Test that the extension's version from the manifest and reported by the 31 // background page is correct. This is to ensure that the processes are in 32 // sync with the Extension. 33 ExtensionProcessManager* manager = browser()->profile()-> 34 GetExtensionProcessManager(); 35 ExtensionHost* ext_host = manager->GetBackgroundHostForExtension(extension); 36 EXPECT_TRUE(ext_host); 37 if (!ext_host) 38 return false; 39 40 std::string version_from_bg; 41 bool exec = ui_test_utils::ExecuteJavaScriptAndExtractString( 42 ext_host->render_view_host(), L"", L"version()", &version_from_bg); 43 EXPECT_TRUE(exec); 44 if (!exec) 45 return false; 46 47 if (version_from_bg != expected_version || 48 extension->VersionString() != expected_version) 49 return false; 50 return true; 51 } 52 53 // Helper method that installs a low permission extension then updates 54 // to the second version requiring increased permissions. Returns whether 55 // the operation was completed successfully. 56 bool InstallAndUpdateIncreasingPermissionsExtension() { 57 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 58 size_t size_before = service->extensions()->size(); 59 60 // Install the initial version, which should happen just fine. 61 if (!InstallExtension( 62 test_data_dir_.AppendASCII("permissions-low-v1.crx"), 1)) 63 return false; 64 65 // Upgrade to a version that wants more permissions. We should disable the 66 // extension and prompt the user to reenable. 67 if (service->extensions()->size() != size_before + 1) 68 return false; 69 if (!UpdateExtension( 70 service->extensions()->at(size_before)->id(), 71 test_data_dir_.AppendASCII("permissions-high-v2.crx"), -1)) 72 return false; 73 EXPECT_EQ(size_before, service->extensions()->size()); 74 if (service->disabled_extensions()->size() != 1u) 75 return false; 76 return true; 77 } 78}; 79 80// Tests that installing the same version overwrites. 81IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallSameVersion) { 82 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 83 const size_t size_before = service->extensions()->size(); 84 ASSERT_TRUE(InstallExtension( 85 test_data_dir_.AppendASCII("install/install.crx"), 1)); 86 FilePath old_path = service->extensions()->back()->path(); 87 88 // Install an extension with the same version. The previous install should be 89 // overwritten. 90 ASSERT_TRUE(InstallExtension( 91 test_data_dir_.AppendASCII("install/install_same_version.crx"), 0)); 92 FilePath new_path = service->extensions()->back()->path(); 93 94 EXPECT_FALSE(IsExtensionAtVersion(service->extensions()->at(size_before), 95 "1.0")); 96 EXPECT_NE(old_path.value(), new_path.value()); 97} 98 99IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallOlderVersion) { 100 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 101 const size_t size_before = service->extensions()->size(); 102 ASSERT_TRUE(InstallExtension( 103 test_data_dir_.AppendASCII("install/install.crx"), 1)); 104 ASSERT_TRUE(InstallExtension( 105 test_data_dir_.AppendASCII("install/install_older_version.crx"), 0)); 106 EXPECT_TRUE(IsExtensionAtVersion(service->extensions()->at(size_before), 107 "1.0")); 108} 109 110IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallThenCancel) { 111 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 112 const size_t size_before = service->extensions()->size(); 113 ASSERT_TRUE(InstallExtension( 114 test_data_dir_.AppendASCII("install/install.crx"), 1)); 115 116 // Cancel this install. 117 StartInstallButCancel(test_data_dir_.AppendASCII("install/install_v2.crx")); 118 EXPECT_TRUE(IsExtensionAtVersion(service->extensions()->at(size_before), 119 "1.0")); 120} 121 122#if defined(OS_MACOSX) 123// See http://crbug.com/46097 124#define MAYBE_Incognito FLAKY_Incognito 125#else 126#define MAYBE_Incognito Incognito 127#endif 128// Tests that installing and uninstalling extensions don't crash with an 129// incognito window open. 130IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_Incognito) { 131 // Open an incognito window to the extensions management page. We just 132 // want to make sure that we don't crash while playing with extensions when 133 // this guy is around. 134 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), 135 GURL(chrome::kChromeUIExtensionsURL)); 136 137 ASSERT_TRUE(InstallExtension(test_data_dir_.AppendASCII("good.crx"), 1)); 138 UninstallExtension("ldnnhddmnhbkjipkidpdiheffobcpfmf"); 139} 140 141// Tests the process of updating an extension to one that requires higher 142// permissions. 143IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, UpdatePermissions) { 144 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 145 ASSERT_TRUE(InstallAndUpdateIncreasingPermissionsExtension()); 146 const size_t size_before = service->extensions()->size(); 147 148 // Now try reenabling it. 149 service->EnableExtension(service->disabled_extensions()->at(0)->id()); 150 EXPECT_EQ(size_before + 1, service->extensions()->size()); 151 EXPECT_EQ(0u, service->disabled_extensions()->size()); 152} 153 154// Tests that we can uninstall a disabled extension. 155IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, UninstallDisabled) { 156 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 157 ASSERT_TRUE(InstallAndUpdateIncreasingPermissionsExtension()); 158 const size_t size_before = service->extensions()->size(); 159 160 // Now try uninstalling it. 161 UninstallExtension(service->disabled_extensions()->at(0)->id()); 162 EXPECT_EQ(size_before, service->extensions()->size()); 163 EXPECT_EQ(0u, service->disabled_extensions()->size()); 164} 165 166// Tests that disabling and re-enabling an extension works. 167IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, DisableEnable) { 168 ExtensionProcessManager* manager = browser()->profile()-> 169 GetExtensionProcessManager(); 170 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 171 const size_t size_before = service->extensions()->size(); 172 173 // Load an extension, expect the background page to be available. 174 ASSERT_TRUE(LoadExtension( 175 test_data_dir_.AppendASCII("good").AppendASCII("Extensions") 176 .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa") 177 .AppendASCII("1.0"))); 178 ASSERT_EQ(size_before + 1, service->extensions()->size()); 179 EXPECT_EQ(0u, service->disabled_extensions()->size()); 180 Extension* extension = service->extensions()->at(size_before); 181 EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension)); 182 ASSERT_TRUE(service->HasInstalledExtensions()); 183 184 // After disabling, the background page should go away. 185 service->DisableExtension("bjafgdebaacbbbecmhlhpofkepfkgcpa"); 186 EXPECT_EQ(size_before, service->extensions()->size()); 187 EXPECT_EQ(1u, service->disabled_extensions()->size()); 188 EXPECT_FALSE(manager->GetBackgroundHostForExtension(extension)); 189 ASSERT_TRUE(service->HasInstalledExtensions()); 190 191 // And bring it back. 192 service->EnableExtension("bjafgdebaacbbbecmhlhpofkepfkgcpa"); 193 EXPECT_EQ(size_before + 1, service->extensions()->size()); 194 EXPECT_EQ(0u, service->disabled_extensions()->size()); 195 EXPECT_TRUE(manager->GetBackgroundHostForExtension(extension)); 196 ASSERT_TRUE(service->HasInstalledExtensions()); 197} 198 199// Tests extension autoupdate. 200IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, AutoUpdate) { 201 FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); 202 // Note: This interceptor gets requests on the IO thread. 203 scoped_refptr<AutoUpdateInterceptor> interceptor(new AutoUpdateInterceptor()); 204 URLFetcher::enable_interception_for_tests(true); 205 206 interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest", 207 basedir.AppendASCII("manifest_v2.xml")); 208 interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v2.crx", 209 basedir.AppendASCII("v2.crx")); 210 211 // Install version 1 of the extension. 212 ExtensionTestMessageListener listener1("v1 installed"); 213 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 214 const size_t size_before = service->extensions()->size(); 215 ASSERT_TRUE(service->disabled_extensions()->empty()); 216 ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v1.crx"), 1)); 217 listener1.WaitUntilSatisfied(); 218 const ExtensionList* extensions = service->extensions(); 219 ASSERT_EQ(size_before + 1, extensions->size()); 220 ASSERT_TRUE(service->HasInstalledExtensions()); 221 ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", 222 extensions->at(size_before)->id()); 223 ASSERT_EQ("1.0", extensions->at(size_before)->VersionString()); 224 225 // We don't want autoupdate blacklist checks. 226 service->updater()->set_blacklist_checks_enabled(false); 227 228 // Run autoupdate and make sure version 2 of the extension was installed. 229 ExtensionTestMessageListener listener2("v2 installed"); 230 service->updater()->CheckNow(); 231 ASSERT_TRUE(WaitForExtensionInstall()); 232 listener2.WaitUntilSatisfied(); 233 extensions = service->extensions(); 234 ASSERT_EQ(size_before + 1, extensions->size()); 235 ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", 236 extensions->at(size_before)->id()); 237 ASSERT_EQ("2.0", extensions->at(size_before)->VersionString()); 238 239 // Now try doing an update to version 3, which has been incorrectly 240 // signed. This should fail. 241 interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest", 242 basedir.AppendASCII("manifest_v3.xml")); 243 interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v3.crx", 244 basedir.AppendASCII("v3.crx")); 245 246 service->updater()->CheckNow(); 247 ASSERT_TRUE(WaitForExtensionInstallError()); 248 249 // Make sure the extension state is the same as before. 250 extensions = service->extensions(); 251 ASSERT_EQ(size_before + 1, extensions->size()); 252 ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", 253 extensions->at(size_before)->id()); 254 ASSERT_EQ("2.0", extensions->at(size_before)->VersionString()); 255} 256 257IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalUrlUpdate) { 258 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 259 const char* kExtensionId = "ogjcoiohnmldgjemafoockdghcjciccf"; 260 // We don't want autoupdate blacklist checks. 261 service->updater()->set_blacklist_checks_enabled(false); 262 263 FilePath basedir = test_data_dir_.AppendASCII("autoupdate"); 264 265 // Note: This interceptor gets requests on the IO thread. 266 scoped_refptr<AutoUpdateInterceptor> interceptor(new AutoUpdateInterceptor()); 267 URLFetcher::enable_interception_for_tests(true); 268 269 interceptor->SetResponseOnIOThread("http://localhost/autoupdate/manifest", 270 basedir.AppendASCII("manifest_v2.xml")); 271 interceptor->SetResponseOnIOThread("http://localhost/autoupdate/v2.crx", 272 basedir.AppendASCII("v2.crx")); 273 274 const size_t size_before = service->extensions()->size(); 275 ASSERT_TRUE(service->disabled_extensions()->empty()); 276 277 // The code that reads external_extensions.json uses this method to inform 278 // the ExtensionsService of an extension to download. Using the real code 279 // is race-prone, because instantating the ExtensionService starts a read 280 // of external_extensions.json before this test function starts. 281 service->AddPendingExtensionFromExternalUpdateUrl( 282 kExtensionId, GURL("http://localhost/autoupdate/manifest")); 283 284 // Run autoupdate and make sure version 2 of the extension was installed. 285 service->updater()->CheckNow(); 286 ASSERT_TRUE(WaitForExtensionInstall()); 287 const ExtensionList* extensions = service->extensions(); 288 ASSERT_EQ(size_before + 1, extensions->size()); 289 ASSERT_EQ(kExtensionId, extensions->at(size_before)->id()); 290 ASSERT_EQ("2.0", extensions->at(size_before)->VersionString()); 291 292 // Uninstalling the extension should set a pref that keeps the extension from 293 // being installed again the next time external_extensions.json is read. 294 295 UninstallExtension(kExtensionId); 296 297 std::set<std::string> killed_ids; 298 service->extension_prefs()->GetKilledExtensionIds(&killed_ids); 299 EXPECT_TRUE(killed_ids.end() != killed_ids.find(kExtensionId)) 300 << "Uninstalling should set kill bit on externaly installed extension."; 301 302 // Installing from non-external source. 303 ASSERT_TRUE(InstallExtension(basedir.AppendASCII("v2.crx"), 1)); 304 305 killed_ids.clear(); 306 service->extension_prefs()->GetKilledExtensionIds(&killed_ids); 307 EXPECT_TRUE(killed_ids.end() == killed_ids.find(kExtensionId)) 308 << "Reinstalling should clear the kill bit."; 309 310 // Uninstalling from a non-external source should not set the kill bit. 311 UninstallExtension(kExtensionId); 312 313 killed_ids.clear(); 314 service->extension_prefs()->GetKilledExtensionIds(&killed_ids); 315 EXPECT_TRUE(killed_ids.end() == killed_ids.find(kExtensionId)) 316 << "Uninstalling non-external extension should not set kill bit."; 317} 318