extension_service.cc revision bb1529ce867d8845a77ec7cdf3e3003ef1771a40
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/shell_window_registry.h" 63#include "chrome/browser/extensions/unpacked_installer.h" 64#include "chrome/browser/extensions/update_observer.h" 65#include "chrome/browser/extensions/updater/extension_updater.h" 66#include "chrome/browser/profiles/profile.h" 67#include "chrome/browser/profiles/profile_manager.h" 68#include "chrome/browser/themes/theme_service.h" 69#include "chrome/browser/themes/theme_service_factory.h" 70#include "chrome/browser/ui/webui/favicon_source.h" 71#include "chrome/browser/ui/webui/ntp/thumbnail_source.h" 72#include "chrome/browser/ui/webui/theme_source.h" 73#include "chrome/common/child_process_logging.h" 74#include "chrome/common/chrome_switches.h" 75#include "chrome/common/chrome_version_info.h" 76#include "chrome/common/extensions/background_info.h" 77#include "chrome/common/extensions/extension.h" 78#include "chrome/common/extensions/extension_constants.h" 79#include "chrome/common/extensions/extension_file_util.h" 80#include "chrome/common/extensions/extension_manifest_constants.h" 81#include "chrome/common/extensions/extension_messages.h" 82#include "chrome/common/extensions/feature_switch.h" 83#include "chrome/common/extensions/features/feature.h" 84#include "chrome/common/extensions/incognito_handler.h" 85#include "chrome/common/extensions/manifest.h" 86#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" 87#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 88#include "chrome/common/extensions/manifest_handlers/shared_module_info.h" 89#include "chrome/common/extensions/manifest_url_handler.h" 90#include "chrome/common/extensions/permissions/permissions_data.h" 91#include "chrome/common/extensions/sync_helper.h" 92#include "chrome/common/pref_names.h" 93#include "chrome/common/startup_metric_utils.h" 94#include "chrome/common/url_constants.h" 95#include "content/public/browser/browser_thread.h" 96#include "content/public/browser/devtools_agent_host.h" 97#include "content/public/browser/notification_service.h" 98#include "content/public/browser/notification_types.h" 99#include "content/public/browser/render_process_host.h" 100#include "content/public/browser/site_instance.h" 101#include "content/public/browser/storage_partition.h" 102#include "content/public/browser/url_data_source.h" 103#include "extensions/common/constants.h" 104#include "extensions/common/error_utils.h" 105#include "grit/generated_resources.h" 106#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 107#include "sync/api/sync_change.h" 108#include "sync/api/sync_error_factory.h" 109#include "ui/webui/web_ui_util.h" 110#include "url/gurl.h" 111#include "webkit/browser/database/database_tracker.h" 112#include "webkit/browser/database/database_util.h" 113 114#if defined(OS_CHROMEOS) 115#include "chrome/browser/chromeos/extensions/install_limiter.h" 116#include "webkit/browser/fileapi/file_system_backend.h" 117#include "webkit/browser/fileapi/file_system_context.h" 118#endif 119 120using content::BrowserContext; 121using content::BrowserThread; 122using content::DevToolsAgentHost; 123using extensions::CrxInstaller; 124using extensions::Extension; 125using extensions::ExtensionIdSet; 126using extensions::ExtensionInfo; 127using extensions::FeatureSwitch; 128using extensions::Manifest; 129using extensions::PermissionMessage; 130using extensions::PermissionMessages; 131using extensions::PermissionSet; 132using extensions::SharedModuleInfo; 133using extensions::UnloadedExtensionInfo; 134 135namespace errors = extension_manifest_errors; 136 137namespace { 138 139// Histogram values for logging events related to externally installed 140// extensions. 141enum ExternalExtensionEvent { 142 EXTERNAL_EXTENSION_INSTALLED = 0, 143 EXTERNAL_EXTENSION_IGNORED, 144 EXTERNAL_EXTENSION_REENABLED, 145 EXTERNAL_EXTENSION_UNINSTALLED, 146 EXTERNAL_EXTENSION_BUCKET_BOUNDARY, 147}; 148 149// Prompt the user this many times before considering an extension acknowledged. 150static const int kMaxExtensionAcknowledgePromptCount = 3; 151 152// Wait this many seconds after an extensions becomes idle before updating it. 153static const int kUpdateIdleDelay = 5; 154 155// Wait this many seconds before trying to garbage collect extensions again. 156static const int kGarbageCollectRetryDelay = 30; 157 158// Wait this many seconds after startup to see if there are any extensions 159// which can be garbage collected. 160static const int kGarbageCollectStartupDelay = 30; 161 162static bool IsSharedModule(const Extension* extension) { 163 return SharedModuleInfo::IsSharedModule(extension); 164} 165 166} // namespace 167 168ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() 169 : background_page_ready(false), 170 being_upgraded(false), 171 has_used_webrequest(false) { 172} 173 174ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() { 175} 176 177// ExtensionService. 178 179const char ExtensionService::kLocalAppSettingsDirectoryName[] = 180 "Local App Settings"; 181const char ExtensionService::kLocalExtensionSettingsDirectoryName[] = 182 "Local Extension Settings"; 183const char ExtensionService::kSyncAppSettingsDirectoryName[] = 184 "Sync App Settings"; 185const char ExtensionService::kSyncExtensionSettingsDirectoryName[] = 186 "Sync Extension Settings"; 187const char ExtensionService::kManagedSettingsDirectoryName[] = 188 "Managed Extension Settings"; 189const char ExtensionService::kStateStoreName[] = "Extension State"; 190const char ExtensionService::kRulesStoreName[] = "Extension Rules"; 191 192void ExtensionService::CheckExternalUninstall(const std::string& id) { 193 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 194 195 // Check if the providers know about this extension. 196 extensions::ProviderCollection::const_iterator i; 197 for (i = external_extension_providers_.begin(); 198 i != external_extension_providers_.end(); ++i) { 199 DCHECK(i->get()->IsReady()); 200 if (i->get()->HasExtension(id)) 201 return; // Yup, known extension, don't uninstall. 202 } 203 204 // We get the list of external extensions to check from preferences. 205 // It is possible that an extension has preferences but is not loaded. 206 // For example, an extension that requires experimental permissions 207 // will not be loaded if the experimental command line flag is not used. 208 // In this case, do not uninstall. 209 if (!GetInstalledExtension(id)) { 210 // We can't call UninstallExtension with an unloaded/invalid 211 // extension ID. 212 LOG(WARNING) << "Attempted uninstallation of unloaded/invalid extension " 213 << "with id: " << id; 214 return; 215 } 216 UninstallExtension(id, true, NULL); 217} 218 219void ExtensionService::SetFileTaskRunnerForTesting( 220 base::SequencedTaskRunner* task_runner) { 221 file_task_runner_ = task_runner; 222} 223 224void ExtensionService::ClearProvidersForTesting() { 225 external_extension_providers_.clear(); 226} 227 228void ExtensionService::AddProviderForTesting( 229 extensions::ExternalProviderInterface* test_provider) { 230 CHECK(test_provider); 231 external_extension_providers_.push_back( 232 linked_ptr<extensions::ExternalProviderInterface>(test_provider)); 233} 234 235bool ExtensionService::OnExternalExtensionUpdateUrlFound( 236 const std::string& id, 237 const GURL& update_url, 238 Manifest::Location location) { 239 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 240 CHECK(Extension::IdIsValid(id)); 241 242 const Extension* extension = GetExtensionById(id, true); 243 if (extension) { 244 // Already installed. Skip this install if the current location has 245 // higher priority than |location|. 246 Manifest::Location current = extension->location(); 247 if (current == Manifest::GetHigherPriorityLocation(current, location)) 248 return false; 249 // Otherwise, overwrite the current installation. 250 } 251 252 // Add |id| to the set of pending extensions. If it can not be added, 253 // then there is already a pending record from a higher-priority install 254 // source. In this case, signal that this extension will not be 255 // installed by returning false. 256 if (!pending_extension_manager()->AddFromExternalUpdateUrl( 257 id, update_url, location)) { 258 return false; 259 } 260 261 update_once_all_providers_are_ready_ = true; 262 return true; 263} 264 265const Extension* ExtensionService::GetInstalledApp(const GURL& url) const { 266 const Extension* extension = extensions_.GetExtensionOrAppByURL(url); 267 return (extension && extension->is_app()) ? extension : NULL; 268} 269 270bool ExtensionService::IsInstalledApp(const GURL& url) const { 271 return !!GetInstalledApp(url); 272} 273 274const Extension* ExtensionService::GetIsolatedAppForRenderer( 275 int renderer_child_id) const { 276 std::set<std::string> extension_ids = 277 process_map_.GetExtensionsInProcess(renderer_child_id); 278 // All apps in one process share the same partition. 279 // It is only possible for the app to have isolated storage 280 // if there is only 1 app in the process. 281 if (extension_ids.size() != 1) 282 return NULL; 283 284 const extensions::Extension* extension = 285 extensions_.GetByID(*(extension_ids.begin())); 286 // We still need to check if the extension has isolated storage, 287 // because it's common for there to be one extension in a process 288 // without isolated storage. 289 if (extension && 290 extensions::AppIsolationInfo::HasIsolatedStorage(extension)) 291 return extension; 292 293 return NULL; 294} 295 296// static 297// This function is used to implement the command-line switch 298// --uninstall-extension, and to uninstall an extension via sync. The LOG 299// statements within this function are used to inform the user if the uninstall 300// cannot be done. 301bool ExtensionService::UninstallExtensionHelper( 302 ExtensionService* extensions_service, 303 const std::string& extension_id) { 304 // We can't call UninstallExtension with an invalid extension ID. 305 if (!extensions_service->GetInstalledExtension(extension_id)) { 306 LOG(WARNING) << "Attempted uninstallation of non-existent extension with " 307 << "id: " << extension_id; 308 return false; 309 } 310 311 // The following call to UninstallExtension will not allow an uninstall of a 312 // policy-controlled extension. 313 string16 error; 314 if (!extensions_service->UninstallExtension(extension_id, false, &error)) { 315 LOG(WARNING) << "Cannot uninstall extension with id " << extension_id 316 << ": " << error; 317 return false; 318 } 319 320 return true; 321} 322 323ExtensionService::ExtensionService(Profile* profile, 324 const CommandLine* command_line, 325 const base::FilePath& install_directory, 326 extensions::ExtensionPrefs* extension_prefs, 327 extensions::Blacklist* blacklist, 328 bool autoupdate_enabled, 329 bool extensions_enabled, 330 extensions::OneShotEvent* ready) 331 : extensions::Blacklist::Observer(blacklist), 332 profile_(profile), 333 system_(extensions::ExtensionSystem::Get(profile)), 334 extension_prefs_(extension_prefs), 335 blacklist_(blacklist), 336 settings_frontend_(extensions::SettingsFrontend::Create(profile)), 337 pending_extension_manager_(*this), 338 install_directory_(install_directory), 339 extensions_enabled_(extensions_enabled), 340 show_extensions_prompts_(true), 341 install_updates_when_idle_(true), 342 ready_(ready), 343 toolbar_model_(this), 344 menu_manager_(profile), 345 event_routers_initialized_(false), 346 update_once_all_providers_are_ready_(false), 347 browser_terminating_(false), 348 installs_delayed_for_gc_(false), 349 is_first_run_(false), 350 app_sync_bundle_(this), 351 extension_sync_bundle_(this) { 352 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 353 354 // Figure out if extension installation should be enabled. 355 if (command_line->HasSwitch(switches::kDisableExtensions) || 356 profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { 357 extensions_enabled_ = false; 358 } 359 360 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 361 content::NotificationService::AllBrowserContextsAndSources()); 362 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, 363 content::NotificationService::AllBrowserContextsAndSources()); 364 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, 365 content::NotificationService::AllBrowserContextsAndSources()); 366 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 367 content::NotificationService::AllBrowserContextsAndSources()); 368 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, 369 content::NotificationService::AllBrowserContextsAndSources()); 370 registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED, 371 content::NotificationService::AllBrowserContextsAndSources()); 372 pref_change_registrar_.Init(profile->GetPrefs()); 373 base::Closure callback = 374 base::Bind(&ExtensionService::OnExtensionInstallPrefChanged, 375 base::Unretained(this)); 376 pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, callback); 377 pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, callback); 378 pref_change_registrar_.Add(prefs::kExtensionAllowedTypes, callback); 379 380 // Set up the ExtensionUpdater 381 if (autoupdate_enabled) { 382 int update_frequency = kDefaultUpdateFrequencySeconds; 383 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { 384 base::StringToInt(command_line->GetSwitchValueASCII( 385 switches::kExtensionsUpdateFrequency), 386 &update_frequency); 387 } 388 updater_.reset(new extensions::ExtensionUpdater(this, 389 extension_prefs, 390 profile->GetPrefs(), 391 profile, 392 blacklist, 393 update_frequency)); 394 } 395 396 component_loader_.reset( 397 new extensions::ComponentLoader(this, 398 profile->GetPrefs(), 399 g_browser_process->local_state())); 400 401 if (extensions_enabled_) { 402 extensions::ExternalProviderImpl::CreateExternalProviders( 403 this, profile_, &external_extension_providers_); 404 } 405 406 // Set this as the ExtensionService for extension sorting to ensure it 407 // cause syncs if required. 408 extension_prefs_->extension_sorting()->SetExtensionService(this); 409 410 is_first_run_ = !extension_prefs_->SetAlertSystemFirstRun(); 411 412#if defined(ENABLE_EXTENSIONS) 413 extension_action_storage_manager_.reset( 414 new extensions::ExtensionActionStorageManager(profile_)); 415#endif 416 417 // How long is the path to the Extensions directory? 418 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ExtensionRootPathLength", 419 install_directory_.value().length(), 0, 500, 100); 420} 421 422const ExtensionSet* ExtensionService::extensions() const { 423 return &extensions_; 424} 425 426const ExtensionSet* ExtensionService::disabled_extensions() const { 427 return &disabled_extensions_; 428} 429 430const ExtensionSet* ExtensionService::terminated_extensions() const { 431 return &terminated_extensions_; 432} 433 434const ExtensionSet* ExtensionService::blacklisted_extensions() const { 435 return &blacklisted_extensions_; 436} 437 438const ExtensionSet* ExtensionService::delayed_installs() const { 439 return &delayed_installs_; 440} 441 442scoped_ptr<const ExtensionSet> 443 ExtensionService::GenerateInstalledExtensionsSet() const { 444 scoped_ptr<ExtensionSet> installed_extensions(new ExtensionSet()); 445 installed_extensions->InsertAll(extensions_); 446 installed_extensions->InsertAll(disabled_extensions_); 447 installed_extensions->InsertAll(terminated_extensions_); 448 installed_extensions->InsertAll(blacklisted_extensions_); 449 return installed_extensions.PassAs<const ExtensionSet>(); 450} 451 452extensions::PendingExtensionManager* 453 ExtensionService::pending_extension_manager() { 454 return &pending_extension_manager_; 455} 456 457ExtensionService::~ExtensionService() { 458 // No need to unload extensions here because they are profile-scoped, and the 459 // profile is in the process of being deleted. 460 461 extensions::ProviderCollection::const_iterator i; 462 for (i = external_extension_providers_.begin(); 463 i != external_extension_providers_.end(); ++i) { 464 extensions::ExternalProviderInterface* provider = i->get(); 465 provider->ServiceShutdown(); 466 } 467} 468 469void ExtensionService::SetSyncStartFlare( 470 const syncer::SyncableService::StartSyncFlare& flare) { 471 flare_ = flare; 472} 473 474void ExtensionService::InitEventRouters() { 475 if (event_routers_initialized_) 476 return; 477 478#if defined(ENABLE_EXTENSIONS) 479 browser_event_router_.reset(new extensions::BrowserEventRouter(profile_)); 480#endif // defined(ENABLE_EXTENSIONS) 481 event_routers_initialized_ = true; 482} 483 484void ExtensionService::Shutdown() { 485 // Do nothing for now. 486} 487 488const Extension* ExtensionService::GetExtensionById( 489 const std::string& id, bool include_disabled) const { 490 int include_mask = INCLUDE_ENABLED; 491 if (include_disabled) { 492 // Include blacklisted extensions here because there are hundreds of 493 // callers of this function, and many might assume that this includes those 494 // that have been disabled due to blacklisting. 495 include_mask |= INCLUDE_DISABLED | INCLUDE_BLACKLISTED; 496 } 497 return GetExtensionById(id, include_mask); 498} 499 500GURL ExtensionService::GetSiteForExtensionId(const std::string& extension_id) { 501 return content::SiteInstance::GetSiteForURL( 502 profile_, 503 Extension::GetBaseURLFromExtensionId(extension_id)); 504} 505 506const Extension* ExtensionService::GetExtensionById( 507 const std::string& id, int include_mask) const { 508 std::string lowercase_id = StringToLowerASCII(id); 509 if (include_mask & INCLUDE_ENABLED) { 510 const Extension* extension = extensions_.GetByID(lowercase_id); 511 if (extension) 512 return extension; 513 } 514 if (include_mask & INCLUDE_DISABLED) { 515 const Extension* extension = disabled_extensions_.GetByID(lowercase_id); 516 if (extension) 517 return extension; 518 } 519 if (include_mask & INCLUDE_TERMINATED) { 520 const Extension* extension = terminated_extensions_.GetByID(lowercase_id); 521 if (extension) 522 return extension; 523 } 524 if (include_mask & INCLUDE_BLACKLISTED) { 525 const Extension* extension = blacklisted_extensions_.GetByID(lowercase_id); 526 if (extension) 527 return extension; 528 } 529 return NULL; 530} 531 532void ExtensionService::Init() { 533 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 534 535 DCHECK(!is_ready()); // Can't redo init. 536 DCHECK_EQ(extensions_.size(), 0u); 537 538 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 539 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) || 540 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) { 541 // The sole purpose of this launch is to install a new extension from CWS 542 // and immediately terminate: loading already installed extensions is 543 // unnecessary and may interfere with the inline install dialog (e.g. if an 544 // extension listens to onStartup and opens a window). 545 SetReadyAndNotifyListeners(); 546 } else { 547 // LoadAllExtensions() calls OnLoadedInstalledExtensions(). 548 component_loader_->LoadAll(); 549 extensions::InstalledLoader(this).LoadAllExtensions(); 550 551 // Finish install (if possible) of extensions that were still delayed while 552 // the browser was shut down. 553 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info( 554 extension_prefs_->GetAllDelayedInstallInfo()); 555 for (size_t i = 0; i < delayed_info->size(); ++i) { 556 ExtensionInfo* info = delayed_info->at(i).get(); 557 scoped_refptr<const Extension> extension(NULL); 558 if (info->extension_manifest) { 559 std::string error; 560 extension = Extension::Create( 561 info->extension_path, 562 info->extension_location, 563 *info->extension_manifest, 564 extension_prefs_->GetDelayedInstallCreationFlags( 565 info->extension_id), 566 info->extension_id, 567 &error); 568 if (extension.get()) 569 delayed_installs_.Insert(extension); 570 } 571 } 572 MaybeFinishDelayedInstallations(); 573 574 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2( 575 extension_prefs_->GetAllDelayedInstallInfo()); 576 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad", 577 delayed_info2->size() - delayed_info->size()); 578 579 SetReadyAndNotifyListeners(); 580 581 // TODO(erikkay) this should probably be deferred to a future point 582 // rather than running immediately at startup. 583 CheckForExternalUpdates(); 584 585 base::MessageLoop::current()->PostDelayedTask( 586 FROM_HERE, 587 base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()), 588 base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay)); 589 590 if (extension_prefs_->NeedsStorageGarbageCollection()) { 591 GarbageCollectIsolatedStorage(); 592 extension_prefs_->SetNeedsStorageGarbageCollection(false); 593 } 594 } 595} 596 597bool ExtensionService::UpdateExtension(const std::string& id, 598 const base::FilePath& extension_path, 599 const GURL& download_url, 600 CrxInstaller** out_crx_installer) { 601 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 602 if (browser_terminating_) { 603 LOG(WARNING) << "Skipping UpdateExtension due to browser shutdown"; 604 // Leak the temp file at extension_path. We don't want to add to the disk 605 // I/O burden at shutdown, we can't rely on the I/O completing anyway, and 606 // the file is in the OS temp directory which should be cleaned up for us. 607 return false; 608 } 609 610 const extensions::PendingExtensionInfo* pending_extension_info = 611 pending_extension_manager()->GetById(id); 612 613 const Extension* extension = GetInstalledExtension(id); 614 if (!pending_extension_info && !extension) { 615 LOG(WARNING) << "Will not update extension " << id 616 << " because it is not installed or pending"; 617 // Delete extension_path since we're not creating a CrxInstaller 618 // that would do it for us. 619 if (!GetFileTaskRunner()->PostTask( 620 FROM_HERE, 621 base::Bind( 622 &extension_file_util::DeleteFile, extension_path, false))) 623 NOTREACHED(); 624 625 return false; 626 } 627 628 // We want a silent install only for non-pending extensions and 629 // pending extensions that have install_silently set. 630 ExtensionInstallPrompt* client = NULL; 631 if (pending_extension_info && !pending_extension_info->install_silently()) 632 client = ExtensionInstallUI::CreateInstallPromptWithProfile(profile_); 633 634 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, client)); 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 if (const Extension* old = GetInstalledExtension(extension->id())) { 2039 is_extension_upgrade = true; 2040 DCHECK_NE(extension, old); 2041 // Other than for unpacked extensions, CrxInstaller should have guaranteed 2042 // that we aren't downgrading. 2043 if (!Manifest::IsUnpackedLocation(extension->location())) 2044 CHECK_GE(extension->version()->CompareTo(*(old->version())), 0); 2045 } 2046 SetBeingUpgraded(extension, is_extension_upgrade); 2047 2048 // The extension is now loaded, remove its data from unloaded extension map. 2049 unloaded_extension_paths_.erase(extension->id()); 2050 2051 // If a terminated extension is loaded, remove it from the terminated list. 2052 UntrackTerminatedExtension(extension->id()); 2053 2054 // If the extension was disabled for a reload, then enable it. 2055 bool reloading = reloading_extensions_.erase(extension->id()) > 0; 2056 2057 // Check if the extension's privileges have changed and mark the 2058 // extension disabled if necessary. 2059 CheckPermissionsIncrease(extension, is_extension_upgrade); 2060 2061 if (is_extension_upgrade && !reloading) { 2062 // To upgrade an extension in place, unload the old one and then load the 2063 // new one. ReloadExtension disables the extension, which is sufficient. 2064 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_UPDATE); 2065 } 2066 2067 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { 2068 // Only prefs is checked for the blacklist. We rely on callers to check the 2069 // blacklist before calling into here, e.g. CrxInstaller checks before 2070 // installation then threads through the install and pending install flow 2071 // of this class, and we check when loading installed extensions. 2072 blacklisted_extensions_.Insert(extension); 2073 } else if (!reloading && 2074 extension_prefs_->IsExtensionDisabled(extension->id())) { 2075 disabled_extensions_.Insert(extension); 2076 SyncExtensionChangeIfNeeded(*extension); 2077 content::NotificationService::current()->Notify( 2078 chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED, 2079 content::Source<Profile>(profile_), 2080 content::Details<const Extension>(extension)); 2081 2082 // Show the extension disabled error if a permissions increase was the 2083 // only reason it was disabled. 2084 if (extension_prefs_->GetDisableReasons(extension->id()) == 2085 Extension::DISABLE_PERMISSIONS_INCREASE) { 2086 extensions::AddExtensionDisabledError(this, extension); 2087 } 2088 } else if (reloading) { 2089 // Replace the old extension with the new version. 2090 CHECK(!disabled_extensions_.Insert(extension)); 2091 EnableExtension(extension->id()); 2092 } else { 2093 // All apps that are displayed in the launcher are ordered by their ordinals 2094 // so we must ensure they have valid ordinals. 2095 if (extension->RequiresSortOrdinal()) { 2096 if (!extension->ShouldDisplayInNewTabPage()) { 2097 extension_prefs_->extension_sorting()->MarkExtensionAsHidden( 2098 extension->id()); 2099 } 2100 extension_prefs_->extension_sorting()->EnsureValidOrdinals( 2101 extension->id(), syncer::StringOrdinal()); 2102 } 2103 2104 extensions_.Insert(extension); 2105 SyncExtensionChangeIfNeeded(*extension); 2106 NotifyExtensionLoaded(extension); 2107 } 2108 SetBeingUpgraded(extension, false); 2109} 2110 2111void ExtensionService::AddComponentExtension(const Extension* extension) { 2112 const std::string old_version_string( 2113 extension_prefs_->GetVersionString(extension->id())); 2114 const Version old_version(old_version_string); 2115 2116 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) { 2117 VLOG(1) << "Component extension " << extension->name() << " (" 2118 << extension->id() << ") installing/upgrading from '" 2119 << old_version_string << "' to " << extension->version()->GetString(); 2120 2121 AddNewOrUpdatedExtension(extension, 2122 Extension::ENABLED_COMPONENT, 2123 extensions::Blacklist::NOT_BLACKLISTED, 2124 syncer::StringOrdinal()); 2125 return; 2126 } 2127 2128 AddExtension(extension); 2129} 2130 2131void ExtensionService::UpdateActivePermissions(const Extension* extension) { 2132 // If the extension has used the optional permissions API, it will have a 2133 // custom set of active permissions defined in the extension prefs. Here, 2134 // we update the extension's active permissions based on the prefs. 2135 scoped_refptr<PermissionSet> active_permissions = 2136 extension_prefs()->GetActivePermissions(extension->id()); 2137 2138 if (active_permissions.get()) { 2139 // We restrict the active permissions to be within the bounds defined in the 2140 // extension's manifest. 2141 // a) active permissions must be a subset of optional + default permissions 2142 // b) active permissions must contains all default permissions 2143 scoped_refptr<PermissionSet> total_permissions = 2144 PermissionSet::CreateUnion( 2145 extensions::PermissionsData::GetRequiredPermissions(extension), 2146 extensions::PermissionsData::GetOptionalPermissions(extension)); 2147 2148 // Make sure the active permissions contain no more than optional + default. 2149 scoped_refptr<PermissionSet> adjusted_active = 2150 PermissionSet::CreateIntersection( 2151 total_permissions.get(), active_permissions.get()); 2152 2153 // Make sure the active permissions contain the default permissions. 2154 adjusted_active = PermissionSet::CreateUnion( 2155 extensions::PermissionsData::GetRequiredPermissions(extension), 2156 adjusted_active.get()); 2157 2158 extensions::PermissionsUpdater perms_updater(profile()); 2159 perms_updater.UpdateActivePermissions(extension, adjusted_active.get()); 2160 } 2161} 2162 2163void ExtensionService::CheckPermissionsIncrease(const Extension* extension, 2164 bool is_extension_upgrade) { 2165 UpdateActivePermissions(extension); 2166 2167 // We keep track of all permissions the user has granted each extension. 2168 // This allows extensions to gracefully support backwards compatibility 2169 // by including unknown permissions in their manifests. When the user 2170 // installs the extension, only the recognized permissions are recorded. 2171 // When the unknown permissions become recognized (e.g., through browser 2172 // upgrade), we can prompt the user to accept these new permissions. 2173 // Extensions can also silently upgrade to less permissions, and then 2174 // silently upgrade to a version that adds these permissions back. 2175 // 2176 // For example, pretend that Chrome 10 includes a permission "omnibox" 2177 // for an API that adds suggestions to the omnibox. An extension can 2178 // maintain backwards compatibility while still having "omnibox" in the 2179 // manifest. If a user installs the extension on Chrome 9, the browser 2180 // will record the permissions it recognized, not including "omnibox." 2181 // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome 2182 // will disable the extension and prompt the user to approve the increase 2183 // in privileges. The extension could then release a new version that 2184 // removes the "omnibox" permission. When the user upgrades, Chrome will 2185 // still remember that "omnibox" had been granted, so that if the 2186 // extension once again includes "omnibox" in an upgrade, the extension 2187 // can upgrade without requiring this user's approval. 2188 int disable_reasons = extension_prefs_->GetDisableReasons(extension->id()); 2189 2190 bool auto_grant_permission = 2191 (!is_extension_upgrade && extension->was_installed_by_default()) || 2192 chrome::IsRunningInForcedAppMode(); 2193 // Silently grant all active permissions to default apps only on install. 2194 // After install they should behave like other apps. 2195 // Silently grant all active permissions to apps install in kiosk mode on both 2196 // install and update. 2197 if (auto_grant_permission) 2198 GrantPermissions(extension); 2199 2200 bool is_privilege_increase = false; 2201 // We only need to compare the granted permissions to the current permissions 2202 // if the extension is not allowed to silently increase its permissions. 2203 if (!extensions::PermissionsData::CanSilentlyIncreasePermissions(extension) && 2204 !auto_grant_permission) { 2205 // Add all the recognized permissions if the granted permissions list 2206 // hasn't been initialized yet. 2207 scoped_refptr<PermissionSet> granted_permissions = 2208 extension_prefs_->GetGrantedPermissions(extension->id()); 2209 CHECK(granted_permissions.get()); 2210 2211 // Here, we check if an extension's privileges have increased in a manner 2212 // that requires the user's approval. This could occur because the browser 2213 // upgraded and recognized additional privileges, or an extension upgrades 2214 // to a version that requires additional privileges. 2215 is_privilege_increase = granted_permissions->HasLessPrivilegesThan( 2216 extension->GetActivePermissions().get(), extension->GetType()); 2217 } 2218 2219 if (is_extension_upgrade) { 2220 // If the extension was already disabled, suppress any alerts for becoming 2221 // disabled on permissions increase. 2222 bool previously_disabled = 2223 extension_prefs_->IsExtensionDisabled(extension->id()); 2224 // Legacy disabled extensions do not have a disable reason. Infer that if 2225 // there was no permission increase, it was likely disabled by the user. 2226 if (previously_disabled && disable_reasons == Extension::DISABLE_NONE && 2227 !extension_prefs_->DidExtensionEscalatePermissions(extension->id())) { 2228 disable_reasons |= Extension::DISABLE_USER_ACTION; 2229 } 2230 // Extensions that came to us disabled from sync need a similar inference, 2231 // except based on the new version's permissions. 2232 if (previously_disabled && 2233 disable_reasons == Extension::DISABLE_UNKNOWN_FROM_SYNC) { 2234 // Remove the DISABLE_UNKNOWN_FROM_SYNC reason. 2235 extension_prefs_->ClearDisableReasons(extension->id()); 2236 if (!is_privilege_increase) 2237 disable_reasons |= Extension::DISABLE_USER_ACTION; 2238 } 2239 disable_reasons &= ~Extension::DISABLE_UNKNOWN_FROM_SYNC; 2240 } 2241 2242 // Extension has changed permissions significantly. Disable it. A 2243 // notification should be sent by the caller. 2244 if (is_privilege_increase) { 2245 disable_reasons |= Extension::DISABLE_PERMISSIONS_INCREASE; 2246 if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id())) { 2247 RecordPermissionMessagesHistogram( 2248 extension, "Extensions.Permissions_AutoDisable"); 2249 } 2250 extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED); 2251 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); 2252 } 2253 if (disable_reasons != Extension::DISABLE_NONE) { 2254 extension_prefs_->AddDisableReason( 2255 extension->id(), 2256 static_cast<Extension::DisableReason>(disable_reasons)); 2257 } 2258} 2259 2260void ExtensionService::UpdateActiveExtensionsInCrashReporter() { 2261 std::set<std::string> extension_ids; 2262 for (ExtensionSet::const_iterator iter = extensions_.begin(); 2263 iter != extensions_.end(); ++iter) { 2264 const Extension* extension = iter->get(); 2265 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) 2266 extension_ids.insert(extension->id()); 2267 } 2268 2269 child_process_logging::SetActiveExtensions(extension_ids); 2270} 2271 2272ExtensionService::ImportStatus ExtensionService::SatisfyImports( 2273 const Extension* extension) { 2274 ImportStatus status = IMPORT_STATUS_OK; 2275 std::vector<std::string> pending; 2276 // TODO(elijahtaylor): Message the user if there is a failure that is 2277 // unrecoverable. 2278 if (SharedModuleInfo::ImportsModules(extension)) { 2279 const std::vector<SharedModuleInfo::ImportInfo>& imports = 2280 SharedModuleInfo::GetImports(extension); 2281 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; 2282 for (i = imports.begin(); i != imports.end(); ++i) { 2283 Version version_required(i->minimum_version); 2284 const Extension* imported_module = 2285 GetExtensionById(i->extension_id, true); 2286 if (!imported_module) { 2287 if (extension->from_webstore()) { 2288 status = IMPORT_STATUS_UNSATISFIED; 2289 pending.push_back(i->extension_id); 2290 } else { 2291 return IMPORT_STATUS_UNRECOVERABLE; 2292 } 2293 } else if (!SharedModuleInfo::IsSharedModule(imported_module)) { 2294 return IMPORT_STATUS_UNRECOVERABLE; 2295 } else if (version_required.IsValid() && 2296 imported_module->version()->CompareTo(version_required) < 0) { 2297 if (imported_module->from_webstore()) { 2298 status = IMPORT_STATUS_UNSATISFIED; 2299 } else { 2300 return IMPORT_STATUS_UNRECOVERABLE; 2301 } 2302 } 2303 } 2304 } 2305 if (status == IMPORT_STATUS_UNSATISFIED) { 2306 for (std::vector<std::string>::const_iterator iter = pending.begin(); 2307 iter != pending.end(); 2308 ++iter) { 2309 pending_extension_manager()->AddFromExtensionImport( 2310 *iter, 2311 extension_urls::GetWebstoreUpdateUrl(), 2312 IsSharedModule); 2313 } 2314 CheckForUpdatesSoon(); 2315 } 2316 return status; 2317} 2318 2319scoped_ptr<const ExtensionSet> 2320 ExtensionService::GetDependentExtensions(const Extension* extension) { 2321 scoped_ptr<ExtensionSet> dependents(new ExtensionSet()); 2322 scoped_ptr<ExtensionSet> set_to_check(new ExtensionSet()); 2323 if (SharedModuleInfo::IsSharedModule(extension)) { 2324 set_to_check->InsertAll(disabled_extensions_); 2325 set_to_check->InsertAll(delayed_installs_); 2326 set_to_check->InsertAll(extensions_); 2327 for (ExtensionSet::const_iterator iter = set_to_check->begin(); 2328 iter != set_to_check->end(); ++iter) { 2329 if (SharedModuleInfo::ImportsExtensionById(iter->get(), 2330 extension->id())) { 2331 dependents->Insert(*iter); 2332 } 2333 } 2334 } 2335 return dependents.PassAs<const ExtensionSet>(); 2336} 2337 2338void ExtensionService::PruneSharedModulesOnUninstall( 2339 const Extension* extension) { 2340 if (SharedModuleInfo::ImportsModules(extension)) { 2341 const std::vector<SharedModuleInfo::ImportInfo>& imports = 2342 SharedModuleInfo::GetImports(extension); 2343 std::vector<SharedModuleInfo::ImportInfo>::const_iterator i; 2344 for (i = imports.begin(); i != imports.end(); ++i) { 2345 const Extension* imported_module = 2346 GetExtensionById(i->extension_id, true); 2347 if (imported_module && imported_module->from_webstore()) { 2348 scoped_ptr<const ExtensionSet> dependents = 2349 GetDependentExtensions(imported_module); 2350 if (dependents->size() == 0) { 2351 UninstallExtension(i->extension_id, false, NULL); 2352 } 2353 } 2354 } 2355 } 2356} 2357 2358void ExtensionService::OnExtensionInstalled( 2359 const Extension* extension, 2360 const syncer::StringOrdinal& page_ordinal, 2361 bool has_requirement_errors, 2362 extensions::Blacklist::BlacklistState blacklist_state, 2363 bool wait_for_idle) { 2364 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2365 2366 const std::string& id = extension->id(); 2367 bool initial_enable = ShouldEnableOnInstall(extension); 2368 const extensions::PendingExtensionInfo* pending_extension_info = NULL; 2369 if ((pending_extension_info = pending_extension_manager()->GetById(id))) { 2370 if (!pending_extension_info->ShouldAllowInstall(extension)) { 2371 pending_extension_manager()->Remove(id); 2372 2373 LOG(WARNING) << "ShouldAllowInstall() returned false for " 2374 << id << " of type " << extension->GetType() 2375 << " and update URL " 2376 << extensions::ManifestURL::GetUpdateURL(extension).spec() 2377 << "; not installing"; 2378 2379 // Delete the extension directory since we're not going to 2380 // load it. 2381 if (!GetFileTaskRunner()->PostTask( 2382 FROM_HERE, 2383 base::Bind(&extension_file_util::DeleteFile, 2384 extension->path(), true))) { 2385 NOTREACHED(); 2386 } 2387 return; 2388 } 2389 2390 pending_extension_manager()->Remove(id); 2391 } else { 2392 // We explicitly want to re-enable an uninstalled external 2393 // extension; if we're here, that means the user is manually 2394 // installing the extension. 2395 if (IsExternalExtensionUninstalled(id)) { 2396 initial_enable = true; 2397 } 2398 } 2399 2400 // Unsupported requirements overrides the management policy. 2401 if (has_requirement_errors) { 2402 initial_enable = false; 2403 extension_prefs_->AddDisableReason( 2404 id, Extension::DISABLE_UNSUPPORTED_REQUIREMENT); 2405 // If the extension was disabled because of unsupported requirements but 2406 // now supports all requirements after an update and there are not other 2407 // disable reasons, enable it. 2408 } else if (extension_prefs_->GetDisableReasons(id) == 2409 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) { 2410 initial_enable = true; 2411 extension_prefs_->ClearDisableReasons(id); 2412 } 2413 2414 if (blacklist_state == extensions::Blacklist::BLACKLISTED) { 2415 // Installation of a blacklisted extension can happen from sync, policy, 2416 // etc, where to maintain consistency we need to install it, just never 2417 // load it (see AddExtension). Usually it should be the job of callers to 2418 // incercept blacklisted extension earlier (e.g. CrxInstaller, before even 2419 // showing the install dialogue). 2420 extension_prefs()->AcknowledgeBlacklistedExtension(id); 2421 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall", 2422 extension->location(), 2423 Manifest::NUM_LOCATIONS); 2424 } 2425 2426 if (!GetInstalledExtension(extension->id())) { 2427 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType", 2428 extension->GetType(), 100); 2429 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallSource", 2430 extension->location(), Manifest::NUM_LOCATIONS); 2431 RecordPermissionMessagesHistogram( 2432 extension, "Extensions.Permissions_Install"); 2433 } else { 2434 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateType", 2435 extension->GetType(), 100); 2436 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateSource", 2437 extension->location(), Manifest::NUM_LOCATIONS); 2438 } 2439 2440 // Certain extension locations are specific enough that we can 2441 // auto-acknowledge any extension that came from one of them. 2442 if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD) 2443 AcknowledgeExternalExtension(extension->id()); 2444 const Extension::State initial_state = 2445 initial_enable ? Extension::ENABLED : Extension::DISABLED; 2446 if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { 2447 extension_prefs_->SetDelayedInstallInfo( 2448 extension, 2449 initial_state, 2450 blacklist_state, 2451 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, 2452 page_ordinal); 2453 2454 // Transfer ownership of |extension|. 2455 delayed_installs_.Insert(extension); 2456 2457 // Notify extension of available update. 2458 extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent( 2459 profile_, id, extension->manifest()->value()); 2460 2461 // Notify observers that app update is available. 2462 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 2463 OnAppUpdateAvailable(extension->id())); 2464 return; 2465 } 2466 2467 ImportStatus status = SatisfyImports(extension); 2468 if (installs_delayed_for_gc()) { 2469 extension_prefs_->SetDelayedInstallInfo( 2470 extension, 2471 initial_state, 2472 blacklist_state, 2473 extensions::ExtensionPrefs::DELAY_REASON_GC, 2474 page_ordinal); 2475 delayed_installs_.Insert(extension); 2476 } else if (status != IMPORT_STATUS_OK) { 2477 if (status == IMPORT_STATUS_UNSATISFIED) { 2478 extension_prefs_->SetDelayedInstallInfo( 2479 extension, 2480 initial_state, 2481 blacklist_state, 2482 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS, 2483 page_ordinal); 2484 delayed_installs_.Insert(extension); 2485 } 2486 } else { 2487 AddNewOrUpdatedExtension(extension, 2488 initial_state, 2489 blacklist_state, 2490 page_ordinal); 2491 } 2492} 2493 2494void ExtensionService::AddNewOrUpdatedExtension( 2495 const Extension* extension, 2496 Extension::State initial_state, 2497 extensions::Blacklist::BlacklistState blacklist_state, 2498 const syncer::StringOrdinal& page_ordinal) { 2499 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2500 extension_prefs_->OnExtensionInstalled(extension, 2501 initial_state, 2502 blacklist_state, 2503 page_ordinal); 2504 delayed_installs_.Remove(extension->id()); 2505 FinishInstallation(extension); 2506} 2507 2508void ExtensionService::MaybeFinishDelayedInstallation( 2509 const std::string& extension_id) { 2510 // Check if the extension already got installed. 2511 if (!delayed_installs_.Contains(extension_id)) 2512 return; 2513 extensions::ExtensionPrefs::DelayReason reason = 2514 extension_prefs_->GetDelayedInstallReason(extension_id); 2515 2516 // Check if the extension is idle. DELAY_REASON_NONE is used for older 2517 // preferences files that will not have set this field but it was previously 2518 // only used for idle updates. 2519 if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE || 2520 reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) && 2521 is_ready() && !IsExtensionIdle(extension_id)) 2522 return; 2523 2524 const Extension* extension = delayed_installs_.GetByID(extension_id); 2525 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) { 2526 ImportStatus status = SatisfyImports(extension); 2527 if (status != IMPORT_STATUS_OK) { 2528 if (status == IMPORT_STATUS_UNRECOVERABLE) { 2529 delayed_installs_.Remove(extension_id); 2530 // Make sure no version of the extension is actually installed, (i.e., 2531 // that this delayed install was not an update). 2532 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get()); 2533 extension_prefs_->DeleteExtensionPrefs(extension_id); 2534 } 2535 return; 2536 } 2537 } 2538 2539 FinishDelayedInstallation(extension_id); 2540} 2541 2542void ExtensionService::FinishDelayedInstallation( 2543 const std::string& extension_id) { 2544 scoped_refptr<const Extension> extension( 2545 GetPendingExtensionUpdate(extension_id)); 2546 CHECK(extension.get()); 2547 delayed_installs_.Remove(extension_id); 2548 2549 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) 2550 NOTREACHED(); 2551 2552 FinishInstallation(extension.get()); 2553} 2554 2555void ExtensionService::FinishInstallation(const Extension* extension) { 2556 const extensions::Extension* existing_extension = 2557 GetInstalledExtension(extension->id()); 2558 bool is_update = false; 2559 std::string old_name; 2560 if (existing_extension) { 2561 is_update = true; 2562 old_name = existing_extension->name(); 2563 } 2564 extensions::InstalledExtensionInfo details(extension, is_update, old_name); 2565 content::NotificationService::current()->Notify( 2566 chrome::NOTIFICATION_EXTENSION_INSTALLED, 2567 content::Source<Profile>(profile_), 2568 content::Details<const extensions::InstalledExtensionInfo>(&details)); 2569 2570 bool unacknowledged_external = IsUnacknowledgedExternalExtension(extension); 2571 2572 // Unpacked extensions default to allowing file access, but if that has been 2573 // overridden, don't reset the value. 2574 if (Manifest::ShouldAlwaysAllowFileAccess(extension->location()) && 2575 !extension_prefs_->HasAllowFileAccessSetting(extension->id())) { 2576 extension_prefs_->SetAllowFileAccess(extension->id(), true); 2577 } 2578 2579 AddExtension(extension); 2580 2581#if defined(ENABLE_THEMES) 2582 // We do this here since AddExtension() is always called on browser startup, 2583 // and we only really care about the last theme installed. 2584 // If that ever changes and we have to move this code somewhere 2585 // else, it should be somewhere that's not in the startup path. 2586 if (extension->is_theme() && extensions_.GetByID(extension->id())) { 2587 DCHECK_EQ(extensions_.GetByID(extension->id()), extension); 2588 // Now that the theme extension is visible from outside the 2589 // ExtensionService, notify the ThemeService about the 2590 // newly-installed theme. 2591 ThemeServiceFactory::GetForProfile(profile_)->SetTheme(extension); 2592 } 2593#endif 2594 2595 // If this is a new external extension that was disabled, alert the user 2596 // so he can reenable it. We do this last so that it has already been 2597 // added to our list of extensions. 2598 if (unacknowledged_external) { 2599 UpdateExternalExtensionAlert(); 2600 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent", 2601 EXTERNAL_EXTENSION_INSTALLED, 2602 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); 2603 if (extensions::ManifestURL::UpdatesFromGallery(extension)) { 2604 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventWebstore", 2605 EXTERNAL_EXTENSION_INSTALLED, 2606 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); 2607 } else { 2608 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventNonWebstore", 2609 EXTERNAL_EXTENSION_INSTALLED, 2610 EXTERNAL_EXTENSION_BUCKET_BOUNDARY); 2611 } 2612 } 2613 2614 // Check extensions that may have been delayed only because this shared module 2615 // was not available. 2616 if (SharedModuleInfo::IsSharedModule(extension)) { 2617 MaybeFinishDelayedInstallations(); 2618 } 2619} 2620 2621const Extension* ExtensionService::GetPendingExtensionUpdate( 2622 const std::string& id) const { 2623 return delayed_installs_.GetByID(id); 2624} 2625 2626void ExtensionService::TrackTerminatedExtension(const Extension* extension) { 2627 if (!terminated_extensions_.Contains(extension->id())) 2628 terminated_extensions_.Insert(make_scoped_refptr(extension)); 2629 2630 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); 2631} 2632 2633void ExtensionService::UntrackTerminatedExtension(const std::string& id) { 2634 std::string lowercase_id = StringToLowerASCII(id); 2635 const Extension* extension = terminated_extensions_.GetByID(lowercase_id); 2636 terminated_extensions_.Remove(lowercase_id); 2637 if (extension) { 2638 content::NotificationService::current()->Notify( 2639 chrome::NOTIFICATION_EXTENSION_REMOVED, 2640 content::Source<Profile>(profile_), 2641 content::Details<const Extension>(extension)); 2642 } 2643} 2644 2645const Extension* ExtensionService::GetTerminatedExtension( 2646 const std::string& id) const { 2647 return GetExtensionById(id, INCLUDE_TERMINATED); 2648} 2649 2650const Extension* ExtensionService::GetInstalledExtension( 2651 const std::string& id) const { 2652 int include_mask = INCLUDE_ENABLED | 2653 INCLUDE_DISABLED | 2654 INCLUDE_TERMINATED | 2655 INCLUDE_BLACKLISTED; 2656 return GetExtensionById(id, include_mask); 2657} 2658 2659bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) { 2660 // Allow bindings for all packaged extensions and component hosted apps. 2661 const Extension* extension = extensions_.GetExtensionOrAppByURL(url); 2662 return extension && (!extension->is_hosted_app() || 2663 extension->location() == Manifest::COMPONENT); 2664} 2665 2666bool ExtensionService::ShouldBlockUrlInBrowserTab(GURL* url) { 2667 const Extension* extension = extensions_.GetExtensionOrAppByURL(*url); 2668 if (extension && extension->is_platform_app()) { 2669 *url = GURL(chrome::kExtensionInvalidRequestURL); 2670 return true; 2671 } 2672 2673 return false; 2674} 2675 2676bool ExtensionService::OnExternalExtensionFileFound( 2677 const std::string& id, 2678 const Version* version, 2679 const base::FilePath& path, 2680 Manifest::Location location, 2681 int creation_flags, 2682 bool mark_acknowledged) { 2683 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2684 CHECK(Extension::IdIsValid(id)); 2685 if (extension_prefs_->IsExternalExtensionUninstalled(id)) 2686 return false; 2687 2688 // Before even bothering to unpack, check and see if we already have this 2689 // version. This is important because these extensions are going to get 2690 // installed on every startup. 2691 const Extension* existing = GetExtensionById(id, true); 2692 2693 if (existing) { 2694 // The default apps will have the location set as INTERNAL. Since older 2695 // default apps are installed as EXTERNAL, we override them. However, if the 2696 // app is already installed as internal, then do the version check. 2697 // TODO(grv) : Remove after Q1-2013. 2698 bool is_default_apps_migration = 2699 (location == Manifest::INTERNAL && 2700 Manifest::IsExternalLocation(existing->location())); 2701 2702 if (!is_default_apps_migration) { 2703 DCHECK(version); 2704 2705 switch (existing->version()->CompareTo(*version)) { 2706 case -1: // existing version is older, we should upgrade 2707 break; 2708 case 0: // existing version is same, do nothing 2709 return false; 2710 case 1: // existing version is newer, uh-oh 2711 LOG(WARNING) << "Found external version of extension " << id 2712 << "that is older than current version. Current version " 2713 << "is: " << existing->VersionString() << ". New " 2714 << "version is: " << version->GetString() 2715 << ". Keeping current version."; 2716 return false; 2717 } 2718 } 2719 } 2720 2721 // If the extension is already pending, don't start an install. 2722 if (!pending_extension_manager()->AddFromExternalFile( 2723 id, location, *version)) { 2724 return false; 2725 } 2726 2727 // no client (silent install) 2728 scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, NULL)); 2729 installer->set_install_source(location); 2730 installer->set_expected_id(id); 2731 installer->set_expected_version(*version); 2732 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE); 2733 installer->set_creation_flags(creation_flags); 2734#if defined(OS_CHROMEOS) 2735 extensions::InstallLimiter::Get(profile_)->Add(installer, path); 2736#else 2737 installer->InstallCrx(path); 2738#endif 2739 2740 // Depending on the source, a new external extension might not need a user 2741 // notification on installation. For such extensions, mark them acknowledged 2742 // now to suppress the notification. 2743 if (mark_acknowledged) 2744 AcknowledgeExternalExtension(id); 2745 2746 return true; 2747} 2748 2749void ExtensionService::ReportExtensionLoadError( 2750 const base::FilePath& extension_path, 2751 const std::string &error, 2752 bool be_noisy) { 2753 content::NotificationService::current()->Notify( 2754 chrome::NOTIFICATION_EXTENSION_LOAD_ERROR, 2755 content::Source<Profile>(profile_), 2756 content::Details<const std::string>(&error)); 2757 2758 std::string path_str = UTF16ToUTF8(extension_path.LossyDisplayName()); 2759 string16 message = UTF8ToUTF16(base::StringPrintf( 2760 "Could not load extension from '%s'. %s", 2761 path_str.c_str(), error.c_str())); 2762 ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy); 2763} 2764 2765void ExtensionService::DidCreateRenderViewForBackgroundPage( 2766 extensions::ExtensionHost* host) { 2767 OrphanedDevTools::iterator iter = 2768 orphaned_dev_tools_.find(host->extension_id()); 2769 if (iter == orphaned_dev_tools_.end()) 2770 return; 2771 2772 iter->second->ConnectRenderViewHost(host->render_view_host()); 2773 orphaned_dev_tools_.erase(iter); 2774} 2775 2776void ExtensionService::Observe(int type, 2777 const content::NotificationSource& source, 2778 const content::NotificationDetails& details) { 2779 switch (type) { 2780 case chrome::NOTIFICATION_APP_TERMINATING: 2781 // Shutdown has started. Don't start any more extension installs. 2782 // (We cannot use ExtensionService::Shutdown() for this because it 2783 // happens too late in browser teardown.) 2784 browser_terminating_ = true; 2785 break; 2786 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: { 2787 if (profile_ != 2788 content::Source<Profile>(source).ptr()->GetOriginalProfile()) { 2789 break; 2790 } 2791 2792 extensions::ExtensionHost* host = 2793 content::Details<extensions::ExtensionHost>(details).ptr(); 2794 2795 // Mark the extension as terminated and Unload it. We want it to 2796 // be in a consistent state: either fully working or not loaded 2797 // at all, but never half-crashed. We do it in a PostTask so 2798 // that other handlers of this notification will still have 2799 // access to the Extension and ExtensionHost. 2800 base::MessageLoop::current()->PostTask( 2801 FROM_HERE, 2802 base::Bind( 2803 &ExtensionService::TrackTerminatedExtension, 2804 AsWeakPtr(), 2805 host->extension())); 2806 break; 2807 } 2808 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: { 2809 content::RenderProcessHost* process = 2810 content::Source<content::RenderProcessHost>(source).ptr(); 2811 Profile* host_profile = 2812 Profile::FromBrowserContext(process->GetBrowserContext()); 2813 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile())) 2814 break; 2815 2816 // Extensions need to know the channel for API restrictions. 2817 process->Send(new ExtensionMsg_SetChannel( 2818 extensions::Feature::GetCurrentChannel())); 2819 2820 // Platform apps need to know the system font. 2821 scoped_ptr<base::DictionaryValue> fonts(new base::DictionaryValue); 2822 webui::SetFontAndTextDirection(fonts.get()); 2823 std::string font_family, font_size; 2824 fonts->GetString("fontfamily", &font_family); 2825 fonts->GetString("fontsize", &font_size); 2826 process->Send(new ExtensionMsg_SetSystemFont( 2827 font_family, font_size)); 2828 2829 // Valid extension function names, used to setup bindings in renderer. 2830 std::vector<std::string> function_names; 2831 ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names); 2832 process->Send(new ExtensionMsg_SetFunctionNames(function_names)); 2833 2834 // Scripting whitelist. This is modified by tests and must be communicated 2835 // to renderers. 2836 process->Send(new ExtensionMsg_SetScriptingWhitelist( 2837 *Extension::GetScriptingWhitelist())); 2838 2839 // Loaded extensions. 2840 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions; 2841 for (ExtensionSet::const_iterator iter = extensions_.begin(); 2842 iter != extensions_.end(); ++iter) { 2843 // Renderers don't need to know about themes. 2844 if (!(*iter)->is_theme()) 2845 loaded_extensions.push_back(ExtensionMsg_Loaded_Params(iter->get())); 2846 } 2847 process->Send(new ExtensionMsg_Loaded(loaded_extensions)); 2848 break; 2849 } 2850 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { 2851 content::RenderProcessHost* process = 2852 content::Source<content::RenderProcessHost>(source).ptr(); 2853 Profile* host_profile = 2854 Profile::FromBrowserContext(process->GetBrowserContext()); 2855 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile())) 2856 break; 2857 2858 process_map_.RemoveAllFromProcess(process->GetID()); 2859 BrowserThread::PostTask( 2860 BrowserThread::IO, FROM_HERE, 2861 base::Bind(&ExtensionInfoMap::UnregisterAllExtensionsInProcess, 2862 system_->info_map(), 2863 process->GetID())); 2864 break; 2865 } 2866 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { 2867 extensions::ExtensionHost* host = 2868 content::Details<extensions::ExtensionHost>(details).ptr(); 2869 std::string extension_id = host->extension_id(); 2870 if (delayed_installs_.Contains(extension_id)) { 2871 // We were waiting for this extension to become idle, it now might have, 2872 // so maybe finish installation. 2873 base::MessageLoop::current()->PostDelayedTask( 2874 FROM_HERE, 2875 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, 2876 AsWeakPtr(), extension_id), 2877 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); 2878 } 2879 break; 2880 } 2881 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: { 2882 // Notify extensions that chrome update is available. 2883 extensions::RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent( 2884 profile_); 2885 2886 // Notify observers that chrome update is available. 2887 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 2888 OnChromeUpdateAvailable()); 2889 break; 2890 } 2891 2892 default: 2893 NOTREACHED() << "Unexpected notification type."; 2894 } 2895} 2896 2897void ExtensionService::OnExtensionInstallPrefChanged() { 2898 IdentifyAlertableExtensions(); 2899 CheckManagementPolicy(); 2900} 2901 2902bool ExtensionService::HasApps() const { 2903 return !GetAppIds().empty(); 2904} 2905 2906ExtensionIdSet ExtensionService::GetAppIds() const { 2907 ExtensionIdSet result; 2908 for (ExtensionSet::const_iterator it = extensions_.begin(); 2909 it != extensions_.end(); ++it) { 2910 if ((*it)->is_app() && (*it)->location() != Manifest::COMPONENT) 2911 result.insert((*it)->id()); 2912 } 2913 2914 return result; 2915} 2916 2917bool ExtensionService::IsBackgroundPageReady(const Extension* extension) const { 2918 if (!extensions::BackgroundInfo::HasPersistentBackgroundPage(extension)) 2919 return true; 2920 ExtensionRuntimeDataMap::const_iterator it = 2921 extension_runtime_data_.find(extension->id()); 2922 return it == extension_runtime_data_.end() ? false : 2923 it->second.background_page_ready; 2924} 2925 2926void ExtensionService::SetBackgroundPageReady(const Extension* extension) { 2927 DCHECK(extensions::BackgroundInfo::HasBackgroundPage(extension)); 2928 extension_runtime_data_[extension->id()].background_page_ready = true; 2929 content::NotificationService::current()->Notify( 2930 chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, 2931 content::Source<const Extension>(extension), 2932 content::NotificationService::NoDetails()); 2933} 2934 2935void ExtensionService::InspectBackgroundPage(const Extension* extension) { 2936 DCHECK(extension); 2937 2938 ExtensionProcessManager* pm = system_->process_manager(); 2939 extensions::LazyBackgroundTaskQueue* queue = 2940 system_->lazy_background_task_queue(); 2941 2942 extensions::ExtensionHost* host = 2943 pm->GetBackgroundHostForExtension(extension->id()); 2944 if (host) { 2945 InspectExtensionHost(host); 2946 } else { 2947 queue->AddPendingTask( 2948 profile_, extension->id(), 2949 base::Bind(&ExtensionService::InspectExtensionHost, 2950 base::Unretained(this))); 2951 } 2952} 2953 2954bool ExtensionService::IsBeingUpgraded(const Extension* extension) const { 2955 ExtensionRuntimeDataMap::const_iterator it = 2956 extension_runtime_data_.find(extension->id()); 2957 return it == extension_runtime_data_.end() ? false : 2958 it->second.being_upgraded; 2959} 2960 2961void ExtensionService::SetBeingUpgraded(const Extension* extension, 2962 bool value) { 2963 extension_runtime_data_[extension->id()].being_upgraded = value; 2964} 2965 2966bool ExtensionService::IsBeingReloaded( 2967 const std::string& extension_id) const { 2968 return ContainsKey(extensions_being_reloaded_, extension_id); 2969} 2970 2971void ExtensionService::SetBeingReloaded(const std::string& extension_id, 2972 bool isBeingReloaded) { 2973 if (isBeingReloaded) 2974 extensions_being_reloaded_.insert(extension_id); 2975 else 2976 extensions_being_reloaded_.erase(extension_id); 2977} 2978 2979bool ExtensionService::HasUsedWebRequest(const Extension* extension) const { 2980 ExtensionRuntimeDataMap::const_iterator it = 2981 extension_runtime_data_.find(extension->id()); 2982 return it == extension_runtime_data_.end() ? false : 2983 it->second.has_used_webrequest; 2984} 2985 2986void ExtensionService::SetHasUsedWebRequest(const Extension* extension, 2987 bool value) { 2988 extension_runtime_data_[extension->id()].has_used_webrequest = value; 2989} 2990 2991void ExtensionService::InspectExtensionHost( 2992 extensions::ExtensionHost* host) { 2993 if (host) 2994 DevToolsWindow::OpenDevToolsWindow(host->render_view_host()); 2995} 2996 2997bool ExtensionService::ShouldEnableOnInstall(const Extension* extension) { 2998 // Extensions installed by policy can't be disabled. So even if a previous 2999 // installation disabled the extension, make sure it is now enabled. 3000 if (system_->management_policy()->MustRemainEnabled(extension, NULL)) 3001 return true; 3002 3003 if (extension_prefs_->IsExtensionDisabled(extension->id())) 3004 return false; 3005 3006 if (FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) { 3007 // External extensions are initially disabled. We prompt the user before 3008 // enabling them. Hosted apps are excepted because they are not dangerous 3009 // (they need to be launched by the user anyway). 3010 if (extension->GetType() != Manifest::TYPE_HOSTED_APP && 3011 Manifest::IsExternalLocation(extension->location()) && 3012 !extension_prefs_->IsExternalExtensionAcknowledged(extension->id())) { 3013 return false; 3014 } 3015 } 3016 3017 return true; 3018} 3019 3020bool ExtensionService::IsExtensionIdle(const std::string& extension_id) const { 3021 ExtensionProcessManager* process_manager = system_->process_manager(); 3022 DCHECK(process_manager); 3023 extensions::ExtensionHost* host = 3024 process_manager->GetBackgroundHostForExtension(extension_id); 3025 if (host) 3026 return false; 3027 return process_manager->GetRenderViewHostsForExtension(extension_id).empty(); 3028} 3029 3030bool ExtensionService::ShouldDelayExtensionUpdate( 3031 const std::string& extension_id, 3032 bool wait_for_idle) const { 3033 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable"; 3034 3035 // If delayed updates are globally disabled, or just for this extension, 3036 // don't delay. 3037 if (!install_updates_when_idle_ || !wait_for_idle) 3038 return false; 3039 3040 const Extension* old = GetInstalledExtension(extension_id); 3041 // If there is no old extension, this is not an update, so don't delay. 3042 if (!old) 3043 return false; 3044 3045 if (extensions::BackgroundInfo::HasPersistentBackgroundPage(old)) { 3046 // Delay installation if the extension listens for the onUpdateAvailable 3047 // event. 3048 return system_->event_router()->ExtensionHasEventListener( 3049 extension_id, kOnUpdateAvailableEvent); 3050 } else { 3051 // Delay installation if the extension is not idle. 3052 return !IsExtensionIdle(extension_id); 3053 } 3054} 3055 3056void ExtensionService::GarbageCollectIsolatedStorage() { 3057 scoped_ptr<base::hash_set<base::FilePath> > active_paths( 3058 new base::hash_set<base::FilePath>()); 3059 for (ExtensionSet::const_iterator it = extensions_.begin(); 3060 it != extensions_.end(); ++it) { 3061 if (extensions::AppIsolationInfo::HasIsolatedStorage(it->get())) { 3062 active_paths->insert(BrowserContext::GetStoragePartitionForSite( 3063 profile_, GetSiteForExtensionId((*it)->id()))->GetPath()); 3064 } 3065 } 3066 3067 DCHECK(!installs_delayed_for_gc()); 3068 set_installs_delayed_for_gc(true); 3069 BrowserContext::GarbageCollectStoragePartitions( 3070 profile_, active_paths.Pass(), 3071 base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, 3072 AsWeakPtr())); 3073} 3074 3075void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { 3076 set_installs_delayed_for_gc(false); 3077 MaybeFinishDelayedInstallations(); 3078} 3079 3080void ExtensionService::MaybeFinishDelayedInstallations() { 3081 std::vector<std::string> to_be_installed; 3082 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); 3083 it != delayed_installs_.end(); 3084 ++it) { 3085 to_be_installed.push_back((*it)->id()); 3086 } 3087 for (std::vector<std::string>::const_iterator it = to_be_installed.begin(); 3088 it != to_be_installed.end(); 3089 ++it) { 3090 MaybeFinishDelayedInstallation(*it); 3091 } 3092} 3093 3094void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() { 3095 extension_prefs_->SetNeedsStorageGarbageCollection(true); 3096} 3097 3098void ExtensionService::OnBlacklistUpdated() { 3099 blacklist_->GetBlacklistedIDs( 3100 GenerateInstalledExtensionsSet()->GetIDs(), 3101 base::Bind(&ExtensionService::ManageBlacklist, 3102 AsWeakPtr(), 3103 blacklisted_extensions_.GetIDs())); 3104} 3105 3106void ExtensionService::ManageBlacklist( 3107 const std::set<std::string>& old_blacklisted_ids, 3108 const std::set<std::string>& new_blacklisted_ids) { 3109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3110 3111 std::set<std::string> no_longer_blacklisted; 3112 std::set_difference(old_blacklisted_ids.begin(), old_blacklisted_ids.end(), 3113 new_blacklisted_ids.begin(), new_blacklisted_ids.end(), 3114 std::inserter(no_longer_blacklisted, 3115 no_longer_blacklisted.begin())); 3116 std::set<std::string> not_yet_blacklisted; 3117 std::set_difference(new_blacklisted_ids.begin(), new_blacklisted_ids.end(), 3118 old_blacklisted_ids.begin(), old_blacklisted_ids.end(), 3119 std::inserter(not_yet_blacklisted, 3120 not_yet_blacklisted.begin())); 3121 3122 for (std::set<std::string>::iterator it = no_longer_blacklisted.begin(); 3123 it != no_longer_blacklisted.end(); ++it) { 3124 scoped_refptr<const Extension> extension = 3125 blacklisted_extensions_.GetByID(*it); 3126 DCHECK(extension.get()) << "Extension " << *it << " no longer blacklisted, " 3127 << "but it was never blacklisted."; 3128 if (!extension.get()) 3129 continue; 3130 blacklisted_extensions_.Remove(*it); 3131 AddExtension(extension.get()); 3132 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled", 3133 extension->location(), 3134 Manifest::NUM_LOCATIONS); 3135 } 3136 3137 for (std::set<std::string>::iterator it = not_yet_blacklisted.begin(); 3138 it != not_yet_blacklisted.end(); ++it) { 3139 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); 3140 DCHECK(extension.get()) << "Extension " << *it << " needs to be " 3141 << "blacklisted, but it's not installed."; 3142 if (!extension.get()) 3143 continue; 3144 blacklisted_extensions_.Insert(extension); 3145 UnloadExtension(*it, extension_misc::UNLOAD_REASON_BLACKLIST); 3146 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled", 3147 extension->location(), Manifest::NUM_LOCATIONS); 3148 } 3149 3150 IdentifyAlertableExtensions(); 3151} 3152 3153void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { 3154 update_observers_.AddObserver(observer); 3155} 3156 3157void ExtensionService::RemoveUpdateObserver( 3158 extensions::UpdateObserver* observer) { 3159 update_observers_.RemoveObserver(observer); 3160} 3161