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