Chromium Code Reviews| 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 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/files/file_util.h" | |
| 12 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/threading/sequenced_worker_pool.h" | 17 #include "base/threading/sequenced_worker_pool.h" |
| 17 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
| 18 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| 19 #include "chrome/browser/browser_process.h" | 20 #include "chrome/browser/browser_process.h" |
| 20 #include "chrome/browser/chrome_notification_types.h" | 21 #include "chrome/browser/chrome_notification_types.h" |
| 21 #include "chrome/browser/content_settings/content_settings_custom_extension_prov ider.h" | 22 #include "chrome/browser/content_settings/content_settings_custom_extension_prov ider.h" |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 49 #include "chrome/browser/ui/webui/theme_source.h" | 50 #include "chrome/browser/ui/webui/theme_source.h" |
| 50 #include "chrome/common/chrome_switches.h" | 51 #include "chrome/common/chrome_switches.h" |
| 51 #include "chrome/common/crash_keys.h" | 52 #include "chrome/common/crash_keys.h" |
| 52 #include "chrome/common/extensions/extension_constants.h" | 53 #include "chrome/common/extensions/extension_constants.h" |
| 53 #include "chrome/common/extensions/features/feature_channel.h" | 54 #include "chrome/common/extensions/features/feature_channel.h" |
| 54 #include "chrome/common/url_constants.h" | 55 #include "chrome/common/url_constants.h" |
| 55 #include "components/content_settings/core/browser/host_content_settings_map.h" | 56 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 56 #include "components/crx_file/id_util.h" | 57 #include "components/crx_file/id_util.h" |
| 57 #include "components/startup_metric_utils/startup_metric_utils.h" | 58 #include "components/startup_metric_utils/startup_metric_utils.h" |
| 58 #include "content/public/browser/devtools_agent_host.h" | 59 #include "content/public/browser/devtools_agent_host.h" |
| 60 #include "content/public/browser/indexed_db_context.h" | |
| 59 #include "content/public/browser/notification_service.h" | 61 #include "content/public/browser/notification_service.h" |
| 60 #include "content/public/browser/render_process_host.h" | 62 #include "content/public/browser/render_process_host.h" |
| 61 #include "content/public/browser/storage_partition.h" | 63 #include "content/public/browser/storage_partition.h" |
| 62 #include "extensions/browser/event_router.h" | 64 #include "extensions/browser/event_router.h" |
| 63 #include "extensions/browser/extension_host.h" | 65 #include "extensions/browser/extension_host.h" |
| 64 #include "extensions/browser/extension_prefs.h" | 66 #include "extensions/browser/extension_prefs.h" |
| 65 #include "extensions/browser/extension_registry.h" | 67 #include "extensions/browser/extension_registry.h" |
| 66 #include "extensions/browser/extension_system.h" | 68 #include "extensions/browser/extension_system.h" |
| 67 #include "extensions/browser/extensions_browser_client.h" | 69 #include "extensions/browser/extensions_browser_client.h" |
| 68 #include "extensions/browser/install_flag.h" | 70 #include "extensions/browser/install_flag.h" |
| 69 #include "extensions/browser/runtime_data.h" | 71 #include "extensions/browser/runtime_data.h" |
| 70 #include "extensions/browser/uninstall_reason.h" | 72 #include "extensions/browser/uninstall_reason.h" |
| 71 #include "extensions/browser/update_observer.h" | 73 #include "extensions/browser/update_observer.h" |
| 72 #include "extensions/browser/updater/extension_cache.h" | 74 #include "extensions/browser/updater/extension_cache.h" |
| 73 #include "extensions/browser/updater/extension_downloader.h" | 75 #include "extensions/browser/updater/extension_downloader.h" |
| 74 #include "extensions/common/extension_messages.h" | 76 #include "extensions/common/extension_messages.h" |
| 75 #include "extensions/common/extension_urls.h" | 77 #include "extensions/common/extension_urls.h" |
| 76 #include "extensions/common/feature_switch.h" | 78 #include "extensions/common/feature_switch.h" |
| 77 #include "extensions/common/file_util.h" | 79 #include "extensions/common/file_util.h" |
| 78 #include "extensions/common/manifest_constants.h" | 80 #include "extensions/common/manifest_constants.h" |
| 79 #include "extensions/common/manifest_handlers/background_info.h" | 81 #include "extensions/common/manifest_handlers/background_info.h" |
| 80 #include "extensions/common/manifest_url_handlers.h" | 82 #include "extensions/common/manifest_url_handlers.h" |
| 81 #include "extensions/common/one_shot_event.h" | 83 #include "extensions/common/one_shot_event.h" |
| 82 #include "extensions/common/permissions/permission_message_provider.h" | 84 #include "extensions/common/permissions/permission_message_provider.h" |
| 83 #include "extensions/common/permissions/permissions_data.h" | 85 #include "extensions/common/permissions/permissions_data.h" |
| 86 #include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h" | |
| 87 #include "storage/common/database/database_identifier.h" | |
| 88 #include "storage/common/fileapi/file_system_types.h" | |
| 84 | 89 |
| 85 #if defined(OS_CHROMEOS) | 90 #if defined(OS_CHROMEOS) |
| 86 #include "chrome/browser/chromeos/extensions/install_limiter.h" | 91 #include "chrome/browser/chromeos/extensions/install_limiter.h" |
| 87 #include "storage/browser/fileapi/file_system_backend.h" | 92 #include "storage/browser/fileapi/file_system_backend.h" |
| 88 #include "storage/browser/fileapi/file_system_context.h" | 93 #include "storage/browser/fileapi/file_system_context.h" |
| 89 #endif | 94 #endif |
| 90 | 95 |
| 91 using content::BrowserContext; | 96 using content::BrowserContext; |
| 92 using content::BrowserThread; | 97 using content::BrowserThread; |
| 93 using content::DevToolsAgentHost; | 98 using content::DevToolsAgentHost; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 108 using extensions::SharedModuleService; | 113 using extensions::SharedModuleService; |
| 109 using extensions::UnloadedExtensionInfo; | 114 using extensions::UnloadedExtensionInfo; |
| 110 | 115 |
| 111 namespace errors = extensions::manifest_errors; | 116 namespace errors = extensions::manifest_errors; |
| 112 | 117 |
| 113 namespace { | 118 namespace { |
| 114 | 119 |
| 115 // Wait this many seconds after an extensions becomes idle before updating it. | 120 // Wait this many seconds after an extensions becomes idle before updating it. |
| 116 const int kUpdateIdleDelay = 5; | 121 const int kUpdateIdleDelay = 5; |
| 117 | 122 |
| 123 void CopyFileSystem( | |
| 124 storage::SandboxFileSystemBackendDelegate* old_sandbox_delegate, | |
| 125 storage::SandboxFileSystemBackendDelegate* sandbox_delegate, | |
| 126 const GURL& origin, | |
| 127 storage::FileSystemType type){ | |
| 128 | |
| 129 base::FilePath old_base_path = | |
| 130 old_sandbox_delegate->GetBaseDirectoryForOriginAndType( | |
| 131 origin, | |
| 132 type, | |
| 133 false); | |
| 134 | |
| 135 base::FilePath base_path = | |
| 136 sandbox_delegate->GetBaseDirectoryForOriginAndType( | |
| 137 origin, | |
| 138 type, | |
| 139 true); | |
| 140 | |
| 141 base::CopyDirectory(old_base_path, base_path.DirName(), true); | |
| 142 } | |
| 143 | |
| 144 void MigrateLegacyPartition( | |
| 145 content::StoragePartition* old_partition, | |
| 146 content::StoragePartition* current_partition, | |
| 147 const Extension* extension) { | |
| 148 GURL extension_url = Extension::GetBaseURLFromExtensionId(extension->id()); | |
|
benwells
2014/11/03 00:08:41
Could you add a check here that this is happening
ryanackley
2014/11/04 22:51:54
Acknowledged.
| |
| 149 | |
| 150 content::IndexedDBContext* indexed_db_context = | |
| 151 current_partition->GetIndexedDBContext(); | |
| 152 content::IndexedDBContext* old_indexed_db_context = | |
| 153 old_partition->GetIndexedDBContext(); | |
| 154 | |
| 155 base::FilePath old_db_path = | |
| 156 old_indexed_db_context->GetFilePath(extension_url); | |
| 157 base::FilePath current_db_path = | |
| 158 indexed_db_context->GetFilePath(extension_url); | |
| 159 | |
| 160 if (base::PathExists(old_db_path) && !base::PathExists(current_db_path)){ | |
| 161 base::CopyDirectory(old_db_path, current_db_path.DirName(), true); | |
| 162 } | |
| 163 | |
| 164 storage::FileSystemContext* old_fs_context = | |
| 165 old_partition->GetFileSystemContext(); | |
| 166 storage::FileSystemContext* fs_context = | |
| 167 current_partition->GetFileSystemContext(); | |
| 168 | |
| 169 storage::SandboxFileSystemBackendDelegate* old_sandbox_delegate = | |
| 170 old_fs_context->sandbox_delegate(); | |
| 171 storage::SandboxFileSystemBackendDelegate* sandbox_delegate = | |
| 172 fs_context->sandbox_delegate(); | |
| 173 | |
| 174 scoped_ptr<storage::SandboxFileSystemBackendDelegate::OriginEnumerator> | |
| 175 enumerator(old_sandbox_delegate->CreateOriginEnumerator()); | |
| 176 | |
| 177 GURL origin; | |
| 178 while (extension_url != (origin = enumerator->Next()) && !origin.is_empty()){ | |
|
benwells
2014/11/03 00:08:41
Nit: you need a space before the curly (here and e
ryanackley
2014/11/04 22:51:53
Acknowledged.
| |
| 179 continue; | |
| 180 } | |
| 181 if (!origin.is_empty()){ | |
| 182 if (enumerator->HasFileSystemType(storage::kFileSystemTypeTemporary)){ | |
| 183 CopyFileSystem( | |
| 184 old_sandbox_delegate, | |
| 185 sandbox_delegate, | |
| 186 extension_url, | |
| 187 storage::kFileSystemTypeTemporary); | |
| 188 } | |
| 189 if (enumerator->HasFileSystemType(storage::kFileSystemTypePersistent)){ | |
| 190 CopyFileSystem( | |
| 191 old_sandbox_delegate, | |
| 192 sandbox_delegate, | |
| 193 extension_url, | |
| 194 storage::kFileSystemTypePersistent); | |
| 195 } | |
| 196 } | |
| 197 } | |
| 198 | |
| 118 } // namespace | 199 } // namespace |
| 119 | 200 |
| 120 // ExtensionService. | 201 // ExtensionService. |
| 121 | 202 |
| 122 void ExtensionService::CheckExternalUninstall(const std::string& id) { | 203 void ExtensionService::CheckExternalUninstall(const std::string& id) { |
| 123 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 204 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 124 | 205 |
| 125 // Check if the providers know about this extension. | 206 // Check if the providers know about this extension. |
| 126 extensions::ProviderCollection::const_iterator i; | 207 extensions::ProviderCollection::const_iterator i; |
| 127 for (i = external_extension_providers_.begin(); | 208 for (i = external_extension_providers_.begin(); |
| (...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1334 } | 1415 } |
| 1335 | 1416 |
| 1336 bool is_extension_upgrade = false; | 1417 bool is_extension_upgrade = false; |
| 1337 bool is_extension_installed = false; | 1418 bool is_extension_installed = false; |
| 1338 const Extension* old = GetInstalledExtension(extension->id()); | 1419 const Extension* old = GetInstalledExtension(extension->id()); |
| 1339 if (old) { | 1420 if (old) { |
| 1340 is_extension_installed = true; | 1421 is_extension_installed = true; |
| 1341 int version_compare_result = | 1422 int version_compare_result = |
| 1342 extension->version()->CompareTo(*(old->version())); | 1423 extension->version()->CompareTo(*(old->version())); |
| 1343 is_extension_upgrade = version_compare_result > 0; | 1424 is_extension_upgrade = version_compare_result > 0; |
| 1425 | |
| 1344 // Other than for unpacked extensions, CrxInstaller should have guaranteed | 1426 // Other than for unpacked extensions, CrxInstaller should have guaranteed |
| 1345 // that we aren't downgrading. | 1427 // that we aren't downgrading. |
| 1346 if (!Manifest::IsUnpackedLocation(extension->location())) | 1428 if (!Manifest::IsUnpackedLocation(extension->location())) |
| 1347 CHECK_GE(version_compare_result, 0); | 1429 CHECK_GE(version_compare_result, 0); |
| 1348 } | 1430 } |
| 1349 system_->runtime_data()->SetBeingUpgraded(extension, is_extension_upgrade); | 1431 system_->runtime_data()->SetBeingUpgraded(extension, is_extension_upgrade); |
| 1350 | 1432 |
| 1351 // The extension is now loaded, remove its data from unloaded extension map. | 1433 // The extension is now loaded, remove its data from unloaded extension map. |
| 1352 unloaded_extension_paths_.erase(extension->id()); | 1434 unloaded_extension_paths_.erase(extension->id()); |
| 1353 | 1435 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1407 extension->id(), | 1489 extension->id(), |
| 1408 extension->ShouldDisplayInNewTabPage() && | 1490 extension->ShouldDisplayInNewTabPage() && |
| 1409 !extension_prefs_->IsEphemeralApp(extension->id())); | 1491 !extension_prefs_->IsEphemeralApp(extension->id())); |
| 1410 if (!extension_prefs_->IsEphemeralApp(extension->id())) { | 1492 if (!extension_prefs_->IsEphemeralApp(extension->id())) { |
| 1411 extension_prefs_->app_sorting()->EnsureValidOrdinals( | 1493 extension_prefs_->app_sorting()->EnsureValidOrdinals( |
| 1412 extension->id(), syncer::StringOrdinal()); | 1494 extension->id(), syncer::StringOrdinal()); |
| 1413 } | 1495 } |
| 1414 } | 1496 } |
| 1415 | 1497 |
| 1416 registry_->AddEnabled(extension); | 1498 registry_->AddEnabled(extension); |
| 1499 | |
| 1417 if (extension_sync_service_) | 1500 if (extension_sync_service_) |
| 1418 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); | 1501 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); |
| 1419 NotifyExtensionLoaded(extension); | 1502 NotifyExtensionLoaded(extension); |
| 1420 } | 1503 } |
| 1504 | |
| 1421 system_->runtime_data()->SetBeingUpgraded(extension, false); | 1505 system_->runtime_data()->SetBeingUpgraded(extension, false); |
| 1422 } | 1506 } |
| 1423 | 1507 |
| 1424 void ExtensionService::AddComponentExtension(const Extension* extension) { | 1508 void ExtensionService::AddComponentExtension(const Extension* extension) { |
| 1425 const std::string old_version_string( | 1509 const std::string old_version_string( |
| 1426 extension_prefs_->GetVersionString(extension->id())); | 1510 extension_prefs_->GetVersionString(extension->id())); |
| 1427 const Version old_version(old_version_string); | 1511 const Version old_version(old_version_string); |
| 1428 | 1512 |
| 1429 VLOG(1) << "AddComponentExtension " << extension->name(); | 1513 VLOG(1) << "AddComponentExtension " << extension->name(); |
| 1430 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) { | 1514 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) { |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1705 page_ordinal, | 1789 page_ordinal, |
| 1706 install_parameter); | 1790 install_parameter); |
| 1707 } | 1791 } |
| 1708 } | 1792 } |
| 1709 | 1793 |
| 1710 void ExtensionService::OnExtensionManagementSettingsChanged() { | 1794 void ExtensionService::OnExtensionManagementSettingsChanged() { |
| 1711 error_controller_->ShowErrorIfNeeded(); | 1795 error_controller_->ShowErrorIfNeeded(); |
| 1712 CheckManagementPolicy(); | 1796 CheckManagementPolicy(); |
| 1713 } | 1797 } |
| 1714 | 1798 |
| 1799 bool ExtensionService::NeedsMigration(const Extension* extension){ | |
|
benwells
2014/11/03 00:08:41
Could all the new logic you're adding go in a new
benwells
2014/11/03 00:08:42
Can you add a check here that this is happening on
ryanackley
2014/11/04 22:51:54
Acknowledged.
ryanackley
2014/11/04 22:51:54
Acknowledged.
| |
| 1800 const Extension* old = GetInstalledExtension(extension->id()); | |
| 1801 return old && old->is_legacy_packaged_app() && extension->is_platform_app(); | |
| 1802 } | |
| 1803 | |
| 1804 void ExtensionService::MigrateThenFinishInstallation( | |
| 1805 const Extension* extension, | |
| 1806 bool was_ephemeral){ | |
| 1807 | |
| 1808 const Extension* old = GetInstalledExtension(extension->id()); | |
| 1809 | |
| 1810 // juggle the enabled status of the new and old extensions so we can get | |
| 1811 // the old and new storage partitions | |
| 1812 content::StoragePartition* old_partition = | |
| 1813 BrowserContext::GetStoragePartitionForSite( | |
| 1814 profile_, | |
| 1815 Extension::GetBaseURLFromExtensionId(extension->id())); | |
| 1816 bool oldWasDisabled = registry_->AddEnabled(extension); | |
| 1817 content::StoragePartition* new_partition = | |
| 1818 BrowserContext::GetStoragePartitionForSite( | |
| 1819 profile_, | |
| 1820 Extension::GetBaseURLFromExtensionId(extension->id())); | |
| 1821 | |
| 1822 if (!oldWasDisabled){ | |
| 1823 registry_->AddEnabled(old); | |
| 1824 }else{ | |
| 1825 registry_->RemoveEnabled(extension->id()); | |
| 1826 } | |
| 1827 | |
| 1828 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE, | |
|
benwells
2014/11/03 00:08:41
Could you use the blocking pool instead? See https
ryanackley
2014/11/04 22:51:54
Acknowledged.
| |
| 1829 base::Bind( | |
| 1830 &MigrateLegacyPartition, | |
| 1831 old_partition, | |
| 1832 new_partition, | |
| 1833 make_scoped_refptr(extension)), | |
| 1834 base::Bind( | |
| 1835 &ExtensionService::FinishInstallation, | |
| 1836 AsWeakPtr(), | |
| 1837 make_scoped_refptr(extension), | |
| 1838 was_ephemeral)); | |
| 1839 } | |
| 1840 | |
| 1715 void ExtensionService::AddNewOrUpdatedExtension( | 1841 void ExtensionService::AddNewOrUpdatedExtension( |
| 1716 const Extension* extension, | 1842 const Extension* extension, |
| 1717 Extension::State initial_state, | 1843 Extension::State initial_state, |
| 1718 int install_flags, | 1844 int install_flags, |
| 1719 const syncer::StringOrdinal& page_ordinal, | 1845 const syncer::StringOrdinal& page_ordinal, |
| 1720 const std::string& install_parameter) { | 1846 const std::string& install_parameter) { |
| 1721 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1847 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1722 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id()); | 1848 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id()); |
| 1723 extension_prefs_->OnExtensionInstalled( | 1849 extension_prefs_->OnExtensionInstalled( |
| 1724 extension, initial_state, page_ordinal, install_flags, install_parameter); | 1850 extension, initial_state, page_ordinal, install_flags, install_parameter); |
| 1725 delayed_installs_.Remove(extension->id()); | 1851 delayed_installs_.Remove(extension->id()); |
| 1726 if (InstallVerifier::NeedsVerification(*extension)) | 1852 if (InstallVerifier::NeedsVerification(*extension)) |
| 1727 system_->install_verifier()->VerifyExtension(extension->id()); | 1853 system_->install_verifier()->VerifyExtension(extension->id()); |
| 1728 FinishInstallation(extension, was_ephemeral); | 1854 |
| 1855 if (NeedsMigration(extension)){ | |
|
benwells
2014/11/03 00:08:42
The patter chrome tends to use here is more like:
ryanackley
2014/11/04 22:51:54
Acknowledged.
| |
| 1856 MigrateThenFinishInstallation(extension, was_ephemeral); | |
| 1857 }else{ | |
| 1858 FinishInstallation(extension, was_ephemeral); | |
| 1859 } | |
| 1860 | |
| 1729 } | 1861 } |
| 1730 | 1862 |
| 1731 void ExtensionService::MaybeFinishDelayedInstallation( | 1863 void ExtensionService::MaybeFinishDelayedInstallation( |
| 1732 const std::string& extension_id) { | 1864 const std::string& extension_id) { |
| 1733 // Check if the extension already got installed. | 1865 // Check if the extension already got installed. |
| 1734 if (!delayed_installs_.Contains(extension_id)) | 1866 if (!delayed_installs_.Contains(extension_id)) |
| 1735 return; | 1867 return; |
| 1736 extensions::ExtensionPrefs::DelayReason reason = | 1868 extensions::ExtensionPrefs::DelayReason reason = |
| 1737 extension_prefs_->GetDelayedInstallReason(extension_id); | 1869 extension_prefs_->GetDelayedInstallReason(extension_id); |
| 1738 | 1870 |
| (...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2371 } | 2503 } |
| 2372 | 2504 |
| 2373 void ExtensionService::OnProfileDestructionStarted() { | 2505 void ExtensionService::OnProfileDestructionStarted() { |
| 2374 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); | 2506 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); |
| 2375 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); | 2507 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); |
| 2376 it != ids_to_unload.end(); | 2508 it != ids_to_unload.end(); |
| 2377 ++it) { | 2509 ++it) { |
| 2378 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); | 2510 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); |
| 2379 } | 2511 } |
| 2380 } | 2512 } |
| OLD | NEW |