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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 #include "storage/browser/fileapi/file_system_backend.h" | 102 #include "storage/browser/fileapi/file_system_backend.h" |
103 #include "storage/browser/fileapi/file_system_context.h" | 103 #include "storage/browser/fileapi/file_system_context.h" |
104 #endif | 104 #endif |
105 | 105 |
106 using content::BrowserContext; | 106 using content::BrowserContext; |
107 using content::BrowserThread; | 107 using content::BrowserThread; |
108 using content::DevToolsAgentHost; | 108 using content::DevToolsAgentHost; |
109 using extensions::APIPermission; | 109 using extensions::APIPermission; |
110 using extensions::AppSorting; | 110 using extensions::AppSorting; |
111 using extensions::CrxInstaller; | 111 using extensions::CrxInstaller; |
112 using extensions::ExternalExtensionInstallInfoFile; | |
113 using extensions::ExternalExtensionInstallInfoUpdateUrl; | |
112 using extensions::Extension; | 114 using extensions::Extension; |
113 using extensions::ExtensionIdSet; | 115 using extensions::ExtensionIdSet; |
114 using extensions::ExtensionInfo; | 116 using extensions::ExtensionInfo; |
115 using extensions::ExtensionRegistry; | 117 using extensions::ExtensionRegistry; |
116 using extensions::ExtensionSet; | 118 using extensions::ExtensionSet; |
119 using extensions::ExternalProviderInterface; | |
117 using extensions::FeatureSwitch; | 120 using extensions::FeatureSwitch; |
118 using extensions::InstallVerifier; | 121 using extensions::InstallVerifier; |
119 using extensions::ManagementPolicy; | 122 using extensions::ManagementPolicy; |
120 using extensions::Manifest; | 123 using extensions::Manifest; |
121 using extensions::PermissionID; | 124 using extensions::PermissionID; |
122 using extensions::PermissionIDSet; | 125 using extensions::PermissionIDSet; |
123 using extensions::PermissionSet; | 126 using extensions::PermissionSet; |
124 using extensions::SharedModuleInfo; | 127 using extensions::SharedModuleInfo; |
125 using extensions::SharedModuleService; | 128 using extensions::SharedModuleService; |
126 using extensions::UnloadedExtensionInfo; | 129 using extensions::UnloadedExtensionInfo; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 void ExtensionService::SetFileTaskRunnerForTesting( | 170 void ExtensionService::SetFileTaskRunnerForTesting( |
168 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { | 171 const scoped_refptr<base::SequencedTaskRunner>& task_runner) { |
169 file_task_runner_ = task_runner; | 172 file_task_runner_ = task_runner; |
170 } | 173 } |
171 | 174 |
172 void ExtensionService::ClearProvidersForTesting() { | 175 void ExtensionService::ClearProvidersForTesting() { |
173 external_extension_providers_.clear(); | 176 external_extension_providers_.clear(); |
174 } | 177 } |
175 | 178 |
176 void ExtensionService::AddProviderForTesting( | 179 void ExtensionService::AddProviderForTesting( |
177 extensions::ExternalProviderInterface* test_provider) { | 180 ExternalProviderInterface* test_provider) { |
178 CHECK(test_provider); | 181 CHECK(test_provider); |
179 external_extension_providers_.push_back( | 182 external_extension_providers_.push_back( |
180 linked_ptr<extensions::ExternalProviderInterface>(test_provider)); | 183 linked_ptr<ExternalProviderInterface>(test_provider)); |
181 } | 184 } |
182 | 185 |
183 void ExtensionService::BlacklistExtensionForTest( | 186 void ExtensionService::BlacklistExtensionForTest( |
184 const std::string& extension_id) { | 187 const std::string& extension_id) { |
185 ExtensionIdSet blacklisted; | 188 ExtensionIdSet blacklisted; |
186 ExtensionIdSet unchanged; | 189 ExtensionIdSet unchanged; |
187 blacklisted.insert(extension_id); | 190 blacklisted.insert(extension_id); |
188 UpdateBlacklistedExtensions(blacklisted, unchanged); | 191 UpdateBlacklistedExtensions(blacklisted, unchanged); |
189 } | 192 } |
190 | 193 |
191 bool ExtensionService::OnExternalExtensionUpdateUrlFound( | 194 bool ExtensionService::OnExternalExtensionUpdateUrlFound( |
192 const std::string& id, | 195 ExternalExtensionInstallInfoUpdateUrl* info, |
193 const std::string& install_parameter, | 196 bool is_initial_load) { |
194 const GURL& update_url, | |
195 Manifest::Location location, | |
196 int creation_flags, | |
197 bool mark_acknowledged) { | |
198 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 197 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
199 CHECK(crx_file::id_util::IdIsValid(id)); | 198 CHECK(crx_file::id_util::IdIsValid(info->extension_id)); |
200 | 199 |
201 if (Manifest::IsExternalLocation(location)) { | 200 if (Manifest::IsExternalLocation(info->download_location)) { |
202 // All extensions that are not user specific can be cached. | 201 // All extensions that are not user specific can be cached. |
203 extensions::ExtensionsBrowserClient::Get()->GetExtensionCache() | 202 extensions::ExtensionsBrowserClient::Get() |
204 ->AllowCaching(id); | 203 ->GetExtensionCache() |
204 ->AllowCaching(info->extension_id); | |
205 } | 205 } |
206 | 206 |
207 const Extension* extension = GetExtensionById(id, true); | 207 const Extension* extension = GetExtensionById(info->extension_id, true); |
208 if (extension) { | 208 if (extension) { |
209 // Already installed. Skip this install if the current location has | 209 // Already installed. Skip this install if the current location has |
210 // higher priority than |location|. | 210 // higher priority than |info->download_location|. |
211 Manifest::Location current = extension->location(); | 211 Manifest::Location current = extension->location(); |
212 if (current == Manifest::GetHigherPriorityLocation(current, location)) | 212 if (current == |
213 Manifest::GetHigherPriorityLocation(current, info->download_location)) { | |
213 return false; | 214 return false; |
215 } | |
214 // Otherwise, overwrite the current installation. | 216 // Otherwise, overwrite the current installation. |
215 } | 217 } |
216 | 218 |
217 // Add |id| to the set of pending extensions. If it can not be added, | 219 // Add |info->extension_id| to the set of pending extensions. If it can not |
218 // then there is already a pending record from a higher-priority install | 220 // be added, then there is already a pending record from a higher-priority |
219 // source. In this case, signal that this extension will not be | 221 // install source. In this case, signal that this extension will not be |
220 // installed by returning false. | 222 // installed by returning false. |
221 if (!pending_extension_manager()->AddFromExternalUpdateUrl( | 223 if (!pending_extension_manager()->AddFromExternalUpdateUrl( |
222 id, | 224 info->extension_id, info->install_parameter, *info->update_url, |
223 install_parameter, | 225 info->download_location, info->creation_flags, |
224 update_url, | 226 info->mark_acknowledged)) { |
225 location, | |
226 creation_flags, | |
227 mark_acknowledged)) { | |
228 return false; | 227 return false; |
229 } | 228 } |
230 | 229 |
231 update_once_all_providers_are_ready_ = true; | 230 if (is_initial_load) |
231 update_once_all_providers_are_ready_ = true; | |
232 return true; | 232 return true; |
233 } | 233 } |
234 | 234 |
235 void ExtensionService::OnExternalProviderUpdateComplete( | |
236 const ExternalProviderInterface* provider, | |
237 const ScopedVector<ExternalExtensionInstallInfoUpdateUrl>& | |
238 update_url_extensions, | |
239 const ScopedVector<ExternalExtensionInstallInfoFile>& file_extensions, | |
240 const std::set<std::string>& removed_extensions) { | |
241 if (!update_url_extensions.empty() || !file_extensions.empty()) { | |
242 // Update pending_extension_manager() with the new extensions first. | |
243 for (const auto& extension : update_url_extensions) | |
244 OnExternalExtensionUpdateUrlFound(extension, false); | |
245 for (const auto& extension : file_extensions) | |
246 OnExternalExtensionFileFound(extension); | |
247 | |
248 if (updater_) { | |
asargent_no_longer_on_chrome
2016/01/25 18:50:52
Does the extension updater need to run if we only
lazyboy
2016/01/26 05:20:04
Ah right, the CRX download is handled differently.
| |
249 // Empty params will cause pending extensions to be updated. | |
250 extensions::ExtensionUpdater::CheckParams empty_params; | |
251 updater_->CheckNow(empty_params); | |
252 } | |
253 } | |
254 | |
255 for (const std::string& id : removed_extensions) | |
256 CheckExternalUninstall(id); | |
asargent_no_longer_on_chrome
2016/01/25 18:50:52
Can we move the handling of uninstalls a few lines
lazyboy
2016/01/26 05:20:04
Moved.
It would be nice to avoid the edge case of
asargent_no_longer_on_chrome
2016/01/26 17:48:07
You're right, from a single provider this should n
| |
257 | |
258 error_controller_->ShowErrorIfNeeded(); | |
259 external_install_manager_->UpdateExternalExtensionAlert(); | |
260 } | |
261 | |
235 // static | 262 // static |
236 // This function is used to uninstall an extension via sync. The LOG statements | 263 // This function is used to uninstall an extension via sync. The LOG statements |
237 // within this function are used to inform the user if the uninstall cannot be | 264 // within this function are used to inform the user if the uninstall cannot be |
238 // done. | 265 // done. |
239 bool ExtensionService::UninstallExtensionHelper( | 266 bool ExtensionService::UninstallExtensionHelper( |
240 ExtensionService* extensions_service, | 267 ExtensionService* extensions_service, |
241 const std::string& extension_id, | 268 const std::string& extension_id, |
242 extensions::UninstallReason reason) { | 269 extensions::UninstallReason reason) { |
243 // We can't call UninstallExtension with an invalid extension ID. | 270 // We can't call UninstallExtension with an invalid extension ID. |
244 if (!extensions_service->GetInstalledExtension(extension_id)) { | 271 if (!extensions_service->GetInstalledExtension(extension_id)) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 return &pending_extension_manager_; | 390 return &pending_extension_manager_; |
364 } | 391 } |
365 | 392 |
366 ExtensionService::~ExtensionService() { | 393 ExtensionService::~ExtensionService() { |
367 // No need to unload extensions here because they are profile-scoped, and the | 394 // No need to unload extensions here because they are profile-scoped, and the |
368 // profile is in the process of being deleted. | 395 // profile is in the process of being deleted. |
369 | 396 |
370 extensions::ProviderCollection::const_iterator i; | 397 extensions::ProviderCollection::const_iterator i; |
371 for (i = external_extension_providers_.begin(); | 398 for (i = external_extension_providers_.begin(); |
372 i != external_extension_providers_.end(); ++i) { | 399 i != external_extension_providers_.end(); ++i) { |
373 extensions::ExternalProviderInterface* provider = i->get(); | 400 ExternalProviderInterface* provider = i->get(); |
374 provider->ServiceShutdown(); | 401 provider->ServiceShutdown(); |
375 } | 402 } |
376 } | 403 } |
377 | 404 |
378 void ExtensionService::Shutdown() { | 405 void ExtensionService::Shutdown() { |
379 extensions::ExtensionManagementFactory::GetInstance() | 406 extensions::ExtensionManagementFactory::GetInstance() |
380 ->GetForBrowserContext(profile()) | 407 ->GetForBrowserContext(profile()) |
381 ->RemoveObserver(this); | 408 ->RemoveObserver(this); |
382 } | 409 } |
383 | 410 |
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1267 // go through the front-end). Extensions that are registered in this | 1294 // go through the front-end). Extensions that are registered in this |
1268 // way are effectively considered 'pre-bundled', and so implicitly | 1295 // way are effectively considered 'pre-bundled', and so implicitly |
1269 // trusted. In general, if something has HKLM or filesystem access, | 1296 // trusted. In general, if something has HKLM or filesystem access, |
1270 // they could install an extension manually themselves anyway. | 1297 // they could install an extension manually themselves anyway. |
1271 | 1298 |
1272 // Ask each external extension provider to give us a call back for each | 1299 // Ask each external extension provider to give us a call back for each |
1273 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. | 1300 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. |
1274 extensions::ProviderCollection::const_iterator i; | 1301 extensions::ProviderCollection::const_iterator i; |
1275 for (i = external_extension_providers_.begin(); | 1302 for (i = external_extension_providers_.begin(); |
1276 i != external_extension_providers_.end(); ++i) { | 1303 i != external_extension_providers_.end(); ++i) { |
1277 extensions::ExternalProviderInterface* provider = i->get(); | 1304 ExternalProviderInterface* provider = i->get(); |
1278 provider->VisitRegisteredExtension(); | 1305 provider->VisitRegisteredExtension(); |
1279 } | 1306 } |
1280 | 1307 |
1281 // Do any required work that we would have done after completion of all | 1308 // Do any required work that we would have done after completion of all |
1282 // providers. | 1309 // providers. |
1283 if (external_extension_providers_.empty()) | 1310 if (external_extension_providers_.empty()) |
1284 OnAllExternalProvidersReady(); | 1311 OnAllExternalProvidersReady(); |
1285 } | 1312 } |
1286 | 1313 |
1287 void ExtensionService::OnExternalProviderReady( | 1314 void ExtensionService::OnExternalProviderReady( |
1288 const extensions::ExternalProviderInterface* provider) { | 1315 const ExternalProviderInterface* provider) { |
1289 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1316 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1290 CHECK(provider->IsReady()); | 1317 CHECK(provider->IsReady()); |
1291 | 1318 |
1292 // An external provider has finished loading. We only take action | 1319 // An external provider has finished loading. We only take action |
1293 // if all of them are finished. So we check them first. | 1320 // if all of them are finished. So we check them first. |
1294 if (AreAllExternalProvidersReady()) | 1321 if (AreAllExternalProvidersReady()) |
1295 OnAllExternalProvidersReady(); | 1322 OnAllExternalProvidersReady(); |
1296 } | 1323 } |
1297 | 1324 |
1298 bool ExtensionService::AreAllExternalProvidersReady() const { | 1325 bool ExtensionService::AreAllExternalProvidersReady() const { |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2001 content::Details<const Extension>(extension)); | 2028 content::Details<const Extension>(extension)); |
2002 } | 2029 } |
2003 } | 2030 } |
2004 | 2031 |
2005 const Extension* ExtensionService::GetInstalledExtension( | 2032 const Extension* ExtensionService::GetInstalledExtension( |
2006 const std::string& id) const { | 2033 const std::string& id) const { |
2007 return registry_->GetExtensionById(id, ExtensionRegistry::EVERYTHING); | 2034 return registry_->GetExtensionById(id, ExtensionRegistry::EVERYTHING); |
2008 } | 2035 } |
2009 | 2036 |
2010 bool ExtensionService::OnExternalExtensionFileFound( | 2037 bool ExtensionService::OnExternalExtensionFileFound( |
2011 const std::string& id, | 2038 ExternalExtensionInstallInfoFile* info) { |
2012 const Version* version, | |
2013 const base::FilePath& path, | |
2014 Manifest::Location location, | |
2015 int creation_flags, | |
2016 bool mark_acknowledged, | |
2017 bool install_immediately) { | |
2018 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2039 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2019 CHECK(crx_file::id_util::IdIsValid(id)); | 2040 CHECK(crx_file::id_util::IdIsValid(info->extension_id)); |
2020 if (extension_prefs_->IsExternalExtensionUninstalled(id)) | 2041 if (extension_prefs_->IsExternalExtensionUninstalled(info->extension_id)) |
2021 return false; | 2042 return false; |
2022 | 2043 |
2023 // Before even bothering to unpack, check and see if we already have this | 2044 // Before even bothering to unpack, check and see if we already have this |
2024 // version. This is important because these extensions are going to get | 2045 // version. This is important because these extensions are going to get |
2025 // installed on every startup. | 2046 // installed on every startup. |
2026 const Extension* existing = GetExtensionById(id, true); | 2047 const Extension* existing = GetExtensionById(info->extension_id, true); |
2027 | 2048 |
2028 if (existing) { | 2049 if (existing) { |
2029 // The default apps will have the location set as INTERNAL. Since older | 2050 // The default apps will have the location set as INTERNAL. Since older |
2030 // default apps are installed as EXTERNAL, we override them. However, if the | 2051 // default apps are installed as EXTERNAL, we override them. However, if the |
2031 // app is already installed as internal, then do the version check. | 2052 // app is already installed as internal, then do the version check. |
2032 // TODO(grv) : Remove after Q1-2013. | 2053 // TODO(grv) : Remove after Q1-2013. |
2033 bool is_default_apps_migration = | 2054 bool is_default_apps_migration = |
2034 (location == Manifest::INTERNAL && | 2055 (info->crx_location == Manifest::INTERNAL && |
2035 Manifest::IsExternalLocation(existing->location())); | 2056 Manifest::IsExternalLocation(existing->location())); |
2036 | 2057 |
2037 if (!is_default_apps_migration) { | 2058 if (!is_default_apps_migration) { |
2038 DCHECK(version); | 2059 DCHECK(info->version.get()); |
2039 | 2060 |
2040 switch (existing->version()->CompareTo(*version)) { | 2061 switch (existing->version()->CompareTo(*info->version)) { |
2041 case -1: // existing version is older, we should upgrade | 2062 case -1: // existing version is older, we should upgrade |
2042 break; | 2063 break; |
2043 case 0: // existing version is same, do nothing | 2064 case 0: // existing version is same, do nothing |
2044 return false; | 2065 return false; |
2045 case 1: // existing version is newer, uh-oh | 2066 case 1: // existing version is newer, uh-oh |
2046 LOG(WARNING) << "Found external version of extension " << id | 2067 LOG(WARNING) << "Found external version of extension " |
2068 << info->extension_id | |
2047 << "that is older than current version. Current version " | 2069 << "that is older than current version. Current version " |
2048 << "is: " << existing->VersionString() << ". New " | 2070 << "is: " << existing->VersionString() << ". New " |
2049 << "version is: " << version->GetString() | 2071 << "version is: " << info->version->GetString() |
2050 << ". Keeping current version."; | 2072 << ". Keeping current version."; |
2051 return false; | 2073 return false; |
2052 } | 2074 } |
2053 } | 2075 } |
2054 } | 2076 } |
2055 | 2077 |
2056 // If the extension is already pending, don't start an install. | 2078 // If the extension is already pending, don't start an install. |
2057 if (!pending_extension_manager()->AddFromExternalFile( | 2079 if (!pending_extension_manager()->AddFromExternalFile( |
2058 id, location, *version, creation_flags, mark_acknowledged)) { | 2080 info->extension_id, info->crx_location, *info->version, |
2081 info->creation_flags, info->mark_acknowledged)) { | |
2059 return false; | 2082 return false; |
2060 } | 2083 } |
2061 | 2084 |
2062 // no client (silent install) | 2085 // no client (silent install) |
2063 scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this)); | 2086 scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this)); |
2064 installer->set_install_source(location); | 2087 installer->set_install_source(info->crx_location); |
2065 installer->set_expected_id(id); | 2088 installer->set_expected_id(info->extension_id); |
2066 installer->set_expected_version(*version, | 2089 installer->set_expected_version(*info->version, |
2067 true /* fail_install_if_unexpected */); | 2090 true /* fail_install_if_unexpected */); |
2068 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE); | 2091 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE); |
2069 installer->set_install_immediately(install_immediately); | 2092 installer->set_install_immediately(info->install_immediately); |
2070 installer->set_creation_flags(creation_flags); | 2093 installer->set_creation_flags(info->creation_flags); |
2071 #if defined(OS_CHROMEOS) | 2094 #if defined(OS_CHROMEOS) |
2072 extensions::InstallLimiter::Get(profile_)->Add(installer, path); | 2095 extensions::InstallLimiter::Get(profile_)->Add(installer, info->path); |
2073 #else | 2096 #else |
2074 installer->InstallCrx(path); | 2097 installer->InstallCrx(info->path); |
2075 #endif | 2098 #endif |
2076 | 2099 |
2077 // Depending on the source, a new external extension might not need a user | 2100 // Depending on the source, a new external extension might not need a user |
2078 // notification on installation. For such extensions, mark them acknowledged | 2101 // notification on installation. For such extensions, mark them acknowledged |
2079 // now to suppress the notification. | 2102 // now to suppress the notification. |
2080 if (mark_acknowledged) | 2103 if (info->mark_acknowledged) |
2081 external_install_manager_->AcknowledgeExternalExtension(id); | 2104 external_install_manager_->AcknowledgeExternalExtension(info->extension_id); |
2082 | 2105 |
2083 return true; | 2106 return true; |
2084 } | 2107 } |
2085 | 2108 |
2086 void ExtensionService::DidCreateRenderViewForBackgroundPage( | 2109 void ExtensionService::DidCreateRenderViewForBackgroundPage( |
2087 extensions::ExtensionHost* host) { | 2110 extensions::ExtensionHost* host) { |
2088 OrphanedDevTools::iterator iter = | 2111 OrphanedDevTools::iterator iter = |
2089 orphaned_dev_tools_.find(host->extension_id()); | 2112 orphaned_dev_tools_.find(host->extension_id()); |
2090 if (iter == orphaned_dev_tools_.end()) | 2113 if (iter == orphaned_dev_tools_.end()) |
2091 return; | 2114 return; |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2465 } | 2488 } |
2466 | 2489 |
2467 void ExtensionService::OnProfileDestructionStarted() { | 2490 void ExtensionService::OnProfileDestructionStarted() { |
2468 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); | 2491 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); |
2469 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); | 2492 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); |
2470 it != ids_to_unload.end(); | 2493 it != ids_to_unload.end(); |
2471 ++it) { | 2494 ++it) { |
2472 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); | 2495 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); |
2473 } | 2496 } |
2474 } | 2497 } |
OLD | NEW |