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