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