Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Unified Diff: chrome/browser/extensions/extension_service.cc

Issue 11415216: Make Blacklist::IsBlacklist asynchronous (it will need to be for safe (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix another test Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/extension_service.cc
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 779456147d73a23a45189e6b4b28fe095f16f287..a52dc40aaa6bc930235109e836159966a2836028 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/extension_service.h"
#include <algorithm>
+#include <iterator>
#include <set>
#include "base/basictypes.h"
@@ -362,6 +363,7 @@ ExtensionService::ExtensionService(Profile* profile,
profile_(profile),
system_(extensions::ExtensionSystem::Get(profile)),
extension_prefs_(extension_prefs),
+ blacklist_(blacklist),
settings_frontend_(extensions::SettingsFrontend::Create(profile)),
pending_extension_manager_(*ALLOW_THIS_IN_INITIALIZER_LIST(this)),
install_directory_(install_directory),
@@ -467,23 +469,29 @@ const ExtensionSet* ExtensionService::terminated_extensions() const {
return &terminated_extensions_;
}
-const ExtensionSet* ExtensionService::GenerateInstalledExtensionsSet() const {
- ExtensionSet* installed_extensions = new ExtensionSet();
+const ExtensionSet* ExtensionService::blacklisted_extensions() const {
+ return &blacklisted_extensions_;
+}
+
+scoped_ptr<const ExtensionSet>
+ ExtensionService::GenerateInstalledExtensionsSet() const {
+ scoped_ptr<ExtensionSet> installed_extensions(new ExtensionSet());
installed_extensions->InsertAll(extensions_);
installed_extensions->InsertAll(disabled_extensions_);
installed_extensions->InsertAll(terminated_extensions_);
- return installed_extensions;
+ installed_extensions->InsertAll(blacklisted_extensions_);
+ return installed_extensions.PassAs<const ExtensionSet>();
}
-const ExtensionSet* ExtensionService::GetWipedOutExtensions() const {
- ExtensionSet* extension_set = new ExtensionSet();
+scoped_ptr<const ExtensionSet> ExtensionService::GetWipedOutExtensions() const {
+ scoped_ptr<ExtensionSet> extension_set(new ExtensionSet());
for (ExtensionSet::const_iterator iter = disabled_extensions_.begin();
iter != disabled_extensions_.end(); ++iter) {
int disabled_reason = extension_prefs_->GetDisableReasons((*iter)->id());
if ((disabled_reason & Extension::DISABLE_SIDELOAD_WIPEOUT) != 0)
extension_set->Insert(*iter);
}
- return extension_set;
+ return extension_set.PassAs<const ExtensionSet>();
}
extensions::PendingExtensionManager*
@@ -579,9 +587,39 @@ void ExtensionService::Shutdown() {
const Extension* ExtensionService::GetExtensionById(
const std::string& id, bool include_disabled) const {
int include_mask = INCLUDE_ENABLED;
- if (include_disabled)
- include_mask |= INCLUDE_DISABLED;
- return GetExtensionByIdInternal(id, include_mask);
+ if (include_disabled) {
+ // Include blacklisted extensions here because there are hundreds of
+ // callers of this function, and many might assume that this includes those
+ // that have been disabled due to blacklisting.
+ include_mask |= INCLUDE_DISABLED | INCLUDE_BLACKLISTED;
+ }
+ return GetExtensionById(id, include_mask);
+}
+
+const Extension* ExtensionService::GetExtensionById(
+ const std::string& id, int include_mask) const {
+ std::string lowercase_id = StringToLowerASCII(id);
+ if (include_mask & INCLUDE_ENABLED) {
+ const Extension* extension = extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ if (include_mask & INCLUDE_DISABLED) {
+ const Extension* extension = disabled_extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ if (include_mask & INCLUDE_TERMINATED) {
+ const Extension* extension = terminated_extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ if (include_mask & INCLUDE_BLACKLISTED) {
+ const Extension* extension = blacklisted_extensions_.GetByID(lowercase_id);
+ if (extension)
+ return extension;
+ }
+ return NULL;
}
void ExtensionService::Init() {
@@ -637,9 +675,7 @@ bool ExtensionService::UpdateExtension(const std::string& id,
const extensions::PendingExtensionInfo* pending_extension_info =
pending_extension_manager()->GetById(id);
- int include_mask = INCLUDE_ENABLED | INCLUDE_DISABLED;
- const Extension* extension =
- GetExtensionByIdInternal(id, include_mask);
+ const Extension* extension = GetInstalledExtension(id);
if (!pending_extension_info && !extension) {
LOG(WARNING) << "Will not update extension " << id
<< " because it is not installed or pending";
@@ -890,13 +926,15 @@ bool ExtensionService::IsExtensionEnabled(
return true;
}
- if (disabled_extensions_.Contains(extension_id))
+ if (disabled_extensions_.Contains(extension_id) ||
+ blacklisted_extensions_.Contains(extension_id)) {
return false;
+ }
// If the extension hasn't been loaded yet, check the prefs for it. Assume
// enabled unless otherwise noted.
return !extension_prefs_->IsExtensionDisabled(extension_id) &&
- !extension_prefs_->IsExternalExtensionUninstalled(extension_id);
+ !extension_prefs_->IsExternalExtensionUninstalled(extension_id);
}
bool ExtensionService::IsExternalExtensionUninstalled(
@@ -914,8 +952,7 @@ void ExtensionService::EnableExtension(const std::string& extension_id) {
extension_prefs_->SetExtensionState(extension_id, Extension::ENABLED);
extension_prefs_->ClearDisableReasons(extension_id);
- const Extension* extension = GetExtensionByIdInternal(extension_id,
- INCLUDE_DISABLED);
+ const Extension* extension = disabled_extensions_.GetByID(extension_id);
// This can happen if sync enables an extension that is not
// installed yet.
if (!extension)
@@ -966,8 +1003,8 @@ void ExtensionService::DisableExtension(
extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED);
extension_prefs_->AddDisableReason(extension_id, disable_reason);
- int include_mask = INCLUDE_ENABLED | INCLUDE_TERMINATED;
- extension = GetExtensionByIdInternal(extension_id, include_mask);
+ int include_mask = INCLUDE_EVERYTHING & ~INCLUDE_DISABLED;
+ extension = GetExtensionById(extension_id, include_mask);
if (!extension)
return;
@@ -1263,6 +1300,7 @@ extensions::ExtensionUpdater* ExtensionService::updater() {
void ExtensionService::CheckManagementPolicy() {
std::vector<std::string> to_be_removed;
+
// Loop through extensions list, unload installed extensions.
for (ExtensionSet::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
@@ -1826,15 +1864,31 @@ void ExtensionService::IdentifyAlertableExtensions() {
bool ExtensionService::PopulateExtensionErrorUI(
ExtensionErrorUI* extension_error_ui) {
bool needs_alert = false;
+
+ // Extensions that are blacklisted.
+ for (ExtensionSet::const_iterator it = blacklisted_extensions_.begin();
+ it != blacklisted_extensions_.end(); ++it) {
+ std::string id = (*it)->id();
+ if (!extension_prefs_->IsBlacklistedExtensionAcknowledged(id)) {
+ extension_error_ui->AddBlacklistedExtension(id);
+ needs_alert = true;
+ }
+ }
+
for (ExtensionSet::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
const Extension* e = *iter;
+
+ // Extensions disabled by policy. Note: this no longer includes blacklisted
+ // extensions, though we still show the same UI.
if (!system_->management_policy()->UserMayLoad(e, NULL)) {
if (!extension_prefs_->IsBlacklistedExtensionAcknowledged(e->id())) {
extension_error_ui->AddBlacklistedExtension(e->id());
needs_alert = true;
}
}
+
+ // Orphaned extensions.
if (extension_prefs_->IsExtensionOrphaned(e->id())) {
if (!extension_prefs_->IsOrphanedExtensionAcknowledged(e->id())) {
extension_error_ui->AddOrphanedExtension(e->id());
@@ -1842,6 +1896,7 @@ bool ExtensionService::PopulateExtensionErrorUI(
}
}
}
+
return needs_alert;
}
@@ -1921,9 +1976,9 @@ void ExtensionService::UnloadExtension(
const std::string& extension_id,
extension_misc::UnloadedExtensionReason reason) {
// Make sure the extension gets deleted after we return from this function.
- int include_mask = INCLUDE_ENABLED | INCLUDE_DISABLED;
+ int include_mask = INCLUDE_EVERYTHING & ~INCLUDE_TERMINATED;
scoped_refptr<const Extension> extension(
- GetExtensionByIdInternal(extension_id, include_mask));
+ GetExtensionById(extension_id, include_mask));
// This method can be called via PostTask, so the extension may have been
// unloaded by the time this runs.
@@ -2081,7 +2136,17 @@ void ExtensionService::AddExtension(const Extension* extension) {
// wipeout before, we might disable this extension here.
MaybeWipeout(extension);
- if (extension_prefs_->IsExtensionDisabled(extension->id())) {
+ // Communicated to the Blacklist.
+ std::set<std::string> already_in_blacklist;
+
+ if (extension_prefs_->IsExtensionBlacklisted(extension->id())) {
+ // Don't check the Blacklist yet because it's asynchronous (we do it at
+ // the end). This pre-emptive check is because we will always store the
+ // blacklisted state of *installed* extensions in prefs, and it's important
+ // not to re-enable blacklisted extensions.
+ blacklisted_extensions_.Insert(extension);
+ already_in_blacklist.insert(extension->id());
+ } else if (extension_prefs_->IsExtensionDisabled(extension->id())) {
disabled_extensions_.Insert(extension);
SyncExtensionChangeIfNeeded(*extension);
content::NotificationService::current()->Notify(
@@ -2093,29 +2158,38 @@ void ExtensionService::AddExtension(const Extension* extension) {
Extension::DISABLE_PERMISSIONS_INCREASE) {
extensions::AddExtensionDisabledError(this, extension);
}
- return;
- }
-
- // All apps that are displayed in the launcher are ordered by their ordinals
- // so we must ensure they have valid ordinals.
- if (extension->RequiresSortOrdinal()) {
- extension_prefs_->extension_sorting()->EnsureValidOrdinals(
- extension->id(), syncer::StringOrdinal());
- }
+ } else {
+ // All apps that are displayed in the launcher are ordered by their ordinals
+ // so we must ensure they have valid ordinals.
+ if (extension->RequiresSortOrdinal()) {
+ extension_prefs_->extension_sorting()->EnsureValidOrdinals(
+ extension->id(), syncer::StringOrdinal());
+ }
- extensions_.Insert(extension);
- SyncExtensionChangeIfNeeded(*extension);
- NotifyExtensionLoaded(extension);
- DoPostLoadTasks(extension);
+ extensions_.Insert(extension);
+ SyncExtensionChangeIfNeeded(*extension);
+ NotifyExtensionLoaded(extension);
+ DoPostLoadTasks(extension);
#if defined(ENABLE_THEMES)
- if (extension->is_theme()) {
- // Now that the theme extension is visible from outside the
- // ExtensionService, notify the ThemeService about the
- // newly-installed theme.
- ThemeServiceFactory::GetForProfile(profile_)->SetTheme(extension);
- }
+ if (extension->is_theme()) {
+ // Now that the theme extension is visible from outside the
+ // ExtensionService, notify the ThemeService about the
+ // newly-installed theme.
+ ThemeServiceFactory::GetForProfile(profile_)->SetTheme(extension);
+ }
#endif
+ }
+
+ // Lastly, begin the process for checking the blacklist status of extensions.
+ // This may need to go to other threads so is asynchronous.
+ std::set<std::string> id_set;
+ id_set.insert(extension->id());
+ blacklist_->GetBlacklistedIDs(
+ id_set,
+ base::Bind(&ExtensionService::ManageBlacklist,
+ AsWeakPtr(),
+ already_in_blacklist));
}
void ExtensionService::AddComponentExtension(const Extension* extension) {
@@ -2188,9 +2262,7 @@ void ExtensionService::InitializePermissions(const Extension* extension) {
// still remember that "omnibox" had been granted, so that if the
// extension once again includes "omnibox" in an upgrade, the extension
// can upgrade without requiring this user's approval.
- int include_mask = INCLUDE_ENABLED | INCLUDE_DISABLED;
- const Extension* old =
- GetExtensionByIdInternal(extension->id(), include_mask);
+ const Extension* old = GetInstalledExtension(extension->id());
bool is_extension_upgrade = old != NULL;
bool is_privilege_increase = false;
bool previously_disabled = false;
@@ -2371,8 +2443,7 @@ void ExtensionService::OnExtensionInstalled(
extension_prefs_->ClearDisableReasons(id);
}
- int include_mask = INCLUDE_ENABLED | INCLUDE_DISABLED;
- if (!GetExtensionByIdInternal(extension->id(), include_mask)) {
+ if (!GetInstalledExtension(extension->id())) {
UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType",
extension->GetType(), 100);
UMA_HISTOGRAM_ENUMERATION("Extensions.InstallSource",
@@ -2484,27 +2555,6 @@ const Extension* ExtensionService::GetPendingExtensionUpdate(
return pending_extension_updates_.GetByID(id);
}
-const Extension* ExtensionService::GetExtensionByIdInternal(
- const std::string& id, int include_mask) const {
- std::string lowercase_id = StringToLowerASCII(id);
- if (include_mask & INCLUDE_ENABLED) {
- const Extension* extension = extensions_.GetByID(lowercase_id);
- if (extension)
- return extension;
- }
- if (include_mask & INCLUDE_DISABLED) {
- const Extension* extension = disabled_extensions_.GetByID(lowercase_id);
- if (extension)
- return extension;
- }
- if (include_mask & INCLUDE_TERMINATED) {
- const Extension* extension = terminated_extensions_.GetByID(lowercase_id);
- if (extension)
- return extension;
- }
- return NULL;
-}
-
void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
if (!terminated_extensions_.Contains(extension->id()))
terminated_extensions_.Insert(make_scoped_refptr(extension));
@@ -2519,13 +2569,16 @@ void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
const Extension* ExtensionService::GetTerminatedExtension(
const std::string& id) const {
- return GetExtensionByIdInternal(id, INCLUDE_TERMINATED);
+ return GetExtensionById(id, INCLUDE_TERMINATED);
}
const Extension* ExtensionService::GetInstalledExtension(
const std::string& id) const {
- int include_mask = INCLUDE_ENABLED | INCLUDE_DISABLED | INCLUDE_TERMINATED;
- return GetExtensionByIdInternal(id, include_mask);
+ int include_mask = INCLUDE_ENABLED |
+ INCLUDE_DISABLED |
+ INCLUDE_TERMINATED |
+ INCLUDE_BLACKLISTED;
+ return GetExtensionById(id, include_mask);
}
bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) {
@@ -3017,9 +3070,7 @@ bool ExtensionService::ShouldDelayExtensionUpdate(
if (!install_updates_when_idle_ || !wait_for_idle)
return false;
- int include_mask = INCLUDE_ENABLED | INCLUDE_DISABLED;
- const Extension* old =
- GetExtensionByIdInternal(extension_id, include_mask);
+ const Extension* old = GetInstalledExtension(extension_id);
// If there is no old extension, this is not an update, so don't delay.
if (!old)
return false;
@@ -3036,5 +3087,49 @@ bool ExtensionService::ShouldDelayExtensionUpdate(
}
void ExtensionService::OnBlacklistUpdated() {
- CheckManagementPolicy();
+ blacklist_->GetBlacklistedIDs(
+ GenerateInstalledExtensionsSet()->GetIDs(),
+ base::Bind(&ExtensionService::ManageBlacklist,
+ AsWeakPtr(),
+ blacklisted_extensions_.GetIDs()));
+}
+
+void ExtensionService::ManageBlacklist(
+ const std::set<std::string>& old_blacklisted_ids,
+ const std::set<std::string>& new_blacklisted_ids) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ std::set<std::string> no_longer_blacklisted;
+ std::set_difference(old_blacklisted_ids.begin(), old_blacklisted_ids.end(),
+ new_blacklisted_ids.begin(), new_blacklisted_ids.end(),
+ std::inserter(no_longer_blacklisted,
+ no_longer_blacklisted.begin()));
+ std::set<std::string> not_yet_blacklisted;
+ std::set_difference(new_blacklisted_ids.begin(), new_blacklisted_ids.end(),
+ old_blacklisted_ids.begin(), old_blacklisted_ids.end(),
+ std::inserter(not_yet_blacklisted,
+ not_yet_blacklisted.begin()));
+
+ for (std::set<std::string>::iterator it = no_longer_blacklisted.begin();
+ it != no_longer_blacklisted.end(); ++it) {
+ scoped_refptr<const Extension> extension =
+ blacklisted_extensions_.GetByID(*it);
+ DCHECK(extension);
+ if (!extension)
+ continue;
+ blacklisted_extensions_.Remove(*it);
+ AddExtension(extension);
+ }
+
+ for (std::set<std::string>::iterator it = not_yet_blacklisted.begin();
+ it != not_yet_blacklisted.end(); ++it) {
+ scoped_refptr<const Extension> extension = GetInstalledExtension(*it);
+ DCHECK(extension);
+ if (!extension)
+ continue;
+ blacklisted_extensions_.Insert(extension);
+ UnloadExtension(*it, extension_misc::UNLOAD_REASON_BLACKLIST);
+ }
+
+ IdentifyAlertableExtensions();
}
« no previous file with comments | « chrome/browser/extensions/extension_service.h ('k') | chrome/browser/extensions/extension_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698