extension_service.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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/values.h"
28#include "base/version.h"
29#include "chrome/browser/app_mode/app_mode_utils.h"
30#include "chrome/browser/browser_process.h"
31#include "chrome/browser/chrome_notification_types.h"
32#include "chrome/browser/extensions/api/app_runtime/app_runtime_api.h"
33#include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
34#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
35#include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
36#include "chrome/browser/extensions/api/runtime/runtime_api.h"
37#include "chrome/browser/extensions/api/storage/settings_frontend.h"
38#include "chrome/browser/extensions/app_sync_data.h"
39#include "chrome/browser/extensions/component_loader.h"
40#include "chrome/browser/extensions/crx_installer.h"
41#include "chrome/browser/extensions/data_deleter.h"
42#include "chrome/browser/extensions/event_router.h"
43#include "chrome/browser/extensions/extension_disabled_ui.h"
44#include "chrome/browser/extensions/extension_error_reporter.h"
45#include "chrome/browser/extensions/extension_error_ui.h"
46#include "chrome/browser/extensions/extension_host.h"
47#include "chrome/browser/extensions/extension_install_ui.h"
48#include "chrome/browser/extensions/extension_process_manager.h"
49#include "chrome/browser/extensions/extension_sorting.h"
50#include "chrome/browser/extensions/extension_special_storage_policy.h"
51#include "chrome/browser/extensions/extension_sync_data.h"
52#include "chrome/browser/extensions/extension_system.h"
53#include "chrome/browser/extensions/external_install_ui.h"
54#include "chrome/browser/extensions/external_provider_impl.h"
55#include "chrome/browser/extensions/external_provider_interface.h"
56#include "chrome/browser/extensions/installed_loader.h"
57#include "chrome/browser/extensions/management_policy.h"
58#include "chrome/browser/extensions/pending_extension_manager.h"
59#include "chrome/browser/extensions/permissions_updater.h"
60#include "chrome/browser/extensions/unpacked_installer.h"
61#include "chrome/browser/extensions/update_observer.h"
62#include "chrome/browser/extensions/updater/extension_updater.h"
63#include "chrome/browser/profiles/profile.h"
64#include "chrome/browser/profiles/profile_manager.h"
65#include "chrome/browser/ui/webui/favicon_source.h"
66#include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
67#include "chrome/browser/ui/webui/theme_source.h"
68#include "chrome/common/chrome_switches.h"
69#include "chrome/common/chrome_version_info.h"
70#include "chrome/common/crash_keys.h"
71#include "chrome/common/extensions/background_info.h"
72#include "chrome/common/extensions/extension.h"
73#include "chrome/common/extensions/extension_constants.h"
74#include "chrome/common/extensions/extension_file_util.h"
75#include "chrome/common/extensions/extension_manifest_constants.h"
76#include "chrome/common/extensions/extension_messages.h"
77#include "chrome/common/extensions/feature_switch.h"
78#include "chrome/common/extensions/features/feature_channel.h"
79#include "chrome/common/extensions/incognito_handler.h"
80#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
81#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
82#include "chrome/common/extensions/manifest_handlers/shared_module_info.h"
83#include "chrome/common/extensions/manifest_url_handler.h"
84#include "chrome/common/extensions/permissions/permissions_data.h"
85#include "chrome/common/extensions/sync_helper.h"
86#include "chrome/common/pref_names.h"
87#include "chrome/common/url_constants.h"
88#include "components/startup_metric_utils/startup_metric_utils.h"
89#include "content/public/browser/browser_thread.h"
90#include "content/public/browser/devtools_agent_host.h"
91#include "content/public/browser/notification_service.h"
92#include "content/public/browser/notification_types.h"
93#include "content/public/browser/render_process_host.h"
94#include "content/public/browser/site_instance.h"
95#include "content/public/browser/storage_partition.h"
96#include "content/public/browser/url_data_source.h"
97#include "extensions/common/constants.h"
98#include "extensions/common/error_utils.h"
99#include "extensions/common/manifest.h"
100#include "grit/generated_resources.h"
101#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
102#include "sync/api/sync_change.h"
103#include "sync/api/sync_error_factory.h"
104#include "ui/webui/web_ui_util.h"
105#include "url/gurl.h"
106#include "webkit/browser/database/database_tracker.h"
107#include "webkit/browser/database/database_util.h"
108
109#if defined(OS_CHROMEOS)
110#include "chrome/browser/chromeos/extensions/install_limiter.h"
111#include "webkit/browser/fileapi/file_system_backend.h"
112#include "webkit/browser/fileapi/file_system_context.h"
113#endif
114
115using content::BrowserContext;
116using content::BrowserThread;
117using content::DevToolsAgentHost;
118using extensions::CrxInstaller;
119using extensions::Extension;
120using extensions::ExtensionIdSet;
121using extensions::ExtensionInfo;
122using extensions::FeatureSwitch;
123using extensions::Manifest;
124using extensions::PermissionMessage;
125using extensions::PermissionMessages;
126using extensions::PermissionSet;
127using extensions::SharedModuleInfo;
128using extensions::UnloadedExtensionInfo;
129
130namespace errors = extension_manifest_errors;
131
132namespace {
133
134// Histogram values for logging events related to externally installed
135// extensions.
136enum ExternalExtensionEvent {
137  EXTERNAL_EXTENSION_INSTALLED = 0,
138  EXTERNAL_EXTENSION_IGNORED,
139  EXTERNAL_EXTENSION_REENABLED,
140  EXTERNAL_EXTENSION_UNINSTALLED,
141  EXTERNAL_EXTENSION_BUCKET_BOUNDARY,
142};
143
144// Prompt the user this many times before considering an extension acknowledged.
145static const int kMaxExtensionAcknowledgePromptCount = 3;
146
147// Wait this many seconds after an extensions becomes idle before updating it.
148static const int kUpdateIdleDelay = 5;
149
150// Wait this many seconds before trying to garbage collect extensions again.
151static const int kGarbageCollectRetryDelay = 30;
152
153// Wait this many seconds after startup to see if there are any extensions
154// which can be garbage collected.
155static const int kGarbageCollectStartupDelay = 30;
156
157static bool IsSharedModule(const Extension* extension) {
158  return SharedModuleInfo::IsSharedModule(extension);
159}
160
161static bool IsCWSSharedModule(const Extension* extension) {
162  return extension->from_webstore() && IsSharedModule(extension);
163}
164
165class SharedModuleProvider : public extensions::ManagementPolicy::Provider {
166 public:
167  SharedModuleProvider() {}
168  virtual ~SharedModuleProvider() {}
169
170  virtual std::string GetDebugPolicyProviderName() const OVERRIDE {
171    return "SharedModuleProvider";
172  }
173
174  virtual bool UserMayModifySettings(const Extension* extension,
175                                     string16* error) const OVERRIDE {
176    return !IsCWSSharedModule(extension);
177  }
178
179  virtual bool MustRemainEnabled(const Extension* extension,
180                                 string16* error) const OVERRIDE {
181    return IsCWSSharedModule(extension);
182  }
183
184 private:
185  DISALLOW_COPY_AND_ASSIGN(SharedModuleProvider);
186};
187
188
189}  // namespace
190
191ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData()
192    : background_page_ready(false),
193      being_upgraded(false),
194      has_used_webrequest(false) {
195}
196
197ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() {
198}
199
200// ExtensionService.
201
202const char ExtensionService::kLocalAppSettingsDirectoryName[] =
203    "Local App Settings";
204const char ExtensionService::kLocalExtensionSettingsDirectoryName[] =
205    "Local Extension Settings";
206const char ExtensionService::kSyncAppSettingsDirectoryName[] =
207    "Sync App Settings";
208const char ExtensionService::kSyncExtensionSettingsDirectoryName[] =
209    "Sync Extension Settings";
210const char ExtensionService::kManagedSettingsDirectoryName[] =
211    "Managed Extension Settings";
212const char ExtensionService::kStateStoreName[] = "Extension State";
213const char ExtensionService::kRulesStoreName[] = "Extension Rules";
214
215void ExtensionService::CheckExternalUninstall(const std::string& id) {
216  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
217
218  // Check if the providers know about this extension.
219  extensions::ProviderCollection::const_iterator i;
220  for (i = external_extension_providers_.begin();
221       i != external_extension_providers_.end(); ++i) {
222    DCHECK(i->get()->IsReady());
223    if (i->get()->HasExtension(id))
224      return;  // Yup, known extension, don't uninstall.
225  }
226
227  // We get the list of external extensions to check from preferences.
228  // It is possible that an extension has preferences but is not loaded.
229  // For example, an extension that requires experimental permissions
230  // will not be loaded if the experimental command line flag is not used.
231  // In this case, do not uninstall.
232  if (!GetInstalledExtension(id)) {
233    // We can't call UninstallExtension with an unloaded/invalid
234    // extension ID.
235    LOG(WARNING) << "Attempted uninstallation of unloaded/invalid extension "
236                 << "with id: " << id;
237    return;
238  }
239  UninstallExtension(id, true, NULL);
240}
241
242void ExtensionService::SetFileTaskRunnerForTesting(
243    base::SequencedTaskRunner* task_runner) {
244  file_task_runner_ = task_runner;
245}
246
247void ExtensionService::ClearProvidersForTesting() {
248  external_extension_providers_.clear();
249}
250
251void ExtensionService::AddProviderForTesting(
252    extensions::ExternalProviderInterface* test_provider) {
253  CHECK(test_provider);
254  external_extension_providers_.push_back(
255      linked_ptr<extensions::ExternalProviderInterface>(test_provider));
256}
257
258bool ExtensionService::OnExternalExtensionUpdateUrlFound(
259    const std::string& id,
260    const GURL& update_url,
261    Manifest::Location location) {
262  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263  CHECK(Extension::IdIsValid(id));
264
265  const Extension* extension = GetExtensionById(id, true);
266  if (extension) {
267    // Already installed. Skip this install if the current location has
268    // higher priority than |location|.
269    Manifest::Location current = extension->location();
270    if (current == Manifest::GetHigherPriorityLocation(current, location))
271      return false;
272    // Otherwise, overwrite the current installation.
273  }
274
275  // Add |id| to the set of pending extensions.  If it can not be added,
276  // then there is already a pending record from a higher-priority install
277  // source.  In this case, signal that this extension will not be
278  // installed by returning false.
279  if (!pending_extension_manager()->AddFromExternalUpdateUrl(
280          id, update_url, location)) {
281    return false;
282  }
283
284  update_once_all_providers_are_ready_ = true;
285  return true;
286}
287
288const Extension* ExtensionService::GetInstalledApp(const GURL& url) const {
289  const Extension* extension = extensions_.GetExtensionOrAppByURL(url);
290  return (extension && extension->is_app()) ? extension : NULL;
291}
292
293bool ExtensionService::IsInstalledApp(const GURL& url) const {
294  return !!GetInstalledApp(url);
295}
296
297const Extension* ExtensionService::GetIsolatedAppForRenderer(
298    int renderer_child_id) const {
299  std::set<std::string> extension_ids =
300      process_map_.GetExtensionsInProcess(renderer_child_id);
301  // All apps in one process share the same partition.
302  // It is only possible for the app to have isolated storage
303  // if there is only 1 app in the process.
304  if (extension_ids.size() != 1)
305    return NULL;
306
307  const extensions::Extension* extension =
308      extensions_.GetByID(*(extension_ids.begin()));
309  // We still need to check if the extension has isolated storage,
310  // because it's common for there to be one extension in a process
311  // without isolated storage.
312  if (extension &&
313      extensions::AppIsolationInfo::HasIsolatedStorage(extension))
314    return extension;
315
316  return NULL;
317}
318
319// static
320// This function is used to implement the command-line switch
321// --uninstall-extension, and to uninstall an extension via sync.  The LOG
322// statements within this function are used to inform the user if the uninstall
323// cannot be done.
324bool ExtensionService::UninstallExtensionHelper(
325    ExtensionService* extensions_service,
326    const std::string& extension_id) {
327  // We can't call UninstallExtension with an invalid extension ID.
328  if (!extensions_service->GetInstalledExtension(extension_id)) {
329    LOG(WARNING) << "Attempted uninstallation of non-existent extension with "
330                 << "id: " << extension_id;
331    return false;
332  }
333
334  // The following call to UninstallExtension will not allow an uninstall of a
335  // policy-controlled extension.
336  string16 error;
337  if (!extensions_service->UninstallExtension(extension_id, false, &error)) {
338    LOG(WARNING) << "Cannot uninstall extension with id " << extension_id
339                 << ": " << error;
340    return false;
341  }
342
343  return true;
344}
345
346ExtensionService::ExtensionService(Profile* profile,
347                                   const CommandLine* command_line,
348                                   const base::FilePath& install_directory,
349                                   extensions::ExtensionPrefs* extension_prefs,
350                                   extensions::Blacklist* blacklist,
351                                   bool autoupdate_enabled,
352                                   bool extensions_enabled,
353                                   extensions::OneShotEvent* ready)
354    : extensions::Blacklist::Observer(blacklist),
355      profile_(profile),
356      system_(extensions::ExtensionSystem::Get(profile)),
357      extension_prefs_(extension_prefs),
358      blacklist_(blacklist),
359      settings_frontend_(extensions::SettingsFrontend::Create(profile)),
360      pending_extension_manager_(*this),
361      install_directory_(install_directory),
362      extensions_enabled_(extensions_enabled),
363      show_extensions_prompts_(true),
364      install_updates_when_idle_(true),
365      ready_(ready),
366      toolbar_model_(this),
367      menu_manager_(profile),
368      update_once_all_providers_are_ready_(false),
369      browser_terminating_(false),
370      installs_delayed_for_gc_(false),
371      is_first_run_(false),
372      app_sync_bundle_(this),
373      extension_sync_bundle_(this) {
374#if defined(OS_CHROMEOS)
375  disable_garbage_collection_ = false;
376#endif
377  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
378
379  // Figure out if extension installation should be enabled.
380  if (command_line->HasSwitch(switches::kDisableExtensions) ||
381      profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) {
382    extensions_enabled_ = false;
383  }
384
385  registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
386                 content::NotificationService::AllBrowserContextsAndSources());
387  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
388                 content::NotificationService::AllBrowserContextsAndSources());
389  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
390                 content::NotificationService::AllBrowserContextsAndSources());
391  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
392                 content::NotificationService::AllBrowserContextsAndSources());
393  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
394                 content::NotificationService::AllBrowserContextsAndSources());
395  registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
396                 content::NotificationService::AllBrowserContextsAndSources());
397  pref_change_registrar_.Init(profile->GetPrefs());
398  base::Closure callback =
399      base::Bind(&ExtensionService::OnExtensionInstallPrefChanged,
400                 base::Unretained(this));
401  pref_change_registrar_.Add(prefs::kExtensionInstallAllowList, callback);
402  pref_change_registrar_.Add(prefs::kExtensionInstallDenyList, callback);
403  pref_change_registrar_.Add(prefs::kExtensionAllowedTypes, callback);
404
405  // Set up the ExtensionUpdater
406  if (autoupdate_enabled) {
407    int update_frequency = kDefaultUpdateFrequencySeconds;
408    if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) {
409      base::StringToInt(command_line->GetSwitchValueASCII(
410          switches::kExtensionsUpdateFrequency),
411          &update_frequency);
412    }
413    updater_.reset(new extensions::ExtensionUpdater(this,
414                                                    extension_prefs,
415                                                    profile->GetPrefs(),
416                                                    profile,
417                                                    blacklist,
418                                                    update_frequency));
419  }
420
421  component_loader_.reset(
422      new extensions::ComponentLoader(this,
423                                      profile->GetPrefs(),
424                                      g_browser_process->local_state()));
425
426  if (extensions_enabled_) {
427    extensions::ExternalProviderImpl::CreateExternalProviders(
428        this, profile_, &external_extension_providers_);
429  }
430
431  // Set this as the ExtensionService for extension sorting to ensure it
432  // cause syncs if required.
433  extension_prefs_->extension_sorting()->SetExtensionService(this);
434
435  is_first_run_ = !extension_prefs_->SetAlertSystemFirstRun();
436
437#if defined(ENABLE_EXTENSIONS)
438  extension_action_storage_manager_.reset(
439      new extensions::ExtensionActionStorageManager(profile_));
440#endif
441
442  shared_module_policy_provider_.reset(new SharedModuleProvider);
443
444  // How long is the path to the Extensions directory?
445  UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ExtensionRootPathLength",
446                              install_directory_.value().length(), 0, 500, 100);
447}
448
449const ExtensionSet* ExtensionService::extensions() const {
450  return &extensions_;
451}
452
453const ExtensionSet* ExtensionService::disabled_extensions() const {
454  return &disabled_extensions_;
455}
456
457const ExtensionSet* ExtensionService::terminated_extensions() const {
458  return &terminated_extensions_;
459}
460
461const ExtensionSet* ExtensionService::blacklisted_extensions() const {
462  return &blacklisted_extensions_;
463}
464
465const ExtensionSet* ExtensionService::delayed_installs() const {
466  return &delayed_installs_;
467}
468
469scoped_ptr<const ExtensionSet>
470    ExtensionService::GenerateInstalledExtensionsSet() const {
471  scoped_ptr<ExtensionSet> installed_extensions(new ExtensionSet());
472  installed_extensions->InsertAll(extensions_);
473  installed_extensions->InsertAll(disabled_extensions_);
474  installed_extensions->InsertAll(terminated_extensions_);
475  installed_extensions->InsertAll(blacklisted_extensions_);
476  return installed_extensions.PassAs<const ExtensionSet>();
477}
478
479extensions::PendingExtensionManager*
480    ExtensionService::pending_extension_manager() {
481  return &pending_extension_manager_;
482}
483
484ExtensionService::~ExtensionService() {
485  // No need to unload extensions here because they are profile-scoped, and the
486  // profile is in the process of being deleted.
487
488  extensions::ProviderCollection::const_iterator i;
489  for (i = external_extension_providers_.begin();
490       i != external_extension_providers_.end(); ++i) {
491    extensions::ExternalProviderInterface* provider = i->get();
492    provider->ServiceShutdown();
493  }
494}
495
496void ExtensionService::SetSyncStartFlare(
497    const syncer::SyncableService::StartSyncFlare& flare) {
498  flare_ = flare;
499}
500
501void ExtensionService::Shutdown() {
502  system_->management_policy()->UnregisterProvider(
503      shared_module_policy_provider_.get());
504}
505
506const Extension* ExtensionService::GetExtensionById(
507    const std::string& id, bool include_disabled) const {
508  int include_mask = INCLUDE_ENABLED;
509  if (include_disabled) {
510    // Include blacklisted extensions here because there are hundreds of
511    // callers of this function, and many might assume that this includes those
512    // that have been disabled due to blacklisting.
513    include_mask |= INCLUDE_DISABLED | INCLUDE_BLACKLISTED;
514  }
515  return GetExtensionById(id, include_mask);
516}
517
518GURL ExtensionService::GetSiteForExtensionId(const std::string& extension_id) {
519  return content::SiteInstance::GetSiteForURL(
520      profile_,
521      Extension::GetBaseURLFromExtensionId(extension_id));
522}
523
524const Extension* ExtensionService::GetExtensionById(
525    const std::string& id, int include_mask) const {
526  std::string lowercase_id = StringToLowerASCII(id);
527  if (include_mask & INCLUDE_ENABLED) {
528    const Extension* extension = extensions_.GetByID(lowercase_id);
529    if (extension)
530      return extension;
531  }
532  if (include_mask & INCLUDE_DISABLED) {
533    const Extension* extension = disabled_extensions_.GetByID(lowercase_id);
534    if (extension)
535      return extension;
536  }
537  if (include_mask & INCLUDE_TERMINATED) {
538    const Extension* extension = terminated_extensions_.GetByID(lowercase_id);
539    if (extension)
540      return extension;
541  }
542  if (include_mask & INCLUDE_BLACKLISTED) {
543    const Extension* extension = blacklisted_extensions_.GetByID(lowercase_id);
544    if (extension)
545      return extension;
546  }
547  return NULL;
548}
549
550void ExtensionService::Init() {
551  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
552
553  DCHECK(!is_ready());  // Can't redo init.
554  DCHECK_EQ(extensions_.size(), 0u);
555
556  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
557  if (cmd_line->HasSwitch(switches::kInstallFromWebstore) ||
558      cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) {
559    // The sole purpose of this launch is to install a new extension from CWS
560    // and immediately terminate: loading already installed extensions is
561    // unnecessary and may interfere with the inline install dialog (e.g. if an
562    // extension listens to onStartup and opens a window).
563    SetReadyAndNotifyListeners();
564  } else {
565    // LoadAllExtensions() calls OnLoadedInstalledExtensions().
566    component_loader_->LoadAll();
567    extensions::InstalledLoader(this).LoadAllExtensions();
568
569    // Attempt to re-enable extensions whose only disable reason is reloading.
570    std::vector<std::string> extensions_to_enable;
571    for (ExtensionSet::const_iterator iter = disabled_extensions_.begin();
572        iter != disabled_extensions_.end(); ++iter) {
573      const Extension* e = iter->get();
574      if (extension_prefs_->GetDisableReasons(e->id()) ==
575          Extension::DISABLE_RELOAD) {
576        extensions_to_enable.push_back(e->id());
577      }
578    }
579    for (std::vector<std::string>::iterator it = extensions_to_enable.begin();
580         it != extensions_to_enable.end(); ++it) {
581      EnableExtension(*it);
582    }
583
584    // Finish install (if possible) of extensions that were still delayed while
585    // the browser was shut down.
586    scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info(
587        extension_prefs_->GetAllDelayedInstallInfo());
588    for (size_t i = 0; i < delayed_info->size(); ++i) {
589      ExtensionInfo* info = delayed_info->at(i).get();
590      scoped_refptr<const Extension> extension(NULL);
591      if (info->extension_manifest) {
592        std::string error;
593        extension = Extension::Create(
594            info->extension_path,
595            info->extension_location,
596            *info->extension_manifest,
597            extension_prefs_->GetDelayedInstallCreationFlags(
598                info->extension_id),
599            info->extension_id,
600            &error);
601        if (extension.get())
602          delayed_installs_.Insert(extension);
603      }
604    }
605    MaybeFinishDelayedInstallations();
606
607    scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2(
608        extension_prefs_->GetAllDelayedInstallInfo());
609    UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad",
610                             delayed_info2->size() - delayed_info->size());
611
612    SetReadyAndNotifyListeners();
613
614    // TODO(erikkay) this should probably be deferred to a future point
615    // rather than running immediately at startup.
616    CheckForExternalUpdates();
617
618    base::MessageLoop::current()->PostDelayedTask(
619        FROM_HERE,
620        base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()),
621        base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay));
622
623    if (extension_prefs_->NeedsStorageGarbageCollection()) {
624      GarbageCollectIsolatedStorage();
625      extension_prefs_->SetNeedsStorageGarbageCollection(false);
626    }
627    system_->management_policy()->RegisterProvider(
628        shared_module_policy_provider_.get());
629  }
630}
631
632bool ExtensionService::UpdateExtension(const std::string& id,
633                                       const base::FilePath& extension_path,
634                                       const GURL& download_url,
635                                       CrxInstaller** out_crx_installer) {
636  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
637  if (browser_terminating_) {
638    LOG(WARNING) << "Skipping UpdateExtension due to browser shutdown";
639    // Leak the temp file at extension_path. We don't want to add to the disk
640    // I/O burden at shutdown, we can't rely on the I/O completing anyway, and
641    // the file is in the OS temp directory which should be cleaned up for us.
642    return false;
643  }
644
645  const extensions::PendingExtensionInfo* pending_extension_info =
646      pending_extension_manager()->GetById(id);
647
648  const Extension* extension = GetInstalledExtension(id);
649  if (!pending_extension_info && !extension) {
650    LOG(WARNING) << "Will not update extension " << id
651                 << " because it is not installed or pending";
652    // Delete extension_path since we're not creating a CrxInstaller
653    // that would do it for us.
654    if (!GetFileTaskRunner()->PostTask(
655            FROM_HERE,
656            base::Bind(
657                &extension_file_util::DeleteFile, extension_path, false)))
658      NOTREACHED();
659
660    return false;
661  }
662
663  // We want a silent install only for non-pending extensions and
664  // pending extensions that have install_silently set.
665  scoped_ptr<ExtensionInstallPrompt> client;
666  if (pending_extension_info && !pending_extension_info->install_silently())
667    client.reset(ExtensionInstallUI::CreateInstallPromptWithProfile(profile_));
668
669  scoped_refptr<CrxInstaller> installer(
670      CrxInstaller::Create(this, client.Pass()));
671  installer->set_expected_id(id);
672  if (pending_extension_info) {
673    installer->set_install_source(pending_extension_info->install_source());
674    if (pending_extension_info->install_silently())
675      installer->set_allow_silent_install(true);
676  } else if (extension) {
677    installer->set_install_source(extension->location());
678  }
679  // If the extension was installed from or has migrated to the webstore, or
680  // its auto-update URL is from the webstore, treat it as a webstore install.
681  // Note that we ignore some older extensions with blank auto-update URLs
682  // because we are mostly concerned with restrictions on NaCl extensions,
683  // which are newer.
684  int creation_flags = Extension::NO_FLAGS;
685  if ((extension && extension->from_webstore()) ||
686      (extension && extensions::ManifestURL::UpdatesFromGallery(extension)) ||
687      (!extension && extension_urls::IsWebstoreUpdateUrl(
688           pending_extension_info->update_url()))) {
689    creation_flags |= Extension::FROM_WEBSTORE;
690  }
691
692  // Bookmark apps being updated is kind of a contradiction, but that's because
693  // we mark the default apps as bookmark apps, and they're hosted in the web
694  // store, thus they can get updated. See http://crbug.com/101605 for more
695  // details.
696  if (extension && extension->from_bookmark())
697    creation_flags |= Extension::FROM_BOOKMARK;
698
699  if (extension && extension->was_installed_by_default())
700    creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT;
701
702  installer->set_creation_flags(creation_flags);
703
704  installer->set_delete_source(true);
705  installer->set_download_url(download_url);
706  installer->set_install_cause(extension_misc::INSTALL_CAUSE_UPDATE);
707  installer->InstallCrx(extension_path);
708
709  if (out_crx_installer)
710    *out_crx_installer = installer.get();
711
712  return true;
713}
714
715void ExtensionService::ReloadExtension(const std::string extension_id) {
716  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
717
718  // If the extension is already reloading, don't reload again.
719  if (extension_prefs_->GetDisableReasons(extension_id) &
720      Extension::DISABLE_RELOAD) {
721    return;
722  }
723
724  base::FilePath path;
725  const Extension* current_extension = GetExtensionById(extension_id, false);
726
727  // Disable the extension if it's loaded. It might not be loaded if it crashed.
728  if (current_extension) {
729    // If the extension has an inspector open for its background page, detach
730    // the inspector and hang onto a cookie for it, so that we can reattach
731    // later.
732    // TODO(yoz): this is not incognito-safe!
733    ExtensionProcessManager* manager = system_->process_manager();
734    extensions::ExtensionHost* host =
735        manager->GetBackgroundHostForExtension(extension_id);
736    if (host && DevToolsAgentHost::HasFor(host->render_view_host())) {
737      // Look for an open inspector for the background page.
738      scoped_refptr<DevToolsAgentHost> agent_host =
739          DevToolsAgentHost::GetOrCreateFor(host->render_view_host());
740      agent_host->DisconnectRenderViewHost();
741      orphaned_dev_tools_[extension_id] = agent_host;
742    }
743
744    path = current_extension->path();
745    // BeingUpgraded is set back to false when the extension is added.
746    SetBeingUpgraded(current_extension, true);
747    DisableExtension(extension_id, Extension::DISABLE_RELOAD);
748    reloading_extensions_.insert(extension_id);
749  } else {
750    path = unloaded_extension_paths_[extension_id];
751  }
752
753  if (delayed_installs_.Contains(extension_id)) {
754    FinishDelayedInstallation(extension_id);
755    return;
756  }
757
758  // If we're reloading a component extension, use the component extension
759  // loader's reloader.
760  if (component_loader_->Exists(extension_id)) {
761    SetBeingReloaded(extension_id, true);
762    component_loader_->Reload(extension_id);
763    SetBeingReloaded(extension_id, false);
764    return;
765  }
766
767  // Check the installed extensions to see if what we're reloading was already
768  // installed.
769  SetBeingReloaded(extension_id, true);
770  scoped_ptr<ExtensionInfo> installed_extension(
771      extension_prefs_->GetInstalledExtensionInfo(extension_id));
772  if (installed_extension.get() &&
773      installed_extension->extension_manifest.get()) {
774    extensions::InstalledLoader(this).Load(*installed_extension, false);
775  } else {
776    // Otherwise, the extension is unpacked (location LOAD).
777    // We should always be able to remember the extension's path. If it's not in
778    // the map, someone failed to update |unloaded_extension_paths_|.
779    CHECK(!path.empty());
780    extensions::UnpackedInstaller::Create(this)->Load(path);
781  }
782  // When reloading is done, mark this extension as done reloading.
783  SetBeingReloaded(extension_id, false);
784}
785
786bool ExtensionService::UninstallExtension(
787    std::string extension_id,
788    bool external_uninstall,
789    string16* error) {
790  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
791
792  scoped_refptr<const Extension> extension(GetInstalledExtension(extension_id));
793
794  // Callers should not send us nonexistent extensions.
795  CHECK(extension.get());
796
797  // Policy change which triggers an uninstall will always set
798  // |external_uninstall| to true so this is the only way to uninstall
799  // managed extensions.
800  if (!external_uninstall &&
801      !system_->management_policy()->UserMayModifySettings(
802        extension.get(), error)) {
803    content::NotificationService::current()->Notify(
804        chrome::NOTIFICATION_EXTENSION_UNINSTALL_NOT_ALLOWED,
805        content::Source<Profile>(profile_),
806        content::Details<const Extension>(extension.get()));
807    return false;
808  }
809
810  // Extract the data we need for sync now, but don't actually sync until we've
811  // completed the uninstallation.
812  // TODO(tim): If we get here and IsSyncing is false, this will cause
813  // "back from the dead" style bugs, because sync will add-back the extension
814  // that was uninstalled here when MergeDataAndStartSyncing is called.
815  // See crbug.com/256795.
816  syncer::SyncChange sync_change;
817  if (extensions::sync_helper::IsSyncableApp(extension.get())) {
818    if (app_sync_bundle_.IsSyncing())
819      sync_change = app_sync_bundle_.CreateSyncChangeToDelete(extension.get());
820    else if (is_ready() && !flare_.is_null())
821      flare_.Run(syncer::APPS);  // Tell sync to start ASAP.
822  } else if (extensions::sync_helper::IsSyncableExtension(extension.get())) {
823    if (extension_sync_bundle_.IsSyncing())
824      sync_change = extension_sync_bundle_.CreateSyncChangeToDelete(extension);
825    else if (is_ready() && !flare_.is_null())
826      flare_.Run(syncer::EXTENSIONS);  // Tell sync to start ASAP.
827  }
828
829  if (IsUnacknowledgedExternalExtension(extension.get())) {
830    UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
831                              EXTERNAL_EXTENSION_UNINSTALLED,
832                              EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
833    if (extensions::ManifestURL::UpdatesFromGallery(extension.get())) {
834      UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventWebstore",
835                                EXTERNAL_EXTENSION_UNINSTALLED,
836                                EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
837    } else {
838      UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventNonWebstore",
839                                EXTERNAL_EXTENSION_UNINSTALLED,
840                                EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
841    }
842  }
843  UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType",
844                            extension->GetType(), 100);
845  RecordPermissionMessagesHistogram(extension.get(),
846                                    "Extensions.Permissions_Uninstall");
847
848  // Unload before doing more cleanup to ensure that nothing is hanging on to
849  // any of these resources.
850  UnloadExtension(extension_id, extension_misc::UNLOAD_REASON_UNINSTALL);
851
852  extension_prefs_->OnExtensionUninstalled(extension_id, extension->location(),
853                                           external_uninstall);
854
855  // Tell the backend to start deleting installed extensions on the file thread.
856  if (!Manifest::IsUnpackedLocation(extension->location())) {
857    if (!GetFileTaskRunner()->PostTask(
858            FROM_HERE,
859            base::Bind(
860                &extension_file_util::UninstallExtension,
861                install_directory_,
862                extension_id)))
863      NOTREACHED();
864  }
865
866  GURL launch_web_url_origin(
867      extensions::AppLaunchInfo::GetLaunchWebURL(extension.get()).GetOrigin());
868  bool is_storage_isolated =
869      extensions::AppIsolationInfo::HasIsolatedStorage(extension.get());
870
871  if (is_storage_isolated) {
872    BrowserContext::AsyncObliterateStoragePartition(
873        profile_,
874        GetSiteForExtensionId(extension_id),
875        base::Bind(&ExtensionService::OnNeedsToGarbageCollectIsolatedStorage,
876                   AsWeakPtr()));
877  } else {
878    if (extension->is_hosted_app() &&
879        !profile_->GetExtensionSpecialStoragePolicy()->
880            IsStorageProtected(launch_web_url_origin)) {
881      extensions::DataDeleter::StartDeleting(
882          profile_, extension_id, launch_web_url_origin);
883    }
884    extensions::DataDeleter::StartDeleting(profile_, extension_id,
885                                           extension->url());
886  }
887
888  UntrackTerminatedExtension(extension_id);
889
890  // Notify interested parties that we've uninstalled this extension.
891  content::NotificationService::current()->Notify(
892      chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
893      content::Source<Profile>(profile_),
894      content::Details<const Extension>(extension.get()));
895
896  if (app_sync_bundle_.HasExtensionId(extension_id) &&
897      sync_change.sync_data().GetDataType() == syncer::APPS) {
898    app_sync_bundle_.ProcessDeletion(extension_id, sync_change);
899  } else if (extension_sync_bundle_.HasExtensionId(extension_id) &&
900             sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) {
901    extension_sync_bundle_.ProcessDeletion(extension_id, sync_change);
902  }
903
904  delayed_installs_.Remove(extension_id);
905
906  PruneSharedModulesOnUninstall(extension.get());
907
908  // Track the uninstallation.
909  UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2);
910
911  return true;
912}
913
914bool ExtensionService::IsExtensionEnabled(
915    const std::string& extension_id) const {
916  if (extensions_.Contains(extension_id) ||
917      terminated_extensions_.Contains(extension_id)) {
918    return true;
919  }
920
921  if (disabled_extensions_.Contains(extension_id) ||
922      blacklisted_extensions_.Contains(extension_id)) {
923    return false;
924  }
925
926  // If the extension hasn't been loaded yet, check the prefs for it. Assume
927  // enabled unless otherwise noted.
928  return !extension_prefs_->IsExtensionDisabled(extension_id) &&
929         !extension_prefs_->IsExternalExtensionUninstalled(extension_id);
930}
931
932bool ExtensionService::IsExternalExtensionUninstalled(
933    const std::string& extension_id) const {
934  return extension_prefs_->IsExternalExtensionUninstalled(extension_id);
935}
936
937bool ExtensionService::IsExtensionEnabledForLauncher(
938    const std::string& extension_id) const {
939  return IsExtensionEnabled(extension_id) &&
940      !GetTerminatedExtension(extension_id);
941}
942
943void ExtensionService::EnableExtension(const std::string& extension_id) {
944  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
945
946  if (IsExtensionEnabled(extension_id))
947    return;
948
949  extension_prefs_->SetExtensionState(extension_id, Extension::ENABLED);
950  extension_prefs_->ClearDisableReasons(extension_id);
951
952  const Extension* extension = disabled_extensions_.GetByID(extension_id);
953  // This can happen if sync enables an extension that is not
954  // installed yet.
955  if (!extension)
956    return;
957
958  if (IsUnacknowledgedExternalExtension(extension)) {
959    UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
960                              EXTERNAL_EXTENSION_REENABLED,
961                              EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
962    if (extensions::ManifestURL::UpdatesFromGallery(extension)) {
963      UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventWebstore",
964                                EXTERNAL_EXTENSION_REENABLED,
965                                EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
966    } else {
967      UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventNonWebstore",
968                                EXTERNAL_EXTENSION_REENABLED,
969                                EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
970    }
971    AcknowledgeExternalExtension(extension->id());
972  }
973
974  // Move it over to the enabled list.
975  extensions_.Insert(make_scoped_refptr(extension));
976  disabled_extensions_.Remove(extension->id());
977
978  NotifyExtensionLoaded(extension);
979
980  // Notify listeners that the extension was enabled.
981  content::NotificationService::current()->Notify(
982      chrome::NOTIFICATION_EXTENSION_ENABLED,
983      content::Source<Profile>(profile_),
984      content::Details<const Extension>(extension));
985
986  SyncExtensionChangeIfNeeded(*extension);
987}
988
989void ExtensionService::DisableExtension(
990    const std::string& extension_id,
991    Extension::DisableReason disable_reason) {
992  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
993
994  // The extension may have been disabled already.
995  if (!IsExtensionEnabled(extension_id))
996    return;
997
998  const Extension* extension = GetInstalledExtension(extension_id);
999  // |extension| can be NULL if sync disables an extension that is not
1000  // installed yet.
1001  if (extension &&
1002      disable_reason != Extension::DISABLE_RELOAD &&
1003      !system_->management_policy()->UserMayModifySettings(extension, NULL)) {
1004    return;
1005  }
1006
1007  extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED);
1008  extension_prefs_->AddDisableReason(extension_id, disable_reason);
1009
1010  int include_mask = INCLUDE_EVERYTHING & ~INCLUDE_DISABLED;
1011  extension = GetExtensionById(extension_id, include_mask);
1012  if (!extension)
1013    return;
1014
1015  // Reset the background_page_ready flag
1016  if (extensions::BackgroundInfo::HasBackgroundPage(extension))
1017    extension_runtime_data_[extension->id()].background_page_ready = false;
1018
1019  // Move it over to the disabled list. Don't send a second unload notification
1020  // for terminated extensions being disabled.
1021  disabled_extensions_.Insert(make_scoped_refptr(extension));
1022  if (extensions_.Contains(extension->id())) {
1023    extensions_.Remove(extension->id());
1024    NotifyExtensionUnloaded(extension, extension_misc::UNLOAD_REASON_DISABLE);
1025  } else {
1026    terminated_extensions_.Remove(extension->id());
1027  }
1028
1029  SyncExtensionChangeIfNeeded(*extension);
1030}
1031
1032void ExtensionService::DisableUserExtensions(
1033    const std::vector<std::string>& except_ids) {
1034  extensions::ManagementPolicy* management_policy =
1035      system_->management_policy();
1036  extensions::ExtensionList to_disable;
1037
1038  for (ExtensionSet::const_iterator extension = extensions_.begin();
1039      extension != extensions_.end(); ++extension) {
1040    if (management_policy->UserMayModifySettings(extension->get(), NULL))
1041      to_disable.push_back(*extension);
1042  }
1043  for (ExtensionSet::const_iterator extension = terminated_extensions_.begin();
1044      extension != terminated_extensions_.end(); ++extension) {
1045    if (management_policy->UserMayModifySettings(extension->get(), NULL))
1046      to_disable.push_back(*extension);
1047  }
1048
1049  for (extensions::ExtensionList::const_iterator extension = to_disable.begin();
1050      extension != to_disable.end(); ++extension) {
1051    if ((*extension)->was_installed_by_default() &&
1052        extension_urls::IsWebstoreUpdateUrl(
1053            extensions::ManifestURL::GetUpdateURL(*extension)))
1054      continue;
1055    const std::string& id = (*extension)->id();
1056    if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id))
1057      DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION);
1058  }
1059}
1060
1061void ExtensionService::GrantPermissionsAndEnableExtension(
1062    const Extension* extension) {
1063  GrantPermissions(extension);
1064  RecordPermissionMessagesHistogram(
1065      extension, "Extensions.Permissions_ReEnable");
1066  extension_prefs_->SetDidExtensionEscalatePermissions(extension, false);
1067  EnableExtension(extension->id());
1068}
1069
1070void ExtensionService::GrantPermissions(const Extension* extension) {
1071  CHECK(extension);
1072  extensions::PermissionsUpdater perms_updater(profile());
1073  perms_updater.GrantActivePermissions(extension);
1074}
1075
1076// static
1077void ExtensionService::RecordPermissionMessagesHistogram(
1078    const Extension* extension, const char* histogram) {
1079  // Since this is called from multiple sources, and since the histogram macros
1080  // use statics, we need to manually lookup the histogram ourselves.
1081  base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
1082      histogram,
1083      1,
1084      PermissionMessage::kEnumBoundary,
1085      PermissionMessage::kEnumBoundary + 1,
1086      base::HistogramBase::kUmaTargetedHistogramFlag);
1087
1088  PermissionMessages permissions =
1089      extensions::PermissionsData::GetPermissionMessages(extension);
1090  if (permissions.empty()) {
1091    counter->Add(PermissionMessage::kNone);
1092  } else {
1093    for (PermissionMessages::iterator it = permissions.begin();
1094         it != permissions.end(); ++it)
1095      counter->Add(it->id());
1096  }
1097}
1098
1099void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
1100  // The ChromeURLRequestContexts need to be first to know that the extension
1101  // was loaded, otherwise a race can arise where a renderer that is created
1102  // for the extension may try to load an extension URL with an extension id
1103  // that the request context doesn't yet know about. The profile is responsible
1104  // for ensuring its URLRequestContexts appropriately discover the loaded
1105  // extension.
1106  system_->RegisterExtensionWithRequestContexts(extension);
1107
1108  // Tell renderers about the new extension, unless it's a theme (renderers
1109  // don't need to know about themes).
1110  if (!extension->is_theme()) {
1111    for (content::RenderProcessHost::iterator i(
1112            content::RenderProcessHost::AllHostsIterator());
1113         !i.IsAtEnd(); i.Advance()) {
1114      content::RenderProcessHost* host = i.GetCurrentValue();
1115      Profile* host_profile =
1116          Profile::FromBrowserContext(host->GetBrowserContext());
1117      if (host_profile->GetOriginalProfile() ==
1118          profile_->GetOriginalProfile()) {
1119        std::vector<ExtensionMsg_Loaded_Params> loaded_extensions(
1120            1, ExtensionMsg_Loaded_Params(extension));
1121        host->Send(
1122            new ExtensionMsg_Loaded(loaded_extensions));
1123      }
1124    }
1125  }
1126
1127  // Tell subsystems that use the EXTENSION_LOADED notification about the new
1128  // extension.
1129  //
1130  // NOTE: It is important that this happen after notifying the renderers about
1131  // the new extensions so that if we navigate to an extension URL in
1132  // NOTIFICATION_EXTENSION_LOADED, the renderer is guaranteed to know about it.
1133  content::NotificationService::current()->Notify(
1134      chrome::NOTIFICATION_EXTENSION_LOADED,
1135      content::Source<Profile>(profile_),
1136      content::Details<const Extension>(extension));
1137
1138  // Tell a random-ass collection of other subsystems about the new extension.
1139  // TODO(aa): What should we do with all this goop? Can it move into the
1140  // relevant objects via EXTENSION_LOADED?
1141
1142  profile_->GetExtensionSpecialStoragePolicy()->
1143      GrantRightsForExtension(extension);
1144
1145  UpdateActiveExtensionsInCrashReporter();
1146
1147  // If the extension has permission to load chrome://favicon/ resources we need
1148  // to make sure that the FaviconSource is registered with the
1149  // ChromeURLDataManager.
1150  if (extensions::PermissionsData::HasHostPermission(
1151          extension, GURL(chrome::kChromeUIFaviconURL))) {
1152    FaviconSource* favicon_source = new FaviconSource(profile_,
1153                                                      FaviconSource::FAVICON);
1154    content::URLDataSource::Add(profile_, favicon_source);
1155  }
1156
1157#if !defined(OS_ANDROID)
1158  // Same for chrome://theme/ resources.
1159  if (extensions::PermissionsData::HasHostPermission(
1160          extension, GURL(chrome::kChromeUIThemeURL))) {
1161    ThemeSource* theme_source = new ThemeSource(profile_);
1162    content::URLDataSource::Add(profile_, theme_source);
1163  }
1164#endif
1165
1166  // Same for chrome://thumb/ resources.
1167  if (extensions::PermissionsData::HasHostPermission(
1168          extension, GURL(chrome::kChromeUIThumbnailURL))) {
1169    ThumbnailSource* thumbnail_source = new ThumbnailSource(profile_);
1170    content::URLDataSource::Add(profile_, thumbnail_source);
1171  }
1172}
1173
1174void ExtensionService::NotifyExtensionUnloaded(
1175    const Extension* extension,
1176    extension_misc::UnloadedExtensionReason reason) {
1177  UnloadedExtensionInfo details(extension, reason);
1178  content::NotificationService::current()->Notify(
1179      chrome::NOTIFICATION_EXTENSION_UNLOADED,
1180      content::Source<Profile>(profile_),
1181      content::Details<UnloadedExtensionInfo>(&details));
1182
1183  for (content::RenderProcessHost::iterator i(
1184          content::RenderProcessHost::AllHostsIterator());
1185       !i.IsAtEnd(); i.Advance()) {
1186    content::RenderProcessHost* host = i.GetCurrentValue();
1187    Profile* host_profile =
1188        Profile::FromBrowserContext(host->GetBrowserContext());
1189    if (host_profile->GetOriginalProfile() == profile_->GetOriginalProfile())
1190      host->Send(new ExtensionMsg_Unloaded(extension->id()));
1191  }
1192
1193  system_->UnregisterExtensionWithRequestContexts(extension->id(), reason);
1194  profile_->GetExtensionSpecialStoragePolicy()->
1195      RevokeRightsForExtension(extension);
1196
1197#if defined(OS_CHROMEOS)
1198  // Revoke external file access for the extension from its file system context.
1199  // It is safe to access the extension's storage partition at this point. The
1200  // storage partition may get destroyed only after the extension gets unloaded.
1201  GURL site = extensions::ExtensionSystem::Get(profile_)->extension_service()->
1202      GetSiteForExtensionId(extension->id());
1203  fileapi::FileSystemContext* filesystem_context =
1204      BrowserContext::GetStoragePartitionForSite(profile_, site)->
1205          GetFileSystemContext();
1206  if (filesystem_context && filesystem_context->external_backend()) {
1207    filesystem_context->external_backend()->
1208        RevokeAccessForExtension(extension->id());
1209  }
1210#endif
1211
1212  UpdateActiveExtensionsInCrashReporter();
1213}
1214
1215Profile* ExtensionService::profile() {
1216  return profile_;
1217}
1218
1219extensions::ExtensionPrefs* ExtensionService::extension_prefs() {
1220  return extension_prefs_;
1221}
1222
1223extensions::SettingsFrontend* ExtensionService::settings_frontend() {
1224  return settings_frontend_.get();
1225}
1226
1227extensions::ContentSettingsStore* ExtensionService::GetContentSettingsStore() {
1228  return extension_prefs()->content_settings_store();
1229}
1230
1231bool ExtensionService::is_ready() {
1232  return ready_->is_signaled();
1233}
1234
1235base::SequencedTaskRunner* ExtensionService::GetFileTaskRunner() {
1236  if (file_task_runner_.get())
1237    return file_task_runner_.get();
1238
1239  // We should be able to interrupt any part of extension install process during
1240  // shutdown. SKIP_ON_SHUTDOWN ensures that not started extension install tasks
1241  // will be ignored/deleted while we will block on started tasks.
1242  std::string token("ext_install-");
1243  token.append(profile_->GetPath().AsUTF8Unsafe());
1244  file_task_runner_ = BrowserThread::GetBlockingPool()->
1245      GetSequencedTaskRunnerWithShutdownBehavior(
1246        BrowserThread::GetBlockingPool()->GetNamedSequenceToken(token),
1247        base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
1248  return file_task_runner_.get();
1249}
1250
1251extensions::ExtensionUpdater* ExtensionService::updater() {
1252  return updater_.get();
1253}
1254
1255void ExtensionService::CheckManagementPolicy() {
1256  std::vector<std::string> to_be_removed;
1257
1258  // Loop through extensions list, unload installed extensions.
1259  for (ExtensionSet::const_iterator iter = extensions_.begin();
1260       iter != extensions_.end(); ++iter) {
1261    const Extension* extension = (iter->get());
1262    if (!system_->management_policy()->UserMayLoad(extension, NULL))
1263      to_be_removed.push_back(extension->id());
1264  }
1265
1266  // UnloadExtension will change the extensions_ list. So, we should
1267  // call it outside the iterator loop.
1268  for (size_t i = 0; i < to_be_removed.size(); ++i)
1269    UnloadExtension(to_be_removed[i], extension_misc::UNLOAD_REASON_DISABLE);
1270}
1271
1272void ExtensionService::CheckForUpdatesSoon() {
1273  if (updater()) {
1274    if (AreAllExternalProvidersReady()) {
1275      updater()->CheckSoon();
1276    } else {
1277      // Sync can start updating before all the external providers are ready
1278      // during startup. Start the update as soon as those providers are ready,
1279      // but not before.
1280      update_once_all_providers_are_ready_ = true;
1281    }
1282  } else {
1283    LOG(WARNING) << "CheckForUpdatesSoon() called with auto-update turned off";
1284  }
1285}
1286
1287syncer::SyncMergeResult ExtensionService::MergeDataAndStartSyncing(
1288    syncer::ModelType type,
1289    const syncer::SyncDataList& initial_sync_data,
1290    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
1291    scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
1292  CHECK(sync_processor.get());
1293  CHECK(sync_error_factory.get());
1294
1295  switch (type) {
1296    case syncer::EXTENSIONS:
1297      extension_sync_bundle_.SetupSync(sync_processor.release(),
1298                                       sync_error_factory.release(),
1299                                       initial_sync_data);
1300      break;
1301
1302    case syncer::APPS:
1303      app_sync_bundle_.SetupSync(sync_processor.release(),
1304                                 sync_error_factory.release(),
1305                                 initial_sync_data);
1306      break;
1307
1308    default:
1309      LOG(FATAL) << "Got " << type << " ModelType";
1310  }
1311
1312  // Process local extensions.
1313  // TODO(yoz): Determine whether pending extensions should be considered too.
1314  //            See crbug.com/104399.
1315  syncer::SyncDataList sync_data_list = GetAllSyncData(type);
1316  syncer::SyncChangeList sync_change_list;
1317  for (syncer::SyncDataList::const_iterator i = sync_data_list.begin();
1318       i != sync_data_list.end();
1319       ++i) {
1320    switch (type) {
1321        case syncer::EXTENSIONS:
1322          sync_change_list.push_back(
1323              extension_sync_bundle_.CreateSyncChange(*i));
1324          break;
1325        case syncer::APPS:
1326          sync_change_list.push_back(app_sync_bundle_.CreateSyncChange(*i));
1327          break;
1328      default:
1329        LOG(FATAL) << "Got " << type << " ModelType";
1330    }
1331  }
1332
1333
1334  if (type == syncer::EXTENSIONS) {
1335    extension_sync_bundle_.ProcessSyncChangeList(sync_change_list);
1336  } else if (type == syncer::APPS) {
1337    app_sync_bundle_.ProcessSyncChangeList(sync_change_list);
1338  }
1339
1340  return syncer::SyncMergeResult(type);
1341}
1342
1343void ExtensionService::StopSyncing(syncer::ModelType type) {
1344  if (type == syncer::APPS) {
1345    app_sync_bundle_.Reset();
1346  } else if (type == syncer::EXTENSIONS) {
1347    extension_sync_bundle_.Reset();
1348  }
1349}
1350
1351syncer::SyncDataList ExtensionService::GetAllSyncData(
1352    syncer::ModelType type) const {
1353  if (type == syncer::EXTENSIONS)
1354    return extension_sync_bundle_.GetAllSyncData();
1355  if (type == syncer::APPS)
1356    return app_sync_bundle_.GetAllSyncData();
1357
1358  // We should only get sync data for extensions and apps.
1359  NOTREACHED();
1360
1361  return syncer::SyncDataList();
1362}
1363
1364syncer::SyncError ExtensionService::ProcessSyncChanges(
1365    const tracked_objects::Location& from_here,
1366    const syncer::SyncChangeList& change_list) {
1367  for (syncer::SyncChangeList::const_iterator i = change_list.begin();
1368      i != change_list.end();
1369      ++i) {
1370    syncer::ModelType type = i->sync_data().GetDataType();
1371    if (type == syncer::EXTENSIONS) {
1372      extension_sync_bundle_.ProcessSyncChange(
1373          extensions::ExtensionSyncData(*i));
1374    } else if (type == syncer::APPS) {
1375      app_sync_bundle_.ProcessSyncChange(extensions::AppSyncData(*i));
1376    }
1377  }
1378
1379  extension_prefs()->extension_sorting()->FixNTPOrdinalCollisions();
1380
1381  return syncer::SyncError();
1382}
1383
1384extensions::ExtensionSyncData ExtensionService::GetExtensionSyncData(
1385    const Extension& extension) const {
1386  return extensions::ExtensionSyncData(extension,
1387                                       IsExtensionEnabled(extension.id()),
1388                                       IsIncognitoEnabled(extension.id()));
1389}
1390
1391extensions::AppSyncData ExtensionService::GetAppSyncData(
1392    const Extension& extension) const {
1393  return extensions::AppSyncData(
1394      extension,
1395      IsExtensionEnabled(extension.id()),
1396      IsIncognitoEnabled(extension.id()),
1397      extension_prefs_->extension_sorting()->GetAppLaunchOrdinal(
1398          extension.id()),
1399      extension_prefs_->extension_sorting()->GetPageOrdinal(extension.id()));
1400}
1401
1402std::vector<extensions::ExtensionSyncData>
1403  ExtensionService::GetExtensionSyncDataList() const {
1404  std::vector<extensions::ExtensionSyncData> extension_sync_list;
1405  extension_sync_bundle_.GetExtensionSyncDataListHelper(extensions_,
1406                                                        &extension_sync_list);
1407  extension_sync_bundle_.GetExtensionSyncDataListHelper(disabled_extensions_,
1408                                                        &extension_sync_list);
1409  extension_sync_bundle_.GetExtensionSyncDataListHelper(terminated_extensions_,
1410                                                        &extension_sync_list);
1411
1412  std::vector<extensions::ExtensionSyncData> pending_extensions =
1413      extension_sync_bundle_.GetPendingData();
1414  extension_sync_list.insert(extension_sync_list.begin(),
1415                             pending_extensions.begin(),
1416                             pending_extensions.end());
1417
1418  return extension_sync_list;
1419}
1420
1421std::vector<extensions::AppSyncData> ExtensionService::GetAppSyncDataList()
1422    const {
1423  std::vector<extensions::AppSyncData> app_sync_list;
1424  app_sync_bundle_.GetAppSyncDataListHelper(extensions_, &app_sync_list);
1425  app_sync_bundle_.GetAppSyncDataListHelper(disabled_extensions_,
1426                                            &app_sync_list);
1427  app_sync_bundle_.GetAppSyncDataListHelper(terminated_extensions_,
1428                                            &app_sync_list);
1429
1430  std::vector<extensions::AppSyncData> pending_apps =
1431      app_sync_bundle_.GetPendingData();
1432  app_sync_list.insert(app_sync_list.begin(),
1433                       pending_apps.begin(),
1434                       pending_apps.end());
1435
1436  return app_sync_list;
1437}
1438
1439bool ExtensionService::ProcessExtensionSyncData(
1440    const extensions::ExtensionSyncData& extension_sync_data) {
1441  if (!ProcessExtensionSyncDataHelper(extension_sync_data,
1442                                      syncer::EXTENSIONS)) {
1443    extension_sync_bundle_.AddPendingExtension(extension_sync_data.id(),
1444                                               extension_sync_data);
1445    CheckForUpdatesSoon();
1446    return false;
1447  }
1448
1449  return true;
1450}
1451
1452bool ExtensionService::ProcessAppSyncData(
1453    const extensions::AppSyncData& app_sync_data) {
1454  const std::string& id = app_sync_data.id();
1455
1456  if (app_sync_data.app_launch_ordinal().IsValid() &&
1457      app_sync_data.page_ordinal().IsValid()) {
1458    extension_prefs_->extension_sorting()->SetAppLaunchOrdinal(
1459        id,
1460        app_sync_data.app_launch_ordinal());
1461    extension_prefs_->extension_sorting()->SetPageOrdinal(
1462        id,
1463        app_sync_data.page_ordinal());
1464  }
1465
1466  if (!ProcessExtensionSyncDataHelper(app_sync_data.extension_sync_data(),
1467                                      syncer::APPS)) {
1468    app_sync_bundle_.AddPendingApp(id, app_sync_data);
1469    CheckForUpdatesSoon();
1470    return false;
1471  }
1472
1473  return true;
1474}
1475
1476bool ExtensionService::IsCorrectSyncType(const Extension& extension,
1477                                         syncer::ModelType type) const {
1478  if (type == syncer::EXTENSIONS &&
1479      extensions::sync_helper::IsSyncableExtension(&extension)) {
1480    return true;
1481  }
1482
1483  if (type == syncer::APPS &&
1484      extensions::sync_helper::IsSyncableApp(&extension)) {
1485    return true;
1486  }
1487
1488  return false;
1489}
1490
1491bool ExtensionService::ProcessExtensionSyncDataHelper(
1492    const extensions::ExtensionSyncData& extension_sync_data,
1493    syncer::ModelType type) {
1494  const std::string& id = extension_sync_data.id();
1495  const Extension* extension = GetInstalledExtension(id);
1496
1497  // TODO(bolms): we should really handle this better.  The particularly bad
1498  // case is where an app becomes an extension or vice versa, and we end up with
1499  // a zombie extension that won't go away.
1500  if (extension && !IsCorrectSyncType(*extension, type))
1501    return true;
1502
1503  // Handle uninstalls first.
1504  if (extension_sync_data.uninstalled()) {
1505    if (!UninstallExtensionHelper(this, id)) {
1506      LOG(WARNING) << "Could not uninstall extension " << id
1507                   << " for sync";
1508    }
1509    return true;
1510  }
1511
1512  // Extension from sync was uninstalled by the user as external extensions.
1513  // Honor user choice and skip installation/enabling.
1514  if (IsExternalExtensionUninstalled(id)) {
1515    LOG(WARNING) << "Extension with id " << id
1516                 << " from sync was uninstalled as external extension";
1517    return true;
1518  }
1519
1520  // Set user settings.
1521  // If the extension has been disabled from sync, it may not have
1522  // been installed yet, so we don't know if the disable reason was a
1523  // permissions increase.  That will be updated once CheckPermissionsIncrease
1524  // is called for it.
1525  if (extension_sync_data.enabled())
1526    EnableExtension(id);
1527  else
1528    DisableExtension(id, Extension::DISABLE_UNKNOWN_FROM_SYNC);
1529
1530  // We need to cache some version information here because setting the
1531  // incognito flag invalidates the |extension| pointer (it reloads the
1532  // extension).
1533  bool extension_installed = (extension != NULL);
1534  int result = extension ?
1535      extension->version()->CompareTo(extension_sync_data.version()) : 0;
1536  SetIsIncognitoEnabled(id, extension_sync_data.incognito_enabled());
1537  extension = NULL;  // No longer safe to use.
1538
1539  if (extension_installed) {
1540    // If the extension is already installed, check if it's outdated.
1541    if (result < 0) {
1542      // Extension is outdated.
1543      return false;
1544    }
1545  } else {
1546    // TODO(akalin): Replace silent update with a list of enabled
1547    // permissions.
1548    const bool kInstallSilently = true;
1549
1550    CHECK(type == syncer::EXTENSIONS || type == syncer::APPS);
1551    extensions::PendingExtensionInfo::ShouldAllowInstallPredicate filter =
1552        (type == syncer::APPS) ? extensions::sync_helper::IsSyncableApp :
1553                                 extensions::sync_helper::IsSyncableExtension;
1554
1555    if (!pending_extension_manager()->AddFromSync(
1556            id,
1557            extension_sync_data.update_url(),
1558            filter,
1559            kInstallSilently)) {
1560      LOG(WARNING) << "Could not add pending extension for " << id;
1561      // This means that the extension is already pending installation, with a
1562      // non-INTERNAL location.  Add to pending_sync_data, even though it will
1563      // never be removed (we'll never install a syncable version of the
1564      // extension), so that GetAllSyncData() continues to send it.
1565    }
1566    // Track pending extensions so that we can return them in GetAllSyncData().
1567    return false;
1568  }
1569
1570  return true;
1571}
1572
1573bool ExtensionService::IsIncognitoEnabled(
1574    const std::string& extension_id) const {
1575  const Extension* extension = GetInstalledExtension(extension_id);
1576  if (extension && !extension->can_be_incognito_enabled())
1577    return false;
1578  // If this is an existing component extension we always allow it to
1579  // work in incognito mode.
1580  if (extension && extension->location() == Manifest::COMPONENT)
1581    return true;
1582  if (extension && extension->force_incognito_enabled())
1583    return true;
1584
1585  // Check the prefs.
1586  return extension_prefs_->IsIncognitoEnabled(extension_id);
1587}
1588
1589void ExtensionService::SetIsIncognitoEnabled(
1590    const std::string& extension_id, bool enabled) {
1591  const Extension* extension = GetInstalledExtension(extension_id);
1592  if (extension && !extension->can_be_incognito_enabled())
1593    return;
1594  if (extension && extension->location() == Manifest::COMPONENT) {
1595    // This shouldn't be called for component extensions unless they are
1596    // syncable.
1597    DCHECK(extensions::sync_helper::IsSyncable(extension));
1598
1599    // If we are here, make sure the we aren't trying to change the value.
1600    DCHECK_EQ(enabled, IsIncognitoEnabled(extension_id));
1601
1602    return;
1603  }
1604
1605  // Broadcast unloaded and loaded events to update browser state. Only bother
1606  // if the value changed and the extension is actually enabled, since there is
1607  // no UI otherwise.
1608  bool old_enabled = extension_prefs_->IsIncognitoEnabled(extension_id);
1609  if (enabled == old_enabled)
1610    return;
1611
1612  extension_prefs_->SetIsIncognitoEnabled(extension_id, enabled);
1613
1614  bool extension_is_enabled = extensions_.Contains(extension_id);
1615
1616  // When we reload the extension the ID may be invalidated if we've passed it
1617  // by const ref everywhere. Make a copy to be safe.
1618  std::string id = extension_id;
1619  if (extension_is_enabled)
1620    ReloadExtension(id);
1621
1622  // Reloading the extension invalidates the |extension| pointer.
1623  extension = GetInstalledExtension(id);
1624  if (extension)
1625    SyncExtensionChangeIfNeeded(*extension);
1626}
1627
1628bool ExtensionService::CanCrossIncognito(const Extension* extension) const {
1629  // We allow the extension to see events and data from another profile iff it
1630  // uses "spanning" behavior and it has incognito access. "split" mode
1631  // extensions only see events for a matching profile.
1632  CHECK(extension);
1633  return IsIncognitoEnabled(extension->id()) &&
1634         !extensions::IncognitoInfo::IsSplitMode(extension);
1635}
1636
1637bool ExtensionService::CanLoadInIncognito(const Extension* extension) const {
1638  if (extension->is_hosted_app())
1639    return true;
1640  // Packaged apps and regular extensions need to be enabled specifically for
1641  // incognito (and split mode should be set).
1642  return extensions::IncognitoInfo::IsSplitMode(extension) &&
1643         IsIncognitoEnabled(extension->id());
1644}
1645
1646void ExtensionService::OnExtensionMoved(
1647    const std::string& moved_extension_id,
1648    const std::string& predecessor_extension_id,
1649    const std::string& successor_extension_id) {
1650  extension_prefs_->extension_sorting()->OnExtensionMoved(
1651      moved_extension_id,
1652      predecessor_extension_id,
1653      successor_extension_id);
1654
1655  const Extension* extension = GetInstalledExtension(moved_extension_id);
1656  if (extension)
1657    SyncExtensionChangeIfNeeded(*extension);
1658}
1659
1660bool ExtensionService::AllowFileAccess(const Extension* extension) const {
1661  return (CommandLine::ForCurrentProcess()->HasSwitch(
1662              switches::kDisableExtensionsFileAccessCheck) ||
1663          extension_prefs_->AllowFileAccess(extension->id()));
1664}
1665
1666void ExtensionService::SetAllowFileAccess(const Extension* extension,
1667                                          bool allow) {
1668  // Reload to update browser state. Only bother if the value changed and the
1669  // extension is actually enabled, since there is no UI otherwise.
1670  bool old_allow = AllowFileAccess(extension);
1671  if (allow == old_allow)
1672    return;
1673
1674  extension_prefs_->SetAllowFileAccess(extension->id(), allow);
1675
1676  bool extension_is_enabled = extensions_.Contains(extension->id());
1677  if (extension_is_enabled)
1678    ReloadExtension(extension->id());
1679}
1680
1681// Some extensions will autoupdate themselves externally from Chrome.  These
1682// are typically part of some larger client application package.  To support
1683// these, the extension will register its location in the the preferences file
1684// (and also, on Windows, in the registry) and this code will periodically
1685// check that location for a .crx file, which it will then install locally if
1686// a new version is available.
1687// Errors are reported through ExtensionErrorReporter. Succcess is not
1688// reported.
1689void ExtensionService::CheckForExternalUpdates() {
1690  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1691
1692  // Note that this installation is intentionally silent (since it didn't
1693  // go through the front-end).  Extensions that are registered in this
1694  // way are effectively considered 'pre-bundled', and so implicitly
1695  // trusted.  In general, if something has HKLM or filesystem access,
1696  // they could install an extension manually themselves anyway.
1697
1698  // Ask each external extension provider to give us a call back for each
1699  // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
1700  extensions::ProviderCollection::const_iterator i;
1701  for (i = external_extension_providers_.begin();
1702       i != external_extension_providers_.end(); ++i) {
1703    extensions::ExternalProviderInterface* provider = i->get();
1704    provider->VisitRegisteredExtension();
1705  }
1706
1707  // Do any required work that we would have done after completion of all
1708  // providers.
1709  if (external_extension_providers_.empty()) {
1710    OnAllExternalProvidersReady();
1711  }
1712}
1713
1714void ExtensionService::OnExternalProviderReady(
1715    const extensions::ExternalProviderInterface* provider) {
1716  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1717  CHECK(provider->IsReady());
1718
1719  // An external provider has finished loading.  We only take action
1720  // if all of them are finished. So we check them first.
1721  if (AreAllExternalProvidersReady())
1722    OnAllExternalProvidersReady();
1723}
1724
1725bool ExtensionService::AreAllExternalProvidersReady() const {
1726  extensions::ProviderCollection::const_iterator i;
1727  for (i = external_extension_providers_.begin();
1728       i != external_extension_providers_.end(); ++i) {
1729    if (!i->get()->IsReady())
1730      return false;
1731  }
1732  return true;
1733}
1734
1735void ExtensionService::OnAllExternalProvidersReady() {
1736  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1737  base::TimeDelta elapsed = base::Time::Now() - profile_->GetStartTime();
1738  UMA_HISTOGRAM_TIMES("Extension.ExternalProvidersReadyAfter", elapsed);
1739
1740  // Install any pending extensions.
1741  if (update_once_all_providers_are_ready_ && updater()) {
1742    update_once_all_providers_are_ready_ = false;
1743    updater()->CheckNow(extensions::ExtensionUpdater::CheckParams());
1744  }
1745
1746  // Uninstall all the unclaimed extensions.
1747  scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> extensions_info(
1748      extension_prefs_->GetInstalledExtensionsInfo());
1749  for (size_t i = 0; i < extensions_info->size(); ++i) {
1750    ExtensionInfo* info = extensions_info->at(i).get();
1751    if (Manifest::IsExternalLocation(info->extension_location))
1752      CheckExternalUninstall(info->extension_id);
1753  }
1754  IdentifyAlertableExtensions();
1755}
1756
1757void ExtensionService::IdentifyAlertableExtensions() {
1758  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1759
1760  // Build up the lists of extensions that require acknowledgment. If this is
1761  // the first time, grandfather extensions that would have caused
1762  // notification.
1763  extension_error_ui_.reset(ExtensionErrorUI::Create(this));
1764
1765  bool did_show_alert = false;
1766  if (PopulateExtensionErrorUI(extension_error_ui_.get())) {
1767    if (!is_first_run_) {
1768      CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1769      did_show_alert = extension_error_ui_->ShowErrorInBubbleView();
1770    } else {
1771      // First run. Just acknowledge all the extensions, silently, by
1772      // shortcutting the display of the UI and going straight to the
1773      // callback for pressing the Accept button.
1774      HandleExtensionAlertAccept();
1775    }
1776  }
1777
1778  UpdateExternalExtensionAlert();
1779
1780  if (!did_show_alert)
1781    extension_error_ui_.reset();
1782}
1783
1784bool ExtensionService::PopulateExtensionErrorUI(
1785    ExtensionErrorUI* extension_error_ui) {
1786  bool needs_alert = false;
1787
1788  // Extensions that are blacklisted.
1789  for (ExtensionSet::const_iterator it = blacklisted_extensions_.begin();
1790       it != blacklisted_extensions_.end(); ++it) {
1791    std::string id = (*it)->id();
1792    if (!extension_prefs_->IsBlacklistedExtensionAcknowledged(id)) {
1793      extension_error_ui->AddBlacklistedExtension(id);
1794      needs_alert = true;
1795    }
1796  }
1797
1798  for (ExtensionSet::const_iterator iter = extensions_.begin();
1799       iter != extensions_.end(); ++iter) {
1800    const Extension* e = iter->get();
1801
1802    // Extensions disabled by policy. Note: this no longer includes blacklisted
1803    // extensions, though we still show the same UI.
1804    if (!system_->management_policy()->UserMayLoad(e, NULL)) {
1805      if (!extension_prefs_->IsBlacklistedExtensionAcknowledged(e->id())) {
1806        extension_error_ui->AddBlacklistedExtension(e->id());
1807        needs_alert = true;
1808      }
1809    }
1810  }
1811
1812  return needs_alert;
1813}
1814
1815void ExtensionService::HandleExtensionAlertClosed() {
1816  const ExtensionIdSet* extension_ids =
1817      extension_error_ui_->get_blacklisted_extension_ids();
1818  for (ExtensionIdSet::const_iterator iter = extension_ids->begin();
1819       iter != extension_ids->end(); ++iter) {
1820    extension_prefs_->AcknowledgeBlacklistedExtension(*iter);
1821  }
1822  extension_error_ui_.reset();
1823}
1824
1825void ExtensionService::HandleExtensionAlertAccept() {
1826  extension_error_ui_->Close();
1827}
1828
1829void ExtensionService::AcknowledgeExternalExtension(const std::string& id) {
1830  extension_prefs_->AcknowledgeExternalExtension(id);
1831  UpdateExternalExtensionAlert();
1832}
1833
1834bool ExtensionService::IsUnacknowledgedExternalExtension(
1835    const Extension* extension) {
1836  if (!FeatureSwitch::prompt_for_external_extensions()->IsEnabled())
1837    return false;
1838
1839  return (Manifest::IsExternalLocation(extension->location()) &&
1840          !extension_prefs_->IsExternalExtensionAcknowledged(extension->id()) &&
1841          !(extension_prefs_->GetDisableReasons(extension->id()) &
1842                Extension::DISABLE_SIDELOAD_WIPEOUT));
1843}
1844
1845void ExtensionService::HandleExtensionAlertDetails() {
1846  extension_error_ui_->ShowExtensions();
1847  // ShowExtensions may cause the error UI to close synchronously, e.g. if it
1848  // causes a navigation.
1849  if (extension_error_ui_)
1850    extension_error_ui_->Close();
1851}
1852
1853void ExtensionService::UpdateExternalExtensionAlert() {
1854  if (!FeatureSwitch::prompt_for_external_extensions()->IsEnabled())
1855    return;
1856
1857  const Extension* extension = NULL;
1858  for (ExtensionSet::const_iterator iter = disabled_extensions_.begin();
1859       iter != disabled_extensions_.end(); ++iter) {
1860    const Extension* e = iter->get();
1861    if (IsUnacknowledgedExternalExtension(e)) {
1862      extension = e;
1863      break;
1864    }
1865  }
1866
1867  if (extension) {
1868    if (!extensions::HasExternalInstallError(this)) {
1869      if (extension_prefs_->IncrementAcknowledgePromptCount(extension->id()) >
1870              kMaxExtensionAcknowledgePromptCount) {
1871        // Stop prompting for this extension, and check if there's another
1872        // one that needs prompting.
1873        extension_prefs_->AcknowledgeExternalExtension(extension->id());
1874        UpdateExternalExtensionAlert();
1875        UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
1876                                  EXTERNAL_EXTENSION_IGNORED,
1877                                  EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1878        if (extensions::ManifestURL::UpdatesFromGallery(extension)) {
1879          UMA_HISTOGRAM_ENUMERATION(
1880              "Extensions.ExternalExtensionEventWebstore",
1881              EXTERNAL_EXTENSION_IGNORED,
1882              EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1883        } else {
1884          UMA_HISTOGRAM_ENUMERATION(
1885              "Extensions.ExternalExtensionEventNonWebstore",
1886              EXTERNAL_EXTENSION_IGNORED,
1887              EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1888        }
1889        return;
1890      }
1891      if (is_first_run_)
1892        extension_prefs_->SetExternalInstallFirstRun(extension->id());
1893      // first_run is true if the extension was installed during a first run
1894      // (even if it's post-first run now).
1895      bool first_run = extension_prefs_->IsExternalInstallFirstRun(
1896          extension->id());
1897      extensions::AddExternalInstallError(this, extension, first_run);
1898    }
1899  } else {
1900    extensions::RemoveExternalInstallError(this);
1901  }
1902}
1903
1904void ExtensionService::UnloadExtension(
1905    const std::string& extension_id,
1906    extension_misc::UnloadedExtensionReason reason) {
1907  // Make sure the extension gets deleted after we return from this function.
1908  int include_mask = INCLUDE_EVERYTHING & ~INCLUDE_TERMINATED;
1909  scoped_refptr<const Extension> extension(
1910      GetExtensionById(extension_id, include_mask));
1911
1912  // This method can be called via PostTask, so the extension may have been
1913  // unloaded by the time this runs.
1914  if (!extension.get()) {
1915    // In case the extension may have crashed/uninstalled. Allow the profile to
1916    // clean up its RequestContexts.
1917    system_->UnregisterExtensionWithRequestContexts(extension_id, reason);
1918    return;
1919  }
1920
1921  // If uninstalling let RuntimeEventRouter know.
1922  if (reason == extension_misc::UNLOAD_REASON_UNINSTALL)
1923    extensions::RuntimeEventRouter::OnExtensionUninstalled(
1924        profile_, extension_id);
1925
1926  // Keep information about the extension so that we can reload it later
1927  // even if it's not permanently installed.
1928  unloaded_extension_paths_[extension->id()] = extension->path();
1929
1930  // Clean up if the extension is meant to be enabled after a reload.
1931  reloading_extensions_.erase(extension->id());
1932
1933  // Clean up runtime data.
1934  extension_runtime_data_.erase(extension_id);
1935
1936  if (disabled_extensions_.Contains(extension->id())) {
1937    disabled_extensions_.Remove(extension->id());
1938    // Make sure the profile cleans up its RequestContexts when an already
1939    // disabled extension is unloaded (since they are also tracking the disabled
1940    // extensions).
1941    system_->UnregisterExtensionWithRequestContexts(extension_id, reason);
1942  } else {
1943    // Remove the extension from our list.
1944    extensions_.Remove(extension->id());
1945    NotifyExtensionUnloaded(extension.get(), reason);
1946  }
1947
1948  content::NotificationService::current()->Notify(
1949      chrome::NOTIFICATION_EXTENSION_REMOVED,
1950      content::Source<Profile>(profile_),
1951      content::Details<const Extension>(extension.get()));
1952}
1953
1954void ExtensionService::RemoveComponentExtension(
1955    const std::string& extension_id) {
1956  scoped_refptr<const Extension> extension(
1957      GetExtensionById(extension_id, false));
1958  UnloadExtension(extension_id, extension_misc::UNLOAD_REASON_UNINSTALL);
1959  content::NotificationService::current()->Notify(
1960      chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
1961      content::Source<Profile>(profile_),
1962      content::Details<const Extension>(extension.get()));
1963}
1964
1965void ExtensionService::UnloadAllExtensions() {
1966  profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions();
1967
1968  extensions_.Clear();
1969  disabled_extensions_.Clear();
1970  terminated_extensions_.Clear();
1971  extension_runtime_data_.clear();
1972
1973  // TODO(erikkay) should there be a notification for this?  We can't use
1974  // EXTENSION_UNLOADED since that implies that the extension has been disabled
1975  // or uninstalled, and UnloadAll is just part of shutdown.
1976}
1977
1978void ExtensionService::ReloadExtensions() {
1979  UnloadAllExtensions();
1980  component_loader_->LoadAll();
1981  extensions::InstalledLoader(this).LoadAllExtensions();
1982  // Don't call SetReadyAndNotifyListeners() since tests call this multiple
1983  // times.
1984}
1985
1986void ExtensionService::GarbageCollectExtensions() {
1987#if defined(OS_CHROMEOS)
1988  if (disable_garbage_collection_)
1989    return;
1990#endif
1991
1992  if (extension_prefs_->pref_service()->ReadOnly())
1993    return;
1994
1995  if (pending_extension_manager()->HasPendingExtensions()) {
1996    // Don't garbage collect while there are pending installations, which may
1997    // be using the temporary installation directory. Try to garbage collect
1998    // again later.
1999    base::MessageLoop::current()->PostDelayedTask(
2000        FROM_HERE,
2001        base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()),
2002        base::TimeDelta::FromSeconds(kGarbageCollectRetryDelay));
2003    return;
2004  }
2005
2006  scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> info(
2007      extension_prefs_->GetInstalledExtensionsInfo());
2008
2009  std::multimap<std::string, base::FilePath> extension_paths;
2010  for (size_t i = 0; i < info->size(); ++i)
2011    extension_paths.insert(std::make_pair(info->at(i)->extension_id,
2012                                          info->at(i)->extension_path));
2013
2014  info = extension_prefs_->GetAllDelayedInstallInfo();
2015  for (size_t i = 0; i < info->size(); ++i)
2016    extension_paths.insert(std::make_pair(info->at(i)->extension_id,
2017                                          info->at(i)->extension_path));
2018
2019  if (!GetFileTaskRunner()->PostTask(
2020          FROM_HERE,
2021          base::Bind(
2022              &extension_file_util::GarbageCollectExtensions,
2023              install_directory_,
2024              extension_paths))) {
2025    NOTREACHED();
2026  }
2027}
2028
2029void ExtensionService::SyncExtensionChangeIfNeeded(const Extension& extension) {
2030  if (extensions::sync_helper::IsSyncableApp(&extension)) {
2031    if (app_sync_bundle_.IsSyncing())
2032      app_sync_bundle_.SyncChangeIfNeeded(extension);
2033    else if (is_ready() && !flare_.is_null())
2034      flare_.Run(syncer::APPS);
2035  } else if (extensions::sync_helper::IsSyncableExtension(&extension)) {
2036    if (extension_sync_bundle_.IsSyncing())
2037      extension_sync_bundle_.SyncChangeIfNeeded(extension);
2038    else if (is_ready() && !flare_.is_null())
2039      flare_.Run(syncer::EXTENSIONS);
2040  }
2041}
2042
2043void ExtensionService::SetReadyAndNotifyListeners() {
2044  ready_->Signal();
2045  content::NotificationService::current()->Notify(
2046      chrome::NOTIFICATION_EXTENSIONS_READY,
2047      content::Source<Profile>(profile_),
2048      content::NotificationService::NoDetails());
2049}
2050
2051void ExtensionService::OnLoadedInstalledExtensions() {
2052  if (updater_)
2053    updater_->Start();
2054
2055  OnBlacklistUpdated();
2056}
2057
2058void ExtensionService::AddExtension(const Extension* extension) {
2059  // TODO(jstritar): We may be able to get rid of this branch by overriding the
2060  // default extension state to DISABLED when the --disable-extensions flag
2061  // is set (http://crbug.com/29067).
2062  if (!extensions_enabled() &&
2063      !extension->is_theme() &&
2064      extension->location() != Manifest::COMPONENT &&
2065      !Manifest::IsExternalLocation(extension->location())) {
2066    return;
2067  }
2068
2069  bool is_extension_upgrade = false;
2070  bool is_extension_installed = false;
2071  const Extension* old = GetInstalledExtension(extension->id());
2072  if (old) {
2073    is_extension_installed = true;
2074    int version_compare_result =
2075        extension->version()->CompareTo(*(old->version()));
2076    is_extension_upgrade = version_compare_result > 0;
2077    // Other than for unpacked extensions, CrxInstaller should have guaranteed
2078    // that we aren't downgrading.
2079    if (!Manifest::IsUnpackedLocation(extension->location()))
2080      CHECK_GE(version_compare_result, 0);
2081  }
2082  SetBeingUpgraded(extension, is_extension_upgrade);
2083
2084  // The extension is now loaded, remove its data from unloaded extension map.
2085  unloaded_extension_paths_.erase(extension->id());
2086
2087  // If a terminated extension is loaded, remove it from the terminated list.
2088  UntrackTerminatedExtension(extension->id());
2089
2090  // If the extension was disabled for a reload, then enable it.
2091  bool reloading = reloading_extensions_.erase(extension->id()) > 0;
2092
2093  // Check if the extension's privileges have changed and mark the
2094  // extension disabled if necessary.
2095  CheckPermissionsIncrease(extension, is_extension_installed);
2096
2097  if (is_extension_installed && !reloading) {
2098    // To upgrade an extension in place, unload the old one and then load the
2099    // new one.  ReloadExtension disables the extension, which is sufficient.
2100    UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_UPDATE);
2101  }
2102
2103  if (extension_prefs_->IsExtensionBlacklisted(extension->id())) {
2104    // Only prefs is checked for the blacklist. We rely on callers to check the
2105    // blacklist before calling into here, e.g. CrxInstaller checks before
2106    // installation then threads through the install and pending install flow
2107    // of this class, and we check when loading installed extensions.
2108    blacklisted_extensions_.Insert(extension);
2109  } else if (!reloading &&
2110             extension_prefs_->IsExtensionDisabled(extension->id())) {
2111    disabled_extensions_.Insert(extension);
2112    SyncExtensionChangeIfNeeded(*extension);
2113    content::NotificationService::current()->Notify(
2114        chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
2115        content::Source<Profile>(profile_),
2116        content::Details<const Extension>(extension));
2117
2118    // Show the extension disabled error if a permissions increase was the
2119    // only reason it was disabled.
2120    if (extension_prefs_->GetDisableReasons(extension->id()) ==
2121        Extension::DISABLE_PERMISSIONS_INCREASE) {
2122      extensions::AddExtensionDisabledError(this, extension);
2123    }
2124  } else if (reloading) {
2125    // Replace the old extension with the new version.
2126    CHECK(!disabled_extensions_.Insert(extension));
2127    EnableExtension(extension->id());
2128  } else {
2129    // All apps that are displayed in the launcher are ordered by their ordinals
2130    // so we must ensure they have valid ordinals.
2131    if (extension->RequiresSortOrdinal()) {
2132      if (!extension->ShouldDisplayInNewTabPage()) {
2133        extension_prefs_->extension_sorting()->MarkExtensionAsHidden(
2134            extension->id());
2135      }
2136      extension_prefs_->extension_sorting()->EnsureValidOrdinals(
2137          extension->id(), syncer::StringOrdinal());
2138    }
2139
2140    extensions_.Insert(extension);
2141    SyncExtensionChangeIfNeeded(*extension);
2142    NotifyExtensionLoaded(extension);
2143  }
2144  SetBeingUpgraded(extension, false);
2145}
2146
2147void ExtensionService::AddComponentExtension(const Extension* extension) {
2148  const std::string old_version_string(
2149      extension_prefs_->GetVersionString(extension->id()));
2150  const Version old_version(old_version_string);
2151
2152  if (!old_version.IsValid() || !old_version.Equals(*extension->version())) {
2153    VLOG(1) << "Component extension " << extension->name() << " ("
2154        << extension->id() << ") installing/upgrading from '"
2155        << old_version_string << "' to " << extension->version()->GetString();
2156
2157    AddNewOrUpdatedExtension(extension,
2158                             Extension::ENABLED_COMPONENT,
2159                             extensions::Blacklist::NOT_BLACKLISTED,
2160                             syncer::StringOrdinal());
2161    return;
2162  }
2163
2164  AddExtension(extension);
2165}
2166
2167void ExtensionService::UpdateActivePermissions(const Extension* extension) {
2168  // If the extension has used the optional permissions API, it will have a
2169  // custom set of active permissions defined in the extension prefs. Here,
2170  // we update the extension's active permissions based on the prefs.
2171  scoped_refptr<PermissionSet> active_permissions =
2172      extension_prefs()->GetActivePermissions(extension->id());
2173
2174  if (active_permissions.get()) {
2175    // We restrict the active permissions to be within the bounds defined in the
2176    // extension's manifest.
2177    //  a) active permissions must be a subset of optional + default permissions
2178    //  b) active permissions must contains all default permissions
2179    scoped_refptr<PermissionSet> total_permissions =
2180        PermissionSet::CreateUnion(
2181            extensions::PermissionsData::GetRequiredPermissions(extension),
2182            extensions::PermissionsData::GetOptionalPermissions(extension));
2183
2184    // Make sure the active permissions contain no more than optional + default.
2185    scoped_refptr<PermissionSet> adjusted_active =
2186        PermissionSet::CreateIntersection(
2187            total_permissions.get(), active_permissions.get());
2188
2189    // Make sure the active permissions contain the default permissions.
2190    adjusted_active = PermissionSet::CreateUnion(
2191        extensions::PermissionsData::GetRequiredPermissions(extension),
2192        adjusted_active.get());
2193
2194    extensions::PermissionsUpdater perms_updater(profile());
2195    perms_updater.UpdateActivePermissions(extension, adjusted_active.get());
2196  }
2197}
2198
2199void ExtensionService::CheckPermissionsIncrease(const Extension* extension,
2200                                                bool is_extension_installed) {
2201  UpdateActivePermissions(extension);
2202
2203  // We keep track of all permissions the user has granted each extension.
2204  // This allows extensions to gracefully support backwards compatibility
2205  // by including unknown permissions in their manifests. When the user
2206  // installs the extension, only the recognized permissions are recorded.
2207  // When the unknown permissions become recognized (e.g., through browser
2208  // upgrade), we can prompt the user to accept these new permissions.
2209  // Extensions can also silently upgrade to less permissions, and then
2210  // silently upgrade to a version that adds these permissions back.
2211  //
2212  // For example, pretend that Chrome 10 includes a permission "omnibox"
2213  // for an API that adds suggestions to the omnibox. An extension can
2214  // maintain backwards compatibility while still having "omnibox" in the
2215  // manifest. If a user installs the extension on Chrome 9, the browser
2216  // will record the permissions it recognized, not including "omnibox."
2217  // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome
2218  // will disable the extension and prompt the user to approve the increase
2219  // in privileges. The extension could then release a new version that
2220  // removes the "omnibox" permission. When the user upgrades, Chrome will
2221  // still remember that "omnibox" had been granted, so that if the
2222  // extension once again includes "omnibox" in an upgrade, the extension
2223  // can upgrade without requiring this user's approval.
2224  int disable_reasons = extension_prefs_->GetDisableReasons(extension->id());
2225
2226  bool auto_grant_permission =
2227      (!is_extension_installed && extension->was_installed_by_default()) ||
2228      chrome::IsRunningInForcedAppMode();
2229  // Silently grant all active permissions to default apps only on install.
2230  // After install they should behave like other apps.
2231  // Silently grant all active permissions to apps install in kiosk mode on both
2232  // install and update.
2233  if (auto_grant_permission)
2234    GrantPermissions(extension);
2235
2236  bool is_privilege_increase = false;
2237  // We only need to compare the granted permissions to the current permissions
2238  // if the extension is not allowed to silently increase its permissions.
2239  if (!extensions::PermissionsData::CanSilentlyIncreasePermissions(extension) &&
2240      !auto_grant_permission) {
2241    // Add all the recognized permissions if the granted permissions list
2242    // hasn't been initialized yet.
2243    scoped_refptr<PermissionSet> granted_permissions =
2244        extension_prefs_->GetGrantedPermissions(extension->id());
2245    CHECK(granted_permissions.get());
2246
2247    // Here, we check if an extension's privileges have increased in a manner
2248    // that requires the user's approval. This could occur because the browser
2249    // upgraded and recognized additional privileges, or an extension upgrades
2250    // to a version that requires additional privileges.
2251    is_privilege_increase = granted_permissions->HasLessPrivilegesThan(
2252        extension->GetActivePermissions().get(), extension->GetType());
2253  }
2254
2255  if (is_extension_installed) {
2256    // If the extension was already disabled, suppress any alerts for becoming
2257    // disabled on permissions increase.
2258    bool previously_disabled =
2259        extension_prefs_->IsExtensionDisabled(extension->id());
2260    // Legacy disabled extensions do not have a disable reason. Infer that if
2261    // there was no permission increase, it was likely disabled by the user.
2262    if (previously_disabled && disable_reasons == Extension::DISABLE_NONE &&
2263        !extension_prefs_->DidExtensionEscalatePermissions(extension->id())) {
2264      disable_reasons |= Extension::DISABLE_USER_ACTION;
2265    }
2266    // Extensions that came to us disabled from sync need a similar inference,
2267    // except based on the new version's permissions.
2268    if (previously_disabled &&
2269        disable_reasons == Extension::DISABLE_UNKNOWN_FROM_SYNC) {
2270      // Remove the DISABLE_UNKNOWN_FROM_SYNC reason.
2271      extension_prefs_->ClearDisableReasons(extension->id());
2272      if (!is_privilege_increase)
2273        disable_reasons |= Extension::DISABLE_USER_ACTION;
2274    }
2275    disable_reasons &= ~Extension::DISABLE_UNKNOWN_FROM_SYNC;
2276  }
2277
2278  // Extension has changed permissions significantly. Disable it. A
2279  // notification should be sent by the caller.
2280  if (is_privilege_increase) {
2281    disable_reasons |= Extension::DISABLE_PERMISSIONS_INCREASE;
2282    if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id())) {
2283      RecordPermissionMessagesHistogram(
2284          extension, "Extensions.Permissions_AutoDisable");
2285    }
2286    extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED);
2287    extension_prefs_->SetDidExtensionEscalatePermissions(extension, true);
2288  }
2289  if (disable_reasons != Extension::DISABLE_NONE) {
2290    extension_prefs_->AddDisableReason(
2291        extension->id(),
2292        static_cast<Extension::DisableReason>(disable_reasons));
2293  }
2294}
2295
2296void ExtensionService::UpdateActiveExtensionsInCrashReporter() {
2297  std::set<std::string> extension_ids;
2298  for (ExtensionSet::const_iterator iter = extensions_.begin();
2299       iter != extensions_.end(); ++iter) {
2300    const Extension* extension = iter->get();
2301    if (!extension->is_theme() && extension->location() != Manifest::COMPONENT)
2302      extension_ids.insert(extension->id());
2303  }
2304
2305  crash_keys::SetActiveExtensions(extension_ids);
2306}
2307
2308ExtensionService::ImportStatus ExtensionService::SatisfyImports(
2309    const Extension* extension) {
2310  ImportStatus status = IMPORT_STATUS_OK;
2311  std::vector<std::string> pending;
2312  // TODO(elijahtaylor): Message the user if there is a failure that is
2313  // unrecoverable.
2314  if (SharedModuleInfo::ImportsModules(extension)) {
2315    const std::vector<SharedModuleInfo::ImportInfo>& imports =
2316        SharedModuleInfo::GetImports(extension);
2317    std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
2318    for (i = imports.begin(); i != imports.end(); ++i) {
2319      Version version_required(i->minimum_version);
2320      const Extension* imported_module =
2321          GetExtensionById(i->extension_id, true);
2322      if (!imported_module) {
2323        if (extension->from_webstore()) {
2324          status = IMPORT_STATUS_UNSATISFIED;
2325          pending.push_back(i->extension_id);
2326        } else {
2327          return IMPORT_STATUS_UNRECOVERABLE;
2328        }
2329      } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
2330        return IMPORT_STATUS_UNRECOVERABLE;
2331      } else if (version_required.IsValid() &&
2332                 imported_module->version()->CompareTo(version_required) < 0) {
2333        if (imported_module->from_webstore()) {
2334          status = IMPORT_STATUS_UNSATISFIED;
2335        } else {
2336          return IMPORT_STATUS_UNRECOVERABLE;
2337        }
2338      }
2339    }
2340  }
2341  if (status == IMPORT_STATUS_UNSATISFIED) {
2342    for (std::vector<std::string>::const_iterator iter = pending.begin();
2343         iter != pending.end();
2344         ++iter) {
2345      pending_extension_manager()->AddFromExtensionImport(
2346          *iter,
2347          extension_urls::GetWebstoreUpdateUrl(),
2348          IsSharedModule);
2349    }
2350    CheckForUpdatesSoon();
2351  }
2352  return status;
2353}
2354
2355scoped_ptr<const ExtensionSet>
2356    ExtensionService::GetDependentExtensions(const Extension* extension) {
2357  scoped_ptr<ExtensionSet> dependents(new ExtensionSet());
2358  scoped_ptr<ExtensionSet> set_to_check(new ExtensionSet());
2359  if (SharedModuleInfo::IsSharedModule(extension)) {
2360    set_to_check->InsertAll(disabled_extensions_);
2361    set_to_check->InsertAll(delayed_installs_);
2362    set_to_check->InsertAll(extensions_);
2363    for (ExtensionSet::const_iterator iter = set_to_check->begin();
2364         iter != set_to_check->end(); ++iter) {
2365      if (SharedModuleInfo::ImportsExtensionById(iter->get(),
2366                                                 extension->id())) {
2367        dependents->Insert(*iter);
2368      }
2369    }
2370  }
2371  return dependents.PassAs<const ExtensionSet>();
2372}
2373
2374void ExtensionService::PruneSharedModulesOnUninstall(
2375    const Extension* extension) {
2376  if (SharedModuleInfo::ImportsModules(extension)) {
2377    const std::vector<SharedModuleInfo::ImportInfo>& imports =
2378        SharedModuleInfo::GetImports(extension);
2379    std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
2380    for (i = imports.begin(); i != imports.end(); ++i) {
2381      const Extension* imported_module =
2382          GetExtensionById(i->extension_id, true);
2383      if (imported_module && imported_module->from_webstore()) {
2384        scoped_ptr<const ExtensionSet> dependents =
2385            GetDependentExtensions(imported_module);
2386        if (dependents->size() == 0) {
2387          UninstallExtension(i->extension_id, true, NULL);
2388        }
2389      }
2390    }
2391  }
2392}
2393
2394void ExtensionService::OnExtensionInstalled(
2395    const Extension* extension,
2396    const syncer::StringOrdinal& page_ordinal,
2397    bool has_requirement_errors,
2398    extensions::Blacklist::BlacklistState blacklist_state,
2399    bool wait_for_idle) {
2400  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2401
2402  const std::string& id = extension->id();
2403  bool initial_enable = ShouldEnableOnInstall(extension);
2404  const extensions::PendingExtensionInfo* pending_extension_info = NULL;
2405  if ((pending_extension_info = pending_extension_manager()->GetById(id))) {
2406    if (!pending_extension_info->ShouldAllowInstall(extension)) {
2407      pending_extension_manager()->Remove(id);
2408
2409      LOG(WARNING) << "ShouldAllowInstall() returned false for "
2410                   << id << " of type " << extension->GetType()
2411                   << " and update URL "
2412                   << extensions::ManifestURL::GetUpdateURL(extension).spec()
2413                   << "; not installing";
2414
2415      // Delete the extension directory since we're not going to
2416      // load it.
2417      if (!GetFileTaskRunner()->PostTask(
2418              FROM_HERE,
2419              base::Bind(&extension_file_util::DeleteFile,
2420                         extension->path(), true))) {
2421        NOTREACHED();
2422      }
2423      return;
2424    }
2425
2426    pending_extension_manager()->Remove(id);
2427  } else {
2428    // We explicitly want to re-enable an uninstalled external
2429    // extension; if we're here, that means the user is manually
2430    // installing the extension.
2431    if (IsExternalExtensionUninstalled(id)) {
2432      initial_enable = true;
2433    }
2434  }
2435
2436  // Unsupported requirements overrides the management policy.
2437  if (has_requirement_errors) {
2438    initial_enable = false;
2439    extension_prefs_->AddDisableReason(
2440        id, Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
2441  // If the extension was disabled because of unsupported requirements but
2442  // now supports all requirements after an update and there are not other
2443  // disable reasons, enable it.
2444  } else if (extension_prefs_->GetDisableReasons(id) ==
2445      Extension::DISABLE_UNSUPPORTED_REQUIREMENT) {
2446    initial_enable = true;
2447    extension_prefs_->ClearDisableReasons(id);
2448  }
2449
2450  if (blacklist_state == extensions::Blacklist::BLACKLISTED) {
2451    // Installation of a blacklisted extension can happen from sync, policy,
2452    // etc, where to maintain consistency we need to install it, just never
2453    // load it (see AddExtension). Usually it should be the job of callers to
2454    // incercept blacklisted extension earlier (e.g. CrxInstaller, before even
2455    // showing the install dialogue).
2456    extension_prefs()->AcknowledgeBlacklistedExtension(id);
2457    UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall",
2458                              extension->location(),
2459                              Manifest::NUM_LOCATIONS);
2460  }
2461
2462  if (!GetInstalledExtension(extension->id())) {
2463    UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType",
2464                              extension->GetType(), 100);
2465    UMA_HISTOGRAM_ENUMERATION("Extensions.InstallSource",
2466                              extension->location(), Manifest::NUM_LOCATIONS);
2467    RecordPermissionMessagesHistogram(
2468        extension, "Extensions.Permissions_Install");
2469  } else {
2470    UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateType",
2471                              extension->GetType(), 100);
2472    UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateSource",
2473                              extension->location(), Manifest::NUM_LOCATIONS);
2474  }
2475
2476  // Certain extension locations are specific enough that we can
2477  // auto-acknowledge any extension that came from one of them.
2478  if (extension->location() == Manifest::EXTERNAL_POLICY_DOWNLOAD)
2479    AcknowledgeExternalExtension(extension->id());
2480  const Extension::State initial_state =
2481      initial_enable ? Extension::ENABLED : Extension::DISABLED;
2482  if (ShouldDelayExtensionUpdate(id, wait_for_idle)) {
2483    extension_prefs_->SetDelayedInstallInfo(
2484        extension,
2485        initial_state,
2486        blacklist_state,
2487        extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
2488        page_ordinal);
2489
2490    // Transfer ownership of |extension|.
2491    delayed_installs_.Insert(extension);
2492
2493    // Notify extension of available update.
2494    extensions::RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
2495        profile_, id, extension->manifest()->value());
2496
2497    // Notify observers that app update is available.
2498    FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
2499                      OnAppUpdateAvailable(extension->id()));
2500    return;
2501  }
2502
2503  ImportStatus status = SatisfyImports(extension);
2504  if (installs_delayed_for_gc()) {
2505    extension_prefs_->SetDelayedInstallInfo(
2506        extension,
2507        initial_state,
2508        blacklist_state,
2509        extensions::ExtensionPrefs::DELAY_REASON_GC,
2510        page_ordinal);
2511    delayed_installs_.Insert(extension);
2512  } else if (status != IMPORT_STATUS_OK) {
2513    if (status == IMPORT_STATUS_UNSATISFIED) {
2514      extension_prefs_->SetDelayedInstallInfo(
2515          extension,
2516          initial_state,
2517          blacklist_state,
2518          extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
2519          page_ordinal);
2520      delayed_installs_.Insert(extension);
2521    }
2522  } else {
2523    AddNewOrUpdatedExtension(extension,
2524                             initial_state,
2525                             blacklist_state,
2526                             page_ordinal);
2527  }
2528}
2529
2530void ExtensionService::AddNewOrUpdatedExtension(
2531    const Extension* extension,
2532    Extension::State initial_state,
2533    extensions::Blacklist::BlacklistState blacklist_state,
2534    const syncer::StringOrdinal& page_ordinal) {
2535  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2536  extension_prefs_->OnExtensionInstalled(extension,
2537                                         initial_state,
2538                                         blacklist_state,
2539                                         page_ordinal);
2540  delayed_installs_.Remove(extension->id());
2541  FinishInstallation(extension);
2542}
2543
2544void ExtensionService::MaybeFinishDelayedInstallation(
2545    const std::string& extension_id) {
2546  // Check if the extension already got installed.
2547  if (!delayed_installs_.Contains(extension_id))
2548    return;
2549  extensions::ExtensionPrefs::DelayReason reason =
2550      extension_prefs_->GetDelayedInstallReason(extension_id);
2551
2552  // Check if the extension is idle. DELAY_REASON_NONE is used for older
2553  // preferences files that will not have set this field but it was previously
2554  // only used for idle updates.
2555  if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE ||
2556       reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) &&
2557       is_ready() && !IsExtensionIdle(extension_id))
2558    return;
2559
2560  const Extension* extension = delayed_installs_.GetByID(extension_id);
2561  if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) {
2562    ImportStatus status = SatisfyImports(extension);
2563    if (status != IMPORT_STATUS_OK) {
2564      if (status == IMPORT_STATUS_UNRECOVERABLE) {
2565        delayed_installs_.Remove(extension_id);
2566        // Make sure no version of the extension is actually installed, (i.e.,
2567        // that this delayed install was not an update).
2568        CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
2569        extension_prefs_->DeleteExtensionPrefs(extension_id);
2570      }
2571      return;
2572    }
2573  }
2574
2575  FinishDelayedInstallation(extension_id);
2576}
2577
2578void ExtensionService::FinishDelayedInstallation(
2579    const std::string& extension_id) {
2580  scoped_refptr<const Extension> extension(
2581      GetPendingExtensionUpdate(extension_id));
2582  CHECK(extension.get());
2583  delayed_installs_.Remove(extension_id);
2584
2585  if (!extension_prefs_->FinishDelayedInstallInfo(extension_id))
2586    NOTREACHED();
2587
2588  FinishInstallation(extension.get());
2589}
2590
2591void ExtensionService::FinishInstallation(const Extension* extension) {
2592  const extensions::Extension* existing_extension =
2593      GetInstalledExtension(extension->id());
2594  bool is_update = false;
2595  std::string old_name;
2596  if (existing_extension) {
2597    is_update = true;
2598    old_name = existing_extension->name();
2599  }
2600  extensions::InstalledExtensionInfo details(extension, is_update, old_name);
2601  content::NotificationService::current()->Notify(
2602      chrome::NOTIFICATION_EXTENSION_INSTALLED,
2603      content::Source<Profile>(profile_),
2604      content::Details<const extensions::InstalledExtensionInfo>(&details));
2605
2606  bool unacknowledged_external = IsUnacknowledgedExternalExtension(extension);
2607
2608  // Unpacked extensions default to allowing file access, but if that has been
2609  // overridden, don't reset the value.
2610  if (Manifest::ShouldAlwaysAllowFileAccess(extension->location()) &&
2611      !extension_prefs_->HasAllowFileAccessSetting(extension->id())) {
2612    extension_prefs_->SetAllowFileAccess(extension->id(), true);
2613  }
2614
2615  AddExtension(extension);
2616
2617  // If this is a new external extension that was disabled, alert the user
2618  // so he can reenable it. We do this last so that it has already been
2619  // added to our list of extensions.
2620  if (unacknowledged_external && !is_update) {
2621    UpdateExternalExtensionAlert();
2622    UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
2623                              EXTERNAL_EXTENSION_INSTALLED,
2624                              EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
2625    if (extensions::ManifestURL::UpdatesFromGallery(extension)) {
2626      UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventWebstore",
2627                                EXTERNAL_EXTENSION_INSTALLED,
2628                                EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
2629    } else {
2630      UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventNonWebstore",
2631                                EXTERNAL_EXTENSION_INSTALLED,
2632                                EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
2633    }
2634  }
2635
2636  // Check extensions that may have been delayed only because this shared module
2637  // was not available.
2638  if (SharedModuleInfo::IsSharedModule(extension)) {
2639    MaybeFinishDelayedInstallations();
2640  }
2641}
2642
2643const Extension* ExtensionService::GetPendingExtensionUpdate(
2644    const std::string& id) const {
2645  return delayed_installs_.GetByID(id);
2646}
2647
2648void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
2649  if (!terminated_extensions_.Contains(extension->id()))
2650    terminated_extensions_.Insert(make_scoped_refptr(extension));
2651
2652  UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE);
2653}
2654
2655void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
2656  std::string lowercase_id = StringToLowerASCII(id);
2657  const Extension* extension = terminated_extensions_.GetByID(lowercase_id);
2658  terminated_extensions_.Remove(lowercase_id);
2659  if (extension) {
2660    content::NotificationService::current()->Notify(
2661        chrome::NOTIFICATION_EXTENSION_REMOVED,
2662        content::Source<Profile>(profile_),
2663        content::Details<const Extension>(extension));
2664  }
2665}
2666
2667const Extension* ExtensionService::GetTerminatedExtension(
2668    const std::string& id) const {
2669  return GetExtensionById(id, INCLUDE_TERMINATED);
2670}
2671
2672const Extension* ExtensionService::GetInstalledExtension(
2673    const std::string& id) const {
2674  int include_mask = INCLUDE_ENABLED |
2675                     INCLUDE_DISABLED |
2676                     INCLUDE_TERMINATED |
2677                     INCLUDE_BLACKLISTED;
2678  return GetExtensionById(id, include_mask);
2679}
2680
2681bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) {
2682  // Allow bindings for all packaged extensions and component hosted apps.
2683  const Extension* extension = extensions_.GetExtensionOrAppByURL(url);
2684  return extension && (!extension->is_hosted_app() ||
2685                       extension->location() == Manifest::COMPONENT);
2686}
2687
2688bool ExtensionService::ShouldBlockUrlInBrowserTab(GURL* url) {
2689  const Extension* extension = extensions_.GetExtensionOrAppByURL(*url);
2690  if (extension && extension->is_platform_app()) {
2691    *url = GURL(chrome::kExtensionInvalidRequestURL);
2692    return true;
2693  }
2694
2695  return false;
2696}
2697
2698bool ExtensionService::OnExternalExtensionFileFound(
2699         const std::string& id,
2700         const Version* version,
2701         const base::FilePath& path,
2702         Manifest::Location location,
2703         int creation_flags,
2704         bool mark_acknowledged) {
2705  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2706  CHECK(Extension::IdIsValid(id));
2707  if (extension_prefs_->IsExternalExtensionUninstalled(id))
2708    return false;
2709
2710  // Before even bothering to unpack, check and see if we already have this
2711  // version. This is important because these extensions are going to get
2712  // installed on every startup.
2713  const Extension* existing = GetExtensionById(id, true);
2714
2715  if (existing) {
2716    // The default apps will have the location set as INTERNAL. Since older
2717    // default apps are installed as EXTERNAL, we override them. However, if the
2718    // app is already installed as internal, then do the version check.
2719    // TODO(grv) : Remove after Q1-2013.
2720    bool is_default_apps_migration =
2721        (location == Manifest::INTERNAL &&
2722         Manifest::IsExternalLocation(existing->location()));
2723
2724    if (!is_default_apps_migration) {
2725      DCHECK(version);
2726
2727      switch (existing->version()->CompareTo(*version)) {
2728        case -1:  // existing version is older, we should upgrade
2729          break;
2730        case 0:  // existing version is same, do nothing
2731          return false;
2732        case 1:  // existing version is newer, uh-oh
2733          LOG(WARNING) << "Found external version of extension " << id
2734                       << "that is older than current version. Current version "
2735                       << "is: " << existing->VersionString() << ". New "
2736                       << "version is: " << version->GetString()
2737                       << ". Keeping current version.";
2738          return false;
2739      }
2740    }
2741  }
2742
2743  // If the extension is already pending, don't start an install.
2744  if (!pending_extension_manager()->AddFromExternalFile(
2745          id, location, *version)) {
2746    return false;
2747  }
2748
2749  // no client (silent install)
2750  scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this));
2751  installer->set_install_source(location);
2752  installer->set_expected_id(id);
2753  installer->set_expected_version(*version);
2754  installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE);
2755  installer->set_creation_flags(creation_flags);
2756#if defined(OS_CHROMEOS)
2757  extensions::InstallLimiter::Get(profile_)->Add(installer, path);
2758#else
2759  installer->InstallCrx(path);
2760#endif
2761
2762  // Depending on the source, a new external extension might not need a user
2763  // notification on installation. For such extensions, mark them acknowledged
2764  // now to suppress the notification.
2765  if (mark_acknowledged)
2766    AcknowledgeExternalExtension(id);
2767
2768  return true;
2769}
2770
2771void ExtensionService::ReportExtensionLoadError(
2772    const base::FilePath& extension_path,
2773    const std::string &error,
2774    bool be_noisy) {
2775  content::NotificationService::current()->Notify(
2776      chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
2777      content::Source<Profile>(profile_),
2778      content::Details<const std::string>(&error));
2779
2780  std::string path_str = UTF16ToUTF8(extension_path.LossyDisplayName());
2781  string16 message = UTF8ToUTF16(base::StringPrintf(
2782      "Could not load extension from '%s'. %s",
2783      path_str.c_str(), error.c_str()));
2784  ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy);
2785}
2786
2787void ExtensionService::DidCreateRenderViewForBackgroundPage(
2788    extensions::ExtensionHost* host) {
2789  OrphanedDevTools::iterator iter =
2790      orphaned_dev_tools_.find(host->extension_id());
2791  if (iter == orphaned_dev_tools_.end())
2792    return;
2793
2794  iter->second->ConnectRenderViewHost(host->render_view_host());
2795  orphaned_dev_tools_.erase(iter);
2796}
2797
2798void ExtensionService::Observe(int type,
2799                               const content::NotificationSource& source,
2800                               const content::NotificationDetails& details) {
2801  switch (type) {
2802    case chrome::NOTIFICATION_APP_TERMINATING:
2803      // Shutdown has started. Don't start any more extension installs.
2804      // (We cannot use ExtensionService::Shutdown() for this because it
2805      // happens too late in browser teardown.)
2806      browser_terminating_ = true;
2807      break;
2808    case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: {
2809      if (profile_ !=
2810          content::Source<Profile>(source).ptr()->GetOriginalProfile()) {
2811        break;
2812      }
2813
2814      extensions::ExtensionHost* host =
2815          content::Details<extensions::ExtensionHost>(details).ptr();
2816
2817      // Mark the extension as terminated and Unload it. We want it to
2818      // be in a consistent state: either fully working or not loaded
2819      // at all, but never half-crashed.  We do it in a PostTask so
2820      // that other handlers of this notification will still have
2821      // access to the Extension and ExtensionHost.
2822      base::MessageLoop::current()->PostTask(
2823          FROM_HERE,
2824          base::Bind(
2825              &ExtensionService::TrackTerminatedExtension,
2826              AsWeakPtr(),
2827              host->extension()));
2828      break;
2829    }
2830    case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
2831      content::RenderProcessHost* process =
2832          content::Source<content::RenderProcessHost>(source).ptr();
2833      Profile* host_profile =
2834          Profile::FromBrowserContext(process->GetBrowserContext());
2835      if (!profile_->IsSameProfile(host_profile->GetOriginalProfile()))
2836          break;
2837
2838      // Extensions need to know the channel for API restrictions.
2839      process->Send(new ExtensionMsg_SetChannel(
2840          extensions::GetCurrentChannel()));
2841
2842      // Platform apps need to know the system font.
2843      scoped_ptr<base::DictionaryValue> fonts(new base::DictionaryValue);
2844      webui::SetFontAndTextDirection(fonts.get());
2845      std::string font_family, font_size;
2846      fonts->GetString("fontfamily", &font_family);
2847      fonts->GetString("fontsize", &font_size);
2848      process->Send(new ExtensionMsg_SetSystemFont(
2849          font_family, font_size));
2850
2851      // Valid extension function names, used to setup bindings in renderer.
2852      std::vector<std::string> function_names;
2853      ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names);
2854      process->Send(new ExtensionMsg_SetFunctionNames(function_names));
2855
2856      // Scripting whitelist. This is modified by tests and must be communicated
2857      // to renderers.
2858      process->Send(new ExtensionMsg_SetScriptingWhitelist(
2859          *Extension::GetScriptingWhitelist()));
2860
2861      // Loaded extensions.
2862      std::vector<ExtensionMsg_Loaded_Params> loaded_extensions;
2863      for (ExtensionSet::const_iterator iter = extensions_.begin();
2864           iter != extensions_.end(); ++iter) {
2865        // Renderers don't need to know about themes.
2866        if (!(*iter)->is_theme())
2867          loaded_extensions.push_back(ExtensionMsg_Loaded_Params(iter->get()));
2868      }
2869      process->Send(new ExtensionMsg_Loaded(loaded_extensions));
2870      break;
2871    }
2872    case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
2873      content::RenderProcessHost* process =
2874          content::Source<content::RenderProcessHost>(source).ptr();
2875      Profile* host_profile =
2876          Profile::FromBrowserContext(process->GetBrowserContext());
2877      if (!profile_->IsSameProfile(host_profile->GetOriginalProfile()))
2878          break;
2879
2880      process_map_.RemoveAllFromProcess(process->GetID());
2881      BrowserThread::PostTask(
2882          BrowserThread::IO, FROM_HERE,
2883          base::Bind(&ExtensionInfoMap::UnregisterAllExtensionsInProcess,
2884                     system_->info_map(),
2885                     process->GetID()));
2886      break;
2887    }
2888    case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
2889      extensions::ExtensionHost* host =
2890          content::Details<extensions::ExtensionHost>(details).ptr();
2891      std::string extension_id = host->extension_id();
2892      if (delayed_installs_.Contains(extension_id)) {
2893        // We were waiting for this extension to become idle, it now might have,
2894        // so maybe finish installation.
2895        base::MessageLoop::current()->PostDelayedTask(
2896            FROM_HERE,
2897            base::Bind(&ExtensionService::MaybeFinishDelayedInstallation,
2898                       AsWeakPtr(), extension_id),
2899            base::TimeDelta::FromSeconds(kUpdateIdleDelay));
2900      }
2901      break;
2902    }
2903    case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: {
2904      // Notify extensions that chrome update is available.
2905      extensions::RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent(
2906          profile_);
2907
2908      // Notify observers that chrome update is available.
2909      FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
2910                        OnChromeUpdateAvailable());
2911      break;
2912    }
2913
2914    default:
2915      NOTREACHED() << "Unexpected notification type.";
2916  }
2917}
2918
2919void ExtensionService::OnExtensionInstallPrefChanged() {
2920  IdentifyAlertableExtensions();
2921  CheckManagementPolicy();
2922}
2923
2924bool ExtensionService::HasApps() const {
2925  return !GetAppIds().empty();
2926}
2927
2928ExtensionIdSet ExtensionService::GetAppIds() const {
2929  ExtensionIdSet result;
2930  for (ExtensionSet::const_iterator it = extensions_.begin();
2931       it != extensions_.end(); ++it) {
2932    if ((*it)->is_app() && (*it)->location() != Manifest::COMPONENT)
2933      result.insert((*it)->id());
2934  }
2935
2936  return result;
2937}
2938
2939bool ExtensionService::IsBackgroundPageReady(const Extension* extension) const {
2940  if (!extensions::BackgroundInfo::HasPersistentBackgroundPage(extension))
2941    return true;
2942  ExtensionRuntimeDataMap::const_iterator it =
2943      extension_runtime_data_.find(extension->id());
2944  return it == extension_runtime_data_.end() ? false :
2945                                               it->second.background_page_ready;
2946}
2947
2948void ExtensionService::SetBackgroundPageReady(const Extension* extension) {
2949  DCHECK(extensions::BackgroundInfo::HasBackgroundPage(extension));
2950  extension_runtime_data_[extension->id()].background_page_ready = true;
2951  content::NotificationService::current()->Notify(
2952      chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
2953      content::Source<const Extension>(extension),
2954      content::NotificationService::NoDetails());
2955}
2956
2957bool ExtensionService::IsBeingUpgraded(const Extension* extension) const {
2958  ExtensionRuntimeDataMap::const_iterator it =
2959      extension_runtime_data_.find(extension->id());
2960  return it == extension_runtime_data_.end() ? false :
2961                                               it->second.being_upgraded;
2962}
2963
2964void ExtensionService::SetBeingUpgraded(const Extension* extension,
2965                                        bool value) {
2966  extension_runtime_data_[extension->id()].being_upgraded = value;
2967}
2968
2969bool ExtensionService::IsBeingReloaded(
2970    const std::string& extension_id) const {
2971  return ContainsKey(extensions_being_reloaded_, extension_id);
2972}
2973
2974void ExtensionService::SetBeingReloaded(const std::string& extension_id,
2975                                        bool isBeingReloaded) {
2976  if (isBeingReloaded)
2977    extensions_being_reloaded_.insert(extension_id);
2978  else
2979    extensions_being_reloaded_.erase(extension_id);
2980}
2981
2982bool ExtensionService::HasUsedWebRequest(const Extension* extension) const {
2983  ExtensionRuntimeDataMap::const_iterator it =
2984      extension_runtime_data_.find(extension->id());
2985  return it == extension_runtime_data_.end() ? false :
2986                                               it->second.has_used_webrequest;
2987}
2988
2989void ExtensionService::SetHasUsedWebRequest(const Extension* extension,
2990                                            bool value) {
2991  extension_runtime_data_[extension->id()].has_used_webrequest = value;
2992}
2993
2994bool ExtensionService::ShouldEnableOnInstall(const Extension* extension) {
2995  // Extensions installed by policy can't be disabled. So even if a previous
2996  // installation disabled the extension, make sure it is now enabled.
2997  if (system_->management_policy()->MustRemainEnabled(extension, NULL))
2998    return true;
2999
3000  if (extension_prefs_->IsExtensionDisabled(extension->id()))
3001    return false;
3002
3003  if (FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) {
3004    // External extensions are initially disabled. We prompt the user before
3005    // enabling them. Hosted apps are excepted because they are not dangerous
3006    // (they need to be launched by the user anyway).
3007    if (extension->GetType() != Manifest::TYPE_HOSTED_APP &&
3008        Manifest::IsExternalLocation(extension->location()) &&
3009        !extension_prefs_->IsExternalExtensionAcknowledged(extension->id())) {
3010      return false;
3011    }
3012  }
3013
3014  return true;
3015}
3016
3017bool ExtensionService::IsExtensionIdle(const std::string& extension_id) const {
3018  ExtensionProcessManager* process_manager = system_->process_manager();
3019  DCHECK(process_manager);
3020  extensions::ExtensionHost* host =
3021      process_manager->GetBackgroundHostForExtension(extension_id);
3022  if (host)
3023    return false;
3024  return process_manager->GetRenderViewHostsForExtension(extension_id).empty();
3025}
3026
3027bool ExtensionService::ShouldDelayExtensionUpdate(
3028    const std::string& extension_id,
3029    bool wait_for_idle) const {
3030  const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable";
3031
3032  // If delayed updates are globally disabled, or just for this extension,
3033  // don't delay.
3034  if (!install_updates_when_idle_ || !wait_for_idle)
3035    return false;
3036
3037  const Extension* old = GetInstalledExtension(extension_id);
3038  // If there is no old extension, this is not an update, so don't delay.
3039  if (!old)
3040    return false;
3041
3042  if (extensions::BackgroundInfo::HasPersistentBackgroundPage(old)) {
3043    // Delay installation if the extension listens for the onUpdateAvailable
3044    // event.
3045    return system_->event_router()->ExtensionHasEventListener(
3046        extension_id, kOnUpdateAvailableEvent);
3047  } else {
3048    // Delay installation if the extension is not idle.
3049    return !IsExtensionIdle(extension_id);
3050  }
3051}
3052
3053void ExtensionService::GarbageCollectIsolatedStorage() {
3054  scoped_ptr<base::hash_set<base::FilePath> > active_paths(
3055      new base::hash_set<base::FilePath>());
3056  for (ExtensionSet::const_iterator it = extensions_.begin();
3057       it != extensions_.end(); ++it) {
3058    if (extensions::AppIsolationInfo::HasIsolatedStorage(it->get())) {
3059      active_paths->insert(BrowserContext::GetStoragePartitionForSite(
3060          profile_, GetSiteForExtensionId((*it)->id()))->GetPath());
3061    }
3062  }
3063
3064  DCHECK(!installs_delayed_for_gc());
3065  set_installs_delayed_for_gc(true);
3066  BrowserContext::GarbageCollectStoragePartitions(
3067      profile_, active_paths.Pass(),
3068      base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished,
3069                 AsWeakPtr()));
3070}
3071
3072void ExtensionService::OnGarbageCollectIsolatedStorageFinished() {
3073  set_installs_delayed_for_gc(false);
3074  MaybeFinishDelayedInstallations();
3075}
3076
3077void ExtensionService::MaybeFinishDelayedInstallations() {
3078  std::vector<std::string> to_be_installed;
3079  for (ExtensionSet::const_iterator it = delayed_installs_.begin();
3080       it != delayed_installs_.end();
3081       ++it) {
3082    to_be_installed.push_back((*it)->id());
3083  }
3084  for (std::vector<std::string>::const_iterator it = to_be_installed.begin();
3085       it != to_be_installed.end();
3086       ++it) {
3087    MaybeFinishDelayedInstallation(*it);
3088  }
3089}
3090
3091void ExtensionService::OnNeedsToGarbageCollectIsolatedStorage() {
3092  extension_prefs_->SetNeedsStorageGarbageCollection(true);
3093}
3094
3095void ExtensionService::OnBlacklistUpdated() {
3096  blacklist_->GetBlacklistedIDs(
3097      GenerateInstalledExtensionsSet()->GetIDs(),
3098      base::Bind(&ExtensionService::ManageBlacklist,
3099                 AsWeakPtr(),
3100                 blacklisted_extensions_.GetIDs()));
3101}
3102
3103void ExtensionService::ManageBlacklist(
3104    const std::set<std::string>& old_blacklisted_ids,
3105    const std::set<std::string>& new_blacklisted_ids) {
3106  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3107
3108  std::set<std::string> no_longer_blacklisted =
3109      base::STLSetDifference<std::set<std::string> >(old_blacklisted_ids,
3110                                                     new_blacklisted_ids);
3111  std::set<std::string> not_yet_blacklisted =
3112      base::STLSetDifference<std::set<std::string> >(new_blacklisted_ids,
3113                                                     old_blacklisted_ids);
3114
3115  for (std::set<std::string>::iterator it = no_longer_blacklisted.begin();
3116       it != no_longer_blacklisted.end(); ++it) {
3117    scoped_refptr<const Extension> extension =
3118        blacklisted_extensions_.GetByID(*it);
3119    DCHECK(extension.get()) << "Extension " << *it << " no longer blacklisted, "
3120                            << "but it was never blacklisted.";
3121    if (!extension.get())
3122      continue;
3123    blacklisted_extensions_.Remove(*it);
3124    AddExtension(extension.get());
3125    UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled",
3126                              extension->location(),
3127                              Manifest::NUM_LOCATIONS);
3128  }
3129
3130  for (std::set<std::string>::iterator it = not_yet_blacklisted.begin();
3131       it != not_yet_blacklisted.end(); ++it) {
3132    scoped_refptr<const Extension> extension = GetInstalledExtension(*it);
3133    DCHECK(extension.get()) << "Extension " << *it << " needs to be "
3134                            << "blacklisted, but it's not installed.";
3135    if (!extension.get())
3136      continue;
3137    blacklisted_extensions_.Insert(extension);
3138    UnloadExtension(*it, extension_misc::UNLOAD_REASON_BLACKLIST);
3139    UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled",
3140                              extension->location(), Manifest::NUM_LOCATIONS);
3141  }
3142
3143  IdentifyAlertableExtensions();
3144}
3145
3146void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) {
3147  update_observers_.AddObserver(observer);
3148}
3149
3150void ExtensionService::RemoveUpdateObserver(
3151    extensions::UpdateObserver* observer) {
3152  update_observers_.RemoveObserver(observer);
3153}
3154