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