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