Chromium Code Reviews| 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( |