extension_service_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 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 "chrome/browser/extensions/extension_service_unittest.h" 6 7#include <algorithm> 8#include <set> 9#include <vector> 10 11#include "base/basictypes.h" 12#include "base/command_line.h" 13#include "base/file_util.h" 14#include "base/json/json_reader.h" 15#include "base/message_loop.h" 16#include "base/path_service.h" 17#include "base/scoped_ptr.h" 18#include "base/stl_util-inl.h" 19#include "base/string16.h" 20#include "base/string_number_conversions.h" 21#include "base/string_util.h" 22#include "base/task.h" 23#include "base/utf_string_conversions.h" 24#include "base/version.h" 25#include "chrome/browser/extensions/crx_installer.h" 26#include "chrome/browser/extensions/extension_creator.h" 27#include "chrome/browser/extensions/extension_error_reporter.h" 28#include "chrome/browser/extensions/extension_service.h" 29#include "chrome/browser/extensions/extension_special_storage_policy.h" 30#include "chrome/browser/extensions/external_extension_provider_interface.h" 31#include "chrome/browser/extensions/external_extension_provider_impl.h" 32#include "chrome/browser/extensions/external_pref_extension_loader.h" 33#include "chrome/browser/extensions/pack_extension_job.cc" 34#include "chrome/browser/prefs/browser_prefs.h" 35#include "chrome/browser/prefs/pref_service_mock_builder.h" 36#include "chrome/browser/prefs/scoped_user_pref_update.h" 37#include "chrome/common/chrome_paths.h" 38#include "chrome/common/chrome_switches.h" 39#include "chrome/common/extensions/extension.h" 40#include "chrome/common/extensions/extension_constants.h" 41#include "chrome/common/extensions/extension_resource.h" 42#include "chrome/common/extensions/url_pattern.h" 43#include "chrome/common/json_value_serializer.h" 44#include "chrome/common/net/url_request_context_getter.h" 45#include "chrome/common/notification_registrar.h" 46#include "chrome/common/notification_service.h" 47#include "chrome/common/notification_type.h" 48#include "chrome/common/pref_names.h" 49#include "chrome/common/url_constants.h" 50#include "chrome/test/testing_profile.h" 51#include "content/browser/appcache/chrome_appcache_service.h" 52#include "content/browser/browser_thread.h" 53#include "content/browser/file_system/browser_file_system_helper.h" 54#include "content/browser/in_process_webkit/dom_storage_context.h" 55#include "content/browser/in_process_webkit/webkit_context.h" 56#include "googleurl/src/gurl.h" 57#include "net/base/cookie_monster.h" 58#include "net/base/cookie_options.h" 59#include "net/url_request/url_request_context.h" 60#include "testing/gtest/include/gtest/gtest.h" 61#include "testing/platform_test.h" 62#include "webkit/database/database_tracker.h" 63#include "webkit/database/database_util.h" 64 65namespace keys = extension_manifest_keys; 66 67namespace { 68 69// Extension ids used during testing. 70const char* const all_zero = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 71const char* const zero_n_one = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"; 72const char* const good0 = "behllobkkfkfnphdnhnkndlbkcpglgmj"; 73const char* const good1 = "hpiknbiabeeppbpihjehijgoemciehgk"; 74const char* const good2 = "bjafgdebaacbbbecmhlhpofkepfkgcpa"; 75const char* const good_crx = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; 76const char* const page_action = "obcimlgaoabeegjmmpldobjndiealpln"; 77const char* const theme_crx = "iamefpfkojoapidjnbafmgkgncegbkad"; 78const char* const theme2_crx = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; 79const char* const permissions_crx = "eagpmdpfmaekmmcejjbmjoecnejeiiin"; 80 81struct ExtensionsOrder { 82 bool operator()(const Extension* a, const Extension* b) { 83 return a->name() < b->name(); 84 } 85}; 86 87static std::vector<std::string> GetErrors() { 88 const std::vector<std::string>* errors = 89 ExtensionErrorReporter::GetInstance()->GetErrors(); 90 std::vector<std::string> ret_val; 91 92 for (std::vector<std::string>::const_iterator iter = errors->begin(); 93 iter != errors->end(); ++iter) { 94 if (iter->find(".svn") == std::string::npos) { 95 ret_val.push_back(*iter); 96 } 97 } 98 99 // The tests rely on the errors being in a certain order, which can vary 100 // depending on how filesystem iteration works. 101 std::stable_sort(ret_val.begin(), ret_val.end()); 102 103 return ret_val; 104} 105 106static void AddPattern(ExtensionExtent* extent, const std::string& pattern) { 107 int schemes = URLPattern::SCHEME_ALL; 108 extent->AddPattern(URLPattern(schemes, pattern)); 109} 110 111static void AssertEqualExtents(ExtensionExtent* extent1, 112 ExtensionExtent* extent2) { 113 std::vector<URLPattern> patterns1 = extent1->patterns(); 114 std::vector<URLPattern> patterns2 = extent2->patterns(); 115 std::set<std::string> strings1; 116 EXPECT_EQ(patterns1.size(), patterns2.size()); 117 118 for (size_t i = 0; i < patterns1.size(); ++i) 119 strings1.insert(patterns1.at(i).GetAsString()); 120 121 std::set<std::string> strings2; 122 for (size_t i = 0; i < patterns2.size(); ++i) 123 strings2.insert(patterns2.at(i).GetAsString()); 124 125 EXPECT_EQ(strings1, strings2); 126} 127 128} // namespace 129 130class MockExtensionProvider : public ExternalExtensionProviderInterface { 131 public: 132 explicit MockExtensionProvider( 133 VisitorInterface* visitor, 134 Extension::Location location) 135 : location_(location), visitor_(visitor), visit_count_(0) { 136 } 137 virtual ~MockExtensionProvider() {} 138 139 void UpdateOrAddExtension(const std::string& id, 140 const std::string& version, 141 const FilePath& path) { 142 extension_map_[id] = std::make_pair(version, path); 143 } 144 145 void RemoveExtension(const std::string& id) { 146 extension_map_.erase(id); 147 } 148 149 // ExternalExtensionProvider implementation: 150 virtual void VisitRegisteredExtension() const { 151 visit_count_++; 152 for (DataMap::const_iterator i = extension_map_.begin(); 153 i != extension_map_.end(); ++i) { 154 scoped_ptr<Version> version; 155 version.reset(Version::GetVersionFromString(i->second.first)); 156 157 visitor_->OnExternalExtensionFileFound( 158 i->first, version.get(), i->second.second, location_); 159 } 160 visitor_->OnExternalProviderReady(); 161 } 162 163 virtual bool HasExtension(const std::string& id) const { 164 return extension_map_.find(id) != extension_map_.end(); 165 } 166 167 virtual bool GetExtensionDetails(const std::string& id, 168 Extension::Location* location, 169 scoped_ptr<Version>* version) const { 170 DataMap::const_iterator it = extension_map_.find(id); 171 if (it == extension_map_.end()) 172 return false; 173 174 if (version) 175 version->reset(Version::GetVersionFromString(it->second.first)); 176 177 if (location) 178 *location = location_; 179 180 return true; 181 } 182 183 virtual bool IsReady() { 184 return true; 185 } 186 187 virtual void ServiceShutdown() { 188 } 189 190 int visit_count() const { return visit_count_; } 191 void set_visit_count(int visit_count) { 192 visit_count_ = visit_count; 193 } 194 195 private: 196 typedef std::map< std::string, std::pair<std::string, FilePath> > DataMap; 197 DataMap extension_map_; 198 Extension::Location location_; 199 VisitorInterface* visitor_; 200 201 // visit_count_ tracks the number of calls to VisitRegisteredExtension(). 202 // Mutable because it must be incremented on each call to 203 // VisitRegisteredExtension(), which must be a const method to inherit 204 // from the class being mocked. 205 mutable int visit_count_; 206 207 DISALLOW_COPY_AND_ASSIGN(MockExtensionProvider); 208}; 209 210class MockProviderVisitor 211 : public ExternalExtensionProviderInterface::VisitorInterface { 212 public: 213 214 // The provider will return |fake_base_path| from 215 // GetBaseCrxFilePath(). User can test the behavior with 216 // and without an empty path using this parameter. 217 explicit MockProviderVisitor(FilePath fake_base_path) 218 : ids_found_(0), 219 fake_base_path_(fake_base_path) { 220 } 221 222 int Visit(const std::string& json_data) { 223 // Give the test json file to the provider for parsing. 224 provider_.reset(new ExternalExtensionProviderImpl( 225 this, 226 new ExternalTestingExtensionLoader(json_data, fake_base_path_), 227 Extension::EXTERNAL_PREF, 228 Extension::EXTERNAL_PREF_DOWNLOAD)); 229 230 // We also parse the file into a dictionary to compare what we get back 231 // from the provider. 232 JSONStringValueSerializer serializer(json_data); 233 Value* json_value = serializer.Deserialize(NULL, NULL); 234 235 if (!json_value || !json_value->IsType(Value::TYPE_DICTIONARY)) { 236 NOTREACHED() << "Unable to deserialize json data"; 237 return -1; 238 } else { 239 DictionaryValue* external_extensions = 240 static_cast<DictionaryValue*>(json_value); 241 prefs_.reset(external_extensions); 242 } 243 244 // Reset our counter. 245 ids_found_ = 0; 246 // Ask the provider to look up all extensions and return them. 247 provider_->VisitRegisteredExtension(); 248 249 return ids_found_; 250 } 251 252 virtual void OnExternalExtensionFileFound(const std::string& id, 253 const Version* version, 254 const FilePath& path, 255 Extension::Location unused) { 256 ++ids_found_; 257 DictionaryValue* pref; 258 // This tests is to make sure that the provider only notifies us of the 259 // values we gave it. So if the id we doesn't exist in our internal 260 // dictionary then something is wrong. 261 EXPECT_TRUE(prefs_->GetDictionary(id, &pref)) 262 << "Got back ID (" << id.c_str() << ") we weren't expecting"; 263 264 EXPECT_TRUE(path.IsAbsolute()); 265 if (!fake_base_path_.empty()) 266 EXPECT_TRUE(fake_base_path_.IsParent(path)); 267 268 if (pref) { 269 EXPECT_TRUE(provider_->HasExtension(id)); 270 271 // Ask provider if the extension we got back is registered. 272 Extension::Location location = Extension::INVALID; 273 scoped_ptr<Version> v1; 274 FilePath crx_path; 275 276 EXPECT_TRUE(provider_->GetExtensionDetails(id, NULL, &v1)); 277 EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str()); 278 279 scoped_ptr<Version> v2; 280 EXPECT_TRUE(provider_->GetExtensionDetails(id, &location, &v2)); 281 EXPECT_STREQ(version->GetString().c_str(), v1->GetString().c_str()); 282 EXPECT_STREQ(version->GetString().c_str(), v2->GetString().c_str()); 283 EXPECT_EQ(Extension::EXTERNAL_PREF, location); 284 285 // Remove it so we won't count it ever again. 286 prefs_->Remove(id, NULL); 287 } 288 } 289 290 virtual void OnExternalExtensionUpdateUrlFound( 291 const std::string& id, const GURL& update_url, 292 Extension::Location location) { 293 ++ids_found_; 294 DictionaryValue* pref; 295 // This tests is to make sure that the provider only notifies us of the 296 // values we gave it. So if the id we doesn't exist in our internal 297 // dictionary then something is wrong. 298 EXPECT_TRUE(prefs_->GetDictionary(id, &pref)) 299 << L"Got back ID (" << id.c_str() << ") we weren't expecting"; 300 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, location); 301 302 if (pref) { 303 EXPECT_TRUE(provider_->HasExtension(id)); 304 305 // External extensions with update URLs do not have versions. 306 scoped_ptr<Version> v1; 307 Extension::Location location1 = Extension::INVALID; 308 EXPECT_TRUE(provider_->GetExtensionDetails(id, &location1, &v1)); 309 EXPECT_FALSE(v1.get()); 310 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, location1); 311 312 // Remove it so we won't count it again. 313 prefs_->Remove(id, NULL); 314 } 315 } 316 317 virtual void OnExternalProviderReady() { 318 EXPECT_TRUE(provider_->IsReady()); 319 } 320 321 private: 322 int ids_found_; 323 FilePath fake_base_path_; 324 scoped_ptr<ExternalExtensionProviderImpl> provider_; 325 scoped_ptr<DictionaryValue> prefs_; 326 327 DISALLOW_COPY_AND_ASSIGN(MockProviderVisitor); 328}; 329 330class ExtensionTestingProfile : public TestingProfile { 331 public: 332 ExtensionTestingProfile() : service_(NULL) { 333 } 334 335 void set_extensions_service(ExtensionService* service) { 336 service_ = service; 337 } 338 virtual ExtensionService* GetExtensionService() { return service_; } 339 340 virtual ChromeAppCacheService* GetAppCacheService() { 341 if (!appcache_service_) { 342 appcache_service_ = new ChromeAppCacheService; 343 BrowserThread::PostTask( 344 BrowserThread::IO, FROM_HERE, 345 NewRunnableMethod( 346 appcache_service_.get(), 347 &ChromeAppCacheService::InitializeOnIOThread, 348 GetPath(), IsOffTheRecord(), 349 make_scoped_refptr(GetHostContentSettingsMap()), 350 make_scoped_refptr(GetExtensionSpecialStoragePolicy()), 351 false)); 352 } 353 return appcache_service_; 354 } 355 356 virtual fileapi::FileSystemContext* GetFileSystemContext() { 357 if (!file_system_context_) 358 file_system_context_ = CreateFileSystemContext( 359 GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy()); 360 return file_system_context_; 361 } 362 363 private: 364 ExtensionService* service_; 365 scoped_refptr<ChromeAppCacheService> appcache_service_; 366 scoped_refptr<fileapi::FileSystemContext> file_system_context_; 367}; 368 369// Our message loop may be used in tests which require it to be an IO loop. 370ExtensionServiceTestBase::ExtensionServiceTestBase() 371 : total_successes_(0), 372 loop_(MessageLoop::TYPE_IO), 373 ui_thread_(BrowserThread::UI, &loop_), 374 db_thread_(BrowserThread::DB, &loop_), 375 webkit_thread_(BrowserThread::WEBKIT, &loop_), 376 file_thread_(BrowserThread::FILE, &loop_), 377 io_thread_(BrowserThread::IO, &loop_) { 378} 379 380ExtensionServiceTestBase::~ExtensionServiceTestBase() { 381 // Drop our reference to ExtensionService and TestingProfile, so that they 382 // can be destroyed while BrowserThreads and MessageLoop are still around 383 // (they are used in the destruction process). 384 service_ = NULL; 385 profile_.reset(NULL); 386 MessageLoop::current()->RunAllPending(); 387} 388 389void ExtensionServiceTestBase::InitializeExtensionService( 390 const FilePath& pref_file, const FilePath& extensions_install_dir) { 391 ExtensionTestingProfile* profile = new ExtensionTestingProfile(); 392 // Create a PrefService that only contains user defined preference values. 393 PrefService* prefs = 394 PrefServiceMockBuilder().WithUserFilePrefs(pref_file).Create(); 395 Profile::RegisterUserPrefs(prefs); 396 browser::RegisterUserPrefs(prefs); 397 profile->SetPrefService(prefs); 398 399 profile_.reset(profile); 400 401 service_ = profile->CreateExtensionService( 402 CommandLine::ForCurrentProcess(), 403 extensions_install_dir); 404 service_->set_extensions_enabled(true); 405 service_->set_show_extensions_prompts(false); 406 profile->set_extensions_service(service_.get()); 407 408 // When we start up, we want to make sure there is no external provider, 409 // since the ExtensionService on Windows will use the Registry as a default 410 // provider and if there is something already registered there then it will 411 // interfere with the tests. Those tests that need an external provider 412 // will register one specifically. 413 service_->ClearProvidersForTesting(); 414 415 total_successes_ = 0; 416} 417 418void ExtensionServiceTestBase::InitializeInstalledExtensionService( 419 const FilePath& prefs_file, const FilePath& source_install_dir) { 420 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 421 FilePath path_ = temp_dir_.path(); 422 path_ = path_.Append(FILE_PATH_LITERAL("TestingExtensionsPath")); 423 file_util::Delete(path_, true); 424 file_util::CreateDirectory(path_); 425 FilePath temp_prefs = path_.Append(FILE_PATH_LITERAL("Preferences")); 426 file_util::CopyFile(prefs_file, temp_prefs); 427 428 extensions_install_dir_ = path_.Append(FILE_PATH_LITERAL("Extensions")); 429 file_util::Delete(extensions_install_dir_, true); 430 file_util::CopyDirectory(source_install_dir, extensions_install_dir_, true); 431 432 InitializeExtensionService(temp_prefs, extensions_install_dir_); 433} 434 435void ExtensionServiceTestBase::InitializeEmptyExtensionService() { 436 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 437 FilePath path_ = temp_dir_.path(); 438 path_ = path_.Append(FILE_PATH_LITERAL("TestingExtensionsPath")); 439 file_util::Delete(path_, true); 440 file_util::CreateDirectory(path_); 441 FilePath prefs_filename = path_ 442 .Append(FILE_PATH_LITERAL("TestPreferences")); 443 extensions_install_dir_ = path_.Append(FILE_PATH_LITERAL("Extensions")); 444 file_util::Delete(extensions_install_dir_, true); 445 file_util::CreateDirectory(extensions_install_dir_); 446 447 InitializeExtensionService(prefs_filename, extensions_install_dir_); 448} 449 450// static 451void ExtensionServiceTestBase::SetUpTestCase() { 452 ExtensionErrorReporter::Init(false); // no noisy errors 453} 454 455void ExtensionServiceTestBase::SetUp() { 456 ExtensionErrorReporter::GetInstance()->ClearErrors(); 457} 458 459class ExtensionServiceTest 460 : public ExtensionServiceTestBase, public NotificationObserver { 461 public: 462 ExtensionServiceTest() : installed_(NULL) { 463 registrar_.Add(this, NotificationType::EXTENSION_LOADED, 464 NotificationService::AllSources()); 465 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, 466 NotificationService::AllSources()); 467 registrar_.Add(this, NotificationType::EXTENSION_INSTALLED, 468 NotificationService::AllSources()); 469 registrar_.Add(this, NotificationType::THEME_INSTALLED, 470 NotificationService::AllSources()); 471 } 472 473 virtual void Observe(NotificationType type, 474 const NotificationSource& source, 475 const NotificationDetails& details) { 476 switch (type.value) { 477 case NotificationType::EXTENSION_LOADED: { 478 const Extension* extension = Details<const Extension>(details).ptr(); 479 loaded_.push_back(make_scoped_refptr(extension)); 480 // The tests rely on the errors being in a certain order, which can vary 481 // depending on how filesystem iteration works. 482 std::stable_sort(loaded_.begin(), loaded_.end(), ExtensionsOrder()); 483 break; 484 } 485 486 case NotificationType::EXTENSION_UNLOADED: { 487 const Extension* e = 488 Details<UnloadedExtensionInfo>(details)->extension; 489 unloaded_id_ = e->id(); 490 ExtensionList::iterator i = 491 std::find(loaded_.begin(), loaded_.end(), e); 492 // TODO(erikkay) fix so this can be an assert. Right now the tests 493 // are manually calling clear() on loaded_, so this isn't doable. 494 if (i == loaded_.end()) 495 return; 496 loaded_.erase(i); 497 break; 498 } 499 case NotificationType::EXTENSION_INSTALLED: 500 case NotificationType::THEME_INSTALLED: 501 installed_ = Details<const Extension>(details).ptr(); 502 break; 503 504 default: 505 DCHECK(false); 506 } 507 } 508 509 void AddMockExternalProvider(ExternalExtensionProviderInterface* provider) { 510 service_->AddProviderForTesting(provider); 511 } 512 513 protected: 514 void TestExternalProvider(MockExtensionProvider* provider, 515 Extension::Location location); 516 517 void PackAndInstallExtension(const FilePath& dir_path, 518 const FilePath& pem_path, 519 bool should_succeed) { 520 FilePath crx_path; 521 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &crx_path)); 522 crx_path = crx_path.AppendASCII("temp.crx"); 523 524 // Use the existing pem key, if provided. 525 FilePath pem_output_path; 526 if (pem_path.value().empty()) { 527 pem_output_path = crx_path.DirName().AppendASCII("temp.pem"); 528 ASSERT_TRUE(file_util::Delete(pem_output_path, false)); 529 } else { 530 ASSERT_TRUE(file_util::PathExists(pem_path)); 531 } 532 533 ASSERT_TRUE(file_util::Delete(crx_path, false)); 534 535 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator()); 536 ASSERT_TRUE(creator->Run(dir_path, 537 crx_path, 538 pem_path, 539 pem_output_path)); 540 541 ASSERT_TRUE(file_util::PathExists(crx_path)); 542 543 InstallExtension(crx_path, should_succeed); 544 } 545 546 void PackAndInstallExtension(const FilePath& dir_path, 547 bool should_succeed) { 548 PackAndInstallExtension(dir_path, FilePath(), should_succeed); 549 } 550 551 // Create a CrxInstaller and start installation. To allow the install 552 // to happen, use loop_.RunAllPending();. Most tests will not use this 553 // method directly. Instead, use InstallExtension(), which waits for 554 // the crx to be installed and does extra error checking. 555 void StartCrxInstall(const FilePath& crx_path) { 556 ASSERT_TRUE(file_util::PathExists(crx_path)); 557 scoped_refptr<CrxInstaller> installer( 558 new CrxInstaller(service_, // frontend 559 NULL)); // no client (silent install) 560 installer->InstallCrx(crx_path); 561 } 562 563 void InstallExtension(const FilePath& path, 564 bool should_succeed) { 565 ASSERT_TRUE(file_util::PathExists(path)); 566 StartCrxInstall(path); 567 loop_.RunAllPending(); 568 std::vector<std::string> errors = GetErrors(); 569 if (should_succeed) { 570 ++total_successes_; 571 572 EXPECT_TRUE(installed_) << path.value(); 573 574 ASSERT_EQ(1u, loaded_.size()) << path.value(); 575 EXPECT_EQ(0u, errors.size()) << path.value(); 576 EXPECT_EQ(total_successes_, service_->extensions()->size()) << 577 path.value(); 578 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)) << 579 path.value(); 580 for (std::vector<std::string>::iterator err = errors.begin(); 581 err != errors.end(); ++err) { 582 LOG(ERROR) << *err; 583 } 584 } else { 585 EXPECT_FALSE(installed_) << path.value(); 586 EXPECT_EQ(0u, loaded_.size()) << path.value(); 587 EXPECT_EQ(1u, errors.size()) << path.value(); 588 } 589 590 installed_ = NULL; 591 loaded_.clear(); 592 ExtensionErrorReporter::GetInstance()->ClearErrors(); 593 } 594 595 enum UpdateState { 596 FAILED_SILENTLY, 597 FAILED, 598 UPDATED, 599 INSTALLED, 600 ENABLED 601 }; 602 603 void UpdateExtension(const std::string& id, const FilePath& in_path, 604 UpdateState expected_state) { 605 ASSERT_TRUE(file_util::PathExists(in_path)); 606 607 // We need to copy this to a temporary location because Update() will delete 608 // it. 609 FilePath path = temp_dir_.path(); 610 path = path.Append(in_path.BaseName()); 611 ASSERT_TRUE(file_util::CopyFile(in_path, path)); 612 613 int previous_enabled_extension_count = 614 service_->extensions()->size(); 615 int previous_installed_extension_count = 616 previous_enabled_extension_count + 617 service_->disabled_extensions()->size(); 618 619 service_->UpdateExtension(id, path, GURL()); 620 loop_.RunAllPending(); 621 622 std::vector<std::string> errors = GetErrors(); 623 int error_count = errors.size(); 624 int enabled_extension_count = 625 service_->extensions()->size(); 626 int installed_extension_count = 627 enabled_extension_count + service_->disabled_extensions()->size(); 628 629 int expected_error_count = (expected_state == FAILED) ? 1 : 0; 630 EXPECT_EQ(expected_error_count, error_count) << path.value(); 631 632 if (expected_state <= FAILED) { 633 EXPECT_EQ(previous_enabled_extension_count, 634 enabled_extension_count); 635 EXPECT_EQ(previous_installed_extension_count, 636 installed_extension_count); 637 } else { 638 int expected_installed_extension_count = 639 (expected_state >= INSTALLED) ? 1 : 0; 640 int expected_enabled_extension_count = 641 (expected_state >= ENABLED) ? 1 : 0; 642 EXPECT_EQ(expected_installed_extension_count, 643 installed_extension_count); 644 EXPECT_EQ(expected_enabled_extension_count, 645 enabled_extension_count); 646 } 647 648 // Update() should delete the temporary input file. 649 EXPECT_FALSE(file_util::PathExists(path)); 650 } 651 652 void ValidatePrefKeyCount(size_t count) { 653 DictionaryValue* dict = 654 profile_->GetPrefs()->GetMutableDictionary("extensions.settings"); 655 ASSERT_TRUE(dict != NULL); 656 EXPECT_EQ(count, dict->size()); 657 } 658 659 void ValidateBooleanPref(const std::string& extension_id, 660 const std::string& pref_path, 661 bool expected_val) { 662 std::string msg = " while checking: "; 663 msg += extension_id; 664 msg += " "; 665 msg += pref_path; 666 msg += " == "; 667 msg += expected_val ? "true" : "false"; 668 669 PrefService* prefs = profile_->GetPrefs(); 670 const DictionaryValue* dict = 671 prefs->GetDictionary("extensions.settings"); 672 ASSERT_TRUE(dict != NULL) << msg; 673 DictionaryValue* pref = NULL; 674 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg; 675 EXPECT_TRUE(pref != NULL) << msg; 676 bool val; 677 ASSERT_TRUE(pref->GetBoolean(pref_path, &val)) << msg; 678 EXPECT_EQ(expected_val, val) << msg; 679 } 680 681 bool IsPrefExist(const std::string& extension_id, 682 const std::string& pref_path) { 683 const DictionaryValue* dict = 684 profile_->GetPrefs()->GetDictionary("extensions.settings"); 685 if (dict == NULL) return false; 686 DictionaryValue* pref = NULL; 687 if (!dict->GetDictionary(extension_id, &pref)) { 688 return false; 689 } 690 if (pref == NULL) { 691 return false; 692 } 693 bool val; 694 if (!pref->GetBoolean(pref_path, &val)) { 695 return false; 696 } 697 return true; 698 } 699 700 void ValidateIntegerPref(const std::string& extension_id, 701 const std::string& pref_path, 702 int expected_val) { 703 std::string msg = " while checking: "; 704 msg += extension_id; 705 msg += " "; 706 msg += pref_path; 707 msg += " == "; 708 msg += base::IntToString(expected_val); 709 710 PrefService* prefs = profile_->GetPrefs(); 711 const DictionaryValue* dict = 712 prefs->GetDictionary("extensions.settings"); 713 ASSERT_TRUE(dict != NULL) << msg; 714 DictionaryValue* pref = NULL; 715 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg; 716 EXPECT_TRUE(pref != NULL) << msg; 717 int val; 718 ASSERT_TRUE(pref->GetInteger(pref_path, &val)) << msg; 719 EXPECT_EQ(expected_val, val) << msg; 720 } 721 722 void ValidateStringPref(const std::string& extension_id, 723 const std::string& pref_path, 724 const std::string& expected_val) { 725 std::string msg = " while checking: "; 726 msg += extension_id; 727 msg += ".manifest."; 728 msg += pref_path; 729 msg += " == "; 730 msg += expected_val; 731 732 const DictionaryValue* dict = 733 profile_->GetPrefs()->GetDictionary("extensions.settings"); 734 ASSERT_TRUE(dict != NULL) << msg; 735 DictionaryValue* pref = NULL; 736 std::string manifest_path = extension_id + ".manifest"; 737 ASSERT_TRUE(dict->GetDictionary(manifest_path, &pref)) << msg; 738 EXPECT_TRUE(pref != NULL) << msg; 739 std::string val; 740 ASSERT_TRUE(pref->GetString(pref_path, &val)) << msg; 741 EXPECT_EQ(expected_val, val) << msg; 742 } 743 744 void SetPref(const std::string& extension_id, 745 const std::string& pref_path, 746 Value* value, 747 const std::string& msg) { 748 const DictionaryValue* dict = 749 profile_->GetPrefs()->GetMutableDictionary("extensions.settings"); 750 ASSERT_TRUE(dict != NULL) << msg; 751 DictionaryValue* pref = NULL; 752 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg; 753 EXPECT_TRUE(pref != NULL) << msg; 754 pref->Set(pref_path, value); 755 } 756 757 void SetPrefInteg(const std::string& extension_id, 758 const std::string& pref_path, 759 int value) { 760 std::string msg = " while setting: "; 761 msg += extension_id; 762 msg += " "; 763 msg += pref_path; 764 msg += " = "; 765 msg += base::IntToString(value); 766 767 SetPref(extension_id, pref_path, Value::CreateIntegerValue(value), msg); 768 } 769 770 void SetPrefBool(const std::string& extension_id, 771 const std::string& pref_path, 772 bool value) { 773 std::string msg = " while setting: "; 774 msg += extension_id + " " + pref_path; 775 msg += " = "; 776 msg += (value ? "true" : "false"); 777 778 SetPref(extension_id, pref_path, Value::CreateBooleanValue(value), msg); 779 } 780 781 void ClearPref(const std::string& extension_id, 782 const std::string& pref_path) { 783 std::string msg = " while clearing: "; 784 msg += extension_id + " " + pref_path; 785 786 const DictionaryValue* dict = 787 profile_->GetPrefs()->GetMutableDictionary("extensions.settings"); 788 ASSERT_TRUE(dict != NULL) << msg; 789 DictionaryValue* pref = NULL; 790 ASSERT_TRUE(dict->GetDictionary(extension_id, &pref)) << msg; 791 EXPECT_TRUE(pref != NULL) << msg; 792 pref->Remove(pref_path, NULL); 793 } 794 795 void SetPrefStringSet(const std::string& extension_id, 796 const std::string& pref_path, 797 const std::set<std::string>& value) { 798 std::string msg = " while setting: "; 799 msg += extension_id + " " + pref_path; 800 801 ListValue* list_value = new ListValue(); 802 for (std::set<std::string>::const_iterator iter = value.begin(); 803 iter != value.end(); ++iter) 804 list_value->Append(Value::CreateStringValue(*iter)); 805 806 SetPref(extension_id, pref_path, list_value, msg); 807 } 808 809 protected: 810 ExtensionList loaded_; 811 std::string unloaded_id_; 812 const Extension* installed_; 813 814 private: 815 NotificationRegistrar registrar_; 816}; 817 818FilePath NormalizeSeparators(const FilePath& path) { 819#if defined(FILE_PATH_USES_WIN_SEPARATORS) 820 return path.NormalizeWindowsPathSeparators(); 821#else 822 return path; 823#endif // FILE_PATH_USES_WIN_SEPARATORS 824} 825 826// Receives notifications from a PackExtensionJob, indicating either that 827// packing succeeded or that there was some error. 828class PackExtensionTestClient : public PackExtensionJob::Client { 829 public: 830 PackExtensionTestClient(const FilePath& expected_crx_path, 831 const FilePath& expected_private_key_path); 832 virtual void OnPackSuccess(const FilePath& crx_path, 833 const FilePath& private_key_path); 834 virtual void OnPackFailure(const std::string& error_message); 835 836 private: 837 const FilePath expected_crx_path_; 838 const FilePath expected_private_key_path_; 839 DISALLOW_COPY_AND_ASSIGN(PackExtensionTestClient); 840}; 841 842PackExtensionTestClient::PackExtensionTestClient( 843 const FilePath& expected_crx_path, 844 const FilePath& expected_private_key_path) 845 : expected_crx_path_(expected_crx_path), 846 expected_private_key_path_(expected_private_key_path) {} 847 848// If packing succeeded, we make sure that the package names match our 849// expectations. 850void PackExtensionTestClient::OnPackSuccess(const FilePath& crx_path, 851 const FilePath& private_key_path) { 852 // We got the notification and processed it; we don't expect any further tasks 853 // to be posted to the current thread, so we should stop blocking and continue 854 // on with the rest of the test. 855 // This call to |Quit()| matches the call to |Run()| in the 856 // |PackPunctuatedExtension| test. 857 MessageLoop::current()->Quit(); 858 EXPECT_EQ(expected_crx_path_.value(), crx_path.value()); 859 EXPECT_EQ(expected_private_key_path_.value(), private_key_path.value()); 860 ASSERT_TRUE(file_util::PathExists(private_key_path)); 861} 862 863// The tests are designed so that we never expect to see a packing error. 864void PackExtensionTestClient::OnPackFailure(const std::string& error_message) { 865 FAIL() << "Packing should not fail."; 866} 867 868// Test loading good extensions from the profile directory. 869TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectorySuccess) { 870 // Initialize the test dir with a good Preferences/extensions. 871 FilePath source_install_dir; 872 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); 873 source_install_dir = source_install_dir 874 .AppendASCII("extensions") 875 .AppendASCII("good") 876 .AppendASCII("Extensions"); 877 FilePath pref_path = source_install_dir 878 .DirName() 879 .AppendASCII("Preferences"); 880 InitializeInstalledExtensionService(pref_path, source_install_dir); 881 882 service_->Init(); 883 884 // On Chrome OS, we disallow extensions with plugins. "good1" has plugins, 885 // so we need to edit it out here. 886 uint32 expected_num_extensions = 3u; 887#if defined(OS_CHROMEOS) 888 --expected_num_extensions; 889#endif 890 ASSERT_EQ(expected_num_extensions, loaded_.size()); 891 892 EXPECT_EQ(std::string(good0), loaded_[0]->id()); 893 EXPECT_EQ(std::string("My extension 1"), 894 loaded_[0]->name()); 895 EXPECT_EQ(std::string("The first extension that I made."), 896 loaded_[0]->description()); 897 EXPECT_EQ(Extension::INTERNAL, loaded_[0]->location()); 898 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)); 899 EXPECT_EQ(expected_num_extensions, service_->extensions()->size()); 900 901 ValidatePrefKeyCount(3); 902 ValidateIntegerPref(good0, "state", Extension::ENABLED); 903 ValidateIntegerPref(good0, "location", Extension::INTERNAL); 904 ValidateIntegerPref(good1, "state", Extension::ENABLED); 905 ValidateIntegerPref(good1, "location", Extension::INTERNAL); 906 ValidateIntegerPref(good2, "state", Extension::ENABLED); 907 ValidateIntegerPref(good2, "location", Extension::INTERNAL); 908 909 const Extension* extension = loaded_[0]; 910 const UserScriptList& scripts = extension->content_scripts(); 911 ASSERT_EQ(2u, scripts.size()); 912 EXPECT_EQ(3u, scripts[0].url_patterns().size()); 913 EXPECT_EQ("file://*", 914 scripts[0].url_patterns()[0].GetAsString()); 915 EXPECT_EQ("http://*.google.com/*", 916 scripts[0].url_patterns()[1].GetAsString()); 917 EXPECT_EQ("https://*.google.com/*", 918 scripts[0].url_patterns()[2].GetAsString()); 919 EXPECT_EQ(2u, scripts[0].js_scripts().size()); 920 ExtensionResource resource00(extension->id(), 921 scripts[0].js_scripts()[0].extension_root(), 922 scripts[0].js_scripts()[0].relative_path()); 923 FilePath expected_path(extension->path().AppendASCII("script1.js")); 924 ASSERT_TRUE(file_util::AbsolutePath(&expected_path)); 925 EXPECT_TRUE(resource00.ComparePathWithDefault(expected_path)); 926 ExtensionResource resource01(extension->id(), 927 scripts[0].js_scripts()[1].extension_root(), 928 scripts[0].js_scripts()[1].relative_path()); 929 expected_path = extension->path().AppendASCII("script2.js"); 930 ASSERT_TRUE(file_util::AbsolutePath(&expected_path)); 931 EXPECT_TRUE(resource01.ComparePathWithDefault(expected_path)); 932 EXPECT_TRUE(extension->plugins().empty()); 933 EXPECT_EQ(1u, scripts[1].url_patterns().size()); 934 EXPECT_EQ("http://*.news.com/*", scripts[1].url_patterns()[0].GetAsString()); 935 ExtensionResource resource10(extension->id(), 936 scripts[1].js_scripts()[0].extension_root(), 937 scripts[1].js_scripts()[0].relative_path()); 938 expected_path = 939 extension->path().AppendASCII("js_files").AppendASCII("script3.js"); 940 ASSERT_TRUE(file_util::AbsolutePath(&expected_path)); 941 EXPECT_TRUE(resource10.ComparePathWithDefault(expected_path)); 942 const std::vector<URLPattern> permissions = extension->host_permissions(); 943 ASSERT_EQ(2u, permissions.size()); 944 EXPECT_EQ("http://*.google.com/*", permissions[0].GetAsString()); 945 EXPECT_EQ("https://*.google.com/*", permissions[1].GetAsString()); 946 947#if !defined(OS_CHROMEOS) 948 EXPECT_EQ(std::string(good1), loaded_[1]->id()); 949 EXPECT_EQ(std::string("My extension 2"), loaded_[1]->name()); 950 EXPECT_EQ(std::string(""), loaded_[1]->description()); 951 EXPECT_EQ(loaded_[1]->GetResourceURL("background.html"), 952 loaded_[1]->background_url()); 953 EXPECT_EQ(0u, loaded_[1]->content_scripts().size()); 954 EXPECT_EQ(2u, loaded_[1]->plugins().size()); 955 EXPECT_EQ(loaded_[1]->path().AppendASCII("content_plugin.dll").value(), 956 loaded_[1]->plugins()[0].path.value()); 957 EXPECT_TRUE(loaded_[1]->plugins()[0].is_public); 958 EXPECT_EQ(loaded_[1]->path().AppendASCII("extension_plugin.dll").value(), 959 loaded_[1]->plugins()[1].path.value()); 960 EXPECT_FALSE(loaded_[1]->plugins()[1].is_public); 961 EXPECT_EQ(Extension::INTERNAL, loaded_[1]->location()); 962#endif 963 964 int index = expected_num_extensions - 1; 965 EXPECT_EQ(std::string(good2), loaded_[index]->id()); 966 EXPECT_EQ(std::string("My extension 3"), loaded_[index]->name()); 967 EXPECT_EQ(std::string(""), loaded_[index]->description()); 968 EXPECT_EQ(0u, loaded_[index]->content_scripts().size()); 969 EXPECT_EQ(Extension::INTERNAL, loaded_[index]->location()); 970}; 971 972// Test loading bad extensions from the profile directory. 973TEST_F(ExtensionServiceTest, LoadAllExtensionsFromDirectoryFail) { 974 // Initialize the test dir with a bad Preferences/extensions. 975 FilePath source_install_dir; 976 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); 977 source_install_dir = source_install_dir 978 .AppendASCII("extensions") 979 .AppendASCII("bad") 980 .AppendASCII("Extensions"); 981 FilePath pref_path = source_install_dir 982 .DirName() 983 .AppendASCII("Preferences"); 984 985 InitializeInstalledExtensionService(pref_path, source_install_dir); 986 987 service_->Init(); 988 loop_.RunAllPending(); 989 990 ASSERT_EQ(4u, GetErrors().size()); 991 ASSERT_EQ(0u, loaded_.size()); 992 993 EXPECT_TRUE(MatchPattern(GetErrors()[0], 994 std::string("Could not load extension from '*'. ") + 995 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[0]; 996 997 EXPECT_TRUE(MatchPattern(GetErrors()[1], 998 std::string("Could not load extension from '*'. ") + 999 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[1]; 1000 1001 EXPECT_TRUE(MatchPattern(GetErrors()[2], 1002 std::string("Could not load extension from '*'. ") + 1003 extension_manifest_errors::kMissingFile)) << GetErrors()[2]; 1004 1005 EXPECT_TRUE(MatchPattern(GetErrors()[3], 1006 std::string("Could not load extension from '*'. ") + 1007 extension_manifest_errors::kManifestUnreadable)) << GetErrors()[3]; 1008}; 1009 1010// Test that partially deleted extensions are cleaned up during startup 1011// Test loading bad extensions from the profile directory. 1012TEST_F(ExtensionServiceTest, CleanupOnStartup) { 1013 FilePath source_install_dir; 1014 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); 1015 source_install_dir = source_install_dir 1016 .AppendASCII("extensions") 1017 .AppendASCII("good") 1018 .AppendASCII("Extensions"); 1019 FilePath pref_path = source_install_dir 1020 .DirName() 1021 .AppendASCII("Preferences"); 1022 1023 InitializeInstalledExtensionService(pref_path, source_install_dir); 1024 1025 // Simulate that one of them got partially deleted by clearing its pref. 1026 DictionaryValue* dict = 1027 profile_->GetPrefs()->GetMutableDictionary("extensions.settings"); 1028 ASSERT_TRUE(dict != NULL); 1029 dict->Remove("behllobkkfkfnphdnhnkndlbkcpglgmj", NULL); 1030 1031 service_->Init(); 1032 loop_.RunAllPending(); 1033 1034 file_util::FileEnumerator dirs(extensions_install_dir_, false, 1035 file_util::FileEnumerator::DIRECTORIES); 1036 size_t count = 0; 1037 while (!dirs.Next().empty()) 1038 count++; 1039 1040 // We should have only gotten two extensions now. 1041 EXPECT_EQ(2u, count); 1042 1043 // And extension1 dir should now be toast. 1044 FilePath extension_dir = extensions_install_dir_ 1045 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj"); 1046 ASSERT_FALSE(file_util::PathExists(extension_dir)); 1047} 1048 1049// Test installing extensions. This test tries to install few extensions using 1050// crx files. If you need to change those crx files, feel free to repackage 1051// them, throw away the key used and change the id's above. 1052TEST_F(ExtensionServiceTest, InstallExtension) { 1053 InitializeEmptyExtensionService(); 1054 1055 FilePath extensions_path; 1056 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1057 extensions_path = extensions_path.AppendASCII("extensions"); 1058 1059 // Extensions not enabled. 1060 set_extensions_enabled(false); 1061 FilePath path = extensions_path.AppendASCII("good.crx"); 1062 InstallExtension(path, false); 1063 set_extensions_enabled(true); 1064 1065 ValidatePrefKeyCount(0); 1066 1067 // A simple extension that should install without error. 1068 path = extensions_path.AppendASCII("good.crx"); 1069 InstallExtension(path, true); 1070 // TODO(erikkay): verify the contents of the installed extension. 1071 1072 int pref_count = 0; 1073 ValidatePrefKeyCount(++pref_count); 1074 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 1075 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL); 1076 1077 // An extension with page actions. 1078 path = extensions_path.AppendASCII("page_action.crx"); 1079 InstallExtension(path, true); 1080 ValidatePrefKeyCount(++pref_count); 1081 ValidateIntegerPref(page_action, "state", Extension::ENABLED); 1082 ValidateIntegerPref(page_action, "location", Extension::INTERNAL); 1083 1084 // Bad signature. 1085 path = extensions_path.AppendASCII("bad_signature.crx"); 1086 InstallExtension(path, false); 1087 ValidatePrefKeyCount(pref_count); 1088 1089 // 0-length extension file. 1090 path = extensions_path.AppendASCII("not_an_extension.crx"); 1091 InstallExtension(path, false); 1092 ValidatePrefKeyCount(pref_count); 1093 1094 // Bad magic number. 1095 path = extensions_path.AppendASCII("bad_magic.crx"); 1096 InstallExtension(path, false); 1097 ValidatePrefKeyCount(pref_count); 1098 1099 // Extensions cannot have folders or files that have underscores except in 1100 // certain whitelisted cases (eg _locales). This is an example of a broader 1101 // class of validation that we do to the directory structure of the extension. 1102 // We did not used to handle this correctly for installation. 1103 path = extensions_path.AppendASCII("bad_underscore.crx"); 1104 InstallExtension(path, false); 1105 ValidatePrefKeyCount(pref_count); 1106 1107 // TODO(erikkay): add more tests for many of the failure cases. 1108 // TODO(erikkay): add tests for upgrade cases. 1109} 1110 1111// Test the handling of killed extensions. 1112TEST_F(ExtensionServiceTest, KilledExtensions) { 1113 InitializeEmptyExtensionService(); 1114 1115 FilePath extensions_path; 1116 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1117 extensions_path = extensions_path.AppendASCII("extensions"); 1118 FilePath path = extensions_path.AppendASCII("good.crx"); 1119 set_extensions_enabled(true); 1120 1121 scoped_ptr<Version> version; 1122 version.reset(Version::GetVersionFromString("1.0.0.0")); 1123 // Install an external extension. 1124 service_->OnExternalExtensionFileFound(good_crx, version.get(), 1125 path, Extension::EXTERNAL_PREF); 1126 loop_.RunAllPending(); 1127 ASSERT_TRUE(NULL != service_->GetExtensionById(good_crx, false)); 1128 1129 // Uninstall it and check that its killbit gets set. 1130 service_->UninstallExtension(good_crx, false); 1131 loop_.RunAllPending(); 1132 ValidateIntegerPref(good_crx, "location", Extension::KILLBIT); 1133 1134 // Try to re-install it externally. This should fail because of the killbit. 1135 service_->OnExternalExtensionFileFound(good_crx, version.get(), 1136 path, Extension::EXTERNAL_PREF); 1137 loop_.RunAllPending(); 1138 ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false)); 1139 ValidateIntegerPref(good_crx, "location", Extension::KILLBIT); 1140 1141 version.reset(Version::GetVersionFromString("1.0.0.1")); 1142 // Repeat the same thing with a newer version of the extension. 1143 path = extensions_path.AppendASCII("good2.crx"); 1144 service_->OnExternalExtensionFileFound(good_crx, version.get(), 1145 path, Extension::EXTERNAL_PREF); 1146 loop_.RunAllPending(); 1147 ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false)); 1148 ValidateIntegerPref(good_crx, "location", Extension::KILLBIT); 1149 1150 // Try adding the same extension from an external update URL. 1151 service_->AddPendingExtensionFromExternalUpdateUrl( 1152 good_crx, 1153 GURL("http:://fake.update/url"), 1154 Extension::EXTERNAL_PREF_DOWNLOAD); 1155 const PendingExtensionMap& pending_extensions = 1156 service_->pending_extensions(); 1157 ASSERT_TRUE(pending_extensions.find(good_crx) == pending_extensions.end()); 1158} 1159 1160// Install a user script (they get converted automatically to an extension) 1161TEST_F(ExtensionServiceTest, InstallUserScript) { 1162 // The details of script conversion are tested elsewhere, this just tests 1163 // integration with ExtensionService. 1164 InitializeEmptyExtensionService(); 1165 1166 FilePath path; 1167 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path)); 1168 path = path.AppendASCII("extensions") 1169 .AppendASCII("user_script_basic.user.js"); 1170 1171 ASSERT_TRUE(file_util::PathExists(path)); 1172 scoped_refptr<CrxInstaller> installer( 1173 new CrxInstaller(service_, NULL)); // silent install 1174 installer->InstallUserScript( 1175 path, 1176 GURL("http://www.aaronboodman.com/scripts/user_script_basic.user.js")); 1177 1178 loop_.RunAllPending(); 1179 std::vector<std::string> errors = GetErrors(); 1180 EXPECT_TRUE(installed_) << "Nothing was installed."; 1181 ASSERT_EQ(1u, loaded_.size()) << "Nothing was loaded."; 1182 EXPECT_EQ(0u, errors.size()) << "There were errors: " 1183 << JoinString(errors, ','); 1184 EXPECT_TRUE(service_->GetExtensionById(loaded_[0]->id(), false)) << 1185 path.value(); 1186 1187 installed_ = NULL; 1188 loaded_.clear(); 1189 ExtensionErrorReporter::GetInstance()->ClearErrors(); 1190} 1191 1192// This tests that the granted permissions preferences are correctly set when 1193// installing an extension. 1194TEST_F(ExtensionServiceTest, GrantedPermissions) { 1195 InitializeEmptyExtensionService(); 1196 FilePath path; 1197 FilePath pem_path; 1198 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path)); 1199 path = path.AppendASCII("extensions") 1200 .AppendASCII("permissions"); 1201 1202 pem_path = path.AppendASCII("unknown.pem"); 1203 path = path.AppendASCII("unknown"); 1204 1205 ASSERT_TRUE(file_util::PathExists(pem_path)); 1206 ASSERT_TRUE(file_util::PathExists(path)); 1207 1208 ExtensionPrefs* prefs = service_->extension_prefs(); 1209 1210 std::set<std::string> expected_api_perms; 1211 std::set<std::string> known_api_perms; 1212 bool full_access; 1213 ExtensionExtent expected_host_perms; 1214 ExtensionExtent known_host_perms; 1215 1216 // Make sure there aren't any granted permissions before the 1217 // extension is installed. 1218 EXPECT_FALSE(prefs->GetGrantedPermissions( 1219 permissions_crx, &full_access, &known_api_perms, &known_host_perms)); 1220 EXPECT_TRUE(known_api_perms.empty()); 1221 EXPECT_TRUE(known_host_perms.is_empty()); 1222 1223 PackAndInstallExtension(path, pem_path, true); 1224 1225 EXPECT_EQ(0u, GetErrors().size()); 1226 ASSERT_EQ(1u, service_->extensions()->size()); 1227 std::string extension_id = service_->extensions()->at(0)->id(); 1228 EXPECT_EQ(permissions_crx, extension_id); 1229 1230 1231 // Verify that the valid API permissions have been recognized. 1232 expected_api_perms.insert("tabs"); 1233 1234 AddPattern(&expected_host_perms, "http://*.google.com/*"); 1235 AddPattern(&expected_host_perms, "https://*.google.com/*"); 1236 AddPattern(&expected_host_perms, "http://*.google.com.hk/*"); 1237 AddPattern(&expected_host_perms, "http://www.example.com/*"); 1238 1239 EXPECT_TRUE(prefs->GetGrantedPermissions(extension_id, 1240 &full_access, 1241 &known_api_perms, 1242 &known_host_perms)); 1243 1244 EXPECT_EQ(expected_api_perms, known_api_perms); 1245 EXPECT_FALSE(full_access); 1246 AssertEqualExtents(&expected_host_perms, &known_host_perms); 1247} 1248 1249#if !defined(OS_CHROMEOS) 1250// Tests that the granted permissions full_access bit gets set correctly when 1251// an extension contains an NPAPI plugin. Don't run this test on Chrome OS 1252// since they don't support plugins. 1253TEST_F(ExtensionServiceTest, GrantedFullAccessPermissions) { 1254 InitializeEmptyExtensionService(); 1255 1256 FilePath path; 1257 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path)); 1258 path = path.AppendASCII("extensions") 1259 .AppendASCII("good") 1260 .AppendASCII("Extensions") 1261 .AppendASCII(good1) 1262 .AppendASCII("2"); 1263 1264 ASSERT_TRUE(file_util::PathExists(path)); 1265 1266 PackAndInstallExtension(path, true); 1267 1268 EXPECT_EQ(0u, GetErrors().size()); 1269 EXPECT_EQ(1u, service_->extensions()->size()); 1270 const Extension* extension = service_->extensions()->at(0); 1271 std::string extension_id = extension->id(); 1272 ExtensionPrefs* prefs = service_->extension_prefs(); 1273 1274 bool full_access; 1275 std::set<std::string> api_permissions; 1276 ExtensionExtent host_permissions; 1277 EXPECT_TRUE(prefs->GetGrantedPermissions( 1278 extension_id, &full_access, &api_permissions, &host_permissions)); 1279 1280 EXPECT_TRUE(full_access); 1281 EXPECT_TRUE(api_permissions.empty()); 1282 EXPECT_TRUE(host_permissions.is_empty()); 1283} 1284#endif 1285 1286// Tests that the extension is disabled when permissions are missing from 1287// the extension's granted permissions preferences. (This simulates updating 1288// the browser to a version which recognizes more permissions). 1289TEST_F(ExtensionServiceTest, GrantedAPIAndHostPermissions) { 1290 InitializeEmptyExtensionService(); 1291 1292 FilePath path; 1293 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path)); 1294 path = path.AppendASCII("extensions") 1295 .AppendASCII("permissions") 1296 .AppendASCII("unknown"); 1297 1298 ASSERT_TRUE(file_util::PathExists(path)); 1299 1300 PackAndInstallExtension(path, true); 1301 1302 EXPECT_EQ(0u, GetErrors().size()); 1303 EXPECT_EQ(1u, service_->extensions()->size()); 1304 const Extension* extension = service_->extensions()->at(0); 1305 std::string extension_id = extension->id(); 1306 1307 ExtensionPrefs* prefs = service_->extension_prefs(); 1308 1309 std::set<std::string> expected_api_permissions; 1310 ExtensionExtent expected_host_permissions; 1311 1312 expected_api_permissions.insert("tabs"); 1313 AddPattern(&expected_host_permissions, "http://*.google.com/*"); 1314 AddPattern(&expected_host_permissions, "https://*.google.com/*"); 1315 AddPattern(&expected_host_permissions, "http://*.google.com.hk/*"); 1316 AddPattern(&expected_host_permissions, "http://www.example.com/*"); 1317 1318 std::set<std::string> api_permissions; 1319 std::set<std::string> host_permissions; 1320 1321 // Test that the extension is disabled when an API permission is missing from 1322 // the extension's granted api permissions preference. (This simulates 1323 // updating the browser to a version which recognizes a new API permission). 1324 SetPrefStringSet(extension_id, "granted_permissions.api", api_permissions); 1325 1326 service_->ReloadExtensions(); 1327 1328 EXPECT_EQ(1u, service_->disabled_extensions()->size()); 1329 extension = service_->disabled_extensions()->at(0); 1330 1331 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::DISABLED); 1332 ASSERT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id)); 1333 1334 // Now grant and re-enable the extension, making sure the prefs are updated. 1335 service_->GrantPermissionsAndEnableExtension(extension); 1336 1337 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::ENABLED); 1338 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id)); 1339 1340 std::set<std::string> current_api_permissions; 1341 ExtensionExtent current_host_permissions; 1342 bool current_full_access; 1343 1344 ASSERT_TRUE(prefs->GetGrantedPermissions(extension_id, 1345 ¤t_full_access, 1346 ¤t_api_permissions, 1347 ¤t_host_permissions)); 1348 1349 ASSERT_FALSE(current_full_access); 1350 ASSERT_EQ(expected_api_permissions, current_api_permissions); 1351 AssertEqualExtents(&expected_host_permissions, ¤t_host_permissions); 1352 1353 // Tests that the extension is disabled when a host permission is missing from 1354 // the extension's granted host permissions preference. (This simulates 1355 // updating the browser to a version which recognizes additional host 1356 // permissions). 1357 api_permissions.clear(); 1358 host_permissions.clear(); 1359 current_api_permissions.clear(); 1360 current_host_permissions.ClearPaths(); 1361 1362 api_permissions.insert("tabs"); 1363 host_permissions.insert("http://*.google.com/*"); 1364 host_permissions.insert("https://*.google.com/*"); 1365 host_permissions.insert("http://*.google.com.hk/*"); 1366 1367 SetPrefStringSet(extension_id, "granted_permissions.api", api_permissions); 1368 SetPrefStringSet(extension_id, "granted_permissions.host", host_permissions); 1369 1370 service_->ReloadExtensions(); 1371 1372 EXPECT_EQ(1u, service_->disabled_extensions()->size()); 1373 extension = service_->disabled_extensions()->at(0); 1374 1375 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::DISABLED); 1376 ASSERT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id)); 1377 1378 // Now grant and re-enable the extension, making sure the prefs are updated. 1379 service_->GrantPermissionsAndEnableExtension(extension); 1380 1381 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::ENABLED); 1382 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id)); 1383 1384 ASSERT_TRUE(prefs->GetGrantedPermissions(extension_id, 1385 ¤t_full_access, 1386 ¤t_api_permissions, 1387 ¤t_host_permissions)); 1388 1389 ASSERT_FALSE(current_full_access); 1390 ASSERT_EQ(expected_api_permissions, current_api_permissions); 1391 AssertEqualExtents(&expected_host_permissions, ¤t_host_permissions); 1392 1393 // Tests that the granted permissions preferences are initialized when 1394 // migrating from the old pref schema. 1395 current_api_permissions.clear(); 1396 current_host_permissions.ClearPaths(); 1397 1398 ClearPref(extension_id, "granted_permissions"); 1399 1400 service_->ReloadExtensions(); 1401 1402 EXPECT_EQ(1u, service_->extensions()->size()); 1403 extension = service_->extensions()->at(0); 1404 1405 ASSERT_TRUE(prefs->GetExtensionState(extension_id) == Extension::ENABLED); 1406 ASSERT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id)); 1407 1408 ASSERT_TRUE(prefs->GetGrantedPermissions(extension_id, 1409 ¤t_full_access, 1410 ¤t_api_permissions, 1411 ¤t_host_permissions)); 1412 1413 ASSERT_FALSE(current_full_access); 1414 ASSERT_EQ(expected_api_permissions, current_api_permissions); 1415 AssertEqualExtents(&expected_host_permissions, ¤t_host_permissions); 1416} 1417 1418// Test Packaging and installing an extension. 1419TEST_F(ExtensionServiceTest, PackExtension) { 1420 InitializeEmptyExtensionService(); 1421 FilePath extensions_path; 1422 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1423 extensions_path = extensions_path.AppendASCII("extensions"); 1424 FilePath input_directory = extensions_path 1425 .AppendASCII("good") 1426 .AppendASCII("Extensions") 1427 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") 1428 .AppendASCII("1.0.0.0"); 1429 1430 ScopedTempDir temp_dir; 1431 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1432 FilePath output_directory = temp_dir.path(); 1433 1434 FilePath crx_path(output_directory.AppendASCII("ex1.crx")); 1435 FilePath privkey_path(output_directory.AppendASCII("privkey.pem")); 1436 1437 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator()); 1438 ASSERT_TRUE(creator->Run(input_directory, crx_path, FilePath(), 1439 privkey_path)); 1440 1441 ASSERT_TRUE(file_util::PathExists(privkey_path)); 1442 InstallExtension(crx_path, true); 1443 1444 // Try packing with invalid paths. 1445 creator.reset(new ExtensionCreator()); 1446 ASSERT_FALSE(creator->Run(FilePath(), FilePath(), FilePath(), FilePath())); 1447 1448 // Try packing an empty directory. Should fail because an empty directory is 1449 // not a valid extension. 1450 ScopedTempDir temp_dir2; 1451 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir()); 1452 creator.reset(new ExtensionCreator()); 1453 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path, 1454 FilePath())); 1455 1456 // Try packing with an invalid manifest. 1457 std::string invalid_manifest_content = "I am not a manifest."; 1458 ASSERT_TRUE(file_util::WriteFile( 1459 temp_dir2.path().Append(Extension::kManifestFilename), 1460 invalid_manifest_content.c_str(), invalid_manifest_content.size())); 1461 creator.reset(new ExtensionCreator()); 1462 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path, 1463 FilePath())); 1464} 1465 1466// Test Packaging and installing an extension whose name contains punctuation. 1467TEST_F(ExtensionServiceTest, PackPunctuatedExtension) { 1468 InitializeEmptyExtensionService(); 1469 FilePath extensions_path; 1470 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1471 extensions_path = extensions_path.AppendASCII("extensions"); 1472 FilePath input_directory = extensions_path 1473 .AppendASCII("good") 1474 .AppendASCII("Extensions") 1475 .AppendASCII(good0) 1476 .AppendASCII("1.0.0.0"); 1477 1478 ScopedTempDir temp_dir; 1479 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1480 1481 // Extension names containing punctuation, and the expected names for the 1482 // packed extensions. 1483 const FilePath punctuated_names[] = { 1484 FilePath(FilePath::StringType( 1485 FILE_PATH_LITERAL("this.extensions.name.has.periods"))), 1486 FilePath(FilePath::StringType( 1487 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod"))), 1488 NormalizeSeparators(FilePath(FilePath::StringType( 1489 FILE_PATH_LITERAL("thisextensionhasaslashinitsname/")))), 1490 }; 1491 const FilePath expected_crx_names[] = { 1492 FilePath(FilePath::StringType( 1493 FILE_PATH_LITERAL("this.extensions.name.has.periods.crx"))), 1494 FilePath(FilePath::StringType( 1495 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.crx"))), 1496 FilePath(FilePath::StringType( 1497 FILE_PATH_LITERAL("thisextensionhasaslashinitsname.crx"))), 1498 }; 1499 const FilePath expected_private_key_names[] = { 1500 FilePath(FilePath::StringType( 1501 FILE_PATH_LITERAL("this.extensions.name.has.periods.pem"))), 1502 FilePath(FilePath::StringType( 1503 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.pem"))), 1504 FilePath(FilePath::StringType( 1505 FILE_PATH_LITERAL("thisextensionhasaslashinitsname.pem"))), 1506 }; 1507 1508 for (size_t i = 0; i < arraysize(punctuated_names); ++i) { 1509 SCOPED_TRACE(punctuated_names[i].value().c_str()); 1510 FilePath output_dir = temp_dir.path().Append(punctuated_names[i]); 1511 1512 // Copy the extension into the output directory, as PackExtensionJob doesn't 1513 // let us choose where to output the packed extension. 1514 ASSERT_TRUE(file_util::CopyDirectory(input_directory, output_dir, true)); 1515 1516 FilePath expected_crx_path = temp_dir.path().Append(expected_crx_names[i]); 1517 FilePath expected_private_key_path = 1518 temp_dir.path().Append(expected_private_key_names[i]); 1519 PackExtensionTestClient pack_client(expected_crx_path, 1520 expected_private_key_path); 1521 scoped_refptr<PackExtensionJob> packer(new PackExtensionJob(&pack_client, 1522 output_dir, 1523 FilePath())); 1524 packer->Start(); 1525 1526 // The packer will post a notification task to the current thread's message 1527 // loop when it is finished. We manually run the loop here so that we 1528 // block and catch the notification; otherwise, the process would exit. 1529 // This call to |Run()| is matched by a call to |Quit()| in the 1530 // |PackExtensionTestClient|'s notification handling code. 1531 MessageLoop::current()->Run(); 1532 1533 if (HasFatalFailure()) 1534 return; 1535 1536 InstallExtension(expected_crx_path, true); 1537 } 1538} 1539 1540// Test Packaging and installing an extension using an openssl generated key. 1541// The openssl is generated with the following: 1542// > openssl genrsa -out privkey.pem 1024 1543// > openssl pkcs8 -topk8 -nocrypt -in privkey.pem -out privkey_asn1.pem 1544// The privkey.pem is a PrivateKey, and the pcks8 -topk8 creates a 1545// PrivateKeyInfo ASN.1 structure, we our RSAPrivateKey expects. 1546TEST_F(ExtensionServiceTest, PackExtensionOpenSSLKey) { 1547 InitializeEmptyExtensionService(); 1548 FilePath extensions_path; 1549 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1550 extensions_path = extensions_path.AppendASCII("extensions"); 1551 FilePath input_directory = extensions_path 1552 .AppendASCII("good") 1553 .AppendASCII("Extensions") 1554 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") 1555 .AppendASCII("1.0.0.0"); 1556 FilePath privkey_path(extensions_path.AppendASCII( 1557 "openssl_privkey_asn1.pem")); 1558 ASSERT_TRUE(file_util::PathExists(privkey_path)); 1559 1560 ScopedTempDir temp_dir; 1561 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1562 FilePath output_directory = temp_dir.path(); 1563 1564 FilePath crx_path(output_directory.AppendASCII("ex1.crx")); 1565 1566 scoped_ptr<ExtensionCreator> creator(new ExtensionCreator()); 1567 ASSERT_TRUE(creator->Run(input_directory, crx_path, privkey_path, 1568 FilePath())); 1569 1570 InstallExtension(crx_path, true); 1571} 1572 1573TEST_F(ExtensionServiceTest, InstallTheme) { 1574 InitializeEmptyExtensionService(); 1575 FilePath extensions_path; 1576 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1577 extensions_path = extensions_path.AppendASCII("extensions"); 1578 1579 // A theme. 1580 FilePath path = extensions_path.AppendASCII("theme.crx"); 1581 InstallExtension(path, true); 1582 int pref_count = 0; 1583 ValidatePrefKeyCount(++pref_count); 1584 ValidateIntegerPref(theme_crx, "state", Extension::ENABLED); 1585 ValidateIntegerPref(theme_crx, "location", Extension::INTERNAL); 1586 1587 // A theme when extensions are disabled. Themes can be installed, even when 1588 // extensions are disabled. 1589 set_extensions_enabled(false); 1590 path = extensions_path.AppendASCII("theme2.crx"); 1591 InstallExtension(path, true); 1592 ValidatePrefKeyCount(++pref_count); 1593 ValidateIntegerPref(theme2_crx, "state", Extension::ENABLED); 1594 ValidateIntegerPref(theme2_crx, "location", Extension::INTERNAL); 1595 1596 // A theme with extension elements. Themes cannot have extension elements so 1597 // this test should fail. 1598 set_extensions_enabled(true); 1599 path = extensions_path.AppendASCII("theme_with_extension.crx"); 1600 InstallExtension(path, false); 1601 ValidatePrefKeyCount(pref_count); 1602 1603 // A theme with image resources missing (misspelt path). 1604 path = extensions_path.AppendASCII("theme_missing_image.crx"); 1605 InstallExtension(path, false); 1606 ValidatePrefKeyCount(pref_count); 1607} 1608 1609TEST_F(ExtensionServiceTest, LoadLocalizedTheme) { 1610 // Load. 1611 InitializeEmptyExtensionService(); 1612 FilePath extension_path; 1613 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extension_path)); 1614 extension_path = extension_path 1615 .AppendASCII("extensions") 1616 .AppendASCII("theme_i18n"); 1617 1618 service_->LoadExtension(extension_path); 1619 loop_.RunAllPending(); 1620 EXPECT_EQ(0u, GetErrors().size()); 1621 ASSERT_EQ(1u, loaded_.size()); 1622 EXPECT_EQ(1u, service_->extensions()->size()); 1623 EXPECT_EQ("name", service_->extensions()->at(0)->name()); 1624 EXPECT_EQ("description", service_->extensions()->at(0)->description()); 1625} 1626 1627TEST_F(ExtensionServiceTest, InstallLocalizedTheme) { 1628 InitializeEmptyExtensionService(); 1629 FilePath theme_path; 1630 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &theme_path)); 1631 theme_path = theme_path 1632 .AppendASCII("extensions") 1633 .AppendASCII("theme_i18n"); 1634 1635 PackAndInstallExtension(theme_path, true); 1636 1637 EXPECT_EQ(0u, GetErrors().size()); 1638 EXPECT_EQ(1u, service_->extensions()->size()); 1639 EXPECT_EQ("name", service_->extensions()->at(0)->name()); 1640 EXPECT_EQ("description", service_->extensions()->at(0)->description()); 1641} 1642 1643TEST_F(ExtensionServiceTest, InstallApps) { 1644 InitializeEmptyExtensionService(); 1645 FilePath extensions_path; 1646 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1647 extensions_path = extensions_path.AppendASCII("extensions"); 1648 1649 // An empty app. 1650 PackAndInstallExtension(extensions_path.AppendASCII("app1"), true); 1651 int pref_count = 0; 1652 ValidatePrefKeyCount(++pref_count); 1653 ASSERT_EQ(1u, service_->extensions()->size()); 1654 std::string id = service_->extensions()->at(0)->id(); 1655 ValidateIntegerPref(id, "state", Extension::ENABLED); 1656 ValidateIntegerPref(id, "location", Extension::INTERNAL); 1657 1658 // Another app with non-overlapping extent. Should succeed. 1659 PackAndInstallExtension(extensions_path.AppendASCII("app2"), true); 1660 ValidatePrefKeyCount(++pref_count); 1661 1662 // A third app whose extent overlaps the first. Should fail. 1663 PackAndInstallExtension(extensions_path.AppendASCII("app3"), false); 1664 ValidatePrefKeyCount(pref_count); 1665} 1666 1667TEST_F(ExtensionServiceTest, UpdateApps) { 1668 InitializeEmptyExtensionService(); 1669 FilePath extensions_path; 1670 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1671 extensions_path = 1672 extensions_path.AppendASCII("extensions").AppendASCII("app_update"); 1673 1674 // First install v1 of a hosted app. 1675 InstallExtension(extensions_path.AppendASCII("v1.crx"), true); 1676 ASSERT_EQ(1u, service_->extensions()->size()); 1677 std::string id = service_->extensions()->at(0)->id(); 1678 ASSERT_EQ(std::string("1"), 1679 service_->extensions()->at(0)->version()->GetString()); 1680 1681 // Now try updating to v2. 1682 UpdateExtension(id, 1683 extensions_path.AppendASCII("v2.crx"), 1684 ENABLED); 1685 ASSERT_EQ(std::string("2"), 1686 service_->extensions()->at(0)->version()->GetString()); 1687} 1688 1689TEST_F(ExtensionServiceTest, InstallAppsWithUnlimtedStorage) { 1690 InitializeEmptyExtensionService(); 1691 EXPECT_TRUE(service_->extensions()->empty()); 1692 1693 FilePath extensions_path; 1694 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1695 extensions_path = extensions_path.AppendASCII("extensions"); 1696 int pref_count = 0; 1697 1698 // Install app1 with unlimited storage. 1699 PackAndInstallExtension(extensions_path.AppendASCII("app1"), true); 1700 ValidatePrefKeyCount(++pref_count); 1701 ASSERT_EQ(1u, service_->extensions()->size()); 1702 const Extension* extension = service_->extensions()->at(0); 1703 const std::string id1 = extension->id(); 1704 EXPECT_TRUE(extension->HasApiPermission( 1705 Extension::kUnlimitedStoragePermission)); 1706 EXPECT_TRUE(extension->web_extent().ContainsURL( 1707 extension->GetFullLaunchURL())); 1708 const GURL origin1(extension->GetFullLaunchURL().GetOrigin()); 1709 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()-> 1710 IsStorageUnlimited(origin1)); 1711 1712 // Install app2 from the same origin with unlimited storage. 1713 PackAndInstallExtension(extensions_path.AppendASCII("app2"), true); 1714 ValidatePrefKeyCount(++pref_count); 1715 ASSERT_EQ(2u, service_->extensions()->size()); 1716 extension = service_->extensions()->at(1); 1717 const std::string id2 = extension->id(); 1718 EXPECT_TRUE(extension->HasApiPermission( 1719 Extension::kUnlimitedStoragePermission)); 1720 EXPECT_TRUE(extension->web_extent().ContainsURL( 1721 extension->GetFullLaunchURL())); 1722 const GURL origin2(extension->GetFullLaunchURL().GetOrigin()); 1723 EXPECT_EQ(origin1, origin2); 1724 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()-> 1725 IsStorageUnlimited(origin2)); 1726 1727 1728 // Uninstall one of them, unlimited storage should still be granted 1729 // to the origin. 1730 service_->UninstallExtension(id1, false); 1731 loop_.RunAllPending(); 1732 EXPECT_EQ(1u, service_->extensions()->size()); 1733 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()-> 1734 IsStorageUnlimited(origin1)); 1735 1736 1737 // Uninstall the other, unlimited storage should be revoked. 1738 service_->UninstallExtension(id2, false); 1739 loop_.RunAllPending(); 1740 EXPECT_EQ(0u, service_->extensions()->size()); 1741 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()-> 1742 IsStorageUnlimited(origin2)); 1743} 1744 1745TEST_F(ExtensionServiceTest, InstallAppsAndCheckStorageProtection) { 1746 InitializeEmptyExtensionService(); 1747 EXPECT_TRUE(service_->extensions()->empty()); 1748 1749 FilePath extensions_path; 1750 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1751 extensions_path = extensions_path.AppendASCII("extensions"); 1752 int pref_count = 0; 1753 1754 PackAndInstallExtension(extensions_path.AppendASCII("app1"), true); 1755 ValidatePrefKeyCount(++pref_count); 1756 ASSERT_EQ(1u, service_->extensions()->size()); 1757 const Extension* extension = service_->extensions()->at(0); 1758 EXPECT_TRUE(extension->is_app()); 1759 const std::string id1 = extension->id(); 1760 const GURL origin1(extension->GetFullLaunchURL().GetOrigin()); 1761 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()-> 1762 IsStorageProtected(origin1)); 1763 1764 // App 4 has a different origin (maps.google.com). 1765 PackAndInstallExtension(extensions_path.AppendASCII("app4"), true); 1766 ValidatePrefKeyCount(++pref_count); 1767 ASSERT_EQ(2u, service_->extensions()->size()); 1768 extension = service_->extensions()->at(1); 1769 const std::string id2 = extension->id(); 1770 const GURL origin2(extension->GetFullLaunchURL().GetOrigin()); 1771 ASSERT_NE(origin1, origin2); 1772 EXPECT_TRUE(profile_->GetExtensionSpecialStoragePolicy()-> 1773 IsStorageProtected(origin2)); 1774 1775 service_->UninstallExtension(id1, false); 1776 loop_.RunAllPending(); 1777 EXPECT_EQ(1u, service_->extensions()->size()); 1778 1779 service_->UninstallExtension(id2, false); 1780 loop_.RunAllPending(); 1781 1782 EXPECT_TRUE(service_->extensions()->empty()); 1783 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()-> 1784 IsStorageProtected(origin1)); 1785 EXPECT_FALSE(profile_->GetExtensionSpecialStoragePolicy()-> 1786 IsStorageProtected(origin2)); 1787} 1788 1789// Test that when an extension version is reinstalled, nothing happens. 1790TEST_F(ExtensionServiceTest, Reinstall) { 1791 InitializeEmptyExtensionService(); 1792 FilePath extensions_path; 1793 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1794 extensions_path = extensions_path.AppendASCII("extensions"); 1795 1796 // A simple extension that should install without error. 1797 FilePath path = extensions_path.AppendASCII("good.crx"); 1798 StartCrxInstall(path); 1799 loop_.RunAllPending(); 1800 1801 ASSERT_TRUE(installed_); 1802 ASSERT_EQ(1u, loaded_.size()); 1803 ASSERT_EQ(0u, GetErrors().size()); 1804 ValidatePrefKeyCount(1); 1805 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 1806 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL); 1807 1808 installed_ = NULL; 1809 loaded_.clear(); 1810 ExtensionErrorReporter::GetInstance()->ClearErrors(); 1811 1812 // Reinstall the same version, it should overwrite the previous one. 1813 StartCrxInstall(path); 1814 loop_.RunAllPending(); 1815 1816 ASSERT_TRUE(installed_); 1817 ASSERT_EQ(1u, loaded_.size()); 1818 ASSERT_EQ(0u, GetErrors().size()); 1819 ValidatePrefKeyCount(1); 1820 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 1821 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL); 1822} 1823 1824// Test upgrading a signed extension. 1825TEST_F(ExtensionServiceTest, UpgradeSignedGood) { 1826 InitializeEmptyExtensionService(); 1827 FilePath extensions_path; 1828 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1829 extensions_path = extensions_path.AppendASCII("extensions"); 1830 1831 FilePath path = extensions_path.AppendASCII("good.crx"); 1832 StartCrxInstall(path); 1833 loop_.RunAllPending(); 1834 1835 ASSERT_TRUE(installed_); 1836 ASSERT_EQ(1u, loaded_.size()); 1837 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString()); 1838 ASSERT_EQ(0u, GetErrors().size()); 1839 1840 // Upgrade to version 2.0 1841 path = extensions_path.AppendASCII("good2.crx"); 1842 StartCrxInstall(path); 1843 loop_.RunAllPending(); 1844 1845 ASSERT_TRUE(installed_); 1846 ASSERT_EQ(1u, loaded_.size()); 1847 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString()); 1848 ASSERT_EQ(0u, GetErrors().size()); 1849} 1850 1851// Test upgrading a signed extension with a bad signature. 1852TEST_F(ExtensionServiceTest, UpgradeSignedBad) { 1853 InitializeEmptyExtensionService(); 1854 FilePath extensions_path; 1855 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1856 extensions_path = extensions_path.AppendASCII("extensions"); 1857 1858 FilePath path = extensions_path.AppendASCII("good.crx"); 1859 StartCrxInstall(path); 1860 loop_.RunAllPending(); 1861 1862 ASSERT_TRUE(installed_); 1863 ASSERT_EQ(1u, loaded_.size()); 1864 ASSERT_EQ(0u, GetErrors().size()); 1865 installed_ = NULL; 1866 1867 // Try upgrading with a bad signature. This should fail during the unpack, 1868 // because the key will not match the signature. 1869 path = extensions_path.AppendASCII("bad_signature.crx"); 1870 StartCrxInstall(path); 1871 loop_.RunAllPending(); 1872 1873 ASSERT_FALSE(installed_); 1874 ASSERT_EQ(1u, loaded_.size()); 1875 ASSERT_EQ(1u, GetErrors().size()); 1876} 1877 1878// Test a normal update via the UpdateExtension API 1879TEST_F(ExtensionServiceTest, UpdateExtension) { 1880 InitializeEmptyExtensionService(); 1881 FilePath extensions_path; 1882 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1883 extensions_path = extensions_path.AppendASCII("extensions"); 1884 1885 FilePath path = extensions_path.AppendASCII("good.crx"); 1886 1887 InstallExtension(path, true); 1888 const Extension* good = service_->extensions()->at(0); 1889 ASSERT_EQ("1.0.0.0", good->VersionString()); 1890 ASSERT_EQ(good_crx, good->id()); 1891 1892 path = extensions_path.AppendASCII("good2.crx"); 1893 UpdateExtension(good_crx, path, ENABLED); 1894 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString()); 1895} 1896 1897// Test updating a not-already-installed extension - this should fail 1898TEST_F(ExtensionServiceTest, UpdateNotInstalledExtension) { 1899 InitializeEmptyExtensionService(); 1900 FilePath extensions_path; 1901 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1902 extensions_path = extensions_path.AppendASCII("extensions"); 1903 1904 FilePath path = extensions_path.AppendASCII("good.crx"); 1905 UpdateExtension(good_crx, path, UPDATED); 1906 loop_.RunAllPending(); 1907 1908 ASSERT_EQ(0u, service_->extensions()->size()); 1909 ASSERT_FALSE(installed_); 1910 ASSERT_EQ(0u, loaded_.size()); 1911} 1912 1913// Makes sure you can't downgrade an extension via UpdateExtension 1914TEST_F(ExtensionServiceTest, UpdateWillNotDowngrade) { 1915 InitializeEmptyExtensionService(); 1916 FilePath extensions_path; 1917 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1918 extensions_path = extensions_path.AppendASCII("extensions"); 1919 1920 FilePath path = extensions_path.AppendASCII("good2.crx"); 1921 1922 InstallExtension(path, true); 1923 const Extension* good = service_->extensions()->at(0); 1924 ASSERT_EQ("1.0.0.1", good->VersionString()); 1925 ASSERT_EQ(good_crx, good->id()); 1926 1927 // Change path from good2.crx -> good.crx 1928 path = extensions_path.AppendASCII("good.crx"); 1929 UpdateExtension(good_crx, path, FAILED); 1930 ASSERT_EQ("1.0.0.1", service_->extensions()->at(0)->VersionString()); 1931} 1932 1933// Make sure calling update with an identical version does nothing 1934TEST_F(ExtensionServiceTest, UpdateToSameVersionIsNoop) { 1935 InitializeEmptyExtensionService(); 1936 FilePath extensions_path; 1937 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1938 extensions_path = extensions_path.AppendASCII("extensions"); 1939 1940 FilePath path = extensions_path.AppendASCII("good.crx"); 1941 1942 InstallExtension(path, true); 1943 const Extension* good = service_->extensions()->at(0); 1944 ASSERT_EQ(good_crx, good->id()); 1945 UpdateExtension(good_crx, path, FAILED_SILENTLY); 1946} 1947 1948// Tests that updating an extension does not clobber old state. 1949TEST_F(ExtensionServiceTest, UpdateExtensionPreservesState) { 1950 InitializeEmptyExtensionService(); 1951 FilePath extensions_path; 1952 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1953 extensions_path = extensions_path.AppendASCII("extensions"); 1954 1955 FilePath path = extensions_path.AppendASCII("good.crx"); 1956 1957 InstallExtension(path, true); 1958 const Extension* good = service_->extensions()->at(0); 1959 ASSERT_EQ("1.0.0.0", good->VersionString()); 1960 ASSERT_EQ(good_crx, good->id()); 1961 1962 // Disable it and allow it to run in incognito. These settings should carry 1963 // over to the updated version. 1964 service_->DisableExtension(good->id()); 1965 service_->SetIsIncognitoEnabled(good, true); 1966 1967 path = extensions_path.AppendASCII("good2.crx"); 1968 UpdateExtension(good_crx, path, INSTALLED); 1969 ASSERT_EQ(1u, service_->disabled_extensions()->size()); 1970 const Extension* good2 = service_->disabled_extensions()->at(0); 1971 ASSERT_EQ("1.0.0.1", good2->version()->GetString()); 1972 EXPECT_TRUE(service_->IsIncognitoEnabled(good2)); 1973} 1974 1975// Tests that updating preserves extension location. 1976TEST_F(ExtensionServiceTest, UpdateExtensionPreservesLocation) { 1977 InitializeEmptyExtensionService(); 1978 FilePath extensions_path; 1979 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 1980 extensions_path = extensions_path.AppendASCII("extensions"); 1981 1982 FilePath path = extensions_path.AppendASCII("good.crx"); 1983 1984 InstallExtension(path, true); 1985 const Extension* good = service_->extensions()->at(0); 1986 1987 ASSERT_EQ("1.0.0.0", good->VersionString()); 1988 ASSERT_EQ(good_crx, good->id()); 1989 1990 // Simulate non-internal location. 1991 const_cast<Extension*>(good)->location_ = Extension::EXTERNAL_PREF; 1992 1993 path = extensions_path.AppendASCII("good2.crx"); 1994 UpdateExtension(good_crx, path, ENABLED); 1995 const Extension* good2 = service_->extensions()->at(0); 1996 ASSERT_EQ("1.0.0.1", good2->version()->GetString()); 1997 EXPECT_EQ(good2->location(), Extension::EXTERNAL_PREF); 1998} 1999 2000// Makes sure that LOAD extension types can downgrade. 2001TEST_F(ExtensionServiceTest, LoadExtensionsCanDowngrade) { 2002 InitializeEmptyExtensionService(); 2003 2004 ScopedTempDir temp; 2005 ASSERT_TRUE(temp.CreateUniqueTempDir()); 2006 2007 // We'll write the extension manifest dynamically to a temporary path 2008 // to make it easier to change the version number. 2009 FilePath extension_path = temp.path(); 2010 FilePath manifest_path = extension_path.Append(Extension::kManifestFilename); 2011 ASSERT_FALSE(file_util::PathExists(manifest_path)); 2012 2013 // Start with version 2.0. 2014 DictionaryValue manifest; 2015 manifest.SetString("version", "2.0"); 2016 manifest.SetString("name", "LOAD Downgrade Test"); 2017 2018 JSONFileValueSerializer serializer(manifest_path); 2019 ASSERT_TRUE(serializer.Serialize(manifest)); 2020 2021 service_->LoadExtension(extension_path); 2022 loop_.RunAllPending(); 2023 2024 EXPECT_EQ(0u, GetErrors().size()); 2025 ASSERT_EQ(1u, loaded_.size()); 2026 EXPECT_EQ(Extension::LOAD, loaded_[0]->location()); 2027 EXPECT_EQ(1u, service_->extensions()->size()); 2028 EXPECT_EQ("2.0", loaded_[0]->VersionString()); 2029 2030 // Now set the version number to 1.0, reload the extensions and verify that 2031 // the downgrade was accepted. 2032 manifest.SetString("version", "1.0"); 2033 ASSERT_TRUE(serializer.Serialize(manifest)); 2034 2035 service_->LoadExtension(extension_path); 2036 loop_.RunAllPending(); 2037 2038 EXPECT_EQ(0u, GetErrors().size()); 2039 ASSERT_EQ(1u, loaded_.size()); 2040 EXPECT_EQ(Extension::LOAD, loaded_[0]->location()); 2041 EXPECT_EQ(1u, service_->extensions()->size()); 2042 EXPECT_EQ("1.0", loaded_[0]->VersionString()); 2043} 2044 2045namespace { 2046 2047bool IsExtension(const Extension& extension) { 2048 return extension.GetType() == Extension::TYPE_EXTENSION; 2049} 2050 2051} // namespace 2052 2053// Test adding a pending extension. 2054TEST_F(ExtensionServiceTest, AddPendingExtensionFromSync) { 2055 InitializeEmptyExtensionService(); 2056 2057 const std::string kFakeId("fake-id"); 2058 const GURL kFakeUpdateURL("http:://fake.update/url"); 2059 const bool kFakeInstallSilently(true); 2060 const Extension::State kFakeInitialState(Extension::ENABLED); 2061 const bool kFakeInitialIncognitoEnabled(false); 2062 2063 service_->AddPendingExtensionFromSync( 2064 kFakeId, kFakeUpdateURL, &IsExtension, 2065 kFakeInstallSilently, kFakeInitialState, kFakeInitialIncognitoEnabled); 2066 PendingExtensionMap::const_iterator it = 2067 service_->pending_extensions().find(kFakeId); 2068 ASSERT_TRUE(it != service_->pending_extensions().end()); 2069 EXPECT_EQ(kFakeUpdateURL, it->second.update_url()); 2070 EXPECT_EQ(&IsExtension, it->second.should_allow_install_); 2071 EXPECT_EQ(kFakeInstallSilently, it->second.install_silently()); 2072} 2073 2074namespace { 2075const char kGoodId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; 2076const char kGoodUpdateURL[] = "http://good.update/url"; 2077const bool kGoodIsFromSync = true; 2078const bool kGoodInstallSilently = true; 2079const Extension::State kGoodInitialState = Extension::DISABLED; 2080const bool kGoodInitialIncognitoEnabled = true; 2081} // namespace 2082 2083// Test updating a pending extension. 2084TEST_F(ExtensionServiceTest, UpdatePendingExtension) { 2085 InitializeEmptyExtensionService(); 2086 service_->AddPendingExtensionFromSync( 2087 kGoodId, GURL(kGoodUpdateURL), &IsExtension, 2088 kGoodInstallSilently, kGoodInitialState, 2089 kGoodInitialIncognitoEnabled); 2090 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), kGoodId)); 2091 2092 FilePath extensions_path; 2093 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2094 extensions_path = extensions_path.AppendASCII("extensions"); 2095 FilePath path = extensions_path.AppendASCII("good.crx"); 2096 UpdateExtension(kGoodId, path, INSTALLED); 2097 2098 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId)); 2099 2100 const Extension* extension = service_->GetExtensionById(kGoodId, true); 2101 ASSERT_TRUE(extension); 2102 2103 bool enabled = service_->GetExtensionById(kGoodId, false); 2104 EXPECT_EQ(enabled, kGoodInitialState == Extension::ENABLED); 2105 EXPECT_EQ(kGoodInitialState, 2106 service_->extension_prefs()->GetExtensionState(extension->id())); 2107 EXPECT_EQ(kGoodInitialIncognitoEnabled, 2108 service_->IsIncognitoEnabled(extension)); 2109} 2110 2111namespace { 2112 2113bool IsTheme(const Extension& extension) { 2114 return extension.is_theme(); 2115} 2116 2117} // namespace 2118 2119// Test updating a pending theme. 2120TEST_F(ExtensionServiceTest, UpdatePendingTheme) { 2121 InitializeEmptyExtensionService(); 2122 service_->AddPendingExtensionFromSync( 2123 theme_crx, GURL(), &IsTheme, 2124 false, Extension::ENABLED, false); 2125 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), theme_crx)); 2126 2127 FilePath extensions_path; 2128 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2129 extensions_path = extensions_path.AppendASCII("extensions"); 2130 FilePath path = extensions_path.AppendASCII("theme.crx"); 2131 UpdateExtension(theme_crx, path, ENABLED); 2132 2133 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), theme_crx)); 2134 2135 const Extension* extension = service_->GetExtensionById(theme_crx, true); 2136 ASSERT_TRUE(extension); 2137 2138 EXPECT_EQ(Extension::ENABLED, 2139 service_->extension_prefs()->GetExtensionState(extension->id())); 2140 EXPECT_FALSE(service_->IsIncognitoEnabled(extension)); 2141} 2142 2143// Test updating a pending CRX as if the source is an external extension 2144// with an update URL. In this case we don't know if the CRX is a theme 2145// or not. 2146TEST_F(ExtensionServiceTest, UpdatePendingExternalCrx) { 2147 InitializeEmptyExtensionService(); 2148 service_->AddPendingExtensionFromExternalUpdateUrl( 2149 theme_crx, GURL(), Extension::EXTERNAL_PREF_DOWNLOAD); 2150 2151 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), theme_crx)); 2152 2153 FilePath extensions_path; 2154 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2155 extensions_path = extensions_path.AppendASCII("extensions"); 2156 FilePath path = extensions_path.AppendASCII("theme.crx"); 2157 UpdateExtension(theme_crx, path, ENABLED); 2158 2159 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), theme_crx)); 2160 2161 const Extension* extension = service_->GetExtensionById(theme_crx, true); 2162 ASSERT_TRUE(extension); 2163 2164 EXPECT_EQ(Extension::ENABLED, 2165 service_->extension_prefs()->GetExtensionState(extension->id())); 2166 EXPECT_FALSE(service_->IsIncognitoEnabled(extension)); 2167} 2168 2169// Test updating a pending CRX as if the source is an external extension 2170// with an update URL. The external update should overwrite a sync update, 2171// but a sync update should not overwrite a non-sync update. 2172TEST_F(ExtensionServiceTest, UpdatePendingExternalCrxWinsOverSync) { 2173 InitializeEmptyExtensionService(); 2174 2175 // Add a crx to be installed from the update mechanism. 2176 service_->AddPendingExtensionFromSync( 2177 kGoodId, GURL(kGoodUpdateURL), &IsExtension, 2178 kGoodInstallSilently, kGoodInitialState, 2179 kGoodInitialIncognitoEnabled); 2180 2181 // Check that there is a pending crx, with is_from_sync set to true. 2182 PendingExtensionMap::const_iterator it; 2183 it = service_->pending_extensions().find(kGoodId); 2184 ASSERT_TRUE(it != service_->pending_extensions().end()); 2185 EXPECT_TRUE(it->second.is_from_sync()); 2186 2187 // Add a crx to be updated, with the same ID, from a non-sync source. 2188 service_->AddPendingExtensionFromExternalUpdateUrl( 2189 kGoodId, GURL(kGoodUpdateURL), Extension::EXTERNAL_PREF_DOWNLOAD); 2190 2191 // Check that there is a pending crx, with is_from_sync set to false. 2192 it = service_->pending_extensions().find(kGoodId); 2193 ASSERT_TRUE(it != service_->pending_extensions().end()); 2194 EXPECT_FALSE(it->second.is_from_sync()); 2195 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, it->second.install_source()); 2196 2197 // Add a crx to be installed from the update mechanism. 2198 service_->AddPendingExtensionFromSync( 2199 kGoodId, GURL(kGoodUpdateURL), &IsExtension, 2200 kGoodInstallSilently, kGoodInitialState, 2201 kGoodInitialIncognitoEnabled); 2202 2203 // Check that the external, non-sync update was not overridden. 2204 it = service_->pending_extensions().find(kGoodId); 2205 ASSERT_TRUE(it != service_->pending_extensions().end()); 2206 EXPECT_FALSE(it->second.is_from_sync()); 2207 EXPECT_EQ(Extension::EXTERNAL_PREF_DOWNLOAD, it->second.install_source()); 2208} 2209 2210// Updating a theme should fail if the updater is explicitly told that 2211// the CRX is not a theme. 2212TEST_F(ExtensionServiceTest, UpdatePendingCrxThemeMismatch) { 2213 InitializeEmptyExtensionService(); 2214 service_->AddPendingExtensionFromSync( 2215 theme_crx, GURL(), &IsExtension, 2216 true, Extension::ENABLED, false); 2217 2218 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), theme_crx)); 2219 2220 FilePath extensions_path; 2221 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2222 extensions_path = extensions_path.AppendASCII("extensions"); 2223 FilePath path = extensions_path.AppendASCII("theme.crx"); 2224 UpdateExtension(theme_crx, path, FAILED_SILENTLY); 2225 2226 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), theme_crx)); 2227 2228 const Extension* extension = service_->GetExtensionById(theme_crx, true); 2229 ASSERT_FALSE(extension); 2230} 2231 2232// TODO(akalin): Test updating a pending extension non-silently once 2233// we can mock out ExtensionInstallUI and inject our version into 2234// UpdateExtension(). 2235 2236// Test updating a pending extension which fails the should-install test. 2237TEST_F(ExtensionServiceTest, UpdatePendingExtensionFailedShouldInstallTest) { 2238 InitializeEmptyExtensionService(); 2239 // Add pending extension with a flipped is_theme. 2240 service_->AddPendingExtensionFromSync( 2241 kGoodId, GURL(kGoodUpdateURL), &IsTheme, 2242 kGoodInstallSilently, kGoodInitialState, 2243 kGoodInitialIncognitoEnabled); 2244 EXPECT_TRUE(ContainsKey(service_->pending_extensions(), kGoodId)); 2245 2246 FilePath extensions_path; 2247 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2248 extensions_path = extensions_path.AppendASCII("extensions"); 2249 FilePath path = extensions_path.AppendASCII("good.crx"); 2250 UpdateExtension(kGoodId, path, UPDATED); 2251 2252 // TODO(akalin): Figure out how to check that the extensions 2253 // directory is cleaned up properly in OnExtensionInstalled(). 2254 2255 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId)); 2256} 2257 2258// TODO(akalin): Figure out how to test that installs of pending 2259// unsyncable extensions are blocked. 2260 2261// Test updating a pending extension for one that is not pending. 2262TEST_F(ExtensionServiceTest, UpdatePendingExtensionNotPending) { 2263 InitializeEmptyExtensionService(); 2264 2265 FilePath extensions_path; 2266 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2267 extensions_path = extensions_path.AppendASCII("extensions"); 2268 FilePath path = extensions_path.AppendASCII("good.crx"); 2269 UpdateExtension(kGoodId, path, UPDATED); 2270 2271 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId)); 2272} 2273 2274// Test updating a pending extension for one that is already 2275// installed. 2276TEST_F(ExtensionServiceTest, UpdatePendingExtensionAlreadyInstalled) { 2277 InitializeEmptyExtensionService(); 2278 2279 FilePath extensions_path; 2280 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2281 extensions_path = extensions_path.AppendASCII("extensions"); 2282 FilePath path = extensions_path.AppendASCII("good.crx"); 2283 InstallExtension(path, true); 2284 ASSERT_EQ(1u, service_->extensions()->size()); 2285 const Extension* good = service_->extensions()->at(0); 2286 2287 EXPECT_FALSE(good->is_theme()); 2288 2289 // Use AddPendingExtensionInternal() as AddPendingExtension() would 2290 // balk. 2291 service_->AddPendingExtensionInternal( 2292 good->id(), good->update_url(), &IsExtension, 2293 kGoodIsFromSync, kGoodInstallSilently, kGoodInitialState, 2294 kGoodInitialIncognitoEnabled, Extension::INTERNAL); 2295 UpdateExtension(good->id(), path, INSTALLED); 2296 2297 EXPECT_FALSE(ContainsKey(service_->pending_extensions(), kGoodId)); 2298} 2299 2300// Test pref settings for blacklist and unblacklist extensions. 2301TEST_F(ExtensionServiceTest, SetUnsetBlacklistInPrefs) { 2302 InitializeEmptyExtensionService(); 2303 std::vector<std::string> blacklist; 2304 blacklist.push_back(good0); 2305 blacklist.push_back("invalid_id"); // an invalid id 2306 blacklist.push_back(good1); 2307 service_->UpdateExtensionBlacklist(blacklist); 2308 // Make sure pref is updated 2309 loop_.RunAllPending(); 2310 2311 // blacklist is set for good0,1,2 2312 ValidateBooleanPref(good0, "blacklist", true); 2313 ValidateBooleanPref(good1, "blacklist", true); 2314 // invalid_id should not be inserted to pref. 2315 EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist")); 2316 2317 // remove good1, add good2 2318 blacklist.pop_back(); 2319 blacklist.push_back(good2); 2320 2321 service_->UpdateExtensionBlacklist(blacklist); 2322 // only good0 and good1 should be set 2323 ValidateBooleanPref(good0, "blacklist", true); 2324 EXPECT_FALSE(IsPrefExist(good1, "blacklist")); 2325 ValidateBooleanPref(good2, "blacklist", true); 2326 EXPECT_FALSE(IsPrefExist("invalid_id", "blacklist")); 2327} 2328 2329// Unload installed extension from blacklist. 2330TEST_F(ExtensionServiceTest, UnloadBlacklistedExtension) { 2331 InitializeEmptyExtensionService(); 2332 FilePath extensions_path; 2333 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2334 extensions_path = extensions_path.AppendASCII("extensions"); 2335 2336 FilePath path = extensions_path.AppendASCII("good.crx"); 2337 2338 InstallExtension(path, true); 2339 const Extension* good = service_->extensions()->at(0); 2340 EXPECT_EQ(good_crx, good->id()); 2341 UpdateExtension(good_crx, path, FAILED_SILENTLY); 2342 2343 std::vector<std::string> blacklist; 2344 blacklist.push_back(good_crx); 2345 service_->UpdateExtensionBlacklist(blacklist); 2346 // Make sure pref is updated 2347 loop_.RunAllPending(); 2348 2349 // Now, the good_crx is blacklisted. 2350 ValidateBooleanPref(good_crx, "blacklist", true); 2351 EXPECT_EQ(0u, service_->extensions()->size()); 2352 2353 // Remove good_crx from blacklist 2354 blacklist.pop_back(); 2355 service_->UpdateExtensionBlacklist(blacklist); 2356 // Make sure pref is updated 2357 loop_.RunAllPending(); 2358 // blacklist value should not be set for good_crx 2359 EXPECT_FALSE(IsPrefExist(good_crx, "blacklist")); 2360} 2361 2362// Unload installed extension from blacklist. 2363TEST_F(ExtensionServiceTest, BlacklistedExtensionWillNotInstall) { 2364 InitializeEmptyExtensionService(); 2365 std::vector<std::string> blacklist; 2366 blacklist.push_back(good_crx); 2367 service_->UpdateExtensionBlacklist(blacklist); 2368 // Make sure pref is updated 2369 loop_.RunAllPending(); 2370 2371 // Now, the good_crx is blacklisted. 2372 ValidateBooleanPref(good_crx, "blacklist", true); 2373 2374 // We can not install good_crx. 2375 FilePath extensions_path; 2376 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2377 extensions_path = extensions_path.AppendASCII("extensions"); 2378 FilePath path = extensions_path.AppendASCII("good.crx"); 2379 StartCrxInstall(path); 2380 loop_.RunAllPending(); 2381 EXPECT_EQ(0u, service_->extensions()->size()); 2382 ValidateBooleanPref(good_crx, "blacklist", true); 2383} 2384 2385// Test loading extensions from the profile directory, except 2386// blacklisted ones. 2387TEST_F(ExtensionServiceTest, WillNotLoadBlacklistedExtensionsFromDirectory) { 2388 // Initialize the test dir with a good Preferences/extensions. 2389 FilePath source_install_dir; 2390 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); 2391 source_install_dir = source_install_dir 2392 .AppendASCII("extensions") 2393 .AppendASCII("good") 2394 .AppendASCII("Extensions"); 2395 FilePath pref_path = source_install_dir 2396 .DirName() 2397 .AppendASCII("Preferences"); 2398 InitializeInstalledExtensionService(pref_path, source_install_dir); 2399 2400 // Blacklist good1. 2401 std::vector<std::string> blacklist; 2402 blacklist.push_back(good1); 2403 service_->UpdateExtensionBlacklist(blacklist); 2404 // Make sure pref is updated 2405 loop_.RunAllPending(); 2406 2407 ValidateBooleanPref(good1, "blacklist", true); 2408 2409 // Load extensions. 2410 service_->Init(); 2411 loop_.RunAllPending(); 2412 2413 std::vector<std::string> errors = GetErrors(); 2414 for (std::vector<std::string>::iterator err = errors.begin(); 2415 err != errors.end(); ++err) { 2416 LOG(ERROR) << *err; 2417 } 2418 ASSERT_EQ(2u, loaded_.size()); 2419 2420 EXPECT_NE(std::string(good1), loaded_[0]->id()); 2421 EXPECT_NE(std::string(good1), loaded_[1]->id()); 2422} 2423 2424#if defined(OS_CHROMEOS) 2425// Test loading extensions from the profile directory, except 2426// ones with a plugin. 2427TEST_F(ExtensionServiceTest, WillNotLoadPluginExtensionsFromDirectory) { 2428 // Initialize the test dir with a good Preferences/extensions. 2429 FilePath source_install_dir; 2430 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); 2431 source_install_dir = source_install_dir 2432 .AppendASCII("extensions") 2433 .AppendASCII("good") 2434 .AppendASCII("Extensions"); 2435 FilePath pref_path = source_install_dir 2436 .DirName() 2437 .AppendASCII("Preferences"); 2438 InitializeInstalledExtensionService(pref_path, source_install_dir); 2439 2440 // good1 contains a plugin. 2441 // Load extensions. 2442 service_->Init(); 2443 loop_.RunAllPending(); 2444 2445 std::vector<std::string> errors = GetErrors(); 2446 for (std::vector<std::string>::iterator err = errors.begin(); 2447 err != errors.end(); ++err) { 2448 LOG(ERROR) << *err; 2449 } 2450 ASSERT_EQ(2u, loaded_.size()); 2451 2452 EXPECT_NE(std::string(good1), loaded_[0]->id()); 2453 EXPECT_NE(std::string(good1), loaded_[1]->id()); 2454} 2455#endif 2456 2457// Will not install extension blacklisted by policy. 2458TEST_F(ExtensionServiceTest, BlacklistedByPolicyWillNotInstall) { 2459 InitializeEmptyExtensionService(); 2460 2461 ListValue* whitelist = 2462 profile_->GetPrefs()->GetMutableList(prefs::kExtensionInstallAllowList); 2463 ListValue* blacklist = 2464 profile_->GetPrefs()->GetMutableList(prefs::kExtensionInstallDenyList); 2465 ASSERT_TRUE(whitelist != NULL && blacklist != NULL); 2466 2467 // Blacklist everything. 2468 blacklist->Append(Value::CreateStringValue("*")); 2469 2470 // Blacklist prevents us from installing good_crx. 2471 FilePath extensions_path; 2472 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2473 extensions_path = extensions_path.AppendASCII("extensions"); 2474 FilePath path = extensions_path.AppendASCII("good.crx"); 2475 StartCrxInstall(path); 2476 loop_.RunAllPending(); 2477 EXPECT_EQ(0u, service_->extensions()->size()); 2478 2479 // Now whitelist this particular extension. 2480 whitelist->Append(Value::CreateStringValue(good_crx)); 2481 2482 // Ensure we can now install good_crx. 2483 StartCrxInstall(path); 2484 loop_.RunAllPending(); 2485 EXPECT_EQ(1u, service_->extensions()->size()); 2486} 2487 2488// Extension blacklisted by policy get unloaded after installing. 2489TEST_F(ExtensionServiceTest, BlacklistedByPolicyRemovedIfRunning) { 2490 InitializeEmptyExtensionService(); 2491 2492 // Install good_crx. 2493 FilePath extensions_path; 2494 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2495 extensions_path = extensions_path.AppendASCII("extensions"); 2496 FilePath path = extensions_path.AppendASCII("good.crx"); 2497 StartCrxInstall(path); 2498 loop_.RunAllPending(); 2499 EXPECT_EQ(1u, service_->extensions()->size()); 2500 2501 { // Scope for pref update notification. 2502 PrefService* prefs = profile_->GetPrefs(); 2503 ScopedUserPrefUpdate pref_update(prefs, prefs::kExtensionInstallDenyList); 2504 ListValue* blacklist = 2505 prefs->GetMutableList(prefs::kExtensionInstallDenyList); 2506 ASSERT_TRUE(blacklist != NULL); 2507 2508 // Blacklist this extension. 2509 blacklist->Append(Value::CreateStringValue(good_crx)); 2510 prefs->ScheduleSavePersistentPrefs(); 2511 } 2512 2513 // Extension should not be running now. 2514 loop_.RunAllPending(); 2515 EXPECT_EQ(0u, service_->extensions()->size()); 2516} 2517 2518// Tests disabling extensions 2519TEST_F(ExtensionServiceTest, DisableExtension) { 2520 InitializeEmptyExtensionService(); 2521 FilePath extensions_path; 2522 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2523 extensions_path = extensions_path.AppendASCII("extensions"); 2524 2525 // A simple extension that should install without error. 2526 FilePath path = extensions_path.AppendASCII("good.crx"); 2527 InstallExtension(path, true); 2528 2529 const char* extension_id = good_crx; 2530 EXPECT_FALSE(service_->extensions()->empty()); 2531 EXPECT_TRUE(service_->GetExtensionById(extension_id, true) != NULL); 2532 EXPECT_TRUE(service_->GetExtensionById(extension_id, false) != NULL); 2533 EXPECT_TRUE(service_->disabled_extensions()->empty()); 2534 2535 // Disable it. 2536 service_->DisableExtension(extension_id); 2537 2538 EXPECT_TRUE(service_->extensions()->empty()); 2539 EXPECT_TRUE(service_->GetExtensionById(extension_id, true) != NULL); 2540 EXPECT_FALSE(service_->GetExtensionById(extension_id, false) != NULL); 2541 EXPECT_FALSE(service_->disabled_extensions()->empty()); 2542} 2543 2544// Tests disabling all extensions (simulating --disable-extensions flag). 2545TEST_F(ExtensionServiceTest, DisableAllExtensions) { 2546 InitializeEmptyExtensionService(); 2547 2548 FilePath extensions_path; 2549 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2550 extensions_path = extensions_path.AppendASCII("extensions"); 2551 2552 FilePath path = extensions_path.AppendASCII("good.crx"); 2553 InstallExtension(path, true); 2554 2555 EXPECT_EQ(1u, service_->extensions()->size()); 2556 EXPECT_EQ(0u, service_->disabled_extensions()->size()); 2557 2558 // Disable extensions. 2559 service_->set_extensions_enabled(false); 2560 service_->ReloadExtensions(); 2561 2562 // There shouldn't be extensions in either list. 2563 EXPECT_EQ(0u, service_->extensions()->size()); 2564 EXPECT_EQ(0u, service_->disabled_extensions()->size()); 2565 2566 // This shouldn't do anything when all extensions are disabled. 2567 service_->EnableExtension(good_crx); 2568 service_->ReloadExtensions(); 2569 2570 // There still shouldn't be extensions in either list. 2571 EXPECT_EQ(0u, service_->extensions()->size()); 2572 EXPECT_EQ(0u, service_->disabled_extensions()->size()); 2573 2574 // And then re-enable the extensions. 2575 service_->set_extensions_enabled(true); 2576 service_->ReloadExtensions(); 2577 2578 EXPECT_EQ(1u, service_->extensions()->size()); 2579 EXPECT_EQ(0u, service_->disabled_extensions()->size()); 2580} 2581 2582// Tests reloading extensions 2583TEST_F(ExtensionServiceTest, ReloadExtensions) { 2584 InitializeEmptyExtensionService(); 2585 FilePath extensions_path; 2586 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2587 extensions_path = extensions_path.AppendASCII("extensions"); 2588 2589 // Simple extension that should install without error. 2590 FilePath path = extensions_path.AppendASCII("good.crx"); 2591 InstallExtension(path, true); 2592 const char* extension_id = good_crx; 2593 service_->DisableExtension(extension_id); 2594 2595 EXPECT_EQ(0u, service_->extensions()->size()); 2596 EXPECT_EQ(1u, service_->disabled_extensions()->size()); 2597 2598 service_->ReloadExtensions(); 2599 2600 // Extension counts shouldn't change. 2601 EXPECT_EQ(0u, service_->extensions()->size()); 2602 EXPECT_EQ(1u, service_->disabled_extensions()->size()); 2603 2604 service_->EnableExtension(extension_id); 2605 2606 EXPECT_EQ(1u, service_->extensions()->size()); 2607 EXPECT_EQ(0u, service_->disabled_extensions()->size()); 2608 2609 // Need to clear |loaded_| manually before reloading as the 2610 // EnableExtension() call above inserted into it and 2611 // UnloadAllExtensions() doesn't send out notifications. 2612 loaded_.clear(); 2613 service_->ReloadExtensions(); 2614 2615 // Extension counts shouldn't change. 2616 EXPECT_EQ(1u, service_->extensions()->size()); 2617 EXPECT_EQ(0u, service_->disabled_extensions()->size()); 2618} 2619 2620// Tests uninstalling normal extensions 2621TEST_F(ExtensionServiceTest, UninstallExtension) { 2622 InitializeEmptyExtensionService(); 2623 FilePath extensions_path; 2624 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2625 extensions_path = extensions_path.AppendASCII("extensions"); 2626 2627 // A simple extension that should install without error. 2628 FilePath path = extensions_path.AppendASCII("good.crx"); 2629 InstallExtension(path, true); 2630 2631 // The directory should be there now. 2632 const char* extension_id = good_crx; 2633 FilePath extension_path = extensions_install_dir_.AppendASCII(extension_id); 2634 EXPECT_TRUE(file_util::PathExists(extension_path)); 2635 2636 ValidatePrefKeyCount(1); 2637 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 2638 ValidateIntegerPref(good_crx, "location", Extension::INTERNAL); 2639 2640 // Uninstall it. 2641 service_->UninstallExtension(extension_id, false); 2642 total_successes_ = 0; 2643 2644 // We should get an unload notification. 2645 ASSERT_TRUE(unloaded_id_.length()); 2646 EXPECT_EQ(extension_id, unloaded_id_); 2647 2648 ValidatePrefKeyCount(0); 2649 2650 // The extension should not be in the service anymore. 2651 ASSERT_FALSE(service_->GetExtensionById(extension_id, false)); 2652 loop_.RunAllPending(); 2653 2654 // The directory should be gone. 2655 EXPECT_FALSE(file_util::PathExists(extension_path)); 2656} 2657 2658// Tests the uninstaller helper. 2659TEST_F(ExtensionServiceTest, UninstallExtensionHelper) { 2660 InitializeEmptyExtensionService(); 2661 FilePath extensions_path; 2662 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2663 extensions_path = extensions_path.AppendASCII("extensions"); 2664 2665 // A simple extension that should install without error. 2666 FilePath path = extensions_path.AppendASCII("good.crx"); 2667 InstallExtension(path, true); 2668 2669 // The directory should be there now. 2670 const char* extension_id = good_crx; 2671 FilePath extension_path = extensions_install_dir_.AppendASCII(extension_id); 2672 EXPECT_TRUE(file_util::PathExists(extension_path)); 2673 2674 bool result = ExtensionService::UninstallExtensionHelper(service_, 2675 extension_id); 2676 total_successes_ = 0; 2677 2678 EXPECT_TRUE(result); 2679 2680 // We should get an unload notification. 2681 ASSERT_TRUE(unloaded_id_.length()); 2682 EXPECT_EQ(extension_id, unloaded_id_); 2683 2684 ValidatePrefKeyCount(0); 2685 2686 // The extension should not be in the service anymore. 2687 ASSERT_FALSE(service_->GetExtensionById(extension_id, false)); 2688 loop_.RunAllPending(); 2689 2690 // The directory should be gone. 2691 EXPECT_FALSE(file_util::PathExists(extension_path)); 2692 2693 // Attempt to uninstall again. This should fail as we just removed the 2694 // extension. 2695 result = ExtensionService::UninstallExtensionHelper(service_, extension_id); 2696 EXPECT_FALSE(result); 2697} 2698 2699// Verifies extension state is removed upon uninstall 2700TEST_F(ExtensionServiceTest, ClearExtensionData) { 2701 InitializeEmptyExtensionService(); 2702 2703 // Load a test extension. 2704 FilePath path; 2705 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path)); 2706 path = path.AppendASCII("extensions"); 2707 path = path.AppendASCII("good.crx"); 2708 InstallExtension(path, true); 2709 const Extension* extension = service_->GetExtensionById(good_crx, false); 2710 ASSERT_TRUE(extension); 2711 GURL ext_url(extension->url()); 2712 string16 origin_id = 2713 webkit_database::DatabaseUtil::GetOriginIdentifier(ext_url); 2714 2715 // Set a cookie for the extension. 2716 net::CookieMonster* cookie_monster = profile_ 2717 ->GetRequestContextForExtensions()->GetCookieStore()->GetCookieMonster(); 2718 ASSERT_TRUE(cookie_monster); 2719 net::CookieOptions options; 2720 cookie_monster->SetCookieWithOptions(ext_url, "dummy=value", options); 2721 net::CookieList list = cookie_monster->GetAllCookiesForURL(ext_url); 2722 EXPECT_EQ(1U, list.size()); 2723 2724 // Open a database. 2725 webkit_database::DatabaseTracker* db_tracker = profile_->GetDatabaseTracker(); 2726 string16 db_name = UTF8ToUTF16("db"); 2727 string16 description = UTF8ToUTF16("db_description"); 2728 int64 size; 2729 int64 available; 2730 db_tracker->DatabaseOpened(origin_id, db_name, description, 1, &size, 2731 &available); 2732 db_tracker->DatabaseClosed(origin_id, db_name); 2733 std::vector<webkit_database::OriginInfo> origins; 2734 db_tracker->GetAllOriginsInfo(&origins); 2735 EXPECT_EQ(1U, origins.size()); 2736 EXPECT_EQ(origin_id, origins[0].GetOrigin()); 2737 2738 // Create local storage. We only simulate this by creating the backing file 2739 // since webkit is not initialized. 2740 DOMStorageContext* context = 2741 profile_->GetWebKitContext()->dom_storage_context(); 2742 FilePath lso_path = context->GetLocalStorageFilePath(origin_id); 2743 EXPECT_TRUE(file_util::CreateDirectory(lso_path.DirName())); 2744 EXPECT_EQ(0, file_util::WriteFile(lso_path, NULL, 0)); 2745 EXPECT_TRUE(file_util::PathExists(lso_path)); 2746 2747 // Create indexed db. Again, it is enough to only simulate this by creating 2748 // the file on the disk. 2749 IndexedDBContext* idb_context = 2750 profile_->GetWebKitContext()->indexed_db_context(); 2751 FilePath idb_path = idb_context->GetIndexedDBFilePath(origin_id); 2752 EXPECT_TRUE(file_util::CreateDirectory(idb_path.DirName())); 2753 EXPECT_EQ(0, file_util::WriteFile(idb_path, NULL, 0)); 2754 EXPECT_TRUE(file_util::PathExists(idb_path)); 2755 2756 // Uninstall the extension. 2757 service_->UninstallExtension(good_crx, false); 2758 loop_.RunAllPending(); 2759 2760 // Check that the cookie is gone. 2761 list = cookie_monster->GetAllCookiesForURL(ext_url); 2762 EXPECT_EQ(0U, list.size()); 2763 2764 // The database should have vanished as well. 2765 origins.clear(); 2766 db_tracker->GetAllOriginsInfo(&origins); 2767 EXPECT_EQ(0U, origins.size()); 2768 2769 // Check that the LSO file has been removed. 2770 EXPECT_FALSE(file_util::PathExists(lso_path)); 2771 2772 // Check if the indexed db has disappeared too. 2773 EXPECT_FALSE(file_util::PathExists(idb_path)); 2774} 2775 2776// Tests loading single extensions (like --load-extension) 2777TEST_F(ExtensionServiceTest, LoadExtension) { 2778 InitializeEmptyExtensionService(); 2779 FilePath extensions_path; 2780 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2781 extensions_path = extensions_path.AppendASCII("extensions"); 2782 2783 FilePath ext1 = extensions_path 2784 .AppendASCII("good") 2785 .AppendASCII("Extensions") 2786 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") 2787 .AppendASCII("1.0.0.0"); 2788 service_->LoadExtension(ext1); 2789 loop_.RunAllPending(); 2790 EXPECT_EQ(0u, GetErrors().size()); 2791 ASSERT_EQ(1u, loaded_.size()); 2792 EXPECT_EQ(Extension::LOAD, loaded_[0]->location()); 2793 EXPECT_EQ(1u, service_->extensions()->size()); 2794 2795 ValidatePrefKeyCount(1); 2796 2797 FilePath no_manifest = extensions_path 2798 .AppendASCII("bad") 2799 // .AppendASCII("Extensions") 2800 .AppendASCII("cccccccccccccccccccccccccccccccc") 2801 .AppendASCII("1"); 2802 service_->LoadExtension(no_manifest); 2803 loop_.RunAllPending(); 2804 EXPECT_EQ(1u, GetErrors().size()); 2805 ASSERT_EQ(1u, loaded_.size()); 2806 EXPECT_EQ(1u, service_->extensions()->size()); 2807 2808 // Test uninstall. 2809 std::string id = loaded_[0]->id(); 2810 EXPECT_FALSE(unloaded_id_.length()); 2811 service_->UninstallExtension(id, false); 2812 loop_.RunAllPending(); 2813 EXPECT_EQ(id, unloaded_id_); 2814 ASSERT_EQ(0u, loaded_.size()); 2815 EXPECT_EQ(0u, service_->extensions()->size()); 2816} 2817 2818// Tests that we generate IDs when they are not specified in the manifest for 2819// --load-extension. 2820TEST_F(ExtensionServiceTest, GenerateID) { 2821 InitializeEmptyExtensionService(); 2822 2823 FilePath extensions_path; 2824 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 2825 extensions_path = extensions_path.AppendASCII("extensions"); 2826 2827 FilePath no_id_ext = extensions_path.AppendASCII("no_id"); 2828 service_->LoadExtension(no_id_ext); 2829 loop_.RunAllPending(); 2830 EXPECT_EQ(0u, GetErrors().size()); 2831 ASSERT_EQ(1u, loaded_.size()); 2832 ASSERT_TRUE(Extension::IdIsValid(loaded_[0]->id())); 2833 EXPECT_EQ(loaded_[0]->location(), Extension::LOAD); 2834 2835 ValidatePrefKeyCount(1); 2836 2837 std::string previous_id = loaded_[0]->id(); 2838 2839 // If we reload the same path, we should get the same extension ID. 2840 service_->LoadExtension(no_id_ext); 2841 loop_.RunAllPending(); 2842 ASSERT_EQ(1u, loaded_.size()); 2843 ASSERT_EQ(previous_id, loaded_[0]->id()); 2844} 2845 2846void ExtensionServiceTest::TestExternalProvider( 2847 MockExtensionProvider* provider, Extension::Location location) { 2848 // Verify that starting with no providers loads no extensions. 2849 service_->Init(); 2850 loop_.RunAllPending(); 2851 ASSERT_EQ(0u, loaded_.size()); 2852 2853 provider->set_visit_count(0); 2854 2855 // Register a test extension externally using the mock registry provider. 2856 FilePath source_path; 2857 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_path)); 2858 source_path = source_path.AppendASCII("extensions").AppendASCII("good.crx"); 2859 2860 // Add the extension. 2861 provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path); 2862 2863 // Reloading extensions should find our externally registered extension 2864 // and install it. 2865 service_->CheckForExternalUpdates(); 2866 loop_.RunAllPending(); 2867 2868 ASSERT_EQ(0u, GetErrors().size()); 2869 ASSERT_EQ(1u, loaded_.size()); 2870 ASSERT_EQ(location, loaded_[0]->location()); 2871 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString()); 2872 ValidatePrefKeyCount(1); 2873 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 2874 ValidateIntegerPref(good_crx, "location", location); 2875 2876 // Reload extensions without changing anything. The extension should be 2877 // loaded again. 2878 loaded_.clear(); 2879 service_->ReloadExtensions(); 2880 loop_.RunAllPending(); 2881 ASSERT_EQ(0u, GetErrors().size()); 2882 ASSERT_EQ(1u, loaded_.size()); 2883 ValidatePrefKeyCount(1); 2884 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 2885 ValidateIntegerPref(good_crx, "location", location); 2886 2887 // Now update the extension with a new version. We should get upgraded. 2888 source_path = source_path.DirName().AppendASCII("good2.crx"); 2889 provider->UpdateOrAddExtension(good_crx, "1.0.0.1", source_path); 2890 2891 loaded_.clear(); 2892 service_->CheckForExternalUpdates(); 2893 loop_.RunAllPending(); 2894 ASSERT_EQ(0u, GetErrors().size()); 2895 ASSERT_EQ(1u, loaded_.size()); 2896 ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString()); 2897 ValidatePrefKeyCount(1); 2898 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 2899 ValidateIntegerPref(good_crx, "location", location); 2900 2901 // Uninstall the extension and reload. Nothing should happen because the 2902 // preference should prevent us from reinstalling. 2903 std::string id = loaded_[0]->id(); 2904 service_->UninstallExtension(id, false); 2905 loop_.RunAllPending(); 2906 2907 // The extension should also be gone from the install directory. 2908 FilePath install_path = extensions_install_dir_.AppendASCII(id); 2909 ASSERT_FALSE(file_util::PathExists(install_path)); 2910 2911 loaded_.clear(); 2912 service_->CheckForExternalUpdates(); 2913 loop_.RunAllPending(); 2914 ASSERT_EQ(0u, loaded_.size()); 2915 ValidatePrefKeyCount(1); 2916 ValidateIntegerPref(good_crx, "state", Extension::KILLBIT); 2917 ValidateIntegerPref(good_crx, "location", location); 2918 2919 // Now clear the preference and reinstall. 2920 SetPrefInteg(good_crx, "state", Extension::ENABLED); 2921 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); 2922 2923 loaded_.clear(); 2924 service_->CheckForExternalUpdates(); 2925 loop_.RunAllPending(); 2926 ASSERT_EQ(1u, loaded_.size()); 2927 ValidatePrefKeyCount(1); 2928 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 2929 ValidateIntegerPref(good_crx, "location", location); 2930 2931 // Now test an externally triggered uninstall (deleting the registry key or 2932 // the pref entry). 2933 provider->RemoveExtension(good_crx); 2934 2935 loaded_.clear(); 2936 service_->OnExternalProviderReady(); 2937 loop_.RunAllPending(); 2938 ASSERT_EQ(0u, loaded_.size()); 2939 ValidatePrefKeyCount(0); 2940 2941 // The extension should also be gone from the install directory. 2942 ASSERT_FALSE(file_util::PathExists(install_path)); 2943 2944 // Now test the case where user uninstalls and then the extension is removed 2945 // from the external provider. 2946 2947 provider->UpdateOrAddExtension(good_crx, "1.0", source_path); 2948 service_->CheckForExternalUpdates(); 2949 loop_.RunAllPending(); 2950 2951 ASSERT_EQ(1u, loaded_.size()); 2952 ASSERT_EQ(0u, GetErrors().size()); 2953 2954 // User uninstalls. 2955 loaded_.clear(); 2956 service_->UninstallExtension(id, false); 2957 loop_.RunAllPending(); 2958 ASSERT_EQ(0u, loaded_.size()); 2959 2960 // Then remove the extension from the extension provider. 2961 provider->RemoveExtension(good_crx); 2962 2963 // Should still be at 0. 2964 loaded_.clear(); 2965 service_->LoadAllExtensions(); 2966 loop_.RunAllPending(); 2967 ASSERT_EQ(0u, loaded_.size()); 2968 ValidatePrefKeyCount(1); 2969 2970 EXPECT_EQ(5, provider->visit_count()); 2971} 2972 2973// Tests the external installation feature 2974#if defined(OS_WIN) 2975TEST_F(ExtensionServiceTest, ExternalInstallRegistry) { 2976 // This should all work, even when normal extension installation is disabled. 2977 InitializeEmptyExtensionService(); 2978 set_extensions_enabled(false); 2979 2980 // Now add providers. Extension system takes ownership of the objects. 2981 MockExtensionProvider* reg_provider = 2982 new MockExtensionProvider(service_.get(), Extension::EXTERNAL_REGISTRY); 2983 AddMockExternalProvider(reg_provider); 2984 TestExternalProvider(reg_provider, Extension::EXTERNAL_REGISTRY); 2985} 2986#endif 2987 2988TEST_F(ExtensionServiceTest, ExternalInstallPref) { 2989 InitializeEmptyExtensionService(); 2990 2991 // Now add providers. Extension system takes ownership of the objects. 2992 MockExtensionProvider* pref_provider = 2993 new MockExtensionProvider(service_.get(), Extension::EXTERNAL_PREF); 2994 2995 AddMockExternalProvider(pref_provider); 2996 TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF); 2997} 2998 2999TEST_F(ExtensionServiceTest, ExternalInstallPrefUpdateUrl) { 3000 // This should all work, even when normal extension installation is disabled. 3001 InitializeEmptyExtensionService(); 3002 set_extensions_enabled(false); 3003 3004 // TODO(skerner): The mock provider is not a good model of a provider 3005 // that works with update URLs, because it adds file and version info. 3006 // Extend the mock to work with update URLs. This test checks the 3007 // behavior that is common to all external extension visitors. The 3008 // browser test ExtensionManagementTest.ExternalUrlUpdate tests that 3009 // what the visitor does results in an extension being downloaded and 3010 // installed. 3011 MockExtensionProvider* pref_provider = 3012 new MockExtensionProvider(service_.get(), 3013 Extension::EXTERNAL_PREF_DOWNLOAD); 3014 AddMockExternalProvider(pref_provider); 3015 TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF_DOWNLOAD); 3016} 3017 3018// Tests that external extensions get uninstalled when the external extension 3019// providers can't account for them. 3020TEST_F(ExtensionServiceTest, ExternalUninstall) { 3021 // Start the extensions service with one external extension already installed. 3022 FilePath source_install_dir; 3023 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); 3024 source_install_dir = source_install_dir 3025 .AppendASCII("extensions") 3026 .AppendASCII("good") 3027 .AppendASCII("Extensions"); 3028 FilePath pref_path = source_install_dir 3029 .DirName() 3030 .AppendASCII("PreferencesExternal"); 3031 3032 // This initializes the extensions service with no ExternalExtensionProviders. 3033 InitializeInstalledExtensionService(pref_path, source_install_dir); 3034 set_extensions_enabled(false); 3035 3036 service_->Init(); 3037 loop_.RunAllPending(); 3038 3039 ASSERT_EQ(0u, GetErrors().size()); 3040 ASSERT_EQ(0u, loaded_.size()); 3041 3042 // Verify that it's not the disabled extensions flag causing it not to load. 3043 set_extensions_enabled(true); 3044 service_->ReloadExtensions(); 3045 loop_.RunAllPending(); 3046 3047 ASSERT_EQ(0u, GetErrors().size()); 3048 ASSERT_EQ(0u, loaded_.size()); 3049} 3050 3051// Test that running multiple update checks simultaneously does not 3052// keep the update from succeeding. 3053TEST_F(ExtensionServiceTest, MultipleExternalUpdateCheck) { 3054 InitializeEmptyExtensionService(); 3055 3056 MockExtensionProvider* provider = 3057 new MockExtensionProvider(service_.get(), Extension::EXTERNAL_PREF); 3058 AddMockExternalProvider(provider); 3059 3060 // Verify that starting with no providers loads no extensions. 3061 service_->Init(); 3062 loop_.RunAllPending(); 3063 ASSERT_EQ(0u, loaded_.size()); 3064 3065 // Start two checks for updates. 3066 provider->set_visit_count(0); 3067 service_->CheckForExternalUpdates(); 3068 service_->CheckForExternalUpdates(); 3069 loop_.RunAllPending(); 3070 3071 // Two calls should cause two checks for external extensions. 3072 EXPECT_EQ(2, provider->visit_count()); 3073 EXPECT_EQ(0u, GetErrors().size()); 3074 EXPECT_EQ(0u, loaded_.size()); 3075 3076 // Register a test extension externally using the mock registry provider. 3077 FilePath source_path; 3078 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_path)); 3079 source_path = source_path.AppendASCII("extensions").AppendASCII("good.crx"); 3080 provider->UpdateOrAddExtension(good_crx, "1.0.0.0", source_path); 3081 3082 // Two checks for external updates should find the extension, and install it 3083 // once. 3084 provider->set_visit_count(0); 3085 service_->CheckForExternalUpdates(); 3086 service_->CheckForExternalUpdates(); 3087 loop_.RunAllPending(); 3088 EXPECT_EQ(2, provider->visit_count()); 3089 ASSERT_EQ(0u, GetErrors().size()); 3090 ASSERT_EQ(1u, loaded_.size()); 3091 ASSERT_EQ(Extension::EXTERNAL_PREF, loaded_[0]->location()); 3092 ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString()); 3093 ValidatePrefKeyCount(1); 3094 ValidateIntegerPref(good_crx, "state", Extension::ENABLED); 3095 ValidateIntegerPref(good_crx, "location", Extension::EXTERNAL_PREF); 3096 3097 provider->RemoveExtension(good_crx); 3098 provider->set_visit_count(0); 3099 service_->CheckForExternalUpdates(); 3100 service_->CheckForExternalUpdates(); 3101 loop_.RunAllPending(); 3102 3103 // Two calls should cause two checks for external extensions. 3104 // Because the external source no longer includes good_crx, 3105 // good_crx will be uninstalled. So, expect that no extensions 3106 // are loaded. 3107 EXPECT_EQ(2, provider->visit_count()); 3108 EXPECT_EQ(0u, GetErrors().size()); 3109 EXPECT_EQ(0u, loaded_.size()); 3110} 3111 3112TEST_F(ExtensionServiceTest, ExternalPrefProvider) { 3113 InitializeEmptyExtensionService(); 3114 3115 // Test some valid extension records. 3116 // Set a base path to avoid erroring out on relative paths. 3117 // Paths starting with // are absolute on every platform we support. 3118 FilePath base_path(FILE_PATH_LITERAL("//base/path")); 3119 ASSERT_TRUE(base_path.IsAbsolute()); 3120 MockProviderVisitor visitor(base_path); 3121 std::string json_data = 3122 "{" 3123 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {" 3124 " \"external_crx\": \"RandomExtension.crx\"," 3125 " \"external_version\": \"1.0\"" 3126 " }," 3127 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {" 3128 " \"external_crx\": \"RandomExtension2.crx\"," 3129 " \"external_version\": \"2.0\"" 3130 " }," 3131 " \"cccccccccccccccccccccccccccccccc\": {" 3132 " \"external_update_url\": \"http:\\\\foo.com/update\"" 3133 " }" 3134 "}"; 3135 EXPECT_EQ(3, visitor.Visit(json_data)); 3136 3137 // Simulate an external_extensions.json file that contains seven invalid 3138 // records: 3139 // - One that is missing the 'external_crx' key. 3140 // - One that is missing the 'external_version' key. 3141 // - One that is specifying .. in the path. 3142 // - One that specifies both a file and update URL. 3143 // - One that specifies no file or update URL. 3144 // - One that has an update URL that is not well formed. 3145 // - One that contains a malformed version. 3146 // - One that has an invalid id. 3147 // - One that has a non-dictionary value. 3148 // The final extension is valid, and we check that it is read to make sure 3149 // failures don't stop valid records from being read. 3150 json_data = 3151 "{" 3152 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {" 3153 " \"external_version\": \"1.0\"" 3154 " }," 3155 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {" 3156 " \"external_crx\": \"RandomExtension.crx\"" 3157 " }," 3158 " \"cccccccccccccccccccccccccccccccc\": {" 3159 " \"external_crx\": \"..\\\\foo\\\\RandomExtension2.crx\"," 3160 " \"external_version\": \"2.0\"" 3161 " }," 3162 " \"dddddddddddddddddddddddddddddddd\": {" 3163 " \"external_crx\": \"RandomExtension2.crx\"," 3164 " \"external_version\": \"2.0\"," 3165 " \"external_update_url\": \"http:\\\\foo.com/update\"" 3166 " }," 3167 " \"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\": {" 3168 " }," 3169 " \"ffffffffffffffffffffffffffffffff\": {" 3170 " \"external_update_url\": \"This string is not a valid URL\"" 3171 " }," 3172 " \"gggggggggggggggggggggggggggggggg\": {" 3173 " \"external_crx\": \"RandomExtension3.crx\"," 3174 " \"external_version\": \"This is not a valid version!\"" 3175 " }," 3176 " \"This is not a valid id!\": {}," 3177 " \"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\": true," 3178 " \"pppppppppppppppppppppppppppppppp\": {" 3179 " \"external_crx\": \"RandomValidExtension.crx\"," 3180 " \"external_version\": \"1.0\"" 3181 " }" 3182 "}"; 3183 EXPECT_EQ(1, visitor.Visit(json_data)); 3184 3185 // Check that if a base path is not provided, use of a relative 3186 // path fails. 3187 FilePath empty; 3188 MockProviderVisitor visitor_no_relative_paths(empty); 3189 3190 // Use absolute paths. Expect success. 3191 json_data = 3192 "{" 3193 " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {" 3194 " \"external_crx\": \"//RandomExtension1.crx\"," 3195 " \"external_version\": \"3.0\"" 3196 " }," 3197 " \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\": {" 3198 " \"external_crx\": \"//path/to/RandomExtension2.crx\"," 3199 " \"external_version\": \"3.0\"" 3200 " }" 3201 "}"; 3202 EXPECT_EQ(2, visitor_no_relative_paths.Visit(json_data)); 3203 3204 // Use a relative path. Expect that it will error out. 3205 json_data = 3206 "{" 3207 " \"cccccccccccccccccccccccccccccccc\": {" 3208 " \"external_crx\": \"RandomExtension2.crx\"," 3209 " \"external_version\": \"3.0\"" 3210 " }" 3211 "}"; 3212 EXPECT_EQ(0, visitor_no_relative_paths.Visit(json_data)); 3213} 3214 3215// Test loading good extensions from the profile directory. 3216TEST_F(ExtensionServiceTest, LoadAndRelocalizeExtensions) { 3217 // Initialize the test dir with a good Preferences/extensions. 3218 FilePath source_install_dir; 3219 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); 3220 source_install_dir = source_install_dir 3221 .AppendASCII("extensions") 3222 .AppendASCII("l10n"); 3223 FilePath pref_path = source_install_dir.AppendASCII("Preferences"); 3224 InitializeInstalledExtensionService(pref_path, source_install_dir); 3225 3226 service_->Init(); 3227 loop_.RunAllPending(); 3228 3229 ASSERT_EQ(3u, loaded_.size()); 3230 3231 // This was equal to "sr" on load. 3232 ValidateStringPref(loaded_[0]->id(), keys::kCurrentLocale, "en"); 3233 3234 // These are untouched by re-localization. 3235 ValidateStringPref(loaded_[1]->id(), keys::kCurrentLocale, "en"); 3236 EXPECT_FALSE(IsPrefExist(loaded_[1]->id(), keys::kCurrentLocale)); 3237 3238 // This one starts with Serbian name, and gets re-localized into English. 3239 EXPECT_EQ("My name is simple.", loaded_[0]->name()); 3240 3241 // These are untouched by re-localization. 3242 EXPECT_EQ("My name is simple.", loaded_[1]->name()); 3243 EXPECT_EQ("no l10n", loaded_[2]->name()); 3244} 3245 3246class ExtensionsReadyRecorder : public NotificationObserver { 3247 public: 3248 ExtensionsReadyRecorder() : ready_(false) { 3249 registrar_.Add(this, NotificationType::EXTENSIONS_READY, 3250 NotificationService::AllSources()); 3251 } 3252 3253 void set_ready(bool value) { ready_ = value; } 3254 bool ready() { return ready_; } 3255 3256 private: 3257 virtual void Observe(NotificationType type, 3258 const NotificationSource& source, 3259 const NotificationDetails& details) { 3260 switch (type.value) { 3261 case NotificationType::EXTENSIONS_READY: 3262 ready_ = true; 3263 break; 3264 default: 3265 NOTREACHED(); 3266 } 3267 } 3268 3269 NotificationRegistrar registrar_; 3270 bool ready_; 3271}; 3272 3273// Test that we get enabled/disabled correctly for all the pref/command-line 3274// combinations. We don't want to derive from the ExtensionServiceTest class 3275// for this test, so we use ExtensionServiceTestSimple. 3276// 3277// Also tests that we always fire EXTENSIONS_READY, no matter whether we are 3278// enabled or not. 3279TEST(ExtensionServiceTestSimple, Enabledness) { 3280 ExtensionsReadyRecorder recorder; 3281 scoped_ptr<TestingProfile> profile(new TestingProfile()); 3282 MessageLoop loop; 3283 BrowserThread ui_thread(BrowserThread::UI, &loop); 3284 BrowserThread file_thread(BrowserThread::FILE, &loop); 3285 scoped_ptr<CommandLine> command_line; 3286 scoped_refptr<ExtensionService> service; 3287 FilePath install_dir = profile->GetPath() 3288 .AppendASCII(ExtensionService::kInstallDirectoryName); 3289 3290 // By default, we are enabled. 3291 command_line.reset(new CommandLine(CommandLine::NO_PROGRAM)); 3292 service = profile->CreateExtensionService(command_line.get(), 3293 install_dir); 3294 EXPECT_TRUE(service->extensions_enabled()); 3295 service->Init(); 3296 loop.RunAllPending(); 3297 EXPECT_TRUE(recorder.ready()); 3298 3299 // If either the command line or pref is set, we are disabled. 3300 recorder.set_ready(false); 3301 profile.reset(new TestingProfile()); 3302 command_line->AppendSwitch(switches::kDisableExtensions); 3303 service = profile->CreateExtensionService(command_line.get(), 3304 install_dir); 3305 EXPECT_FALSE(service->extensions_enabled()); 3306 service->Init(); 3307 loop.RunAllPending(); 3308 EXPECT_TRUE(recorder.ready()); 3309 3310 recorder.set_ready(false); 3311 profile.reset(new TestingProfile()); 3312 profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true); 3313 service = profile->CreateExtensionService(command_line.get(), 3314 install_dir); 3315 EXPECT_FALSE(service->extensions_enabled()); 3316 service->Init(); 3317 loop.RunAllPending(); 3318 EXPECT_TRUE(recorder.ready()); 3319 3320 recorder.set_ready(false); 3321 profile.reset(new TestingProfile()); 3322 profile->GetPrefs()->SetBoolean(prefs::kDisableExtensions, true); 3323 command_line.reset(new CommandLine(CommandLine::NO_PROGRAM)); 3324 service = profile->CreateExtensionService(command_line.get(), 3325 install_dir); 3326 EXPECT_FALSE(service->extensions_enabled()); 3327 service->Init(); 3328 loop.RunAllPending(); 3329 EXPECT_TRUE(recorder.ready()); 3330 3331 // Explicitly delete all the resources used in this test. 3332 profile.reset(); 3333 service = NULL; 3334} 3335 3336// Test loading extensions that require limited and unlimited storage quotas. 3337TEST_F(ExtensionServiceTest, StorageQuota) { 3338 InitializeEmptyExtensionService(); 3339 3340 FilePath extensions_path; 3341 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); 3342 extensions_path = extensions_path.AppendASCII("extensions") 3343 .AppendASCII("storage_quota"); 3344 3345 FilePath limited_quota_ext = extensions_path.AppendASCII("limited_quota") 3346 .AppendASCII("1.0"); 3347 3348 // The old permission name for unlimited quota was "unlimited_storage", but 3349 // we changed it to "unlimitedStorage". This tests both versions. 3350 FilePath unlimited_quota_ext = extensions_path.AppendASCII("unlimited_quota") 3351 .AppendASCII("1.0"); 3352 FilePath unlimited_quota_ext2 = extensions_path.AppendASCII("unlimited_quota") 3353 .AppendASCII("2.0"); 3354 service_->LoadExtension(limited_quota_ext); 3355 service_->LoadExtension(unlimited_quota_ext); 3356 service_->LoadExtension(unlimited_quota_ext2); 3357 loop_.RunAllPending(); 3358 3359 ASSERT_EQ(3u, loaded_.size()); 3360 EXPECT_TRUE(profile_.get()); 3361 EXPECT_FALSE(profile_->IsOffTheRecord()); 3362 3363 // Open the database from each origin to make the tracker aware 3364 // of the existence of these origins and to get their quotas. 3365 int64 limited_quota = -1; 3366 int64 unlimited_quota = -1; 3367 string16 limited_quota_identifier = 3368 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[0]->url()); 3369 string16 unlimited_quota_identifier = 3370 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[1]->url()); 3371 string16 unlimited_quota_identifier2 = 3372 webkit_database::DatabaseUtil::GetOriginIdentifier(loaded_[2]->url()); 3373 string16 db_name = UTF8ToUTF16("db"); 3374 string16 description = UTF8ToUTF16("db_description"); 3375 int64 database_size; 3376 webkit_database::DatabaseTracker* db_tracker = profile_->GetDatabaseTracker(); 3377 3378 // First check the normal limited quota extension. 3379 db_tracker->DatabaseOpened(limited_quota_identifier, db_name, description, 3380 1, &database_size, &limited_quota); 3381 db_tracker->DatabaseClosed(limited_quota_identifier, db_name); 3382 EXPECT_EQ(profile_->GetDatabaseTracker()->GetDefaultQuota(), limited_quota); 3383 3384 // Now check the two unlimited quota ones. 3385 db_tracker->DatabaseOpened(unlimited_quota_identifier, db_name, description, 3386 1, &database_size, &unlimited_quota); 3387 db_tracker->DatabaseClosed(unlimited_quota_identifier, db_name); 3388 EXPECT_EQ(kint64max, unlimited_quota); 3389 db_tracker->DatabaseOpened(unlimited_quota_identifier2, db_name, description, 3390 1, &database_size, &unlimited_quota); 3391 db_tracker->DatabaseClosed(unlimited_quota_identifier2, db_name); 3392 3393 EXPECT_EQ(kint64max, unlimited_quota); 3394} 3395 3396// Tests ExtensionService::register_component_extension(). 3397TEST_F(ExtensionServiceTest, ComponentExtensions) { 3398 InitializeEmptyExtensionService(); 3399 3400 // Component extensions should work even when extensions are disabled. 3401 set_extensions_enabled(false); 3402 3403 FilePath path; 3404 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path)); 3405 path = path.AppendASCII("extensions") 3406 .AppendASCII("good") 3407 .AppendASCII("Extensions") 3408 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") 3409 .AppendASCII("1.0.0.0"); 3410 3411 std::string manifest; 3412 ASSERT_TRUE(file_util::ReadFileToString( 3413 path.Append(Extension::kManifestFilename), &manifest)); 3414 3415 service_->register_component_extension( 3416 ExtensionService::ComponentExtensionInfo(manifest, path)); 3417 service_->Init(); 3418 3419 // Note that we do not pump messages -- the extension should be loaded 3420 // immediately. 3421 3422 EXPECT_EQ(0u, GetErrors().size()); 3423 ASSERT_EQ(1u, loaded_.size()); 3424 EXPECT_EQ(Extension::COMPONENT, loaded_[0]->location()); 3425 EXPECT_EQ(1u, service_->extensions()->size()); 3426 3427 // Component extensions shouldn't get recourded in the prefs. 3428 ValidatePrefKeyCount(0); 3429 3430 // Reload all extensions, and make sure it comes back. 3431 std::string extension_id = service_->extensions()->at(0)->id(); 3432 loaded_.clear(); 3433 service_->ReloadExtensions(); 3434 ASSERT_EQ(1u, service_->extensions()->size()); 3435 EXPECT_EQ(extension_id, service_->extensions()->at(0)->id()); 3436} 3437