1// Copyright 2014 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_system_impl.h" 6 7#include "base/base_switches.h" 8#include "base/bind.h" 9#include "base/command_line.h" 10#include "base/files/file_path.h" 11#include "base/memory/weak_ptr.h" 12#include "base/metrics/field_trial.h" 13#include "base/metrics/histogram.h" 14#include "base/strings/string_tokenizer.h" 15#include "base/strings/string_util.h" 16#include "chrome/browser/browser_process.h" 17#include "chrome/browser/content_settings/cookie_settings.h" 18#include "chrome/browser/extensions/blacklist.h" 19#include "chrome/browser/extensions/component_loader.h" 20#include "chrome/browser/extensions/declarative_user_script_master.h" 21#include "chrome/browser/extensions/error_console/error_console.h" 22#include "chrome/browser/extensions/extension_error_reporter.h" 23#include "chrome/browser/extensions/extension_management.h" 24#include "chrome/browser/extensions/extension_service.h" 25#include "chrome/browser/extensions/extension_system_factory.h" 26#include "chrome/browser/extensions/extension_util.h" 27#include "chrome/browser/extensions/extension_warning_badge_service.h" 28#include "chrome/browser/extensions/install_verifier.h" 29#include "chrome/browser/extensions/navigation_observer.h" 30#include "chrome/browser/extensions/shared_module_service.h" 31#include "chrome/browser/extensions/shared_user_script_master.h" 32#include "chrome/browser/extensions/state_store_notification_observer.h" 33#include "chrome/browser/extensions/unpacked_installer.h" 34#include "chrome/browser/profiles/profile.h" 35#include "chrome/browser/profiles/profile_manager.h" 36#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 37#include "chrome/common/chrome_switches.h" 38#include "chrome/common/chrome_version_info.h" 39#include "chrome/common/extensions/extension_constants.h" 40#include "chrome/common/extensions/extension_file_util.h" 41#include "chrome/common/extensions/features/feature_channel.h" 42#include "chrome/common/extensions/manifest_url_handler.h" 43#include "content/public/browser/browser_thread.h" 44#include "content/public/browser/url_data_source.h" 45#include "extensions/browser/content_verifier.h" 46#include "extensions/browser/content_verifier_delegate.h" 47#include "extensions/browser/event_router.h" 48#include "extensions/browser/extension_pref_store.h" 49#include "extensions/browser/extension_pref_value_map.h" 50#include "extensions/browser/extension_pref_value_map_factory.h" 51#include "extensions/browser/extension_prefs.h" 52#include "extensions/browser/extension_registry.h" 53#include "extensions/browser/info_map.h" 54#include "extensions/browser/lazy_background_task_queue.h" 55#include "extensions/browser/management_policy.h" 56#include "extensions/browser/process_manager.h" 57#include "extensions/browser/quota_service.h" 58#include "extensions/browser/runtime_data.h" 59#include "extensions/browser/state_store.h" 60#include "extensions/browser/warning_service.h" 61#include "extensions/browser/warning_set.h" 62#include "extensions/common/constants.h" 63#include "extensions/common/extension.h" 64#include "extensions/common/extension_urls.h" 65#include "extensions/common/manifest.h" 66#include "net/base/escape.h" 67 68#if defined(ENABLE_NOTIFICATIONS) 69#include "chrome/browser/notifications/desktop_notification_service.h" 70#include "chrome/browser/notifications/desktop_notification_service_factory.h" 71#include "ui/message_center/notifier_settings.h" 72#endif 73 74#if defined(OS_CHROMEOS) 75#include "chrome/browser/app_mode/app_mode_utils.h" 76#include "chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.h" 77#include "chrome/browser/chromeos/policy/device_local_account.h" 78#include "chrome/browser/extensions/extension_assets_manager_chromeos.h" 79#include "chromeos/chromeos_switches.h" 80#include "chromeos/login/login_state.h" 81#include "components/user_manager/user.h" 82#include "components/user_manager/user_manager.h" 83#endif 84 85using content::BrowserThread; 86 87namespace { 88 89const char kContentVerificationExperimentName[] = 90 "ExtensionContentVerification"; 91 92} // namespace 93 94namespace extensions { 95 96// 97// ExtensionSystemImpl::Shared 98// 99 100ExtensionSystemImpl::Shared::Shared(Profile* profile) 101 : profile_(profile) { 102} 103 104ExtensionSystemImpl::Shared::~Shared() { 105} 106 107void ExtensionSystemImpl::Shared::InitPrefs() { 108 lazy_background_task_queue_.reset(new LazyBackgroundTaskQueue(profile_)); 109 event_router_.reset(new EventRouter(profile_, ExtensionPrefs::Get(profile_))); 110 // Two state stores. The latter, which contains declarative rules, must be 111 // loaded immediately so that the rules are ready before we issue network 112 // requests. 113 state_store_.reset(new StateStore( 114 profile_, 115 profile_->GetPath().AppendASCII(extensions::kStateStoreName), 116 true)); 117 state_store_notification_observer_.reset( 118 new StateStoreNotificationObserver(state_store_.get())); 119 120 rules_store_.reset(new StateStore( 121 profile_, 122 profile_->GetPath().AppendASCII(extensions::kRulesStoreName), 123 false)); 124 125 blacklist_.reset(new Blacklist(ExtensionPrefs::Get(profile_))); 126 127#if defined(OS_CHROMEOS) 128 const user_manager::User* user = 129 user_manager::UserManager::Get()->GetActiveUser(); 130 policy::DeviceLocalAccount::Type device_local_account_type; 131 if (user && policy::IsDeviceLocalAccountUser(user->email(), 132 &device_local_account_type)) { 133 device_local_account_management_policy_provider_.reset( 134 new chromeos::DeviceLocalAccountManagementPolicyProvider( 135 device_local_account_type)); 136 } 137#endif // defined(OS_CHROMEOS) 138} 139 140void ExtensionSystemImpl::Shared::RegisterManagementPolicyProviders() { 141 management_policy_->RegisterProvider( 142 ExtensionManagementFactory::GetForBrowserContext(profile_) 143 ->GetProvider()); 144 145#if defined(OS_CHROMEOS) 146 if (device_local_account_management_policy_provider_) { 147 management_policy_->RegisterProvider( 148 device_local_account_management_policy_provider_.get()); 149 } 150#endif // defined(OS_CHROMEOS) 151 152 management_policy_->RegisterProvider(install_verifier_.get()); 153} 154 155namespace { 156 157class ContentVerifierDelegateImpl : public ContentVerifierDelegate { 158 public: 159 explicit ContentVerifierDelegateImpl(ExtensionService* service) 160 : service_(service->AsWeakPtr()), default_mode_(GetDefaultMode()) {} 161 162 virtual ~ContentVerifierDelegateImpl() {} 163 164 virtual Mode ShouldBeVerified(const Extension& extension) OVERRIDE { 165#if defined(OS_CHROMEOS) 166 if (ExtensionAssetsManagerChromeOS::IsSharedInstall(&extension)) 167 return ContentVerifierDelegate::ENFORCE_STRICT; 168#endif 169 170 if (!extension.is_extension() && !extension.is_legacy_packaged_app()) 171 return ContentVerifierDelegate::NONE; 172 if (!Manifest::IsAutoUpdateableLocation(extension.location())) 173 return ContentVerifierDelegate::NONE; 174 175 if (!ManifestURL::UpdatesFromGallery(&extension)) { 176 // It's possible that the webstore update url was overridden for testing 177 // so also consider extensions with the default (production) update url 178 // to be from the store as well. 179 GURL default_webstore_url = extension_urls::GetDefaultWebstoreUpdateUrl(); 180 if (ManifestURL::GetUpdateURL(&extension) != default_webstore_url) 181 return ContentVerifierDelegate::NONE; 182 } 183 184 return default_mode_; 185 } 186 187 virtual const ContentVerifierKey& PublicKey() OVERRIDE { 188 static ContentVerifierKey key( 189 extension_misc::kWebstoreSignaturesPublicKey, 190 extension_misc::kWebstoreSignaturesPublicKeySize); 191 return key; 192 } 193 194 virtual GURL GetSignatureFetchUrl(const std::string& extension_id, 195 const base::Version& version) OVERRIDE { 196 // TODO(asargent) Factor out common code from the extension updater's 197 // ManifestFetchData class that can be shared for use here. 198 std::vector<std::string> parts; 199 parts.push_back("uc"); 200 parts.push_back("installsource=signature"); 201 parts.push_back("id=" + extension_id); 202 parts.push_back("v=" + version.GetString()); 203 std::string x_value = 204 net::EscapeQueryParamValue(JoinString(parts, "&"), true); 205 std::string query = "response=redirect&x=" + x_value; 206 207 GURL base_url = extension_urls::GetWebstoreUpdateUrl(); 208 GURL::Replacements replacements; 209 replacements.SetQuery(query.c_str(), url::Component(0, query.length())); 210 return base_url.ReplaceComponents(replacements); 211 } 212 213 virtual std::set<base::FilePath> GetBrowserImagePaths( 214 const extensions::Extension* extension) OVERRIDE { 215 return extension_file_util::GetBrowserImagePaths(extension); 216 } 217 218 virtual void VerifyFailed(const std::string& extension_id, 219 ContentVerifyJob::FailureReason reason) OVERRIDE { 220 if (!service_) 221 return; 222 ExtensionRegistry* registry = ExtensionRegistry::Get(service_->profile()); 223 const Extension* extension = 224 registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED); 225 if (!extension) 226 return; 227 Mode mode = ShouldBeVerified(*extension); 228 if (mode >= ContentVerifierDelegate::ENFORCE) { 229 service_->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED); 230 ExtensionPrefs::Get(service_->profile()) 231 ->IncrementCorruptedDisableCount(); 232 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionBecameDisabled", true); 233 UMA_HISTOGRAM_ENUMERATION("Extensions.CorruptExtensionDisabledReason", 234 reason, ContentVerifyJob::FAILURE_REASON_MAX); 235 } else if (!ContainsKey(would_be_disabled_ids_, extension_id)) { 236 UMA_HISTOGRAM_BOOLEAN("Extensions.CorruptExtensionWouldBeDisabled", true); 237 would_be_disabled_ids_.insert(extension_id); 238 } 239 } 240 241 static Mode GetDefaultMode() { 242 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 243 244 Mode experiment_value = NONE; 245 const std::string group = base::FieldTrialList::FindFullName( 246 kContentVerificationExperimentName); 247 if (group == "EnforceStrict") 248 experiment_value = ContentVerifierDelegate::ENFORCE_STRICT; 249 else if (group == "Enforce") 250 experiment_value = ContentVerifierDelegate::ENFORCE; 251 else if (group == "Bootstrap") 252 experiment_value = ContentVerifierDelegate::BOOTSTRAP; 253 254 // The field trial value that normally comes from the server can be 255 // overridden on the command line, which we don't want to allow since 256 // malware can set chrome command line flags. There isn't currently a way 257 // to find out what the server-provided value is in this case, so we 258 // conservatively default to the strictest mode if we detect our experiment 259 // name being overridden. 260 if (command_line->HasSwitch(switches::kForceFieldTrials)) { 261 std::string forced_trials = 262 command_line->GetSwitchValueASCII(switches::kForceFieldTrials); 263 if (forced_trials.find(kContentVerificationExperimentName) != 264 std::string::npos) 265 experiment_value = ContentVerifierDelegate::ENFORCE_STRICT; 266 } 267 268 Mode cmdline_value = NONE; 269 if (command_line->HasSwitch(switches::kExtensionContentVerification)) { 270 std::string switch_value = command_line->GetSwitchValueASCII( 271 switches::kExtensionContentVerification); 272 if (switch_value == switches::kExtensionContentVerificationBootstrap) 273 cmdline_value = ContentVerifierDelegate::BOOTSTRAP; 274 else if (switch_value == switches::kExtensionContentVerificationEnforce) 275 cmdline_value = ContentVerifierDelegate::ENFORCE; 276 else if (switch_value == 277 switches::kExtensionContentVerificationEnforceStrict) 278 cmdline_value = ContentVerifierDelegate::ENFORCE_STRICT; 279 else 280 // If no value was provided (or the wrong one), just default to enforce. 281 cmdline_value = ContentVerifierDelegate::ENFORCE; 282 } 283 284 // We don't want to allow the command-line flags to eg disable enforcement 285 // if the experiment group says it should be on, or malware may just modify 286 // the command line flags. So return the more restrictive of the 2 values. 287 return std::max(experiment_value, cmdline_value); 288 } 289 290 private: 291 base::WeakPtr<ExtensionService> service_; 292 ContentVerifierDelegate::Mode default_mode_; 293 294 // For reporting metrics in BOOTSTRAP mode, when an extension would be 295 // disabled if content verification was in ENFORCE mode. 296 std::set<std::string> would_be_disabled_ids_; 297 298 DISALLOW_COPY_AND_ASSIGN(ContentVerifierDelegateImpl); 299}; 300 301} // namespace 302 303void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { 304 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 305 306 navigation_observer_.reset(new NavigationObserver(profile_)); 307 308 bool allow_noisy_errors = !command_line->HasSwitch(switches::kNoErrorDialogs); 309 ExtensionErrorReporter::Init(allow_noisy_errors); 310 311 shared_user_script_master_.reset(new SharedUserScriptMaster(profile_)); 312 313 // ExtensionService depends on RuntimeData. 314 runtime_data_.reset(new RuntimeData(ExtensionRegistry::Get(profile_))); 315 316 bool autoupdate_enabled = !profile_->IsGuestSession(); 317#if defined(OS_CHROMEOS) 318 if (!extensions_enabled) 319 autoupdate_enabled = false; 320#endif 321 extension_service_.reset(new ExtensionService( 322 profile_, 323 CommandLine::ForCurrentProcess(), 324 profile_->GetPath().AppendASCII(extensions::kInstallDirectoryName), 325 ExtensionPrefs::Get(profile_), 326 blacklist_.get(), 327 autoupdate_enabled, 328 extensions_enabled, 329 &ready_)); 330 331 // These services must be registered before the ExtensionService tries to 332 // load any extensions. 333 { 334 install_verifier_.reset( 335 new InstallVerifier(ExtensionPrefs::Get(profile_), profile_)); 336 install_verifier_->Init(); 337 content_verifier_ = new ContentVerifier( 338 profile_, new ContentVerifierDelegateImpl(extension_service_.get())); 339 ContentVerifierDelegate::Mode mode = 340 ContentVerifierDelegateImpl::GetDefaultMode(); 341#if defined(OS_CHROMEOS) 342 mode = std::max(mode, ContentVerifierDelegate::BOOTSTRAP); 343#endif 344 if (mode >= ContentVerifierDelegate::BOOTSTRAP) 345 content_verifier_->Start(); 346 info_map()->SetContentVerifier(content_verifier_.get()); 347 348 management_policy_.reset(new ManagementPolicy); 349 RegisterManagementPolicyProviders(); 350 } 351 352 bool skip_session_extensions = false; 353#if defined(OS_CHROMEOS) 354 // Skip loading session extensions if we are not in a user session. 355 skip_session_extensions = !chromeos::LoginState::Get()->IsUserLoggedIn(); 356 if (chrome::IsRunningInForcedAppMode()) { 357 extension_service_->component_loader()-> 358 AddDefaultComponentExtensionsForKioskMode(skip_session_extensions); 359 } else { 360 extension_service_->component_loader()->AddDefaultComponentExtensions( 361 skip_session_extensions); 362 } 363#else 364 extension_service_->component_loader()->AddDefaultComponentExtensions( 365 skip_session_extensions); 366#endif 367 if (command_line->HasSwitch(switches::kLoadComponentExtension)) { 368 CommandLine::StringType path_list = command_line->GetSwitchValueNative( 369 switches::kLoadComponentExtension); 370 base::StringTokenizerT<CommandLine::StringType, 371 CommandLine::StringType::const_iterator> t(path_list, 372 FILE_PATH_LITERAL(",")); 373 while (t.GetNext()) { 374 // Load the component extension manifest synchronously. 375 // Blocking the UI thread is acceptable here since 376 // this flag designated for developers. 377 base::ThreadRestrictions::ScopedAllowIO allow_io; 378 extension_service_->component_loader()->AddOrReplace( 379 base::FilePath(t.token())); 380 } 381 } 382 extension_service_->Init(); 383 384 // Make the chrome://extension-icon/ resource available. 385 content::URLDataSource::Add(profile_, new ExtensionIconSource(profile_)); 386 387 warning_service_.reset(new WarningService(profile_)); 388 extension_warning_badge_service_.reset( 389 new ExtensionWarningBadgeService(profile_)); 390 warning_service_->AddObserver( 391 extension_warning_badge_service_.get()); 392 error_console_.reset(new ErrorConsole(profile_)); 393 quota_service_.reset(new QuotaService); 394 395 if (extensions_enabled) { 396 // Load any extensions specified with --load-extension. 397 // TODO(yoz): Seems like this should move into ExtensionService::Init. 398 // But maybe it's no longer important. 399 if (command_line->HasSwitch(switches::kLoadExtension)) { 400 CommandLine::StringType path_list = command_line->GetSwitchValueNative( 401 switches::kLoadExtension); 402 base::StringTokenizerT<CommandLine::StringType, 403 CommandLine::StringType::const_iterator> t(path_list, 404 FILE_PATH_LITERAL(",")); 405 while (t.GetNext()) { 406 std::string extension_id; 407 UnpackedInstaller::Create(extension_service_.get())-> 408 LoadFromCommandLine(base::FilePath(t.token()), &extension_id); 409 } 410 } 411 } 412} 413 414void ExtensionSystemImpl::Shared::Shutdown() { 415 if (warning_service_) { 416 warning_service_->RemoveObserver( 417 extension_warning_badge_service_.get()); 418 } 419 if (content_verifier_.get()) 420 content_verifier_->Shutdown(); 421 if (extension_service_) 422 extension_service_->Shutdown(); 423} 424 425StateStore* ExtensionSystemImpl::Shared::state_store() { 426 return state_store_.get(); 427} 428 429StateStore* ExtensionSystemImpl::Shared::rules_store() { 430 return rules_store_.get(); 431} 432 433ExtensionService* ExtensionSystemImpl::Shared::extension_service() { 434 return extension_service_.get(); 435} 436 437RuntimeData* ExtensionSystemImpl::Shared::runtime_data() { 438 return runtime_data_.get(); 439} 440 441ManagementPolicy* ExtensionSystemImpl::Shared::management_policy() { 442 return management_policy_.get(); 443} 444 445SharedUserScriptMaster* 446ExtensionSystemImpl::Shared::shared_user_script_master() { 447 return shared_user_script_master_.get(); 448} 449 450InfoMap* ExtensionSystemImpl::Shared::info_map() { 451 if (!extension_info_map_.get()) 452 extension_info_map_ = new InfoMap(); 453 return extension_info_map_.get(); 454} 455 456LazyBackgroundTaskQueue* 457 ExtensionSystemImpl::Shared::lazy_background_task_queue() { 458 return lazy_background_task_queue_.get(); 459} 460 461EventRouter* ExtensionSystemImpl::Shared::event_router() { 462 return event_router_.get(); 463} 464 465WarningService* ExtensionSystemImpl::Shared::warning_service() { 466 return warning_service_.get(); 467} 468 469Blacklist* ExtensionSystemImpl::Shared::blacklist() { 470 return blacklist_.get(); 471} 472 473ErrorConsole* ExtensionSystemImpl::Shared::error_console() { 474 return error_console_.get(); 475} 476 477InstallVerifier* ExtensionSystemImpl::Shared::install_verifier() { 478 return install_verifier_.get(); 479} 480 481QuotaService* ExtensionSystemImpl::Shared::quota_service() { 482 return quota_service_.get(); 483} 484 485ContentVerifier* ExtensionSystemImpl::Shared::content_verifier() { 486 return content_verifier_.get(); 487} 488 489DeclarativeUserScriptMaster* 490ExtensionSystemImpl::Shared::GetDeclarativeUserScriptMasterByExtension( 491 const ExtensionId& extension_id) { 492 DCHECK(ready().is_signaled()); 493 DeclarativeUserScriptMaster* master = NULL; 494 for (ScopedVector<DeclarativeUserScriptMaster>::iterator it = 495 declarative_user_script_masters_.begin(); 496 it != declarative_user_script_masters_.end(); 497 ++it) { 498 if ((*it)->extension_id() == extension_id) { 499 master = *it; 500 break; 501 } 502 } 503 if (!master) { 504 master = new DeclarativeUserScriptMaster(profile_, extension_id); 505 declarative_user_script_masters_.push_back(master); 506 } 507 return master; 508} 509 510// 511// ExtensionSystemImpl 512// 513 514ExtensionSystemImpl::ExtensionSystemImpl(Profile* profile) 515 : profile_(profile) { 516 shared_ = ExtensionSystemSharedFactory::GetForBrowserContext(profile); 517 518 if (profile->IsOffTheRecord()) { 519 process_manager_.reset(ProcessManager::Create(profile)); 520 } else { 521 shared_->InitPrefs(); 522 } 523} 524 525ExtensionSystemImpl::~ExtensionSystemImpl() { 526} 527 528void ExtensionSystemImpl::Shutdown() { 529 process_manager_.reset(); 530} 531 532void ExtensionSystemImpl::InitForRegularProfile(bool extensions_enabled) { 533 DCHECK(!profile_->IsOffTheRecord()); 534 if (shared_user_script_master() || extension_service()) 535 return; // Already initialized. 536 537 // The InfoMap needs to be created before the ProcessManager. 538 shared_->info_map(); 539 540 process_manager_.reset(ProcessManager::Create(profile_)); 541 542 shared_->Init(extensions_enabled); 543} 544 545ExtensionService* ExtensionSystemImpl::extension_service() { 546 return shared_->extension_service(); 547} 548 549RuntimeData* ExtensionSystemImpl::runtime_data() { 550 return shared_->runtime_data(); 551} 552 553ManagementPolicy* ExtensionSystemImpl::management_policy() { 554 return shared_->management_policy(); 555} 556 557SharedUserScriptMaster* ExtensionSystemImpl::shared_user_script_master() { 558 return shared_->shared_user_script_master(); 559} 560 561ProcessManager* ExtensionSystemImpl::process_manager() { 562 return process_manager_.get(); 563} 564 565StateStore* ExtensionSystemImpl::state_store() { 566 return shared_->state_store(); 567} 568 569StateStore* ExtensionSystemImpl::rules_store() { 570 return shared_->rules_store(); 571} 572 573InfoMap* ExtensionSystemImpl::info_map() { return shared_->info_map(); } 574 575LazyBackgroundTaskQueue* ExtensionSystemImpl::lazy_background_task_queue() { 576 return shared_->lazy_background_task_queue(); 577} 578 579EventRouter* ExtensionSystemImpl::event_router() { 580 return shared_->event_router(); 581} 582 583WarningService* ExtensionSystemImpl::warning_service() { 584 return shared_->warning_service(); 585} 586 587Blacklist* ExtensionSystemImpl::blacklist() { 588 return shared_->blacklist(); 589} 590 591const OneShotEvent& ExtensionSystemImpl::ready() const { 592 return shared_->ready(); 593} 594 595ErrorConsole* ExtensionSystemImpl::error_console() { 596 return shared_->error_console(); 597} 598 599InstallVerifier* ExtensionSystemImpl::install_verifier() { 600 return shared_->install_verifier(); 601} 602 603QuotaService* ExtensionSystemImpl::quota_service() { 604 return shared_->quota_service(); 605} 606 607ContentVerifier* ExtensionSystemImpl::content_verifier() { 608 return shared_->content_verifier(); 609} 610 611scoped_ptr<ExtensionSet> ExtensionSystemImpl::GetDependentExtensions( 612 const Extension* extension) { 613 return extension_service()->shared_module_service()->GetDependentExtensions( 614 extension); 615} 616 617DeclarativeUserScriptMaster* 618ExtensionSystemImpl::GetDeclarativeUserScriptMasterByExtension( 619 const ExtensionId& extension_id) { 620 return shared_->GetDeclarativeUserScriptMasterByExtension(extension_id); 621} 622 623void ExtensionSystemImpl::RegisterExtensionWithRequestContexts( 624 const Extension* extension) { 625 base::Time install_time; 626 if (extension->location() != Manifest::COMPONENT) { 627 install_time = ExtensionPrefs::Get(profile_)-> 628 GetInstallTime(extension->id()); 629 } 630 bool incognito_enabled = util::IsIncognitoEnabled(extension->id(), profile_); 631 632 bool notifications_disabled = false; 633#if defined(ENABLE_NOTIFICATIONS) 634 message_center::NotifierId notifier_id( 635 message_center::NotifierId::APPLICATION, 636 extension->id()); 637 638 DesktopNotificationService* notification_service = 639 DesktopNotificationServiceFactory::GetForProfile(profile_); 640 notifications_disabled = 641 !notification_service->IsNotifierEnabled(notifier_id); 642#endif 643 644 BrowserThread::PostTask( 645 BrowserThread::IO, FROM_HERE, 646 base::Bind(&InfoMap::AddExtension, info_map(), 647 make_scoped_refptr(extension), install_time, 648 incognito_enabled, notifications_disabled)); 649} 650 651void ExtensionSystemImpl::UnregisterExtensionWithRequestContexts( 652 const std::string& extension_id, 653 const UnloadedExtensionInfo::Reason reason) { 654 BrowserThread::PostTask( 655 BrowserThread::IO, 656 FROM_HERE, 657 base::Bind(&InfoMap::RemoveExtension, info_map(), extension_id, reason)); 658} 659 660} // namespace extensions 661