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