extension_service.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 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 <set>
9
10#include "base/basictypes.h"
11#include "base/command_line.h"
12#include "base/file_util.h"
13#include "base/metrics/histogram.h"
14#include "base/stl_util-inl.h"
15#include "base/string16.h"
16#include "base/string_number_conversions.h"
17#include "base/string_util.h"
18#include "base/stringprintf.h"
19#include "base/threading/thread_restrictions.h"
20#include "base/time.h"
21#include "base/utf_string_conversions.h"
22#include "base/values.h"
23#include "base/version.h"
24#include "chrome/browser/browser_process.h"
25#include "chrome/browser/debugger/devtools_manager.h"
26#include "chrome/browser/extensions/crx_installer.h"
27#include "chrome/browser/extensions/default_apps.h"
28#include "chrome/browser/extensions/extension_accessibility_api.h"
29#include "chrome/browser/extensions/extension_bookmarks_module.h"
30#include "chrome/browser/extensions/extension_browser_event_router.h"
31#include "chrome/browser/extensions/extension_cookies_api.h"
32#include "chrome/browser/extensions/extension_data_deleter.h"
33#include "chrome/browser/extensions/extension_error_reporter.h"
34#include "chrome/browser/extensions/extension_history_api.h"
35#include "chrome/browser/extensions/extension_host.h"
36#include "chrome/browser/extensions/extension_management_api.h"
37#include "chrome/browser/extensions/extension_process_manager.h"
38#include "chrome/browser/extensions/extension_processes_api.h"
39#include "chrome/browser/extensions/extension_special_storage_policy.h"
40#include "chrome/browser/extensions/extension_updater.h"
41#include "chrome/browser/extensions/extension_web_ui.h"
42#include "chrome/browser/extensions/extension_webnavigation_api.h"
43#include "chrome/browser/extensions/external_extension_provider_impl.h"
44#include "chrome/browser/extensions/external_extension_provider_interface.h"
45#include "chrome/browser/net/chrome_url_request_context.h"
46#include "chrome/browser/prefs/pref_service.h"
47#include "chrome/browser/profiles/profile.h"
48#include "chrome/browser/search_engines/template_url_model.h"
49#include "chrome/browser/themes/browser_theme_provider.h"
50#include "chrome/browser/ui/webui/shown_sections_handler.h"
51#include "chrome/common/child_process_logging.h"
52#include "chrome/common/chrome_switches.h"
53#include "chrome/common/extensions/extension.h"
54#include "chrome/common/extensions/extension_constants.h"
55#include "chrome/common/extensions/extension_error_utils.h"
56#include "chrome/common/extensions/extension_file_util.h"
57#include "chrome/common/extensions/extension_l10n_util.h"
58#include "chrome/common/extensions/extension_resource.h"
59#include "chrome/common/json_value_serializer.h"
60#include "chrome/common/notification_service.h"
61#include "chrome/common/notification_type.h"
62#include "chrome/common/pref_names.h"
63#include "chrome/common/url_constants.h"
64#include "content/browser/browser_thread.h"
65#include "googleurl/src/gurl.h"
66#include "net/base/registry_controlled_domain.h"
67#include "webkit/database/database_tracker.h"
68#include "webkit/database/database_util.h"
69
70using base::Time;
71
72namespace errors = extension_manifest_errors;
73
74namespace {
75
76#if defined(OS_LINUX)
77static const int kOmniboxIconPaddingLeft = 2;
78static const int kOmniboxIconPaddingRight = 2;
79#elif defined(OS_MACOSX)
80static const int kOmniboxIconPaddingLeft = 0;
81static const int kOmniboxIconPaddingRight = 2;
82#else
83static const int kOmniboxIconPaddingLeft = 0;
84static const int kOmniboxIconPaddingRight = 0;
85#endif
86
87// The following enumeration is used in histograms matching
88// Extensions.ManifestReload* .  Values may be added, as long
89// as existing values are not changed.
90enum ManifestReloadReason {
91  NOT_NEEDED = 0,  // Reload not needed.
92  UNPACKED_DIR,  // Unpacked directory
93  NEEDS_RELOCALIZATION,  // The local has changed since we read this extension.
94  NUM_MANIFEST_RELOAD_REASONS
95};
96
97ManifestReloadReason ShouldReloadExtensionManifest(const ExtensionInfo& info) {
98  // Always reload manifests of unpacked extensions, because they can change
99  // on disk independent of the manifest in our prefs.
100  if (info.extension_location == Extension::LOAD)
101    return UNPACKED_DIR;
102
103  // Reload the manifest if it needs to be relocalized.
104  if (extension_l10n_util::ShouldRelocalizeManifest(info))
105    return NEEDS_RELOCALIZATION;
106
107  return NOT_NEEDED;
108}
109
110}  // namespace
111
112
113ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData()
114    : background_page_ready(false),
115      being_upgraded(false) {
116}
117
118ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() {
119}
120
121// ExtensionService.
122
123const char* ExtensionService::kInstallDirectoryName = "Extensions";
124const char* ExtensionService::kCurrentVersionFileName = "Current Version";
125
126// Implements IO for the ExtensionService.
127
128class ExtensionServiceBackend
129    : public base::RefCountedThreadSafe<ExtensionServiceBackend> {
130 public:
131  // |install_directory| is a path where to look for extensions to load.
132  explicit ExtensionServiceBackend(const FilePath& install_directory);
133
134  // Loads a single extension from |path| where |path| is the top directory of
135  // a specific extension where its manifest file lives.
136  // Errors are reported through ExtensionErrorReporter. On success,
137  // AddExtension() is called.
138  // TODO(erikkay): It might be useful to be able to load a packed extension
139  // (presumably into memory) without installing it.
140  void LoadSingleExtension(const FilePath &path,
141                           scoped_refptr<ExtensionService> frontend);
142
143 private:
144  friend class base::RefCountedThreadSafe<ExtensionServiceBackend>;
145
146  virtual ~ExtensionServiceBackend();
147
148  // Finish installing the extension in |crx_path| after it has been unpacked to
149  // |unpacked_path|.  If |expected_id| is not empty, it's verified against the
150  // extension's manifest before installation. If |silent| is true, there will
151  // be no install confirmation dialog. |from_gallery| indicates whether the
152  // crx was installed from our gallery, which results in different UI.
153  //
154  // Note: We take ownership of |extension|.
155  void OnExtensionUnpacked(const FilePath& crx_path,
156                           const FilePath& unpacked_path,
157                           const Extension* extension,
158                           const std::string expected_id);
159
160  // Notify the frontend that there was an error loading an extension.
161  void ReportExtensionLoadError(const FilePath& extension_path,
162                                const std::string& error);
163
164  // This is a naked pointer which is set by each entry point.
165  // The entry point is responsible for ensuring lifetime.
166  ExtensionService* frontend_;
167
168  // The top-level extensions directory being installed to.
169  FilePath install_directory_;
170
171  // Whether errors result in noisy alerts.
172  bool alert_on_error_;
173
174  DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend);
175};
176
177ExtensionServiceBackend::ExtensionServiceBackend(
178    const FilePath& install_directory)
179        : frontend_(NULL),
180          install_directory_(install_directory),
181          alert_on_error_(false) {
182}
183
184ExtensionServiceBackend::~ExtensionServiceBackend() {
185}
186
187void ExtensionServiceBackend::LoadSingleExtension(
188    const FilePath& path_in, scoped_refptr<ExtensionService> frontend) {
189  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
190
191  frontend_ = frontend;
192
193  // Explicit UI loads are always noisy.
194  alert_on_error_ = true;
195
196  FilePath extension_path = path_in;
197  file_util::AbsolutePath(&extension_path);
198
199  std::string error;
200  scoped_refptr<const Extension> extension(extension_file_util::LoadExtension(
201      extension_path,
202      Extension::LOAD,
203      false,  // Don't require id
204      Extension::ShouldDoStrictErrorChecking(Extension::LOAD),
205      &error));
206
207  if (!extension) {
208    ReportExtensionLoadError(extension_path, error);
209    return;
210  }
211
212  // Report this as an installed extension so that it gets remembered in the
213  // prefs.
214  BrowserThread::PostTask(
215      BrowserThread::UI, FROM_HERE,
216      NewRunnableMethod(frontend_,
217                        &ExtensionService::OnExtensionInstalled,
218                        extension));
219}
220
221void ExtensionServiceBackend::ReportExtensionLoadError(
222    const FilePath& extension_path, const std::string &error) {
223  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
224  BrowserThread::PostTask(
225      BrowserThread::UI, FROM_HERE,
226      NewRunnableMethod(
227          frontend_,
228          &ExtensionService::ReportExtensionLoadError, extension_path,
229          error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_));
230}
231
232void ExtensionService::CheckExternalUninstall(const std::string& id) {
233  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
234
235  // Check if the providers know about this extension.
236  ProviderCollection::const_iterator i;
237  for (i = external_extension_providers_.begin();
238       i != external_extension_providers_.end(); ++i) {
239    DCHECK(i->get()->IsReady());
240    if (i->get()->HasExtension(id))
241      return;  // Yup, known extension, don't uninstall.
242  }
243
244  // This is an external extension that we don't have registered.  Uninstall.
245  UninstallExtension(id, true);
246}
247
248void ExtensionService::ClearProvidersForTesting() {
249  external_extension_providers_.clear();
250}
251
252void ExtensionService::AddProviderForTesting(
253    ExternalExtensionProviderInterface* test_provider) {
254  CHECK(test_provider);
255  external_extension_providers_.push_back(
256      linked_ptr<ExternalExtensionProviderInterface>(test_provider));
257}
258
259void ExtensionService::OnExternalExtensionUpdateUrlFound(
260    const std::string& id,
261    const GURL& update_url,
262    Extension::Location location) {
263  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264  CHECK(Extension::IdIsValid(id));
265
266  if (GetExtensionById(id, true)) {
267    // Already installed.  Do not change the update URL that the extension set.
268    return;
269  }
270  AddPendingExtensionFromExternalUpdateUrl(id, update_url, location);
271  external_extension_url_added_ |= true;
272}
273
274bool ExtensionService::IsDownloadFromGallery(const GURL& download_url,
275                                             const GURL& referrer_url) {
276  // Special-case the themes mini-gallery.
277  // TODO(erikkay) When that gallery goes away, remove this code.
278  if (IsDownloadFromMiniGallery(download_url) &&
279      StartsWithASCII(referrer_url.spec(),
280                      extension_urls::kMiniGalleryBrowsePrefix, false)) {
281    return true;
282  }
283
284  const Extension* download_extension = GetExtensionByWebExtent(download_url);
285  const Extension* referrer_extension = GetExtensionByWebExtent(referrer_url);
286  const Extension* webstore_app = GetWebStoreApp();
287
288  bool referrer_valid = (referrer_extension == webstore_app);
289  bool download_valid = (download_extension == webstore_app);
290
291  // If the command-line gallery URL is set, then be a bit more lenient.
292  GURL store_url =
293      GURL(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
294           switches::kAppsGalleryURL));
295  if (!store_url.is_empty()) {
296    std::string store_tld =
297        net::RegistryControlledDomainService::GetDomainAndRegistry(store_url);
298    if (!referrer_valid) {
299      std::string referrer_tld =
300          net::RegistryControlledDomainService::GetDomainAndRegistry(
301              referrer_url);
302      // The referrer gets stripped when transitioning from https to http,
303      // or when hitting an unknown test cert and that commonly happens in
304      // testing environments.  Given this, we allow an empty referrer when
305      // the command-line flag is set.
306      // Otherwise, the TLD must match the TLD of the command-line url.
307      referrer_valid = referrer_url.is_empty() || (referrer_tld == store_tld);
308    }
309
310    if (!download_valid) {
311      std::string download_tld =
312          net::RegistryControlledDomainService::GetDomainAndRegistry(
313              GURL(download_url));
314
315      // Otherwise, the TLD must match the TLD of the command-line url.
316      download_valid = (download_tld == store_tld);
317    }
318  }
319
320  return (referrer_valid && download_valid);
321}
322
323bool ExtensionService::IsDownloadFromMiniGallery(const GURL& download_url) {
324  return StartsWithASCII(download_url.spec(),
325                         extension_urls::kMiniGalleryDownloadPrefix,
326                         false);  // case_sensitive
327}
328
329bool ExtensionService::IsInstalledApp(const GURL& url) {
330  // Check for hosted app.
331  if (GetExtensionByWebExtent(url) != NULL)
332    return true;
333
334  // Check for packaged app.
335  const Extension* extension = GetExtensionByURL(url);
336  return extension != NULL && extension->is_app();
337}
338
339// static
340bool ExtensionService::UninstallExtensionHelper(
341    ExtensionService* extensions_service,
342    const std::string& extension_id) {
343
344  // We can't call UninstallExtension with an invalid extension ID, so check it
345  // first.
346  if (extensions_service->GetExtensionById(extension_id, true) ||
347      extensions_service->GetTerminatedExtension(extension_id)) {
348    extensions_service->UninstallExtension(extension_id, false);
349  } else {
350    LOG(WARNING) << "Attempted uninstallation of non-existent extension with "
351      << "id: " << extension_id;
352    return false;
353  }
354
355  return true;
356}
357
358ExtensionService::ExtensionService(Profile* profile,
359                                   const CommandLine* command_line,
360                                   const FilePath& install_directory,
361                                   ExtensionPrefs* extension_prefs,
362                                   bool autoupdate_enabled)
363    : profile_(profile),
364      extension_prefs_(extension_prefs),
365      install_directory_(install_directory),
366      extensions_enabled_(true),
367      show_extensions_prompts_(true),
368      ready_(false),
369      ALLOW_THIS_IN_INITIALIZER_LIST(toolbar_model_(this)),
370      default_apps_(profile->GetPrefs(),
371                    g_browser_process->GetApplicationLocale()),
372      event_routers_initialized_(false) {
373  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
374
375  // Figure out if extension installation should be enabled.
376  if (command_line->HasSwitch(switches::kDisableExtensions)) {
377    extensions_enabled_ = false;
378  } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) {
379    extensions_enabled_ = false;
380  }
381
382  registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED,
383                 NotificationService::AllSources());
384  pref_change_registrar_.Init(profile->GetPrefs());
385  pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, this);
386  pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, this);
387
388  // Set up the ExtensionUpdater
389  if (autoupdate_enabled) {
390    int update_frequency = kDefaultUpdateFrequencySeconds;
391    if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) {
392      base::StringToInt(command_line->GetSwitchValueASCII(
393          switches::kExtensionsUpdateFrequency),
394          &update_frequency);
395    }
396    updater_ = new ExtensionUpdater(this,
397                                    profile->GetPrefs(),
398                                    update_frequency);
399  }
400
401  backend_ = new ExtensionServiceBackend(install_directory_);
402
403  ExternalExtensionProviderImpl::CreateExternalProviders(
404      this, profile_, &external_extension_providers_);
405
406  // Use monochrome icons for Omnibox icons.
407  omnibox_popup_icon_manager_.set_monochrome(true);
408  omnibox_icon_manager_.set_monochrome(true);
409  omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft,
410                                                0, kOmniboxIconPaddingRight));
411}
412
413const ExtensionList* ExtensionService::extensions() const {
414  return &extensions_;
415}
416
417const ExtensionList* ExtensionService::disabled_extensions() const {
418  return &disabled_extensions_;
419}
420
421const ExtensionList* ExtensionService::terminated_extensions() const {
422  return &terminated_extensions_;
423}
424
425const PendingExtensionMap& ExtensionService::pending_extensions() const {
426  return pending_extensions_;
427}
428
429bool ExtensionService::HasInstalledExtensions() {
430  return !(extensions_.empty() && disabled_extensions_.empty());
431}
432
433ExtensionService::~ExtensionService() {
434  DCHECK(!profile_);  // Profile should have told us it's going away.
435  UnloadAllExtensions();
436
437  ProviderCollection::const_iterator i;
438  for (i = external_extension_providers_.begin();
439       i != external_extension_providers_.end(); ++i) {
440    ExternalExtensionProviderInterface* provider = i->get();
441    provider->ServiceShutdown();
442  }
443}
444
445void ExtensionService::InitEventRouters() {
446  if (event_routers_initialized_)
447    return;
448
449  ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_);
450  ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_);
451  browser_event_router_.reset(new ExtensionBrowserEventRouter(profile_));
452  browser_event_router_->Init();
453  ExtensionBookmarkEventRouter::GetInstance()->Observe(
454      profile_->GetBookmarkModel());
455  ExtensionCookiesEventRouter::GetInstance()->Init();
456  ExtensionManagementEventRouter::GetInstance()->Init();
457  ExtensionProcessesEventRouter::GetInstance()->ObserveProfile(profile_);
458  ExtensionWebNavigationEventRouter::GetInstance()->Init();
459  event_routers_initialized_ = true;
460}
461
462const Extension* ExtensionService::GetExtensionById(const std::string& id,
463                                                     bool include_disabled) {
464  return GetExtensionByIdInternal(id, true, include_disabled);
465}
466
467void ExtensionService::Init() {
468  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
469
470  DCHECK(!ready_);  // Can't redo init.
471  DCHECK_EQ(extensions_.size(), 0u);
472
473  // Hack: we need to ensure the ResourceDispatcherHost is ready before we load
474  // the first extension, because its members listen for loaded notifications.
475  g_browser_process->resource_dispatcher_host();
476
477  LoadAllExtensions();
478
479  // TODO(erikkay) this should probably be deferred to a future point
480  // rather than running immediately at startup.
481  CheckForExternalUpdates();
482
483  // TODO(erikkay) this should probably be deferred as well.
484  GarbageCollectExtensions();
485}
486
487void ExtensionService::UpdateExtension(const std::string& id,
488                                       const FilePath& extension_path,
489                                       const GURL& download_url) {
490  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
491
492  PendingExtensionMap::const_iterator it = pending_extensions_.find(id);
493  bool is_pending_extension = (it != pending_extensions_.end());
494
495  const Extension* extension = GetExtensionByIdInternal(id, true, true);
496  if (!is_pending_extension && !extension) {
497    LOG(WARNING) << "Will not update extension " << id
498                 << " because it is not installed or pending";
499    // Delete extension_path since we're not creating a CrxInstaller
500    // that would do it for us.
501    BrowserThread::PostTask(
502        BrowserThread::FILE, FROM_HERE,
503        NewRunnableFunction(
504            extension_file_util::DeleteFile, extension_path, false));
505    return;
506  }
507
508  // We want a silent install only for non-pending extensions and
509  // pending extensions that have install_silently set.
510  ExtensionInstallUI* client =
511      (!is_pending_extension || it->second.install_silently()) ?
512      NULL : new ExtensionInstallUI(profile_);
513
514  scoped_refptr<CrxInstaller> installer(
515      new CrxInstaller(this,  // frontend
516                       client));
517  installer->set_expected_id(id);
518  if (is_pending_extension)
519    installer->set_install_source(it->second.install_source());
520  else if (extension)
521    installer->set_install_source(extension->location());
522  installer->set_delete_source(true);
523  installer->set_original_url(download_url);
524  installer->InstallCrx(extension_path);
525}
526
527void ExtensionService::AddPendingExtensionFromSync(
528    const std::string& id, const GURL& update_url,
529    PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
530    bool install_silently, bool enable_on_install,
531    bool enable_incognito_on_install) {
532  if (GetExtensionByIdInternal(id, true, true)) {
533    LOG(DFATAL) << "Trying to add pending extension " << id
534                << " which already exists";
535    return;
536  }
537
538  AddPendingExtensionInternal(id, update_url, should_allow_install, true,
539                              install_silently, enable_on_install,
540                              enable_incognito_on_install,
541                              Extension::INTERNAL);
542}
543
544namespace {
545
546bool AlwaysInstall(const Extension& extension) {
547  return true;
548}
549
550}  // namespace
551
552void ExtensionService::AddPendingExtensionFromExternalUpdateUrl(
553    const std::string& id, const GURL& update_url,
554    Extension::Location location) {
555  const bool kIsFromSync = false;
556  const bool kInstallSilently = true;
557  const bool kEnableOnInstall = true;
558  const bool kEnableIncognitoOnInstall = false;
559  if (extension_prefs_->IsExtensionKilled(id))
560    return;
561
562  if (GetExtensionByIdInternal(id, true, true)) {
563    LOG(DFATAL) << "Trying to add extension " << id
564                << " by external update, but it is already installed.";
565    return;
566  }
567
568  AddPendingExtensionInternal(id, update_url, &AlwaysInstall,
569                              kIsFromSync, kInstallSilently,
570                              kEnableOnInstall, kEnableIncognitoOnInstall,
571                              location);
572}
573
574namespace {
575
576bool IsApp(const Extension& extension) {
577  return extension.is_app();
578}
579
580}  // namespace
581
582// TODO(akalin): Change DefaultAppList to DefaultExtensionList and
583// remove the IsApp() check.
584
585void ExtensionService::AddPendingExtensionFromDefaultAppList(
586    const std::string& id) {
587  const bool kIsFromSync = false;
588  const bool kInstallSilently = true;
589  const bool kEnableOnInstall = true;
590  const bool kEnableIncognitoOnInstall = true;
591
592  // This can legitimately happen if the user manually installed one of the
593  // default apps before this code ran.
594  if (GetExtensionByIdInternal(id, true, true))
595    return;
596
597  AddPendingExtensionInternal(id, GURL(), &IsApp,
598                              kIsFromSync, kInstallSilently,
599                              kEnableOnInstall, kEnableIncognitoOnInstall,
600                              Extension::INTERNAL);
601}
602
603void ExtensionService::AddPendingExtensionInternal(
604    const std::string& id, const GURL& update_url,
605    PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
606    bool is_from_sync, bool install_silently,
607    bool enable_on_install, bool enable_incognito_on_install,
608    Extension::Location install_source) {
609  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
610
611  // If a non-sync update is pending, a sync request should not
612  // overwrite it.  This is important for external extensions.
613  // If an external extension download is pending, and the user has
614  // the extension in their sync profile, the install should set the
615  // type to be external.  An external extension should not be
616  // rejected if it fails the safty checks for a syncable extension.
617  // TODO(skerner): Work out other potential overlapping conditions.
618  // (crbug.com/61000)
619  PendingExtensionMap::iterator it = pending_extensions_.find(id);
620  if (it != pending_extensions_.end()) {
621    VLOG(1) << "Extension id " << id
622            << " was entered for update more than once."
623            << "  old is_from_sync = " << it->second.is_from_sync()
624            << "  new is_from_sync = " << is_from_sync;
625    if (!it->second.is_from_sync() && is_from_sync)
626      return;
627  }
628
629  pending_extensions_[id] =
630      PendingExtensionInfo(update_url, should_allow_install,
631                           is_from_sync, install_silently, enable_on_install,
632                           enable_incognito_on_install, install_source);
633}
634
635void ExtensionService::ReloadExtension(const std::string& extension_id) {
636  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
637  FilePath path;
638  const Extension* current_extension = GetExtensionById(extension_id, false);
639
640  // Disable the extension if it's loaded. It might not be loaded if it crashed.
641  if (current_extension) {
642    // If the extension has an inspector open for its background page, detach
643    // the inspector and hang onto a cookie for it, so that we can reattach
644    // later.
645    ExtensionProcessManager* manager = profile_->GetExtensionProcessManager();
646    ExtensionHost* host = manager->GetBackgroundHostForExtension(
647        current_extension);
648    if (host) {
649      // Look for an open inspector for the background page.
650      int devtools_cookie = DevToolsManager::GetInstance()->DetachClientHost(
651          host->render_view_host());
652      if (devtools_cookie >= 0)
653        orphaned_dev_tools_[extension_id] = devtools_cookie;
654    }
655
656    path = current_extension->path();
657    DisableExtension(extension_id);
658    disabled_extension_paths_[extension_id] = path;
659  } else {
660    path = unloaded_extension_paths_[extension_id];
661  }
662
663  // Check the installed extensions to see if what we're reloading was already
664  // installed.
665  scoped_ptr<ExtensionInfo> installed_extension(
666      extension_prefs_->GetInstalledExtensionInfo(extension_id));
667  if (installed_extension.get() &&
668      installed_extension->extension_manifest.get()) {
669    LoadInstalledExtension(*installed_extension, false);
670  } else {
671    // We should always be able to remember the extension's path. If it's not in
672    // the map, someone failed to update |unloaded_extension_paths_|.
673    CHECK(!path.empty());
674    LoadExtension(path);
675  }
676}
677
678void ExtensionService::UninstallExtension(const std::string& extension_id,
679                                           bool external_uninstall) {
680  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
681
682  const Extension* extension =
683      GetExtensionByIdInternal(extension_id, true, true);
684  if (!extension)
685    extension = GetTerminatedExtension(extension_id);
686
687  // Callers should not send us nonexistent extensions.
688  CHECK(extension);
689
690  // Get hold of information we need after unloading, since the extension
691  // pointer will be invalid then.
692  GURL extension_url(extension->url());
693  Extension::Location location(extension->location());
694  UninstalledExtensionInfo uninstalled_extension_info(*extension);
695
696  UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType",
697                            extension->GetType(), 100);
698
699  // Also copy the extension identifier since the reference might have been
700  // obtained via Extension::id().
701  std::string extension_id_copy(extension_id);
702
703  if (profile_->GetTemplateURLModel())
704    profile_->GetTemplateURLModel()->UnregisterExtensionKeyword(extension);
705
706  // Unload before doing more cleanup to ensure that nothing is hanging on to
707  // any of these resources.
708  UnloadExtension(extension_id, UnloadedExtensionInfo::UNINSTALL);
709
710  extension_prefs_->OnExtensionUninstalled(extension_id_copy, location,
711                                           external_uninstall);
712
713  // Tell the backend to start deleting installed extensions on the file thread.
714  if (Extension::LOAD != location) {
715    BrowserThread::PostTask(
716      BrowserThread::FILE, FROM_HERE,
717      NewRunnableFunction(
718          &extension_file_util::UninstallExtension,
719          install_directory_,
720          extension_id_copy));
721  }
722
723  ClearExtensionData(extension_url);
724  UntrackTerminatedExtension(extension_id);
725
726  // Notify interested parties that we've uninstalled this extension.
727  NotificationService::current()->Notify(
728      NotificationType::EXTENSION_UNINSTALLED,
729      Source<Profile>(profile_),
730      Details<UninstalledExtensionInfo>(&uninstalled_extension_info));
731}
732
733void ExtensionService::ClearExtensionData(const GURL& extension_url) {
734  scoped_refptr<ExtensionDataDeleter> deleter(
735      new ExtensionDataDeleter(profile_, extension_url));
736  deleter->StartDeleting();
737}
738
739void ExtensionService::EnableExtension(const std::string& extension_id) {
740  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
741
742  const Extension* extension =
743      GetExtensionByIdInternal(extension_id, false, true);
744  if (!extension)
745    return;
746
747  extension_prefs_->SetExtensionState(extension, Extension::ENABLED);
748
749  // Move it over to the enabled list.
750  extensions_.push_back(make_scoped_refptr(extension));
751  ExtensionList::iterator iter = std::find(disabled_extensions_.begin(),
752                                           disabled_extensions_.end(),
753                                           extension);
754  disabled_extensions_.erase(iter);
755
756  // Make sure any browser action contained within it is not hidden.
757  extension_prefs_->SetBrowserActionVisibility(extension, true);
758
759  ExtensionWebUI::RegisterChromeURLOverrides(profile_,
760      extension->GetChromeURLOverrides());
761
762  NotifyExtensionLoaded(extension);
763  UpdateActiveExtensionsInCrashReporter();
764}
765
766void ExtensionService::DisableExtension(const std::string& extension_id) {
767  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
768
769  const Extension* extension =
770      GetExtensionByIdInternal(extension_id, true, false);
771  // The extension may have been disabled already.
772  if (!extension)
773    return;
774
775  extension_prefs_->SetExtensionState(extension, Extension::DISABLED);
776
777  // Move it over to the disabled list.
778  disabled_extensions_.push_back(make_scoped_refptr(extension));
779  ExtensionList::iterator iter = std::find(extensions_.begin(),
780                                           extensions_.end(),
781                                           extension);
782  extensions_.erase(iter);
783
784  ExtensionWebUI::UnregisterChromeURLOverrides(profile_,
785      extension->GetChromeURLOverrides());
786
787  NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::DISABLE);
788  UpdateActiveExtensionsInCrashReporter();
789}
790
791void ExtensionService::GrantPermissions(const Extension* extension) {
792  CHECK(extension);
793
794  // We only maintain the granted permissions prefs for INTERNAL extensions.
795  CHECK(extension->location() == Extension::INTERNAL);
796
797  ExtensionExtent effective_hosts = extension->GetEffectiveHostPermissions();
798  extension_prefs_->AddGrantedPermissions(extension->id(),
799                                          extension->HasFullPermissions(),
800                                          extension->api_permissions(),
801                                          effective_hosts);
802}
803
804void ExtensionService::GrantPermissionsAndEnableExtension(
805    const Extension* extension) {
806  CHECK(extension);
807  GrantPermissions(extension);
808  extension_prefs_->SetDidExtensionEscalatePermissions(extension, false);
809  EnableExtension(extension->id());
810}
811
812void ExtensionService::LoadExtension(const FilePath& extension_path) {
813  BrowserThread::PostTask(
814      BrowserThread::FILE, FROM_HERE,
815      NewRunnableMethod(
816          backend_.get(),
817          &ExtensionServiceBackend::LoadSingleExtension,
818          extension_path, scoped_refptr<ExtensionService>(this)));
819}
820
821void ExtensionService::LoadComponentExtensions() {
822  for (RegisteredComponentExtensions::iterator it =
823           component_extension_manifests_.begin();
824       it != component_extension_manifests_.end(); ++it) {
825    JSONStringValueSerializer serializer(it->manifest);
826    scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL));
827    if (!manifest.get()) {
828      DLOG(ERROR) << "Failed to parse manifest for extension";
829      continue;
830    }
831
832    std::string error;
833    scoped_refptr<const Extension> extension(Extension::Create(
834        it->root_directory,
835        Extension::COMPONENT,
836        *static_cast<DictionaryValue*>(manifest.get()),
837        true,  // Require key
838        Extension::ShouldDoStrictErrorChecking(Extension::COMPONENT),
839        &error));
840    if (!extension.get()) {
841      NOTREACHED() << error;
842      return;
843    }
844    AddExtension(extension);
845  }
846}
847
848void ExtensionService::LoadAllExtensions() {
849  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
850
851  base::TimeTicks start_time = base::TimeTicks::Now();
852
853  // Load any component extensions.
854  LoadComponentExtensions();
855
856  // Load the previously installed extensions.
857  scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
858      extension_prefs_->GetInstalledExtensionsInfo());
859
860  std::vector<int> reload_reason_counts(NUM_MANIFEST_RELOAD_REASONS, 0);
861  bool should_write_prefs = false;
862
863  for (size_t i = 0; i < extensions_info->size(); ++i) {
864    ExtensionInfo* info = extensions_info->at(i).get();
865
866    ManifestReloadReason reload_reason = ShouldReloadExtensionManifest(*info);
867    ++reload_reason_counts[reload_reason];
868    UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestReloadEnumValue",
869                              reload_reason, 100);
870
871    if (reload_reason != NOT_NEEDED) {
872      // Reloading and extension reads files from disk.  We do this on the
873      // UI thread because reloads should be very rare, and the complexity
874      // added by delaying the time when the extensions service knows about
875      // all extensions is significant.  See crbug.com/37548 for details.
876      // |allow_io| disables tests that file operations run on the file
877      // thread.
878      base::ThreadRestrictions::ScopedAllowIO allow_io;
879
880      std::string error;
881      scoped_refptr<const Extension> extension(
882          extension_file_util::LoadExtension(
883              info->extension_path,
884              info->extension_location,
885              false,  // Don't require key
886              Extension::ShouldDoStrictErrorChecking(info->extension_location),
887              &error));
888
889      if (extension.get()) {
890        extensions_info->at(i)->extension_manifest.reset(
891            static_cast<DictionaryValue*>(
892                extension->manifest_value()->DeepCopy()));
893        should_write_prefs = true;
894      }
895    }
896  }
897
898  for (size_t i = 0; i < extensions_info->size(); ++i) {
899    LoadInstalledExtension(*extensions_info->at(i), should_write_prefs);
900  }
901
902  OnLoadedInstalledExtensions();
903
904  // The histograms Extensions.ManifestReload* allow us to validate
905  // the assumption that reloading manifest is a rare event.
906  UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNotNeeded",
907                           reload_reason_counts[NOT_NEEDED]);
908  UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadUnpackedDir",
909                           reload_reason_counts[UNPACKED_DIR]);
910  UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNeedsRelocalization",
911                           reload_reason_counts[NEEDS_RELOCALIZATION]);
912
913  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAll", extensions_.size());
914  UMA_HISTOGRAM_COUNTS_100("Extensions.Disabled", disabled_extensions_.size());
915
916  UMA_HISTOGRAM_TIMES("Extensions.LoadAllTime",
917                      base::TimeTicks::Now() - start_time);
918
919  int app_count = 0;
920  int hosted_app_count = 0;
921  int packaged_app_count = 0;
922  int user_script_count = 0;
923  int extension_count = 0;
924  int theme_count = 0;
925  int external_count = 0;
926  int page_action_count = 0;
927  int browser_action_count = 0;
928  ExtensionList::iterator ex;
929  for (ex = extensions_.begin(); ex != extensions_.end(); ++ex) {
930    Extension::Location location = (*ex)->location();
931    Extension::Type type = (*ex)->GetType();
932    if ((*ex)->is_app()) {
933      UMA_HISTOGRAM_ENUMERATION("Extensions.AppLocation",
934                                location, 100);
935    } else if (type == Extension::TYPE_EXTENSION) {
936      UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionLocation",
937                                location, 100);
938    }
939
940    // Don't count component extensions, since they are only extensions as an
941    // implementation detail.
942    if (location == Extension::COMPONENT)
943      continue;
944
945    // Don't count unpacked extensions, since they're a developer-specific
946    // feature.
947    if (location == Extension::LOAD)
948      continue;
949
950    // Using an enumeration shows us the total installed ratio across all users.
951    // Using the totals per user at each startup tells us the distribution of
952    // usage for each user (e.g. 40% of users have at least one app installed).
953    UMA_HISTOGRAM_ENUMERATION("Extensions.LoadType", type, 100);
954    switch (type) {
955      case Extension::TYPE_THEME:
956        ++theme_count;
957        break;
958      case Extension::TYPE_USER_SCRIPT:
959        ++user_script_count;
960        break;
961      case Extension::TYPE_HOSTED_APP:
962        ++app_count;
963        ++hosted_app_count;
964        break;
965      case Extension::TYPE_PACKAGED_APP:
966        ++app_count;
967        ++packaged_app_count;
968        break;
969      case Extension::TYPE_EXTENSION:
970      default:
971        ++extension_count;
972        break;
973    }
974    if (Extension::IsExternalLocation(location))
975      ++external_count;
976    if ((*ex)->page_action() != NULL)
977      ++page_action_count;
978    if ((*ex)->browser_action() != NULL)
979      ++browser_action_count;
980  }
981  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp", app_count);
982  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count);
983  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", packaged_app_count);
984  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension", extension_count);
985  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count);
986  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count);
987  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExternal", external_count);
988  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPageAction", page_action_count);
989  UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction",
990                           browser_action_count);
991}
992
993void ExtensionService::LoadInstalledExtension(const ExtensionInfo& info,
994                                              bool write_to_prefs) {
995  std::string error;
996  scoped_refptr<const Extension> extension(NULL);
997  if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id)) {
998    error = errors::kDisabledByPolicy;
999  } else if (info.extension_manifest.get()) {
1000    bool require_key = info.extension_location != Extension::LOAD;
1001    extension = Extension::Create(
1002        info.extension_path,
1003        info.extension_location,
1004        *info.extension_manifest,
1005        require_key,
1006        Extension::ShouldDoStrictErrorChecking(info.extension_location),
1007        &error);
1008  } else {
1009    error = errors::kManifestUnreadable;
1010  }
1011
1012  if (!extension) {
1013    ReportExtensionLoadError(info.extension_path,
1014                             error,
1015                             NotificationType::EXTENSION_INSTALL_ERROR,
1016                             false);
1017    return;
1018  }
1019
1020  if (write_to_prefs)
1021    extension_prefs_->UpdateManifest(extension);
1022
1023  AddExtension(extension);
1024}
1025
1026void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
1027  // The ChromeURLRequestContexts need to be first to know that the extension
1028  // was loaded, otherwise a race can arise where a renderer that is created
1029  // for the extension may try to load an extension URL with an extension id
1030  // that the request context doesn't yet know about. The profile is responsible
1031  // for ensuring its URLRequestContexts appropriately discover the loaded
1032  // extension.
1033  if (profile_) {
1034    profile_->RegisterExtensionWithRequestContexts(extension);
1035    profile_->GetExtensionSpecialStoragePolicy()->
1036        GrantRightsForExtension(extension);
1037  }
1038
1039  NotificationService::current()->Notify(
1040      NotificationType::EXTENSION_LOADED,
1041      Source<Profile>(profile_),
1042      Details<const Extension>(extension));
1043}
1044
1045void ExtensionService::NotifyExtensionUnloaded(
1046    const Extension* extension, UnloadedExtensionInfo::Reason reason) {
1047  UnloadedExtensionInfo details(extension, reason);
1048  NotificationService::current()->Notify(
1049      NotificationType::EXTENSION_UNLOADED,
1050      Source<Profile>(profile_),
1051      Details<UnloadedExtensionInfo>(&details));
1052
1053  if (profile_) {
1054    profile_->UnregisterExtensionWithRequestContexts(extension);
1055    profile_->GetExtensionSpecialStoragePolicy()->
1056        RevokeRightsForExtension(extension);
1057  }
1058}
1059
1060void ExtensionService::UpdateExtensionBlacklist(
1061  const std::vector<std::string>& blacklist) {
1062  // Use this set to indicate if an extension in the blacklist has been used.
1063  std::set<std::string> blacklist_set;
1064  for (unsigned int i = 0; i < blacklist.size(); ++i) {
1065    if (Extension::IdIsValid(blacklist[i])) {
1066      blacklist_set.insert(blacklist[i]);
1067    }
1068  }
1069  extension_prefs_->UpdateBlacklist(blacklist_set);
1070  std::vector<std::string> to_be_removed;
1071  // Loop current extensions, unload installed extensions.
1072  for (ExtensionList::const_iterator iter = extensions_.begin();
1073       iter != extensions_.end(); ++iter) {
1074    const Extension* extension = (*iter);
1075    if (blacklist_set.find(extension->id()) != blacklist_set.end()) {
1076      to_be_removed.push_back(extension->id());
1077    }
1078  }
1079
1080  // UnloadExtension will change the extensions_ list. So, we should
1081  // call it outside the iterator loop.
1082  for (unsigned int i = 0; i < to_be_removed.size(); ++i) {
1083    UnloadExtension(to_be_removed[i], UnloadedExtensionInfo::DISABLE);
1084  }
1085}
1086
1087Profile* ExtensionService::profile() {
1088  return profile_;
1089}
1090
1091void ExtensionService::DestroyingProfile() {
1092  if (updater_.get()) {
1093    updater_->Stop();
1094  }
1095  browser_event_router_.reset();
1096  pref_change_registrar_.RemoveAll();
1097  profile_ = NULL;
1098  toolbar_model_.DestroyingProfile();
1099}
1100
1101ExtensionPrefs* ExtensionService::extension_prefs() {
1102  return extension_prefs_;
1103}
1104
1105void ExtensionService::CheckAdminBlacklist() {
1106  std::vector<std::string> to_be_removed;
1107  // Loop through extensions list, unload installed extensions.
1108  for (ExtensionList::const_iterator iter = extensions_.begin();
1109       iter != extensions_.end(); ++iter) {
1110    const Extension* extension = (*iter);
1111    if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id()))
1112      to_be_removed.push_back(extension->id());
1113  }
1114
1115  // UnloadExtension will change the extensions_ list. So, we should
1116  // call it outside the iterator loop.
1117  for (unsigned int i = 0; i < to_be_removed.size(); ++i)
1118    UnloadExtension(to_be_removed[i], UnloadedExtensionInfo::DISABLE);
1119}
1120
1121bool ExtensionService::IsIncognitoEnabled(const Extension* extension) {
1122  // If this is a component extension we always allow it to work in incognito
1123  // mode.
1124  if (extension->location() == Extension::COMPONENT)
1125    return true;
1126
1127  // Check the prefs.
1128  return extension_prefs_->IsIncognitoEnabled(extension->id());
1129}
1130
1131void ExtensionService::SetIsIncognitoEnabled(const Extension* extension,
1132                                              bool enabled) {
1133  extension_prefs_->SetIsIncognitoEnabled(extension->id(), enabled);
1134
1135  // Broadcast unloaded and loaded events to update browser state. Only bother
1136  // if the extension is actually enabled, since there is no UI otherwise.
1137  bool is_enabled = std::find(extensions_.begin(), extensions_.end(),
1138                              extension) != extensions_.end();
1139  if (is_enabled) {
1140    NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::DISABLE);
1141    NotifyExtensionLoaded(extension);
1142  }
1143}
1144
1145bool ExtensionService::CanCrossIncognito(const Extension* extension) {
1146  // We allow the extension to see events and data from another profile iff it
1147  // uses "spanning" behavior and it has incognito access. "split" mode
1148  // extensions only see events for a matching profile.
1149  return IsIncognitoEnabled(extension) && !extension->incognito_split_mode();
1150}
1151
1152bool ExtensionService::AllowFileAccess(const Extension* extension) {
1153  return (CommandLine::ForCurrentProcess()->HasSwitch(
1154              switches::kDisableExtensionsFileAccessCheck) ||
1155          extension_prefs_->AllowFileAccess(extension->id()));
1156}
1157
1158void ExtensionService::SetAllowFileAccess(const Extension* extension,
1159                                           bool allow) {
1160  extension_prefs_->SetAllowFileAccess(extension->id(), allow);
1161  NotificationService::current()->Notify(
1162      NotificationType::EXTENSION_USER_SCRIPTS_UPDATED,
1163      Source<Profile>(profile_),
1164      Details<const Extension>(extension));
1165}
1166
1167bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) {
1168  return extension_prefs_->GetBrowserActionVisibility(extension);
1169}
1170
1171void ExtensionService::SetBrowserActionVisibility(const Extension* extension,
1172                                                  bool visible) {
1173  extension_prefs_->SetBrowserActionVisibility(extension, visible);
1174}
1175
1176// Some extensions will autoupdate themselves externally from Chrome.  These
1177// are typically part of some larger client application package.  To support
1178// these, the extension will register its location in the the preferences file
1179// (and also, on Windows, in the registry) and this code will periodically
1180// check that location for a .crx file, which it will then install locally if
1181// a new version is available.
1182// Errors are reported through ExtensionErrorReporter. Succcess is not
1183// reported.
1184void ExtensionService::CheckForExternalUpdates() {
1185  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1186
1187  // Note that this installation is intentionally silent (since it didn't
1188  // go through the front-end).  Extensions that are registered in this
1189  // way are effectively considered 'pre-bundled', and so implicitly
1190  // trusted.  In general, if something has HKLM or filesystem access,
1191  // they could install an extension manually themselves anyway.
1192
1193  // If any external extension records give a URL, a provider will set
1194  // this to true.  Used by OnExternalProviderReady() to see if we need
1195  // to start an update check to fetch a new external extension.
1196  external_extension_url_added_ = false;
1197
1198  // Ask each external extension provider to give us a call back for each
1199  // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
1200  ProviderCollection::const_iterator i;
1201  for (i = external_extension_providers_.begin();
1202       i != external_extension_providers_.end(); ++i) {
1203    ExternalExtensionProviderInterface* provider = i->get();
1204    provider->VisitRegisteredExtension();
1205  }
1206
1207  // Uninstall of unclaimed extensions will happen after all the providers
1208  // had reported ready.  Every provider calls OnExternalProviderReady()
1209  // when it finishes, and OnExternalProviderReady() only acts when all
1210  // providers are ready.  In case there are no providers, we call it
1211  // to trigger removal of extensions that used to have an external source.
1212  if (external_extension_providers_.empty())
1213    OnExternalProviderReady();
1214}
1215
1216void ExtensionService::OnExternalProviderReady() {
1217  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1218
1219  // An external provider has finished loading.  We only take action
1220  // if all of them are finished. So we check them first.
1221  ProviderCollection::const_iterator i;
1222  for (i = external_extension_providers_.begin();
1223       i != external_extension_providers_.end(); ++i) {
1224    ExternalExtensionProviderInterface* provider = i->get();
1225    if (!provider->IsReady())
1226      return;
1227  }
1228
1229  // All the providers are ready.  Install any pending extensions.
1230  if (external_extension_url_added_ && updater()) {
1231    external_extension_url_added_ = false;
1232    updater()->CheckNow();
1233  }
1234
1235  // Uninstall all the unclaimed extensions.
1236  scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
1237      extension_prefs_->GetInstalledExtensionsInfo());
1238  for (size_t i = 0; i < extensions_info->size(); ++i) {
1239    ExtensionInfo* info = extensions_info->at(i).get();
1240    if (Extension::IsExternalLocation(info->extension_location))
1241      CheckExternalUninstall(info->extension_id);
1242  }
1243}
1244
1245void ExtensionService::UnloadExtension(
1246    const std::string& extension_id,
1247    UnloadedExtensionInfo::Reason reason) {
1248  // Make sure the extension gets deleted after we return from this function.
1249  scoped_refptr<const Extension> extension(
1250      GetExtensionByIdInternal(extension_id, true, true));
1251
1252  // This method can be called via PostTask, so the extension may have been
1253  // unloaded by the time this runs.
1254  if (!extension)
1255    return;
1256
1257  // Keep information about the extension so that we can reload it later
1258  // even if it's not permanently installed.
1259  unloaded_extension_paths_[extension->id()] = extension->path();
1260
1261  // Clean up if the extension is meant to be enabled after a reload.
1262  disabled_extension_paths_.erase(extension->id());
1263
1264  // Clean up runtime data.
1265  extension_runtime_data_.erase(extension_id);
1266
1267  ExtensionWebUI::UnregisterChromeURLOverrides(profile_,
1268      extension->GetChromeURLOverrides());
1269
1270  ExtensionList::iterator iter = std::find(disabled_extensions_.begin(),
1271                                           disabled_extensions_.end(),
1272                                           extension.get());
1273  if (iter != disabled_extensions_.end()) {
1274    UnloadedExtensionInfo details(extension, reason);
1275    details.already_disabled = true;
1276    disabled_extensions_.erase(iter);
1277    NotificationService::current()->Notify(
1278        NotificationType::EXTENSION_UNLOADED,
1279        Source<Profile>(profile_),
1280        Details<UnloadedExtensionInfo>(&details));
1281    return;
1282  }
1283
1284  iter = std::find(extensions_.begin(), extensions_.end(), extension.get());
1285
1286  // Remove the extension from our list.
1287  extensions_.erase(iter);
1288
1289  NotifyExtensionUnloaded(extension.get(), reason);
1290  UpdateActiveExtensionsInCrashReporter();
1291}
1292
1293void ExtensionService::UnloadAllExtensions() {
1294  if (profile_) {
1295    profile_->GetExtensionSpecialStoragePolicy()->
1296        RevokeRightsForAllExtensions();
1297  }
1298  extensions_.clear();
1299  disabled_extensions_.clear();
1300  terminated_extension_ids_.clear();
1301  terminated_extensions_.clear();
1302  extension_runtime_data_.clear();
1303
1304  // TODO(erikkay) should there be a notification for this?  We can't use
1305  // EXTENSION_UNLOADED since that implies that the extension has been disabled
1306  // or uninstalled, and UnloadAll is just part of shutdown.
1307}
1308
1309void ExtensionService::ReloadExtensions() {
1310  UnloadAllExtensions();
1311  LoadAllExtensions();
1312}
1313
1314void ExtensionService::GarbageCollectExtensions() {
1315  if (extension_prefs_->pref_service()->ReadOnly())
1316    return;
1317
1318  scoped_ptr<ExtensionPrefs::ExtensionsInfo> info(
1319      extension_prefs_->GetInstalledExtensionsInfo());
1320
1321  std::map<std::string, FilePath> extension_paths;
1322  for (size_t i = 0; i < info->size(); ++i)
1323    extension_paths[info->at(i)->extension_id] = info->at(i)->extension_path;
1324
1325  BrowserThread::PostTask(
1326      BrowserThread::FILE, FROM_HERE,
1327      NewRunnableFunction(
1328          &extension_file_util::GarbageCollectExtensions, install_directory_,
1329          extension_paths));
1330
1331  // Also garbage-collect themes.  We check |profile_| to be
1332  // defensive; in the future, we may call GarbageCollectExtensions()
1333  // from somewhere other than Init() (e.g., in a timer).
1334  if (profile_) {
1335    profile_->GetThemeProvider()->RemoveUnusedThemes();
1336  }
1337}
1338
1339void ExtensionService::OnLoadedInstalledExtensions() {
1340  if (updater_.get()) {
1341    updater_->Start();
1342  }
1343
1344  ready_ = true;
1345  NotificationService::current()->Notify(
1346      NotificationType::EXTENSIONS_READY,
1347      Source<Profile>(profile_),
1348      NotificationService::NoDetails());
1349}
1350
1351void ExtensionService::AddExtension(const Extension* extension) {
1352  // Ensure extension is deleted unless we transfer ownership.
1353  scoped_refptr<const Extension> scoped_extension(extension);
1354
1355  // The extension is now loaded, remove its data from unloaded extension map.
1356  unloaded_extension_paths_.erase(extension->id());
1357
1358  // If a terminated extension is loaded, remove it from the terminated list.
1359  UntrackTerminatedExtension(extension->id());
1360
1361  // If the extension was disabled for a reload, then enable it.
1362  if (disabled_extension_paths_.erase(extension->id()) > 0)
1363    EnableExtension(extension->id());
1364
1365  // TODO(jstritar): We may be able to get rid of this branch by overriding the
1366  // default extension state to DISABLED when the --disable-extensions flag
1367  // is set (http://crbug.com/29067).
1368  if (!extensions_enabled() &&
1369      !extension->is_theme() &&
1370      extension->location() != Extension::COMPONENT &&
1371      !Extension::IsExternalLocation(extension->location()))
1372    return;
1373
1374  // Check if the extension's privileges have changed and disable the
1375  // extension if necessary.
1376  DisableIfPrivilegeIncrease(extension);
1377
1378  switch (extension_prefs_->GetExtensionState(extension->id())) {
1379    case Extension::ENABLED:
1380      extensions_.push_back(scoped_extension);
1381
1382      NotifyExtensionLoaded(extension);
1383
1384      ExtensionWebUI::RegisterChromeURLOverrides(
1385          profile_, extension->GetChromeURLOverrides());
1386      break;
1387    case Extension::DISABLED:
1388      disabled_extensions_.push_back(scoped_extension);
1389      NotificationService::current()->Notify(
1390          NotificationType::EXTENSION_UPDATE_DISABLED,
1391          Source<Profile>(profile_),
1392          Details<const Extension>(extension));
1393      break;
1394    default:
1395      NOTREACHED();
1396      break;
1397  }
1398
1399  SetBeingUpgraded(extension, false);
1400
1401  UpdateActiveExtensionsInCrashReporter();
1402
1403  if (profile_->GetTemplateURLModel())
1404    profile_->GetTemplateURLModel()->RegisterExtensionKeyword(extension);
1405
1406  // Load the icon for omnibox-enabled extensions so it will be ready to display
1407  // in the URL bar.
1408  if (!extension->omnibox_keyword().empty()) {
1409    omnibox_popup_icon_manager_.LoadIcon(extension);
1410    omnibox_icon_manager_.LoadIcon(extension);
1411  }
1412}
1413
1414void ExtensionService::DisableIfPrivilegeIncrease(const Extension* extension) {
1415  // We keep track of all permissions the user has granted each extension.
1416  // This allows extensions to gracefully support backwards compatibility
1417  // by including unknown permissions in their manifests. When the user
1418  // installs the extension, only the recognized permissions are recorded.
1419  // When the unknown permissions become recognized (e.g., through browser
1420  // upgrade), we can prompt the user to accept these new permissions.
1421  // Extensions can also silently upgrade to less permissions, and then
1422  // silently upgrade to a version that adds these permissions back.
1423  //
1424  // For example, pretend that Chrome 10 includes a permission "omnibox"
1425  // for an API that adds suggestions to the omnibox. An extension can
1426  // maintain backwards compatibility while still having "omnibox" in the
1427  // manifest. If a user installs the extension on Chrome 9, the browser
1428  // will record the permissions it recognized, not including "omnibox."
1429  // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome
1430  // will disable the extension and prompt the user to approve the increase
1431  // in privileges. The extension could then release a new version that
1432  // removes the "omnibox" permission. When the user upgrades, Chrome will
1433  // still remember that "omnibox" had been granted, so that if the
1434  // extension once again includes "omnibox" in an upgrade, the extension
1435  // can upgrade without requiring this user's approval.
1436  const Extension* old = GetExtensionByIdInternal(extension->id(),
1437                                                  true, true);
1438  bool granted_full_access;
1439  std::set<std::string> granted_apis;
1440  ExtensionExtent granted_extent;
1441
1442  bool is_extension_upgrade = old != NULL;
1443  bool is_privilege_increase = false;
1444
1445  // We only record the granted permissions for INTERNAL extensions, since
1446  // they can't silently increase privileges.
1447  if (extension->location() == Extension::INTERNAL) {
1448    // Add all the recognized permissions if the granted permissions list
1449    // hasn't been initialized yet.
1450    if (!extension_prefs_->GetGrantedPermissions(extension->id(),
1451                                                 &granted_full_access,
1452                                                 &granted_apis,
1453                                                 &granted_extent)) {
1454      GrantPermissions(extension);
1455      CHECK(extension_prefs_->GetGrantedPermissions(extension->id(),
1456                                                    &granted_full_access,
1457                                                    &granted_apis,
1458                                                    &granted_extent));
1459    }
1460
1461    // Here, we check if an extension's privileges have increased in a manner
1462    // that requires the user's approval. This could occur because the browser
1463    // upgraded and recognized additional privileges, or an extension upgrades
1464    // to a version that requires additional privileges.
1465    is_privilege_increase = Extension::IsPrivilegeIncrease(
1466        granted_full_access, granted_apis, granted_extent, extension);
1467  }
1468
1469  if (is_extension_upgrade) {
1470    // Other than for unpacked extensions, CrxInstaller should have guaranteed
1471    // that we aren't downgrading.
1472    if (extension->location() != Extension::LOAD)
1473      CHECK(extension->version()->CompareTo(*(old->version())) >= 0);
1474
1475    // Extensions get upgraded if the privileges are allowed to increase or
1476    // the privileges haven't increased.
1477    if (!is_privilege_increase) {
1478      SetBeingUpgraded(old, true);
1479      SetBeingUpgraded(extension, true);
1480    }
1481
1482    // To upgrade an extension in place, unload the old one and
1483    // then load the new one.
1484    UnloadExtension(old->id(), UnloadedExtensionInfo::UPDATE);
1485    old = NULL;
1486  }
1487
1488  // Extension has changed permissions significantly. Disable it. A
1489  // notification should be sent by the caller.
1490  if (is_privilege_increase) {
1491    extension_prefs_->SetExtensionState(extension, Extension::DISABLED);
1492    extension_prefs_->SetDidExtensionEscalatePermissions(extension, true);
1493  }
1494}
1495
1496void ExtensionService::UpdateActiveExtensionsInCrashReporter() {
1497  std::set<std::string> extension_ids;
1498  for (size_t i = 0; i < extensions_.size(); ++i) {
1499    if (!extensions_[i]->is_theme() &&
1500        extensions_[i]->location() != Extension::COMPONENT)
1501      extension_ids.insert(extensions_[i]->id());
1502  }
1503
1504  child_process_logging::SetActiveExtensions(extension_ids);
1505}
1506
1507void ExtensionService::OnExtensionInstalled(const Extension* extension) {
1508  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1509
1510  // Ensure extension is deleted unless we transfer ownership.
1511  scoped_refptr<const Extension> scoped_extension(extension);
1512  Extension::State initial_state = Extension::DISABLED;
1513  bool initial_enable_incognito = false;
1514  PendingExtensionMap::iterator it =
1515      pending_extensions_.find(extension->id());
1516  if (it != pending_extensions_.end()) {
1517    PendingExtensionInfo pending_extension_info = it->second;
1518    pending_extensions_.erase(it);
1519    it = pending_extensions_.end();
1520
1521    if (!pending_extension_info.ShouldAllowInstall(*extension)) {
1522      LOG(WARNING)
1523          << "should_install_extension() returned false for "
1524          << extension->id() << " of type " << extension->GetType()
1525          << " and update URL " << extension->update_url().spec()
1526          << "; not installing";
1527      // Delete the extension directory since we're not going to
1528      // load it.
1529      BrowserThread::PostTask(
1530          BrowserThread::FILE, FROM_HERE,
1531          NewRunnableFunction(&extension_file_util::DeleteFile, extension->path(), true));
1532      return;
1533    }
1534
1535    if (extension->is_theme()) {
1536      DCHECK(pending_extension_info.enable_on_install());
1537      initial_state = Extension::ENABLED;
1538      DCHECK(!pending_extension_info.enable_incognito_on_install());
1539      initial_enable_incognito = false;
1540    } else {
1541      initial_state =
1542          pending_extension_info.enable_on_install() ?
1543          Extension::ENABLED : Extension::DISABLED;
1544      initial_enable_incognito =
1545          pending_extension_info.enable_incognito_on_install();
1546    }
1547  } else {
1548    // Make sure we preserve enabled/disabled states.
1549    Extension::State existing_state =
1550        extension_prefs_->GetExtensionState(extension->id());
1551    initial_state =
1552        (existing_state == Extension::DISABLED) ?
1553        Extension::DISABLED : Extension::ENABLED;
1554    initial_enable_incognito =
1555        extension_prefs_->IsIncognitoEnabled(extension->id());
1556  }
1557
1558  UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType",
1559                            extension->GetType(), 100);
1560  ShownSectionsHandler::OnExtensionInstalled(profile_->GetPrefs(), extension);
1561  extension_prefs_->OnExtensionInstalled(
1562      extension, initial_state, initial_enable_incognito);
1563
1564  // Unpacked extensions start off with file access since they are a developer
1565  // feature.
1566  if (extension->location() == Extension::LOAD)
1567    extension_prefs_->SetAllowFileAccess(extension->id(), true);
1568
1569  // If the extension is a theme, tell the profile (and therefore ThemeProvider)
1570  // to apply it.
1571  if (extension->is_theme()) {
1572    NotificationService::current()->Notify(
1573        NotificationType::THEME_INSTALLED,
1574        Source<Profile>(profile_),
1575        Details<const Extension>(extension));
1576  } else {
1577    NotificationService::current()->Notify(
1578        NotificationType::EXTENSION_INSTALLED,
1579        Source<Profile>(profile_),
1580        Details<const Extension>(extension));
1581  }
1582
1583  if (extension->is_app()) {
1584    ExtensionIdSet installed_ids = GetAppIds();
1585    installed_ids.insert(extension->id());
1586    default_apps_.DidInstallApp(installed_ids);
1587  }
1588
1589  // Transfer ownership of |extension| to AddExtension.
1590  AddExtension(scoped_extension);
1591}
1592
1593const Extension* ExtensionService::GetExtensionByIdInternal(
1594    const std::string& id, bool include_enabled, bool include_disabled) {
1595  std::string lowercase_id = StringToLowerASCII(id);
1596  if (include_enabled) {
1597    for (ExtensionList::const_iterator iter = extensions_.begin();
1598        iter != extensions_.end(); ++iter) {
1599      if ((*iter)->id() == lowercase_id)
1600        return *iter;
1601    }
1602  }
1603  if (include_disabled) {
1604    for (ExtensionList::const_iterator iter = disabled_extensions_.begin();
1605        iter != disabled_extensions_.end(); ++iter) {
1606      if ((*iter)->id() == lowercase_id)
1607        return *iter;
1608    }
1609  }
1610  return NULL;
1611}
1612
1613void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
1614  if (terminated_extension_ids_.insert(extension->id()).second)
1615    terminated_extensions_.push_back(make_scoped_refptr(extension));
1616}
1617
1618void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
1619  if (terminated_extension_ids_.erase(id) <= 0)
1620    return;
1621
1622  std::string lowercase_id = StringToLowerASCII(id);
1623  for (ExtensionList::iterator iter = terminated_extensions_.begin();
1624       iter != terminated_extensions_.end(); ++iter) {
1625    if ((*iter)->id() == lowercase_id) {
1626      terminated_extensions_.erase(iter);
1627      return;
1628    }
1629  }
1630}
1631
1632const Extension* ExtensionService::GetTerminatedExtension(
1633    const std::string& id) {
1634  std::string lowercase_id = StringToLowerASCII(id);
1635  for (ExtensionList::const_iterator iter = terminated_extensions_.begin();
1636       iter != terminated_extensions_.end(); ++iter) {
1637    if ((*iter)->id() == lowercase_id)
1638      return *iter;
1639  }
1640  return NULL;
1641}
1642
1643const Extension* ExtensionService::GetWebStoreApp() {
1644  return GetExtensionById(extension_misc::kWebStoreAppId, false);
1645}
1646
1647const Extension* ExtensionService::GetExtensionByURL(const GURL& url) {
1648  return url.scheme() != chrome::kExtensionScheme ? NULL :
1649      GetExtensionById(url.host(), false);
1650}
1651
1652const Extension* ExtensionService::GetExtensionByWebExtent(const GURL& url) {
1653  for (size_t i = 0; i < extensions_.size(); ++i) {
1654    if (extensions_[i]->web_extent().ContainsURL(url))
1655      return extensions_[i];
1656  }
1657  return NULL;
1658}
1659
1660bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) {
1661  // Allow bindings for all packaged extension.
1662  if (GetExtensionByURL(url))
1663    return true;
1664
1665  // Allow bindings for all component, hosted apps.
1666  const Extension* extension = GetExtensionByWebExtent(url);
1667  return (extension && extension->location() == Extension::COMPONENT);
1668}
1669
1670const Extension* ExtensionService::GetExtensionByOverlappingWebExtent(
1671    const ExtensionExtent& extent) {
1672  for (size_t i = 0; i < extensions_.size(); ++i) {
1673    if (extensions_[i]->web_extent().OverlapsWith(extent))
1674      return extensions_[i];
1675  }
1676
1677  return NULL;
1678}
1679
1680const SkBitmap& ExtensionService::GetOmniboxIcon(
1681    const std::string& extension_id) {
1682  return omnibox_icon_manager_.GetIcon(extension_id);
1683}
1684
1685const SkBitmap& ExtensionService::GetOmniboxPopupIcon(
1686    const std::string& extension_id) {
1687  return omnibox_popup_icon_manager_.GetIcon(extension_id);
1688}
1689
1690void ExtensionService::OnExternalExtensionFileFound(
1691         const std::string& id,
1692         const Version* version,
1693         const FilePath& path,
1694         Extension::Location location) {
1695  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1696  CHECK(Extension::IdIsValid(id));
1697  if (extension_prefs_->IsExtensionKilled(id))
1698    return;
1699
1700  DCHECK(version);
1701
1702  // Before even bothering to unpack, check and see if we already have this
1703  // version. This is important because these extensions are going to get
1704  // installed on every startup.
1705  const Extension* existing = GetExtensionById(id, true);
1706  if (existing) {
1707    switch (existing->version()->CompareTo(*version)) {
1708      case -1:  // existing version is older, we should upgrade
1709        break;
1710      case 0:  // existing version is same, do nothing
1711        return;
1712      case 1:  // existing version is newer, uh-oh
1713        LOG(WARNING) << "Found external version of extension " << id
1714                     << "that is older than current version. Current version "
1715                     << "is: " << existing->VersionString() << ". New version "
1716                     << "is: " << version << ". Keeping current version.";
1717        return;
1718    }
1719  }
1720
1721  GURL update_url = GURL();
1722  bool is_from_sync = false;
1723  bool install_silently = true;
1724  bool enable_on_install = true;
1725  bool enable_incognito_on_install = false;
1726  pending_extensions_[id] = PendingExtensionInfo(
1727      update_url,
1728      &AlwaysInstall,
1729      is_from_sync,
1730      install_silently,
1731      enable_on_install,
1732      enable_incognito_on_install,
1733      location);
1734
1735  scoped_refptr<CrxInstaller> installer(
1736      new CrxInstaller(this,  // frontend
1737                       NULL));  // no client (silent install)
1738  installer->set_install_source(location);
1739  installer->set_expected_id(id);
1740  installer->InstallCrx(path);
1741}
1742
1743void ExtensionService::ReportExtensionLoadError(
1744    const FilePath& extension_path,
1745    const std::string &error,
1746    NotificationType type,
1747    bool be_noisy) {
1748  NotificationService* service = NotificationService::current();
1749  service->Notify(type,
1750                  Source<Profile>(profile_),
1751                  Details<const std::string>(&error));
1752
1753  std::string path_str = UTF16ToUTF8(extension_path.LossyDisplayName());
1754  std::string message = base::StringPrintf(
1755      "Could not load extension from '%s'. %s",
1756      path_str.c_str(), error.c_str());
1757  ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy);
1758}
1759
1760void ExtensionService::DidCreateRenderViewForBackgroundPage(
1761    ExtensionHost* host) {
1762  OrphanedDevTools::iterator iter =
1763      orphaned_dev_tools_.find(host->extension()->id());
1764  if (iter == orphaned_dev_tools_.end())
1765    return;
1766
1767  DevToolsManager::GetInstance()->AttachClientHost(
1768      iter->second, host->render_view_host());
1769  orphaned_dev_tools_.erase(iter);
1770}
1771
1772void ExtensionService::Observe(NotificationType type,
1773                                const NotificationSource& source,
1774                                const NotificationDetails& details) {
1775  switch (type.value) {
1776    case NotificationType::EXTENSION_PROCESS_TERMINATED: {
1777      if (profile_ != Source<Profile>(source).ptr()->GetOriginalProfile())
1778        break;
1779
1780      ExtensionHost* host = Details<ExtensionHost>(details).ptr();
1781      TrackTerminatedExtension(host->extension());
1782
1783      // Unload the entire extension. We want it to be in a consistent state:
1784      // either fully working or not loaded at all, but never half-crashed.
1785      // We do it in a PostTask so that other handlers of this notification will
1786      // still have access to the Extension and ExtensionHost.
1787      MessageLoop::current()->PostTask(FROM_HERE,
1788          NewRunnableMethod(this,
1789                            &ExtensionService::UnloadExtension,
1790                            host->extension()->id(),
1791                            UnloadedExtensionInfo::DISABLE));
1792      break;
1793    }
1794
1795    case NotificationType::PREF_CHANGED: {
1796      std::string* pref_name = Details<std::string>(details).ptr();
1797      if (*pref_name == prefs::kExtensionInstallAllowList ||
1798          *pref_name == prefs::kExtensionInstallDenyList) {
1799        CheckAdminBlacklist();
1800      } else {
1801        NOTREACHED() << "Unexpected preference name.";
1802      }
1803      break;
1804    }
1805
1806    default:
1807      NOTREACHED() << "Unexpected notification type.";
1808  }
1809}
1810
1811bool ExtensionService::HasApps() const {
1812  return !GetAppIds().empty();
1813}
1814
1815ExtensionIdSet ExtensionService::GetAppIds() const {
1816  ExtensionIdSet result;
1817  for (ExtensionList::const_iterator it = extensions_.begin();
1818       it != extensions_.end(); ++it) {
1819    if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT)
1820      result.insert((*it)->id());
1821  }
1822
1823  return result;
1824}
1825
1826bool ExtensionService::IsBackgroundPageReady(const Extension* extension) {
1827  return (extension->background_url().is_empty() ||
1828          extension_runtime_data_[extension->id()].background_page_ready);
1829}
1830
1831void ExtensionService::SetBackgroundPageReady(const Extension* extension) {
1832  DCHECK(!extension->background_url().is_empty());
1833  extension_runtime_data_[extension->id()].background_page_ready = true;
1834  NotificationService::current()->Notify(
1835      NotificationType::EXTENSION_BACKGROUND_PAGE_READY,
1836      Source<const Extension>(extension),
1837      NotificationService::NoDetails());
1838}
1839
1840bool ExtensionService::IsBeingUpgraded(const Extension* extension) {
1841  return extension_runtime_data_[extension->id()].being_upgraded;
1842}
1843
1844void ExtensionService::SetBeingUpgraded(const Extension* extension,
1845                                         bool value) {
1846  extension_runtime_data_[extension->id()].being_upgraded = value;
1847}
1848
1849PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) {
1850  return &extension_runtime_data_[extension->id()].property_bag;
1851}
1852