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 |