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

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: rebased 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 23 matching lines...) Expand all
121 using content::DevToolsAgentHost; 123 using content::DevToolsAgentHost;
122 using extensions::CrxInstaller; 124 using extensions::CrxInstaller;
123 using extensions::Extension; 125 using extensions::Extension;
124 using extensions::ExtensionIdSet; 126 using extensions::ExtensionIdSet;
125 using extensions::ExtensionInfo; 127 using extensions::ExtensionInfo;
126 using extensions::FeatureSwitch; 128 using extensions::FeatureSwitch;
127 using extensions::Manifest; 129 using extensions::Manifest;
128 using extensions::PermissionMessage; 130 using extensions::PermissionMessage;
129 using extensions::PermissionMessages; 131 using extensions::PermissionMessages;
130 using extensions::PermissionSet; 132 using extensions::PermissionSet;
133 using extensions::SharedModuleInfo;
131 using extensions::UnloadedExtensionInfo; 134 using extensions::UnloadedExtensionInfo;
132 135
133 namespace errors = extension_manifest_errors; 136 namespace errors = extension_manifest_errors;
134 137
135 namespace { 138 namespace {
136 139
137 // Histogram values for logging events related to externally installed 140 // Histogram values for logging events related to externally installed
138 // extensions. 141 // extensions.
139 enum ExternalExtensionEvent { 142 enum ExternalExtensionEvent {
140 EXTERNAL_EXTENSION_INSTALLED = 0, 143 EXTERNAL_EXTENSION_INSTALLED = 0,
141 EXTERNAL_EXTENSION_IGNORED, 144 EXTERNAL_EXTENSION_IGNORED,
142 EXTERNAL_EXTENSION_REENABLED, 145 EXTERNAL_EXTENSION_REENABLED,
143 EXTERNAL_EXTENSION_UNINSTALLED, 146 EXTERNAL_EXTENSION_UNINSTALLED,
144 EXTERNAL_EXTENSION_BUCKET_BOUNDARY, 147 EXTERNAL_EXTENSION_BUCKET_BOUNDARY,
145 }; 148 };
146 149
147 // Prompt the user this many times before considering an extension acknowledged. 150 // Prompt the user this many times before considering an extension acknowledged.
148 static const int kMaxExtensionAcknowledgePromptCount = 3; 151 static const int kMaxExtensionAcknowledgePromptCount = 3;
149 152
150 // Wait this many seconds after an extensions becomes idle before updating it. 153 // Wait this many seconds after an extensions becomes idle before updating it.
151 static const int kUpdateIdleDelay = 5; 154 static const int kUpdateIdleDelay = 5;
152 155
153 // Wait this many seconds before trying to garbage collect extensions again. 156 // Wait this many seconds before trying to garbage collect extensions again.
154 static const int kGarbageCollectRetryDelay = 30; 157 static const int kGarbageCollectRetryDelay = 30;
155 158
156 // Wait this many seconds after startup to see if there are any extensions 159 // Wait this many seconds after startup to see if there are any extensions
157 // which can be garbage collected. 160 // which can be garbage collected.
158 static const int kGarbageCollectStartupDelay = 30; 161 static const int kGarbageCollectStartupDelay = 30;
159 162
163 static bool IsSharedModule(const Extension* extension) {
164 return SharedModuleInfo::IsSharedModule(extension);
165 }
166
160 } // namespace 167 } // namespace
161 168
162 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() 169 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData()
163 : background_page_ready(false), 170 : background_page_ready(false),
164 being_upgraded(false), 171 being_upgraded(false),
165 has_used_webrequest(false) { 172 has_used_webrequest(false) {
166 } 173 }
167 174
168 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() { 175 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() {
169 } 176 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 install_directory_(install_directory), 340 install_directory_(install_directory),
334 extensions_enabled_(extensions_enabled), 341 extensions_enabled_(extensions_enabled),
335 show_extensions_prompts_(true), 342 show_extensions_prompts_(true),
336 install_updates_when_idle_(true), 343 install_updates_when_idle_(true),
337 ready_(ready), 344 ready_(ready),
338 toolbar_model_(this), 345 toolbar_model_(this),
339 menu_manager_(profile), 346 menu_manager_(profile),
340 event_routers_initialized_(false), 347 event_routers_initialized_(false),
341 update_once_all_providers_are_ready_(false), 348 update_once_all_providers_are_ready_(false),
342 browser_terminating_(false), 349 browser_terminating_(false),
343 installs_delayed_(false), 350 installs_delayed_for_gc_(false),
344 is_first_run_(false), 351 is_first_run_(false),
345 app_sync_bundle_(this), 352 app_sync_bundle_(this),
346 extension_sync_bundle_(this) { 353 extension_sync_bundle_(this) {
347 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 354 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
348 355
349 // Figure out if extension installation should be enabled. 356 // Figure out if extension installation should be enabled.
350 if (command_line->HasSwitch(switches::kDisableExtensions) || 357 if (command_line->HasSwitch(switches::kDisableExtensions) ||
351 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { 358 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) {
352 extensions_enabled_ = false; 359 extensions_enabled_ = false;
353 } 360 }
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 530
524 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 531 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
525 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) || 532 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) ||
526 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) { 533 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) {
527 // The sole purpose of this launch is to install a new extension from CWS 534 // The sole purpose of this launch is to install a new extension from CWS
528 // and immediately terminate: loading already installed extensions is 535 // and immediately terminate: loading already installed extensions is
529 // unnecessary and may interfere with the inline install dialog (e.g. if an 536 // unnecessary and may interfere with the inline install dialog (e.g. if an
530 // extension listens to onStartup and opens a window). 537 // extension listens to onStartup and opens a window).
531 SetReadyAndNotifyListeners(); 538 SetReadyAndNotifyListeners();
532 } else { 539 } else {
533 // TODO(mek): It might be cleaner to do the FinishDelayedInstallInfo stuff
534 // here instead of in installedloader.
535
536 // LoadAllExtensions() calls OnLoadedInstalledExtensions(). 540 // LoadAllExtensions() calls OnLoadedInstalledExtensions().
537 component_loader_->LoadAll(); 541 component_loader_->LoadAll();
538 extensions::InstalledLoader(this).LoadAllExtensions(); 542 extensions::InstalledLoader(this).LoadAllExtensions();
543
544 // Finish install (if possible) of extensions that were still delayed while
545 // the browser was shut down.
546 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info(
547 extension_prefs_->GetAllDelayedInstallInfo());
548 for (size_t i = 0; i < delayed_info->size(); ++i) {
549 ExtensionInfo* info = delayed_info->at(i).get();
550 scoped_refptr<const Extension> extension(NULL);
551 if (info->extension_manifest) {
552 std::string error;
553 extension = Extension::Create(
554 info->extension_path,
555 info->extension_location,
556 *info->extension_manifest,
557 extension_prefs_->GetDelayedInstallCreationFlags(
558 info->extension_id),
559 info->extension_id,
560 &error);
561 if (extension.get())
562 delayed_installs_.Insert(extension);
563 }
564 }
565 MaybeFinishDelayedInstallations();
566
567 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2(
568 extension_prefs_->GetAllDelayedInstallInfo());
569 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad",
570 delayed_info2->size() - delayed_info->size());
571
539 SetReadyAndNotifyListeners(); 572 SetReadyAndNotifyListeners();
540 573
541 // TODO(erikkay) this should probably be deferred to a future point 574 // TODO(erikkay) this should probably be deferred to a future point
542 // rather than running immediately at startup. 575 // rather than running immediately at startup.
543 CheckForExternalUpdates(); 576 CheckForExternalUpdates();
544 577
545 base::MessageLoop::current()->PostDelayedTask( 578 base::MessageLoop::current()->PostDelayedTask(
546 FROM_HERE, 579 FROM_HERE,
547 base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()), 580 base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()),
548 base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay)); 581 base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay));
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 orphaned_dev_tools_[extension_id] = devtools_cookie; 698 orphaned_dev_tools_[extension_id] = devtools_cookie;
666 } 699 }
667 700
668 path = current_extension->path(); 701 path = current_extension->path();
669 DisableExtension(extension_id, Extension::DISABLE_RELOAD); 702 DisableExtension(extension_id, Extension::DISABLE_RELOAD);
670 reloading_extensions_.insert(extension_id); 703 reloading_extensions_.insert(extension_id);
671 } else { 704 } else {
672 path = unloaded_extension_paths_[extension_id]; 705 path = unloaded_extension_paths_[extension_id];
673 } 706 }
674 707
675 if (delayed_updates_for_idle_.Contains(extension_id)) { 708 if (delayed_installs_.Contains(extension_id)) {
676 FinishDelayedInstallation(extension_id); 709 FinishDelayedInstallation(extension_id);
677 return; 710 return;
678 } 711 }
679 712
680 // If we're reloading a component extension, use the component extension 713 // If we're reloading a component extension, use the component extension
681 // loader's reloader. 714 // loader's reloader.
682 if (component_loader_->Exists(extension_id)) { 715 if (component_loader_->Exists(extension_id)) {
683 component_loader_->Reload(extension_id); 716 component_loader_->Reload(extension_id);
684 return; 717 return;
685 } 718 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 content::Details<const Extension>(extension.get())); 826 content::Details<const Extension>(extension.get()));
794 827
795 if (app_sync_bundle_.HasExtensionId(extension_id) && 828 if (app_sync_bundle_.HasExtensionId(extension_id) &&
796 sync_change.sync_data().GetDataType() == syncer::APPS) { 829 sync_change.sync_data().GetDataType() == syncer::APPS) {
797 app_sync_bundle_.ProcessDeletion(extension_id, sync_change); 830 app_sync_bundle_.ProcessDeletion(extension_id, sync_change);
798 } else if (extension_sync_bundle_.HasExtensionId(extension_id) && 831 } else if (extension_sync_bundle_.HasExtensionId(extension_id) &&
799 sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) { 832 sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) {
800 extension_sync_bundle_.ProcessDeletion(extension_id, sync_change); 833 extension_sync_bundle_.ProcessDeletion(extension_id, sync_change);
801 } 834 }
802 835
803 delayed_updates_for_idle_.Remove(extension_id);
804 delayed_installs_.Remove(extension_id); 836 delayed_installs_.Remove(extension_id);
805 837
838 PruneSharedModulesOnUninstall(extension);
839
806 // Track the uninstallation. 840 // Track the uninstallation.
807 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2); 841 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2);
808 842
809 return true; 843 return true;
810 } 844 }
811 845
812 bool ExtensionService::IsExtensionEnabled( 846 bool ExtensionService::IsExtensionEnabled(
813 const std::string& extension_id) const { 847 const std::string& extension_id) const {
814 if (extensions_.Contains(extension_id) || 848 if (extensions_.Contains(extension_id) ||
815 terminated_extensions_.Contains(extension_id)) { 849 terminated_extensions_.Contains(extension_id)) {
(...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after
2162 for (ExtensionSet::const_iterator iter = extensions_.begin(); 2196 for (ExtensionSet::const_iterator iter = extensions_.begin();
2163 iter != extensions_.end(); ++iter) { 2197 iter != extensions_.end(); ++iter) {
2164 const Extension* extension = iter->get(); 2198 const Extension* extension = iter->get();
2165 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) 2199 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT)
2166 extension_ids.insert(extension->id()); 2200 extension_ids.insert(extension->id());
2167 } 2201 }
2168 2202
2169 child_process_logging::SetActiveExtensions(extension_ids); 2203 child_process_logging::SetActiveExtensions(extension_ids);
2170 } 2204 }
2171 2205
2206 ExtensionService::ImportStatus ExtensionService::SatisfyImports(
2207 const Extension* extension) {
2208 ImportStatus status = IMPORT_STATUS_OK;
2209 std::vector<std::string> pending;
2210 // TODO(elijahtaylor): Message the user if there is a failure that is
2211 // unrecoverable.
2212 if (SharedModuleInfo::ImportsModules(extension)) {
2213 const std::vector<SharedModuleInfo::ImportInfo>& imports =
2214 SharedModuleInfo::GetImports(extension);
2215 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
2216 for (i = imports.begin(); i != imports.end(); ++i) {
2217 Version version_required(i->minimum_version);
2218 const Extension* imported_module =
2219 GetExtensionById(i->extension_id, true);
2220 if (!imported_module) {
2221 if (extension->from_webstore()) {
2222 status = IMPORT_STATUS_UNSATISFIED;
2223 pending.push_back(i->extension_id);
2224 } else {
2225 return IMPORT_STATUS_UNRECOVERABLE;
2226 }
2227 } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
2228 return IMPORT_STATUS_UNRECOVERABLE;
2229 } else if (version_required.IsValid() &&
2230 imported_module->version()->CompareTo(version_required) < 0) {
2231 if (imported_module->from_webstore()) {
2232 status = IMPORT_STATUS_UNSATISFIED;
2233 } else {
2234 return IMPORT_STATUS_UNRECOVERABLE;
2235 }
2236 }
2237 }
2238 }
2239 if (status == IMPORT_STATUS_UNSATISFIED) {
2240 for (std::vector<std::string>::const_iterator iter = pending.begin();
2241 iter != pending.end();
2242 ++iter) {
2243 pending_extension_manager()->AddFromExtensionImport(
2244 *iter,
2245 extension_urls::GetWebstoreUpdateUrl(),
2246 IsSharedModule);
2247 }
2248 CheckForUpdatesSoon();
2249 }
2250 return status;
2251 }
2252
2253 scoped_ptr<const ExtensionSet>
2254 ExtensionService::GetDependentExtensions(const Extension* extension) {
2255 scoped_ptr<ExtensionSet> dependents(new ExtensionSet());
2256 scoped_ptr<ExtensionSet> set_to_check(new ExtensionSet());
2257 if (SharedModuleInfo::IsSharedModule(extension)) {
2258 set_to_check->InsertAll(disabled_extensions_);
2259 set_to_check->InsertAll(delayed_installs_);
2260 set_to_check->InsertAll(extensions_);
2261 for (ExtensionSet::const_iterator iter = set_to_check->begin();
2262 iter != set_to_check->end(); ++iter) {
2263 if (SharedModuleInfo::ImportsExtensionById(*iter, extension->id())) {
2264 dependents->Insert(*iter);
2265 }
2266 }
2267 }
2268 return dependents.PassAs<const ExtensionSet>();
2269 }
2270
2271 void ExtensionService::PruneSharedModulesOnUninstall(
2272 const Extension* extension) {
2273 if (SharedModuleInfo::ImportsModules(extension)) {
2274 const std::vector<SharedModuleInfo::ImportInfo>& imports =
2275 SharedModuleInfo::GetImports(extension);
2276 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
2277 for (i = imports.begin(); i != imports.end(); ++i) {
2278 const Extension* imported_module =
2279 GetExtensionById(i->extension_id, true);
2280 if (imported_module && imported_module->from_webstore()) {
2281 scoped_ptr<const ExtensionSet> dependents =
2282 GetDependentExtensions(imported_module);
2283 if (dependents->size() == 0) {
2284 UninstallExtension(i->extension_id, false, NULL);
2285 }
2286 }
2287 }
2288 }
2289 }
2290
2172 void ExtensionService::OnExtensionInstalled( 2291 void ExtensionService::OnExtensionInstalled(
2173 const Extension* extension, 2292 const Extension* extension,
2174 const syncer::StringOrdinal& page_ordinal, 2293 const syncer::StringOrdinal& page_ordinal,
2175 bool has_requirement_errors, 2294 bool has_requirement_errors,
2176 bool wait_for_idle) { 2295 bool wait_for_idle) {
2177 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2296 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2178 2297
2179 const std::string& id = extension->id(); 2298 const std::string& id = extension->id();
2180 bool initial_enable = ShouldEnableOnInstall(extension); 2299 bool initial_enable = ShouldEnableOnInstall(extension);
2181 const extensions::PendingExtensionInfo* pending_extension_info = NULL; 2300 const extensions::PendingExtensionInfo* pending_extension_info = NULL;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2244 } 2363 }
2245 2364
2246 // Certain extension locations are specific enough that we can 2365 // Certain extension locations are specific enough that we can
2247 // auto-acknowledge any extension that came from one of them. 2366 // auto-acknowledge any extension that came from one of them.
2248 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD) 2367 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD)
2249 AcknowledgeExternalExtension(extension->id()); 2368 AcknowledgeExternalExtension(extension->id());
2250 const Extension::State initial_state = 2369 const Extension::State initial_state =
2251 initial_enable ? Extension::ENABLED : Extension::DISABLED; 2370 initial_enable ? Extension::ENABLED : Extension::DISABLED;
2252 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { 2371 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) {
2253 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, 2372 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2254 page_ordinal); 2373 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, page_ordinal);
2255 2374
2256 // Transfer ownership of |extension|. 2375 // Transfer ownership of |extension|.
2257 delayed_updates_for_idle_.Insert(extension); 2376 delayed_installs_.Insert(extension);
2258 2377
2259 // Notify extension of available update. 2378 // Notify extension of available update.
2260 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( 2379 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
2261 profile_, id, extension->manifest()->value()); 2380 profile_, id, extension->manifest()->value());
2262 2381
2263 // Notify observers that app update is available. 2382 // Notify observers that app update is available.
2264 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 2383 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
2265 OnAppUpdateAvailable(extension->id())); 2384 OnAppUpdateAvailable(extension->id()));
2266 return; 2385 return;
2267 } 2386 }
2268 2387
2269 if (installs_delayed()) { 2388 ImportStatus status = SatisfyImports(extension);
2389 if (installs_delayed_for_gc()) {
2270 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, 2390 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2271 page_ordinal); 2391 extensions::ExtensionPrefs::DELAY_REASON_GC, page_ordinal);
2272 delayed_installs_.Insert(extension); 2392 delayed_installs_.Insert(extension);
2393 } else if (status != IMPORT_STATUS_OK) {
2394 if (status == IMPORT_STATUS_UNSATISFIED) {
2395 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
2396 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
2397 page_ordinal);
2398 delayed_installs_.Insert(extension);
2399 }
2273 } else { 2400 } else {
2274 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal); 2401 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal);
2275 } 2402 }
2276 } 2403 }
2277 2404
2278 void ExtensionService::AddNewOrUpdatedExtension( 2405 void ExtensionService::AddNewOrUpdatedExtension(
2279 const Extension* extension, 2406 const Extension* extension,
2280 Extension::State initial_state, 2407 Extension::State initial_state,
2281 const syncer::StringOrdinal& page_ordinal) { 2408 const syncer::StringOrdinal& page_ordinal) {
2282 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2409 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2283 2410
2284 extension_prefs_->OnExtensionInstalled( 2411 extension_prefs_->OnExtensionInstalled(
2285 extension, 2412 extension,
2286 initial_state, 2413 initial_state,
2287 page_ordinal); 2414 page_ordinal);
2288 2415
2289 FinishInstallation(extension); 2416 FinishInstallation(extension);
2290 } 2417 }
2291 2418
2292 void ExtensionService::MaybeFinishDelayedInstallation( 2419 void ExtensionService::MaybeFinishDelayedInstallation(
2293 const std::string& extension_id) { 2420 const std::string& extension_id) {
2294 // Check if the extension already got updated. 2421 // Check if the extension already got installed.
2295 if (!delayed_updates_for_idle_.Contains(extension_id)) 2422 if (!delayed_installs_.Contains(extension_id))
2296 return; 2423 return;
2297 // Check if the extension is idle. 2424 extensions::ExtensionPrefs::DelayReason reason =
2298 if (!IsExtensionIdle(extension_id)) 2425 extension_prefs_->GetDelayedInstallReason(extension_id);
2426
2427 // Check if the extension is idle. DELAY_REASON_NONE is used for older
2428 // preferences files that will not have set this field but it was previously
2429 // only used for idle updates.
2430 if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE ||
2431 reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) &&
2432 is_ready() && !IsExtensionIdle(extension_id))
2299 return; 2433 return;
2300 2434
2435 const Extension* extension = delayed_installs_.GetByID(extension_id);
2436 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) {
2437 ImportStatus status = SatisfyImports(extension);
2438 if (status != IMPORT_STATUS_OK) {
2439 if (status == IMPORT_STATUS_UNRECOVERABLE) {
2440 delayed_installs_.Remove(extension_id);
2441 // Make sure no version of the extension is actually installed, (i.e.,
2442 // that this delayed install was not an update).
2443 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
2444 extension_prefs_->DeleteExtensionPrefs(extension_id);
2445 }
2446 return;
2447 }
2448 }
2449
2301 FinishDelayedInstallation(extension_id); 2450 FinishDelayedInstallation(extension_id);
2302 } 2451 }
2303 2452
2304 void ExtensionService::FinishDelayedInstallation( 2453 void ExtensionService::FinishDelayedInstallation(
2305 const std::string& extension_id) { 2454 const std::string& extension_id) {
2306 scoped_refptr<const Extension> extension( 2455 scoped_refptr<const Extension> extension(
2307 GetPendingExtensionUpdate(extension_id)); 2456 GetPendingExtensionUpdate(extension_id));
2308 CHECK(extension.get()); 2457 CHECK(extension.get());
2309 delayed_updates_for_idle_.Remove(extension_id); 2458 delayed_installs_.Remove(extension_id);
2310 2459
2311 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) 2460 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id))
2312 NOTREACHED(); 2461 NOTREACHED();
2313 2462
2314 FinishInstallation(extension.get()); 2463 FinishInstallation(extension.get());
2315 } 2464 }
2316 2465
2317 void ExtensionService::FinishInstallation(const Extension* extension) { 2466 void ExtensionService::FinishInstallation(const Extension* extension) {
2318 const extensions::Extension* existing_extension = 2467 const extensions::Extension* existing_extension =
2319 GetInstalledExtension(extension->id()); 2468 GetInstalledExtension(extension->id());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2356 2505
2357 // If this is a new external extension that was disabled, alert the user 2506 // If this is a new external extension that was disabled, alert the user
2358 // so he can reenable it. We do this last so that it has already been 2507 // so he can reenable it. We do this last so that it has already been
2359 // added to our list of extensions. 2508 // added to our list of extensions.
2360 if (unacknowledged_external) { 2509 if (unacknowledged_external) {
2361 UpdateExternalExtensionAlert(); 2510 UpdateExternalExtensionAlert();
2362 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", 2511 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
2363 EXTERNAL_EXTENSION_INSTALLED, 2512 EXTERNAL_EXTENSION_INSTALLED,
2364 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); 2513 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
2365 } 2514 }
2515
2516 // Check extensions that may have been delayed only because this shared module
2517 // was not available.
2518 if (SharedModuleInfo::IsSharedModule(extension)) {
2519 MaybeFinishDelayedInstallations();
2520 }
2366 } 2521 }
2367 2522
2368 const Extension* ExtensionService::GetPendingExtensionUpdate( 2523 const Extension* ExtensionService::GetPendingExtensionUpdate(
2369 const std::string& id) const { 2524 const std::string& id) const {
2370 return delayed_updates_for_idle_.GetByID(id); 2525 return delayed_installs_.GetByID(id);
2371 } 2526 }
2372 2527
2373 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { 2528 void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
2374 if (!terminated_extensions_.Contains(extension->id())) 2529 if (!terminated_extensions_.Contains(extension->id()))
2375 terminated_extensions_.Insert(make_scoped_refptr(extension)); 2530 terminated_extensions_.Insert(make_scoped_refptr(extension));
2376 2531
2377 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); 2532 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE);
2378 } 2533 }
2379 2534
2380 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { 2535 void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2603 BrowserThread::IO, FROM_HERE, 2758 BrowserThread::IO, FROM_HERE,
2604 base::Bind(&ExtensionInfoMap::UnregisterAllExtensionsInProcess, 2759 base::Bind(&ExtensionInfoMap::UnregisterAllExtensionsInProcess,
2605 system_->info_map(), 2760 system_->info_map(),
2606 process->GetID())); 2761 process->GetID()));
2607 break; 2762 break;
2608 } 2763 }
2609 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { 2764 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
2610 extensions::ExtensionHost* host = 2765 extensions::ExtensionHost* host =
2611 content::Details<extensions::ExtensionHost>(details).ptr(); 2766 content::Details<extensions::ExtensionHost>(details).ptr();
2612 std::string extension_id = host->extension_id(); 2767 std::string extension_id = host->extension_id();
2613 if (delayed_updates_for_idle_.Contains(extension_id)) { 2768 if (delayed_installs_.Contains(extension_id)) {
2614 // We were waiting for this extension to become idle, it now might have, 2769 // We were waiting for this extension to become idle, it now might have,
2615 // so maybe finish installation. 2770 // so maybe finish installation.
2616 base::MessageLoop::current()->PostDelayedTask( 2771 base::MessageLoop::current()->PostDelayedTask(
2617 FROM_HERE, 2772 FROM_HERE,
2618 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, 2773 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation,
2619 AsWeakPtr(), extension_id), 2774 AsWeakPtr(), extension_id),
2620 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); 2775 base::TimeDelta::FromSeconds(kUpdateIdleDelay));
2621 } 2776 }
2622 break; 2777 break;
2623 } 2778 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2787 scoped_ptr<base::hash_set<base::FilePath> > active_paths( 2942 scoped_ptr<base::hash_set<base::FilePath> > active_paths(
2788 new base::hash_set<base::FilePath>()); 2943 new base::hash_set<base::FilePath>());
2789 for (ExtensionSet::const_iterator it = extensions_.begin(); 2944 for (ExtensionSet::const_iterator it = extensions_.begin();
2790 it != extensions_.end(); ++it) { 2945 it != extensions_.end(); ++it) {
2791 if (extensions::AppIsolationInfo::HasIsolatedStorage(it->get())) { 2946 if (extensions::AppIsolationInfo::HasIsolatedStorage(it->get())) {
2792 active_paths->insert(BrowserContext::GetStoragePartitionForSite( 2947 active_paths->insert(BrowserContext::GetStoragePartitionForSite(
2793 profile_, GetSiteForExtensionId((*it)->id()))->GetPath()); 2948 profile_, GetSiteForExtensionId((*it)->id()))->GetPath());
2794 } 2949 }
2795 } 2950 }
2796 2951
2797 DCHECK(!installs_delayed()); 2952 DCHECK(!installs_delayed_for_gc());
2798 set_installs_delayed(true); 2953 set_installs_delayed_for_gc(true);
2799 BrowserContext::GarbageCollectStoragePartitions( 2954 BrowserContext::GarbageCollectStoragePartitions(
2800 profile_, active_paths.Pass(), 2955 profile_, active_paths.Pass(),
2801 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, 2956 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished,
2802 AsWeakPtr())); 2957 AsWeakPtr()));
2803 } 2958 }
2804 2959
2805 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { 2960 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() {
2806 set_installs_delayed(false); 2961 set_installs_delayed_for_gc(false);
2962 MaybeFinishDelayedInstallations();
2963 }
2964
2965 void ExtensionService::MaybeFinishDelayedInstallations() {
2966 std::vector<std::string> to_be_installed;
2807 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); 2967 for (ExtensionSet::const_iterator it = delayed_installs_.begin();
2808 it != delayed_installs_.end(); 2968 it != delayed_installs_.end();
2809 ++it) { 2969 ++it) {
2810 FinishDelayedInstallation((*it)->id()); 2970 to_be_installed.push_back((*it)->id());
2811 } 2971 }
2812 for (ExtensionSet::const_iterator it = delayed_updates_for_idle_.begin(); 2972 for (std::vector<std::string>::const_iterator it = to_be_installed.begin();
2813 it != delayed_updates_for_idle_.end(); 2973 it != to_be_installed.end();
2814 ++it) { 2974 ++it) {
2815 MaybeFinishDelayedInstallation((*it)->id()); 2975 MaybeFinishDelayedInstallation(*it);
2816 } 2976 }
2817 delayed_installs_.Clear();
2818 } 2977 }
2819 2978
2820 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() { 2979 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() {
2821 extension_prefs_->SetNeedsStorageGarbageCollection(true); 2980 extension_prefs_->SetNeedsStorageGarbageCollection(true);
2822 } 2981 }
2823 2982
2824 void ExtensionService::OnBlacklistUpdated() { 2983 void ExtensionService::OnBlacklistUpdated() {
2825 blacklist_->GetBlacklistedIDs( 2984 blacklist_->GetBlacklistedIDs(
2826 GenerateInstalledExtensionsSet()->GetIDs(), 2985 GenerateInstalledExtensionsSet()->GetIDs(),
2827 base::Bind(&ExtensionService::ManageBlacklist, 2986 base::Bind(&ExtensionService::ManageBlacklist,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2875 } 3034 }
2876 3035
2877 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { 3036 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) {
2878 update_observers_.AddObserver(observer); 3037 update_observers_.AddObserver(observer);
2879 } 3038 }
2880 3039
2881 void ExtensionService::RemoveUpdateObserver( 3040 void ExtensionService::RemoveUpdateObserver(
2882 extensions::UpdateObserver* observer) { 3041 extensions::UpdateObserver* observer) {
2883 update_observers_.RemoveObserver(observer); 3042 update_observers_.RemoveObserver(observer);
2884 } 3043 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_service.h ('k') | chrome/browser/extensions/extension_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698