Index: chrome/browser/extensions/extension_service.cc |
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc |
index 5617fb921cc72ee43c69857c9835ff5e360edb15..6f7ab514e48a0ceb28d6cd0aa1b3eac4b3df3765 100644 |
--- a/chrome/browser/extensions/extension_service.cc |
+++ b/chrome/browser/extensions/extension_service.cc |
@@ -47,6 +47,7 @@ |
#include "chrome/browser/extensions/extension_error_ui.h" |
#include "chrome/browser/extensions/extension_host.h" |
#include "chrome/browser/extensions/extension_install_ui.h" |
+#include "chrome/browser/extensions/extension_install_ui_default.h" |
#include "chrome/browser/extensions/extension_process_manager.h" |
#include "chrome/browser/extensions/extension_sorting.h" |
#include "chrome/browser/extensions/extension_special_storage_policy.h" |
@@ -107,6 +108,7 @@ |
#include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
#include "sync/api/sync_change.h" |
#include "sync/api/sync_error_factory.h" |
+#include "ui/base/l10n/l10n_util.h" |
#include "webkit/database/database_tracker.h" |
#include "webkit/database/database_util.h" |
@@ -124,6 +126,7 @@ using extensions::CrxInstaller; |
using extensions::Extension; |
using extensions::ExtensionIdSet; |
using extensions::ExtensionInfo; |
+using extensions::ExtensionList; |
using extensions::FeatureSwitch; |
using extensions::Manifest; |
using extensions::PermissionMessage; |
@@ -759,7 +762,10 @@ void ExtensionService::ReloadExtensionWithEvents( |
extension_prefs_->GetInstalledExtensionInfo(extension_id)); |
if (installed_extension.get() && |
installed_extension->extension_manifest.get()) { |
- extensions::InstalledLoader(this).Load(*installed_extension, false); |
+ // The extension is being reloaded so it couldn't have been blacklisted, so |
+ // it probably isn't blacklisted now either... |
+ AddNonBlacklistedExtension( |
+ extensions::InstalledLoader(this).Load(*installed_extension, false)); |
} else { |
// Otherwise, the extension is unpacked (location LOAD). |
// We should always be able to remember the extension's path. If it's not in |
@@ -2045,86 +2051,34 @@ void ExtensionService::OnLoadedInstalledExtensions() { |
content::NotificationService::NoDetails()); |
} |
-void ExtensionService::AddExtension(const Extension* extension) { |
- // TODO(jstritar): We may be able to get rid of this branch by overriding the |
- // default extension state to DISABLED when the --disable-extensions flag |
- // is set (http://crbug.com/29067). |
- if (!extensions_enabled() && |
- !extension->is_theme() && |
- extension->location() != Manifest::COMPONENT && |
- !Manifest::IsExternalLocation(extension->location())) { |
+void ExtensionService::AddExtensions(const ExtensionList& extensions) { |
Matt Perry
2013/02/07 01:05:35
Rather than adding a new API, couldn't you instead
not at google - send to devlin
2013/02/07 02:11:37
Done.
|
+ if (extensions.empty()) |
return; |
- } |
- SetBeingUpgraded(extension, false); |
- |
- // The extension is now loaded, remove its data from unloaded extension map. |
- unloaded_extension_paths_.erase(extension->id()); |
- |
- // If a terminated extension is loaded, remove it from the terminated list. |
- UntrackTerminatedExtension(extension->id()); |
- |
- // If the extension was disabled for a reload, then enable it. |
- if (disabled_extension_paths_.erase(extension->id()) > 0) |
- EnableExtension(extension->id()); |
- |
- // Check if the extension's privileges have changed and disable the |
- // extension if necessary. |
- InitializePermissions(extension); |
- |
- // If this extension is a sideloaded extension and we've not performed a |
- // wipeout before, we might disable this extension here. |
- MaybeWipeout(extension); |
- |
- // Communicated to the Blacklist. |
+ std::set<std::string> all_ids; |
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( |
- chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED, |
- content::Source<Profile>(profile_), |
- content::Details<const Extension>(extension)); |
- |
- // Show the extension disabled error if a permissions increase was the |
- // only reason it was disabled. |
- if (extension_prefs_->GetDisableReasons(extension->id()) == |
- Extension::DISABLE_PERMISSIONS_INCREASE) { |
- extensions::AddExtensionDisabledError(this, extension); |
- } |
- } 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); |
+ for (ExtensionList::const_iterator it = extensions.begin(); |
+ it != extensions.end(); ++it) { |
+ const std::string& id = (*it)->id(); |
+ // Well... this is a lie, it might actually be blacklisted, but we check |
+ // that below asynchronously. |
+ if (!AddNonBlacklistedExtension(*it)) |
+ already_in_blacklist.insert(id); |
+ all_ids.insert(id); |
} |
- // 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, |
+ all_ids, |
base::Bind(&ExtensionService::ManageBlacklist, |
AsWeakPtr(), |
already_in_blacklist)); |
} |
+void ExtensionService::AddExtension(const Extension* extension) { |
+ AddExtensions(ExtensionList(1, make_scoped_refptr(extension))); |
+} |
+ |
void ExtensionService::AddComponentExtension(const Extension* extension) { |
const std::string old_version_string( |
extension_prefs_->GetVersionString(extension->id())); |
@@ -2141,7 +2095,7 @@ void ExtensionService::AddComponentExtension(const Extension* extension) { |
return; |
} |
- AddExtension(extension); |
+ AddNonBlacklistedExtension(extension); |
} |
void ExtensionService::InitializePermissions(const Extension* extension) { |
@@ -2322,7 +2276,55 @@ void ExtensionService::UpdateActiveExtensionsInCrashReporter() { |
child_process_logging::SetActiveExtensions(extension_ids); |
} |
-void ExtensionService::OnExtensionInstalled( |
+namespace { |
+ |
+// Runs |closure| if |extension| isn't blacklisted, and runs |on_done| either |
+// way. |
+void RunIfNotBlacklisted(Profile* profile, |
+ const scoped_refptr<const Extension>& extension, |
+ const base::Closure& closure, |
+ const base::Callback<void(bool)>& on_done, |
+ const std::set<std::string>& blacklist) { |
+ if (blacklist.count(extension->id())) { |
+ ExtensionInstallUIDefault(profile).OnInstallFailure( |
+ extensions::CrxInstallerError( |
+ l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED, |
+ UTF8ToUTF16(extension->name())))); |
+ on_done.Run(false); |
+ return; |
+ } |
+ |
+ closure.Run(); |
+ on_done.Run(true); |
+} |
+ |
+} // namespace |
+ |
+void ExtensionService::InstallExtensionAsync( |
+ const Extension* extension, |
+ const syncer::StringOrdinal& page_ordinal, |
+ bool has_requirement_errors, |
+ bool wait_for_idle, |
+ const base::Callback<void(bool)>& on_done) { |
+ std::set<std::string> id; |
+ id.insert(extension->id()); |
+ blacklist_->GetBlacklistedIDs( |
+ id, |
+ base::Bind(&RunIfNotBlacklisted, |
+ profile_, |
+ // Note: binding extension here to a scoped_ptr keeps it in |
+ // scope all the way to InstallExtensionNow. |
+ make_scoped_refptr(extension), |
+ base::Bind(&ExtensionService::InstallExtensionNow, |
+ AsWeakPtr(), |
+ extension, |
+ page_ordinal, |
+ has_requirement_errors, |
+ wait_for_idle), |
+ on_done)); |
+} |
+ |
+void ExtensionService::InstallExtensionNow( |
const Extension* extension, |
const syncer::StringOrdinal& page_ordinal, |
bool has_requirement_errors, |
@@ -2481,10 +2483,10 @@ void ExtensionService::FinishInstallation(const Extension* extension) { |
AddExtension(extension); |
#if defined(ENABLE_THEMES) |
- // We do this here since AddExtension() is always called on browser |
- // startup, and we only really care about the last theme installed. |
- // If that ever changes and we have to move this code somewhere |
- // else, it should be somewhere that's not in the startup path. |
+ // We do this here since AddExtensions() is always called on browser startup, |
+ // and we only really care about the last theme installed. If that ever |
+ // changes and we have to move this code somewhere else, it should be |
+ // somewhere that's not in the startup path. |
if (extension->is_theme() && extensions_.GetByID(extension->id())) { |
DCHECK_EQ(extensions_.GetByID(extension->id()), extension); |
// Now that the theme extension is visible from outside the |
@@ -2522,6 +2524,76 @@ void ExtensionService::UntrackTerminatedExtension(const std::string& id) { |
terminated_extensions_.Remove(lowercase_id); |
} |
+bool ExtensionService::AddNonBlacklistedExtension(const Extension* extension) { |
+ // TODO(jstritar): We may be able to get rid of this branch by overriding the |
+ // default extension state to DISABLED when the --disable-extensions flag |
+ // is set (http://crbug.com/29067). |
+ if (!extensions_enabled() && |
+ !extension->is_theme() && |
+ extension->location() != Manifest::COMPONENT && |
+ !Manifest::IsExternalLocation(extension->location())) { |
+ return true; |
+ } |
+ |
+ SetBeingUpgraded(extension, false); |
+ |
+ // The extension is now loaded, remove its data from unloaded extension map. |
+ unloaded_extension_paths_.erase(extension->id()); |
+ |
+ // If a terminated extension is loaded, remove it from the terminated list. |
+ UntrackTerminatedExtension(extension->id()); |
+ |
+ // If the extension was disabled for a reload, then enable it. |
+ if (disabled_extension_paths_.erase(extension->id()) > 0) |
+ EnableExtension(extension->id()); |
+ |
+ // Check if the extension's privileges have changed and disable the |
+ // extension if necessary. |
+ InitializePermissions(extension); |
+ |
+ // If this extension is a sideloaded extension and we've not performed a |
+ // wipeout before, we might disable this extension here. |
+ MaybeWipeout(extension); |
+ |
+ // Communicated to the Blacklist. |
+ bool was_prefs_blacklisted = false; |
+ |
+ if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { |
+ // We always store the blacklisted state of *installed* extensions in |
+ // prefs, and it's important not to re-enable them. |
+ blacklisted_extensions_.Insert(extension); |
+ was_prefs_blacklisted = true; |
+ } else if (extension_prefs_->IsExtensionDisabled(extension->id())) { |
+ disabled_extensions_.Insert(extension); |
+ SyncExtensionChangeIfNeeded(*extension); |
+ content::NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED, |
+ content::Source<Profile>(profile_), |
+ content::Details<const Extension>(extension)); |
+ |
+ // Show the extension disabled error if a permissions increase was the |
+ // only reason it was disabled. |
+ if (extension_prefs_->GetDisableReasons(extension->id()) == |
+ Extension::DISABLE_PERMISSIONS_INCREASE) { |
+ extensions::AddExtensionDisabledError(this, extension); |
+ } |
+ } 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); |
+ } |
+ |
+ return !was_prefs_blacklisted; |
+} |
+ |
const Extension* ExtensionService::GetTerminatedExtension( |
const std::string& id) const { |
return GetExtensionById(id, INCLUDE_TERMINATED); |
@@ -3107,7 +3179,7 @@ void ExtensionService::ManageBlacklist( |
if (!extension) |
continue; |
blacklisted_extensions_.Remove(*it); |
- AddExtension(extension); |
+ AddNonBlacklistedExtension(extension); |
} |
for (std::set<std::string>::iterator it = not_yet_blacklisted.begin(); |