extension_service.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file. 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <algorithm> 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <iterator> 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <set> 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/command_line.h" 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/metrics/histogram.h" 1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/stringprintf.h" 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/time/time.h" 1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/browser_process.h" 2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chrome_notification_types.h" 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/component_loader.h" 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/crx_installer.h" 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/data_deleter.h" 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_assets_manager.h" 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_disabled_ui.h" 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_error_controller.h" 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_install_ui.h" 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_special_storage_policy.h" 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_sync_service.h" 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h" 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/external_install_manager.h" 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/external_provider_impl.h" 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/install_verifier.h" 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/installed_loader.h" 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/pending_extension_manager.h" 3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/permissions_updater.h" 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/shared_module_service.h" 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/unpacked_installer.h" 4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/updater/extension_cache.h" 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/updater/extension_downloader.h" 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/updater/extension_updater.h" 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/signin/profile_identity_provider.h" 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h" 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/ui/webui/favicon_source.h" 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/ui/webui/ntp/thumbnail_source.h" 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/ui/webui/theme_source.h" 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/crash_keys.h" 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/extensions/features/feature_channel.h" 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/extensions/manifest_url_handler.h" 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/pref_names.h" 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/url_constants.h" 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "components/signin/core/browser/signin_manager.h" 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "components/startup_metric_utils/startup_metric_utils.h" 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h" 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/public/browser/notification_service.h" 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/public/browser/render_process_host.h" 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/public/browser/storage_partition.h" 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/event_router.h" 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/extension_host.h" 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/extension_prefs.h" 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/extension_registry.h" 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/extension_system.h" 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/install_flag.h" 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/pref_names.h" 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/runtime_data.h" 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h" 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/update_observer.h" 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/extension_messages.h" 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/feature_switch.h" 7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/file_util.h" 7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h" 8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/one_shot_event.h" 8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/permissions/permission_message_provider.h" 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_CHROMEOS) 8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/install_limiter.h" 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_backend.h" 8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_context.h" 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using content::BrowserContext; 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using content::BrowserThread; 9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using content::DevToolsAgentHost; 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::CrxInstaller; 9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::Extension; 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::ExtensionDownloader; 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::ExtensionDownloaderDelegate; 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::ExtensionIdSet; 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::ExtensionInfo; 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::ExtensionRegistry; 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::ExtensionSet; 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::FeatureSwitch; 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::InstallVerifier; 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::ManagementPolicy; 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::Manifest; 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::PermissionMessage; 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::PermissionMessages; 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::PermissionSet; 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::SharedModuleInfo; 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::SharedModuleService; 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using extensions::UnloadedExtensionInfo; 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace errors = extensions::manifest_errors; 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace { 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Wait this many seconds after an extensions becomes idle before updating it. 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const int kUpdateIdleDelay = 5; 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS) 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<IdentityProvider> CreateWebstoreIdentityProvider(Profile* profile) { 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return make_scoped_ptr<IdentityProvider>(new ProfileIdentityProvider( 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SigninManagerFactory::GetForProfile(profile), 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ProfileOAuth2TokenServiceFactory::GetForProfile(profile), 12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LoginUIServiceFactory::GetForProfile(profile))); 12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif // defined(ENABLE_EXTENSIONS) 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace 12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// ExtensionService. 13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionService::CheckExternalUninstall(const std::string& id) { 13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Check if the providers know about this extension. 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extensions::ProviderCollection::const_iterator i; 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (i = external_extension_providers_.begin(); 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) i != external_extension_providers_.end(); ++i) { 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(i->get()->IsReady()); 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (i->get()->HasExtension(id)) 14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; // Yup, known extension, don't uninstall. 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // We get the list of external extensions to check from preferences. 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // It is possible that an extension has preferences but is not loaded. 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // For example, an extension that requires experimental permissions 14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // will not be loaded if the experimental command line flag is not used. 14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // In this case, do not uninstall. 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!GetInstalledExtension(id)) { 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // We can't call UninstallExtension with an unloaded/invalid 15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // extension ID. 15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LOG(WARNING) << "Attempted uninstallation of unloaded/invalid extension " 15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "with id: " << id; 15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) UninstallExtension(id, 15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extensions::UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION, 15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&base::DoNothing), 15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NULL); 16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionService::SetFileTaskRunnerForTesting( 16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::SequencedTaskRunner* task_runner) { 16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) file_task_runner_ = task_runner; 16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionService::ClearProvidersForTesting() { 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) external_extension_providers_.clear(); 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionService::AddProviderForTesting( 17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extensions::ExternalProviderInterface* test_provider) { 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CHECK(test_provider); 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) external_extension_providers_.push_back( 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) linked_ptr<extensions::ExternalProviderInterface>(test_provider)); 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionService::BlacklistExtensionForTest( 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& extension_id) { 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionIdSet blocked; 18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionIdSet unchanged; 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) blocked.insert(extension_id); 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) UpdateBlockedExtensions(blocked, unchanged); 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool ExtensionService::OnExternalExtensionUpdateUrlFound( 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& id, 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& install_parameter, 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GURL& update_url, 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Manifest::Location location, 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int creation_flags, 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool mark_acknowledged) { 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CHECK(Extension::IdIsValid(id)); 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (Manifest::IsExternalLocation(location)) { 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // All extensions that are not user specific can be cached. 19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extensions::ExtensionCache::GetInstance()->AllowCaching(id); 19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const Extension* extension = GetExtensionById(id, true); 20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (extension) { 20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Already installed. Skip this install if the current location has 20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // higher priority than |location|. 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Manifest::Location current = extension->location(); 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (current == Manifest::GetHigherPriorityLocation(current, location)) 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Otherwise, overwrite the current installation. 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Add |id| to the set of pending extensions. If it can not be added, 21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // then there is already a pending record from a higher-priority install 21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // source. In this case, signal that this extension will not be 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // installed by returning false. 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!pending_extension_manager()->AddFromExternalUpdateUrl( 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) id, 21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) install_parameter, 21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) update_url, 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) location, 22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) creation_flags, 22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) mark_acknowledged)) { 22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) update_once_all_providers_are_ready_ = true; 22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return true; 22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static 23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This function is used to uninstall an extension via sync. The LOG statements 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// within this function are used to inform the user if the uninstall cannot be 23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// done. 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool ExtensionService::UninstallExtensionHelper( 23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExtensionService* extensions_service, 23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& extension_id, 23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) extensions::UninstallReason reason) { 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // We can't call UninstallExtension with an invalid extension ID. 23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!extensions_service->GetInstalledExtension(extension_id)) { 23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LOG(WARNING) << "Attempted uninstallation of non-existent extension with " 24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "id: " << extension_id; 24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 243 244 // The following call to UninstallExtension will not allow an uninstall of a 245 // policy-controlled extension. 246 base::string16 error; 247 if (!extensions_service->UninstallExtension( 248 extension_id, reason, base::Bind(&base::DoNothing), &error)) { 249 LOG(WARNING) << "Cannot uninstall extension with id " << extension_id 250 << ": " << error; 251 return false; 252 } 253 254 return true; 255} 256 257ExtensionService::ExtensionService(Profile* profile, 258 const CommandLine* command_line, 259 const base::FilePath& install_directory, 260 extensions::ExtensionPrefs* extension_prefs, 261 extensions::Blacklist* blacklist, 262 bool autoupdate_enabled, 263 bool extensions_enabled, 264 extensions::OneShotEvent* ready) 265 : extensions::Blacklist::Observer(blacklist), 266 profile_(profile), 267 system_(extensions::ExtensionSystem::Get(profile)), 268 extension_prefs_(extension_prefs), 269 blacklist_(blacklist), 270 extension_sync_service_(NULL), 271 registry_(extensions::ExtensionRegistry::Get(profile)), 272 pending_extension_manager_(profile), 273 install_directory_(install_directory), 274 extensions_enabled_(extensions_enabled), 275 show_extensions_prompts_(true), 276 install_updates_when_idle_(true), 277 ready_(ready), 278 update_once_all_providers_are_ready_(false), 279 browser_terminating_(false), 280 installs_delayed_for_gc_(false), 281 is_first_run_(false), 282 shared_module_service_(new extensions::SharedModuleService(profile_)) { 283 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 284 285 // Figure out if extension installation should be enabled. 286 if (extensions::ExtensionsBrowserClient::Get()->AreExtensionsDisabled( 287 *command_line, profile)) 288 extensions_enabled_ = false; 289 290 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 291 content::NotificationService::AllBrowserContextsAndSources()); 292 registrar_.Add(this, 293 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, 294 content::NotificationService::AllBrowserContextsAndSources()); 295 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 296 content::NotificationService::AllBrowserContextsAndSources()); 297 registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED, 298 content::NotificationService::AllBrowserContextsAndSources()); 299 registrar_.Add(this, 300 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED, 301 content::Source<Profile>(profile_)); 302 pref_change_registrar_.Init(profile->GetPrefs()); 303 base::Closure callback = 304 base::Bind(&ExtensionService::OnExtensionInstallPrefChanged, 305 base::Unretained(this)); 306 pref_change_registrar_.Add(extensions::pref_names::kInstallAllowList, 307 callback); 308 pref_change_registrar_.Add(extensions::pref_names::kInstallDenyList, 309 callback); 310 pref_change_registrar_.Add(extensions::pref_names::kAllowedTypes, callback); 311 312 // Set up the ExtensionUpdater 313 if (autoupdate_enabled) { 314 int update_frequency = extensions::kDefaultUpdateFrequencySeconds; 315 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { 316 base::StringToInt(command_line->GetSwitchValueASCII( 317 switches::kExtensionsUpdateFrequency), 318 &update_frequency); 319 } 320 updater_.reset(new extensions::ExtensionUpdater( 321 this, 322 extension_prefs, 323 profile->GetPrefs(), 324 profile, 325 update_frequency, 326 extensions::ExtensionCache::GetInstance(), 327 base::Bind(&ExtensionService::CreateExtensionDownloader, 328 base::Unretained(this)))); 329 } 330 331 component_loader_.reset( 332 new extensions::ComponentLoader(this, 333 profile->GetPrefs(), 334 g_browser_process->local_state(), 335 profile)); 336 337 if (extensions_enabled_) { 338 extensions::ExternalProviderImpl::CreateExternalProviders( 339 this, profile_, &external_extension_providers_); 340 } 341 342 // Set this as the ExtensionService for app sorting to ensure it causes syncs 343 // if required. 344 is_first_run_ = !extension_prefs_->SetAlertSystemFirstRun(); 345 346 error_controller_.reset( 347 new extensions::ExtensionErrorController(profile_, is_first_run_)); 348 external_install_manager_.reset( 349 new extensions::ExternalInstallManager(profile_, is_first_run_)); 350 351 extension_action_storage_manager_.reset( 352 new extensions::ExtensionActionStorageManager(profile_)); 353 354 // How long is the path to the Extensions directory? 355 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ExtensionRootPathLength", 356 install_directory_.value().length(), 0, 500, 100); 357} 358 359const ExtensionSet* ExtensionService::extensions() const { 360 return ®istry_->enabled_extensions(); 361} 362 363extensions::PendingExtensionManager* 364 ExtensionService::pending_extension_manager() { 365 return &pending_extension_manager_; 366} 367 368ExtensionService::~ExtensionService() { 369 // No need to unload extensions here because they are profile-scoped, and the 370 // profile is in the process of being deleted. 371 372 extensions::ProviderCollection::const_iterator i; 373 for (i = external_extension_providers_.begin(); 374 i != external_extension_providers_.end(); ++i) { 375 extensions::ExternalProviderInterface* provider = i->get(); 376 provider->ServiceShutdown(); 377 } 378} 379 380void ExtensionService::Shutdown() { 381 system_->management_policy()->UnregisterProvider( 382 shared_module_policy_provider_.get()); 383} 384 385const Extension* ExtensionService::GetExtensionById( 386 const std::string& id, bool include_disabled) const { 387 int include_mask = ExtensionRegistry::ENABLED; 388 if (include_disabled) { 389 // Include blacklisted extensions here because there are hundreds of 390 // callers of this function, and many might assume that this includes those 391 // that have been disabled due to blacklisting. 392 include_mask |= ExtensionRegistry::DISABLED | 393 ExtensionRegistry::BLACKLISTED; 394 } 395 return registry_->GetExtensionById(id, include_mask); 396} 397 398void ExtensionService::Init() { 399 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 400 401 base::Time begin_time = base::Time::Now(); 402 403 DCHECK(!is_ready()); // Can't redo init. 404 DCHECK_EQ(registry_->enabled_extensions().size(), 0u); 405 406 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 407 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) || 408 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) { 409 // The sole purpose of this launch is to install a new extension from CWS 410 // and immediately terminate: loading already installed extensions is 411 // unnecessary and may interfere with the inline install dialog (e.g. if an 412 // extension listens to onStartup and opens a window). 413 SetReadyAndNotifyListeners(); 414 } else { 415 // LoadAllExtensions() calls OnLoadedInstalledExtensions(). 416 component_loader_->LoadAll(); 417 extensions::InstalledLoader(this).LoadAllExtensions(); 418 419 // Attempt to re-enable extensions whose only disable reason is reloading. 420 std::vector<std::string> extensions_to_enable; 421 const ExtensionSet& disabled_extensions = registry_->disabled_extensions(); 422 for (ExtensionSet::const_iterator iter = disabled_extensions.begin(); 423 iter != disabled_extensions.end(); ++iter) { 424 const Extension* e = iter->get(); 425 if (extension_prefs_->GetDisableReasons(e->id()) == 426 Extension::DISABLE_RELOAD) { 427 extensions_to_enable.push_back(e->id()); 428 } 429 } 430 for (std::vector<std::string>::iterator it = extensions_to_enable.begin(); 431 it != extensions_to_enable.end(); ++it) { 432 EnableExtension(*it); 433 } 434 435 // Finish install (if possible) of extensions that were still delayed while 436 // the browser was shut down. 437 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info( 438 extension_prefs_->GetAllDelayedInstallInfo()); 439 for (size_t i = 0; i < delayed_info->size(); ++i) { 440 ExtensionInfo* info = delayed_info->at(i).get(); 441 scoped_refptr<const Extension> extension(NULL); 442 if (info->extension_manifest) { 443 std::string error; 444 extension = Extension::Create( 445 info->extension_path, 446 info->extension_location, 447 *info->extension_manifest, 448 extension_prefs_->GetDelayedInstallCreationFlags( 449 info->extension_id), 450 info->extension_id, 451 &error); 452 if (extension.get()) 453 delayed_installs_.Insert(extension); 454 } 455 } 456 MaybeFinishDelayedInstallations(); 457 458 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2( 459 extension_prefs_->GetAllDelayedInstallInfo()); 460 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad", 461 delayed_info2->size() - delayed_info->size()); 462 463 SetReadyAndNotifyListeners(); 464 465 // TODO(erikkay) this should probably be deferred to a future point 466 // rather than running immediately at startup. 467 CheckForExternalUpdates(); 468 469 LoadGreylistFromPrefs(); 470 } 471 472 UMA_HISTOGRAM_TIMES("Extensions.ExtensionServiceInitTime", 473 base::Time::Now() - begin_time); 474} 475 476void ExtensionService::LoadGreylistFromPrefs() { 477 scoped_ptr<ExtensionSet> all_extensions = 478 registry_->GenerateInstalledExtensionsSet(); 479 480 for (ExtensionSet::const_iterator it = all_extensions->begin(); 481 it != all_extensions->end(); ++it) { 482 extensions::BlacklistState state = 483 extension_prefs_->GetExtensionBlacklistState((*it)->id()); 484 if (state == extensions::BLACKLISTED_SECURITY_VULNERABILITY || 485 state == extensions::BLACKLISTED_POTENTIALLY_UNWANTED || 486 state == extensions::BLACKLISTED_CWS_POLICY_VIOLATION) 487 greylist_.Insert(*it); 488 } 489} 490 491bool ExtensionService::UpdateExtension(const std::string& id, 492 const base::FilePath& extension_path, 493 bool file_ownership_passed, 494 CrxInstaller** out_crx_installer) { 495 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 496 if (browser_terminating_) { 497 LOG(WARNING) << "Skipping UpdateExtension due to browser shutdown"; 498 // Leak the temp file at extension_path. We don't want to add to the disk 499 // I/O burden at shutdown, we can't rely on the I/O completing anyway, and 500 // the file is in the OS temp directory which should be cleaned up for us. 501 return false; 502 } 503 504 const extensions::PendingExtensionInfo* pending_extension_info = 505 pending_extension_manager()->GetById(id); 506 507 const Extension* extension = GetInstalledExtension(id); 508 if (!pending_extension_info && !extension) { 509 LOG(WARNING) << "Will not update extension " << id 510 << " because it is not installed or pending"; 511 // Delete extension_path since we're not creating a CrxInstaller 512 // that would do it for us. 513 if (!GetFileTaskRunner()->PostTask( 514 FROM_HERE, 515 base::Bind( 516 &extensions::file_util::DeleteFile, extension_path, false))) 517 NOTREACHED(); 518 519 return false; 520 } 521 522 // We want a silent install only for non-pending extensions and 523 // pending extensions that have install_silently set. 524 scoped_ptr<ExtensionInstallPrompt> client; 525 if (pending_extension_info && !pending_extension_info->install_silently()) 526 client.reset(ExtensionInstallUI::CreateInstallPromptWithProfile(profile_)); 527 528 scoped_refptr<CrxInstaller> installer( 529 CrxInstaller::Create(this, client.Pass())); 530 installer->set_expected_id(id); 531 int creation_flags = Extension::NO_FLAGS; 532 if (pending_extension_info) { 533 installer->set_install_source(pending_extension_info->install_source()); 534 if (pending_extension_info->install_silently()) 535 installer->set_allow_silent_install(true); 536 if (pending_extension_info->remote_install()) 537 installer->set_grant_permissions(false); 538 creation_flags = pending_extension_info->creation_flags(); 539 if (pending_extension_info->mark_acknowledged()) 540 external_install_manager_->AcknowledgeExternalExtension(id); 541 } else if (extension) { 542 installer->set_install_source(extension->location()); 543 } 544 // If the extension was installed from or has migrated to the webstore, or 545 // its auto-update URL is from the webstore, treat it as a webstore install. 546 // Note that we ignore some older extensions with blank auto-update URLs 547 // because we are mostly concerned with restrictions on NaCl extensions, 548 // which are newer. 549 if ((extension && extension->from_webstore()) || 550 (extension && extensions::ManifestURL::UpdatesFromGallery(extension)) || 551 (!extension && extension_urls::IsWebstoreUpdateUrl( 552 pending_extension_info->update_url()))) { 553 creation_flags |= Extension::FROM_WEBSTORE; 554 } 555 556 // Bookmark apps being updated is kind of a contradiction, but that's because 557 // we mark the default apps as bookmark apps, and they're hosted in the web 558 // store, thus they can get updated. See http://crbug.com/101605 for more 559 // details. 560 if (extension && extension->from_bookmark()) 561 creation_flags |= Extension::FROM_BOOKMARK; 562 563 if (extension && extension->was_installed_by_default()) 564 creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT; 565 566 if (extension && extension->was_installed_by_oem()) 567 creation_flags |= Extension::WAS_INSTALLED_BY_OEM; 568 569 if (extension && extension->was_installed_by_custodian()) 570 creation_flags |= Extension::WAS_INSTALLED_BY_CUSTODIAN; 571 572 if (extension) { 573 installer->set_is_ephemeral(extension_prefs_->IsEphemeralApp(id)); 574 installer->set_do_not_sync(extension_prefs_->DoNotSync(id)); 575 } 576 577 installer->set_creation_flags(creation_flags); 578 579 installer->set_delete_source(file_ownership_passed); 580 installer->set_install_cause(extension_misc::INSTALL_CAUSE_UPDATE); 581 installer->InstallCrx(extension_path); 582 583 if (out_crx_installer) 584 *out_crx_installer = installer.get(); 585 586 return true; 587} 588 589scoped_ptr<ExtensionDownloader> ExtensionService::CreateExtensionDownloader( 590 ExtensionDownloaderDelegate* delegate) { 591 scoped_ptr<ExtensionDownloader> downloader; 592#if defined(ENABLE_EXTENSIONS) 593 scoped_ptr<IdentityProvider> identity_provider = 594 CreateWebstoreIdentityProvider(profile_); 595 downloader.reset(new ExtensionDownloader( 596 delegate, 597 profile_->GetRequestContext())); 598 downloader->SetWebstoreIdentityProvider(identity_provider.Pass()); 599#endif 600 return downloader.Pass(); 601} 602 603void ExtensionService::ReloadExtensionImpl( 604 // "transient" because the process of reloading may cause the reference 605 // to become invalid. Instead, use |extension_id|, a copy. 606 const std::string& transient_extension_id, 607 bool be_noisy) { 608 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 609 610 // If the extension is already reloading, don't reload again. 611 if (extension_prefs_->GetDisableReasons(transient_extension_id) & 612 Extension::DISABLE_RELOAD) { 613 return; 614 } 615 616 // Ignore attempts to reload a blacklisted extension. Sometimes this can 617 // happen in a convoluted reload sequence triggered by the termination of a 618 // blacklisted extension and a naive attempt to reload it. For an example see 619 // http://crbug.com/373842. 620 if (registry_->blacklisted_extensions().Contains(transient_extension_id)) 621 return; 622 623 base::FilePath path; 624 625 std::string extension_id = transient_extension_id; 626 const Extension* transient_current_extension = 627 GetExtensionById(extension_id, false); 628 629 // Disable the extension if it's loaded. It might not be loaded if it crashed. 630 if (transient_current_extension) { 631 // If the extension has an inspector open for its background page, detach 632 // the inspector and hang onto a cookie for it, so that we can reattach 633 // later. 634 // TODO(yoz): this is not incognito-safe! 635 extensions::ProcessManager* manager = system_->process_manager(); 636 extensions::ExtensionHost* host = 637 manager->GetBackgroundHostForExtension(extension_id); 638 if (host && DevToolsAgentHost::HasFor(host->host_contents())) { 639 // Look for an open inspector for the background page. 640 scoped_refptr<DevToolsAgentHost> agent_host = 641 DevToolsAgentHost::GetOrCreateFor(host->host_contents()); 642 agent_host->DisconnectWebContents(); 643 orphaned_dev_tools_[extension_id] = agent_host; 644 } 645 646 path = transient_current_extension->path(); 647 // BeingUpgraded is set back to false when the extension is added. 648 system_->runtime_data()->SetBeingUpgraded(transient_current_extension, 649 true); 650 DisableExtension(extension_id, Extension::DISABLE_RELOAD); 651 reloading_extensions_.insert(extension_id); 652 } else { 653 std::map<std::string, base::FilePath>::const_iterator iter = 654 unloaded_extension_paths_.find(extension_id); 655 if (iter == unloaded_extension_paths_.end()) { 656 return; 657 } 658 path = unloaded_extension_paths_[extension_id]; 659 } 660 661 transient_current_extension = NULL; 662 663 if (delayed_installs_.Contains(extension_id)) { 664 FinishDelayedInstallation(extension_id); 665 return; 666 } 667 668 // If we're reloading a component extension, use the component extension 669 // loader's reloader. 670 if (component_loader_->Exists(extension_id)) { 671 component_loader_->Reload(extension_id); 672 return; 673 } 674 675 // Check the installed extensions to see if what we're reloading was already 676 // installed. 677 scoped_ptr<ExtensionInfo> installed_extension( 678 extension_prefs_->GetInstalledExtensionInfo(extension_id)); 679 if (installed_extension.get() && 680 installed_extension->extension_manifest.get()) { 681 extensions::InstalledLoader(this).Load(*installed_extension, false); 682 } else { 683 // Otherwise, the extension is unpacked (location LOAD). 684 // We should always be able to remember the extension's path. If it's not in 685 // the map, someone failed to update |unloaded_extension_paths_|. 686 CHECK(!path.empty()); 687 scoped_refptr<extensions::UnpackedInstaller> unpacked_installer = 688 extensions::UnpackedInstaller::Create(this); 689 unpacked_installer->set_be_noisy_on_failure(be_noisy); 690 unpacked_installer->Load(path); 691 } 692} 693 694void ExtensionService::ReloadExtension(const std::string& extension_id) { 695 ReloadExtensionImpl(extension_id, true); // be_noisy 696} 697 698void ExtensionService::ReloadExtensionWithQuietFailure( 699 const std::string& extension_id) { 700 ReloadExtensionImpl(extension_id, false); // be_noisy 701} 702 703bool ExtensionService::UninstallExtension( 704 // "transient" because the process of uninstalling may cause the reference 705 // to become invalid. Instead, use |extenson->id()|. 706 const std::string& transient_extension_id, 707 extensions::UninstallReason reason, 708 const base::Closure& deletion_done_callback, 709 base::string16* error) { 710 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 711 712 scoped_refptr<const Extension> extension = 713 GetInstalledExtension(transient_extension_id); 714 715 // Callers should not send us nonexistent extensions. 716 CHECK(extension.get()); 717 718 // Policy change which triggers an uninstall will always set 719 // |external_uninstall| to true so this is the only way to uninstall 720 // managed extensions. 721 // Shared modules being uninstalled will also set |external_uninstall| to true 722 // so that we can guarantee users don't uninstall a shared module. 723 // (crbug.com/273300) 724 // TODO(rdevlin.cronin): This is probably not right. We should do something 725 // else, like include an enum IS_INTERNAL_UNINSTALL or IS_USER_UNINSTALL so 726 // we don't do this. 727 bool external_uninstall = 728 (reason == extensions::UNINSTALL_REASON_INTERNAL_MANAGEMENT) || 729 (reason == extensions::UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION) || 730 (reason == extensions::UNINSTALL_REASON_ORPHANED_SHARED_MODULE) || 731 (reason == extensions::UNINSTALL_REASON_SYNC && 732 extension->was_installed_by_custodian()); 733 if (!external_uninstall && 734 !system_->management_policy()->UserMayModifySettings( 735 extension.get(), error)) { 736 content::NotificationService::current()->Notify( 737 extensions::NOTIFICATION_EXTENSION_UNINSTALL_NOT_ALLOWED, 738 content::Source<Profile>(profile_), 739 content::Details<const Extension>(extension.get())); 740 return false; 741 } 742 743 syncer::SyncChange sync_change; 744 if (extension_sync_service_) { 745 sync_change = extension_sync_service_->PrepareToSyncUninstallExtension( 746 extension.get(), is_ready()); 747 } 748 749 system_->install_verifier()->Remove(extension->id()); 750 751 UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType", 752 extension->GetType(), 100); 753 RecordPermissionMessagesHistogram(extension.get(), 754 "Extensions.Permissions_Uninstall2"); 755 756 // Unload before doing more cleanup to ensure that nothing is hanging on to 757 // any of these resources. 758 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UNINSTALL); 759 760 // Tell the backend to start deleting installed extensions on the file thread. 761 if (!Manifest::IsUnpackedLocation(extension->location())) { 762 if (!GetFileTaskRunner()->PostTask( 763 FROM_HERE, 764 base::Bind(&ExtensionService::UninstallExtensionOnFileThread, 765 extension->id(), 766 profile_, 767 install_directory_, 768 extension->path()))) 769 NOTREACHED(); 770 } 771 772 extensions::DataDeleter::StartDeleting( 773 profile_, extension.get(), deletion_done_callback); 774 775 UntrackTerminatedExtension(extension->id()); 776 777 // Notify interested parties that we've uninstalled this extension. 778 content::NotificationService::current()->Notify( 779 extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED, 780 content::Source<Profile>(profile_), 781 content::Details<const Extension>(extension.get())); 782 ExtensionRegistry::Get(profile_) 783 ->TriggerOnUninstalled(extension.get(), reason); 784 785 if (extension_sync_service_) { 786 extension_sync_service_->ProcessSyncUninstallExtension(extension->id(), 787 sync_change); 788 } 789 790 delayed_installs_.Remove(extension->id()); 791 792 extension_prefs_->OnExtensionUninstalled( 793 extension->id(), extension->location(), external_uninstall); 794 795 // Track the uninstallation. 796 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2); 797 798 return true; 799} 800 801// static 802void ExtensionService::UninstallExtensionOnFileThread( 803 const std::string& id, 804 Profile* profile, 805 const base::FilePath& install_dir, 806 const base::FilePath& extension_path) { 807 extensions::ExtensionAssetsManager* assets_manager = 808 extensions::ExtensionAssetsManager::GetInstance(); 809 assets_manager->UninstallExtension(id, profile, install_dir, extension_path); 810} 811 812bool ExtensionService::IsExtensionEnabled( 813 const std::string& extension_id) const { 814 if (registry_->enabled_extensions().Contains(extension_id) || 815 registry_->terminated_extensions().Contains(extension_id)) { 816 return true; 817 } 818 819 if (registry_->disabled_extensions().Contains(extension_id) || 820 registry_->blacklisted_extensions().Contains(extension_id)) { 821 return false; 822 } 823 824 // If the extension hasn't been loaded yet, check the prefs for it. Assume 825 // enabled unless otherwise noted. 826 return !extension_prefs_->IsExtensionDisabled(extension_id) && 827 !extension_prefs_->IsExtensionBlacklisted(extension_id) && 828 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); 829} 830 831void ExtensionService::EnableExtension(const std::string& extension_id) { 832 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 833 834 if (IsExtensionEnabled(extension_id)) 835 return; 836 const Extension* extension = 837 registry_->disabled_extensions().GetByID(extension_id); 838 839 ManagementPolicy* policy = system_->management_policy(); 840 if (extension && policy->MustRemainDisabled(extension, NULL, NULL)) { 841 UMA_HISTOGRAM_COUNTS_100("Extensions.EnableDeniedByPolicy", 1); 842 return; 843 } 844 845 extension_prefs_->SetExtensionState(extension_id, Extension::ENABLED); 846 extension_prefs_->ClearDisableReasons(extension_id); 847 848 // This can happen if sync enables an extension that is not 849 // installed yet. 850 if (!extension) 851 return; 852 853 // Move it over to the enabled list. 854 registry_->AddEnabled(make_scoped_refptr(extension)); 855 registry_->RemoveDisabled(extension->id()); 856 857 NotifyExtensionLoaded(extension); 858 859 // Notify listeners that the extension was enabled. 860 content::NotificationService::current()->Notify( 861 extensions::NOTIFICATION_EXTENSION_ENABLED, 862 content::Source<Profile>(profile_), 863 content::Details<const Extension>(extension)); 864 865 if (extension_sync_service_) 866 extension_sync_service_->SyncEnableExtension(*extension); 867} 868 869void ExtensionService::DisableExtension( 870 const std::string& extension_id, 871 Extension::DisableReason disable_reason) { 872 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 873 874 // The extension may have been disabled already. Just add a disable reason. 875 if (!IsExtensionEnabled(extension_id)) { 876 extension_prefs_->AddDisableReason(extension_id, disable_reason); 877 return; 878 } 879 880 const Extension* extension = GetInstalledExtension(extension_id); 881 // |extension| can be NULL if sync disables an extension that is not 882 // installed yet. 883 // EXTERNAL_COMPONENT extensions are not generally modifiable by users, but 884 // can be uninstalled by the browser if the user sets extension-specific 885 // preferences. 886 if (extension && 887 disable_reason != Extension::DISABLE_RELOAD && 888 !system_->management_policy()->UserMayModifySettings(extension, NULL) && 889 extension->location() != Manifest::EXTERNAL_COMPONENT) { 890 return; 891 } 892 893 extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED); 894 extension_prefs_->AddDisableReason(extension_id, disable_reason); 895 896 int include_mask = 897 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::DISABLED; 898 extension = registry_->GetExtensionById(extension_id, include_mask); 899 if (!extension) 900 return; 901 902 // The extension is either enabled or terminated. 903 DCHECK(registry_->enabled_extensions().Contains(extension->id()) || 904 registry_->terminated_extensions().Contains(extension->id())); 905 906 // Move it over to the disabled list. Don't send a second unload notification 907 // for terminated extensions being disabled. 908 registry_->AddDisabled(make_scoped_refptr(extension)); 909 if (registry_->enabled_extensions().Contains(extension->id())) { 910 registry_->RemoveEnabled(extension->id()); 911 NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::REASON_DISABLE); 912 } else { 913 registry_->RemoveTerminated(extension->id()); 914 } 915 916 if (extension_sync_service_) 917 extension_sync_service_->SyncDisableExtension(*extension); 918} 919 920void ExtensionService::DisableUserExtensions( 921 const std::vector<std::string>& except_ids) { 922 extensions::ManagementPolicy* management_policy = 923 system_->management_policy(); 924 extensions::ExtensionList to_disable; 925 926 const ExtensionSet& enabled_set = registry_->enabled_extensions(); 927 for (ExtensionSet::const_iterator extension = enabled_set.begin(); 928 extension != enabled_set.end(); ++extension) { 929 if (management_policy->UserMayModifySettings(extension->get(), NULL)) 930 to_disable.push_back(*extension); 931 } 932 const ExtensionSet& terminated_set = registry_->terminated_extensions(); 933 for (ExtensionSet::const_iterator extension = terminated_set.begin(); 934 extension != terminated_set.end(); ++extension) { 935 if (management_policy->UserMayModifySettings(extension->get(), NULL)) 936 to_disable.push_back(*extension); 937 } 938 939 for (extensions::ExtensionList::const_iterator extension = to_disable.begin(); 940 extension != to_disable.end(); ++extension) { 941 if ((*extension)->was_installed_by_default() && 942 extension_urls::IsWebstoreUpdateUrl( 943 extensions::ManifestURL::GetUpdateURL(*extension))) 944 continue; 945 const std::string& id = (*extension)->id(); 946 if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id)) 947 DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION); 948 } 949} 950 951void ExtensionService::GrantPermissionsAndEnableExtension( 952 const Extension* extension) { 953 GrantPermissions(extension); 954 RecordPermissionMessagesHistogram(extension, 955 "Extensions.Permissions_ReEnable2"); 956 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); 957 EnableExtension(extension->id()); 958} 959 960void ExtensionService::GrantPermissions(const Extension* extension) { 961 CHECK(extension); 962 extensions::PermissionsUpdater(profile()).GrantActivePermissions(extension); 963} 964 965// static 966void ExtensionService::RecordPermissionMessagesHistogram( 967 const Extension* extension, const char* histogram) { 968 // Since this is called from multiple sources, and since the histogram macros 969 // use statics, we need to manually lookup the histogram ourselves. 970 base::HistogramBase* counter = base::LinearHistogram::FactoryGet( 971 histogram, 972 1, 973 PermissionMessage::kEnumBoundary, 974 PermissionMessage::kEnumBoundary + 1, 975 base::HistogramBase::kUmaTargetedHistogramFlag); 976 977 PermissionMessages permissions = 978 extension->permissions_data()->GetPermissionMessages(); 979 if (permissions.empty()) { 980 counter->Add(PermissionMessage::kNone); 981 } else { 982 for (PermissionMessages::iterator it = permissions.begin(); 983 it != permissions.end(); ++it) 984 counter->Add(it->id()); 985 } 986} 987 988void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { 989 // The URLRequestContexts need to be first to know that the extension 990 // was loaded, otherwise a race can arise where a renderer that is created 991 // for the extension may try to load an extension URL with an extension id 992 // that the request context doesn't yet know about. The profile is responsible 993 // for ensuring its URLRequestContexts appropriately discover the loaded 994 // extension. 995 system_->RegisterExtensionWithRequestContexts(extension); 996 997 // Tell renderers about the new extension, unless it's a theme (renderers 998 // don't need to know about themes). 999 if (!extension->is_theme()) { 1000 for (content::RenderProcessHost::iterator i( 1001 content::RenderProcessHost::AllHostsIterator()); 1002 !i.IsAtEnd(); i.Advance()) { 1003 content::RenderProcessHost* host = i.GetCurrentValue(); 1004 Profile* host_profile = 1005 Profile::FromBrowserContext(host->GetBrowserContext()); 1006 if (host_profile->GetOriginalProfile() == 1007 profile_->GetOriginalProfile()) { 1008 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions( 1009 1, ExtensionMsg_Loaded_Params(extension)); 1010 host->Send( 1011 new ExtensionMsg_Loaded(loaded_extensions)); 1012 } 1013 } 1014 } 1015 1016 // Tell subsystems that use the EXTENSION_LOADED notification about the new 1017 // extension. 1018 // 1019 // NOTE: It is important that this happen after notifying the renderers about 1020 // the new extensions so that if we navigate to an extension URL in 1021 // ExtensionRegistryObserver::OnLoaded or 1022 // NOTIFICATION_EXTENSION_LOADED_DEPRECATED, the 1023 // renderer is guaranteed to know about it. 1024 registry_->TriggerOnLoaded(extension); 1025 1026 content::NotificationService::current()->Notify( 1027 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 1028 content::Source<Profile>(profile_), 1029 content::Details<const Extension>(extension)); 1030 1031 // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a 1032 // BrowserContextKeyedService and use ExtensionRegistryObserver. 1033 profile_->GetExtensionSpecialStoragePolicy()-> 1034 GrantRightsForExtension(extension); 1035 1036 // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't 1037 // work properly multi-profile. Besides which, it should be using 1038 // ExtensionRegistryObserver. See http://crbug.com/355029. 1039 UpdateActiveExtensionsInCrashReporter(); 1040 1041 const extensions::PermissionsData* permissions_data = 1042 extension->permissions_data(); 1043 1044 // If the extension has permission to load chrome://favicon/ resources we need 1045 // to make sure that the FaviconSource is registered with the 1046 // ChromeURLDataManager. 1047 if (permissions_data->HasHostPermission(GURL(chrome::kChromeUIFaviconURL))) { 1048 FaviconSource* favicon_source = new FaviconSource(profile_, 1049 FaviconSource::FAVICON); 1050 content::URLDataSource::Add(profile_, favicon_source); 1051 } 1052 1053 // Same for chrome://theme/ resources. 1054 if (permissions_data->HasHostPermission(GURL(chrome::kChromeUIThemeURL))) { 1055 ThemeSource* theme_source = new ThemeSource(profile_); 1056 content::URLDataSource::Add(profile_, theme_source); 1057 } 1058 1059 // Same for chrome://thumb/ resources. 1060 if (permissions_data->HasHostPermission( 1061 GURL(chrome::kChromeUIThumbnailURL))) { 1062 ThumbnailSource* thumbnail_source = new ThumbnailSource(profile_, false); 1063 content::URLDataSource::Add(profile_, thumbnail_source); 1064 } 1065} 1066 1067void ExtensionService::NotifyExtensionUnloaded( 1068 const Extension* extension, 1069 UnloadedExtensionInfo::Reason reason) { 1070 UnloadedExtensionInfo details(extension, reason); 1071 1072 registry_->TriggerOnUnloaded(extension, reason); 1073 1074 content::NotificationService::current()->Notify( 1075 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 1076 content::Source<Profile>(profile_), 1077 content::Details<UnloadedExtensionInfo>(&details)); 1078 1079 for (content::RenderProcessHost::iterator i( 1080 content::RenderProcessHost::AllHostsIterator()); 1081 !i.IsAtEnd(); i.Advance()) { 1082 content::RenderProcessHost* host = i.GetCurrentValue(); 1083 Profile* host_profile = 1084 Profile::FromBrowserContext(host->GetBrowserContext()); 1085 if (host_profile->GetOriginalProfile() == profile_->GetOriginalProfile()) 1086 host->Send(new ExtensionMsg_Unloaded(extension->id())); 1087 } 1088 1089 system_->UnregisterExtensionWithRequestContexts(extension->id(), reason); 1090 1091 // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a 1092 // BrowserContextKeyedService and use ExtensionRegistryObserver. 1093 profile_->GetExtensionSpecialStoragePolicy()-> 1094 RevokeRightsForExtension(extension); 1095 1096#if defined(OS_CHROMEOS) 1097 // Revoke external file access for the extension from its file system context. 1098 // It is safe to access the extension's storage partition at this point. The 1099 // storage partition may get destroyed only after the extension gets unloaded. 1100 GURL site = 1101 extensions::util::GetSiteForExtensionId(extension->id(), profile_); 1102 fileapi::FileSystemContext* filesystem_context = 1103 BrowserContext::GetStoragePartitionForSite(profile_, site)-> 1104 GetFileSystemContext(); 1105 if (filesystem_context && filesystem_context->external_backend()) { 1106 filesystem_context->external_backend()-> 1107 RevokeAccessForExtension(extension->id()); 1108 } 1109#endif 1110 1111 // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't 1112 // work properly multi-profile. Besides which, it should be using 1113 // ExtensionRegistryObserver::OnExtensionLoaded. See http://crbug.com/355029. 1114 UpdateActiveExtensionsInCrashReporter(); 1115} 1116 1117content::BrowserContext* ExtensionService::GetBrowserContext() const { 1118 // Implemented in the .cc file to avoid adding a profile.h dependency to 1119 // extension_service.h. 1120 return profile_; 1121} 1122 1123bool ExtensionService::is_ready() { 1124 return ready_->is_signaled(); 1125} 1126 1127base::SequencedTaskRunner* ExtensionService::GetFileTaskRunner() { 1128 if (file_task_runner_.get()) 1129 return file_task_runner_.get(); 1130 1131 // We should be able to interrupt any part of extension install process during 1132 // shutdown. SKIP_ON_SHUTDOWN ensures that not started extension install tasks 1133 // will be ignored/deleted while we will block on started tasks. 1134 std::string token("ext_install-"); 1135 token.append(profile_->GetPath().AsUTF8Unsafe()); 1136 file_task_runner_ = BrowserThread::GetBlockingPool()-> 1137 GetSequencedTaskRunnerWithShutdownBehavior( 1138 BrowserThread::GetBlockingPool()->GetNamedSequenceToken(token), 1139 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 1140 return file_task_runner_.get(); 1141} 1142 1143void ExtensionService::CheckManagementPolicy() { 1144 std::vector<std::string> to_unload; 1145 std::map<std::string, Extension::DisableReason> to_disable; 1146 1147 // Loop through the extensions list, finding extensions we need to unload or 1148 // disable. 1149 const ExtensionSet& extensions = registry_->enabled_extensions(); 1150 for (ExtensionSet::const_iterator iter = extensions.begin(); 1151 iter != extensions.end(); ++iter) { 1152 const Extension* extension = (iter->get()); 1153 if (!system_->management_policy()->UserMayLoad(extension, NULL)) 1154 to_unload.push_back(extension->id()); 1155 Extension::DisableReason disable_reason = Extension::DISABLE_NONE; 1156 if (system_->management_policy()->MustRemainDisabled( 1157 extension, &disable_reason, NULL)) 1158 to_disable[extension->id()] = disable_reason; 1159 } 1160 1161 for (size_t i = 0; i < to_unload.size(); ++i) 1162 UnloadExtension(to_unload[i], UnloadedExtensionInfo::REASON_DISABLE); 1163 1164 for (std::map<std::string, Extension::DisableReason>::const_iterator i = 1165 to_disable.begin(); i != to_disable.end(); ++i) 1166 DisableExtension(i->first, i->second); 1167} 1168 1169void ExtensionService::CheckForUpdatesSoon() { 1170 // This can legitimately happen in unit tests. 1171 if (!updater_.get()) 1172 return; 1173 1174 if (AreAllExternalProvidersReady()) { 1175 updater_->CheckSoon(); 1176 } else { 1177 // Sync can start updating before all the external providers are ready 1178 // during startup. Start the update as soon as those providers are ready, 1179 // but not before. 1180 update_once_all_providers_are_ready_ = true; 1181 } 1182} 1183 1184// Some extensions will autoupdate themselves externally from Chrome. These 1185// are typically part of some larger client application package. To support 1186// these, the extension will register its location in the the preferences file 1187// (and also, on Windows, in the registry) and this code will periodically 1188// check that location for a .crx file, which it will then install locally if 1189// a new version is available. 1190// Errors are reported through ExtensionErrorReporter. Succcess is not 1191// reported. 1192void ExtensionService::CheckForExternalUpdates() { 1193 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1194 1195 // Note that this installation is intentionally silent (since it didn't 1196 // go through the front-end). Extensions that are registered in this 1197 // way are effectively considered 'pre-bundled', and so implicitly 1198 // trusted. In general, if something has HKLM or filesystem access, 1199 // they could install an extension manually themselves anyway. 1200 1201 // Ask each external extension provider to give us a call back for each 1202 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. 1203 extensions::ProviderCollection::const_iterator i; 1204 for (i = external_extension_providers_.begin(); 1205 i != external_extension_providers_.end(); ++i) { 1206 extensions::ExternalProviderInterface* provider = i->get(); 1207 provider->VisitRegisteredExtension(); 1208 } 1209 1210 // Do any required work that we would have done after completion of all 1211 // providers. 1212 if (external_extension_providers_.empty()) 1213 OnAllExternalProvidersReady(); 1214} 1215 1216void ExtensionService::OnExternalProviderReady( 1217 const extensions::ExternalProviderInterface* provider) { 1218 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1219 CHECK(provider->IsReady()); 1220 1221 // An external provider has finished loading. We only take action 1222 // if all of them are finished. So we check them first. 1223 if (AreAllExternalProvidersReady()) 1224 OnAllExternalProvidersReady(); 1225} 1226 1227bool ExtensionService::AreAllExternalProvidersReady() const { 1228 extensions::ProviderCollection::const_iterator i; 1229 for (i = external_extension_providers_.begin(); 1230 i != external_extension_providers_.end(); ++i) { 1231 if (!i->get()->IsReady()) 1232 return false; 1233 } 1234 return true; 1235} 1236 1237void ExtensionService::OnAllExternalProvidersReady() { 1238 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1239 base::TimeDelta elapsed = base::Time::Now() - profile_->GetStartTime(); 1240 UMA_HISTOGRAM_TIMES("Extension.ExternalProvidersReadyAfter", elapsed); 1241 1242 // Install any pending extensions. 1243 if (update_once_all_providers_are_ready_ && updater()) { 1244 update_once_all_providers_are_ready_ = false; 1245 extensions::ExtensionUpdater::CheckParams params; 1246 params.callback = external_updates_finished_callback_; 1247 updater()->CheckNow(params); 1248 } 1249 1250 // Uninstall all the unclaimed extensions. 1251 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> extensions_info( 1252 extension_prefs_->GetInstalledExtensionsInfo()); 1253 for (size_t i = 0; i < extensions_info->size(); ++i) { 1254 ExtensionInfo* info = extensions_info->at(i).get(); 1255 if (Manifest::IsExternalLocation(info->extension_location)) 1256 CheckExternalUninstall(info->extension_id); 1257 } 1258 1259 error_controller_->ShowErrorIfNeeded(); 1260 1261 external_install_manager_->UpdateExternalExtensionAlert(); 1262} 1263 1264void ExtensionService::UnloadExtension( 1265 const std::string& extension_id, 1266 UnloadedExtensionInfo::Reason reason) { 1267 // Make sure the extension gets deleted after we return from this function. 1268 int include_mask = 1269 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::TERMINATED; 1270 scoped_refptr<const Extension> extension( 1271 registry_->GetExtensionById(extension_id, include_mask)); 1272 1273 // This method can be called via PostTask, so the extension may have been 1274 // unloaded by the time this runs. 1275 if (!extension.get()) { 1276 // In case the extension may have crashed/uninstalled. Allow the profile to 1277 // clean up its RequestContexts. 1278 system_->UnregisterExtensionWithRequestContexts(extension_id, reason); 1279 return; 1280 } 1281 1282 // Keep information about the extension so that we can reload it later 1283 // even if it's not permanently installed. 1284 unloaded_extension_paths_[extension->id()] = extension->path(); 1285 1286 // Clean up if the extension is meant to be enabled after a reload. 1287 reloading_extensions_.erase(extension->id()); 1288 1289 if (registry_->disabled_extensions().Contains(extension->id())) { 1290 registry_->RemoveDisabled(extension->id()); 1291 // Make sure the profile cleans up its RequestContexts when an already 1292 // disabled extension is unloaded (since they are also tracking the disabled 1293 // extensions). 1294 system_->UnregisterExtensionWithRequestContexts(extension_id, reason); 1295 // Don't send the unloaded notification. It was sent when the extension 1296 // was disabled. 1297 } else { 1298 // Remove the extension from the enabled list. 1299 registry_->RemoveEnabled(extension->id()); 1300 NotifyExtensionUnloaded(extension.get(), reason); 1301 } 1302 1303 content::NotificationService::current()->Notify( 1304 extensions::NOTIFICATION_EXTENSION_REMOVED, 1305 content::Source<Profile>(profile_), 1306 content::Details<const Extension>(extension.get())); 1307} 1308 1309void ExtensionService::RemoveComponentExtension( 1310 const std::string& extension_id) { 1311 scoped_refptr<const Extension> extension( 1312 GetExtensionById(extension_id, false)); 1313 UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_UNINSTALL); 1314 if (extension.get()) { 1315 content::NotificationService::current()->Notify( 1316 extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED, 1317 content::Source<Profile>(profile_), 1318 content::Details<const Extension>(extension.get())); 1319 ExtensionRegistry::Get(profile_)->TriggerOnUninstalled( 1320 extension.get(), extensions::UNINSTALL_REASON_INTERNAL_MANAGEMENT); 1321 } 1322} 1323 1324void ExtensionService::UnloadAllExtensionsForTest() { 1325 UnloadAllExtensionsInternal(); 1326} 1327 1328void ExtensionService::ReloadExtensionsForTest() { 1329 // Calling UnloadAllExtensionsForTest here triggers a false-positive presubmit 1330 // warning about calling test code in production. 1331 UnloadAllExtensionsInternal(); 1332 component_loader_->LoadAll(); 1333 extensions::InstalledLoader(this).LoadAllExtensions(); 1334 // Don't call SetReadyAndNotifyListeners() since tests call this multiple 1335 // times. 1336} 1337 1338void ExtensionService::SetReadyAndNotifyListeners() { 1339 ready_->Signal(); 1340 content::NotificationService::current()->Notify( 1341 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, 1342 content::Source<Profile>(profile_), 1343 content::NotificationService::NoDetails()); 1344} 1345 1346void ExtensionService::OnLoadedInstalledExtensions() { 1347 if (updater_) 1348 updater_->Start(); 1349 1350 OnBlacklistUpdated(); 1351} 1352 1353void ExtensionService::AddExtension(const Extension* extension) { 1354 // TODO(jstritar): We may be able to get rid of this branch by overriding the 1355 // default extension state to DISABLED when the --disable-extensions flag 1356 // is set (http://crbug.com/29067). 1357 if (!extensions_enabled() && 1358 !extension->is_theme() && 1359 extension->location() != Manifest::COMPONENT && 1360 !Manifest::IsExternalLocation(extension->location())) { 1361 return; 1362 } 1363 1364 bool is_extension_upgrade = false; 1365 bool is_extension_installed = false; 1366 const Extension* old = GetInstalledExtension(extension->id()); 1367 if (old) { 1368 is_extension_installed = true; 1369 int version_compare_result = 1370 extension->version()->CompareTo(*(old->version())); 1371 is_extension_upgrade = version_compare_result > 0; 1372 // Other than for unpacked extensions, CrxInstaller should have guaranteed 1373 // that we aren't downgrading. 1374 if (!Manifest::IsUnpackedLocation(extension->location())) 1375 CHECK_GE(version_compare_result, 0); 1376 } 1377 system_->runtime_data()->SetBeingUpgraded(extension, is_extension_upgrade); 1378 1379 // The extension is now loaded, remove its data from unloaded extension map. 1380 unloaded_extension_paths_.erase(extension->id()); 1381 1382 // If a terminated extension is loaded, remove it from the terminated list. 1383 UntrackTerminatedExtension(extension->id()); 1384 1385 // If the extension was disabled for a reload, then enable it. 1386 bool reloading = reloading_extensions_.erase(extension->id()) > 0; 1387 1388 // Check if the extension's privileges have changed and mark the 1389 // extension disabled if necessary. 1390 CheckPermissionsIncrease(extension, is_extension_installed); 1391 1392 if (is_extension_installed && !reloading) { 1393 // To upgrade an extension in place, unload the old one and then load the 1394 // new one. ReloadExtension disables the extension, which is sufficient. 1395 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE); 1396 } 1397 1398 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { 1399 // Only prefs is checked for the blacklist. We rely on callers to check the 1400 // blacklist before calling into here, e.g. CrxInstaller checks before 1401 // installation then threads through the install and pending install flow 1402 // of this class, and we check when loading installed extensions. 1403 registry_->AddBlacklisted(extension); 1404 } else if (!reloading && 1405 extension_prefs_->IsExtensionDisabled(extension->id())) { 1406 registry_->AddDisabled(extension); 1407 if (extension_sync_service_) 1408 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); 1409 content::NotificationService::current()->Notify( 1410 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED, 1411 content::Source<Profile>(profile_), 1412 content::Details<const Extension>(extension)); 1413 1414 // Show the extension disabled error if a permissions increase or a remote 1415 // installation is the reason it was disabled, and no other reasons exist. 1416 int reasons = extension_prefs_->GetDisableReasons(extension->id()); 1417 const int kReasonMask = Extension::DISABLE_PERMISSIONS_INCREASE | 1418 Extension::DISABLE_REMOTE_INSTALL; 1419 if (reasons & kReasonMask && !(reasons & ~kReasonMask)) { 1420 extensions::AddExtensionDisabledError( 1421 this, 1422 extension, 1423 extension_prefs_->HasDisableReason( 1424 extension->id(), Extension::DISABLE_REMOTE_INSTALL)); 1425 } 1426 } else if (reloading) { 1427 // Replace the old extension with the new version. 1428 CHECK(!registry_->AddDisabled(extension)); 1429 EnableExtension(extension->id()); 1430 } else { 1431 // All apps that are displayed in the launcher are ordered by their ordinals 1432 // so we must ensure they have valid ordinals. 1433 if (extension->RequiresSortOrdinal()) { 1434 extension_prefs_->app_sorting()->SetExtensionVisible( 1435 extension->id(), 1436 extension->ShouldDisplayInNewTabPage() && 1437 !extension_prefs_->IsEphemeralApp(extension->id())); 1438 if (!extension_prefs_->IsEphemeralApp(extension->id())) { 1439 extension_prefs_->app_sorting()->EnsureValidOrdinals( 1440 extension->id(), syncer::StringOrdinal()); 1441 } 1442 } 1443 1444 registry_->AddEnabled(extension); 1445 if (extension_sync_service_) 1446 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); 1447 NotifyExtensionLoaded(extension); 1448 } 1449 system_->runtime_data()->SetBeingUpgraded(extension, false); 1450} 1451 1452void ExtensionService::AddComponentExtension(const Extension* extension) { 1453 const std::string old_version_string( 1454 extension_prefs_->GetVersionString(extension->id())); 1455 const Version old_version(old_version_string); 1456 1457 VLOG(1) << "AddComponentExtension " << extension->name(); 1458 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) { 1459 VLOG(1) << "Component extension " << extension->name() << " (" 1460 << extension->id() << ") installing/upgrading from '" 1461 << old_version_string << "' to " << extension->version()->GetString(); 1462 1463 AddNewOrUpdatedExtension(extension, 1464 Extension::ENABLED, 1465 extensions::kInstallFlagNone, 1466 syncer::StringOrdinal(), 1467 std::string()); 1468 return; 1469 } 1470 1471 AddExtension(extension); 1472} 1473 1474void ExtensionService::CheckPermissionsIncrease(const Extension* extension, 1475 bool is_extension_installed) { 1476 extensions::PermissionsUpdater(profile_).InitializePermissions(extension); 1477 1478 // We keep track of all permissions the user has granted each extension. 1479 // This allows extensions to gracefully support backwards compatibility 1480 // by including unknown permissions in their manifests. When the user 1481 // installs the extension, only the recognized permissions are recorded. 1482 // When the unknown permissions become recognized (e.g., through browser 1483 // upgrade), we can prompt the user to accept these new permissions. 1484 // Extensions can also silently upgrade to less permissions, and then 1485 // silently upgrade to a version that adds these permissions back. 1486 // 1487 // For example, pretend that Chrome 10 includes a permission "omnibox" 1488 // for an API that adds suggestions to the omnibox. An extension can 1489 // maintain backwards compatibility while still having "omnibox" in the 1490 // manifest. If a user installs the extension on Chrome 9, the browser 1491 // will record the permissions it recognized, not including "omnibox." 1492 // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome 1493 // will disable the extension and prompt the user to approve the increase 1494 // in privileges. The extension could then release a new version that 1495 // removes the "omnibox" permission. When the user upgrades, Chrome will 1496 // still remember that "omnibox" had been granted, so that if the 1497 // extension once again includes "omnibox" in an upgrade, the extension 1498 // can upgrade without requiring this user's approval. 1499 int disable_reasons = extension_prefs_->GetDisableReasons(extension->id()); 1500 1501 bool auto_grant_permission = 1502 (!is_extension_installed && extension->was_installed_by_default()) || 1503 extensions::ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode(); 1504 // Silently grant all active permissions to default apps only on install. 1505 // After install they should behave like other apps. 1506 // Silently grant all active permissions to apps install in kiosk mode on both 1507 // install and update. 1508 if (auto_grant_permission) 1509 GrantPermissions(extension); 1510 1511 bool is_privilege_increase = false; 1512 // We only need to compare the granted permissions to the current permissions 1513 // if the extension is not allowed to silently increase its permissions. 1514 if (!extensions::PermissionsData::CanSilentlyIncreasePermissions(extension) && 1515 !auto_grant_permission) { 1516 // Add all the recognized permissions if the granted permissions list 1517 // hasn't been initialized yet. 1518 scoped_refptr<PermissionSet> granted_permissions = 1519 extension_prefs_->GetGrantedPermissions(extension->id()); 1520 CHECK(granted_permissions.get()); 1521 1522 // Here, we check if an extension's privileges have increased in a manner 1523 // that requires the user's approval. This could occur because the browser 1524 // upgraded and recognized additional privileges, or an extension upgrades 1525 // to a version that requires additional privileges. 1526 is_privilege_increase = 1527 extensions::PermissionMessageProvider::Get()->IsPrivilegeIncrease( 1528 granted_permissions, 1529 extension->permissions_data()->active_permissions().get(), 1530 extension->GetType()); 1531 } 1532 1533 if (is_extension_installed) { 1534 // If the extension was already disabled, suppress any alerts for becoming 1535 // disabled on permissions increase. 1536 bool previously_disabled = 1537 extension_prefs_->IsExtensionDisabled(extension->id()); 1538 // Legacy disabled extensions do not have a disable reason. Infer that if 1539 // there was no permission increase, it was likely disabled by the user. 1540 if (previously_disabled && disable_reasons == Extension::DISABLE_NONE && 1541 !extension_prefs_->DidExtensionEscalatePermissions(extension->id())) { 1542 disable_reasons |= Extension::DISABLE_USER_ACTION; 1543 } 1544 // Extensions that came to us disabled from sync need a similar inference, 1545 // except based on the new version's permissions. 1546 if (previously_disabled && 1547 disable_reasons == Extension::DISABLE_UNKNOWN_FROM_SYNC) { 1548 // Remove the DISABLE_UNKNOWN_FROM_SYNC reason. 1549 extension_prefs_->ClearDisableReasons(extension->id()); 1550 if (!is_privilege_increase) 1551 disable_reasons |= Extension::DISABLE_USER_ACTION; 1552 } 1553 disable_reasons &= ~Extension::DISABLE_UNKNOWN_FROM_SYNC; 1554 } 1555 1556 // Extension has changed permissions significantly. Disable it. A 1557 // notification should be sent by the caller. If the extension is already 1558 // disabled because it was installed remotely, don't add another disable 1559 // reason, but instead always set the "did escalate permissions" flag, to 1560 // ensure enabling it will always show a warning. 1561 if (disable_reasons == Extension::DISABLE_REMOTE_INSTALL) { 1562 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); 1563 } else if (is_privilege_increase) { 1564 disable_reasons |= Extension::DISABLE_PERMISSIONS_INCREASE; 1565 if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id())) { 1566 RecordPermissionMessagesHistogram(extension, 1567 "Extensions.Permissions_AutoDisable2"); 1568 } 1569 extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED); 1570 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); 1571 } 1572 if (disable_reasons != Extension::DISABLE_NONE) { 1573 extension_prefs_->AddDisableReason( 1574 extension->id(), 1575 static_cast<Extension::DisableReason>(disable_reasons)); 1576 } 1577} 1578 1579void ExtensionService::UpdateActiveExtensionsInCrashReporter() { 1580 std::set<std::string> extension_ids; 1581 const ExtensionSet& extensions = registry_->enabled_extensions(); 1582 for (ExtensionSet::const_iterator iter = extensions.begin(); 1583 iter != extensions.end(); ++iter) { 1584 const Extension* extension = iter->get(); 1585 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) 1586 extension_ids.insert(extension->id()); 1587 } 1588 1589 // TODO(kalman): This is broken. ExtensionService is per-profile. 1590 // crash_keys::SetActiveExtensions is per-process. See 1591 // http://crbug.com/355029. 1592 crash_keys::SetActiveExtensions(extension_ids); 1593} 1594 1595void ExtensionService::OnExtensionInstalled( 1596 const Extension* extension, 1597 const syncer::StringOrdinal& page_ordinal, 1598 int install_flags) { 1599 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1600 1601 const std::string& id = extension->id(); 1602 bool initial_enable = ShouldEnableOnInstall(extension); 1603 std::string install_parameter; 1604 const extensions::PendingExtensionInfo* pending_extension_info = 1605 pending_extension_manager()->GetById(id); 1606 if (pending_extension_info) { 1607 if (!pending_extension_info->ShouldAllowInstall(extension)) { 1608 pending_extension_manager()->Remove(id); 1609 1610 LOG(WARNING) << "ShouldAllowInstall() returned false for " 1611 << id << " of type " << extension->GetType() 1612 << " and update URL " 1613 << extensions::ManifestURL::GetUpdateURL(extension).spec() 1614 << "; not installing"; 1615 1616 // Delete the extension directory since we're not going to 1617 // load it. 1618 if (!GetFileTaskRunner()->PostTask( 1619 FROM_HERE, 1620 base::Bind(&extensions::file_util::DeleteFile, 1621 extension->path(), 1622 true))) { 1623 NOTREACHED(); 1624 } 1625 return; 1626 } 1627 1628 install_parameter = pending_extension_info->install_parameter(); 1629 pending_extension_manager()->Remove(id); 1630 } else { 1631 // We explicitly want to re-enable an uninstalled external 1632 // extension; if we're here, that means the user is manually 1633 // installing the extension. 1634 if (extension_prefs_->IsExternalExtensionUninstalled(id)) { 1635 initial_enable = true; 1636 } 1637 } 1638 1639 // Unsupported requirements overrides the management policy. 1640 if (install_flags & extensions::kInstallFlagHasRequirementErrors) { 1641 initial_enable = false; 1642 extension_prefs_->AddDisableReason( 1643 id, Extension::DISABLE_UNSUPPORTED_REQUIREMENT); 1644 // If the extension was disabled because of unsupported requirements but 1645 // now supports all requirements after an update and there are not other 1646 // disable reasons, enable it. 1647 } else if (extension_prefs_->GetDisableReasons(id) == 1648 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) { 1649 initial_enable = true; 1650 extension_prefs_->ClearDisableReasons(id); 1651 } 1652 1653 if (install_flags & extensions::kInstallFlagIsBlacklistedForMalware) { 1654 // Installation of a blacklisted extension can happen from sync, policy, 1655 // etc, where to maintain consistency we need to install it, just never 1656 // load it (see AddExtension). Usually it should be the job of callers to 1657 // incercept blacklisted extension earlier (e.g. CrxInstaller, before even 1658 // showing the install dialogue). 1659 extension_prefs_->AcknowledgeBlacklistedExtension(id); 1660 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall", 1661 extension->location(), 1662 Manifest::NUM_LOCATIONS); 1663 } 1664 1665 if (!GetInstalledExtension(extension->id())) { 1666 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType", 1667 extension->GetType(), 100); 1668 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallSource", 1669 extension->location(), Manifest::NUM_LOCATIONS); 1670 RecordPermissionMessagesHistogram(extension, 1671 "Extensions.Permissions_Install2"); 1672 } else { 1673 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateType", 1674 extension->GetType(), 100); 1675 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateSource", 1676 extension->location(), Manifest::NUM_LOCATIONS); 1677 1678 // A fully installed app cannot be demoted to an ephemeral app. 1679 if ((install_flags & extensions::kInstallFlagIsEphemeral) && 1680 !extension_prefs_->IsEphemeralApp(id)) { 1681 install_flags &= ~static_cast<int>(extensions::kInstallFlagIsEphemeral); 1682 } 1683 } 1684 1685 const Extension::State initial_state = 1686 initial_enable ? Extension::ENABLED : Extension::DISABLED; 1687 if (ShouldDelayExtensionUpdate( 1688 id, 1689 !!(install_flags & extensions::kInstallFlagInstallImmediately))) { 1690 extension_prefs_->SetDelayedInstallInfo( 1691 extension, 1692 initial_state, 1693 install_flags, 1694 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, 1695 page_ordinal, 1696 install_parameter); 1697 1698 // Transfer ownership of |extension|. 1699 delayed_installs_.Insert(extension); 1700 1701 // Notify observers that app update is available. 1702 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 1703 OnAppUpdateAvailable(extension)); 1704 return; 1705 } 1706 1707 extensions::SharedModuleService::ImportStatus status = 1708 shared_module_service_->SatisfyImports(extension); 1709 if (installs_delayed_for_gc_) { 1710 extension_prefs_->SetDelayedInstallInfo( 1711 extension, 1712 initial_state, 1713 install_flags, 1714 extensions::ExtensionPrefs::DELAY_REASON_GC, 1715 page_ordinal, 1716 install_parameter); 1717 delayed_installs_.Insert(extension); 1718 } else if (status != SharedModuleService::IMPORT_STATUS_OK) { 1719 if (status == SharedModuleService::IMPORT_STATUS_UNSATISFIED) { 1720 extension_prefs_->SetDelayedInstallInfo( 1721 extension, 1722 initial_state, 1723 install_flags, 1724 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS, 1725 page_ordinal, 1726 install_parameter); 1727 delayed_installs_.Insert(extension); 1728 } 1729 } else { 1730 AddNewOrUpdatedExtension(extension, 1731 initial_state, 1732 install_flags, 1733 page_ordinal, 1734 install_parameter); 1735 } 1736} 1737 1738void ExtensionService::AddNewOrUpdatedExtension( 1739 const Extension* extension, 1740 Extension::State initial_state, 1741 int install_flags, 1742 const syncer::StringOrdinal& page_ordinal, 1743 const std::string& install_parameter) { 1744 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1745 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id()); 1746 extension_prefs_->OnExtensionInstalled( 1747 extension, initial_state, page_ordinal, install_flags, install_parameter); 1748 delayed_installs_.Remove(extension->id()); 1749 if (InstallVerifier::NeedsVerification(*extension)) 1750 system_->install_verifier()->VerifyExtension(extension->id()); 1751 FinishInstallation(extension, was_ephemeral); 1752} 1753 1754void ExtensionService::MaybeFinishDelayedInstallation( 1755 const std::string& extension_id) { 1756 // Check if the extension already got installed. 1757 if (!delayed_installs_.Contains(extension_id)) 1758 return; 1759 extensions::ExtensionPrefs::DelayReason reason = 1760 extension_prefs_->GetDelayedInstallReason(extension_id); 1761 1762 // Check if the extension is idle. DELAY_REASON_NONE is used for older 1763 // preferences files that will not have set this field but it was previously 1764 // only used for idle updates. 1765 if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE || 1766 reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) && 1767 is_ready() && !extensions::util::IsExtensionIdle(extension_id, profile_)) 1768 return; 1769 1770 const Extension* extension = delayed_installs_.GetByID(extension_id); 1771 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) { 1772 extensions::SharedModuleService::ImportStatus status = 1773 shared_module_service_->SatisfyImports(extension); 1774 if (status != SharedModuleService::IMPORT_STATUS_OK) { 1775 if (status == SharedModuleService::IMPORT_STATUS_UNRECOVERABLE) { 1776 delayed_installs_.Remove(extension_id); 1777 // Make sure no version of the extension is actually installed, (i.e., 1778 // that this delayed install was not an update). 1779 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get()); 1780 extension_prefs_->DeleteExtensionPrefs(extension_id); 1781 } 1782 return; 1783 } 1784 } 1785 1786 FinishDelayedInstallation(extension_id); 1787} 1788 1789void ExtensionService::FinishDelayedInstallation( 1790 const std::string& extension_id) { 1791 scoped_refptr<const Extension> extension( 1792 GetPendingExtensionUpdate(extension_id)); 1793 CHECK(extension.get()); 1794 delayed_installs_.Remove(extension_id); 1795 1796 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id()); 1797 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) 1798 NOTREACHED(); 1799 1800 FinishInstallation(extension.get(), was_ephemeral); 1801} 1802 1803void ExtensionService::FinishInstallation( 1804 const Extension* extension, bool was_ephemeral) { 1805 const extensions::Extension* existing_extension = 1806 GetInstalledExtension(extension->id()); 1807 bool is_update = false; 1808 std::string old_name; 1809 if (existing_extension) { 1810 is_update = true; 1811 old_name = existing_extension->name(); 1812 } 1813 bool from_ephemeral = 1814 was_ephemeral && !extension_prefs_->IsEphemeralApp(extension->id()); 1815 extensions::InstalledExtensionInfo details( 1816 extension, is_update, from_ephemeral, old_name); 1817 content::NotificationService::current()->Notify( 1818 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, 1819 content::Source<Profile>(profile_), 1820 content::Details<const extensions::InstalledExtensionInfo>(&details)); 1821 1822 registry_->TriggerOnWillBeInstalled( 1823 extension, is_update, from_ephemeral, old_name); 1824 1825 // Unpacked extensions default to allowing file access, but if that has been 1826 // overridden, don't reset the value. 1827 if (Manifest::ShouldAlwaysAllowFileAccess(extension->location()) && 1828 !extension_prefs_->HasAllowFileAccessSetting(extension->id())) { 1829 extension_prefs_->SetAllowFileAccess(extension->id(), true); 1830 } 1831 1832 AddExtension(extension); 1833 1834 // Notify observers that need to know when an installation is complete. 1835 registry_->TriggerOnInstalled(extension, is_update); 1836 1837 // Check extensions that may have been delayed only because this shared module 1838 // was not available. 1839 if (SharedModuleInfo::IsSharedModule(extension)) 1840 MaybeFinishDelayedInstallations(); 1841} 1842 1843void ExtensionService::PromoteEphemeralApp( 1844 const extensions::Extension* extension, bool is_from_sync) { 1845 DCHECK(GetInstalledExtension(extension->id()) && 1846 extension_prefs_->IsEphemeralApp(extension->id())); 1847 1848 if (extension->RequiresSortOrdinal()) { 1849 extension_prefs_->app_sorting()->SetExtensionVisible( 1850 extension->id(), extension->ShouldDisplayInNewTabPage()); 1851 1852 if (!is_from_sync) { 1853 // Reset the sort ordinals of the app to ensure it is added to the default 1854 // position, like newly installed apps would. 1855 extension_prefs_->app_sorting()->ClearOrdinals(extension->id()); 1856 } 1857 1858 extension_prefs_->app_sorting()->EnsureValidOrdinals( 1859 extension->id(), syncer::StringOrdinal()); 1860 } 1861 1862 // Remove the ephemeral flags from the preferences. 1863 extension_prefs_->OnEphemeralAppPromoted(extension->id()); 1864 1865 // Fire install-related events to allow observers to handle the promotion 1866 // of the ephemeral app. 1867 extensions::InstalledExtensionInfo details( 1868 extension, 1869 true /* is update */, 1870 true /* from ephemeral */, 1871 extension->name() /* old name */); 1872 content::NotificationService::current()->Notify( 1873 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, 1874 content::Source<Profile>(profile_), 1875 content::Details<const extensions::InstalledExtensionInfo>(&details)); 1876 1877 registry_->TriggerOnWillBeInstalled( 1878 extension, 1879 true /* is update */, 1880 true /* from ephemeral */, 1881 extension->name() /* old name */); 1882 1883 if (registry_->enabled_extensions().Contains(extension->id())) { 1884 // If the app is already enabled and loaded, fire the load events to allow 1885 // observers to handle the promotion of the ephemeral app. 1886 content::NotificationService::current()->Notify( 1887 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 1888 content::Source<Profile>(profile_), 1889 content::Details<const Extension>(extension)); 1890 1891 registry_->TriggerOnLoaded(extension); 1892 } else { 1893 // Cached ephemeral apps may be updated and disabled due to permissions 1894 // increase. The app can be enabled (as long as no other disable reasons 1895 // exist) as the install was user-acknowledged. 1896 int disable_mask = Extension::DISABLE_NONE; 1897 if (!is_from_sync) 1898 disable_mask |= Extension::DISABLE_PERMISSIONS_INCREASE; 1899 1900 int other_disable_reasons = 1901 extension_prefs_->GetDisableReasons(extension->id()) & ~disable_mask; 1902 if (!other_disable_reasons) { 1903 if (extension_prefs_->DidExtensionEscalatePermissions(extension->id())) 1904 GrantPermissionsAndEnableExtension(extension); 1905 else 1906 EnableExtension(extension->id()); 1907 } 1908 } 1909 1910 registry_->TriggerOnInstalled(extension, true); 1911 1912 if (!is_from_sync && extension_sync_service_) 1913 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); 1914} 1915 1916const Extension* ExtensionService::GetPendingExtensionUpdate( 1917 const std::string& id) const { 1918 return delayed_installs_.GetByID(id); 1919} 1920 1921void ExtensionService::TrackTerminatedExtension(const Extension* extension) { 1922 // No need to check for duplicates; inserting a duplicate is a no-op. 1923 registry_->AddTerminated(make_scoped_refptr(extension)); 1924 extensions_being_terminated_.erase(extension->id()); 1925 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_TERMINATE); 1926} 1927 1928void ExtensionService::TerminateExtension(const std::string& extension_id) { 1929 const Extension* extension = GetInstalledExtension(extension_id); 1930 TrackTerminatedExtension(extension); 1931} 1932 1933void ExtensionService::UntrackTerminatedExtension(const std::string& id) { 1934 std::string lowercase_id = base::StringToLowerASCII(id); 1935 const Extension* extension = 1936 registry_->terminated_extensions().GetByID(lowercase_id); 1937 registry_->RemoveTerminated(lowercase_id); 1938 if (extension) { 1939 content::NotificationService::current()->Notify( 1940 extensions::NOTIFICATION_EXTENSION_REMOVED, 1941 content::Source<Profile>(profile_), 1942 content::Details<const Extension>(extension)); 1943 } 1944} 1945 1946const Extension* ExtensionService::GetInstalledExtension( 1947 const std::string& id) const { 1948 return registry_->GetExtensionById(id, ExtensionRegistry::EVERYTHING); 1949} 1950 1951bool ExtensionService::OnExternalExtensionFileFound( 1952 const std::string& id, 1953 const Version* version, 1954 const base::FilePath& path, 1955 Manifest::Location location, 1956 int creation_flags, 1957 bool mark_acknowledged) { 1958 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1959 CHECK(Extension::IdIsValid(id)); 1960 if (extension_prefs_->IsExternalExtensionUninstalled(id)) 1961 return false; 1962 1963 // Before even bothering to unpack, check and see if we already have this 1964 // version. This is important because these extensions are going to get 1965 // installed on every startup. 1966 const Extension* existing = GetExtensionById(id, true); 1967 1968 if (existing) { 1969 // The default apps will have the location set as INTERNAL. Since older 1970 // default apps are installed as EXTERNAL, we override them. However, if the 1971 // app is already installed as internal, then do the version check. 1972 // TODO(grv) : Remove after Q1-2013. 1973 bool is_default_apps_migration = 1974 (location == Manifest::INTERNAL && 1975 Manifest::IsExternalLocation(existing->location())); 1976 1977 if (!is_default_apps_migration) { 1978 DCHECK(version); 1979 1980 switch (existing->version()->CompareTo(*version)) { 1981 case -1: // existing version is older, we should upgrade 1982 break; 1983 case 0: // existing version is same, do nothing 1984 return false; 1985 case 1: // existing version is newer, uh-oh 1986 LOG(WARNING) << "Found external version of extension " << id 1987 << "that is older than current version. Current version " 1988 << "is: " << existing->VersionString() << ". New " 1989 << "version is: " << version->GetString() 1990 << ". Keeping current version."; 1991 return false; 1992 } 1993 } 1994 } 1995 1996 // If the extension is already pending, don't start an install. 1997 if (!pending_extension_manager()->AddFromExternalFile( 1998 id, location, *version, creation_flags, mark_acknowledged)) { 1999 return false; 2000 } 2001 2002 // no client (silent install) 2003 scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this)); 2004 installer->set_install_source(location); 2005 installer->set_expected_id(id); 2006 installer->set_expected_version(*version); 2007 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE); 2008 installer->set_creation_flags(creation_flags); 2009#if defined(OS_CHROMEOS) 2010 extensions::InstallLimiter::Get(profile_)->Add(installer, path); 2011#else 2012 installer->InstallCrx(path); 2013#endif 2014 2015 // Depending on the source, a new external extension might not need a user 2016 // notification on installation. For such extensions, mark them acknowledged 2017 // now to suppress the notification. 2018 if (mark_acknowledged) 2019 external_install_manager_->AcknowledgeExternalExtension(id); 2020 2021 return true; 2022} 2023 2024void ExtensionService::DidCreateRenderViewForBackgroundPage( 2025 extensions::ExtensionHost* host) { 2026 OrphanedDevTools::iterator iter = 2027 orphaned_dev_tools_.find(host->extension_id()); 2028 if (iter == orphaned_dev_tools_.end()) 2029 return; 2030 2031 iter->second->ConnectWebContents(host->host_contents()); 2032 orphaned_dev_tools_.erase(iter); 2033} 2034 2035void ExtensionService::Observe(int type, 2036 const content::NotificationSource& source, 2037 const content::NotificationDetails& details) { 2038 switch (type) { 2039 case chrome::NOTIFICATION_APP_TERMINATING: 2040 // Shutdown has started. Don't start any more extension installs. 2041 // (We cannot use ExtensionService::Shutdown() for this because it 2042 // happens too late in browser teardown.) 2043 browser_terminating_ = true; 2044 break; 2045 case extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: { 2046 if (profile_ != 2047 content::Source<Profile>(source).ptr()->GetOriginalProfile()) { 2048 break; 2049 } 2050 2051 extensions::ExtensionHost* host = 2052 content::Details<extensions::ExtensionHost>(details).ptr(); 2053 2054 // If the extension is already being terminated, there is nothing left to 2055 // do. 2056 if (!extensions_being_terminated_.insert(host->extension_id()).second) 2057 break; 2058 2059 // Mark the extension as terminated and Unload it. We want it to 2060 // be in a consistent state: either fully working or not loaded 2061 // at all, but never half-crashed. We do it in a PostTask so 2062 // that other handlers of this notification will still have 2063 // access to the Extension and ExtensionHost. 2064 base::MessageLoop::current()->PostTask( 2065 FROM_HERE, 2066 base::Bind( 2067 &ExtensionService::TrackTerminatedExtension, 2068 AsWeakPtr(), 2069 host->extension())); 2070 break; 2071 } 2072 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { 2073 content::RenderProcessHost* process = 2074 content::Source<content::RenderProcessHost>(source).ptr(); 2075 Profile* host_profile = 2076 Profile::FromBrowserContext(process->GetBrowserContext()); 2077 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile())) 2078 break; 2079 2080 extensions::ProcessMap* process_map = 2081 extensions::ProcessMap::Get(profile_); 2082 if (process_map->Contains(process->GetID())) { 2083 // An extension process was terminated, this might have resulted in an 2084 // app or extension becoming idle. 2085 std::set<std::string> extension_ids = 2086 process_map->GetExtensionsInProcess(process->GetID()); 2087 for (std::set<std::string>::const_iterator it = extension_ids.begin(); 2088 it != extension_ids.end(); ++it) { 2089 if (delayed_installs_.Contains(*it)) { 2090 base::MessageLoop::current()->PostDelayedTask( 2091 FROM_HERE, 2092 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation, 2093 AsWeakPtr(), *it), 2094 base::TimeDelta::FromSeconds(kUpdateIdleDelay)); 2095 } 2096 } 2097 } 2098 2099 process_map->RemoveAllFromProcess(process->GetID()); 2100 BrowserThread::PostTask( 2101 BrowserThread::IO, 2102 FROM_HERE, 2103 base::Bind(&extensions::InfoMap::UnregisterAllExtensionsInProcess, 2104 system_->info_map(), 2105 process->GetID())); 2106 break; 2107 } 2108 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: { 2109 // Notify observers that chrome update is available. 2110 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, 2111 OnChromeUpdateAvailable()); 2112 break; 2113 } 2114 case chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED: { 2115 OnProfileDestructionStarted(); 2116 break; 2117 } 2118 2119 default: 2120 NOTREACHED() << "Unexpected notification type."; 2121 } 2122} 2123 2124void ExtensionService::OnExtensionInstallPrefChanged() { 2125 error_controller_->ShowErrorIfNeeded(); 2126 CheckManagementPolicy(); 2127} 2128 2129bool ExtensionService::ShouldEnableOnInstall(const Extension* extension) { 2130 // Extensions installed by policy can't be disabled. So even if a previous 2131 // installation disabled the extension, make sure it is now enabled. 2132 if (system_->management_policy()->MustRemainEnabled(extension, NULL)) 2133 return true; 2134 2135 if (extension_prefs_->IsExtensionDisabled(extension->id())) 2136 return false; 2137 2138 if (FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) { 2139 // External extensions are initially disabled. We prompt the user before 2140 // enabling them. Hosted apps are excepted because they are not dangerous 2141 // (they need to be launched by the user anyway). 2142 if (extension->GetType() != Manifest::TYPE_HOSTED_APP && 2143 Manifest::IsExternalLocation(extension->location()) && 2144 !extension_prefs_->IsExternalExtensionAcknowledged(extension->id())) { 2145 return false; 2146 } 2147 } 2148 2149 return true; 2150} 2151 2152bool ExtensionService::ShouldDelayExtensionUpdate( 2153 const std::string& extension_id, 2154 bool install_immediately) const { 2155 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable"; 2156 2157 // If delayed updates are globally disabled, or just for this extension, 2158 // don't delay. 2159 if (!install_updates_when_idle_ || install_immediately) 2160 return false; 2161 2162 const Extension* old = GetInstalledExtension(extension_id); 2163 // If there is no old extension, this is not an update, so don't delay. 2164 if (!old) 2165 return false; 2166 2167 if (extensions::BackgroundInfo::HasPersistentBackgroundPage(old)) { 2168 // Delay installation if the extension listens for the onUpdateAvailable 2169 // event. 2170 return system_->event_router()->ExtensionHasEventListener( 2171 extension_id, kOnUpdateAvailableEvent); 2172 } else { 2173 // Delay installation if the extension is not idle. 2174 return !extensions::util::IsExtensionIdle(extension_id, profile_); 2175 } 2176} 2177 2178void ExtensionService::OnGarbageCollectIsolatedStorageStart() { 2179 DCHECK(!installs_delayed_for_gc_); 2180 installs_delayed_for_gc_ = true; 2181} 2182 2183void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { 2184 DCHECK(installs_delayed_for_gc_); 2185 installs_delayed_for_gc_ = false; 2186 MaybeFinishDelayedInstallations(); 2187} 2188 2189void ExtensionService::MaybeFinishDelayedInstallations() { 2190 std::vector<std::string> to_be_installed; 2191 for (ExtensionSet::const_iterator it = delayed_installs_.begin(); 2192 it != delayed_installs_.end(); 2193 ++it) { 2194 to_be_installed.push_back((*it)->id()); 2195 } 2196 for (std::vector<std::string>::const_iterator it = to_be_installed.begin(); 2197 it != to_be_installed.end(); 2198 ++it) { 2199 MaybeFinishDelayedInstallation(*it); 2200 } 2201} 2202 2203void ExtensionService::OnBlacklistUpdated() { 2204 blacklist_->GetBlacklistedIDs( 2205 registry_->GenerateInstalledExtensionsSet()->GetIDs(), 2206 base::Bind(&ExtensionService::ManageBlacklist, AsWeakPtr())); 2207} 2208 2209void ExtensionService::ManageBlacklist( 2210 const extensions::Blacklist::BlacklistStateMap& state_map) { 2211 DCHECK_CURRENTLY_ON(BrowserThread::UI); 2212 2213 std::set<std::string> blocked; 2214 ExtensionIdSet greylist; 2215 ExtensionIdSet unchanged; 2216 for (extensions::Blacklist::BlacklistStateMap::const_iterator it = 2217 state_map.begin(); 2218 it != state_map.end(); 2219 ++it) { 2220 switch (it->second) { 2221 case extensions::NOT_BLACKLISTED: 2222 break; 2223 2224 case extensions::BLACKLISTED_MALWARE: 2225 blocked.insert(it->first); 2226 break; 2227 2228 case extensions::BLACKLISTED_SECURITY_VULNERABILITY: 2229 case extensions::BLACKLISTED_CWS_POLICY_VIOLATION: 2230 case extensions::BLACKLISTED_POTENTIALLY_UNWANTED: 2231 greylist.insert(it->first); 2232 break; 2233 2234 case extensions::BLACKLISTED_UNKNOWN: 2235 unchanged.insert(it->first); 2236 break; 2237 } 2238 } 2239 2240 UpdateBlockedExtensions(blocked, unchanged); 2241 UpdateGreylistedExtensions(greylist, unchanged, state_map); 2242 2243 error_controller_->ShowErrorIfNeeded(); 2244} 2245 2246namespace { 2247void Partition(const ExtensionIdSet& before, 2248 const ExtensionIdSet& after, 2249 const ExtensionIdSet& unchanged, 2250 ExtensionIdSet* no_longer, 2251 ExtensionIdSet* not_yet) { 2252 *not_yet = base::STLSetDifference<ExtensionIdSet>(after, before); 2253 *no_longer = base::STLSetDifference<ExtensionIdSet>(before, after); 2254 *no_longer = base::STLSetDifference<ExtensionIdSet>(*no_longer, unchanged); 2255} 2256} // namespace 2257 2258void ExtensionService::UpdateBlockedExtensions( 2259 const ExtensionIdSet& blocked, 2260 const ExtensionIdSet& unchanged) { 2261 ExtensionIdSet not_yet_blocked, no_longer_blocked; 2262 Partition(registry_->blacklisted_extensions().GetIDs(), 2263 blocked, unchanged, 2264 &no_longer_blocked, ¬_yet_blocked); 2265 2266 for (ExtensionIdSet::iterator it = no_longer_blocked.begin(); 2267 it != no_longer_blocked.end(); ++it) { 2268 scoped_refptr<const Extension> extension = 2269 registry_->blacklisted_extensions().GetByID(*it); 2270 if (!extension.get()) { 2271 NOTREACHED() << "Extension " << *it << " no longer blocked, " 2272 << "but it was never blocked."; 2273 continue; 2274 } 2275 registry_->RemoveBlacklisted(*it); 2276 extension_prefs_->SetExtensionBlacklisted(extension->id(), false); 2277 AddExtension(extension.get()); 2278 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled", 2279 extension->location(), 2280 Manifest::NUM_LOCATIONS); 2281 } 2282 2283 for (ExtensionIdSet::iterator it = not_yet_blocked.begin(); 2284 it != not_yet_blocked.end(); ++it) { 2285 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); 2286 if (!extension.get()) { 2287 NOTREACHED() << "Extension " << *it << " needs to be " 2288 << "blacklisted, but it's not installed."; 2289 continue; 2290 } 2291 registry_->AddBlacklisted(extension); 2292 extension_prefs_->SetExtensionBlacklistState( 2293 extension->id(), extensions::BLACKLISTED_MALWARE); 2294 UnloadExtension(*it, UnloadedExtensionInfo::REASON_BLACKLIST); 2295 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled", 2296 extension->location(), Manifest::NUM_LOCATIONS); 2297 } 2298} 2299 2300// TODO(oleg): UMA logging 2301void ExtensionService::UpdateGreylistedExtensions( 2302 const ExtensionIdSet& greylist, 2303 const ExtensionIdSet& unchanged, 2304 const extensions::Blacklist::BlacklistStateMap& state_map) { 2305 ExtensionIdSet not_yet_greylisted, no_longer_greylisted; 2306 Partition(greylist_.GetIDs(), 2307 greylist, unchanged, 2308 &no_longer_greylisted, ¬_yet_greylisted); 2309 2310 for (ExtensionIdSet::iterator it = no_longer_greylisted.begin(); 2311 it != no_longer_greylisted.end(); ++it) { 2312 scoped_refptr<const Extension> extension = greylist_.GetByID(*it); 2313 if (!extension.get()) { 2314 NOTREACHED() << "Extension " << *it << " no longer greylisted, " 2315 << "but it was not marked as greylisted."; 2316 continue; 2317 } 2318 2319 greylist_.Remove(*it); 2320 extension_prefs_->SetExtensionBlacklistState(extension->id(), 2321 extensions::NOT_BLACKLISTED); 2322 if (extension_prefs_->GetDisableReasons(extension->id()) & 2323 extensions::Extension::DISABLE_GREYLIST) 2324 EnableExtension(*it); 2325 } 2326 2327 for (ExtensionIdSet::iterator it = not_yet_greylisted.begin(); 2328 it != not_yet_greylisted.end(); ++it) { 2329 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); 2330 if (!extension.get()) { 2331 NOTREACHED() << "Extension " << *it << " needs to be " 2332 << "disabled, but it's not installed."; 2333 continue; 2334 } 2335 greylist_.Insert(extension); 2336 extension_prefs_->SetExtensionBlacklistState(extension->id(), 2337 state_map.find(*it)->second); 2338 if (registry_->enabled_extensions().Contains(extension->id())) 2339 DisableExtension(*it, extensions::Extension::DISABLE_GREYLIST); 2340 } 2341} 2342 2343void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { 2344 update_observers_.AddObserver(observer); 2345} 2346 2347void ExtensionService::RemoveUpdateObserver( 2348 extensions::UpdateObserver* observer) { 2349 update_observers_.RemoveObserver(observer); 2350} 2351 2352// Used only by test code. 2353void ExtensionService::UnloadAllExtensionsInternal() { 2354 profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions(); 2355 2356 registry_->ClearAll(); 2357 system_->runtime_data()->ClearAll(); 2358 2359 // TODO(erikkay) should there be a notification for this? We can't use 2360 // EXTENSION_UNLOADED since that implies that the extension has been disabled 2361 // or uninstalled. 2362} 2363 2364void ExtensionService::OnProfileDestructionStarted() { 2365 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); 2366 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); 2367 it != ids_to_unload.end(); 2368 ++it) { 2369 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); 2370 } 2371} 2372