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