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