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