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