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