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