| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 #include "chrome/common/extensions/manifest.h" | 98 #include "chrome/common/extensions/manifest.h" |
| 99 #include "chrome/common/pref_names.h" | 99 #include "chrome/common/pref_names.h" |
| 100 #include "chrome/common/url_constants.h" | 100 #include "chrome/common/url_constants.h" |
| 101 #include "content/public/browser/browser_thread.h" | 101 #include "content/public/browser/browser_thread.h" |
| 102 #include "content/public/browser/devtools_agent_host_registry.h" | 102 #include "content/public/browser/devtools_agent_host_registry.h" |
| 103 #include "content/public/browser/devtools_manager.h" | 103 #include "content/public/browser/devtools_manager.h" |
| 104 #include "content/public/browser/notification_service.h" | 104 #include "content/public/browser/notification_service.h" |
| 105 #include "content/public/browser/notification_types.h" | 105 #include "content/public/browser/notification_types.h" |
| 106 #include "content/public/browser/plugin_service.h" | 106 #include "content/public/browser/plugin_service.h" |
| 107 #include "content/public/browser/render_process_host.h" | 107 #include "content/public/browser/render_process_host.h" |
| 108 #include "content/public/browser/site_instance.h" |
| 109 #include "content/public/browser/storage_partition.h" |
| 108 #include "content/public/common/pepper_plugin_info.h" | 110 #include "content/public/common/pepper_plugin_info.h" |
| 109 #include "extensions/common/error_utils.h" | 111 #include "extensions/common/error_utils.h" |
| 110 #include "googleurl/src/gurl.h" | 112 #include "googleurl/src/gurl.h" |
| 111 #include "grit/generated_resources.h" | 113 #include "grit/generated_resources.h" |
| 112 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 114 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 113 #include "sync/api/sync_change.h" | 115 #include "sync/api/sync_change.h" |
| 114 #include "sync/api/sync_error_factory.h" | 116 #include "sync/api/sync_error_factory.h" |
| 115 #include "webkit/database/database_tracker.h" | 117 #include "webkit/database/database_tracker.h" |
| 116 #include "webkit/database/database_util.h" | 118 #include "webkit/database/database_util.h" |
| 117 | 119 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 show_extensions_prompts_(true), | 369 show_extensions_prompts_(true), |
| 368 install_updates_when_idle_(true), | 370 install_updates_when_idle_(true), |
| 369 ready_(false), | 371 ready_(false), |
| 370 toolbar_model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 372 toolbar_model_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 371 menu_manager_(profile), | 373 menu_manager_(profile), |
| 372 app_notification_manager_( | 374 app_notification_manager_( |
| 373 new extensions::AppNotificationManager(profile)), | 375 new extensions::AppNotificationManager(profile)), |
| 374 event_routers_initialized_(false), | 376 event_routers_initialized_(false), |
| 375 update_once_all_providers_are_ready_(false), | 377 update_once_all_providers_are_ready_(false), |
| 376 browser_terminating_(false), | 378 browser_terminating_(false), |
| 379 installs_delayed_(false), |
| 377 wipeout_is_active_(false), | 380 wipeout_is_active_(false), |
| 378 app_sync_bundle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 381 app_sync_bundle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 379 extension_sync_bundle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 382 extension_sync_bundle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 380 app_shortcut_manager_(profile) { | 383 app_shortcut_manager_(profile) { |
| 381 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 384 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 382 | 385 |
| 383 // Figure out if extension installation should be enabled. | 386 // Figure out if extension installation should be enabled. |
| 384 if (command_line->HasSwitch(switches::kDisableExtensions) || | 387 if (command_line->HasSwitch(switches::kDisableExtensions) || |
| 385 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { | 388 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { |
| 386 extensions_enabled_ = false; | 389 extensions_enabled_ = false; |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 int include_mask = INCLUDE_ENABLED; | 585 int include_mask = INCLUDE_ENABLED; |
| 583 if (include_disabled) { | 586 if (include_disabled) { |
| 584 // Include blacklisted extensions here because there are hundreds of | 587 // Include blacklisted extensions here because there are hundreds of |
| 585 // callers of this function, and many might assume that this includes those | 588 // callers of this function, and many might assume that this includes those |
| 586 // that have been disabled due to blacklisting. | 589 // that have been disabled due to blacklisting. |
| 587 include_mask |= INCLUDE_DISABLED | INCLUDE_BLACKLISTED; | 590 include_mask |= INCLUDE_DISABLED | INCLUDE_BLACKLISTED; |
| 588 } | 591 } |
| 589 return GetExtensionById(id, include_mask); | 592 return GetExtensionById(id, include_mask); |
| 590 } | 593 } |
| 591 | 594 |
| 595 GURL ExtensionService::GetSiteForExtensionId(const std::string& extension_id) { |
| 596 return content::SiteInstance::GetSiteForURL( |
| 597 profile_, |
| 598 Extension::GetBaseURLFromExtensionId(extension_id)); |
| 599 } |
| 600 |
| 592 const Extension* ExtensionService::GetExtensionById( | 601 const Extension* ExtensionService::GetExtensionById( |
| 593 const std::string& id, int include_mask) const { | 602 const std::string& id, int include_mask) const { |
| 594 std::string lowercase_id = StringToLowerASCII(id); | 603 std::string lowercase_id = StringToLowerASCII(id); |
| 595 if (include_mask & INCLUDE_ENABLED) { | 604 if (include_mask & INCLUDE_ENABLED) { |
| 596 const Extension* extension = extensions_.GetByID(lowercase_id); | 605 const Extension* extension = extensions_.GetByID(lowercase_id); |
| 597 if (extension) | 606 if (extension) |
| 598 return extension; | 607 return extension; |
| 599 } | 608 } |
| 600 if (include_mask & INCLUDE_DISABLED) { | 609 if (include_mask & INCLUDE_DISABLED) { |
| 601 const Extension* extension = disabled_extensions_.GetByID(lowercase_id); | 610 const Extension* extension = disabled_extensions_.GetByID(lowercase_id); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 614 } | 623 } |
| 615 return NULL; | 624 return NULL; |
| 616 } | 625 } |
| 617 | 626 |
| 618 void ExtensionService::Init() { | 627 void ExtensionService::Init() { |
| 619 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 628 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 620 | 629 |
| 621 DCHECK(!ready_); // Can't redo init. | 630 DCHECK(!ready_); // Can't redo init. |
| 622 DCHECK_EQ(extensions_.size(), 0u); | 631 DCHECK_EQ(extensions_.size(), 0u); |
| 623 | 632 |
| 624 // TODO(mek): It might be cleaner to do the FinishIdleInstallInfo stuff here | 633 // TODO(mek): It might be cleaner to do the FinishDelayedInstallInfo stuff |
| 625 // instead of in installedloader | 634 // here instead of in installedloader. |
| 626 component_loader_->LoadAll(); | 635 component_loader_->LoadAll(); |
| 627 extensions::InstalledLoader(this).LoadAllExtensions(); | 636 extensions::InstalledLoader(this).LoadAllExtensions(); |
| 628 | 637 |
| 629 // The Sideload Wipeout effort takes place during load (see above), so once | 638 // The Sideload Wipeout effort takes place during load (see above), so once |
| 630 // that is done the flag can be set so that we don't have to check again. | 639 // that is done the flag can be set so that we don't have to check again. |
| 631 if (wipeout_is_active_) { | 640 if (wipeout_is_active_) { |
| 632 extension_prefs_->SetSideloadWipeoutDone(); | 641 extension_prefs_->SetSideloadWipeoutDone(); |
| 633 wipeout_is_active_ = false; // Wipeout is only on during load. | 642 wipeout_is_active_ = false; // Wipeout is only on during load. |
| 634 } | 643 } |
| 635 | 644 |
| 636 // If we are running in the import process, don't bother initializing the | 645 // If we are running in the import process, don't bother initializing the |
| 637 // extension service since this can interfere with the main browser process | 646 // extension service since this can interfere with the main browser process |
| 638 // that is already running an extension service for this profile. | 647 // that is already running an extension service for this profile. |
| 639 // TODO(aa): can we start up even less of ExtensionService? | 648 // TODO(aa): can we start up even less of ExtensionService? |
| 640 // http://crbug.com/107636 | 649 // http://crbug.com/107636 |
| 641 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kImport) && | 650 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kImport) && |
| 642 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kImportFromFile)) { | 651 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kImportFromFile)) { |
| 643 if (g_browser_process->profile_manager() && | 652 if (g_browser_process->profile_manager() && |
| 644 g_browser_process->profile_manager()->will_import()) { | 653 g_browser_process->profile_manager()->will_import()) { |
| 645 RegisterForImportFinished(); | 654 RegisterForImportFinished(); |
| 646 } else { | 655 } else { |
| 647 // TODO(erikkay) this should probably be deferred to a future point | 656 // TODO(erikkay) this should probably be deferred to a future point |
| 648 // rather than running immediately at startup. | 657 // rather than running immediately at startup. |
| 649 CheckForExternalUpdates(); | 658 CheckForExternalUpdates(); |
| 650 | 659 |
| 651 // TODO(erikkay) this should probably be deferred as well. | 660 // TODO(erikkay) this should probably be deferred as well. |
| 652 GarbageCollectExtensions(); | 661 GarbageCollectExtensions(); |
| 653 } | 662 } |
| 654 } | 663 } |
| 664 |
| 665 if (extension_prefs_->NeedsStorageGarbageCollection()) { |
| 666 GarbageCollectIsolatedStorage(); |
| 667 extension_prefs_->SetNeedsStorageGarbageCollection(false); |
| 668 } |
| 655 } | 669 } |
| 656 | 670 |
| 657 bool ExtensionService::UpdateExtension(const std::string& id, | 671 bool ExtensionService::UpdateExtension(const std::string& id, |
| 658 const FilePath& extension_path, | 672 const FilePath& extension_path, |
| 659 const GURL& download_url, | 673 const GURL& download_url, |
| 660 CrxInstaller** out_crx_installer) { | 674 CrxInstaller** out_crx_installer) { |
| 661 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 675 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 662 if (browser_terminating_) { | 676 if (browser_terminating_) { |
| 663 LOG(WARNING) << "Skipping UpdateExtension due to browser shutdown"; | 677 LOG(WARNING) << "Skipping UpdateExtension due to browser shutdown"; |
| 664 // Leak the temp file at extension_path. We don't want to add to the disk | 678 // Leak the temp file at extension_path. We don't want to add to the disk |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 | 790 |
| 777 on_load_events_[extension_id] = events; | 791 on_load_events_[extension_id] = events; |
| 778 | 792 |
| 779 path = current_extension->path(); | 793 path = current_extension->path(); |
| 780 DisableExtension(extension_id, Extension::DISABLE_RELOAD); | 794 DisableExtension(extension_id, Extension::DISABLE_RELOAD); |
| 781 disabled_extension_paths_[extension_id] = path; | 795 disabled_extension_paths_[extension_id] = path; |
| 782 } else { | 796 } else { |
| 783 path = unloaded_extension_paths_[extension_id]; | 797 path = unloaded_extension_paths_[extension_id]; |
| 784 } | 798 } |
| 785 | 799 |
| 786 if (pending_extension_updates_.Contains(extension_id)) { | 800 if (delayed_updates_for_idle_.Contains(extension_id)) { |
| 787 FinishDelayedInstallation(extension_id); | 801 FinishDelayedInstallation(extension_id); |
| 788 return; | 802 return; |
| 789 } | 803 } |
| 790 | 804 |
| 791 // If we're reloading a component extension, use the component extension | 805 // If we're reloading a component extension, use the component extension |
| 792 // loader's reloader. | 806 // loader's reloader. |
| 793 if (component_loader_->Exists(extension_id)) { | 807 if (component_loader_->Exists(extension_id)) { |
| 794 component_loader_->Reload(extension_id); | 808 component_loader_->Reload(extension_id); |
| 795 return; | 809 return; |
| 796 } | 810 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 &extension_file_util::UninstallExtension, | 888 &extension_file_util::UninstallExtension, |
| 875 install_directory_, | 889 install_directory_, |
| 876 extension_id))) | 890 extension_id))) |
| 877 NOTREACHED(); | 891 NOTREACHED(); |
| 878 } | 892 } |
| 879 | 893 |
| 880 GURL launch_web_url_origin(extension->launch_web_url()); | 894 GURL launch_web_url_origin(extension->launch_web_url()); |
| 881 launch_web_url_origin = launch_web_url_origin.GetOrigin(); | 895 launch_web_url_origin = launch_web_url_origin.GetOrigin(); |
| 882 bool is_storage_isolated = extension->is_storage_isolated(); | 896 bool is_storage_isolated = extension->is_storage_isolated(); |
| 883 | 897 |
| 884 if (extension->is_hosted_app() && | 898 if (is_storage_isolated) { |
| 885 !profile_->GetExtensionSpecialStoragePolicy()-> | 899 BrowserContext::AsyncObliterateStoragePartition( |
| 886 IsStorageProtected(launch_web_url_origin)) { | 900 profile_, |
| 887 extensions::DataDeleter::StartDeleting( | 901 GetSiteForExtensionId(extension_id), |
| 888 profile_, extension_id, launch_web_url_origin, is_storage_isolated); | 902 base::Bind(&ExtensionService::OnNeedsToGarbageCollectIsolatedStorage, |
| 903 AsWeakPtr())); |
| 904 } else { |
| 905 if (extension->is_hosted_app() && |
| 906 !profile_->GetExtensionSpecialStoragePolicy()-> |
| 907 IsStorageProtected(launch_web_url_origin)) { |
| 908 extensions::DataDeleter::StartDeleting( |
| 909 profile_, extension_id, launch_web_url_origin); |
| 910 } |
| 911 extensions::DataDeleter::StartDeleting(profile_, extension_id, |
| 912 extension->url()); |
| 889 } | 913 } |
| 890 extensions::DataDeleter::StartDeleting( | |
| 891 profile_, extension_id, extension->url(), is_storage_isolated); | |
| 892 | 914 |
| 893 UntrackTerminatedExtension(extension_id); | 915 UntrackTerminatedExtension(extension_id); |
| 894 | 916 |
| 895 // Notify interested parties that we've uninstalled this extension. | 917 // Notify interested parties that we've uninstalled this extension. |
| 896 content::NotificationService::current()->Notify( | 918 content::NotificationService::current()->Notify( |
| 897 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | 919 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
| 898 content::Source<Profile>(profile_), | 920 content::Source<Profile>(profile_), |
| 899 content::Details<const Extension>(extension)); | 921 content::Details<const Extension>(extension)); |
| 900 | 922 |
| 901 if (app_sync_bundle_.HasExtensionId(extension_id) && | 923 if (app_sync_bundle_.HasExtensionId(extension_id) && |
| 902 sync_change.sync_data().GetDataType() == syncer::APPS) { | 924 sync_change.sync_data().GetDataType() == syncer::APPS) { |
| 903 app_sync_bundle_.ProcessDeletion(extension_id, sync_change); | 925 app_sync_bundle_.ProcessDeletion(extension_id, sync_change); |
| 904 } else if (extension_sync_bundle_.HasExtensionId(extension_id) && | 926 } else if (extension_sync_bundle_.HasExtensionId(extension_id) && |
| 905 sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) { | 927 sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) { |
| 906 extension_sync_bundle_.ProcessDeletion(extension_id, sync_change); | 928 extension_sync_bundle_.ProcessDeletion(extension_id, sync_change); |
| 907 } | 929 } |
| 908 | 930 |
| 909 pending_extension_updates_.Remove(extension_id); | 931 delayed_updates_for_idle_.Remove(extension_id); |
| 932 delayed_installs_.Remove(extension_id); |
| 910 | 933 |
| 911 // Track the uninstallation. | 934 // Track the uninstallation. |
| 912 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2); | 935 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2); |
| 913 | 936 |
| 914 return true; | 937 return true; |
| 915 } | 938 } |
| 916 | 939 |
| 917 bool ExtensionService::IsExtensionEnabled( | 940 bool ExtensionService::IsExtensionEnabled( |
| 918 const std::string& extension_id) const { | 941 const std::string& extension_id) const { |
| 919 if (extensions_.Contains(extension_id) || | 942 if (extensions_.Contains(extension_id) || |
| (...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2064 } | 2087 } |
| 2065 | 2088 |
| 2066 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> info( | 2089 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> info( |
| 2067 extension_prefs_->GetInstalledExtensionsInfo()); | 2090 extension_prefs_->GetInstalledExtensionsInfo()); |
| 2068 | 2091 |
| 2069 std::multimap<std::string, FilePath> extension_paths; | 2092 std::multimap<std::string, FilePath> extension_paths; |
| 2070 for (size_t i = 0; i < info->size(); ++i) | 2093 for (size_t i = 0; i < info->size(); ++i) |
| 2071 extension_paths.insert(std::make_pair(info->at(i)->extension_id, | 2094 extension_paths.insert(std::make_pair(info->at(i)->extension_id, |
| 2072 info->at(i)->extension_path)); | 2095 info->at(i)->extension_path)); |
| 2073 | 2096 |
| 2074 info = extension_prefs_->GetAllIdleInstallInfo(); | 2097 info = extension_prefs_->GetAllDelayedInstallInfo(); |
| 2075 for (size_t i = 0; i < info->size(); ++i) | 2098 for (size_t i = 0; i < info->size(); ++i) |
| 2076 extension_paths.insert(std::make_pair(info->at(i)->extension_id, | 2099 extension_paths.insert(std::make_pair(info->at(i)->extension_id, |
| 2077 info->at(i)->extension_path)); | 2100 info->at(i)->extension_path)); |
| 2078 | 2101 |
| 2079 if (!GetFileTaskRunner()->PostTask( | 2102 if (!GetFileTaskRunner()->PostTask( |
| 2080 FROM_HERE, | 2103 FROM_HERE, |
| 2081 base::Bind( | 2104 base::Bind( |
| 2082 &extension_file_util::GarbageCollectExtensions, | 2105 &extension_file_util::GarbageCollectExtensions, |
| 2083 install_directory_, | 2106 install_directory_, |
| 2084 extension_paths))) { | 2107 extension_paths))) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2196 const std::string old_version_string( | 2219 const std::string old_version_string( |
| 2197 extension_prefs_->GetVersionString(extension->id())); | 2220 extension_prefs_->GetVersionString(extension->id())); |
| 2198 const Version old_version(old_version_string); | 2221 const Version old_version(old_version_string); |
| 2199 | 2222 |
| 2200 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) { | 2223 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) { |
| 2201 VLOG(1) << "Component extension " << extension->name() << " (" | 2224 VLOG(1) << "Component extension " << extension->name() << " (" |
| 2202 << extension->id() << ") installing/upgrading from '" | 2225 << extension->id() << ") installing/upgrading from '" |
| 2203 << old_version_string << "' to " << extension->version()->GetString(); | 2226 << old_version_string << "' to " << extension->version()->GetString(); |
| 2204 | 2227 |
| 2205 AddNewOrUpdatedExtension(extension, | 2228 AddNewOrUpdatedExtension(extension, |
| 2206 syncer::StringOrdinal(), | 2229 Extension::ENABLED_COMPONENT, |
| 2207 Extension::ENABLED_COMPONENT); | 2230 syncer::StringOrdinal()); |
| 2208 return; | 2231 return; |
| 2209 } | 2232 } |
| 2210 | 2233 |
| 2211 AddExtension(extension); | 2234 AddExtension(extension); |
| 2212 } | 2235 } |
| 2213 | 2236 |
| 2214 void ExtensionService::InitializePermissions(const Extension* extension) { | 2237 void ExtensionService::InitializePermissions(const Extension* extension) { |
| 2215 // If the extension has used the optional permissions API, it will have a | 2238 // If the extension has used the optional permissions API, it will have a |
| 2216 // custom set of active permissions defined in the extension prefs. Here, | 2239 // custom set of active permissions defined in the extension prefs. Here, |
| 2217 // we update the extension's active permissions based on the prefs. | 2240 // we update the extension's active permissions based on the prefs. |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2456 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateType", | 2479 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateType", |
| 2457 extension->GetType(), 100); | 2480 extension->GetType(), 100); |
| 2458 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateSource", | 2481 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateSource", |
| 2459 extension->location(), Extension::NUM_LOCATIONS); | 2482 extension->location(), Extension::NUM_LOCATIONS); |
| 2460 } | 2483 } |
| 2461 | 2484 |
| 2462 // Certain extension locations are specific enough that we can | 2485 // Certain extension locations are specific enough that we can |
| 2463 // auto-acknowledge any extension that came from one of them. | 2486 // auto-acknowledge any extension that came from one of them. |
| 2464 if (extension->location() == Extension::EXTERNAL_POLICY_DOWNLOAD) | 2487 if (extension->location() == Extension::EXTERNAL_POLICY_DOWNLOAD) |
| 2465 AcknowledgeExternalExtension(extension->id()); | 2488 AcknowledgeExternalExtension(extension->id()); |
| 2466 | 2489 const Extension::State initial_state = |
| 2490 initial_enable ? Extension::ENABLED : Extension::DISABLED; |
| 2467 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { | 2491 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { |
| 2468 extension_prefs_->SetIdleInstallInfo( | 2492 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, |
| 2469 extension, | 2493 page_ordinal); |
| 2470 initial_enable ? Extension::ENABLED : Extension::DISABLED, | |
| 2471 page_ordinal); | |
| 2472 | 2494 |
| 2473 // Transfer ownership of |extension|. | 2495 // Transfer ownership of |extension|. |
| 2474 pending_extension_updates_.Insert(extension); | 2496 delayed_updates_for_idle_.Insert(extension); |
| 2475 | 2497 |
| 2476 // Notify extension of available update. | 2498 // Notify extension of available update. |
| 2477 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( | 2499 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( |
| 2478 profile_, id, extension->manifest()->value()); | 2500 profile_, id, extension->manifest()->value()); |
| 2479 return; | 2501 return; |
| 2480 } | 2502 } |
| 2481 | 2503 |
| 2482 // Transfer ownership of |extension|. | 2504 if (installs_delayed()) { |
| 2483 AddNewOrUpdatedExtension( | 2505 extension_prefs_->SetDelayedInstallInfo(extension, initial_state, |
| 2484 extension, | 2506 page_ordinal); |
| 2485 page_ordinal, | 2507 delayed_installs_.Insert(extension); |
| 2486 initial_enable ? Extension::ENABLED : Extension::DISABLED); | 2508 } else { |
| 2509 AddNewOrUpdatedExtension(extension, initial_state, page_ordinal); |
| 2510 } |
| 2487 } | 2511 } |
| 2488 | 2512 |
| 2489 void ExtensionService::AddNewOrUpdatedExtension( | 2513 void ExtensionService::AddNewOrUpdatedExtension( |
| 2490 const Extension* extension, | 2514 const Extension* extension, |
| 2491 const syncer::StringOrdinal& page_ordinal, | 2515 Extension::State initial_state, |
| 2492 Extension::State initial_state) { | 2516 const syncer::StringOrdinal& page_ordinal) { |
| 2493 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2517 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 2494 | 2518 |
| 2495 extension_prefs_->OnExtensionInstalled( | 2519 extension_prefs_->OnExtensionInstalled( |
| 2496 extension, | 2520 extension, |
| 2497 initial_state, | 2521 initial_state, |
| 2498 page_ordinal); | 2522 page_ordinal); |
| 2499 | 2523 |
| 2500 // Unpacked extensions default to allowing file access, but if that has been | |
| 2501 // overridden, don't reset the value. | |
| 2502 if (Extension::ShouldAlwaysAllowFileAccess(extension->location()) && | |
| 2503 !extension_prefs_->HasAllowFileAccessSetting(extension->id())) { | |
| 2504 extension_prefs_->SetAllowFileAccess(extension->id(), true); | |
| 2505 } | |
| 2506 | |
| 2507 FinishInstallation(extension); | 2524 FinishInstallation(extension); |
| 2508 } | 2525 } |
| 2509 | 2526 |
| 2510 void ExtensionService::MaybeFinishDelayedInstallation( | 2527 void ExtensionService::MaybeFinishDelayedInstallation( |
| 2511 const std::string& extension_id) { | 2528 const std::string& extension_id) { |
| 2512 // Check if the extension already got updated. | 2529 // Check if the extension already got updated. |
| 2513 if (!pending_extension_updates_.Contains(extension_id)) | 2530 if (!delayed_updates_for_idle_.Contains(extension_id)) |
| 2514 return; | 2531 return; |
| 2515 // Check if the extension is idle. | 2532 // Check if the extension is idle. |
| 2516 if (!IsExtensionIdle(extension_id)) | 2533 if (!IsExtensionIdle(extension_id)) |
| 2517 return; | 2534 return; |
| 2518 | 2535 |
| 2519 FinishDelayedInstallation(extension_id); | 2536 FinishDelayedInstallation(extension_id); |
| 2520 } | 2537 } |
| 2521 | 2538 |
| 2522 void ExtensionService::FinishDelayedInstallation( | 2539 void ExtensionService::FinishDelayedInstallation( |
| 2523 const std::string& extension_id) { | 2540 const std::string& extension_id) { |
| 2524 scoped_refptr<const Extension> extension( | 2541 scoped_refptr<const Extension> extension( |
| 2525 GetPendingExtensionUpdate(extension_id)); | 2542 GetPendingExtensionUpdate(extension_id)); |
| 2526 CHECK(extension); | 2543 CHECK(extension); |
| 2527 pending_extension_updates_.Remove(extension_id); | 2544 delayed_updates_for_idle_.Remove(extension_id); |
| 2528 | 2545 |
| 2529 if (!extension_prefs_->FinishIdleInstallInfo(extension_id)) | 2546 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) |
| 2530 NOTREACHED(); | 2547 NOTREACHED(); |
| 2531 | 2548 |
| 2532 FinishInstallation(extension); | 2549 FinishInstallation(extension); |
| 2533 } | 2550 } |
| 2534 | 2551 |
| 2535 void ExtensionService::FinishInstallation(const Extension* extension) { | 2552 void ExtensionService::FinishInstallation(const Extension* extension) { |
| 2536 content::NotificationService::current()->Notify( | 2553 content::NotificationService::current()->Notify( |
| 2537 chrome::NOTIFICATION_EXTENSION_INSTALLED, | 2554 chrome::NOTIFICATION_EXTENSION_INSTALLED, |
| 2538 content::Source<Profile>(profile_), | 2555 content::Source<Profile>(profile_), |
| 2539 content::Details<const Extension>(extension)); | 2556 content::Details<const Extension>(extension)); |
| 2540 | 2557 |
| 2541 bool unacknowledged_external = IsUnacknowledgedExternalExtension(extension); | 2558 bool unacknowledged_external = IsUnacknowledgedExternalExtension(extension); |
| 2542 | 2559 |
| 2560 // Unpacked extensions default to allowing file access, but if that has been |
| 2561 // overridden, don't reset the value. |
| 2562 if (Extension::ShouldAlwaysAllowFileAccess(extension->location()) && |
| 2563 !extension_prefs_->HasAllowFileAccessSetting(extension->id())) { |
| 2564 extension_prefs_->SetAllowFileAccess(extension->id(), true); |
| 2565 } |
| 2566 |
| 2543 AddExtension(extension); | 2567 AddExtension(extension); |
| 2544 | 2568 |
| 2545 #if defined(ENABLE_THEMES) | 2569 #if defined(ENABLE_THEMES) |
| 2546 // We do this here since AddExtension() is always called on browser | 2570 // We do this here since AddExtension() is always called on browser |
| 2547 // startup, and we only really care about the last theme installed. | 2571 // startup, and we only really care about the last theme installed. |
| 2548 // If that ever changes and we have to move this code somewhere | 2572 // If that ever changes and we have to move this code somewhere |
| 2549 // else, it should be somewhere that's not in the startup path. | 2573 // else, it should be somewhere that's not in the startup path. |
| 2550 if (extension->is_theme() && extensions_.GetByID(extension->id())) { | 2574 if (extension->is_theme() && extensions_.GetByID(extension->id())) { |
| 2551 DCHECK_EQ(extensions_.GetByID(extension->id()), extension); | 2575 DCHECK_EQ(extensions_.GetByID(extension->id()), extension); |
| 2552 // Now that the theme extension is visible from outside the | 2576 // Now that the theme extension is visible from outside the |
| 2553 // ExtensionService, notify the ThemeService about the | 2577 // ExtensionService, notify the ThemeService about the |
| 2554 // newly-installed theme. | 2578 // newly-installed theme. |
| 2555 ThemeServiceFactory::GetForProfile(profile_)->SetTheme(extension); | 2579 ThemeServiceFactory::GetForProfile(profile_)->SetTheme(extension); |
| 2556 } | 2580 } |
| 2557 #endif | 2581 #endif |
| 2558 | 2582 |
| 2559 // If this is a new external extension that was disabled, alert the user | 2583 // If this is a new external extension that was disabled, alert the user |
| 2560 // so he can reenable it. We do this last so that it has already been | 2584 // so he can reenable it. We do this last so that it has already been |
| 2561 // added to our list of extensions. | 2585 // added to our list of extensions. |
| 2562 if (unacknowledged_external) { | 2586 if (unacknowledged_external) { |
| 2563 UpdateExternalExtensionAlert(); | 2587 UpdateExternalExtensionAlert(); |
| 2564 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", | 2588 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", |
| 2565 EXTERNAL_EXTENSION_INSTALLED, | 2589 EXTERNAL_EXTENSION_INSTALLED, |
| 2566 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); | 2590 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); |
| 2567 } | 2591 } |
| 2568 } | 2592 } |
| 2569 | 2593 |
| 2570 const Extension* ExtensionService::GetPendingExtensionUpdate( | 2594 const Extension* ExtensionService::GetPendingExtensionUpdate( |
| 2571 const std::string& id) const { | 2595 const std::string& id) const { |
| 2572 return pending_extension_updates_.GetByID(id); | 2596 return delayed_updates_for_idle_.GetByID(id); |
| 2573 } | 2597 } |
| 2574 | 2598 |
| 2575 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { | 2599 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { |
| 2576 if (!terminated_extensions_.Contains(extension->id())) | 2600 if (!terminated_extensions_.Contains(extension->id())) |
| 2577 terminated_extensions_.Insert(make_scoped_refptr(extension)); | 2601 terminated_extensions_.Insert(make_scoped_refptr(extension)); |
| 2578 | 2602 |
| 2579 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); | 2603 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); |
| 2580 } | 2604 } |
| 2581 | 2605 |
| 2582 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { | 2606 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2808 break; | 2832 break; |
| 2809 } | 2833 } |
| 2810 case chrome::NOTIFICATION_IMPORT_FINISHED: { | 2834 case chrome::NOTIFICATION_IMPORT_FINISHED: { |
| 2811 InitAfterImport(); | 2835 InitAfterImport(); |
| 2812 break; | 2836 break; |
| 2813 } | 2837 } |
| 2814 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { | 2838 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { |
| 2815 extensions::ExtensionHost* host = | 2839 extensions::ExtensionHost* host = |
| 2816 content::Details<extensions::ExtensionHost>(details).ptr(); | 2840 content::Details<extensions::ExtensionHost>(details).ptr(); |
| 2817 std::string extension_id = host->extension_id(); | 2841 std::string extension_id = host->extension_id(); |
| 2818 if (pending_extension_updates_.Contains(extension_id)) { | 2842 if (delayed_updates_for_idle_.Contains(extension_id)) { |
| 2819 // We were waiting for this extension to become idle, it now might have, | 2843 // We were waiting for this extension to become idle, it now might have, |
| 2820 // so maybe finish installation. | 2844 // so maybe finish installation. |
| 2821 MessageLoop::current()->PostDelayedTask( | 2845 MessageLoop::current()->PostDelayedTask( |
| 2822 FROM_HERE, | 2846 FROM_HERE, |
| 2823 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, | 2847 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, |
| 2824 AsWeakPtr(), extension_id), | 2848 AsWeakPtr(), extension_id), |
| 2825 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); | 2849 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); |
| 2826 } | 2850 } |
| 2827 break; | 2851 break; |
| 2828 } | 2852 } |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3096 // Delay installation if the extension listens for the onUpdateAvailable | 3120 // Delay installation if the extension listens for the onUpdateAvailable |
| 3097 // event. | 3121 // event. |
| 3098 return system_->event_router()->ExtensionHasEventListener( | 3122 return system_->event_router()->ExtensionHasEventListener( |
| 3099 extension_id, kOnUpdateAvailableEvent); | 3123 extension_id, kOnUpdateAvailableEvent); |
| 3100 } else { | 3124 } else { |
| 3101 // Delay installation if the extension is not idle. | 3125 // Delay installation if the extension is not idle. |
| 3102 return !IsExtensionIdle(extension_id); | 3126 return !IsExtensionIdle(extension_id); |
| 3103 } | 3127 } |
| 3104 } | 3128 } |
| 3105 | 3129 |
| 3130 void ExtensionService::GarbageCollectIsolatedStorage() { |
| 3131 scoped_ptr<base::hash_set<FilePath> > active_paths( |
| 3132 new base::hash_set<FilePath>()); |
| 3133 for (ExtensionSet::const_iterator it = extensions_.begin(); |
| 3134 it != extensions_.end(); ++it) { |
| 3135 if ((*it)->is_storage_isolated()) { |
| 3136 active_paths->insert( |
| 3137 BrowserContext::GetStoragePartitionForSite( |
| 3138 profile_, |
| 3139 GetSiteForExtensionId((*it)->id()))->GetPath()); |
| 3140 } |
| 3141 } |
| 3142 |
| 3143 DCHECK(!installs_delayed()); |
| 3144 set_installs_delayed(true); |
| 3145 BrowserContext::GarbageCollectStoragePartitions( |
| 3146 profile_, active_paths.Pass(), |
| 3147 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, |
| 3148 AsWeakPtr())); |
| 3149 } |
| 3150 |
| 3151 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { |
| 3152 set_installs_delayed(false); |
| 3153 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); |
| 3154 it != delayed_installs_.end(); |
| 3155 ++it) { |
| 3156 FinishDelayedInstallation((*it)->id()); |
| 3157 } |
| 3158 for (ExtensionSet::const_iterator it = delayed_updates_for_idle_.begin(); |
| 3159 it != delayed_updates_for_idle_.end(); |
| 3160 ++it) { |
| 3161 MaybeFinishDelayedInstallation((*it)->id()); |
| 3162 } |
| 3163 delayed_installs_.Clear(); |
| 3164 } |
| 3165 |
| 3166 void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() { |
| 3167 extension_prefs_->SetNeedsStorageGarbageCollection(true); |
| 3168 } |
| 3169 |
| 3106 void ExtensionService::OnBlacklistUpdated() { | 3170 void ExtensionService::OnBlacklistUpdated() { |
| 3107 blacklist_->GetBlacklistedIDs( | 3171 blacklist_->GetBlacklistedIDs( |
| 3108 GenerateInstalledExtensionsSet()->GetIDs(), | 3172 GenerateInstalledExtensionsSet()->GetIDs(), |
| 3109 base::Bind(&ExtensionService::ManageBlacklist, | 3173 base::Bind(&ExtensionService::ManageBlacklist, |
| 3110 AsWeakPtr(), | 3174 AsWeakPtr(), |
| 3111 blacklisted_extensions_.GetIDs())); | 3175 blacklisted_extensions_.GetIDs())); |
| 3112 } | 3176 } |
| 3113 | 3177 |
| 3114 void ExtensionService::ManageBlacklist( | 3178 void ExtensionService::ManageBlacklist( |
| 3115 const std::set<std::string>& old_blacklisted_ids, | 3179 const std::set<std::string>& old_blacklisted_ids, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3143 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); | 3207 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); |
| 3144 DCHECK(extension); | 3208 DCHECK(extension); |
| 3145 if (!extension) | 3209 if (!extension) |
| 3146 continue; | 3210 continue; |
| 3147 blacklisted_extensions_.Insert(extension); | 3211 blacklisted_extensions_.Insert(extension); |
| 3148 UnloadExtension(*it, extension_misc::UNLOAD_REASON_BLACKLIST); | 3212 UnloadExtension(*it, extension_misc::UNLOAD_REASON_BLACKLIST); |
| 3149 } | 3213 } |
| 3150 | 3214 |
| 3151 IdentifyAlertableExtensions(); | 3215 IdentifyAlertableExtensions(); |
| 3152 } | 3216 } |
| OLD | NEW |