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

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: 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 380 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 bool ExtensionService::CheckImports(const Extension* extension,
2212 bool* unrecoverable) {
2213 bool import_failed = false;
2214 // TODO(elijahtaylor): Message the user if there is a failure that is
2215 // unrecoverable.
asargent_no_longer_on_chrome 2013/06/13 05:47:16 Maybe add "CHECK(unrecoverable != NULL);" here?
elijahtaylor1 2013/06/13 23:32:09 removed
2216 *unrecoverable = false;
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 import_failed = true;
2227 if (extension->from_webstore()) {
2228 if (pending_extension_manager()->AddFromExtensionImport(
2229 i->extension_id,
2230 extension_urls::GetWebstoreUpdateUrl(),
2231 IsSharedModule)) {
2232 CheckForUpdatesSoon();
2233 }
2234 } else {
2235 *unrecoverable = true;
2236 }
2237 } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
2238 import_failed = true;
2239 *unrecoverable = true;
2240 } else if (version_required.IsValid() &&
2241 imported_module->version()->CompareTo(version_required) < 0) {
2242 import_failed = true;
2243 if (imported_module->from_webstore()) {
2244 CheckForUpdatesSoon();
2245 } else {
2246 *unrecoverable = true;
2247 }
2248 }
2249 }
2250 }
2251 return !import_failed;
2252 }
2253
2254 scoped_ptr<const ExtensionSet>
2255 ExtensionService::GetSharedModuleImporters(const Extension* extension) {
2256 scoped_ptr<ExtensionSet> importers(new ExtensionSet());
2257 scoped_ptr<ExtensionSet> set_to_check(new ExtensionSet());
2258 if (SharedModuleInfo::IsSharedModule(extension)) {
2259 set_to_check->InsertAll(disabled_extensions_);
2260 set_to_check->InsertAll(delayed_installs_);
2261 set_to_check->InsertAll(extensions_);
2262 for (ExtensionSet::const_iterator iter = set_to_check->begin();
2263 iter != set_to_check->end(); ++iter) {
2264 if (SharedModuleInfo::ImportsExtensionById(*iter, extension->id())) {
2265 importers->Insert(*iter);
2266 }
2267 }
2268 }
2269 return importers.PassAs<const ExtensionSet>();
2270 }
2271
2272 void ExtensionService::PruneSharedModulesOnUninstall(
2273 const Extension* extension) {
2274 if (SharedModuleInfo::ImportsModules(extension)) {
2275 const std::vector<SharedModuleInfo::ImportInfo>& imports =
2276 SharedModuleInfo::GetImports(extension);
2277 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
2278 for (i = imports.begin(); i != imports.end(); ++i) {
2279 const Extension* imported_module =
2280 GetExtensionById(i->extension_id, true);
2281 if (imported_module && imported_module->from_webstore()) {
2282 scoped_ptr<const ExtensionSet> importers =
2283 GetSharedModuleImporters(imported_module);
2284 if (importers->size() == 0) {
2285 UninstallExtension(i->extension_id, false, NULL);
2286 }
2287 }
2288 }
2289 }
2290 }
2291
2179 void ExtensionService::OnExtensionInstalled( 2292 void ExtensionService::OnExtensionInstalled(
2180 const Extension* extension, 2293 const Extension* extension,
2181 const syncer::StringOrdinal& page_ordinal, 2294 const syncer::StringOrdinal& page_ordinal,
2182 bool has_requirement_errors, 2295 bool has_requirement_errors,
2183 bool wait_for_idle) { 2296 bool wait_for_idle) {
2184 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2297 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2185 2298
2186 const std::string& id = extension->id(); 2299 const std::string& id = extension->id();
2187 bool initial_enable = ShouldEnableOnInstall(extension); 2300 bool initial_enable = ShouldEnableOnInstall(extension);
2188 const extensions::PendingExtensionInfo* pending_extension_info = NULL; 2301 const extensions::PendingExtensionInfo* pending_extension_info = NULL;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2251 } 2364 }
2252 2365
2253 // Certain extension locations are specific enough that we can 2366 // Certain extension locations are specific enough that we can
2254 // auto-acknowledge any extension that came from one of them. 2367 // auto-acknowledge any extension that came from one of them.
2255 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD) 2368 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD)
2256 AcknowledgeExternalExtension(extension->id()); 2369 AcknowledgeExternalExtension(extension->id());
2257 const Extension::State initial_state = 2370 const Extension::State initial_state =
2258 initial_enable ? Extension::ENABLED : Extension::DISABLED; 2371 initial_enable ? Extension::ENABLED : Extension::DISABLED;
2259 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { 2372 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) {
2260 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, 2373 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2261 page_ordinal); 2374 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, page_ordinal);
2262 2375
2263 // Transfer ownership of |extension|. 2376 // Transfer ownership of |extension|.
2264 delayed_updates_for_idle_.Insert(extension); 2377 delayed_installs_.Insert(extension);
2265 2378
2266 // Notify extension of available update. 2379 // Notify extension of available update.
2267 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( 2380 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
2268 profile_, id, extension->manifest()->value()); 2381 profile_, id, extension->manifest()->value());
2269 2382
2270 // Notify observers that app update is available. 2383 // Notify observers that app update is available.
2271 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 2384 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
2272 OnAppUpdateAvailable(extension->id())); 2385 OnAppUpdateAvailable(extension->id()));
2273 return; 2386 return;
2274 } 2387 }
2275 2388
2389 bool unrecoverable_import_error;
asargent_no_longer_on_chrome 2013/06/13 05:47:16 consider initializing (otherwise you might get a c
elijahtaylor1 2013/06/13 23:32:09 removed
2276 if (installs_delayed()) { 2390 if (installs_delayed()) {
2277 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, 2391 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2278 page_ordinal); 2392 extensions::ExtensionPrefs::DELAY_REASON_GLOBAL, page_ordinal);
2279 delayed_installs_.Insert(extension); 2393 delayed_installs_.Insert(extension);
2394 } else if (!CheckImports(extension, &unrecoverable_import_error)) {
2395 if (!unrecoverable_import_error) {
2396 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2397 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
2398 page_ordinal);
2399 delayed_installs_.Insert(extension);
2400 }
2280 } else { 2401 } else {
2281 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal); 2402 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal);
2282 } 2403 }
2283 } 2404 }
2284 2405
2285 void ExtensionService::AddNewOrUpdatedExtension( 2406 void ExtensionService::AddNewOrUpdatedExtension(
2286 const Extension* extension, 2407 const Extension* extension,
2287 Extension::State initial_state, 2408 Extension::State initial_state,
2288 const syncer::StringOrdinal& page_ordinal) { 2409 const syncer::StringOrdinal& page_ordinal) {
2289 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2410 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2290 2411
2291 extension_prefs_->OnExtensionInstalled( 2412 extension_prefs_->OnExtensionInstalled(
2292 extension, 2413 extension,
2293 initial_state, 2414 initial_state,
2294 page_ordinal); 2415 page_ordinal);
2295 2416
2296 FinishInstallation(extension); 2417 FinishInstallation(extension);
2297 } 2418 }
2298 2419
2299 void ExtensionService::MaybeFinishDelayedInstallation( 2420 void ExtensionService::MaybeFinishDelayedInstallation(
2300 const std::string& extension_id) { 2421 const std::string& extension_id) {
2301 // Check if the extension already got updated. 2422 // Check if the extension already got installed.
2302 if (!delayed_updates_for_idle_.Contains(extension_id)) 2423 if (!delayed_installs_.Contains(extension_id))
2303 return; 2424 return;
2425 extensions::ExtensionPrefs::DelayReason reason =
2426 extension_prefs_->GetDelayedInstallReason(extension_id);
2427
2304 // Check if the extension is idle. 2428 // Check if the extension is idle.
2305 if (!IsExtensionIdle(extension_id)) 2429 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE &&
2430 !IsExtensionIdle(extension_id))
2306 return; 2431 return;
2307 2432
2433 const Extension* extension = delayed_installs_.GetByID(extension_id);
2434 bool unrecoverable_import_error;
2435 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS &&
2436 !CheckImports(extension, &unrecoverable_import_error)) {
2437 if (unrecoverable_import_error) {
2438 delayed_installs_.Remove(extension_id);
2439 // Make sure no version of the extension is actually installed, (i.e.,
2440 // that this delayed install was not an update).
2441 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
2442 extension_prefs_->DeleteExtensionPrefs(extension_id);
2443 }
2444 return;
2445 }
2446
2308 FinishDelayedInstallation(extension_id); 2447 FinishDelayedInstallation(extension_id);
2309 } 2448 }
2310 2449
2311 void ExtensionService::FinishDelayedInstallation( 2450 void ExtensionService::FinishDelayedInstallation(
2312 const std::string& extension_id) { 2451 const std::string& extension_id) {
2313 scoped_refptr<const Extension> extension( 2452 scoped_refptr<const Extension> extension(
2314 GetPendingExtensionUpdate(extension_id)); 2453 GetPendingExtensionUpdate(extension_id));
2315 CHECK(extension.get()); 2454 CHECK(extension.get());
2316 delayed_updates_for_idle_.Remove(extension_id); 2455 delayed_installs_.Remove(extension_id);
2317 2456
2318 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) 2457 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id))
2319 NOTREACHED(); 2458 NOTREACHED();
2320 2459
2321 FinishInstallation(extension.get()); 2460 FinishInstallation(extension.get());
2322 } 2461 }
2323 2462
2324 void ExtensionService::FinishInstallation(const Extension* extension) { 2463 void ExtensionService::FinishInstallation(const Extension* extension) {
2325 const extensions::Extension* existing_extension = 2464 const extensions::Extension* existing_extension =
2326 GetInstalledExtension(extension->id()); 2465 GetInstalledExtension(extension->id());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 2502
2364 // If this is a new external extension that was disabled, alert the user 2503 // 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 2504 // so he can reenable it. We do this last so that it has already been
2366 // added to our list of extensions. 2505 // added to our list of extensions.
2367 if (unacknowledged_external) { 2506 if (unacknowledged_external) {
2368 UpdateExternalExtensionAlert(); 2507 UpdateExternalExtensionAlert();
2369 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", 2508 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
2370 EXTERNAL_EXTENSION_INSTALLED, 2509 EXTERNAL_EXTENSION_INSTALLED,
2371 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); 2510 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
2372 } 2511 }
2512
2513 // Check extensions that may have been delayed only because this shared module
2514 // was not available.
2515 if (SharedModuleInfo::IsSharedModule(extension)) {
2516 MaybeFinishDelayedInstallations();
2517 }
2373 } 2518 }
2374 2519
2375 const Extension* ExtensionService::GetPendingExtensionUpdate( 2520 const Extension* ExtensionService::GetPendingExtensionUpdate(
2376 const std::string& id) const { 2521 const std::string& id) const {
2377 return delayed_updates_for_idle_.GetByID(id); 2522 return delayed_installs_.GetByID(id);
2378 } 2523 }
2379 2524
2380 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { 2525 void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
2381 if (!terminated_extensions_.Contains(extension->id())) 2526 if (!terminated_extensions_.Contains(extension->id()))
2382 terminated_extensions_.Insert(make_scoped_refptr(extension)); 2527 terminated_extensions_.Insert(make_scoped_refptr(extension));
2383 2528
2384 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); 2529 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE);
2385 } 2530 }
2386 2531
2387 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { 2532 void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 break; 2750 break;
2606 } 2751 }
2607 case chrome::NOTIFICATION_IMPORT_FINISHED: { 2752 case chrome::NOTIFICATION_IMPORT_FINISHED: {
2608 InitAfterImport(); 2753 InitAfterImport();
2609 break; 2754 break;
2610 } 2755 }
2611 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { 2756 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
2612 extensions::ExtensionHost* host = 2757 extensions::ExtensionHost* host =
2613 content::Details<extensions::ExtensionHost>(details).ptr(); 2758 content::Details<extensions::ExtensionHost>(details).ptr();
2614 std::string extension_id = host->extension_id(); 2759 std::string extension_id = host->extension_id();
2615 if (delayed_updates_for_idle_.Contains(extension_id)) { 2760 if (delayed_installs_.Contains(extension_id)) {
2616 // We were waiting for this extension to become idle, it now might have, 2761 // We were waiting for this extension to become idle, it now might have,
2617 // so maybe finish installation. 2762 // so maybe finish installation.
2618 base::MessageLoop::current()->PostDelayedTask( 2763 base::MessageLoop::current()->PostDelayedTask(
2619 FROM_HERE, 2764 FROM_HERE,
2620 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, 2765 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation,
2621 AsWeakPtr(), extension_id), 2766 AsWeakPtr(), extension_id),
2622 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); 2767 base::TimeDelta::FromSeconds(kUpdateIdleDelay));
2623 } 2768 }
2624 break; 2769 break;
2625 } 2770 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
2801 DCHECK(!installs_delayed()); 2946 DCHECK(!installs_delayed());
2802 set_installs_delayed(true); 2947 set_installs_delayed(true);
2803 BrowserContext::GarbageCollectStoragePartitions( 2948 BrowserContext::GarbageCollectStoragePartitions(
2804 profile_, active_paths.Pass(), 2949 profile_, active_paths.Pass(),
2805 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, 2950 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished,
2806 AsWeakPtr())); 2951 AsWeakPtr()));
2807 } 2952 }
2808 2953
2809 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { 2954 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() {
2810 set_installs_delayed(false); 2955 set_installs_delayed(false);
2956 MaybeFinishDelayedInstallations();
2957 }
2958
2959 void ExtensionService::MaybeFinishDelayedInstallations() {
2960 std::vector<std::string> to_be_installed;
2811 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); 2961 for (ExtensionSet::const_iterator it = delayed_installs_.begin();
2812 it != delayed_installs_.end(); 2962 it != delayed_installs_.end();
2813 ++it) { 2963 ++it) {
2814 FinishDelayedInstallation((*it)->id()); 2964 to_be_installed.push_back((*it)->id());
2815 } 2965 }
2816 for (ExtensionSet::const_iterator it = delayed_updates_for_idle_.begin(); 2966 for (std::vector<std::string>::const_iterator it = to_be_installed.begin();
2817 it != delayed_updates_for_idle_.end(); 2967 it != to_be_installed.end();
2818 ++it) { 2968 ++it) {
2819 MaybeFinishDelayedInstallation((*it)->id()); 2969 MaybeFinishDelayedInstallation(*it);
2820 } 2970 }
2821 delayed_installs_.Clear();
2822 } 2971 }
2823 2972
2824 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() { 2973 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() {
2825 extension_prefs_->SetNeedsStorageGarbageCollection(true); 2974 extension_prefs_->SetNeedsStorageGarbageCollection(true);
2826 } 2975 }
2827 2976
2828 void ExtensionService::OnBlacklistUpdated() { 2977 void ExtensionService::OnBlacklistUpdated() {
2829 blacklist_->GetBlacklistedIDs( 2978 blacklist_->GetBlacklistedIDs(
2830 GenerateInstalledExtensionsSet()->GetIDs(), 2979 GenerateInstalledExtensionsSet()->GetIDs(),
2831 base::Bind(&ExtensionService::ManageBlacklist, 2980 base::Bind(&ExtensionService::ManageBlacklist,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2879 } 3028 }
2880 3029
2881 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { 3030 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) {
2882 update_observers_.AddObserver(observer); 3031 update_observers_.AddObserver(observer);
2883 } 3032 }
2884 3033
2885 void ExtensionService::RemoveUpdateObserver( 3034 void ExtensionService::RemoveUpdateObserver(
2886 extensions::UpdateObserver* observer) { 3035 extensions::UpdateObserver* observer) {
2887 update_observers_.RemoveObserver(observer); 3036 update_observers_.RemoveObserver(observer);
2888 } 3037 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698