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