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