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