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