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