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 22 matching lines...) Expand all Loading... |
120 using content::DevToolsAgentHost; | 122 using content::DevToolsAgentHost; |
121 using extensions::CrxInstaller; | 123 using extensions::CrxInstaller; |
122 using extensions::Extension; | 124 using extensions::Extension; |
123 using extensions::ExtensionIdSet; | 125 using extensions::ExtensionIdSet; |
124 using extensions::ExtensionInfo; | 126 using extensions::ExtensionInfo; |
125 using extensions::FeatureSwitch; | 127 using extensions::FeatureSwitch; |
126 using extensions::Manifest; | 128 using extensions::Manifest; |
127 using extensions::PermissionMessage; | 129 using extensions::PermissionMessage; |
128 using extensions::PermissionMessages; | 130 using extensions::PermissionMessages; |
129 using extensions::PermissionSet; | 131 using extensions::PermissionSet; |
| 132 using extensions::SharedModuleInfo; |
130 using extensions::UnloadedExtensionInfo; | 133 using extensions::UnloadedExtensionInfo; |
131 | 134 |
132 namespace errors = extension_manifest_errors; | 135 namespace errors = extension_manifest_errors; |
133 | 136 |
134 namespace { | 137 namespace { |
135 | 138 |
136 // Histogram values for logging events related to externally installed | 139 // Histogram values for logging events related to externally installed |
137 // extensions. | 140 // extensions. |
138 enum ExternalExtensionEvent { | 141 enum ExternalExtensionEvent { |
139 EXTERNAL_EXTENSION_INSTALLED = 0, | 142 EXTERNAL_EXTENSION_INSTALLED = 0, |
140 EXTERNAL_EXTENSION_IGNORED, | 143 EXTERNAL_EXTENSION_IGNORED, |
141 EXTERNAL_EXTENSION_REENABLED, | 144 EXTERNAL_EXTENSION_REENABLED, |
142 EXTERNAL_EXTENSION_UNINSTALLED, | 145 EXTERNAL_EXTENSION_UNINSTALLED, |
143 EXTERNAL_EXTENSION_BUCKET_BOUNDARY, | 146 EXTERNAL_EXTENSION_BUCKET_BOUNDARY, |
144 }; | 147 }; |
145 | 148 |
146 // Prompt the user this many times before considering an extension acknowledged. | 149 // Prompt the user this many times before considering an extension acknowledged. |
147 static const int kMaxExtensionAcknowledgePromptCount = 3; | 150 static const int kMaxExtensionAcknowledgePromptCount = 3; |
148 | 151 |
149 // Wait this many seconds after an extensions becomes idle before updating it. | 152 // Wait this many seconds after an extensions becomes idle before updating it. |
150 static const int kUpdateIdleDelay = 5; | 153 static const int kUpdateIdleDelay = 5; |
151 | 154 |
152 // Wait this many seconds before trying to garbage collect extensions again. | 155 // Wait this many seconds before trying to garbage collect extensions again. |
153 static const int kGarbageCollectRetryDelay = 30; | 156 static const int kGarbageCollectRetryDelay = 30; |
154 | 157 |
| 158 static bool IsSharedModule(const Extension* extension) { |
| 159 return SharedModuleInfo::IsSharedModule(extension); |
| 160 } |
| 161 |
155 } // namespace | 162 } // namespace |
156 | 163 |
157 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() | 164 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() |
158 : background_page_ready(false), | 165 : background_page_ready(false), |
159 being_upgraded(false), | 166 being_upgraded(false), |
160 has_used_webrequest(false) { | 167 has_used_webrequest(false) { |
161 } | 168 } |
162 | 169 |
163 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() { | 170 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() { |
164 } | 171 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 install_directory_(install_directory), | 335 install_directory_(install_directory), |
329 extensions_enabled_(extensions_enabled), | 336 extensions_enabled_(extensions_enabled), |
330 show_extensions_prompts_(true), | 337 show_extensions_prompts_(true), |
331 install_updates_when_idle_(true), | 338 install_updates_when_idle_(true), |
332 ready_(ready), | 339 ready_(ready), |
333 toolbar_model_(this), | 340 toolbar_model_(this), |
334 menu_manager_(profile), | 341 menu_manager_(profile), |
335 event_routers_initialized_(false), | 342 event_routers_initialized_(false), |
336 update_once_all_providers_are_ready_(false), | 343 update_once_all_providers_are_ready_(false), |
337 browser_terminating_(false), | 344 browser_terminating_(false), |
338 installs_delayed_(false), | 345 installs_delayed_for_gc_(false), |
339 is_first_run_(false), | 346 is_first_run_(false), |
340 app_sync_bundle_(this), | 347 app_sync_bundle_(this), |
341 extension_sync_bundle_(this) { | 348 extension_sync_bundle_(this) { |
342 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 349 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
343 | 350 |
344 // Figure out if extension installation should be enabled. | 351 // Figure out if extension installation should be enabled. |
345 if (command_line->HasSwitch(switches::kDisableExtensions) || | 352 if (command_line->HasSwitch(switches::kDisableExtensions) || |
346 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { | 353 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { |
347 extensions_enabled_ = false; | 354 extensions_enabled_ = false; |
348 } | 355 } |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
2169 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 2201 for (ExtensionSet::const_iterator iter = extensions_.begin(); |
2170 iter != extensions_.end(); ++iter) { | 2202 iter != extensions_.end(); ++iter) { |
2171 const Extension* extension = *iter; | 2203 const Extension* extension = *iter; |
2172 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) | 2204 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) |
2173 extension_ids.insert(extension->id()); | 2205 extension_ids.insert(extension->id()); |
2174 } | 2206 } |
2175 | 2207 |
2176 child_process_logging::SetActiveExtensions(extension_ids); | 2208 child_process_logging::SetActiveExtensions(extension_ids); |
2177 } | 2209 } |
2178 | 2210 |
| 2211 ExtensionService::ImportStatus ExtensionService::CheckImports( |
| 2212 const Extension* extension) { |
| 2213 ImportStatus status = IMPORT_STATUS_OK; |
| 2214 std::vector<std::string> pending; |
| 2215 // TODO(elijahtaylor): Message the user if there is a failure that is |
| 2216 // unrecoverable. |
| 2217 if (SharedModuleInfo::ImportsModules(extension)) { |
| 2218 const std::vector<SharedModuleInfo::ImportInfo>& imports = |
| 2219 SharedModuleInfo::GetImports(extension); |
| 2220 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; |
| 2221 for (i = imports.begin(); i != imports.end(); ++i) { |
| 2222 Version version_required(i->minimum_version); |
| 2223 const Extension* imported_module = |
| 2224 GetExtensionById(i->extension_id, true); |
| 2225 if (!imported_module) { |
| 2226 if (extension->from_webstore()) { |
| 2227 status = IMPORT_STATUS_UNSATISFIED; |
| 2228 pending.push_back(i->extension_id); |
| 2229 } else { |
| 2230 return IMPORT_STATUS_UNRECOVERABLE; |
| 2231 } |
| 2232 } else if (!SharedModuleInfo::IsSharedModule(imported_module)) { |
| 2233 return IMPORT_STATUS_UNRECOVERABLE; |
| 2234 } else if (version_required.IsValid() && |
| 2235 imported_module->version()->CompareTo(version_required) < 0) { |
| 2236 if (imported_module->from_webstore()) { |
| 2237 status = IMPORT_STATUS_UNSATISFIED; |
| 2238 } else { |
| 2239 return IMPORT_STATUS_UNRECOVERABLE; |
| 2240 } |
| 2241 } |
| 2242 } |
| 2243 } |
| 2244 if (status == IMPORT_STATUS_UNSATISFIED) { |
| 2245 for (std::vector<std::string>::const_iterator iter = pending.begin(); |
| 2246 iter != pending.end(); |
| 2247 ++iter) { |
| 2248 pending_extension_manager()->AddFromExtensionImport( |
| 2249 *iter, |
| 2250 extension_urls::GetWebstoreUpdateUrl(), |
| 2251 IsSharedModule); |
| 2252 } |
| 2253 CheckForUpdatesSoon(); |
| 2254 } |
| 2255 return status; |
| 2256 } |
| 2257 |
| 2258 scoped_ptr<const ExtensionSet> |
| 2259 ExtensionService::GetDependentExtensions(const Extension* extension) { |
| 2260 scoped_ptr<ExtensionSet> dependents(new ExtensionSet()); |
| 2261 scoped_ptr<ExtensionSet> set_to_check(new ExtensionSet()); |
| 2262 if (SharedModuleInfo::IsSharedModule(extension)) { |
| 2263 set_to_check->InsertAll(disabled_extensions_); |
| 2264 set_to_check->InsertAll(delayed_installs_); |
| 2265 set_to_check->InsertAll(extensions_); |
| 2266 for (ExtensionSet::const_iterator iter = set_to_check->begin(); |
| 2267 iter != set_to_check->end(); ++iter) { |
| 2268 if (SharedModuleInfo::ImportsExtensionById(*iter, extension->id())) { |
| 2269 dependents->Insert(*iter); |
| 2270 } |
| 2271 } |
| 2272 } |
| 2273 return dependents.PassAs<const ExtensionSet>(); |
| 2274 } |
| 2275 |
| 2276 void ExtensionService::PruneSharedModulesOnUninstall( |
| 2277 const Extension* extension) { |
| 2278 if (SharedModuleInfo::ImportsModules(extension)) { |
| 2279 const std::vector<SharedModuleInfo::ImportInfo>& imports = |
| 2280 SharedModuleInfo::GetImports(extension); |
| 2281 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; |
| 2282 for (i = imports.begin(); i != imports.end(); ++i) { |
| 2283 const Extension* imported_module = |
| 2284 GetExtensionById(i->extension_id, true); |
| 2285 if (imported_module && imported_module->from_webstore()) { |
| 2286 scoped_ptr<const ExtensionSet> dependents = |
| 2287 GetDependentExtensions(imported_module); |
| 2288 if (dependents->size() == 0) { |
| 2289 UninstallExtension(i->extension_id, false, NULL); |
| 2290 } |
| 2291 } |
| 2292 } |
| 2293 } |
| 2294 } |
| 2295 |
2179 void ExtensionService::OnExtensionInstalled( | 2296 void ExtensionService::OnExtensionInstalled( |
2180 const Extension* extension, | 2297 const Extension* extension, |
2181 const syncer::StringOrdinal& page_ordinal, | 2298 const syncer::StringOrdinal& page_ordinal, |
2182 bool has_requirement_errors, | 2299 bool has_requirement_errors, |
2183 bool wait_for_idle) { | 2300 bool wait_for_idle) { |
2184 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2301 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2185 | 2302 |
2186 const std::string& id = extension->id(); | 2303 const std::string& id = extension->id(); |
2187 bool initial_enable = ShouldEnableOnInstall(extension); | 2304 bool initial_enable = ShouldEnableOnInstall(extension); |
2188 const extensions::PendingExtensionInfo* pending_extension_info = NULL; | 2305 const extensions::PendingExtensionInfo* pending_extension_info = NULL; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 } | 2368 } |
2252 | 2369 |
2253 // Certain extension locations are specific enough that we can | 2370 // Certain extension locations are specific enough that we can |
2254 // auto-acknowledge any extension that came from one of them. | 2371 // auto-acknowledge any extension that came from one of them. |
2255 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD) | 2372 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD) |
2256 AcknowledgeExternalExtension(extension->id()); | 2373 AcknowledgeExternalExtension(extension->id()); |
2257 const Extension::State initial_state = | 2374 const Extension::State initial_state = |
2258 initial_enable ? Extension::ENABLED : Extension::DISABLED; | 2375 initial_enable ? Extension::ENABLED : Extension::DISABLED; |
2259 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { | 2376 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { |
2260 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, | 2377 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, |
2261 page_ordinal); | 2378 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, page_ordinal); |
2262 | 2379 |
2263 // Transfer ownership of |extension|. | 2380 // Transfer ownership of |extension|. |
2264 delayed_updates_for_idle_.Insert(extension); | 2381 delayed_installs_.Insert(extension); |
2265 | 2382 |
2266 // Notify extension of available update. | 2383 // Notify extension of available update. |
2267 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( | 2384 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( |
2268 profile_, id, extension->manifest()->value()); | 2385 profile_, id, extension->manifest()->value()); |
2269 | 2386 |
2270 // Notify observers that app update is available. | 2387 // Notify observers that app update is available. |
2271 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, | 2388 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, |
2272 OnAppUpdateAvailable(extension->id())); | 2389 OnAppUpdateAvailable(extension->id())); |
2273 return; | 2390 return; |
2274 } | 2391 } |
2275 | 2392 |
2276 if (installs_delayed()) { | 2393 ImportStatus status = CheckImports(extension); |
| 2394 if (installs_delayed_for_gc()) { |
2277 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, | 2395 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, |
2278 page_ordinal); | 2396 extensions::ExtensionPrefs::DELAY_REASON_GC, page_ordinal); |
2279 delayed_installs_.Insert(extension); | 2397 delayed_installs_.Insert(extension); |
| 2398 } else if (status != IMPORT_STATUS_OK) { |
| 2399 if (status == IMPORT_STATUS_UNSATISFIED) { |
| 2400 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, |
| 2401 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS, |
| 2402 page_ordinal); |
| 2403 delayed_installs_.Insert(extension); |
| 2404 } |
2280 } else { | 2405 } else { |
2281 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal); | 2406 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal); |
2282 } | 2407 } |
2283 } | 2408 } |
2284 | 2409 |
2285 void ExtensionService::AddNewOrUpdatedExtension( | 2410 void ExtensionService::AddNewOrUpdatedExtension( |
2286 const Extension* extension, | 2411 const Extension* extension, |
2287 Extension::State initial_state, | 2412 Extension::State initial_state, |
2288 const syncer::StringOrdinal& page_ordinal) { | 2413 const syncer::StringOrdinal& page_ordinal) { |
2289 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2414 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2290 | 2415 |
2291 extension_prefs_->OnExtensionInstalled( | 2416 extension_prefs_->OnExtensionInstalled( |
2292 extension, | 2417 extension, |
2293 initial_state, | 2418 initial_state, |
2294 page_ordinal); | 2419 page_ordinal); |
2295 | 2420 |
2296 FinishInstallation(extension); | 2421 FinishInstallation(extension); |
2297 } | 2422 } |
2298 | 2423 |
2299 void ExtensionService::MaybeFinishDelayedInstallation( | 2424 void ExtensionService::MaybeFinishDelayedInstallation( |
2300 const std::string& extension_id) { | 2425 const std::string& extension_id) { |
2301 // Check if the extension already got updated. | 2426 // Check if the extension already got installed. |
2302 if (!delayed_updates_for_idle_.Contains(extension_id)) | 2427 if (!delayed_installs_.Contains(extension_id)) |
2303 return; | 2428 return; |
| 2429 extensions::ExtensionPrefs::DelayReason reason = |
| 2430 extension_prefs_->GetDelayedInstallReason(extension_id); |
| 2431 |
2304 // Check if the extension is idle. | 2432 // Check if the extension is idle. |
2305 if (!IsExtensionIdle(extension_id)) | 2433 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE && |
| 2434 !IsExtensionIdle(extension_id)) |
2306 return; | 2435 return; |
2307 | 2436 |
| 2437 const Extension* extension = delayed_installs_.GetByID(extension_id); |
| 2438 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) { |
| 2439 ImportStatus status = CheckImports(extension); |
| 2440 if (status != IMPORT_STATUS_OK) { |
| 2441 if (status == IMPORT_STATUS_UNRECOVERABLE) { |
| 2442 delayed_installs_.Remove(extension_id); |
| 2443 // Make sure no version of the extension is actually installed, (i.e., |
| 2444 // that this delayed install was not an update). |
| 2445 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get()); |
| 2446 extension_prefs_->DeleteExtensionPrefs(extension_id); |
| 2447 } |
| 2448 return; |
| 2449 } |
| 2450 } |
| 2451 |
2308 FinishDelayedInstallation(extension_id); | 2452 FinishDelayedInstallation(extension_id); |
2309 } | 2453 } |
2310 | 2454 |
2311 void ExtensionService::FinishDelayedInstallation( | 2455 void ExtensionService::FinishDelayedInstallation( |
2312 const std::string& extension_id) { | 2456 const std::string& extension_id) { |
2313 scoped_refptr<const Extension> extension( | 2457 scoped_refptr<const Extension> extension( |
2314 GetPendingExtensionUpdate(extension_id)); | 2458 GetPendingExtensionUpdate(extension_id)); |
2315 CHECK(extension.get()); | 2459 CHECK(extension.get()); |
2316 delayed_updates_for_idle_.Remove(extension_id); | 2460 delayed_installs_.Remove(extension_id); |
2317 | 2461 |
2318 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) | 2462 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) |
2319 NOTREACHED(); | 2463 NOTREACHED(); |
2320 | 2464 |
2321 FinishInstallation(extension.get()); | 2465 FinishInstallation(extension.get()); |
2322 } | 2466 } |
2323 | 2467 |
2324 void ExtensionService::FinishInstallation(const Extension* extension) { | 2468 void ExtensionService::FinishInstallation(const Extension* extension) { |
2325 const extensions::Extension* existing_extension = | 2469 const extensions::Extension* existing_extension = |
2326 GetInstalledExtension(extension->id()); | 2470 GetInstalledExtension(extension->id()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2363 | 2507 |
2364 // If this is a new external extension that was disabled, alert the user | 2508 // If this is a new external extension that was disabled, alert the user |
2365 // so he can reenable it. We do this last so that it has already been | 2509 // so he can reenable it. We do this last so that it has already been |
2366 // added to our list of extensions. | 2510 // added to our list of extensions. |
2367 if (unacknowledged_external) { | 2511 if (unacknowledged_external) { |
2368 UpdateExternalExtensionAlert(); | 2512 UpdateExternalExtensionAlert(); |
2369 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", | 2513 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", |
2370 EXTERNAL_EXTENSION_INSTALLED, | 2514 EXTERNAL_EXTENSION_INSTALLED, |
2371 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); | 2515 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); |
2372 } | 2516 } |
| 2517 |
| 2518 // Check extensions that may have been delayed only because this shared module |
| 2519 // was not available. |
| 2520 if (SharedModuleInfo::IsSharedModule(extension)) { |
| 2521 MaybeFinishDelayedInstallations(); |
| 2522 } |
2373 } | 2523 } |
2374 | 2524 |
2375 const Extension* ExtensionService::GetPendingExtensionUpdate( | 2525 const Extension* ExtensionService::GetPendingExtensionUpdate( |
2376 const std::string& id) const { | 2526 const std::string& id) const { |
2377 return delayed_updates_for_idle_.GetByID(id); | 2527 return delayed_installs_.GetByID(id); |
2378 } | 2528 } |
2379 | 2529 |
2380 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { | 2530 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { |
2381 if (!terminated_extensions_.Contains(extension->id())) | 2531 if (!terminated_extensions_.Contains(extension->id())) |
2382 terminated_extensions_.Insert(make_scoped_refptr(extension)); | 2532 terminated_extensions_.Insert(make_scoped_refptr(extension)); |
2383 | 2533 |
2384 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); | 2534 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); |
2385 } | 2535 } |
2386 | 2536 |
2387 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { | 2537 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2605 break; | 2755 break; |
2606 } | 2756 } |
2607 case chrome::NOTIFICATION_IMPORT_FINISHED: { | 2757 case chrome::NOTIFICATION_IMPORT_FINISHED: { |
2608 InitAfterImport(); | 2758 InitAfterImport(); |
2609 break; | 2759 break; |
2610 } | 2760 } |
2611 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { | 2761 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { |
2612 extensions::ExtensionHost* host = | 2762 extensions::ExtensionHost* host = |
2613 content::Details<extensions::ExtensionHost>(details).ptr(); | 2763 content::Details<extensions::ExtensionHost>(details).ptr(); |
2614 std::string extension_id = host->extension_id(); | 2764 std::string extension_id = host->extension_id(); |
2615 if (delayed_updates_for_idle_.Contains(extension_id)) { | 2765 if (delayed_installs_.Contains(extension_id)) { |
2616 // We were waiting for this extension to become idle, it now might have, | 2766 // We were waiting for this extension to become idle, it now might have, |
2617 // so maybe finish installation. | 2767 // so maybe finish installation. |
2618 base::MessageLoop::current()->PostDelayedTask( | 2768 base::MessageLoop::current()->PostDelayedTask( |
2619 FROM_HERE, | 2769 FROM_HERE, |
2620 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, | 2770 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, |
2621 AsWeakPtr(), extension_id), | 2771 AsWeakPtr(), extension_id), |
2622 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); | 2772 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); |
2623 } | 2773 } |
2624 break; | 2774 break; |
2625 } | 2775 } |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2791 for (ExtensionSet::const_iterator it = extensions_.begin(); | 2941 for (ExtensionSet::const_iterator it = extensions_.begin(); |
2792 it != extensions_.end(); ++it) { | 2942 it != extensions_.end(); ++it) { |
2793 if (extensions::AppIsolationInfo::HasIsolatedStorage(*it)) { | 2943 if (extensions::AppIsolationInfo::HasIsolatedStorage(*it)) { |
2794 active_paths->insert( | 2944 active_paths->insert( |
2795 BrowserContext::GetStoragePartitionForSite( | 2945 BrowserContext::GetStoragePartitionForSite( |
2796 profile_, | 2946 profile_, |
2797 GetSiteForExtensionId((*it)->id()))->GetPath()); | 2947 GetSiteForExtensionId((*it)->id()))->GetPath()); |
2798 } | 2948 } |
2799 } | 2949 } |
2800 | 2950 |
2801 DCHECK(!installs_delayed()); | 2951 DCHECK(!installs_delayed_for_gc()); |
2802 set_installs_delayed(true); | 2952 set_installs_delayed_for_gc(true); |
2803 BrowserContext::GarbageCollectStoragePartitions( | 2953 BrowserContext::GarbageCollectStoragePartitions( |
2804 profile_, active_paths.Pass(), | 2954 profile_, active_paths.Pass(), |
2805 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, | 2955 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, |
2806 AsWeakPtr())); | 2956 AsWeakPtr())); |
2807 } | 2957 } |
2808 | 2958 |
2809 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { | 2959 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { |
2810 set_installs_delayed(false); | 2960 set_installs_delayed_for_gc(false); |
| 2961 MaybeFinishDelayedInstallations(); |
| 2962 } |
| 2963 |
| 2964 void ExtensionService::MaybeFinishDelayedInstallations() { |
| 2965 std::vector<std::string> to_be_installed; |
2811 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); | 2966 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); |
2812 it != delayed_installs_.end(); | 2967 it != delayed_installs_.end(); |
2813 ++it) { | 2968 ++it) { |
2814 FinishDelayedInstallation((*it)->id()); | 2969 to_be_installed.push_back((*it)->id()); |
2815 } | 2970 } |
2816 for (ExtensionSet::const_iterator it = delayed_updates_for_idle_.begin(); | 2971 for (std::vector<std::string>::const_iterator it = to_be_installed.begin(); |
2817 it != delayed_updates_for_idle_.end(); | 2972 it != to_be_installed.end(); |
2818 ++it) { | 2973 ++it) { |
2819 MaybeFinishDelayedInstallation((*it)->id()); | 2974 MaybeFinishDelayedInstallation(*it); |
2820 } | 2975 } |
2821 delayed_installs_.Clear(); | |
2822 } | 2976 } |
2823 | 2977 |
2824 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() { | 2978 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() { |
2825 extension_prefs_->SetNeedsStorageGarbageCollection(true); | 2979 extension_prefs_->SetNeedsStorageGarbageCollection(true); |
2826 } | 2980 } |
2827 | 2981 |
2828 void ExtensionService::OnBlacklistUpdated() { | 2982 void ExtensionService::OnBlacklistUpdated() { |
2829 blacklist_->GetBlacklistedIDs( | 2983 blacklist_->GetBlacklistedIDs( |
2830 GenerateInstalledExtensionsSet()->GetIDs(), | 2984 GenerateInstalledExtensionsSet()->GetIDs(), |
2831 base::Bind(&ExtensionService::ManageBlacklist, | 2985 base::Bind(&ExtensionService::ManageBlacklist, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2879 } | 3033 } |
2880 | 3034 |
2881 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { | 3035 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { |
2882 update_observers_.AddObserver(observer); | 3036 update_observers_.AddObserver(observer); |
2883 } | 3037 } |
2884 | 3038 |
2885 void ExtensionService::RemoveUpdateObserver( | 3039 void ExtensionService::RemoveUpdateObserver( |
2886 extensions::UpdateObserver* observer) { | 3040 extensions::UpdateObserver* observer) { |
2887 update_observers_.RemoveObserver(observer); | 3041 update_observers_.RemoveObserver(observer); |
2888 } | 3042 } |
OLD | NEW |