Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_service.h" | 5 #include "chrome/browser/extensions/extension_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 system_->management_policy()->UnregisterProvider( | 369 system_->management_policy()->UnregisterProvider( |
| 370 shared_module_policy_provider_.get()); | 370 shared_module_policy_provider_.get()); |
| 371 } | 371 } |
| 372 | 372 |
| 373 const Extension* ExtensionService::GetExtensionById( | 373 const Extension* ExtensionService::GetExtensionById( |
| 374 const std::string& id, bool include_disabled) const { | 374 const std::string& id, bool include_disabled) const { |
| 375 int include_mask = ExtensionRegistry::ENABLED; | 375 int include_mask = ExtensionRegistry::ENABLED; |
| 376 if (include_disabled) { | 376 if (include_disabled) { |
| 377 // Include blacklisted extensions here because there are hundreds of | 377 // Include blacklisted extensions here because there are hundreds of |
| 378 // callers of this function, and many might assume that this includes those | 378 // callers of this function, and many might assume that this includes those |
| 379 // that have been disabled due to blacklisting. | 379 // that have been disabled due to blacklisting. |
|
not at google - send to devlin
2014/11/12 18:23:00
Update comment?
Mike Lerman
2014/11/12 20:58:42
Done.
| |
| 380 include_mask |= ExtensionRegistry::DISABLED | | 380 include_mask |= ExtensionRegistry::DISABLED | |
| 381 ExtensionRegistry::BLACKLISTED; | 381 ExtensionRegistry::BLACKLISTED | |
| 382 ExtensionRegistry::LOCKED; | |
| 382 } | 383 } |
| 383 return registry_->GetExtensionById(id, include_mask); | 384 return registry_->GetExtensionById(id, include_mask); |
| 384 } | 385 } |
| 385 | 386 |
| 386 void ExtensionService::Init() { | 387 void ExtensionService::Init() { |
| 387 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 388 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 388 | 389 |
| 389 base::Time begin_time = base::Time::Now(); | 390 base::Time begin_time = base::Time::Now(); |
| 390 | 391 |
| 391 DCHECK(!is_ready()); // Can't redo init. | 392 DCHECK(!is_ready()); // Can't redo init. |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 const std::string& transient_extension_id, | 573 const std::string& transient_extension_id, |
| 573 bool be_noisy) { | 574 bool be_noisy) { |
| 574 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 575 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 575 | 576 |
| 576 // If the extension is already reloading, don't reload again. | 577 // If the extension is already reloading, don't reload again. |
| 577 if (extension_prefs_->GetDisableReasons(transient_extension_id) & | 578 if (extension_prefs_->GetDisableReasons(transient_extension_id) & |
| 578 Extension::DISABLE_RELOAD) { | 579 Extension::DISABLE_RELOAD) { |
| 579 return; | 580 return; |
| 580 } | 581 } |
| 581 | 582 |
| 582 // Ignore attempts to reload a blacklisted extension. Sometimes this can | 583 // Ignore attempts to reload a blacklisted or locked extension. Sometimes this |
|
not at google - send to devlin
2014/11/12 18:22:59
Also update this comment.
Mike Lerman
2014/11/12 20:58:41
Ah, I'd only done half! Thanks. Done.
| |
| 583 // happen in a convoluted reload sequence triggered by the termination of a | 584 // can happen in a convoluted reload sequence triggered by the termination of |
| 584 // blacklisted extension and a naive attempt to reload it. For an example see | 585 // a blacklisted extension and a naive attempt to reload it. For an example |
| 585 // http://crbug.com/373842. | 586 // see http://crbug.com/373842. |
| 586 if (registry_->blacklisted_extensions().Contains(transient_extension_id)) | 587 if (registry_->blacklisted_extensions().Contains(transient_extension_id) || |
| 588 registry_->locked_extensions().Contains(transient_extension_id)) { | |
| 587 return; | 589 return; |
| 590 } | |
| 588 | 591 |
| 589 base::FilePath path; | 592 base::FilePath path; |
| 590 | 593 |
| 591 std::string extension_id = transient_extension_id; | 594 std::string extension_id = transient_extension_id; |
| 592 const Extension* transient_current_extension = | 595 const Extension* transient_current_extension = |
| 593 GetExtensionById(extension_id, false); | 596 GetExtensionById(extension_id, false); |
| 594 | 597 |
| 595 // Disable the extension if it's loaded. It might not be loaded if it crashed. | 598 // Disable the extension if it's loaded. It might not be loaded if it crashed. |
| 596 if (transient_current_extension) { | 599 if (transient_current_extension) { |
| 597 // If the extension has an inspector open for its background page, detach | 600 // If the extension has an inspector open for its background page, detach |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 782 } | 785 } |
| 783 | 786 |
| 784 bool ExtensionService::IsExtensionEnabled( | 787 bool ExtensionService::IsExtensionEnabled( |
| 785 const std::string& extension_id) const { | 788 const std::string& extension_id) const { |
| 786 if (registry_->enabled_extensions().Contains(extension_id) || | 789 if (registry_->enabled_extensions().Contains(extension_id) || |
| 787 registry_->terminated_extensions().Contains(extension_id)) { | 790 registry_->terminated_extensions().Contains(extension_id)) { |
| 788 return true; | 791 return true; |
| 789 } | 792 } |
| 790 | 793 |
| 791 if (registry_->disabled_extensions().Contains(extension_id) || | 794 if (registry_->disabled_extensions().Contains(extension_id) || |
| 792 registry_->blacklisted_extensions().Contains(extension_id)) { | 795 registry_->blacklisted_extensions().Contains(extension_id) || |
| 796 registry_->locked_extensions().Contains(extension_id)) { | |
| 793 return false; | 797 return false; |
| 794 } | 798 } |
| 795 | 799 |
| 796 // If the extension hasn't been loaded yet, check the prefs for it. Assume | 800 // If the extension hasn't been loaded yet, check the prefs for it. Assume |
| 797 // enabled unless otherwise noted. | 801 // enabled unless otherwise noted. |
| 798 return !extension_prefs_->IsExtensionDisabled(extension_id) && | 802 return !extension_prefs_->IsExtensionDisabled(extension_id) && |
| 799 !extension_prefs_->IsExtensionBlacklisted(extension_id) && | 803 !extension_prefs_->IsExtensionBlacklisted(extension_id) && |
| 804 !extension_prefs_->IsExtensionLocked(extension_id) && | |
| 800 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); | 805 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); |
| 801 } | 806 } |
| 802 | 807 |
| 803 void ExtensionService::EnableExtension(const std::string& extension_id) { | 808 void ExtensionService::EnableExtension(const std::string& extension_id) { |
| 804 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 809 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 805 | 810 |
| 806 if (IsExtensionEnabled(extension_id)) | 811 if (IsExtensionEnabled(extension_id)) |
| 807 return; | 812 return; |
| 808 const Extension* extension = | 813 const Extension* extension = |
| 809 registry_->disabled_extensions().GetByID(extension_id); | 814 registry_->disabled_extensions().GetByID(extension_id); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 if ((*extension)->was_installed_by_default() && | 918 if ((*extension)->was_installed_by_default() && |
| 914 extension_urls::IsWebstoreUpdateUrl( | 919 extension_urls::IsWebstoreUpdateUrl( |
| 915 extensions::ManifestURL::GetUpdateURL(extension->get()))) | 920 extensions::ManifestURL::GetUpdateURL(extension->get()))) |
| 916 continue; | 921 continue; |
| 917 const std::string& id = (*extension)->id(); | 922 const std::string& id = (*extension)->id(); |
| 918 if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id)) | 923 if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id)) |
| 919 DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION); | 924 DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION); |
| 920 } | 925 } |
| 921 } | 926 } |
| 922 | 927 |
| 928 | |
|
not at google - send to devlin
2014/11/12 18:23:00
Remove redundant new line.
Mike Lerman
2014/11/12 20:58:42
Done.
| |
| 929 // Extensions specified by |extension_ids| should become locked. Extensions | |
| 930 // are no longer considered enabled or disabled. Blacklisted extensions are | |
| 931 // now considered both blacklisted and locked. | |
| 932 void ExtensionService::LockAllExtensions() { | |
| 933 scoped_ptr<ExtensionSet> extensions = | |
| 934 registry_->GenerateInstalledExtensionsSet(); | |
| 935 | |
| 936 ExtensionIdSet to_lock; | |
| 937 for (ExtensionSet::const_iterator extension = extensions->begin(); | |
|
not at google - send to devlin
2014/11/12 18:23:00
You could use the new : foreach syntax?
Mike Lerman
2014/11/12 20:58:42
Done.
| |
| 938 extension != extensions->end(); | |
| 939 ++extension) { | |
| 940 const std::string& id = (*extension)->id(); | |
| 941 if (!registry_->locked_extensions().Contains(id)) | |
| 942 to_lock.insert(id); | |
| 943 } | |
| 944 | |
| 945 for (ExtensionIdSet::iterator id = to_lock.begin(); | |
| 946 id != to_lock.end(); ++id) { | |
| 947 scoped_refptr<const Extension> extension = GetInstalledExtension(*id); | |
|
not at google - send to devlin
2014/11/12 18:23:00
Unless something is very wrong, this shouldn't be
Mike Lerman
2014/11/12 20:58:42
That saves a lot of code. Thanks!
| |
| 948 if (!extension.get()) { | |
| 949 NOTREACHED() << "Extension " << *id << " needs to be " | |
| 950 << "locked, but it's not installed."; | |
| 951 continue; | |
| 952 } | |
| 953 | |
| 954 // Don't lock core components. | |
| 955 if (extension.get()->location() == Manifest::COMPONENT || | |
| 956 extension.get()->location() == Manifest::EXTERNAL_COMPONENT) { | |
|
not at google - send to devlin
2014/11/12 18:23:00
Hm, it's surprising that this is the first time we
Mike Lerman
2014/11/12 20:58:42
It seems like this DCHECK in DisableExtension woul
| |
| 957 continue; | |
| 958 } | |
| 959 | |
| 960 if (system_->management_policy()->MustRemainEnabled(extension.get(), NULL)) | |
| 961 continue; | |
| 962 | |
| 963 // Blacklisted extensions remain in the blacklisted list. | |
|
not at google - send to devlin
2014/11/12 18:23:00
What about terminated extensions? Those need to go
Mike Lerman
2014/11/12 20:58:42
I had assumed that a terminated extension was A) A
not at google - send to devlin
2014/11/12 23:41:42
You can restart a terminated extension by going to
Mike Lerman
2014/11/13 15:30:04
Acknowledged.
| |
| 964 if (registry_->enabled_extensions().Contains(*id)) { | |
| 965 registry_->RemoveEnabled(*id); | |
| 966 } else if (registry_->disabled_extensions().Contains(*id)) { | |
| 967 registry_->RemoveDisabled(*id); | |
| 968 } | |
|
not at google - send to devlin
2014/11/12 18:23:00
I don't actually think the "if"s here are necessar
Mike Lerman
2014/11/12 20:58:42
Done.
| |
| 969 registry_->AddLocked(extension.get()); | |
| 970 extension_prefs_->SetExtensionState(*id, Extension::LOCKED); | |
| 971 UnloadExtension( | |
| 972 *id, extensions::UnloadedExtensionInfo::REASON_PROFILE_LOCK); | |
| 973 } | |
| 974 } | |
| 975 | |
| 976 // All locked extensions should revert to being either enabled or disabled | |
| 977 // as appropriate. | |
| 978 void ExtensionService::UnlockAllLockedExtensions() { | |
| 979 ExtensionIdSet to_unlock = registry_->locked_extensions().GetIDs(); | |
| 980 | |
| 981 for (ExtensionIdSet::iterator it = to_unlock.begin(); | |
| 982 it != to_unlock.end(); ++it) { | |
| 983 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); | |
| 984 if (!extension.get()) { | |
| 985 NOTREACHED() << "Extension " << *it << " needs to be " | |
|
not at google - send to devlin
2014/11/12 18:23:00
Again; not possible, and this code is perfectly sa
Mike Lerman
2014/11/12 20:58:42
Really? I can't loop directory of registry->locked
not at google - send to devlin
2014/11/12 23:41:42
Oh right, good point, I guess you need to take a c
| |
| 986 << "unlocked, but it's not installed."; | |
| 987 continue; | |
| 988 } | |
| 989 | |
| 990 registry_->RemoveLocked(*it); | |
| 991 if (extension_prefs_->GetDisableReasons(*it)) | |
| 992 extension_prefs_->SetExtensionState(*it, Extension::DISABLED); | |
| 993 else | |
| 994 extension_prefs_->SetExtensionState(*it, Extension::ENABLED); | |
|
not at google - send to devlin
2014/11/12 18:23:00
Again: terminated extensions.
Mike Lerman
2014/11/12 20:58:42
Done.
| |
| 995 AddExtension(extension.get()); | |
| 996 } | |
| 997 } | |
| 998 | |
| 923 void ExtensionService::GrantPermissionsAndEnableExtension( | 999 void ExtensionService::GrantPermissionsAndEnableExtension( |
| 924 const Extension* extension) { | 1000 const Extension* extension) { |
| 925 GrantPermissions(extension); | 1001 GrantPermissions(extension); |
| 926 RecordPermissionMessagesHistogram(extension, | 1002 RecordPermissionMessagesHistogram(extension, |
| 927 "Extensions.Permissions_ReEnable2"); | 1003 "Extensions.Permissions_ReEnable2"); |
| 928 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); | 1004 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); |
| 929 EnableExtension(extension->id()); | 1005 EnableExtension(extension->id()); |
| 930 } | 1006 } |
| 931 | 1007 |
| 932 void ExtensionService::GrantPermissions(const Extension* extension) { | 1008 void ExtensionService::GrantPermissions(const Extension* extension) { |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1366 // new one. ReloadExtension disables the extension, which is sufficient. | 1442 // new one. ReloadExtension disables the extension, which is sufficient. |
| 1367 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE); | 1443 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE); |
| 1368 } | 1444 } |
| 1369 | 1445 |
| 1370 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { | 1446 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { |
| 1371 // Only prefs is checked for the blacklist. We rely on callers to check the | 1447 // Only prefs is checked for the blacklist. We rely on callers to check the |
| 1372 // blacklist before calling into here, e.g. CrxInstaller checks before | 1448 // blacklist before calling into here, e.g. CrxInstaller checks before |
| 1373 // installation then threads through the install and pending install flow | 1449 // installation then threads through the install and pending install flow |
| 1374 // of this class, and we check when loading installed extensions. | 1450 // of this class, and we check when loading installed extensions. |
| 1375 registry_->AddBlacklisted(extension); | 1451 registry_->AddBlacklisted(extension); |
| 1452 } else if (extension_prefs_->IsExtensionLocked(extension->id())) { | |
| 1453 registry_->AddLocked(extension); | |
| 1376 } else if (!reloading && | 1454 } else if (!reloading && |
| 1377 extension_prefs_->IsExtensionDisabled(extension->id())) { | 1455 extension_prefs_->IsExtensionDisabled(extension->id())) { |
| 1378 registry_->AddDisabled(extension); | 1456 registry_->AddDisabled(extension); |
| 1379 if (extension_sync_service_) | 1457 if (extension_sync_service_) |
| 1380 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); | 1458 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); |
| 1381 content::NotificationService::current()->Notify( | 1459 content::NotificationService::current()->Notify( |
| 1382 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED, | 1460 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED, |
| 1383 content::Source<Profile>(profile_), | 1461 content::Source<Profile>(profile_), |
| 1384 content::Details<const Extension>(extension)); | 1462 content::Details<const Extension>(extension)); |
| 1385 | 1463 |
| (...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2388 } | 2466 } |
| 2389 | 2467 |
| 2390 void ExtensionService::OnProfileDestructionStarted() { | 2468 void ExtensionService::OnProfileDestructionStarted() { |
| 2391 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); | 2469 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); |
| 2392 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); | 2470 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); |
| 2393 it != ids_to_unload.end(); | 2471 it != ids_to_unload.end(); |
| 2394 ++it) { | 2472 ++it) { |
| 2395 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); | 2473 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); |
| 2396 } | 2474 } |
| 2397 } | 2475 } |
| OLD | NEW |