extension_service.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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 3// found in the LICENSE file. 4 5#include "chrome/browser/extensions/extension_service.h" 6 7#include <algorithm> 8#include <iterator> 9#include <set> 10 11#include "base/command_line.h" 12#include "base/metrics/histogram.h" 13#include "base/strings/string_number_conversions.h" 14#include "base/strings/stringprintf.h" 15#include "base/strings/utf_string_conversions.h" 16#include "base/threading/sequenced_worker_pool.h" 17#include "base/threading/thread_restrictions.h" 18#include "base/time/time.h" 19#include "chrome/browser/browser_process.h" 20#include "chrome/browser/chrome_notification_types.h" 21#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 22#include "chrome/browser/extensions/component_loader.h" 23#include "chrome/browser/extensions/crx_installer.h" 24#include "chrome/browser/extensions/data_deleter.h" 25#include "chrome/browser/extensions/extension_assets_manager.h" 26#include "chrome/browser/extensions/extension_disabled_ui.h" 27#include "chrome/browser/extensions/extension_error_controller.h" 28#include "chrome/browser/extensions/extension_install_ui.h" 29#include "chrome/browser/extensions/extension_special_storage_policy.h" 30#include "chrome/browser/extensions/extension_sync_service.h" 31#include "chrome/browser/extensions/extension_util.h" 32#include "chrome/browser/extensions/external_install_manager.h" 33#include "chrome/browser/extensions/external_provider_impl.h" 34#include "chrome/browser/extensions/install_verifier.h" 35#include "chrome/browser/extensions/installed_loader.h" 36#include "chrome/browser/extensions/pending_extension_manager.h" 37#include "chrome/browser/extensions/permissions_updater.h" 38#include "chrome/browser/extensions/shared_module_service.h" 39#include "chrome/browser/extensions/unpacked_installer.h" 40#include "chrome/browser/extensions/updater/extension_cache.h" 41#include "chrome/browser/extensions/updater/extension_downloader.h" 42#include "chrome/browser/extensions/updater/extension_updater.h" 43#include "chrome/browser/profiles/profile.h" 44#include "chrome/browser/signin/profile_identity_provider.h" 45#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 46#include "chrome/browser/signin/signin_manager_factory.h" 47#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 48#include "chrome/browser/ui/webui/favicon_source.h" 49#include "chrome/browser/ui/webui/ntp/thumbnail_source.h" 50#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" 51#include "chrome/browser/ui/webui/theme_source.h" 52#include "chrome/common/chrome_switches.h" 53#include "chrome/common/crash_keys.h" 54#include "chrome/common/extensions/extension_constants.h" 55#include "chrome/common/extensions/features/feature_channel.h" 56#include "chrome/common/extensions/manifest_url_handler.h" 57#include "chrome/common/pref_names.h" 58#include "chrome/common/url_constants.h" 59#include "components/crx_file/id_util.h" 60#include "components/signin/core/browser/signin_manager.h" 61#include "components/startup_metric_utils/startup_metric_utils.h" 62#include "content/public/browser/devtools_agent_host.h" 63#include "content/public/browser/notification_service.h" 64#include "content/public/browser/render_process_host.h" 65#include "content/public/browser/storage_partition.h" 66#include "extensions/browser/event_router.h" 67#include "extensions/browser/extension_host.h" 68#include "extensions/browser/extension_prefs.h" 69#include "extensions/browser/extension_registry.h" 70#include "extensions/browser/extension_system.h" 71#include "extensions/browser/install_flag.h" 72#include "extensions/browser/pref_names.h" 73#include "extensions/browser/runtime_data.h" 74#include "extensions/browser/uninstall_reason.h" 75#include "extensions/browser/update_observer.h" 76#include "extensions/common/extension_messages.h" 77#include "extensions/common/feature_switch.h" 78#include "extensions/common/file_util.h" 79#include "extensions/common/manifest_constants.h" 80#include "extensions/common/manifest_handlers/background_info.h" 81#include "extensions/common/one_shot_event.h" 82#include "extensions/common/permissions/permission_message_provider.h" 83#include "extensions/common/permissions/permissions_data.h" 84 85#if defined(OS_CHROMEOS) 86#include "chrome/browser/chromeos/extensions/install_limiter.h" 87#include "webkit/browser/fileapi/file_system_backend.h" 88#include "webkit/browser/fileapi/file_system_context.h" 89#endif 90 91using content::BrowserContext; 92using content::BrowserThread; 93using content::DevToolsAgentHost; 94using extensions::CrxInstaller; 95using extensions::Extension; 96using extensions::ExtensionDownloader; 97using extensions::ExtensionDownloaderDelegate; 98using extensions::ExtensionIdSet; 99using extensions::ExtensionInfo; 100using extensions::ExtensionRegistry; 101using extensions::ExtensionSet; 102using extensions::FeatureSwitch; 103using extensions::InstallVerifier; 104using extensions::ManagementPolicy; 105using extensions::Manifest; 106using extensions::PermissionMessage; 107using extensions::PermissionMessages; 108using extensions::PermissionSet; 109using extensions::SharedModuleInfo; 110using extensions::SharedModuleService; 111using extensions::UnloadedExtensionInfo; 112 113namespace errors = extensions::manifest_errors; 114 115namespace { 116 117// Wait this many seconds after an extensions becomes idle before updating it. 118const int kUpdateIdleDelay = 5; 119 120scoped_ptr<IdentityProvider> CreateWebstoreIdentityProvider(Profile* profile) { 121 return make_scoped_ptr<IdentityProvider>(new ProfileIdentityProvider( 122 SigninManagerFactory::GetForProfile(profile), 123 ProfileOAuth2TokenServiceFactory::GetForProfile(profile), 124 LoginUIServiceFactory::GetForProfile(profile))); 125} 126 127} // namespace 128 129// ExtensionService. 130 131void ExtensionService::CheckExternalUninstall(const std::string& id) { 132 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 133 134 // Check if the providers know about this extension. 135 extensions::ProviderCollection::const_iterator i; 136 for (i = external_extension_providers_.begin(); 137 i != external_extension_providers_.end(); ++i) { 138 DCHECK(i->get()->IsReady()); 139 if (i->get()->HasExtension(id)) 140 return; // Yup, known extension, don't uninstall. 141 } 142 143 // We get the list of external extensions to check from preferences. 144 // It is possible that an extension has preferences but is not loaded. 145 // For example, an extension that requires experimental permissions 146 // will not be loaded if the experimental command line flag is not used. 147 // In this case, do not uninstall. 148 if (!GetInstalledExtension(id)) { 149 // We can't call UninstallExtension with an unloaded/invalid 150 // extension ID. 151 LOG(WARNING) << "Attempted uninstallation of unloaded/invalid extension " 152 << "with id: " << id; 153 return; 154 } 155 UninstallExtension(id, 156 extensions::UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION, 157 base::Bind(&base::DoNothing), 158 NULL); 159} 160 161void ExtensionService::SetFileTaskRunnerForTesting( 162 base::SequencedTaskRunner* task_runner) { 163 file_task_runner_ = task_runner; 164} 165 166void ExtensionService::ClearProvidersForTesting() { 167 external_extension_providers_.clear(); 168} 169 170void ExtensionService::AddProviderForTesting( 171 extensions::ExternalProviderInterface* test_provider) { 172 CHECK(test_provider); 173 external_extension_providers_.push_back( 174 linked_ptr<extensions::ExternalProviderInterface>(test_provider)); 175} 176 177void ExtensionService::BlacklistExtensionForTest( 178 const std::string& extension_id) { 179 ExtensionIdSet blocked; 180 ExtensionIdSet unchanged; 181 blocked.insert(extension_id); 182 UpdateBlockedExtensions(blocked, unchanged); 183} 184 185bool ExtensionService::OnExternalExtensionUpdateUrlFound( 186 const std::string& id, 187 const std::string& install_parameter, 188 const GURL& update_url, 189 Manifest::Location location, 190 int creation_flags, 191 bool mark_acknowledged) { 192 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 193 CHECK(crx_file::id_util::IdIsValid(id)); 194 195 if (Manifest::IsExternalLocation(location)) { 196 // All extensions that are not user specific can be cached. 197 extensions::ExtensionCache::GetInstance()->AllowCaching(id); 198 } 199 200 const Extension* extension = GetExtensionById(id, true); 201 if (extension) { 202 // Already installed. Skip this install if the current location has 203 // higher priority than |location|. 204 Manifest::Location current = extension->location(); 205 if (current == Manifest::GetHigherPriorityLocation(current, location)) 206 return false; 207 // Otherwise, overwrite the current installation. 208 } 209 210 // Add |id| to the set of pending extensions. If it can not be added, 211 // then there is already a pending record from a higher-priority install 212 // source. In this case, signal that this extension will not be 213 // installed by returning false. 214 if (!pending_extension_manager()->AddFromExternalUpdateUrl( 215 id, 216 install_parameter, 217 update_url, 218 location, 219 creation_flags, 220 mark_acknowledged)) { 221 return false; 222 } 223 224 update_once_all_providers_are_ready_ = true; 225 return true; 226} 227 228// static 229// This function is used to uninstall an extension via sync. The LOG statements 230// within this function are used to inform the user if the uninstall cannot be 231// done. 232bool ExtensionService::UninstallExtensionHelper( 233 ExtensionService* extensions_service, 234 const std::string& extension_id, 235 extensions::UninstallReason reason) { 236 // We can't call UninstallExtension with an invalid extension ID. 237 if (!extensions_service->GetInstalledExtension(extension_id)) { 238 LOG(WARNING) << "Attempted uninstallation of non-existent extension with " 239 << "id: " << extension_id; 240 return false; 241 } 242 243 // The following call to UninstallExtension will not allow an uninstall of a 244 // policy-controlled extension. 245 base::string16 error; 246 if (!extensions_service->UninstallExtension( 247 extension_id, reason, base::Bind(&base::DoNothing), &error)) { 248 LOG(WARNING) << "Cannot uninstall extension with id " << extension_id 249 << ": " << error; 250 return false; 251 } 252 253 return true; 254} 255 256ExtensionService::ExtensionService(Profile* profile, 257 const CommandLine* command_line, 258 const base::FilePath& install_directory, 259 extensions::ExtensionPrefs* extension_prefs, 260 extensions::Blacklist* blacklist, 261 bool autoupdate_enabled, 262 bool extensions_enabled, 263 extensions::OneShotEvent* ready) 264 : extensions::Blacklist::Observer(blacklist), 265 profile_(profile), 266 system_(extensions::ExtensionSystem::Get(profile)), 267 extension_prefs_(extension_prefs), 268 blacklist_(blacklist), 269 extension_sync_service_(NULL), 270 registry_(extensions::ExtensionRegistry::Get(profile)), 271 pending_extension_manager_(profile), 272 install_directory_(install_directory), 273 extensions_enabled_(extensions_enabled), 274 show_extensions_prompts_(true), 275 install_updates_when_idle_(true), 276 ready_(ready), 277 update_once_all_providers_are_ready_(false), 278 browser_terminating_(false), 279 installs_delayed_for_gc_(false), 280 is_first_run_(false), 281 shared_module_service_(new extensions::SharedModuleService(profile_)) { 282 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 283 284 // Figure out if extension installation should be enabled. 285 if (extensions::ExtensionsBrowserClient::Get()->AreExtensionsDisabled( 286 *command_line, profile)) 287 extensions_enabled_ = false; 288 289 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 290 content::NotificationService::AllBrowserContextsAndSources()); 291 registrar_.Add(this, 292 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, 293 content::NotificationService::AllBrowserContextsAndSources()); 294 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 295 content::NotificationService::AllBrowserContextsAndSources()); 296 registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED, 297 content::NotificationService::AllBrowserContextsAndSources()); 298 registrar_.Add(this, 299 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED, 300 content::Source<Profile>(profile_)); 301 pref_change_registrar_.Init(profile->GetPrefs()); 302 base::Closure callback = 303 base::Bind(&ExtensionService::OnExtensionInstallPrefChanged, 304 base::Unretained(this)); 305 pref_change_registrar_.Add(extensions::pref_names::kInstallAllowList, 306 callback); 307 pref_change_registrar_.Add(extensions::pref_names::kInstallDenyList, 308 callback); 309 pref_change_registrar_.Add(extensions::pref_names::kAllowedTypes, callback); 310 311 // Set up the ExtensionUpdater 312 if (autoupdate_enabled) { 313 int update_frequency = extensions::kDefaultUpdateFrequencySeconds; 314 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { 315 base::StringToInt(command_line->GetSwitchValueASCII( 316 switches::kExtensionsUpdateFrequency), 317 &update_frequency); 318 } 319 updater_.reset(new extensions::ExtensionUpdater( 320 this, 321 extension_prefs, 322 profile->GetPrefs(), 323 profile, 324 update_frequency, 325 extensions::ExtensionCache::GetInstance(), 326 base::Bind(&ExtensionService::CreateExtensionDownloader, 327 base::Unretained(this)))); 328 } 329 330 component_loader_.reset( 331 new extensions::ComponentLoader(this, 332 profile->GetPrefs(), 333 g_browser_process->local_state(), 334 profile)); 335 336 if (extensions_enabled_) { 337 extensions::ExternalProviderImpl::CreateExternalProviders( 338 this, profile_, &external_extension_providers_); 339 } 340 341 // Set this as the ExtensionService for app sorting to ensure it causes syncs 342 // if required. 343 is_first_run_ = !extension_prefs_->SetAlertSystemFirstRun(); 344 345 error_controller_.reset( 346 new extensions::ExtensionErrorController(profile_, is_first_run_)); 347 external_install_manager_.reset( 348 new extensions::ExternalInstallManager(profile_, is_first_run_)); 349 350 extension_action_storage_manager_.reset( 351 new extensions::ExtensionActionStorageManager(profile_)); 352 353 // How long is the path to the Extensions directory? 354 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ExtensionRootPathLength", 355 install_directory_.value().length(), 0, 500, 100); 356} 357 358const ExtensionSet* ExtensionService::extensions() const { 359 return ®istry_->enabled_extensions(); 360} 361 362extensions::PendingExtensionManager* 363 ExtensionService::pending_extension_manager() { 364 return &pending_extension_manager_; 365} 366 367ExtensionService::~ExtensionService() { 368 // No need to unload extensions here because they are profile-scoped, and the 369 // profile is in the process of being deleted. 370 371 extensions::ProviderCollection::const_iterator i; 372 for (i = external_extension_providers_.begin(); 373 i != external_extension_providers_.end(); ++i) { 374 extensions::ExternalProviderInterface* provider = i->get(); 375 provider->ServiceShutdown(); 376 } 377} 378 379void ExtensionService::Shutdown() { 380 system_->management_policy()->UnregisterProvider( 381 shared_module_policy_provider_.get()); 382} 383 384const Extension* ExtensionService::GetExtensionById( 385 const std::string& id, bool include_disabled) const { 386 int include_mask = ExtensionRegistry::ENABLED; 387 if (include_disabled) { 388 // Include blacklisted extensions here because there are hundreds of 389 // callers of this function, and many might assume that this includes those 390 // that have been disabled due to blacklisting. 391 include_mask |= ExtensionRegistry::DISABLED | 392 ExtensionRegistry::BLACKLISTED; 393 } 394 return registry_->GetExtensionById(id, include_mask); 395} 396 397void ExtensionService::Init() { 398 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 399 400 base::Time begin_time = base::Time::Now(); 401 402 DCHECK(!is_ready()); // Can't redo init. 403 DCHECK_EQ(registry_->enabled_extensions().size(), 0u); 404 405 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 406 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) || 407 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) { 408 // The sole purpose of this launch is to install a new extension from CWS 409 // and immediately terminate: loading already installed extensions is 410 // unnecessary and may interfere with the inline install dialog (e.g. if an 411 // extension listens to onStartup and opens a window). 412 SetReadyAndNotifyListeners(); 413 } else { 414 // LoadAllExtensions() calls OnLoadedInstalledExtensions(). 415 component_loader_->LoadAll(); 416 extensions::InstalledLoader(this).LoadAllExtensions(); 417 418 // Attempt to re-enable extensions whose only disable reason is reloading. 419 std::vector<std::string> extensions_to_enable; 420 const ExtensionSet& disabled_extensions = registry_->disabled_extensions(); 421 for (ExtensionSet::const_iterator iter = disabled_extensions.begin(); 422 iter != disabled_extensions.end(); ++iter) { 423 const Extension* e = iter->get(); 424 if (extension_prefs_->GetDisableReasons(e->id()) == 425 Extension::DISABLE_RELOAD) { 426 extensions_to_enable.push_back(e->id()); 427 } 428 } 429 for (std::vector<std::string>::iterator it = extensions_to_enable.begin(); 430 it != extensions_to_enable.end(); ++it) { 431 EnableExtension(*it); 432 } 433 434 // Finish install (if possible) of extensions that were still delayed while 435 // the browser was shut down. 436 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info( 437 extension_prefs_->GetAllDelayedInstallInfo()); 438 for (size_t i = 0; i < delayed_info->size(); ++i) { 439 ExtensionInfo* info = delayed_info->at(i).get(); 440 scoped_refptr<const Extension> extension(NULL); 441 if (info->extension_manifest) { 442 std::string error; 443 extension = Extension::Create( 444 info->extension_path, 445 info->extension_location, 446 *info->extension_manifest, 447 extension_prefs_->GetDelayedInstallCreationFlags( 448 info->extension_id), 449 info->extension_id, 450 &error); 451 if (extension.get()) 452 delayed_installs_.Insert(extension); 453 } 454 } 455 MaybeFinishDelayedInstallations(); 456 457 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2( 458 extension_prefs_->GetAllDelayedInstallInfo()); 459 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad", 460 delayed_info2->size() - delayed_info->size()); 461 462 SetReadyAndNotifyListeners(); 463 464 // TODO(erikkay) this should probably be deferred to a future point 465 // rather than running immediately at startup. 466 CheckForExternalUpdates(); 467 468 LoadGreylistFromPrefs(); 469 } 470 471 UMA_HISTOGRAM_TIMES("Extensions.ExtensionServiceInitTime", 472 base::Time::Now() - begin_time); 473} 474 475void ExtensionService::LoadGreylistFromPrefs() { 476 scoped_ptr<ExtensionSet> all_extensions = 477 registry_->GenerateInstalledExtensionsSet(); 478 479 for (ExtensionSet::const_iterator it = all_extensions->begin(); 480 it != all_extensions->end(); ++it) { 481 extensions::BlacklistState state = 482 extension_prefs_->GetExtensionBlacklistState((*it)->id()); 483 if (state == extensions::BLACKLISTED_SECURITY_VULNERABILITY || 484 state == extensions::BLACKLISTED_POTENTIALLY_UNWANTED || 485 state == extensions::BLACKLISTED_CWS_POLICY_VIOLATION) 486 greylist_.Insert(*it); 487 } 488} 489 490bool ExtensionService::UpdateExtension(const std::string& id, 491 const base::FilePath& extension_path, 492 bool file_ownership_passed, 493 CrxInstaller** out_crx_installer) { 494 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 495 if (browser_terminating_) { 496 LOG(WARNING) << "Skipping UpdateExtension due to browser shutdown"; 497 // Leak the temp file at extension_path. We don't want to add to the disk 498 // I/O burden at shutdown, we can't rely on the I/O completing anyway, and 499 // the file is in the OS temp directory which should be cleaned up for us. 500 return false; 501 } 502 503 const extensions::PendingExtensionInfo* pending_extension_info = 504 pending_extension_manager()->GetById(id); 505 506 const Extension* extension = GetInstalledExtension(id); 507 if (!pending_extension_info && !extension) { 508 LOG(WARNING) << "Will not update extension " << id 509 << " because it is not installed or pending"; 510 // Delete extension_path since we're not creating a CrxInstaller 511 // that would do it for us. 512 if (!GetFileTaskRunner()->PostTask( 513 FROM_HERE, 514 base::Bind( 515 &extensions::file_util::DeleteFile, extension_path, false))) 516 NOTREACHED(); 517 518 return false; 519 } 520 521 // We want a silent install only for non-pending extensions and 522 // pending extensions that have install_silently set. 523 scoped_ptr<ExtensionInstallPrompt> client; 524 if (pending_extension_info && !pending_extension_info->install_silently()) 525 client.reset(ExtensionInstallUI::CreateInstallPromptWithProfile(profile_)); 526 527 scoped_refptr<CrxInstaller> installer( 528 CrxInstaller::Create(this, client.Pass())); 529 installer->set_expected_id(id); 530 int creation_flags = Extension::NO_FLAGS; 531 if (pending_extension_info) { 532 installer->set_install_source(pending_extension_info->install_source()); 533 if (pending_extension_info->install_silently()) 534 installer->set_allow_silent_install(true); 535 if (pending_extension_info->remote_install()) 536 installer->set_grant_permissions(false); 537 creation_flags = pending_extension_info->creation_flags(); 538 if (pending_extension_info->mark_acknowledged()) 539 external_install_manager_->AcknowledgeExternalExtension(id); 540 } else if (extension) { 541 installer->set_install_source(extension->location()); 542 } 543 // If the extension was installed from or has migrated to the webstore, or 544 // its auto-update URL is from the webstore, treat it as a webstore install. 545 // Note that we ignore some older extensions with blank auto-update URLs 546 // because we are mostly concerned with restrictions on NaCl extensions, 547 // which are newer. 548 if ((extension && extension->from_webstore()) || 549 (extension && extensions::ManifestURL::UpdatesFromGallery(extension)) || 550 (!extension && extension_urls::IsWebstoreUpdateUrl( 551 pending_extension_info->update_url()))) { 552 creation_flags |= Extension::FROM_WEBSTORE; 553 } 554 555 // Bookmark apps being updated is kind of a contradiction, but that's because 556 // we mark the default apps as bookmark apps, and they're hosted in the web 557 // store, thus they can get updated. See http://crbug.com/101605 for more 558 // details. 559 if (extension && extension->from_bookmark()) 560 creation_flags |= Extension::FROM_BOOKMARK; 561 562 if (extension && extension->was_installed_by_default()) 563 creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT; 564 565 if (extension && extension->was_installed_by_oem()) 566 creation_flags |= Extension::WAS_INSTALLED_BY_OEM; 567 568 if (extension && extension->was_installed_by_custodian()) 569 creation_flags |= Extension::WAS_INSTALLED_BY_CUSTODIAN; 570 571 if (extension) { 572 installer->set_is_ephemeral(extension_prefs_->IsEphemeralApp(id)); 573 installer->set_do_not_sync(extension_prefs_->DoNotSync(id)); 574 } 575 576 installer->set_creation_flags(creation_flags); 577 578 installer->set_delete_source(file_ownership_passed); 579 installer->set_install_cause(extension_misc::INSTALL_CAUSE_UPDATE); 580 installer->InstallCrx(extension_path); 581 582 if (out_crx_installer) 583 *out_crx_installer = installer.get(); 584 585 return true; 586} 587 588scoped_ptr<ExtensionDownloader> ExtensionService::CreateExtensionDownloader( 589 ExtensionDownloaderDelegate* delegate) { 590 scoped_ptr<ExtensionDownloader> downloader; 591 scoped_ptr<IdentityProvider> identity_provider = 592 CreateWebstoreIdentityProvider(profile_); 593 downloader.reset(new ExtensionDownloader( 594 delegate, 595 profile_->GetRequestContext())); 596 downloader->SetWebstoreIdentityProvider(identity_provider.Pass()); 597 return downloader.Pass(); 598} 599 600void ExtensionService::ReloadExtensionImpl( 601 // "transient" because the process of reloading may cause the reference 602 // to become invalid. Instead, use |extension_id|, a copy. 603 const std::string& transient_extension_id, 604 bool be_noisy) { 605 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 606 607 // If the extension is already reloading, don't reload again. 608 if (extension_prefs_->GetDisableReasons(transient_extension_id) & 609 Extension::DISABLE_RELOAD) { 610 return; 611 } 612 613 // Ignore attempts to reload a blacklisted extension. Sometimes this can 614 // happen in a convoluted reload sequence triggered by the termination of a 615 // blacklisted extension and a naive attempt to reload it. For an example see 616 // http://crbug.com/373842. 617 if (registry_->blacklisted_extensions().Contains(transient_extension_id)) 618 return; 619 620 base::FilePath path; 621 622 std::string extension_id = transient_extension_id; 623 const Extension* transient_current_extension = 624 GetExtensionById(extension_id, false); 625 626 // Disable the extension if it's loaded. It might not be loaded if it crashed. 627 if (transient_current_extension) { 628 // If the extension has an inspector open for its background page, detach 629 // the inspector and hang onto a cookie for it, so that we can reattach 630 // later. 631 // TODO(yoz): this is not incognito-safe! 632 extensions::ProcessManager* manager = system_->process_manager(); 633 extensions::ExtensionHost* host = 634 manager->GetBackgroundHostForExtension(extension_id); 635 if (host && DevToolsAgentHost::HasFor(host->host_contents())) { 636 // Look for an open inspector for the background page. 637 scoped_refptr<DevToolsAgentHost> agent_host = 638 DevToolsAgentHost::GetOrCreateFor(host->host_contents()); 639 agent_host->DisconnectWebContents(); 640 orphaned_dev_tools_[extension_id] = agent_host; 641 } 642 643 path = transient_current_extension->path(); 644 // BeingUpgraded is set back to false when the extension is added. 645 system_->runtime_data()->SetBeingUpgraded(transient_current_extension, 646 true); 647 DisableExtension(extension_id, Extension::DISABLE_RELOAD); 648 reloading_extensions_.insert(extension_id); 649 } else { 650 std::map<std::string, base::FilePath>::const_iterator iter = 651 unloaded_extension_paths_.find(extension_id); 652 if (iter == unloaded_extension_paths_.end()) { 653 return; 654 } 655 path = unloaded_extension_paths_[extension_id]; 656 } 657 658 transient_current_extension = NULL; 659 660 if (delayed_installs_.Contains(extension_id)) { 661 FinishDelayedInstallation(extension_id); 662 return; 663 } 664 665 // If we're reloading a component extension, use the component extension 666 // loader's reloader. 667 if (component_loader_->Exists(extension_id)) { 668 component_loader_->Reload(extension_id); 669 return; 670 } 671 672 // Check the installed extensions to see if what we're reloading was already 673 // installed. 674 scoped_ptr<ExtensionInfo> installed_extension( 675 extension_prefs_->GetInstalledExtensionInfo(extension_id)); 676 if (installed_extension.get() && 677 installed_extension->extension_manifest.get()) { 678 extensions::InstalledLoader(this).Load(*installed_extension, false); 679 } else { 680 // Otherwise, the extension is unpacked (location LOAD). 681 // We should always be able to remember the extension's path. If it's not in 682 // the map, someone failed to update |unloaded_extension_paths_|. 683 CHECK(!path.empty()); 684 scoped_refptr<extensions::UnpackedInstaller> unpacked_installer = 685 extensions::UnpackedInstaller::Create(this); 686 unpacked_installer->set_be_noisy_on_failure(be_noisy); 687 unpacked_installer->Load(path); 688 } 689} 690 691void ExtensionService::ReloadExtension(const std::string& extension_id) { 692 ReloadExtensionImpl(extension_id, true); // be_noisy 693} 694 695void ExtensionService::ReloadExtensionWithQuietFailure( 696 const std::string& extension_id) { 697 ReloadExtensionImpl(extension_id, false); // be_noisy 698} 699 700bool ExtensionService::UninstallExtension( 701 // "transient" because the process of uninstalling may cause the reference 702 // to become invalid. Instead, use |extenson->id()|. 703 const std::string& transient_extension_id, 704 extensions::UninstallReason reason, 705 const base::Closure& deletion_done_callback, 706 base::string16* error) { 707 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 708 709 scoped_refptr<const Extension> extension = 710 GetInstalledExtension(transient_extension_id); 711 712 // Callers should not send us nonexistent extensions. 713 CHECK(extension.get()); 714 715 // Policy change which triggers an uninstall will always set 716 // |external_uninstall| to true so this is the only way to uninstall 717 // managed extensions. 718 // Shared modules being uninstalled will also set |external_uninstall| to true 719 // so that we can guarantee users don't uninstall a shared module. 720 // (crbug.com/273300) 721 // TODO(rdevlin.cronin): This is probably not right. We should do something 722 // else, like include an enum IS_INTERNAL_UNINSTALL or IS_USER_UNINSTALL so 723 // we don't do this. 724 bool external_uninstall = 725 (reason == extensions::UNINSTALL_REASON_INTERNAL_MANAGEMENT) || 726 (reason == extensions::UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION) || 727 (reason == extensions::UNINSTALL_REASON_ORPHANED_SHARED_MODULE) || 728 (reason == extensions::UNINSTALL_REASON_SYNC && 729 extension->was_installed_by_custodian()); 730 if (!external_uninstall && 731 !system_->management_policy()->UserMayModifySettings( 732 extension.get(), error)) { 733 content::NotificationService::current()->Notify( 734 extensions::NOTIFICATION_EXTENSION_UNINSTALL_NOT_ALLOWED, 735 content::Source<Profile>(profile_), 736 content::Details<const Extension>(extension.get())); 737 return false; 738 } 739 740 syncer::SyncChange sync_change; 741 if (extension_sync_service_) { 742 sync_change = extension_sync_service_->PrepareToSyncUninstallExtension( 743 extension.get(), is_ready()); 744 } 745 746 system_->install_verifier()->Remove(extension->id()); 747 748 UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType", 749 extension->GetType(), 100); 750 RecordPermissionMessagesHistogram(extension.get(), 751 "Extensions.Permissions_Uninstall2"); 752 753 // Unload before doing more cleanup to ensure that nothing is hanging on to 754 // any of these resources. 755 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UNINSTALL); 756 757 // Tell the backend to start deleting installed extensions on the file thread. 758 if (!Manifest::IsUnpackedLocation(extension->location())) { 759 if (!GetFileTaskRunner()->PostTask( 760 FROM_HERE, 761 base::Bind(&ExtensionService::UninstallExtensionOnFileThread, 762 extension->id(), 763 profile_, 764 install_directory_, 765 extension->path()))) 766 NOTREACHED(); 767 } 768 769 extensions::DataDeleter::StartDeleting( 770 profile_, extension.get(), deletion_done_callback); 771 772 UntrackTerminatedExtension(extension->id()); 773 774 // Notify interested parties that we've uninstalled this extension. 775 content::NotificationService::current()->Notify( 776 extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED, 777 content::Source<Profile>(profile_), 778 content::Details<const Extension>(extension.get())); 779 ExtensionRegistry::Get(profile_) 780 ->TriggerOnUninstalled(extension.get(), reason); 781 782 if (extension_sync_service_) { 783 extension_sync_service_->ProcessSyncUninstallExtension(extension->id(), 784 sync_change); 785 } 786 787 delayed_installs_.Remove(extension->id()); 788 789 extension_prefs_->OnExtensionUninstalled( 790 extension->id(), extension->location(), external_uninstall); 791 792 // Track the uninstallation. 793 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2); 794 795 return true; 796} 797 798// static 799void ExtensionService::UninstallExtensionOnFileThread( 800 const std::string& id, 801 Profile* profile, 802 const base::FilePath& install_dir, 803 const base::FilePath& extension_path) { 804 extensions::ExtensionAssetsManager* assets_manager = 805 extensions::ExtensionAssetsManager::GetInstance(); 806 assets_manager->UninstallExtension(id, profile, install_dir, extension_path); 807} 808 809bool ExtensionService::IsExtensionEnabled( 810 const std::string& extension_id) const { 811 if (registry_->enabled_extensions().Contains(extension_id) || 812 registry_->terminated_extensions().Contains(extension_id)) { 813 return true; 814 } 815 816 if (registry_->disabled_extensions().Contains(extension_id) || 817 registry_->blacklisted_extensions().Contains(extension_id)) { 818 return false; 819 } 820 821 // If the extension hasn't been loaded yet, check the prefs for it. Assume 822 // enabled unless otherwise noted. 823 return !extension_prefs_->IsExtensionDisabled(extension_id) && 824 !extension_prefs_->IsExtensionBlacklisted(extension_id) && 825 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); 826} 827 828void ExtensionService::EnableExtension(const std::string& extension_id) { 829 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 830 831 if (IsExtensionEnabled(extension_id)) 832 return; 833 const Extension* extension = 834 registry_->disabled_extensions().GetByID(extension_id); 835 836 ManagementPolicy* policy = system_->management_policy(); 837 if (extension && policy->MustRemainDisabled(extension, NULL, NULL)) { 838 UMA_HISTOGRAM_COUNTS_100("Extensions.EnableDeniedByPolicy", 1); 839 return; 840 } 841 842 extension_prefs_->SetExtensionState(extension_id, Extension::ENABLED); 843 extension_prefs_->ClearDisableReasons(extension_id); 844 845 // This can happen if sync enables an extension that is not 846 // installed yet. 847 if (!extension) 848 return; 849 850 // Move it over to the enabled list. 851 registry_->AddEnabled(make_scoped_refptr(extension)); 852 registry_->RemoveDisabled(extension->id()); 853 854 NotifyExtensionLoaded(extension); 855 856 // Notify listeners that the extension was enabled. 857 content::NotificationService::current()->Notify( 858 extensions::NOTIFICATION_EXTENSION_ENABLED, 859 content::Source<Profile>(profile_), 860 content::Details<const Extension>(extension)); 861 862 if (extension_sync_service_) 863 extension_sync_service_->SyncEnableExtension(*extension); 864} 865 866void ExtensionService::DisableExtension( 867 const std::string& extension_id, 868 Extension::DisableReason disable_reason) { 869 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 870 871 // The extension may have been disabled already. Just add a disable reason. 872 if (!IsExtensionEnabled(extension_id)) { 873 extension_prefs_->AddDisableReason(extension_id, disable_reason); 874 return; 875 } 876 877 const Extension* extension = GetInstalledExtension(extension_id); 878 // |extension| can be NULL if sync disables an extension that is not 879 // installed yet. 880 // EXTERNAL_COMPONENT extensions are not generally modifiable by users, but 881 // can be uninstalled by the browser if the user sets extension-specific 882 // preferences. 883 if (extension && 884 disable_reason != Extension::DISABLE_RELOAD && 885 !system_->management_policy()->UserMayModifySettings(extension, NULL) && 886 extension->location() != Manifest::EXTERNAL_COMPONENT) { 887 return; 888 } 889 890 extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED); 891 extension_prefs_->AddDisableReason(extension_id, disable_reason); 892 893 int include_mask = 894 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::DISABLED; 895 extension = registry_->GetExtensionById(extension_id, include_mask); 896 if (!extension) 897 return; 898 899 // The extension is either enabled or terminated. 900 DCHECK(registry_->enabled_extensions().Contains(extension->id()) || 901 registry_->terminated_extensions().Contains(extension->id())); 902 903 // Move it over to the disabled list. Don't send a second unload notification 904 // for terminated extensions being disabled. 905 registry_->AddDisabled(make_scoped_refptr(extension)); 906 if (registry_->enabled_extensions().Contains(extension->id())) { 907 registry_->RemoveEnabled(extension->id()); 908 NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::REASON_DISABLE); 909 } else { 910 registry_->RemoveTerminated(extension->id()); 911 } 912 913 if (extension_sync_service_) 914 extension_sync_service_->SyncDisableExtension(*extension); 915} 916 917void ExtensionService::DisableUserExtensions( 918 const std::vector<std::string>& except_ids) { 919 extensions::ManagementPolicy* management_policy = 920 system_->management_policy(); 921 extensions::ExtensionList to_disable; 922 923 const ExtensionSet& enabled_set = registry_->enabled_extensions(); 924 for (ExtensionSet::const_iterator extension = enabled_set.begin(); 925 extension != enabled_set.end(); ++extension) { 926 if (management_policy->UserMayModifySettings(extension->get(), NULL)) 927 to_disable.push_back(*extension); 928 } 929 const ExtensionSet& terminated_set = registry_->terminated_extensions(); 930 for (ExtensionSet::const_iterator extension = terminated_set.begin(); 931 extension != terminated_set.end(); ++extension) { 932 if (management_policy->UserMayModifySettings(extension->get(), NULL)) 933 to_disable.push_back(*extension); 934 } 935 936 for (extensions::ExtensionList::const_iterator extension = to_disable.begin(); 937 extension != to_disable.end(); ++extension) { 938 if ((*extension)->was_installed_by_default() && 939 extension_urls::IsWebstoreUpdateUrl( 940 extensions::ManifestURL::GetUpdateURL(*extension))) 941 continue; 942 const std::string& id = (*extension)->id(); 943 if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id)) 944 DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION); 945 } 946} 947 948void ExtensionService::GrantPermissionsAndEnableExtension( 949 const Extension* extension) { 950 GrantPermissions(extension); 951 RecordPermissionMessagesHistogram(extension, 952 "Extensions.Permissions_ReEnable2"); 953 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); 954 EnableExtension(extension->id()); 955} 956 957void ExtensionService::GrantPermissions(const Extension* extension) { 958 CHECK(extension); 959 extensions::PermissionsUpdater(profile()).GrantActivePermissions(extension); 960} 961 962// static 963void ExtensionService::RecordPermissionMessagesHistogram( 964 const Extension* extension, const char* histogram) { 965 // Since this is called from multiple sources, and since the histogram macros 966 // use statics, we need to manually lookup the histogram ourselves. 967 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( 968 histogram, 969 1, 970 PermissionMessage::kEnumBoundary, 971 PermissionMessage::kEnumBoundary + 1, 972 base::HistogramBase::kUmaTargetedHistogramFlag); 973 974 PermissionMessages permissions = 975 extension->permissions_data()->GetPermissionMessages(); 976 if (permissions.empty()) { 977 counter->Add(PermissionMessage::kNone); 978 } else { 979 for (PermissionMessages::iterator it = permissions.begin(); 980 it != permissions.end(); ++it) 981 counter->Add(it->id()); 982 } 983} 984 985void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { 986 // The URLRequestContexts need to be first to know that the extension 987 // was loaded, otherwise a race can arise where a renderer that is created 988 // for the extension may try to load an extension URL with an extension id 989 // that the request context doesn't yet know about. The profile is responsible 990 // for ensuring its URLRequestContexts appropriately discover the loaded 991 // extension. 992 system_->RegisterExtensionWithRequestContexts(extension); 993 994 // Tell renderers about the new extension, unless it's a theme (renderers 995 // don't need to know about themes). 996 if (!extension->is_theme()) { 997 for (content::RenderProcessHost::iterator i( 998 content::RenderProcessHost::AllHostsIterator()); 999 !i.IsAtEnd(); i.Advance()) { 1000 content::RenderProcessHost* host = i.GetCurrentValue(); 1001 Profile* host_profile = 1002 Profile::FromBrowserContext(host->GetBrowserContext()); 1003 if (host_profile->GetOriginalProfile() == 1004 profile_->GetOriginalProfile()) { 1005 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions( 1006 1, ExtensionMsg_Loaded_Params(extension)); 1007 host->Send( 1008 new ExtensionMsg_Loaded(loaded_extensions)); 1009 } 1010 } 1011 } 1012 1013 // Tell subsystems that use the EXTENSION_LOADED notification about the new 1014 // extension. 1015 // 1016 // NOTE: It is important that this happen after notifying the renderers about 1017 // the new extensions so that if we navigate to an extension URL in 1018 // ExtensionRegistryObserver::OnLoaded or 1019 // NOTIFICATION_EXTENSION_LOADED_DEPRECATED, the 1020 // renderer is guaranteed to know about it. 1021 registry_->TriggerOnLoaded(extension); 1022 1023 content::NotificationService::current()->Notify( 1024 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 1025 content::Source<Profile>(profile_), 1026 content::Details<const Extension>(extension)); 1027 1028 // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a 1029 // BrowserContextKeyedService and use ExtensionRegistryObserver. 1030 profile_->GetExtensionSpecialStoragePolicy()-> 1031 GrantRightsForExtension(extension); 1032 1033 // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't 1034 // work properly multi-profile. Besides which, it should be using 1035 // ExtensionRegistryObserver. See http://crbug.com/355029. 1036 UpdateActiveExtensionsInCrashReporter(); 1037 1038 const extensions::PermissionsData* permissions_data = 1039 extension->permissions_data(); 1040 1041 // If the extension has permission to load chrome://favicon/ resources we need 1042 // to make sure that the FaviconSource is registered with the 1043 // ChromeURLDataManager. 1044 if (permissions_data->HasHostPermission(GURL(chrome::kChromeUIFaviconURL))) { 1045 FaviconSource* favicon_source = new FaviconSource(profile_, 1046 FaviconSource::FAVICON); 1047 content::URLDataSource::Add(profile_, favicon_source); 1048 } 1049 1050 // Same for chrome://theme/ resources. 1051 if (permissions_data->HasHostPermission(GURL(chrome::kChromeUIThemeURL))) { 1052 ThemeSource* theme_source = new ThemeSource(profile_); 1053 content::URLDataSource::Add(profile_, theme_source); 1054 } 1055 1056 // Same for chrome://thumb/ resources. 1057 if (permissions_data->HasHostPermission( 1058 GURL(chrome::kChromeUIThumbnailURL))) { 1059 ThumbnailSource* thumbnail_source = new ThumbnailSource(profile_, false); 1060 content::URLDataSource::Add(profile_, thumbnail_source); 1061 } 1062} 1063 1064void ExtensionService::NotifyExtensionUnloaded( 1065 const Extension* extension, 1066 UnloadedExtensionInfo::Reason reason) { 1067 UnloadedExtensionInfo details(extension, reason); 1068 1069 registry_->TriggerOnUnloaded(extension, reason); 1070 1071 content::NotificationService::current()->Notify( 1072 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 1073 content::Source<Profile>(profile_), 1074 content::Details<UnloadedExtensionInfo>(&details)); 1075 1076 for (content::RenderProcessHost::iterator i( 1077 content::RenderProcessHost::AllHostsIterator()); 1078 !i.IsAtEnd(); i.Advance()) { 1079 content::RenderProcessHost* host = i.GetCurrentValue(); 1080 Profile* host_profile = 1081 Profile::FromBrowserContext(host->GetBrowserContext()); 1082 if (host_profile->GetOriginalProfile() == profile_->GetOriginalProfile()) 1083 host->Send(new ExtensionMsg_Unloaded(extension->id())); 1084 } 1085 1086 system_->UnregisterExtensionWithRequestContexts(extension->id(), reason); 1087 1088 // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a 1089 // BrowserContextKeyedService and use ExtensionRegistryObserver. 1090 profile_->GetExtensionSpecialStoragePolicy()-> 1091 RevokeRightsForExtension(extension); 1092 1093#if defined(OS_CHROMEOS) 1094 // Revoke external file access for the extension from its file system context. 1095 // It is safe to access the extension's storage partition at this point. The 1096 // storage partition may get destroyed only after the extension gets unloaded. 1097 GURL site = 1098 extensions::util::GetSiteForExtensionId(extension->id(), profile_); 1099 storage::FileSystemContext* filesystem_context = 1100 BrowserContext::GetStoragePartitionForSite(profile_, site) 1101 ->GetFileSystemContext(); 1102 if (filesystem_context && filesystem_context->external_backend()) { 1103 filesystem_context->external_backend()-> 1104 RevokeAccessForExtension(extension->id()); 1105 } 1106#endif 1107 1108 // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't 1109 // work properly multi-profile. Besides which, it should be using 1110 // ExtensionRegistryObserver::OnExtensionLoaded. See http://crbug.com/355029. 1111 UpdateActiveExtensionsInCrashReporter(); 1112} 1113 1114content::BrowserContext* ExtensionService::GetBrowserContext() const { 1115 // Implemented in the .cc file to avoid adding a profile.h dependency to 1116 // extension_service.h. 1117 return profile_; 1118} 1119 1120bool ExtensionService::is_ready() { 1121 return ready_->is_signaled(); 1122} 1123 1124base::SequencedTaskRunner* ExtensionService::GetFileTaskRunner() { 1125 if (file_task_runner_.get()) 1126 return file_task_runner_.get(); 1127 1128 // We should be able to interrupt any part of extension install process during 1129 // shutdown. SKIP_ON_SHUTDOWN ensures that not started extension install tasks 1130 // will be ignored/deleted while we will block on started tasks. 1131 std::string token("ext_install-"); 1132 token.append(profile_->GetPath().AsUTF8Unsafe()); 1133 file_task_runner_ = BrowserThread::GetBlockingPool()-> 1134 GetSequencedTaskRunnerWithShutdownBehavior( 1135 BrowserThread::GetBlockingPool()->GetNamedSequenceToken(token), 1136 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 1137 return file_task_runner_.get(); 1138} 1139 1140void ExtensionService::CheckManagementPolicy() { 1141 std::vector<std::string> to_unload; 1142 std::map<std::string, Extension::DisableReason> to_disable; 1143 1144 // Loop through the extensions list, finding extensions we need to unload or 1145 // disable. 1146 const ExtensionSet& extensions = registry_->enabled_extensions(); 1147 for (ExtensionSet::const_iterator iter = extensions.begin(); 1148 iter != extensions.end(); ++iter) { 1149 const Extension* extension = (iter->get()); 1150 if (!system_->management_policy()->UserMayLoad(extension, NULL)) 1151 to_unload.push_back(extension->id()); 1152 Extension::DisableReason disable_reason = Extension::DISABLE_NONE; 1153 if (system_->management_policy()->MustRemainDisabled( 1154 extension, &disable_reason, NULL)) 1155 to_disable[extension->id()] = disable_reason; 1156 } 1157 1158 for (size_t i = 0; i < to_unload.size(); ++i) 1159 UnloadExtension(to_unload[i], UnloadedExtensionInfo::REASON_DISABLE); 1160 1161 for (std::map<std::string, Extension::DisableReason>::const_iterator i = 1162 to_disable.begin(); i != to_disable.end(); ++i) 1163 DisableExtension(i->first, i->second); 1164} 1165 1166void ExtensionService::CheckForUpdatesSoon() { 1167 // This can legitimately happen in unit tests. 1168 if (!updater_.get()) 1169 return; 1170 1171 if (AreAllExternalProvidersReady()) { 1172 updater_->CheckSoon(); 1173 } else { 1174 // Sync can start updating before all the external providers are ready 1175 // during startup. Start the update as soon as those providers are ready, 1176 // but not before. 1177 update_once_all_providers_are_ready_ = true; 1178 } 1179} 1180 1181// Some extensions will autoupdate themselves externally from Chrome. These 1182// are typically part of some larger client application package. To support 1183// these, the extension will register its location in the the preferences file 1184// (and also, on Windows, in the registry) and this code will periodically 1185// check that location for a .crx file, which it will then install locally if 1186// a new version is available. 1187// Errors are reported through ExtensionErrorReporter. Succcess is not 1188// reported. 1189void ExtensionService::CheckForExternalUpdates() { 1190 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1191 1192 // Note that this installation is intentionally silent (since it didn't 1193 // go through the front-end). Extensions that are registered in this 1194 // way are effectively considered 'pre-bundled', and so implicitly 1195 // trusted. In general, if something has HKLM or filesystem access, 1196 // they could install an extension manually themselves anyway. 1197 1198 // Ask each external extension provider to give us a call back for each 1199 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. 1200 extensions::ProviderCollection::const_iterator i; 1201 for (i = external_extension_providers_.begin(); 1202 i != external_extension_providers_.end(); ++i) { 1203 extensions::ExternalProviderInterface* provider = i->get(); 1204 provider->VisitRegisteredExtension(); 1205 } 1206 1207 // Do any required work that we would have done after completion of all 1208 // providers. 1209 if (external_extension_providers_.empty()) 1210 OnAllExternalProvidersReady(); 1211} 1212 1213void ExtensionService::OnExternalProviderReady( 1214 const extensions::ExternalProviderInterface* provider) { 1215 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1216 CHECK(provider->IsReady()); 1217 1218 // An external provider has finished loading. We only take action 1219 // if all of them are finished. So we check them first. 1220 if (AreAllExternalProvidersReady()) 1221 OnAllExternalProvidersReady(); 1222} 1223 1224bool ExtensionService::AreAllExternalProvidersReady() const { 1225 extensions::ProviderCollection::const_iterator i; 1226 for (i = external_extension_providers_.begin(); 1227 i != external_extension_providers_.end(); ++i) { 1228 if (!i->get()->IsReady()) 1229 return false; 1230 } 1231 return true; 1232} 1233 1234void ExtensionService::OnAllExternalProvidersReady() { 1235 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1236 base::TimeDelta elapsed = base::Time::Now() - profile_->GetStartTime(); 1237 UMA_HISTOGRAM_TIMES("Extension.ExternalProvidersReadyAfter", elapsed); 1238 1239 // Install any pending extensions. 1240 if (update_once_all_providers_are_ready_ && updater()) { 1241 update_once_all_providers_are_ready_ = false; 1242 extensions::ExtensionUpdater::CheckParams params; 1243 params.callback = external_updates_finished_callback_; 1244 updater()->CheckNow(params); 1245 } 1246 1247 // Uninstall all the unclaimed extensions. 1248 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> extensions_info( 1249 extension_prefs_->GetInstalledExtensionsInfo()); 1250 for (size_t i = 0; i < extensions_info->size(); ++i) { 1251 ExtensionInfo* info = extensions_info->at(i).get(); 1252 if (Manifest::IsExternalLocation(info->extension_location)) 1253 CheckExternalUninstall(info->extension_id); 1254 } 1255 1256 error_controller_->ShowErrorIfNeeded(); 1257 1258 external_install_manager_->UpdateExternalExtensionAlert(); 1259} 1260 1261void ExtensionService::UnloadExtension( 1262 const std::string& extension_id, 1263 UnloadedExtensionInfo::Reason reason) { 1264 // Make sure the extension gets deleted after we return from this function. 1265 int include_mask = 1266 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::TERMINATED; 1267 scoped_refptr<const Extension> extension( 1268 registry_->GetExtensionById(extension_id, include_mask)); 1269 1270 // This method can be called via PostTask, so the extension may have been 1271 // unloaded by the time this runs. 1272 if (!extension.get()) { 1273 // In case the extension may have crashed/uninstalled. Allow the profile to 1274 // clean up its RequestContexts. 1275 system_->UnregisterExtensionWithRequestContexts(extension_id, reason); 1276 return; 1277 } 1278 1279 // Keep information about the extension so that we can reload it later 1280 // even if it's not permanently installed. 1281 unloaded_extension_paths_[extension->id()] = extension->path(); 1282 1283 // Clean up if the extension is meant to be enabled after a reload. 1284 reloading_extensions_.erase(extension->id()); 1285 1286 if (registry_->disabled_extensions().Contains(extension->id())) { 1287 registry_->RemoveDisabled(extension->id()); 1288 // Make sure the profile cleans up its RequestContexts when an already 1289 // disabled extension is unloaded (since they are also tracking the disabled 1290 // extensions). 1291 system_->UnregisterExtensionWithRequestContexts(extension_id, reason); 1292 // Don't send the unloaded notification. It was sent when the extension 1293 // was disabled. 1294 } else { 1295 // Remove the extension from the enabled list. 1296 registry_->RemoveEnabled(extension->id()); 1297 NotifyExtensionUnloaded(extension.get(), reason); 1298 } 1299 1300 content::NotificationService::current()->Notify( 1301 extensions::NOTIFICATION_EXTENSION_REMOVED, 1302 content::Source<Profile>(profile_), 1303 content::Details<const Extension>(extension.get())); 1304} 1305 1306void ExtensionService::RemoveComponentExtension( 1307 const std::string& extension_id) { 1308 scoped_refptr<const Extension> extension( 1309 GetExtensionById(extension_id, false)); 1310 UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_UNINSTALL); 1311 if (extension.get()) { 1312 content::NotificationService::current()->Notify( 1313 extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED, 1314 content::Source<Profile>(profile_), 1315 content::Details<const Extension>(extension.get())); 1316 ExtensionRegistry::Get(profile_)->TriggerOnUninstalled( 1317 extension.get(), extensions::UNINSTALL_REASON_INTERNAL_MANAGEMENT); 1318 } 1319} 1320 1321void ExtensionService::UnloadAllExtensionsForTest() { 1322 UnloadAllExtensionsInternal(); 1323} 1324 1325void ExtensionService::ReloadExtensionsForTest() { 1326 // Calling UnloadAllExtensionsForTest here triggers a false-positive presubmit 1327 // warning about calling test code in production. 1328 UnloadAllExtensionsInternal(); 1329 component_loader_->LoadAll(); 1330 extensions::InstalledLoader(this).LoadAllExtensions(); 1331 // Don't call SetReadyAndNotifyListeners() since tests call this multiple 1332 // times. 1333} 1334 1335void ExtensionService::SetReadyAndNotifyListeners() { 1336 ready_->Signal(); 1337 content::NotificationService::current()->Notify( 1338 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, 1339 content::Source<Profile>(profile_), 1340 content::NotificationService::NoDetails()); 1341} 1342 1343void ExtensionService::OnLoadedInstalledExtensions() { 1344 if (updater_) 1345 updater_->Start(); 1346 1347 OnBlacklistUpdated(); 1348} 1349 1350void ExtensionService::AddExtension(const Extension* extension) { 1351 // TODO(jstritar): We may be able to get rid of this branch by overriding the 1352 // default extension state to DISABLED when the --disable-extensions flag 1353 // is set (http://crbug.com/29067). 1354 if (!extensions_enabled() && 1355 !extension->is_theme() && 1356 extension->location() != Manifest::COMPONENT && 1357 !Manifest::IsExternalLocation(extension->location())) { 1358 return; 1359 } 1360 1361 bool is_extension_upgrade = false; 1362 bool is_extension_installed = false; 1363 const Extension* old = GetInstalledExtension(extension->id()); 1364 if (old) { 1365 is_extension_installed = true; 1366 int version_compare_result = 1367 extension->version()->CompareTo(*(old->version())); 1368 is_extension_upgrade = version_compare_result > 0; 1369 // Other than for unpacked extensions, CrxInstaller should have guaranteed 1370 // that we aren't downgrading. 1371 if (!Manifest::IsUnpackedLocation(extension->location())) 1372 CHECK_GE(version_compare_result, 0); 1373 } 1374 system_->runtime_data()->SetBeingUpgraded(extension, is_extension_upgrade); 1375 1376 // The extension is now loaded, remove its data from unloaded extension map. 1377 unloaded_extension_paths_.erase(extension->id()); 1378 1379 // If a terminated extension is loaded, remove it from the terminated list. 1380 UntrackTerminatedExtension(extension->id()); 1381 1382 // If the extension was disabled for a reload, then enable it. 1383 bool reloading = reloading_extensions_.erase(extension->id()) > 0; 1384 1385 // Check if the extension's privileges have changed and mark the 1386 // extension disabled if necessary. 1387 CheckPermissionsIncrease(extension, is_extension_installed); 1388 1389 if (is_extension_installed && !reloading) { 1390 // To upgrade an extension in place, unload the old one and then load the 1391 // new one. ReloadExtension disables the extension, which is sufficient. 1392 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE); 1393 } 1394 1395 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { 1396 // Only prefs is checked for the blacklist. We rely on callers to check the 1397 // blacklist before calling into here, e.g. CrxInstaller checks before 1398 // installation then threads through the install and pending install flow 1399 // of this class, and we check when loading installed extensions. 1400 registry_->AddBlacklisted(extension); 1401 } else if (!reloading && 1402 extension_prefs_->IsExtensionDisabled(extension->id())) { 1403 registry_->AddDisabled(extension); 1404 if (extension_sync_service_) 1405 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); 1406 content::NotificationService::current()->Notify( 1407 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED, 1408 content::Source<Profile>(profile_), 1409 content::Details<const Extension>(extension)); 1410 1411 // Show the extension disabled error if a permissions increase or a remote 1412 // installation is the reason it was disabled, and no other reasons exist. 1413 int reasons = extension_prefs_->GetDisableReasons(extension->id()); 1414 const int kReasonMask = Extension::DISABLE_PERMISSIONS_INCREASE | 1415 Extension::DISABLE_REMOTE_INSTALL; 1416 if (reasons & kReasonMask && !(reasons & ~kReasonMask)) { 1417 extensions::AddExtensionDisabledError( 1418 this, 1419 extension, 1420 extension_prefs_->HasDisableReason( 1421 extension->id(), Extension::DISABLE_REMOTE_INSTALL)); 1422 } 1423 } else if (reloading) { 1424 // Replace the old extension with the new version. 1425 CHECK(!registry_->AddDisabled(extension)); 1426 EnableExtension(extension->id()); 1427 } else { 1428 // All apps that are displayed in the launcher are ordered by their ordinals 1429 // so we must ensure they have valid ordinals. 1430 if (extension->RequiresSortOrdinal()) { 1431 extension_prefs_->app_sorting()->SetExtensionVisible( 1432 extension->id(), 1433 extension->ShouldDisplayInNewTabPage() && 1434 !extension_prefs_->IsEphemeralApp(extension->id())); 1435 if (!extension_prefs_->IsEphemeralApp(extension->id())) { 1436 extension_prefs_->app_sorting()->EnsureValidOrdinals( 1437 extension->id(), syncer::StringOrdinal()); 1438 } 1439 } 1440 1441 registry_->AddEnabled(extension); 1442 if (extension_sync_service_) 1443 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); 1444 NotifyExtensionLoaded(extension); 1445 } 1446 system_->runtime_data()->SetBeingUpgraded(extension, false); 1447} 1448 1449void ExtensionService::AddComponentExtension(const Extension* extension) { 1450 const std::string old_version_string( 1451 extension_prefs_->GetVersionString(extension->id())); 1452 const Version old_version(old_version_string); 1453 1454 VLOG(1) << "AddComponentExtension " << extension->name(); 1455 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) { 1456 VLOG(1) << "Component extension " << extension->name() << " (" 1457 << extension->id() << ") installing/upgrading from '" 1458 << old_version_string << "' to " << extension->version()->GetString(); 1459 1460 AddNewOrUpdatedExtension(extension, 1461 Extension::ENABLED, 1462 extensions::kInstallFlagNone, 1463 syncer::StringOrdinal(), 1464 std::string()); 1465 return; 1466 } 1467 1468 AddExtension(extension); 1469} 1470 1471void ExtensionService::CheckPermissionsIncrease(const Extension* extension, 1472 bool is_extension_installed) { 1473 extensions::PermissionsUpdater(profile_).InitializePermissions(extension); 1474 1475 // We keep track of all permissions the user has granted each extension. 1476 // This allows extensions to gracefully support backwards compatibility 1477 // by including unknown permissions in their manifests. When the user 1478 // installs the extension, only the recognized permissions are recorded. 1479 // When the unknown permissions become recognized (e.g., through browser 1480 // upgrade), we can prompt the user to accept these new permissions. 1481 // Extensions can also silently upgrade to less permissions, and then 1482 // silently upgrade to a version that adds these permissions back. 1483 // 1484 // For example, pretend that Chrome 10 includes a permission "omnibox" 1485 // for an API that adds suggestions to the omnibox. An extension can 1486 // maintain backwards compatibility while still having "omnibox" in the 1487 // manifest. If a user installs the extension on Chrome 9, the browser 1488 // will record the permissions it recognized, not including "omnibox." 1489 // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome 1490 // will disable the extension and prompt the user to approve the increase 1491 // in privileges. The extension could then release a new version that 1492 // removes the "omnibox" permission. When the user upgrades, Chrome will 1493 // still remember that "omnibox" had been granted, so that if the 1494 // extension once again includes "omnibox" in an upgrade, the extension 1495 // can upgrade without requiring this user's approval. 1496 int disable_reasons = extension_prefs_->GetDisableReasons(extension->id()); 1497 1498 bool auto_grant_permission = 1499 (!is_extension_installed && extension->was_installed_by_default()) || 1500 extensions::ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode(); 1501 // Silently grant all active permissions to default apps only on install. 1502 // After install they should behave like other apps. 1503 // Silently grant all active permissions to apps install in kiosk mode on both 1504 // install and update. 1505 if (auto_grant_permission) 1506 GrantPermissions(extension); 1507 1508 bool is_privilege_increase = false; 1509 // We only need to compare the granted permissions to the current permissions 1510 // if the extension is not allowed to silently increase its permissions. 1511 if (!extensions::PermissionsData::CanSilentlyIncreasePermissions(extension) && 1512 !auto_grant_permission) { 1513 // Add all the recognized permissions if the granted permissions list 1514 // hasn't been initialized yet. 1515 scoped_refptr<PermissionSet> granted_permissions = 1516 extension_prefs_->GetGrantedPermissions(extension->id()); 1517 CHECK(granted_permissions.get()); 1518 1519 // Here, we check if an extension's privileges have increased in a manner 1520 // that requires the user's approval. This could occur because the browser 1521 // upgraded and recognized additional privileges, or an extension upgrades 1522 // to a version that requires additional privileges. 1523 is_privilege_increase = 1524 extensions::PermissionMessageProvider::Get()->IsPrivilegeIncrease( 1525 granted_permissions, 1526 extension->permissions_data()->active_permissions().get(), 1527 extension->GetType()); 1528 } 1529 1530 if (is_extension_installed) { 1531 // If the extension was already disabled, suppress any alerts for becoming 1532 // disabled on permissions increase. 1533 bool previously_disabled = 1534 extension_prefs_->IsExtensionDisabled(extension->id()); 1535 // Legacy disabled extensions do not have a disable reason. Infer that if 1536 // there was no permission increase, it was likely disabled by the user. 1537 if (previously_disabled && disable_reasons == Extension::DISABLE_NONE && 1538 !extension_prefs_->DidExtensionEscalatePermissions(extension->id())) { 1539 disable_reasons |= Extension::DISABLE_USER_ACTION; 1540 } 1541 // Extensions that came to us disabled from sync need a similar inference, 1542 // except based on the new version's permissions. 1543 if (previously_disabled && 1544 disable_reasons == Extension::DISABLE_UNKNOWN_FROM_SYNC) { 1545 // Remove the DISABLE_UNKNOWN_FROM_SYNC reason. 1546 extension_prefs_->ClearDisableReasons(extension->id()); 1547 if (!is_privilege_increase) 1548 disable_reasons |= Extension::DISABLE_USER_ACTION; 1549 } 1550 disable_reasons &= ~Extension::DISABLE_UNKNOWN_FROM_SYNC; 1551 } 1552 1553 // Extension has changed permissions significantly. Disable it. A 1554 // notification should be sent by the caller. If the extension is already 1555 // disabled because it was installed remotely, don't add another disable 1556 // reason, but instead always set the "did escalate permissions" flag, to 1557 // ensure enabling it will always show a warning. 1558 if (disable_reasons == Extension::DISABLE_REMOTE_INSTALL) { 1559 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); 1560 } else if (is_privilege_increase) { 1561 disable_reasons |= Extension::DISABLE_PERMISSIONS_INCREASE; 1562 if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id())) { 1563 RecordPermissionMessagesHistogram(extension, 1564 "Extensions.Permissions_AutoDisable2"); 1565 } 1566 extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED); 1567 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); 1568 } 1569 if (disable_reasons != Extension::DISABLE_NONE) { 1570 extension_prefs_->AddDisableReason( 1571 extension->id(), 1572 static_cast<Extension::DisableReason>(disable_reasons)); 1573 } 1574} 1575 1576void ExtensionService::UpdateActiveExtensionsInCrashReporter() { 1577 std::set<std::string> extension_ids; 1578 const ExtensionSet& extensions = registry_->enabled_extensions(); 1579 for (ExtensionSet::const_iterator iter = extensions.begin(); 1580 iter != extensions.end(); ++iter) { 1581 const Extension* extension = iter->get(); 1582 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) 1583 extension_ids.insert(extension->id()); 1584 } 1585 1586 // TODO(kalman): This is broken. ExtensionService is per-profile. 1587 // crash_keys::SetActiveExtensions is per-process. See 1588 // http://crbug.com/355029. 1589 crash_keys::SetActiveExtensions(extension_ids); 1590} 1591 1592void ExtensionService::OnExtensionInstalled( 1593 const Extension* extension, 1594 const syncer::StringOrdinal& page_ordinal, 1595 int install_flags) { 1596 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1597 1598 const std::string& id = extension->id(); 1599 bool initial_enable = ShouldEnableOnInstall(extension); 1600 std::string install_parameter; 1601 const extensions::PendingExtensionInfo* pending_extension_info = 1602 pending_extension_manager()->GetById(id); 1603 if (pending_extension_info) { 1604 if (!pending_extension_info->ShouldAllowInstall(extension)) { 1605 pending_extension_manager()->Remove(id); 1606 1607 LOG(WARNING) << "ShouldAllowInstall() returned false for " 1608 << id << " of type " << extension->GetType() 1609 << " and update URL " 1610 << extensions::ManifestURL::GetUpdateURL(extension).spec() 1611 << "; not installing"; 1612 1613 // Delete the extension directory since we're not going to 1614 // load it. 1615 if (!GetFileTaskRunner()->PostTask( 1616 FROM_HERE, 1617 base::Bind(&extensions::file_util::DeleteFile, 1618 extension->path(), 1619 true))) { 1620 NOTREACHED(); 1621 } 1622 return; 1623 } 1624 1625 install_parameter = pending_extension_info->install_parameter(); 1626 pending_extension_manager()->Remove(id); 1627 } else { 1628 // We explicitly want to re-enable an uninstalled external 1629 // extension; if we're here, that means the user is manually 1630 // installing the extension. 1631 if (extension_prefs_->IsExternalExtensionUninstalled(id)) { 1632 initial_enable = true; 1633 } 1634 } 1635 1636 // Unsupported requirements overrides the management policy. 1637 if (install_flags & extensions::kInstallFlagHasRequirementErrors) { 1638 initial_enable = false; 1639 extension_prefs_->AddDisableReason( 1640 id, Extension::DISABLE_UNSUPPORTED_REQUIREMENT); 1641 // If the extension was disabled because of unsupported requirements but 1642 // now supports all requirements after an update and there are not other 1643 // disable reasons, enable it. 1644 } else if (extension_prefs_->GetDisableReasons(id) == 1645 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) { 1646 initial_enable = true; 1647 extension_prefs_->ClearDisableReasons(id); 1648 } 1649 1650 if (install_flags & extensions::kInstallFlagIsBlacklistedForMalware) { 1651 // Installation of a blacklisted extension can happen from sync, policy, 1652 // etc, where to maintain consistency we need to install it, just never 1653 // load it (see AddExtension). Usually it should be the job of callers to 1654 // incercept blacklisted extension earlier (e.g. CrxInstaller, before even 1655 // showing the install dialogue). 1656 extension_prefs_->AcknowledgeBlacklistedExtension(id); 1657 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall", 1658 extension->location(), 1659 Manifest::NUM_LOCATIONS); 1660 } 1661 1662 if (!GetInstalledExtension(extension->id())) { 1663 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType", 1664 extension->GetType(), 100); 1665 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallSource", 1666 extension->location(), Manifest::NUM_LOCATIONS); 1667 RecordPermissionMessagesHistogram(extension, 1668 "Extensions.Permissions_Install2"); 1669 } else { 1670 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateType", 1671 extension->GetType(), 100); 1672 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateSource", 1673 extension->location(), Manifest::NUM_LOCATIONS); 1674 1675 // A fully installed app cannot be demoted to an ephemeral app. 1676 if ((install_flags & extensions::kInstallFlagIsEphemeral) && 1677 !extension_prefs_->IsEphemeralApp(id)) { 1678 install_flags &= ~static_cast<int>(extensions::kInstallFlagIsEphemeral); 1679 } 1680 } 1681 1682 const Extension::State initial_state = 1683 initial_enable ? Extension::ENABLED : Extension::DISABLED; 1684 if (ShouldDelayExtensionUpdate( 1685 id, 1686 !!(install_flags & extensions::kInstallFlagInstallImmediately))) { 1687 extension_prefs_->SetDelayedInstallInfo( 1688 extension, 1689 initial_state, 1690 install_flags, 1691 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, 1692 page_ordinal, 1693 install_parameter); 1694 1695 // Transfer ownership of |extension|. 1696 delayed_installs_.Insert(extension); 1697 1698 // Notify observers that app update is available. 1699 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 1700 OnAppUpdateAvailable(extension)); 1701 return; 1702 } 1703 1704 extensions::SharedModuleService::ImportStatus status = 1705 shared_module_service_->SatisfyImports(extension); 1706 if (installs_delayed_for_gc_) { 1707 extension_prefs_->SetDelayedInstallInfo( 1708 extension, 1709 initial_state, 1710 install_flags, 1711 extensions::ExtensionPrefs::DELAY_REASON_GC, 1712 page_ordinal, 1713 install_parameter); 1714 delayed_installs_.Insert(extension); 1715 } else if (status != SharedModuleService::IMPORT_STATUS_OK) { 1716 if (status == SharedModuleService::IMPORT_STATUS_UNSATISFIED) { 1717 extension_prefs_->SetDelayedInstallInfo( 1718 extension, 1719 initial_state, 1720 install_flags, 1721 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS, 1722 page_ordinal, 1723 install_parameter); 1724 delayed_installs_.Insert(extension); 1725 } 1726 } else { 1727 AddNewOrUpdatedExtension(extension, 1728 initial_state, 1729 install_flags, 1730 page_ordinal, 1731 install_parameter); 1732 } 1733} 1734 1735void ExtensionService::AddNewOrUpdatedExtension( 1736 const Extension* extension, 1737 Extension::State initial_state, 1738 int install_flags, 1739 const syncer::StringOrdinal& page_ordinal, 1740 const std::string& install_parameter) { 1741 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1742 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id()); 1743 extension_prefs_->OnExtensionInstalled( 1744 extension, initial_state, page_ordinal, install_flags, install_parameter); 1745 delayed_installs_.Remove(extension->id()); 1746 if (InstallVerifier::NeedsVerification(*extension)) 1747 system_->install_verifier()->VerifyExtension(extension->id()); 1748 FinishInstallation(extension, was_ephemeral); 1749} 1750 1751void ExtensionService::MaybeFinishDelayedInstallation( 1752 const std::string& extension_id) { 1753 // Check if the extension already got installed. 1754 if (!delayed_installs_.Contains(extension_id)) 1755 return; 1756 extensions::ExtensionPrefs::DelayReason reason = 1757 extension_prefs_->GetDelayedInstallReason(extension_id); 1758 1759 // Check if the extension is idle. DELAY_REASON_NONE is used for older 1760 // preferences files that will not have set this field but it was previously 1761 // only used for idle updates. 1762 if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE || 1763 reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) && 1764 is_ready() && !extensions::util::IsExtensionIdle(extension_id, profile_)) 1765 return; 1766 1767 const Extension* extension = delayed_installs_.GetByID(extension_id); 1768 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) { 1769 extensions::SharedModuleService::ImportStatus status = 1770 shared_module_service_->SatisfyImports(extension); 1771 if (status != SharedModuleService::IMPORT_STATUS_OK) { 1772 if (status == SharedModuleService::IMPORT_STATUS_UNRECOVERABLE) { 1773 delayed_installs_.Remove(extension_id); 1774 // Make sure no version of the extension is actually installed, (i.e., 1775 // that this delayed install was not an update). 1776 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get()); 1777 extension_prefs_->DeleteExtensionPrefs(extension_id); 1778 } 1779 return; 1780 } 1781 } 1782 1783 FinishDelayedInstallation(extension_id); 1784} 1785 1786void ExtensionService::FinishDelayedInstallation( 1787 const std::string& extension_id) { 1788 scoped_refptr<const Extension> extension( 1789 GetPendingExtensionUpdate(extension_id)); 1790 CHECK(extension.get()); 1791 delayed_installs_.Remove(extension_id); 1792 1793 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id()); 1794 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) 1795 NOTREACHED(); 1796 1797 FinishInstallation(extension.get(), was_ephemeral); 1798} 1799 1800void ExtensionService::FinishInstallation( 1801 const Extension* extension, bool was_ephemeral) { 1802 const extensions::Extension* existing_extension = 1803 GetInstalledExtension(extension->id()); 1804 bool is_update = false; 1805 std::string old_name; 1806 if (existing_extension) { 1807 is_update = true; 1808 old_name = existing_extension->name(); 1809 } 1810 bool from_ephemeral = 1811 was_ephemeral && !extension_prefs_->IsEphemeralApp(extension->id()); 1812 extensions::InstalledExtensionInfo details( 1813 extension, is_update, from_ephemeral, old_name); 1814 content::NotificationService::current()->Notify( 1815 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, 1816 content::Source<Profile>(profile_), 1817 content::Details<const extensions::InstalledExtensionInfo>(&details)); 1818 1819 registry_->TriggerOnWillBeInstalled( 1820 extension, is_update, from_ephemeral, old_name); 1821 1822 // Unpacked extensions default to allowing file access, but if that has been 1823 // overridden, don't reset the value. 1824 if (Manifest::ShouldAlwaysAllowFileAccess(extension->location()) && 1825 !extension_prefs_->HasAllowFileAccessSetting(extension->id())) { 1826 extension_prefs_->SetAllowFileAccess(extension->id(), true); 1827 } 1828 1829 AddExtension(extension); 1830 1831 // Notify observers that need to know when an installation is complete. 1832 registry_->TriggerOnInstalled(extension, is_update); 1833 1834 // Check extensions that may have been delayed only because this shared module 1835 // was not available. 1836 if (SharedModuleInfo::IsSharedModule(extension)) 1837 MaybeFinishDelayedInstallations(); 1838} 1839 1840void ExtensionService::PromoteEphemeralApp( 1841 const extensions::Extension* extension, bool is_from_sync) { 1842 DCHECK(GetInstalledExtension(extension->id()) && 1843 extension_prefs_->IsEphemeralApp(extension->id())); 1844 1845 if (extension->RequiresSortOrdinal()) { 1846 extension_prefs_->app_sorting()->SetExtensionVisible( 1847 extension->id(), extension->ShouldDisplayInNewTabPage()); 1848 1849 if (!is_from_sync) { 1850 // Reset the sort ordinals of the app to ensure it is added to the default 1851 // position, like newly installed apps would. 1852 extension_prefs_->app_sorting()->ClearOrdinals(extension->id()); 1853 } 1854 1855 extension_prefs_->app_sorting()->EnsureValidOrdinals( 1856 extension->id(), syncer::StringOrdinal()); 1857 } 1858 1859 // Remove the ephemeral flags from the preferences. 1860 extension_prefs_->OnEphemeralAppPromoted(extension->id()); 1861 1862 // Fire install-related events to allow observers to handle the promotion 1863 // of the ephemeral app. 1864 extensions::InstalledExtensionInfo details( 1865 extension, 1866 true /* is update */, 1867 true /* from ephemeral */, 1868 extension->name() /* old name */); 1869 content::NotificationService::current()->Notify( 1870 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, 1871 content::Source<Profile>(profile_), 1872 content::Details<const extensions::InstalledExtensionInfo>(&details)); 1873 1874 registry_->TriggerOnWillBeInstalled( 1875 extension, 1876 true /* is update */, 1877 true /* from ephemeral */, 1878 extension->name() /* old name */); 1879 1880 if (registry_->enabled_extensions().Contains(extension->id())) { 1881 // If the app is already enabled and loaded, fire the load events to allow 1882 // observers to handle the promotion of the ephemeral app. 1883 content::NotificationService::current()->Notify( 1884 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 1885 content::Source<Profile>(profile_), 1886 content::Details<const Extension>(extension)); 1887 1888 registry_->TriggerOnLoaded(extension); 1889 } else { 1890 // Cached ephemeral apps may be updated and disabled due to permissions 1891 // increase. The app can be enabled (as long as no other disable reasons 1892 // exist) as the install was user-acknowledged. 1893 int disable_mask = Extension::DISABLE_NONE; 1894 if (!is_from_sync) 1895 disable_mask |= Extension::DISABLE_PERMISSIONS_INCREASE; 1896 1897 int other_disable_reasons = 1898 extension_prefs_->GetDisableReasons(extension->id()) & ~disable_mask; 1899 if (!other_disable_reasons) { 1900 if (extension_prefs_->DidExtensionEscalatePermissions(extension->id())) 1901 GrantPermissionsAndEnableExtension(extension); 1902 else 1903 EnableExtension(extension->id()); 1904 } 1905 } 1906 1907 registry_->TriggerOnInstalled(extension, true); 1908 1909 if (!is_from_sync && extension_sync_service_) 1910 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); 1911} 1912 1913const Extension* ExtensionService::GetPendingExtensionUpdate( 1914 const std::string& id) const { 1915 return delayed_installs_.GetByID(id); 1916} 1917 1918void ExtensionService::TrackTerminatedExtension(const Extension* extension) { 1919 // No need to check for duplicates; inserting a duplicate is a no-op. 1920 registry_->AddTerminated(make_scoped_refptr(extension)); 1921 extensions_being_terminated_.erase(extension->id()); 1922 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_TERMINATE); 1923} 1924 1925void ExtensionService::TerminateExtension(const std::string& extension_id) { 1926 const Extension* extension = GetInstalledExtension(extension_id); 1927 TrackTerminatedExtension(extension); 1928} 1929 1930void ExtensionService::UntrackTerminatedExtension(const std::string& id) { 1931 std::string lowercase_id = base::StringToLowerASCII(id); 1932 const Extension* extension = 1933 registry_->terminated_extensions().GetByID(lowercase_id); 1934 registry_->RemoveTerminated(lowercase_id); 1935 if (extension) { 1936 content::NotificationService::current()->Notify( 1937 extensions::NOTIFICATION_EXTENSION_REMOVED, 1938 content::Source<Profile>(profile_), 1939 content::Details<const Extension>(extension)); 1940 } 1941} 1942 1943const Extension* ExtensionService::GetInstalledExtension( 1944 const std::string& id) const { 1945 return registry_->GetExtensionById(id, ExtensionRegistry::EVERYTHING); 1946} 1947 1948bool ExtensionService::OnExternalExtensionFileFound( 1949 const std::string& id, 1950 const Version* version, 1951 const base::FilePath& path, 1952 Manifest::Location location, 1953 int creation_flags, 1954 bool mark_acknowledged) { 1955 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1956 CHECK(crx_file::id_util::IdIsValid(id)); 1957 if (extension_prefs_->IsExternalExtensionUninstalled(id)) 1958 return false; 1959 1960 // Before even bothering to unpack, check and see if we already have this 1961 // version. This is important because these extensions are going to get 1962 // installed on every startup. 1963 const Extension* existing = GetExtensionById(id, true); 1964 1965 if (existing) { 1966 // The default apps will have the location set as INTERNAL. Since older 1967 // default apps are installed as EXTERNAL, we override them. However, if the 1968 // app is already installed as internal, then do the version check. 1969 // TODO(grv) : Remove after Q1-2013. 1970 bool is_default_apps_migration = 1971 (location == Manifest::INTERNAL && 1972 Manifest::IsExternalLocation(existing->location())); 1973 1974 if (!is_default_apps_migration) { 1975 DCHECK(version); 1976 1977 switch (existing->version()->CompareTo(*version)) { 1978 case -1: // existing version is older, we should upgrade 1979 break; 1980 case 0: // existing version is same, do nothing 1981 return false; 1982 case 1: // existing version is newer, uh-oh 1983 LOG(WARNING) << "Found external version of extension " << id 1984 << "that is older than current version. Current version " 1985 << "is: " << existing->VersionString() << ". New " 1986 << "version is: " << version->GetString() 1987 << ". Keeping current version."; 1988 return false; 1989 } 1990 } 1991 } 1992 1993 // If the extension is already pending, don't start an install. 1994 if (!pending_extension_manager()->AddFromExternalFile( 1995 id, location, *version, creation_flags, mark_acknowledged)) { 1996 return false; 1997 } 1998 1999 // no client (silent install) 2000 scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this)); 2001 installer->set_install_source(location); 2002 installer->set_expected_id(id); 2003 installer->set_expected_version(*version); 2004 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE); 2005 installer->set_creation_flags(creation_flags); 2006#if defined(OS_CHROMEOS) 2007 extensions::InstallLimiter::Get(profile_)->Add(installer, path); 2008#else 2009 installer->InstallCrx(path); 2010#endif 2011 2012 // Depending on the source, a new external extension might not need a user 2013 // notification on installation. For such extensions, mark them acknowledged 2014 // now to suppress the notification. 2015 if (mark_acknowledged) 2016 external_install_manager_->AcknowledgeExternalExtension(id); 2017 2018 return true; 2019} 2020 2021void ExtensionService::DidCreateRenderViewForBackgroundPage( 2022 extensions::ExtensionHost* host) { 2023 OrphanedDevTools::iterator iter = 2024 orphaned_dev_tools_.find(host->extension_id()); 2025 if (iter == orphaned_dev_tools_.end()) 2026 return; 2027 2028 iter->second->ConnectWebContents(host->host_contents()); 2029 orphaned_dev_tools_.erase(iter); 2030} 2031 2032void ExtensionService::Observe(int type, 2033 const content::NotificationSource& source, 2034 const content::NotificationDetails& details) { 2035 switch (type) { 2036 case chrome::NOTIFICATION_APP_TERMINATING: 2037 // Shutdown has started. Don't start any more extension installs. 2038 // (We cannot use ExtensionService::Shutdown() for this because it 2039 // happens too late in browser teardown.) 2040 browser_terminating_ = true; 2041 break; 2042 case extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: { 2043 if (profile_ != 2044 content::Source<Profile>(source).ptr()->GetOriginalProfile()) { 2045 break; 2046 } 2047 2048 extensions::ExtensionHost* host = 2049 content::Details<extensions::ExtensionHost>(details).ptr(); 2050 2051 // If the extension is already being terminated, there is nothing left to 2052 // do. 2053 if (!extensions_being_terminated_.insert(host->extension_id()).second) 2054 break; 2055 2056 // Mark the extension as terminated and Unload it. We want it to 2057 // be in a consistent state: either fully working or not loaded 2058 // at all, but never half-crashed. We do it in a PostTask so 2059 // that other handlers of this notification will still have 2060 // access to the Extension and ExtensionHost. 2061 base::MessageLoop::current()->PostTask( 2062 FROM_HERE, 2063 base::Bind( 2064 &ExtensionService::TrackTerminatedExtension, 2065 AsWeakPtr(), 2066 host->extension())); 2067 break; 2068 } 2069 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { 2070 content::RenderProcessHost* process = 2071 content::Source<content::RenderProcessHost>(source).ptr(); 2072 Profile* host_profile = 2073 Profile::FromBrowserContext(process->GetBrowserContext()); 2074 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile())) 2075 break; 2076 2077 extensions::ProcessMap* process_map = 2078 extensions::ProcessMap::Get(profile_); 2079 if (process_map->Contains(process->GetID())) { 2080 // An extension process was terminated, this might have resulted in an 2081 // app or extension becoming idle. 2082 std::set<std::string> extension_ids = 2083 process_map->GetExtensionsInProcess(process->GetID()); 2084 for (std::set<std::string>::const_iterator it = extension_ids.begin(); 2085 it != extension_ids.end(); ++it) { 2086 if (delayed_installs_.Contains(*it)) { 2087 base::MessageLoop::current()->PostDelayedTask( 2088 FROM_HERE, 2089 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, 2090 AsWeakPtr(), *it), 2091 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); 2092 } 2093 } 2094 } 2095 2096 process_map->RemoveAllFromProcess(process->GetID()); 2097 BrowserThread::PostTask( 2098 BrowserThread::IO, 2099 FROM_HERE, 2100 base::Bind(&extensions::InfoMap::UnregisterAllExtensionsInProcess, 2101 system_->info_map(), 2102 process->GetID())); 2103 break; 2104 } 2105 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: { 2106 // Notify observers that chrome update is available. 2107 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 2108 OnChromeUpdateAvailable()); 2109 break; 2110 } 2111 case chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED: { 2112 OnProfileDestructionStarted(); 2113 break; 2114 } 2115 2116 default: 2117 NOTREACHED() << "Unexpected notification type."; 2118 } 2119} 2120 2121void ExtensionService::OnExtensionInstallPrefChanged() { 2122 error_controller_->ShowErrorIfNeeded(); 2123 CheckManagementPolicy(); 2124} 2125 2126bool ExtensionService::ShouldEnableOnInstall(const Extension* extension) { 2127 // Extensions installed by policy can't be disabled. So even if a previous 2128 // installation disabled the extension, make sure it is now enabled. 2129 if (system_->management_policy()->MustRemainEnabled(extension, NULL)) 2130 return true; 2131 2132 if (extension_prefs_->IsExtensionDisabled(extension->id())) 2133 return false; 2134 2135 if (FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) { 2136 // External extensions are initially disabled. We prompt the user before 2137 // enabling them. Hosted apps are excepted because they are not dangerous 2138 // (they need to be launched by the user anyway). 2139 if (extension->GetType() != Manifest::TYPE_HOSTED_APP && 2140 Manifest::IsExternalLocation(extension->location()) && 2141 !extension_prefs_->IsExternalExtensionAcknowledged(extension->id())) { 2142 return false; 2143 } 2144 } 2145 2146 return true; 2147} 2148 2149bool ExtensionService::ShouldDelayExtensionUpdate( 2150 const std::string& extension_id, 2151 bool install_immediately) const { 2152 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable"; 2153 2154 // If delayed updates are globally disabled, or just for this extension, 2155 // don't delay. 2156 if (!install_updates_when_idle_ || install_immediately) 2157 return false; 2158 2159 const Extension* old = GetInstalledExtension(extension_id); 2160 // If there is no old extension, this is not an update, so don't delay. 2161 if (!old) 2162 return false; 2163 2164 if (extensions::BackgroundInfo::HasPersistentBackgroundPage(old)) { 2165 // Delay installation if the extension listens for the onUpdateAvailable 2166 // event. 2167 return system_->event_router()->ExtensionHasEventListener( 2168 extension_id, kOnUpdateAvailableEvent); 2169 } else { 2170 // Delay installation if the extension is not idle. 2171 return !extensions::util::IsExtensionIdle(extension_id, profile_); 2172 } 2173} 2174 2175void ExtensionService::OnGarbageCollectIsolatedStorageStart() { 2176 DCHECK(!installs_delayed_for_gc_); 2177 installs_delayed_for_gc_ = true; 2178} 2179 2180void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { 2181 DCHECK(installs_delayed_for_gc_); 2182 installs_delayed_for_gc_ = false; 2183 MaybeFinishDelayedInstallations(); 2184} 2185 2186void ExtensionService::MaybeFinishDelayedInstallations() { 2187 std::vector<std::string> to_be_installed; 2188 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); 2189 it != delayed_installs_.end(); 2190 ++it) { 2191 to_be_installed.push_back((*it)->id()); 2192 } 2193 for (std::vector<std::string>::const_iterator it = to_be_installed.begin(); 2194 it != to_be_installed.end(); 2195 ++it) { 2196 MaybeFinishDelayedInstallation(*it); 2197 } 2198} 2199 2200void ExtensionService::OnBlacklistUpdated() { 2201 blacklist_->GetBlacklistedIDs( 2202 registry_->GenerateInstalledExtensionsSet()->GetIDs(), 2203 base::Bind(&ExtensionService::ManageBlacklist, AsWeakPtr())); 2204} 2205 2206void ExtensionService::ManageBlacklist( 2207 const extensions::Blacklist::BlacklistStateMap& state_map) { 2208 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2209 2210 std::set<std::string> blocked; 2211 ExtensionIdSet greylist; 2212 ExtensionIdSet unchanged; 2213 for (extensions::Blacklist::BlacklistStateMap::const_iterator it = 2214 state_map.begin(); 2215 it != state_map.end(); 2216 ++it) { 2217 switch (it->second) { 2218 case extensions::NOT_BLACKLISTED: 2219 break; 2220 2221 case extensions::BLACKLISTED_MALWARE: 2222 blocked.insert(it->first); 2223 break; 2224 2225 case extensions::BLACKLISTED_SECURITY_VULNERABILITY: 2226 case extensions::BLACKLISTED_CWS_POLICY_VIOLATION: 2227 case extensions::BLACKLISTED_POTENTIALLY_UNWANTED: 2228 greylist.insert(it->first); 2229 break; 2230 2231 case extensions::BLACKLISTED_UNKNOWN: 2232 unchanged.insert(it->first); 2233 break; 2234 } 2235 } 2236 2237 UpdateBlockedExtensions(blocked, unchanged); 2238 UpdateGreylistedExtensions(greylist, unchanged, state_map); 2239 2240 error_controller_->ShowErrorIfNeeded(); 2241} 2242 2243namespace { 2244void Partition(const ExtensionIdSet& before, 2245 const ExtensionIdSet& after, 2246 const ExtensionIdSet& unchanged, 2247 ExtensionIdSet* no_longer, 2248 ExtensionIdSet* not_yet) { 2249 *not_yet = base::STLSetDifference<ExtensionIdSet>(after, before); 2250 *no_longer = base::STLSetDifference<ExtensionIdSet>(before, after); 2251 *no_longer = base::STLSetDifference<ExtensionIdSet>(*no_longer, unchanged); 2252} 2253} // namespace 2254 2255void ExtensionService::UpdateBlockedExtensions( 2256 const ExtensionIdSet& blocked, 2257 const ExtensionIdSet& unchanged) { 2258 ExtensionIdSet not_yet_blocked, no_longer_blocked; 2259 Partition(registry_->blacklisted_extensions().GetIDs(), 2260 blocked, unchanged, 2261 &no_longer_blocked, ¬_yet_blocked); 2262 2263 for (ExtensionIdSet::iterator it = no_longer_blocked.begin(); 2264 it != no_longer_blocked.end(); ++it) { 2265 scoped_refptr<const Extension> extension = 2266 registry_->blacklisted_extensions().GetByID(*it); 2267 if (!extension.get()) { 2268 NOTREACHED() << "Extension " << *it << " no longer blocked, " 2269 << "but it was never blocked."; 2270 continue; 2271 } 2272 registry_->RemoveBlacklisted(*it); 2273 extension_prefs_->SetExtensionBlacklisted(extension->id(), false); 2274 AddExtension(extension.get()); 2275 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled", 2276 extension->location(), 2277 Manifest::NUM_LOCATIONS); 2278 } 2279 2280 for (ExtensionIdSet::iterator it = not_yet_blocked.begin(); 2281 it != not_yet_blocked.end(); ++it) { 2282 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); 2283 if (!extension.get()) { 2284 NOTREACHED() << "Extension " << *it << " needs to be " 2285 << "blacklisted, but it's not installed."; 2286 continue; 2287 } 2288 registry_->AddBlacklisted(extension); 2289 extension_prefs_->SetExtensionBlacklistState( 2290 extension->id(), extensions::BLACKLISTED_MALWARE); 2291 UnloadExtension(*it, UnloadedExtensionInfo::REASON_BLACKLIST); 2292 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled", 2293 extension->location(), Manifest::NUM_LOCATIONS); 2294 } 2295} 2296 2297// TODO(oleg): UMA logging 2298void ExtensionService::UpdateGreylistedExtensions( 2299 const ExtensionIdSet& greylist, 2300 const ExtensionIdSet& unchanged, 2301 const extensions::Blacklist::BlacklistStateMap& state_map) { 2302 ExtensionIdSet not_yet_greylisted, no_longer_greylisted; 2303 Partition(greylist_.GetIDs(), 2304 greylist, unchanged, 2305 &no_longer_greylisted, ¬_yet_greylisted); 2306 2307 for (ExtensionIdSet::iterator it = no_longer_greylisted.begin(); 2308 it != no_longer_greylisted.end(); ++it) { 2309 scoped_refptr<const Extension> extension = greylist_.GetByID(*it); 2310 if (!extension.get()) { 2311 NOTREACHED() << "Extension " << *it << " no longer greylisted, " 2312 << "but it was not marked as greylisted."; 2313 continue; 2314 } 2315 2316 greylist_.Remove(*it); 2317 extension_prefs_->SetExtensionBlacklistState(extension->id(), 2318 extensions::NOT_BLACKLISTED); 2319 if (extension_prefs_->GetDisableReasons(extension->id()) & 2320 extensions::Extension::DISABLE_GREYLIST) 2321 EnableExtension(*it); 2322 } 2323 2324 for (ExtensionIdSet::iterator it = not_yet_greylisted.begin(); 2325 it != not_yet_greylisted.end(); ++it) { 2326 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); 2327 if (!extension.get()) { 2328 NOTREACHED() << "Extension " << *it << " needs to be " 2329 << "disabled, but it's not installed."; 2330 continue; 2331 } 2332 greylist_.Insert(extension); 2333 extension_prefs_->SetExtensionBlacklistState(extension->id(), 2334 state_map.find(*it)->second); 2335 if (registry_->enabled_extensions().Contains(extension->id())) 2336 DisableExtension(*it, extensions::Extension::DISABLE_GREYLIST); 2337 } 2338} 2339 2340void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { 2341 update_observers_.AddObserver(observer); 2342} 2343 2344void ExtensionService::RemoveUpdateObserver( 2345 extensions::UpdateObserver* observer) { 2346 update_observers_.RemoveObserver(observer); 2347} 2348 2349// Used only by test code. 2350void ExtensionService::UnloadAllExtensionsInternal() { 2351 profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions(); 2352 2353 registry_->ClearAll(); 2354 system_->runtime_data()->ClearAll(); 2355 2356 // TODO(erikkay) should there be a notification for this? We can't use 2357 // EXTENSION_UNLOADED since that implies that the extension has been disabled 2358 // or uninstalled. 2359} 2360 2361void ExtensionService::OnProfileDestructionStarted() { 2362 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); 2363 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); 2364 it != ids_to_unload.end(); 2365 ++it) { 2366 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); 2367 } 2368} 2369