Index: chrome/browser/extensions/extension_service.cc |
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc |
index 89e50cdd342c4208cafade1080e597e23759a141..4c432d1a54d4473133ad5846135a70d1bf483476 100644 |
--- a/chrome/browser/extensions/extension_service.cc |
+++ b/chrome/browser/extensions/extension_service.cc |
@@ -80,6 +80,7 @@ |
#include "chrome/common/extensions/api/plugins/plugins_handler.h" |
#include "chrome/common/extensions/background_info.h" |
#include "chrome/common/extensions/extension.h" |
+#include "chrome/common/extensions/extension_constants.h" |
#include "chrome/common/extensions/extension_file_util.h" |
#include "chrome/common/extensions/extension_manifest_constants.h" |
#include "chrome/common/extensions/extension_messages.h" |
@@ -88,6 +89,7 @@ |
#include "chrome/common/extensions/incognito_handler.h" |
#include "chrome/common/extensions/manifest.h" |
#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" |
+#include "chrome/common/extensions/manifest_handlers/shared_module_info.h" |
#include "chrome/common/extensions/manifest_url_handler.h" |
#include "chrome/common/pref_names.h" |
#include "chrome/common/startup_metric_utils.h" |
@@ -130,6 +132,7 @@ using extensions::Manifest; |
using extensions::PermissionMessage; |
using extensions::PermissionMessages; |
using extensions::PermissionSet; |
+using extensions::SharedModuleInfo; |
using extensions::UnloadedExtensionInfo; |
namespace errors = extension_manifest_errors; |
@@ -165,6 +168,10 @@ static bool IsSyncableApp(const Extension& extension) { |
return extension.GetSyncType() == Extension::SYNC_TYPE_APP; |
} |
+static bool IsSharedModule(const Extension& extension) { |
+ return SharedModuleInfo::IsSharedModule(&extension); |
+} |
+ |
} // namespace |
ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() |
@@ -872,6 +879,8 @@ bool ExtensionService::UninstallExtension( |
delayed_updates_for_idle_.Remove(extension_id); |
delayed_installs_.Remove(extension_id); |
+ PruneSharedModulesOnUninstall(extension); |
+ |
// Track the uninstallation. |
UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2); |
@@ -2028,6 +2037,8 @@ void ExtensionService::OnLoadedInstalledExtensions() { |
OnBlacklistUpdated(); |
SetReadyAndNotifyListeners(); |
+ |
+ CheckImportsOnAllExtensions(); |
} |
void ExtensionService::AddExtension(const Extension* extension) { |
@@ -2277,6 +2288,103 @@ void ExtensionService::ScheduleLaunchOnLoad(const std::string& extension_id) { |
on_load_events_[extension_id] = EVENT_LAUNCHED; |
} |
+bool ExtensionService::CheckImports(const Extension* extension) { |
+ bool import_failed = false; |
+ if (SharedModuleInfo::ImportsModules(extension)) { |
+ const std::vector<SharedModuleInfo::ImportInfo>& imports = |
+ SharedModuleInfo::GetImports(extension); |
+ std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; |
+ for (i = imports.begin(); i != imports.end(); ++i) { |
+ Version version_required(i->minimum_version); |
+ const Extension* imported_module = |
+ GetExtensionById(i->extension_id, true); |
+ if (!imported_module || |
+ (version_required.IsValid() && |
+ imported_module->version()->CompareTo(version_required) < 0)) { |
+ import_failed = true; |
+ if (extension->from_webstore()) { |
+ if (pending_extension_manager()->AddFromExtensionImport( |
asargent_no_longer_on_chrome
2013/05/17 17:13:49
in the implementation of PendingExtensionManager::
|
+ i->extension_id, |
+ extension_urls::GetWebstoreUpdateUrl(), |
+ IsSharedModule)) { |
+ CheckForUpdatesSoon(); |
+ } |
+ } |
+ } |
+ if (imported_module && |
+ !SharedModuleInfo::IsSharedModule(imported_module)) { |
+ import_failed = true; |
+ } |
+ } |
+ } |
+ const std::string& id = extension->id(); |
+ if (import_failed) { |
+ extension_prefs_->AddDisableReason( |
+ id, Extension::DISABLE_MISSING_IMPORT); |
+ } else if (extension_prefs_->GetDisableReasons(id) == |
+ Extension::DISABLE_MISSING_IMPORT) { |
+ EnableExtension(id); |
+ } |
+ return !import_failed; |
+} |
+ |
+void ExtensionService::CheckImportsOnAllExtensions() { |
+ std::vector<const Extension*> extensions_to_check; |
+ for (ExtensionSet::const_iterator iter = disabled_extensions_.begin(); |
+ iter != disabled_extensions_.end(); ++iter) { |
+ extensions_to_check.push_back(*iter); |
+ } |
+ for (ExtensionSet::const_iterator iter = extensions_.begin(); |
+ iter != extensions_.end(); ++iter) { |
+ extensions_to_check.push_back(*iter); |
+ } |
+ std::vector<const Extension*>::const_iterator iter; |
+ for (iter = extensions_to_check.begin(); |
+ iter != extensions_to_check.end(); |
+ ++iter) { |
+ CheckImports(*iter); |
+ } |
+} |
+ |
+void ExtensionService::PruneSharedModulesOnUninstall( |
+ const Extension* extension) { |
+ if (SharedModuleInfo::ImportsModules(extension)) { |
+ const std::vector<SharedModuleInfo::ImportInfo>& imports = |
+ SharedModuleInfo::GetImports(extension); |
+ std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; |
+ for (i = imports.begin(); i != imports.end(); ++i) { |
+ const Extension* imported_module = |
+ GetExtensionById(i->extension_id, true); |
+ if (!imported_module) |
+ continue; |
+ if (SharedModuleInfo::IsSharedModule(imported_module)) { |
+ bool is_referenced = false; |
+ for (ExtensionSet::const_iterator iter = disabled_extensions_.begin(); |
+ iter != disabled_extensions_.end(); ++iter) { |
+ if (SharedModuleInfo::ImportsExtensionById(*iter, i->extension_id)) { |
+ is_referenced = true; |
+ break; |
+ } |
+ } |
+ if (!is_referenced) { |
+ for (ExtensionSet::const_iterator iter = extensions_.begin(); |
+ iter != extensions_.end(); ++iter) { |
+ if (SharedModuleInfo::ImportsExtensionById(*iter, |
+ i->extension_id)) { |
+ is_referenced = true; |
+ break; |
+ } |
+ } |
+ } |
+ if (!is_referenced) { |
+ UninstallExtension(i->extension_id, false, NULL); |
+ } |
+ } |
+ } |
+ } |
+} |
+ |
+ |
void ExtensionService::OnExtensionInstalled( |
const Extension* extension, |
const syncer::StringOrdinal& page_ordinal, |
@@ -2337,6 +2445,10 @@ void ExtensionService::OnExtensionInstalled( |
extension_prefs_->ClearDisableReasons(id); |
} |
+ if (!CheckImports(extension)) { |
+ initial_enable = false; |
+ } |
+ |
if (!GetInstalledExtension(extension->id())) { |
UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType", |
extension->GetType(), 100); |
@@ -2464,6 +2576,27 @@ void ExtensionService::FinishInstallation(const Extension* extension) { |
EXTERNAL_EXTENSION_INSTALLED, |
EXTERNAL_EXTENSION_BUCKET_BOUNDARY); |
} |
+ |
+ // Check extensions that may be disabled only because this shared module was |
+ // not available. |
+ if (SharedModuleInfo::IsSharedModule(extension)) { |
+ // Build a list of extensions to check because they can't be checked |
+ // within the loop iterating over disabled_extensions_ because contents |
+ // of that set may change as we CheckImports. |
+ std::vector<const Extension*> extensions_to_check; |
+ for (ExtensionSet::const_iterator iter = disabled_extensions_.begin(); |
+ iter != disabled_extensions_.end(); ++iter) { |
+ if (SharedModuleInfo::ImportsExtensionById((*iter), extension->id())) { |
+ extensions_to_check.push_back(*iter); |
+ } |
+ } |
+ std::vector<const Extension*>::const_iterator iter; |
+ for (iter = extensions_to_check.begin(); |
+ iter != extensions_to_check.end(); |
+ ++iter) { |
+ CheckImports(*iter); |
+ } |
+ } |
} |
const Extension* ExtensionService::GetPendingExtensionUpdate( |