Temporarily disable extensions and sync while a profile is locked.
Place all the heavy lifting and logic in profiles code, with extensions providing a new collection for holding "locked" extensions.
This replaces CL 697143003.
BUG=354124
Review URL: https://codereview.chromium.org/695133005
Cr-Commit-Position: refs/heads/master@{#305897}
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 390092d..b4e4820 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -167,10 +167,10 @@
void ExtensionService::BlacklistExtensionForTest(
const std::string& extension_id) {
- ExtensionIdSet blocked;
+ ExtensionIdSet blacklisted;
ExtensionIdSet unchanged;
- blocked.insert(extension_id);
- UpdateBlockedExtensions(blocked, unchanged);
+ blacklisted.insert(extension_id);
+ UpdateBlacklistedExtensions(blacklisted, unchanged);
}
bool ExtensionService::OnExternalExtensionUpdateUrlFound(
@@ -270,6 +270,7 @@
browser_terminating_(false),
installs_delayed_for_gc_(false),
is_first_run_(false),
+ block_extensions_(false),
shared_module_service_(new extensions::SharedModuleService(profile_)) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -370,11 +371,11 @@
const std::string& id, bool include_disabled) const {
int include_mask = ExtensionRegistry::ENABLED;
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 blacklisted and blocked 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 or blocking.
include_mask |= ExtensionRegistry::DISABLED |
- ExtensionRegistry::BLACKLISTED;
+ ExtensionRegistry::BLACKLISTED | ExtensionRegistry::BLOCKED;
}
return registry_->GetExtensionById(id, include_mask);
}
@@ -575,12 +576,14 @@
return;
}
- // Ignore attempts to reload a blacklisted extension. Sometimes this can
- // happen in a convoluted reload sequence triggered by the termination of a
- // blacklisted extension and a naive attempt to reload it. For an example see
- // http://crbug.com/373842.
- if (registry_->blacklisted_extensions().Contains(transient_extension_id))
+ // Ignore attempts to reload a blacklisted or blocked extension. Sometimes
+ // this can happen in a convoluted reload sequence triggered by the
+ // termination of a blacklisted or blocked extension and a naive attempt to
+ // reload it. For an example see http://crbug.com/373842.
+ if (registry_->blacklisted_extensions().Contains(transient_extension_id) ||
+ registry_->blocked_extensions().Contains(transient_extension_id)) {
return;
+ }
base::FilePath path;
@@ -785,10 +788,15 @@
}
if (registry_->disabled_extensions().Contains(extension_id) ||
- registry_->blacklisted_extensions().Contains(extension_id)) {
+ registry_->blacklisted_extensions().Contains(extension_id) ||
+ registry_->blocked_extensions().Contains(extension_id)) {
return false;
}
+ if (block_extensions_ &&
+ CanBlockExtension(GetInstalledExtension(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) &&
@@ -916,6 +924,48 @@
}
}
+// Extensions that are not locked, components or forced by policy should be
+// locked. Extensions are no longer considered enabled or disabled. Blacklisted
+// extensions are now considered both blacklisted and locked.
+void ExtensionService::BlockAllExtensions() {
+ if (block_extensions_)
+ return;
+ block_extensions_ = true;
+
+ // Blacklisted extensions are already unloaded, need not be blocked.
+ scoped_ptr<ExtensionSet> extensions =
+ registry_->GenerateInstalledExtensionsSet(ExtensionRegistry::ENABLED |
+ ExtensionRegistry::DISABLED |
+ ExtensionRegistry::TERMINATED);
+
+ for (const scoped_refptr<const Extension>& extension : *extensions) {
+ const std::string& id = extension->id();
+
+ if (!CanBlockExtension(extension.get()))
+ continue;
+
+ registry_->RemoveEnabled(id);
+ registry_->RemoveDisabled(id);
+ registry_->RemoveTerminated(id);
+
+ registry_->AddBlocked(extension.get());
+ UnloadExtension(id, extensions::UnloadedExtensionInfo::REASON_LOCK_ALL);
+ }
+}
+
+// All locked extensions should revert to being either enabled or disabled
+// as appropriate.
+void ExtensionService::UnblockAllExtensions() {
+ block_extensions_ = false;
+ scoped_ptr<ExtensionSet> to_unblock =
+ registry_->GenerateInstalledExtensionsSet(ExtensionRegistry::BLOCKED);
+
+ for (const scoped_refptr<const Extension>& extension : *to_unblock) {
+ registry_->RemoveBlocked(extension->id());
+ AddExtension(extension.get());
+ }
+}
+
void ExtensionService::GrantPermissionsAndEnableExtension(
const Extension* extension) {
GrantPermissions(extension);
@@ -1371,6 +1421,8 @@
// installation then threads through the install and pending install flow
// of this class, and we check when loading installed extensions.
registry_->AddBlacklisted(extension);
+ } else if (block_extensions_ && CanBlockExtension(extension)) {
+ registry_->AddBlocked(extension);
} else if (!reloading &&
extension_prefs_->IsExtensionDisabled(extension->id())) {
registry_->AddDisabled(extension);
@@ -2194,6 +2246,13 @@
return Extension::DISABLE_NONE;
}
+// Helper method to determine if an extension can be blocked.
+bool ExtensionService::CanBlockExtension(const Extension* extension) const {
+ return extension->location() != Manifest::COMPONENT &&
+ extension->location() != Manifest::EXTERNAL_COMPONENT &&
+ !system_->management_policy()->MustRemainEnabled(extension, NULL);
+}
+
bool ExtensionService::ShouldDelayExtensionUpdate(
const std::string& extension_id,
bool install_immediately) const {
@@ -2255,7 +2314,7 @@
const extensions::Blacklist::BlacklistStateMap& state_map) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::set<std::string> blocked;
+ std::set<std::string> blacklisted;
ExtensionIdSet greylist;
ExtensionIdSet unchanged;
for (extensions::Blacklist::BlacklistStateMap::const_iterator it =
@@ -2267,7 +2326,7 @@
break;
case extensions::BLACKLISTED_MALWARE:
- blocked.insert(it->first);
+ blacklisted.insert(it->first);
break;
case extensions::BLACKLISTED_SECURITY_VULNERABILITY:
@@ -2282,7 +2341,7 @@
}
}
- UpdateBlockedExtensions(blocked, unchanged);
+ UpdateBlacklistedExtensions(blacklisted, unchanged);
UpdateGreylistedExtensions(greylist, unchanged, state_map);
error_controller_->ShowErrorIfNeeded();
@@ -2300,21 +2359,20 @@
}
} // namespace
-void ExtensionService::UpdateBlockedExtensions(
- const ExtensionIdSet& blocked,
+void ExtensionService::UpdateBlacklistedExtensions(
+ const ExtensionIdSet& blacklisted,
const ExtensionIdSet& unchanged) {
ExtensionIdSet not_yet_blocked, no_longer_blocked;
- Partition(registry_->blacklisted_extensions().GetIDs(),
- blocked, unchanged,
- &no_longer_blocked, ¬_yet_blocked);
+ Partition(registry_->blacklisted_extensions().GetIDs(), blacklisted,
+ unchanged, &no_longer_blocked, ¬_yet_blocked);
for (ExtensionIdSet::iterator it = no_longer_blocked.begin();
it != no_longer_blocked.end(); ++it) {
scoped_refptr<const Extension> extension =
registry_->blacklisted_extensions().GetByID(*it);
if (!extension.get()) {
- NOTREACHED() << "Extension " << *it << " no longer blocked, "
- << "but it was never blocked.";
+ NOTREACHED() << "Extension " << *it << " no longer blacklisted, "
+ << "but it was never blacklisted.";
continue;
}
registry_->RemoveBlacklisted(*it);