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

Side by Side Diff: chrome/browser/extensions/extension_service.cc

Issue 14973007: Auto-install/uninstall shared module dependencies for extensions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: more feedback Created 7 years, 6 months 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_service.h" 5 #include "chrome/browser/extensions/extension_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 #include <set> 9 #include <set>
10 10
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 #include "chrome/browser/themes/theme_service_factory.h" 69 #include "chrome/browser/themes/theme_service_factory.h"
70 #include "chrome/browser/ui/webui/favicon_source.h" 70 #include "chrome/browser/ui/webui/favicon_source.h"
71 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h" 71 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
72 #include "chrome/browser/ui/webui/theme_source.h" 72 #include "chrome/browser/ui/webui/theme_source.h"
73 #include "chrome/common/child_process_logging.h" 73 #include "chrome/common/child_process_logging.h"
74 #include "chrome/common/chrome_notification_types.h" 74 #include "chrome/common/chrome_notification_types.h"
75 #include "chrome/common/chrome_switches.h" 75 #include "chrome/common/chrome_switches.h"
76 #include "chrome/common/chrome_version_info.h" 76 #include "chrome/common/chrome_version_info.h"
77 #include "chrome/common/extensions/background_info.h" 77 #include "chrome/common/extensions/background_info.h"
78 #include "chrome/common/extensions/extension.h" 78 #include "chrome/common/extensions/extension.h"
79 #include "chrome/common/extensions/extension_constants.h"
79 #include "chrome/common/extensions/extension_file_util.h" 80 #include "chrome/common/extensions/extension_file_util.h"
80 #include "chrome/common/extensions/extension_manifest_constants.h" 81 #include "chrome/common/extensions/extension_manifest_constants.h"
81 #include "chrome/common/extensions/extension_messages.h" 82 #include "chrome/common/extensions/extension_messages.h"
82 #include "chrome/common/extensions/feature_switch.h" 83 #include "chrome/common/extensions/feature_switch.h"
83 #include "chrome/common/extensions/features/feature.h" 84 #include "chrome/common/extensions/features/feature.h"
84 #include "chrome/common/extensions/incognito_handler.h" 85 #include "chrome/common/extensions/incognito_handler.h"
85 #include "chrome/common/extensions/manifest.h" 86 #include "chrome/common/extensions/manifest.h"
86 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" 87 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
87 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 88 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
89 #include "chrome/common/extensions/manifest_handlers/shared_module_info.h"
88 #include "chrome/common/extensions/manifest_url_handler.h" 90 #include "chrome/common/extensions/manifest_url_handler.h"
89 #include "chrome/common/extensions/permissions/permissions_data.h" 91 #include "chrome/common/extensions/permissions/permissions_data.h"
90 #include "chrome/common/extensions/sync_helper.h" 92 #include "chrome/common/extensions/sync_helper.h"
91 #include "chrome/common/pref_names.h" 93 #include "chrome/common/pref_names.h"
92 #include "chrome/common/startup_metric_utils.h" 94 #include "chrome/common/startup_metric_utils.h"
93 #include "chrome/common/url_constants.h" 95 #include "chrome/common/url_constants.h"
94 #include "content/public/browser/browser_thread.h" 96 #include "content/public/browser/browser_thread.h"
95 #include "content/public/browser/devtools_agent_host.h" 97 #include "content/public/browser/devtools_agent_host.h"
96 #include "content/public/browser/notification_service.h" 98 #include "content/public/browser/notification_service.h"
97 #include "content/public/browser/notification_types.h" 99 #include "content/public/browser/notification_types.h"
(...skipping 22 matching lines...) Expand all
120 using content::DevToolsAgentHost; 122 using content::DevToolsAgentHost;
121 using extensions::CrxInstaller; 123 using extensions::CrxInstaller;
122 using extensions::Extension; 124 using extensions::Extension;
123 using extensions::ExtensionIdSet; 125 using extensions::ExtensionIdSet;
124 using extensions::ExtensionInfo; 126 using extensions::ExtensionInfo;
125 using extensions::FeatureSwitch; 127 using extensions::FeatureSwitch;
126 using extensions::Manifest; 128 using extensions::Manifest;
127 using extensions::PermissionMessage; 129 using extensions::PermissionMessage;
128 using extensions::PermissionMessages; 130 using extensions::PermissionMessages;
129 using extensions::PermissionSet; 131 using extensions::PermissionSet;
132 using extensions::SharedModuleInfo;
130 using extensions::UnloadedExtensionInfo; 133 using extensions::UnloadedExtensionInfo;
131 134
132 namespace errors = extension_manifest_errors; 135 namespace errors = extension_manifest_errors;
133 136
134 namespace { 137 namespace {
135 138
136 // Histogram values for logging events related to externally installed 139 // Histogram values for logging events related to externally installed
137 // extensions. 140 // extensions.
138 enum ExternalExtensionEvent { 141 enum ExternalExtensionEvent {
139 EXTERNAL_EXTENSION_INSTALLED = 0, 142 EXTERNAL_EXTENSION_INSTALLED = 0,
140 EXTERNAL_EXTENSION_IGNORED, 143 EXTERNAL_EXTENSION_IGNORED,
141 EXTERNAL_EXTENSION_REENABLED, 144 EXTERNAL_EXTENSION_REENABLED,
142 EXTERNAL_EXTENSION_UNINSTALLED, 145 EXTERNAL_EXTENSION_UNINSTALLED,
143 EXTERNAL_EXTENSION_BUCKET_BOUNDARY, 146 EXTERNAL_EXTENSION_BUCKET_BOUNDARY,
144 }; 147 };
145 148
146 // Prompt the user this many times before considering an extension acknowledged. 149 // Prompt the user this many times before considering an extension acknowledged.
147 static const int kMaxExtensionAcknowledgePromptCount = 3; 150 static const int kMaxExtensionAcknowledgePromptCount = 3;
148 151
149 // Wait this many seconds after an extensions becomes idle before updating it. 152 // Wait this many seconds after an extensions becomes idle before updating it.
150 static const int kUpdateIdleDelay = 5; 153 static const int kUpdateIdleDelay = 5;
151 154
152 // Wait this many seconds before trying to garbage collect extensions again. 155 // Wait this many seconds before trying to garbage collect extensions again.
153 static const int kGarbageCollectRetryDelay = 30; 156 static const int kGarbageCollectRetryDelay = 30;
154 157
158 static bool IsSharedModule(const Extension* extension) {
159 return SharedModuleInfo::IsSharedModule(extension);
160 }
161
155 } // namespace 162 } // namespace
156 163
157 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() 164 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData()
158 : background_page_ready(false), 165 : background_page_ready(false),
159 being_upgraded(false), 166 being_upgraded(false),
160 has_used_webrequest(false) { 167 has_used_webrequest(false) {
161 } 168 }
162 169
163 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() { 170 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() {
164 } 171 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 install_directory_(install_directory), 335 install_directory_(install_directory),
329 extensions_enabled_(extensions_enabled), 336 extensions_enabled_(extensions_enabled),
330 show_extensions_prompts_(true), 337 show_extensions_prompts_(true),
331 install_updates_when_idle_(true), 338 install_updates_when_idle_(true),
332 ready_(ready), 339 ready_(ready),
333 toolbar_model_(this), 340 toolbar_model_(this),
334 menu_manager_(profile), 341 menu_manager_(profile),
335 event_routers_initialized_(false), 342 event_routers_initialized_(false),
336 update_once_all_providers_are_ready_(false), 343 update_once_all_providers_are_ready_(false),
337 browser_terminating_(false), 344 browser_terminating_(false),
338 installs_delayed_(false), 345 installs_delayed_for_gc_(false),
339 is_first_run_(false), 346 is_first_run_(false),
340 app_sync_bundle_(this), 347 app_sync_bundle_(this),
341 extension_sync_bundle_(this) { 348 extension_sync_bundle_(this) {
342 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 349 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
343 350
344 // Figure out if extension installation should be enabled. 351 // Figure out if extension installation should be enabled.
345 if (command_line->HasSwitch(switches::kDisableExtensions) || 352 if (command_line->HasSwitch(switches::kDisableExtensions) ||
346 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { 353 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) {
347 extensions_enabled_ = false; 354 extensions_enabled_ = false;
348 } 355 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 552
546 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 553 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
547 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) || 554 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) ||
548 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) { 555 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) {
549 // The sole purpose of this launch is to install a new extension from CWS 556 // The sole purpose of this launch is to install a new extension from CWS
550 // and immediately terminate: loading already installed extensions is 557 // and immediately terminate: loading already installed extensions is
551 // unnecessary and may interfere with the inline install dialog (e.g. if an 558 // unnecessary and may interfere with the inline install dialog (e.g. if an
552 // extension listens to onStartup and opens a window). 559 // extension listens to onStartup and opens a window).
553 SetReadyAndNotifyListeners(); 560 SetReadyAndNotifyListeners();
554 } else { 561 } else {
555 // TODO(mek): It might be cleaner to do the FinishDelayedInstallInfo stuff
556 // here instead of in installedloader.
557 if (g_browser_process->profile_manager() && 562 if (g_browser_process->profile_manager() &&
558 g_browser_process->profile_manager()->will_import()) { 563 g_browser_process->profile_manager()->will_import()) {
559 // Do not load any component extensions, since they may conflict with the 564 // Do not load any component extensions, since they may conflict with the
560 // import process. 565 // import process.
561 566
562 extensions::InstalledLoader(this).LoadAllExtensions(); 567 extensions::InstalledLoader(this).LoadAllExtensions();
563 SetReadyAndNotifyListeners(); 568 SetReadyAndNotifyListeners();
564 RegisterForImportFinished(); 569 RegisterForImportFinished();
565 } else { 570 } else {
566 // In this case, LoadAllExtensions() calls OnLoadedInstalledExtensions(). 571 // In this case, LoadAllExtensions() calls OnLoadedInstalledExtensions().
567 component_loader_->LoadAll(); 572 component_loader_->LoadAll();
568 extensions::InstalledLoader(this).LoadAllExtensions(); 573 extensions::InstalledLoader(this).LoadAllExtensions();
569 SetReadyAndNotifyListeners(); 574 SetReadyAndNotifyListeners();
570 575
571 // TODO(erikkay) this should probably be deferred to a future point 576 // TODO(erikkay) this should probably be deferred to a future point
572 // rather than running immediately at startup. 577 // rather than running immediately at startup.
573 CheckForExternalUpdates(); 578 CheckForExternalUpdates();
574 579
575 // TODO(erikkay) this should probably be deferred as well. 580 // TODO(erikkay) this should probably be deferred as well.
576 GarbageCollectExtensions(); 581 GarbageCollectExtensions();
577 } 582 }
578 583
584 // Finish install (if possible) of extensions that were still delayed while
585 // the browser was shut down.
586 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info(
587 extension_prefs_->GetAllDelayedInstallInfo());
588 for (size_t i = 0; i < delayed_info->size(); ++i) {
589 ExtensionInfo* info = delayed_info->at(i).get();
590 scoped_refptr<const Extension> extension(NULL);
591 if (info->extension_manifest) {
592 std::string error;
593 extension = Extension::Create(
594 info->extension_path,
595 info->extension_location,
596 *info->extension_manifest,
597 extension_prefs_->GetDelayedInstallCreationFlags(
598 info->extension_id),
599 &error);
600 if (extension.get())
601 delayed_installs_.Insert(extension);
602 }
603 }
604 MaybeFinishDelayedInstallations();
605 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2(
606 extension_prefs_->GetAllDelayedInstallInfo());
607 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad",
608 delayed_info2->size() - delayed_info->size());
609
579 if (extension_prefs_->NeedsStorageGarbageCollection()) { 610 if (extension_prefs_->NeedsStorageGarbageCollection()) {
580 GarbageCollectIsolatedStorage(); 611 GarbageCollectIsolatedStorage();
581 extension_prefs_->SetNeedsStorageGarbageCollection(false); 612 extension_prefs_->SetNeedsStorageGarbageCollection(false);
582 } 613 }
583 } 614 }
584 } 615 }
585 616
586 bool ExtensionService::UpdateExtension(const std::string& id, 617 bool ExtensionService::UpdateExtension(const std::string& id,
587 const base::FilePath& extension_path, 618 const base::FilePath& extension_path,
588 const GURL& download_url, 619 const GURL& download_url,
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 orphaned_dev_tools_[extension_id] = devtools_cookie; 725 orphaned_dev_tools_[extension_id] = devtools_cookie;
695 } 726 }
696 727
697 path = current_extension->path(); 728 path = current_extension->path();
698 DisableExtension(extension_id, Extension::DISABLE_RELOAD); 729 DisableExtension(extension_id, Extension::DISABLE_RELOAD);
699 reloading_extensions_.insert(extension_id); 730 reloading_extensions_.insert(extension_id);
700 } else { 731 } else {
701 path = unloaded_extension_paths_[extension_id]; 732 path = unloaded_extension_paths_[extension_id];
702 } 733 }
703 734
704 if (delayed_updates_for_idle_.Contains(extension_id)) { 735 if (delayed_installs_.Contains(extension_id)) {
705 FinishDelayedInstallation(extension_id); 736 FinishDelayedInstallation(extension_id);
706 return; 737 return;
707 } 738 }
708 739
709 // If we're reloading a component extension, use the component extension 740 // If we're reloading a component extension, use the component extension
710 // loader's reloader. 741 // loader's reloader.
711 if (component_loader_->Exists(extension_id)) { 742 if (component_loader_->Exists(extension_id)) {
712 component_loader_->Reload(extension_id); 743 component_loader_->Reload(extension_id);
713 return; 744 return;
714 } 745 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 content::Details<const Extension>(extension.get())); 853 content::Details<const Extension>(extension.get()));
823 854
824 if (app_sync_bundle_.HasExtensionId(extension_id) && 855 if (app_sync_bundle_.HasExtensionId(extension_id) &&
825 sync_change.sync_data().GetDataType() == syncer::APPS) { 856 sync_change.sync_data().GetDataType() == syncer::APPS) {
826 app_sync_bundle_.ProcessDeletion(extension_id, sync_change); 857 app_sync_bundle_.ProcessDeletion(extension_id, sync_change);
827 } else if (extension_sync_bundle_.HasExtensionId(extension_id) && 858 } else if (extension_sync_bundle_.HasExtensionId(extension_id) &&
828 sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) { 859 sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) {
829 extension_sync_bundle_.ProcessDeletion(extension_id, sync_change); 860 extension_sync_bundle_.ProcessDeletion(extension_id, sync_change);
830 } 861 }
831 862
832 delayed_updates_for_idle_.Remove(extension_id);
833 delayed_installs_.Remove(extension_id); 863 delayed_installs_.Remove(extension_id);
834 864
865 PruneSharedModulesOnUninstall(extension);
866
835 // Track the uninstallation. 867 // Track the uninstallation.
836 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2); 868 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2);
837 869
838 return true; 870 return true;
839 } 871 }
840 872
841 bool ExtensionService::IsExtensionEnabled( 873 bool ExtensionService::IsExtensionEnabled(
842 const std::string& extension_id) const { 874 const std::string& extension_id) const {
843 if (extensions_.Contains(extension_id) || 875 if (extensions_.Contains(extension_id) ||
844 terminated_extensions_.Contains(extension_id)) { 876 terminated_extensions_.Contains(extension_id)) {
(...skipping 1324 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 for (ExtensionSet::const_iterator iter = extensions_.begin(); 2201 for (ExtensionSet::const_iterator iter = extensions_.begin();
2170 iter != extensions_.end(); ++iter) { 2202 iter != extensions_.end(); ++iter) {
2171 const Extension* extension = *iter; 2203 const Extension* extension = *iter;
2172 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) 2204 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT)
2173 extension_ids.insert(extension->id()); 2205 extension_ids.insert(extension->id());
2174 } 2206 }
2175 2207
2176 child_process_logging::SetActiveExtensions(extension_ids); 2208 child_process_logging::SetActiveExtensions(extension_ids);
2177 } 2209 }
2178 2210
2211 ExtensionService::ImportStatus ExtensionService::CheckImports(
2212 const Extension* extension) {
2213 ImportStatus status = IMPORT_STATUS_OK;
2214 std::vector<std::string> pending;
2215 // TODO(elijahtaylor): Message the user if there is a failure that is
2216 // unrecoverable.
2217 if (SharedModuleInfo::ImportsModules(extension)) {
2218 const std::vector<SharedModuleInfo::ImportInfo>& imports =
2219 SharedModuleInfo::GetImports(extension);
2220 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
2221 for (i = imports.begin(); i != imports.end(); ++i) {
2222 Version version_required(i->minimum_version);
2223 const Extension* imported_module =
2224 GetExtensionById(i->extension_id, true);
2225 if (!imported_module) {
2226 if (extension->from_webstore()) {
2227 status = IMPORT_STATUS_UNSATISFIED;
2228 pending.push_back(i->extension_id);
2229 } else {
2230 return IMPORT_STATUS_UNRECOVERABLE;
2231 }
2232 } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
2233 return IMPORT_STATUS_UNRECOVERABLE;
2234 } else if (version_required.IsValid() &&
2235 imported_module->version()->CompareTo(version_required) < 0) {
2236 if (imported_module->from_webstore()) {
2237 status = IMPORT_STATUS_UNSATISFIED;
2238 } else {
2239 return IMPORT_STATUS_UNRECOVERABLE;
2240 }
2241 }
2242 }
2243 }
2244 if (status == IMPORT_STATUS_UNSATISFIED) {
2245 for (std::vector<std::string>::const_iterator iter = pending.begin();
2246 iter != pending.end();
2247 ++iter) {
2248 pending_extension_manager()->AddFromExtensionImport(
2249 *iter,
2250 extension_urls::GetWebstoreUpdateUrl(),
2251 IsSharedModule);
2252 }
2253 CheckForUpdatesSoon();
2254 }
2255 return status;
2256 }
2257
2258 scoped_ptr<const ExtensionSet>
2259 ExtensionService::GetDependentExtensions(const Extension* extension) {
2260 scoped_ptr<ExtensionSet> dependents(new ExtensionSet());
2261 scoped_ptr<ExtensionSet> set_to_check(new ExtensionSet());
2262 if (SharedModuleInfo::IsSharedModule(extension)) {
2263 set_to_check->InsertAll(disabled_extensions_);
2264 set_to_check->InsertAll(delayed_installs_);
2265 set_to_check->InsertAll(extensions_);
2266 for (ExtensionSet::const_iterator iter = set_to_check->begin();
2267 iter != set_to_check->end(); ++iter) {
2268 if (SharedModuleInfo::ImportsExtensionById(*iter, extension->id())) {
2269 dependents->Insert(*iter);
2270 }
2271 }
2272 }
2273 return dependents.PassAs<const ExtensionSet>();
2274 }
2275
2276 void ExtensionService::PruneSharedModulesOnUninstall(
2277 const Extension* extension) {
2278 if (SharedModuleInfo::ImportsModules(extension)) {
2279 const std::vector<SharedModuleInfo::ImportInfo>& imports =
2280 SharedModuleInfo::GetImports(extension);
2281 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
2282 for (i = imports.begin(); i != imports.end(); ++i) {
2283 const Extension* imported_module =
2284 GetExtensionById(i->extension_id, true);
2285 if (imported_module && imported_module->from_webstore()) {
2286 scoped_ptr<const ExtensionSet> dependents =
2287 GetDependentExtensions(imported_module);
2288 if (dependents->size() == 0) {
2289 UninstallExtension(i->extension_id, false, NULL);
2290 }
2291 }
2292 }
2293 }
2294 }
2295
2179 void ExtensionService::OnExtensionInstalled( 2296 void ExtensionService::OnExtensionInstalled(
2180 const Extension* extension, 2297 const Extension* extension,
2181 const syncer::StringOrdinal& page_ordinal, 2298 const syncer::StringOrdinal& page_ordinal,
2182 bool has_requirement_errors, 2299 bool has_requirement_errors,
2183 bool wait_for_idle) { 2300 bool wait_for_idle) {
2184 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2301 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2185 2302
2186 const std::string& id = extension->id(); 2303 const std::string& id = extension->id();
2187 bool initial_enable = ShouldEnableOnInstall(extension); 2304 bool initial_enable = ShouldEnableOnInstall(extension);
2188 const extensions::PendingExtensionInfo* pending_extension_info = NULL; 2305 const extensions::PendingExtensionInfo* pending_extension_info = NULL;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2251 } 2368 }
2252 2369
2253 // Certain extension locations are specific enough that we can 2370 // Certain extension locations are specific enough that we can
2254 // auto-acknowledge any extension that came from one of them. 2371 // auto-acknowledge any extension that came from one of them.
2255 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD) 2372 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD)
2256 AcknowledgeExternalExtension(extension->id()); 2373 AcknowledgeExternalExtension(extension->id());
2257 const Extension::State initial_state = 2374 const Extension::State initial_state =
2258 initial_enable ? Extension::ENABLED : Extension::DISABLED; 2375 initial_enable ? Extension::ENABLED : Extension::DISABLED;
2259 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { 2376 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) {
2260 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, 2377 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2261 page_ordinal); 2378 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, page_ordinal);
2262 2379
2263 // Transfer ownership of |extension|. 2380 // Transfer ownership of |extension|.
2264 delayed_updates_for_idle_.Insert(extension); 2381 delayed_installs_.Insert(extension);
2265 2382
2266 // Notify extension of available update. 2383 // Notify extension of available update.
2267 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( 2384 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
2268 profile_, id, extension->manifest()->value()); 2385 profile_, id, extension->manifest()->value());
2269 2386
2270 // Notify observers that app update is available. 2387 // Notify observers that app update is available.
2271 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 2388 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
2272 OnAppUpdateAvailable(extension->id())); 2389 OnAppUpdateAvailable(extension->id()));
2273 return; 2390 return;
2274 } 2391 }
2275 2392
2276 if (installs_delayed()) { 2393 ImportStatus status = CheckImports(extension);
2394 if (installs_delayed_for_gc()) {
2277 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, 2395 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2278 page_ordinal); 2396 extensions::ExtensionPrefs::DELAY_REASON_GC, page_ordinal);
2279 delayed_installs_.Insert(extension); 2397 delayed_installs_.Insert(extension);
2398 } else if (status != IMPORT_STATUS_OK) {
2399 if (status == IMPORT_STATUS_UNSATISFIED) {
2400 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2401 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
2402 page_ordinal);
2403 delayed_installs_.Insert(extension);
2404 }
2280 } else { 2405 } else {
2281 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal); 2406 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal);
2282 } 2407 }
2283 } 2408 }
2284 2409
2285 void ExtensionService::AddNewOrUpdatedExtension( 2410 void ExtensionService::AddNewOrUpdatedExtension(
2286 const Extension* extension, 2411 const Extension* extension,
2287 Extension::State initial_state, 2412 Extension::State initial_state,
2288 const syncer::StringOrdinal& page_ordinal) { 2413 const syncer::StringOrdinal& page_ordinal) {
2289 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2414 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2290 2415
2291 extension_prefs_->OnExtensionInstalled( 2416 extension_prefs_->OnExtensionInstalled(
2292 extension, 2417 extension,
2293 initial_state, 2418 initial_state,
2294 page_ordinal); 2419 page_ordinal);
2295 2420
2296 FinishInstallation(extension); 2421 FinishInstallation(extension);
2297 } 2422 }
2298 2423
2299 void ExtensionService::MaybeFinishDelayedInstallation( 2424 void ExtensionService::MaybeFinishDelayedInstallation(
2300 const std::string& extension_id) { 2425 const std::string& extension_id) {
2301 // Check if the extension already got updated. 2426 // Check if the extension already got installed.
2302 if (!delayed_updates_for_idle_.Contains(extension_id)) 2427 if (!delayed_installs_.Contains(extension_id))
2303 return; 2428 return;
2429 extensions::ExtensionPrefs::DelayReason reason =
2430 extension_prefs_->GetDelayedInstallReason(extension_id);
2431
2304 // Check if the extension is idle. 2432 // Check if the extension is idle.
2305 if (!IsExtensionIdle(extension_id)) 2433 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE &&
2434 !IsExtensionIdle(extension_id))
2306 return; 2435 return;
2307 2436
2437 const Extension* extension = delayed_installs_.GetByID(extension_id);
2438 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) {
2439 ImportStatus status = CheckImports(extension);
2440 if (status != IMPORT_STATUS_OK) {
2441 if (status == IMPORT_STATUS_UNRECOVERABLE) {
2442 delayed_installs_.Remove(extension_id);
2443 // Make sure no version of the extension is actually installed, (i.e.,
2444 // that this delayed install was not an update).
2445 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
2446 extension_prefs_->DeleteExtensionPrefs(extension_id);
2447 }
2448 return;
2449 }
2450 }
2451
2308 FinishDelayedInstallation(extension_id); 2452 FinishDelayedInstallation(extension_id);
2309 } 2453 }
2310 2454
2311 void ExtensionService::FinishDelayedInstallation( 2455 void ExtensionService::FinishDelayedInstallation(
2312 const std::string& extension_id) { 2456 const std::string& extension_id) {
2313 scoped_refptr<const Extension> extension( 2457 scoped_refptr<const Extension> extension(
2314 GetPendingExtensionUpdate(extension_id)); 2458 GetPendingExtensionUpdate(extension_id));
2315 CHECK(extension.get()); 2459 CHECK(extension.get());
2316 delayed_updates_for_idle_.Remove(extension_id); 2460 delayed_installs_.Remove(extension_id);
2317 2461
2318 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) 2462 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id))
2319 NOTREACHED(); 2463 NOTREACHED();
2320 2464
2321 FinishInstallation(extension.get()); 2465 FinishInstallation(extension.get());
2322 } 2466 }
2323 2467
2324 void ExtensionService::FinishInstallation(const Extension* extension) { 2468 void ExtensionService::FinishInstallation(const Extension* extension) {
2325 const extensions::Extension* existing_extension = 2469 const extensions::Extension* existing_extension =
2326 GetInstalledExtension(extension->id()); 2470 GetInstalledExtension(extension->id());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 2507
2364 // If this is a new external extension that was disabled, alert the user 2508 // If this is a new external extension that was disabled, alert the user
2365 // so he can reenable it. We do this last so that it has already been 2509 // so he can reenable it. We do this last so that it has already been
2366 // added to our list of extensions. 2510 // added to our list of extensions.
2367 if (unacknowledged_external) { 2511 if (unacknowledged_external) {
2368 UpdateExternalExtensionAlert(); 2512 UpdateExternalExtensionAlert();
2369 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", 2513 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
2370 EXTERNAL_EXTENSION_INSTALLED, 2514 EXTERNAL_EXTENSION_INSTALLED,
2371 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); 2515 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
2372 } 2516 }
2517
2518 // Check extensions that may have been delayed only because this shared module
2519 // was not available.
2520 if (SharedModuleInfo::IsSharedModule(extension)) {
2521 MaybeFinishDelayedInstallations();
2522 }
2373 } 2523 }
2374 2524
2375 const Extension* ExtensionService::GetPendingExtensionUpdate( 2525 const Extension* ExtensionService::GetPendingExtensionUpdate(
2376 const std::string& id) const { 2526 const std::string& id) const {
2377 return delayed_updates_for_idle_.GetByID(id); 2527 return delayed_installs_.GetByID(id);
2378 } 2528 }
2379 2529
2380 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { 2530 void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
2381 if (!terminated_extensions_.Contains(extension->id())) 2531 if (!terminated_extensions_.Contains(extension->id()))
2382 terminated_extensions_.Insert(make_scoped_refptr(extension)); 2532 terminated_extensions_.Insert(make_scoped_refptr(extension));
2383 2533
2384 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); 2534 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE);
2385 } 2535 }
2386 2536
2387 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { 2537 void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 break; 2755 break;
2606 } 2756 }
2607 case chrome::NOTIFICATION_IMPORT_FINISHED: { 2757 case chrome::NOTIFICATION_IMPORT_FINISHED: {
2608 InitAfterImport(); 2758 InitAfterImport();
2609 break; 2759 break;
2610 } 2760 }
2611 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { 2761 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
2612 extensions::ExtensionHost* host = 2762 extensions::ExtensionHost* host =
2613 content::Details<extensions::ExtensionHost>(details).ptr(); 2763 content::Details<extensions::ExtensionHost>(details).ptr();
2614 std::string extension_id = host->extension_id(); 2764 std::string extension_id = host->extension_id();
2615 if (delayed_updates_for_idle_.Contains(extension_id)) { 2765 if (delayed_installs_.Contains(extension_id)) {
2616 // We were waiting for this extension to become idle, it now might have, 2766 // We were waiting for this extension to become idle, it now might have,
2617 // so maybe finish installation. 2767 // so maybe finish installation.
2618 base::MessageLoop::current()->PostDelayedTask( 2768 base::MessageLoop::current()->PostDelayedTask(
2619 FROM_HERE, 2769 FROM_HERE,
2620 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, 2770 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation,
2621 AsWeakPtr(), extension_id), 2771 AsWeakPtr(), extension_id),
2622 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); 2772 base::TimeDelta::FromSeconds(kUpdateIdleDelay));
2623 } 2773 }
2624 break; 2774 break;
2625 } 2775 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
2791 for (ExtensionSet::const_iterator it = extensions_.begin(); 2941 for (ExtensionSet::const_iterator it = extensions_.begin();
2792 it != extensions_.end(); ++it) { 2942 it != extensions_.end(); ++it) {
2793 if (extensions::AppIsolationInfo::HasIsolatedStorage(*it)) { 2943 if (extensions::AppIsolationInfo::HasIsolatedStorage(*it)) {
2794 active_paths->insert( 2944 active_paths->insert(
2795 BrowserContext::GetStoragePartitionForSite( 2945 BrowserContext::GetStoragePartitionForSite(
2796 profile_, 2946 profile_,
2797 GetSiteForExtensionId((*it)->id()))->GetPath()); 2947 GetSiteForExtensionId((*it)->id()))->GetPath());
2798 } 2948 }
2799 } 2949 }
2800 2950
2801 DCHECK(!installs_delayed()); 2951 DCHECK(!installs_delayed_for_gc());
2802 set_installs_delayed(true); 2952 set_installs_delayed_for_gc(true);
2803 BrowserContext::GarbageCollectStoragePartitions( 2953 BrowserContext::GarbageCollectStoragePartitions(
2804 profile_, active_paths.Pass(), 2954 profile_, active_paths.Pass(),
2805 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, 2955 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished,
2806 AsWeakPtr())); 2956 AsWeakPtr()));
2807 } 2957 }
2808 2958
2809 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { 2959 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() {
2810 set_installs_delayed(false); 2960 set_installs_delayed_for_gc(false);
2961 MaybeFinishDelayedInstallations();
2962 }
2963
2964 void ExtensionService::MaybeFinishDelayedInstallations() {
2965 std::vector<std::string> to_be_installed;
2811 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); 2966 for (ExtensionSet::const_iterator it = delayed_installs_.begin();
2812 it != delayed_installs_.end(); 2967 it != delayed_installs_.end();
2813 ++it) { 2968 ++it) {
2814 FinishDelayedInstallation((*it)->id()); 2969 to_be_installed.push_back((*it)->id());
2815 } 2970 }
2816 for (ExtensionSet::const_iterator it = delayed_updates_for_idle_.begin(); 2971 for (std::vector<std::string>::const_iterator it = to_be_installed.begin();
2817 it != delayed_updates_for_idle_.end(); 2972 it != to_be_installed.end();
2818 ++it) { 2973 ++it) {
2819 MaybeFinishDelayedInstallation((*it)->id()); 2974 MaybeFinishDelayedInstallation(*it);
2820 } 2975 }
2821 delayed_installs_.Clear();
2822 } 2976 }
2823 2977
2824 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() { 2978 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() {
2825 extension_prefs_->SetNeedsStorageGarbageCollection(true); 2979 extension_prefs_->SetNeedsStorageGarbageCollection(true);
2826 } 2980 }
2827 2981
2828 void ExtensionService::OnBlacklistUpdated() { 2982 void ExtensionService::OnBlacklistUpdated() {
2829 blacklist_->GetBlacklistedIDs( 2983 blacklist_->GetBlacklistedIDs(
2830 GenerateInstalledExtensionsSet()->GetIDs(), 2984 GenerateInstalledExtensionsSet()->GetIDs(),
2831 base::Bind(&ExtensionService::ManageBlacklist, 2985 base::Bind(&ExtensionService::ManageBlacklist,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2879 } 3033 }
2880 3034
2881 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { 3035 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) {
2882 update_observers_.AddObserver(observer); 3036 update_observers_.AddObserver(observer);
2883 } 3037 }
2884 3038
2885 void ExtensionService::RemoveUpdateObserver( 3039 void ExtensionService::RemoveUpdateObserver(
2886 extensions::UpdateObserver* observer) { 3040 extensions::UpdateObserver* observer) {
2887 update_observers_.RemoveObserver(observer); 3041 update_observers_.RemoveObserver(observer);
2888 } 3042 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698