OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |