| 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 |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 // includes those that have been disabled due to blacklisting or blocking. | 379 // includes those that have been disabled due to blacklisting or blocking. |
| 380 include_mask |= ExtensionRegistry::DISABLED | | 380 include_mask |= ExtensionRegistry::DISABLED | |
| 381 ExtensionRegistry::BLACKLISTED | ExtensionRegistry::BLOCKED; | 381 ExtensionRegistry::BLACKLISTED | ExtensionRegistry::BLOCKED; |
| 382 } | 382 } |
| 383 return registry_->GetExtensionById(id, include_mask); | 383 return registry_->GetExtensionById(id, include_mask); |
| 384 } | 384 } |
| 385 | 385 |
| 386 void ExtensionService::Init() { | 386 void ExtensionService::Init() { |
| 387 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 387 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 388 TRACE_EVENT0("browser,startup", "ExtensionService::Init"); | 388 TRACE_EVENT0("browser,startup", "ExtensionService::Init"); |
| 389 base::Time begin_time = base::Time::Now(); | 389 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.ExtensionServiceInitTime"); |
| 390 | 390 |
| 391 DCHECK(!is_ready()); // Can't redo init. | 391 DCHECK(!is_ready()); // Can't redo init. |
| 392 DCHECK_EQ(registry_->enabled_extensions().size(), 0u); | 392 DCHECK_EQ(registry_->enabled_extensions().size(), 0u); |
| 393 | 393 |
| 394 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 394 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 395 if (cmd_line->HasSwitch(switches::kInstallEphemeralAppFromWebstore)) { | 395 if (cmd_line->HasSwitch(switches::kInstallEphemeralAppFromWebstore)) { |
| 396 // The sole purpose of this launch is to install a new extension from CWS | 396 // The sole purpose of this launch is to install a new extension from CWS |
| 397 // and immediately terminate: loading already installed extensions is | 397 // and immediately terminate: loading already installed extensions is |
| 398 // unnecessary and may interfere with the inline install dialog (e.g. if an | 398 // unnecessary and may interfere with the inline install dialog (e.g. if an |
| 399 // extension listens to onStartup and opens a window). | 399 // extension listens to onStartup and opens a window). |
| 400 SetReadyAndNotifyListeners(); | 400 SetReadyAndNotifyListeners(); |
| 401 } else { | 401 } else { |
| 402 // LoadAllExtensions() calls OnLoadedInstalledExtensions(). | 402 // LoadAllExtensions() calls OnLoadedInstalledExtensions(). |
| 403 component_loader_->LoadAll(); | 403 component_loader_->LoadAll(); |
| 404 extensions::InstalledLoader(this).LoadAllExtensions(); | 404 extensions::InstalledLoader(this).LoadAllExtensions(); |
| 405 | 405 |
| 406 // Attempt to re-enable extensions whose only disable reason is reloading. | 406 EnabledReloadableExtensions(); |
| 407 std::vector<std::string> extensions_to_enable; | 407 MaybeFinishShutdownDelayed(); |
| 408 const ExtensionSet& disabled_extensions = registry_->disabled_extensions(); | |
| 409 for (ExtensionSet::const_iterator iter = disabled_extensions.begin(); | |
| 410 iter != disabled_extensions.end(); ++iter) { | |
| 411 const Extension* e = iter->get(); | |
| 412 if (extension_prefs_->GetDisableReasons(e->id()) == | |
| 413 Extension::DISABLE_RELOAD) { | |
| 414 extensions_to_enable.push_back(e->id()); | |
| 415 } | |
| 416 } | |
| 417 for (std::vector<std::string>::iterator it = extensions_to_enable.begin(); | |
| 418 it != extensions_to_enable.end(); ++it) { | |
| 419 EnableExtension(*it); | |
| 420 } | |
| 421 | |
| 422 // Finish install (if possible) of extensions that were still delayed while | |
| 423 // the browser was shut down. | |
| 424 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info( | |
| 425 extension_prefs_->GetAllDelayedInstallInfo()); | |
| 426 for (size_t i = 0; i < delayed_info->size(); ++i) { | |
| 427 ExtensionInfo* info = delayed_info->at(i).get(); | |
| 428 scoped_refptr<const Extension> extension(NULL); | |
| 429 if (info->extension_manifest) { | |
| 430 std::string error; | |
| 431 extension = Extension::Create( | |
| 432 info->extension_path, | |
| 433 info->extension_location, | |
| 434 *info->extension_manifest, | |
| 435 extension_prefs_->GetDelayedInstallCreationFlags( | |
| 436 info->extension_id), | |
| 437 info->extension_id, | |
| 438 &error); | |
| 439 if (extension.get()) | |
| 440 delayed_installs_.Insert(extension); | |
| 441 } | |
| 442 } | |
| 443 MaybeFinishDelayedInstallations(); | |
| 444 | |
| 445 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2( | |
| 446 extension_prefs_->GetAllDelayedInstallInfo()); | |
| 447 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad", | |
| 448 delayed_info2->size() - delayed_info->size()); | |
| 449 | |
| 450 SetReadyAndNotifyListeners(); | 408 SetReadyAndNotifyListeners(); |
| 451 | 409 |
| 452 // TODO(erikkay) this should probably be deferred to a future point | 410 // TODO(erikkay): this should probably be deferred to a future point |
| 453 // rather than running immediately at startup. | 411 // rather than running immediately at startup. |
| 454 CheckForExternalUpdates(); | 412 CheckForExternalUpdates(); |
| 455 | 413 |
| 456 LoadGreylistFromPrefs(); | 414 LoadGreylistFromPrefs(); |
| 457 } | 415 } |
| 416 } |
| 458 | 417 |
| 459 UMA_HISTOGRAM_TIMES("Extensions.ExtensionServiceInitTime", | 418 void ExtensionService::EnabledReloadableExtensions() { |
| 460 base::Time::Now() - begin_time); | 419 TRACE_EVENT0("browser,startup", |
| 420 "ExtensionService::EnabledReloadableExtensions"); |
| 421 |
| 422 std::vector<std::string> extensions_to_enable; |
| 423 const ExtensionSet& disabled_extensions = registry_->disabled_extensions(); |
| 424 for (ExtensionSet::const_iterator iter = disabled_extensions.begin(); |
| 425 iter != disabled_extensions.end(); ++iter) { |
| 426 const Extension* e = iter->get(); |
| 427 if (extension_prefs_->GetDisableReasons(e->id()) == |
| 428 Extension::DISABLE_RELOAD) { |
| 429 extensions_to_enable.push_back(e->id()); |
| 430 } |
| 431 } |
| 432 for (const std::string& extension : extensions_to_enable) { |
| 433 EnableExtension(extension); |
| 434 } |
| 435 } |
| 436 |
| 437 void ExtensionService::MaybeFinishShutdownDelayed() { |
| 438 TRACE_EVENT0("browser,startup", |
| 439 "ExtensionService::MaybeFinishShutdownDelayed"); |
| 440 |
| 441 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info( |
| 442 extension_prefs_->GetAllDelayedInstallInfo()); |
| 443 for (size_t i = 0; i < delayed_info->size(); ++i) { |
| 444 ExtensionInfo* info = delayed_info->at(i).get(); |
| 445 scoped_refptr<const Extension> extension(NULL); |
| 446 if (info->extension_manifest) { |
| 447 std::string error; |
| 448 extension = Extension::Create( |
| 449 info->extension_path, info->extension_location, |
| 450 *info->extension_manifest, |
| 451 extension_prefs_->GetDelayedInstallCreationFlags(info->extension_id), |
| 452 info->extension_id, &error); |
| 453 if (extension.get()) |
| 454 delayed_installs_.Insert(extension); |
| 455 } |
| 456 } |
| 457 MaybeFinishDelayedInstallations(); |
| 458 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2( |
| 459 extension_prefs_->GetAllDelayedInstallInfo()); |
| 460 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad", |
| 461 delayed_info2->size() - delayed_info->size()); |
| 461 } | 462 } |
| 462 | 463 |
| 463 void ExtensionService::LoadGreylistFromPrefs() { | 464 void ExtensionService::LoadGreylistFromPrefs() { |
| 465 TRACE_EVENT0("browser,startup", "ExtensionService::LoadGreylistFromPrefs"); |
| 466 |
| 464 scoped_ptr<ExtensionSet> all_extensions = | 467 scoped_ptr<ExtensionSet> all_extensions = |
| 465 registry_->GenerateInstalledExtensionsSet(); | 468 registry_->GenerateInstalledExtensionsSet(); |
| 466 | 469 |
| 467 for (ExtensionSet::const_iterator it = all_extensions->begin(); | 470 for (ExtensionSet::const_iterator it = all_extensions->begin(); |
| 468 it != all_extensions->end(); ++it) { | 471 it != all_extensions->end(); ++it) { |
| 469 extensions::BlacklistState state = | 472 extensions::BlacklistState state = |
| 470 extension_prefs_->GetExtensionBlacklistState((*it)->id()); | 473 extension_prefs_->GetExtensionBlacklistState((*it)->id()); |
| 471 if (state == extensions::BLACKLISTED_SECURITY_VULNERABILITY || | 474 if (state == extensions::BLACKLISTED_SECURITY_VULNERABILITY || |
| 472 state == extensions::BLACKLISTED_POTENTIALLY_UNWANTED || | 475 state == extensions::BLACKLISTED_POTENTIALLY_UNWANTED || |
| 473 state == extensions::BLACKLISTED_CWS_POLICY_VIOLATION) | 476 state == extensions::BLACKLISTED_CWS_POLICY_VIOLATION) |
| (...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 updater_->CheckSoon(); | 1256 updater_->CheckSoon(); |
| 1254 } else { | 1257 } else { |
| 1255 // Sync can start updating before all the external providers are ready | 1258 // Sync can start updating before all the external providers are ready |
| 1256 // during startup. Start the update as soon as those providers are ready, | 1259 // during startup. Start the update as soon as those providers are ready, |
| 1257 // but not before. | 1260 // but not before. |
| 1258 update_once_all_providers_are_ready_ = true; | 1261 update_once_all_providers_are_ready_ = true; |
| 1259 } | 1262 } |
| 1260 } | 1263 } |
| 1261 | 1264 |
| 1262 // Some extensions will autoupdate themselves externally from Chrome. These | 1265 // Some extensions will autoupdate themselves externally from Chrome. These |
| 1263 // are typically part of some larger client application package. To support | 1266 // are typically part of some larger client application package. To support |
| 1264 // these, the extension will register its location in the the preferences file | 1267 // these, the extension will register its location in the preferences file |
| 1265 // (and also, on Windows, in the registry) and this code will periodically | 1268 // (and also, on Windows, in the registry) and this code will periodically |
| 1266 // check that location for a .crx file, which it will then install locally if | 1269 // check that location for a .crx file, which it will then install locally if |
| 1267 // a new version is available. | 1270 // a new version is available. |
| 1268 // Errors are reported through ExtensionErrorReporter. Succcess is not | 1271 // Errors are reported through ExtensionErrorReporter. Success is not |
| 1269 // reported. | 1272 // reported. |
| 1270 void ExtensionService::CheckForExternalUpdates() { | 1273 void ExtensionService::CheckForExternalUpdates() { |
| 1271 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1274 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1275 TRACE_EVENT0("browser,startup", "ExtensionService::CheckForExternalUpdates"); |
| 1276 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.CheckForExternalUpdatesTime"); |
| 1272 | 1277 |
| 1273 // Note that this installation is intentionally silent (since it didn't | 1278 // Note that this installation is intentionally silent (since it didn't |
| 1274 // go through the front-end). Extensions that are registered in this | 1279 // go through the front-end). Extensions that are registered in this |
| 1275 // way are effectively considered 'pre-bundled', and so implicitly | 1280 // way are effectively considered 'pre-bundled', and so implicitly |
| 1276 // trusted. In general, if something has HKLM or filesystem access, | 1281 // trusted. In general, if something has HKLM or filesystem access, |
| 1277 // they could install an extension manually themselves anyway. | 1282 // they could install an extension manually themselves anyway. |
| 1278 | 1283 |
| 1279 // Ask each external extension provider to give us a call back for each | 1284 // Ask each external extension provider to give us a call back for each |
| 1280 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. | 1285 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. |
| 1281 extensions::ProviderCollection::const_iterator i; | 1286 extensions::ProviderCollection::const_iterator i; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 // Calling UnloadAllExtensionsForTest here triggers a false-positive presubmit | 1412 // Calling UnloadAllExtensionsForTest here triggers a false-positive presubmit |
| 1408 // warning about calling test code in production. | 1413 // warning about calling test code in production. |
| 1409 UnloadAllExtensionsInternal(); | 1414 UnloadAllExtensionsInternal(); |
| 1410 component_loader_->LoadAll(); | 1415 component_loader_->LoadAll(); |
| 1411 extensions::InstalledLoader(this).LoadAllExtensions(); | 1416 extensions::InstalledLoader(this).LoadAllExtensions(); |
| 1412 // Don't call SetReadyAndNotifyListeners() since tests call this multiple | 1417 // Don't call SetReadyAndNotifyListeners() since tests call this multiple |
| 1413 // times. | 1418 // times. |
| 1414 } | 1419 } |
| 1415 | 1420 |
| 1416 void ExtensionService::SetReadyAndNotifyListeners() { | 1421 void ExtensionService::SetReadyAndNotifyListeners() { |
| 1417 const base::TimeTicks start_time = base::TimeTicks::Now(); | 1422 TRACE_EVENT0("browser,startup", |
| 1423 "ExtensionService::SetReadyAndNotifyListeners"); |
| 1424 SCOPED_UMA_HISTOGRAM_TIMER( |
| 1425 "Extensions.ExtensionServiceNotifyReadyListenersTime"); |
| 1426 |
| 1418 ready_->Signal(); | 1427 ready_->Signal(); |
| 1419 content::NotificationService::current()->Notify( | 1428 content::NotificationService::current()->Notify( |
| 1420 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, | 1429 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, |
| 1421 content::Source<Profile>(profile_), | 1430 content::Source<Profile>(profile_), |
| 1422 content::NotificationService::NoDetails()); | 1431 content::NotificationService::NoDetails()); |
| 1423 UMA_HISTOGRAM_TIMES("Extensions.ExtensionServiceNotifyReadyListenersTime", | |
| 1424 base::TimeTicks::Now() - start_time); | |
| 1425 } | 1432 } |
| 1426 | 1433 |
| 1427 void ExtensionService::OnLoadedInstalledExtensions() { | 1434 void ExtensionService::OnLoadedInstalledExtensions() { |
| 1428 if (updater_) | 1435 if (updater_) |
| 1429 updater_->Start(); | 1436 updater_->Start(); |
| 1430 | 1437 |
| 1431 OnBlacklistUpdated(); | 1438 OnBlacklistUpdated(); |
| 1432 } | 1439 } |
| 1433 | 1440 |
| 1434 void ExtensionService::AddExtension(const Extension* extension) { | 1441 void ExtensionService::AddExtension(const Extension* extension) { |
| (...skipping 1112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2547 } | 2554 } |
| 2548 | 2555 |
| 2549 void ExtensionService::OnProfileDestructionStarted() { | 2556 void ExtensionService::OnProfileDestructionStarted() { |
| 2550 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); | 2557 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); |
| 2551 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); | 2558 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); |
| 2552 it != ids_to_unload.end(); | 2559 it != ids_to_unload.end(); |
| 2553 ++it) { | 2560 ++it) { |
| 2554 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); | 2561 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); |
| 2555 } | 2562 } |
| 2556 } | 2563 } |
| OLD | NEW |