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