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