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

Side by Side Diff: chrome/browser/extensions/extension_service.cc

Issue 1890163004: extensions: Abstract out install delay strategy (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: for comments in #4 Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_service.h" 5 #include "chrome/browser/extensions/extension_service.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <iterator> 10 #include <iterator>
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 #include "chrome/common/url_constants.h" 63 #include "chrome/common/url_constants.h"
64 #include "components/content_settings/core/browser/host_content_settings_map.h" 64 #include "components/content_settings/core/browser/host_content_settings_map.h"
65 #include "components/crx_file/id_util.h" 65 #include "components/crx_file/id_util.h"
66 #include "content/public/browser/devtools_agent_host.h" 66 #include "content/public/browser/devtools_agent_host.h"
67 #include "content/public/browser/notification_service.h" 67 #include "content/public/browser/notification_service.h"
68 #include "content/public/browser/render_process_host.h" 68 #include "content/public/browser/render_process_host.h"
69 #include "content/public/browser/storage_partition.h" 69 #include "content/public/browser/storage_partition.h"
70 #include "extensions/browser/app_sorting.h" 70 #include "extensions/browser/app_sorting.h"
71 #include "extensions/browser/event_router.h" 71 #include "extensions/browser/event_router.h"
72 #include "extensions/browser/extension_host.h" 72 #include "extensions/browser/extension_host.h"
73 #include "extensions/browser/extension_prefs.h"
74 #include "extensions/browser/extension_registry.h" 73 #include "extensions/browser/extension_registry.h"
75 #include "extensions/browser/extension_system.h" 74 #include "extensions/browser/extension_system.h"
76 #include "extensions/browser/extensions_browser_client.h" 75 #include "extensions/browser/extensions_browser_client.h"
77 #include "extensions/browser/external_install_info.h" 76 #include "extensions/browser/external_install_info.h"
78 #include "extensions/browser/install_flag.h" 77 #include "extensions/browser/install_flag.h"
79 #include "extensions/browser/runtime_data.h" 78 #include "extensions/browser/runtime_data.h"
80 #include "extensions/browser/uninstall_reason.h" 79 #include "extensions/browser/uninstall_reason.h"
81 #include "extensions/browser/update_observer.h" 80 #include "extensions/browser/update_observer.h"
82 #include "extensions/browser/updater/extension_cache.h" 81 #include "extensions/browser/updater/extension_cache.h"
83 #include "extensions/browser/updater/extension_downloader.h" 82 #include "extensions/browser/updater/extension_downloader.h"
(...skipping 1679 matching lines...) Expand 10 before | Expand all | Expand 10 after
1763 } 1762 }
1764 1763
1765 const Extension::State initial_state = 1764 const Extension::State initial_state =
1766 disable_reasons == Extension::DISABLE_NONE ? Extension::ENABLED 1765 disable_reasons == Extension::DISABLE_NONE ? Extension::ENABLED
1767 : Extension::DISABLED; 1766 : Extension::DISABLED;
1768 if (initial_state == Extension::ENABLED) 1767 if (initial_state == Extension::ENABLED)
1769 extension_prefs_->SetExtensionEnabled(id); 1768 extension_prefs_->SetExtensionEnabled(id);
1770 else 1769 else
1771 extension_prefs_->SetExtensionDisabled(id, disable_reasons); 1770 extension_prefs_->SetExtensionDisabled(id, disable_reasons);
1772 1771
1773 if (ShouldDelayExtensionUpdate( 1772 extensions::ExtensionPrefs::DelayReason delay_reason;
1774 id, 1773 extensions::InstallGate::Action action = ShouldDelayExtensionInstall(
1775 !!(install_flags & extensions::kInstallFlagInstallImmediately))) { 1774 extension, !!(install_flags & extensions::kInstallFlagInstallImmediately),
1776 extension_prefs_->SetDelayedInstallInfo( 1775 &delay_reason);
1777 extension, 1776 switch (action) {
1778 initial_state, 1777 case extensions::InstallGate::INSTALL:
1779 install_flags, 1778 AddNewOrUpdatedExtension(extension, initial_state, install_flags,
1780 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, 1779 page_ordinal, install_parameter);
1781 page_ordinal, 1780 return;
1782 install_parameter); 1781 case extensions::InstallGate::DELAY:
1782 extension_prefs_->SetDelayedInstallInfo(extension, initial_state,
1783 install_flags, delay_reason,
1784 page_ordinal, install_parameter);
1783 1785
1784 // Transfer ownership of |extension|. 1786 // Transfer ownership of |extension|.
1785 delayed_installs_.Insert(extension); 1787 delayed_installs_.Insert(extension);
1786 1788
1787 // Notify observers that app update is available. 1789 if (delay_reason ==
1788 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 1790 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE) {
1789 OnAppUpdateAvailable(extension)); 1791 // Notify observers that app update is available.
1790 return; 1792 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
1793 OnAppUpdateAvailable(extension));
1794 }
1795 return;
1796 case extensions::InstallGate::ABORT:
1797 // Do nothing to abort the install. One such case is the shared module
1798 // service gets IMPORT_STATUS_UNRECOVERABLE status for the pending
1799 // install.
1800 return;
1791 } 1801 }
1792 1802
1793 extensions::SharedModuleService::ImportStatus status = 1803 NOTREACHED() << "Unknown action for delayed install: " << action;
1794 shared_module_service_->SatisfyImports(extension);
1795 if (installs_delayed_for_gc_) {
1796 extension_prefs_->SetDelayedInstallInfo(
1797 extension,
1798 initial_state,
1799 install_flags,
1800 extensions::ExtensionPrefs::DELAY_REASON_GC,
1801 page_ordinal,
1802 install_parameter);
1803 delayed_installs_.Insert(extension);
1804 } else if (status != SharedModuleService::IMPORT_STATUS_OK) {
1805 if (status == SharedModuleService::IMPORT_STATUS_UNSATISFIED) {
1806 extension_prefs_->SetDelayedInstallInfo(
1807 extension,
1808 initial_state,
1809 install_flags,
1810 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
1811 page_ordinal,
1812 install_parameter);
1813 delayed_installs_.Insert(extension);
1814 }
1815 } else {
1816 AddNewOrUpdatedExtension(extension,
1817 initial_state,
1818 install_flags,
1819 page_ordinal,
1820 install_parameter);
1821 }
1822 } 1804 }
1823 1805
1824 void ExtensionService::OnExtensionManagementSettingsChanged() { 1806 void ExtensionService::OnExtensionManagementSettingsChanged() {
1825 error_controller_->ShowErrorIfNeeded(); 1807 error_controller_->ShowErrorIfNeeded();
1826 1808
1827 // Revokes blocked permissions from active_permissions for all extensions. 1809 // Revokes blocked permissions from active_permissions for all extensions.
1828 extensions::ExtensionManagement* settings = 1810 extensions::ExtensionManagement* settings =
1829 extensions::ExtensionManagementFactory::GetForBrowserContext(profile()); 1811 extensions::ExtensionManagementFactory::GetForBrowserContext(profile());
1830 CHECK(settings); 1812 CHECK(settings);
1831 std::unique_ptr<ExtensionSet> all_extensions( 1813 std::unique_ptr<ExtensionSet> all_extensions(
(...skipping 30 matching lines...) Expand all
1862 AsWeakPtr(), base::RetainedRef(extension))); 1844 AsWeakPtr(), base::RetainedRef(extension)));
1863 return; 1845 return;
1864 } 1846 }
1865 1847
1866 FinishInstallation(extension); 1848 FinishInstallation(extension);
1867 } 1849 }
1868 1850
1869 void ExtensionService::MaybeFinishDelayedInstallation( 1851 void ExtensionService::MaybeFinishDelayedInstallation(
1870 const std::string& extension_id) { 1852 const std::string& extension_id) {
1871 // Check if the extension already got installed. 1853 // Check if the extension already got installed.
1872 if (!delayed_installs_.Contains(extension_id)) 1854 const Extension* extension = delayed_installs_.GetByID(extension_id);
1873 return; 1855 if (!extension)
1874 extensions::ExtensionPrefs::DelayReason reason =
1875 extension_prefs_->GetDelayedInstallReason(extension_id);
1876
1877 // Check if the extension is idle. DELAY_REASON_NONE is used for older
1878 // preferences files that will not have set this field but it was previously
1879 // only used for idle updates.
1880 if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE ||
1881 reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) &&
1882 is_ready() && !extensions::util::IsExtensionIdle(extension_id, profile_))
1883 return; 1856 return;
1884 1857
1885 const Extension* extension = delayed_installs_.GetByID(extension_id); 1858 extensions::ExtensionPrefs::DelayReason reason;
1886 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) { 1859 const extensions::InstallGate::Action action = ShouldDelayExtensionInstall(
1887 extensions::SharedModuleService::ImportStatus status = 1860 extension, false /* install_immediately*/, &reason);
1888 shared_module_service_->SatisfyImports(extension); 1861 switch (action) {
1889 if (status != SharedModuleService::IMPORT_STATUS_OK) { 1862 case extensions::InstallGate::INSTALL:
1890 if (status == SharedModuleService::IMPORT_STATUS_UNRECOVERABLE) { 1863 break;
1891 delayed_installs_.Remove(extension_id); 1864 case extensions::InstallGate::DELAY:
1892 // Make sure no version of the extension is actually installed, (i.e., 1865 // Bail out and continue to delay the install.
1893 // that this delayed install was not an update).
1894 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
1895 extension_prefs_->DeleteExtensionPrefs(extension_id);
1896 }
1897 return; 1866 return;
1898 } 1867 case extensions::InstallGate::ABORT:
1868 delayed_installs_.Remove(extension_id);
1869 // Make sure no version of the extension is actually installed, (i.e.,
1870 // that this delayed install was not an update).
1871 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
1872 extension_prefs_->DeleteExtensionPrefs(extension_id);
1873 return;
1899 } 1874 }
1900 1875
1901 FinishDelayedInstallation(extension_id); 1876 FinishDelayedInstallation(extension_id);
1902 } 1877 }
1903 1878
1904 void ExtensionService::FinishDelayedInstallation( 1879 void ExtensionService::FinishDelayedInstallation(
1905 const std::string& extension_id) { 1880 const std::string& extension_id) {
1906 scoped_refptr<const Extension> extension( 1881 scoped_refptr<const Extension> extension(
1907 GetPendingExtensionUpdate(extension_id)); 1882 GetPendingExtensionUpdate(extension_id));
1908 CHECK(extension.get()); 1883 CHECK(extension.get());
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2239 } 2214 }
2240 2215
2241 // Helper method to determine if an extension can be blocked. 2216 // Helper method to determine if an extension can be blocked.
2242 bool ExtensionService::CanBlockExtension(const Extension* extension) const { 2217 bool ExtensionService::CanBlockExtension(const Extension* extension) const {
2243 DCHECK(extension); 2218 DCHECK(extension);
2244 return extension->location() != Manifest::COMPONENT && 2219 return extension->location() != Manifest::COMPONENT &&
2245 extension->location() != Manifest::EXTERNAL_COMPONENT && 2220 extension->location() != Manifest::EXTERNAL_COMPONENT &&
2246 !system_->management_policy()->MustRemainEnabled(extension, nullptr); 2221 !system_->management_policy()->MustRemainEnabled(extension, nullptr);
2247 } 2222 }
2248 2223
2249 bool ExtensionService::ShouldDelayExtensionUpdate( 2224 extensions::InstallGate::Action ExtensionService::ShouldDelayExtensionInstall(
2250 const std::string& extension_id, 2225 const extensions::Extension* extension,
2251 bool install_immediately) const { 2226 bool install_immediately,
2252 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable"; 2227 extensions::ExtensionPrefs::DelayReason* reason) const {
2228 for (const auto& entry : install_delayer_registry_) {
2229 extensions::InstallGate* const delayer = entry.second;
2230 extensions::InstallGate::Action action =
2231 delayer->ShouldDelay(extension, install_immediately);
2232 if (action != extensions::InstallGate::INSTALL) {
2233 *reason = entry.first;
2234 return action;
2235 }
2236 }
2253 2237
2254 // If delayed updates are globally disabled, or just for this extension, 2238 return extensions::InstallGate::INSTALL;
2255 // don't delay.
2256 if (!install_updates_when_idle_ || install_immediately)
2257 return false;
2258
2259 const Extension* old = GetInstalledExtension(extension_id);
2260 // If there is no old extension, this is not an update, so don't delay.
2261 if (!old)
2262 return false;
2263
2264 if (extensions::BackgroundInfo::HasPersistentBackgroundPage(old)) {
2265 // Delay installation if the extension listens for the onUpdateAvailable
2266 // event.
2267 return extensions::EventRouter::Get(profile_)
2268 ->ExtensionHasEventListener(extension_id, kOnUpdateAvailableEvent);
2269 } else {
2270 // Delay installation if the extension is not idle.
2271 return !extensions::util::IsExtensionIdle(extension_id, profile_);
2272 }
2273 }
2274
2275 void ExtensionService::OnGarbageCollectIsolatedStorageStart() {
2276 DCHECK(!installs_delayed_for_gc_);
2277 installs_delayed_for_gc_ = true;
2278 }
2279
2280 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() {
2281 DCHECK(installs_delayed_for_gc_);
2282 installs_delayed_for_gc_ = false;
2283 MaybeFinishDelayedInstallations();
2284 } 2239 }
2285 2240
2286 void ExtensionService::MaybeFinishDelayedInstallations() { 2241 void ExtensionService::MaybeFinishDelayedInstallations() {
2287 std::vector<std::string> to_be_installed; 2242 std::vector<std::string> to_be_installed;
2288 for (const auto& extension : delayed_installs_) { 2243 for (const auto& extension : delayed_installs_) {
2289 to_be_installed.push_back(extension->id()); 2244 to_be_installed.push_back(extension->id());
2290 } 2245 }
2291 for (const auto& extension_id : to_be_installed) { 2246 for (const auto& extension_id : to_be_installed) {
2292 MaybeFinishDelayedInstallation(extension_id); 2247 MaybeFinishDelayedInstallation(extension_id);
2293 } 2248 }
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 2386
2432 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { 2387 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) {
2433 update_observers_.AddObserver(observer); 2388 update_observers_.AddObserver(observer);
2434 } 2389 }
2435 2390
2436 void ExtensionService::RemoveUpdateObserver( 2391 void ExtensionService::RemoveUpdateObserver(
2437 extensions::UpdateObserver* observer) { 2392 extensions::UpdateObserver* observer) {
2438 update_observers_.RemoveObserver(observer); 2393 update_observers_.RemoveObserver(observer);
2439 } 2394 }
2440 2395
2396 void ExtensionService::RegisterInstallGate(
2397 extensions::ExtensionPrefs::DelayReason reason,
2398 extensions::InstallGate* install_delayer) {
2399 DCHECK(install_delayer_registry_.end() ==
2400 install_delayer_registry_.find(reason));
2401 install_delayer_registry_[reason] = install_delayer;
2402 }
2403
2404 void ExtensionService::UnregisterInstallGate(
2405 extensions::InstallGate* install_delayer) {
2406 for (auto it = install_delayer_registry_.begin();
2407 it != install_delayer_registry_.end(); ++it) {
2408 if (it->second == install_delayer) {
2409 install_delayer_registry_.erase(it);
2410 return;
2411 }
2412 }
2413 }
2414
2441 // Used only by test code. 2415 // Used only by test code.
2442 void ExtensionService::UnloadAllExtensionsInternal() { 2416 void ExtensionService::UnloadAllExtensionsInternal() {
2443 profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions(); 2417 profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions();
2444 2418
2445 registry_->ClearAll(); 2419 registry_->ClearAll();
2446 system_->runtime_data()->ClearAll(); 2420 system_->runtime_data()->ClearAll();
2447 2421
2448 // TODO(erikkay) should there be a notification for this? We can't use 2422 // TODO(erikkay) should there be a notification for this? We can't use
2449 // EXTENSION_UNLOADED since that implies that the extension has been disabled 2423 // EXTENSION_UNLOADED since that implies that the extension has been disabled
2450 // or uninstalled. 2424 // or uninstalled.
2451 } 2425 }
2452 2426
2453 void ExtensionService::OnProfileDestructionStarted() { 2427 void ExtensionService::OnProfileDestructionStarted() {
2454 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); 2428 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs();
2455 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); 2429 for (ExtensionIdSet::iterator it = ids_to_unload.begin();
2456 it != ids_to_unload.end(); 2430 it != ids_to_unload.end();
2457 ++it) { 2431 ++it) {
2458 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); 2432 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN);
2459 } 2433 }
2460 } 2434 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_service.h ('k') | chrome/browser/extensions/extension_service_test_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698