// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/error_console/error_console.h"

#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/error_console/error_console_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/crx_file/id_util.h"
#include "components/prefs/pref_service.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/features/feature_channel.h"

namespace extensions {

namespace {

// The key into the Extension prefs for an Extension's specific reporting
// settings.
const char kStoreExtensionErrorsPref[] = "store_extension_errors";

// This is the default mask for which errors to report. That is, if an extension
// does not have specific preference set, this will be used instead.
const int kDefaultMask = 0;

const char kAppsDeveloperToolsExtensionId[] =
    "ohmmkhmmmpcnpikjeljgnaoabkaalbgc";

}  // namespace

void ErrorConsole::Observer::OnErrorAdded(const ExtensionError* error) {
}

void ErrorConsole::Observer::OnErrorsRemoved(
    const std::set<std::string>& extension_ids) {
}

void ErrorConsole::Observer::OnErrorConsoleDestroyed() {
}

ErrorConsole::ErrorConsole(Profile* profile)
    : enabled_(false),
      default_mask_(kDefaultMask),
      profile_(profile),
      prefs_(nullptr),
      registry_observer_(this) {
  pref_registrar_.Init(profile_->GetPrefs());
  pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode,
                      base::Bind(&ErrorConsole::OnPrefChanged,
                                 base::Unretained(this)));

  registry_observer_.Add(ExtensionRegistry::Get(profile_));

  CheckEnabled();
}

ErrorConsole::~ErrorConsole() {
  for (auto& observer : observers_)
    observer.OnErrorConsoleDestroyed();
}

// static
ErrorConsole* ErrorConsole::Get(content::BrowserContext* browser_context) {
  return ErrorConsoleFactory::GetForBrowserContext(browser_context);
}

void ErrorConsole::SetReportingForExtension(const std::string& extension_id,
                                            ExtensionError::Type type,
                                            bool enabled) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
    return;

  int mask = default_mask_;
  // This call can fail if the preference isn't set, but we don't really care
  // if it does, because we just use the default mask instead.
  prefs_->ReadPrefAsInteger(extension_id, kStoreExtensionErrorsPref, &mask);

  if (enabled)
    mask |= 1 << type;
  else
    mask &= ~(1 << type);

  prefs_->UpdateExtensionPref(extension_id, kStoreExtensionErrorsPref,
                              std::make_unique<base::Value>(mask));
}

void ErrorConsole::SetReportingAllForExtension(
    const std::string& extension_id, bool enabled) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
    return;

  int mask = enabled ? (1 << ExtensionError::NUM_ERROR_TYPES) - 1 : 0;

  prefs_->UpdateExtensionPref(extension_id, kStoreExtensionErrorsPref,
                              std::make_unique<base::Value>(mask));
}

bool ErrorConsole::IsReportingEnabledForExtension(
    const std::string& extension_id) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
    return false;

  return GetMaskForExtension(extension_id) != 0;
}

void ErrorConsole::UseDefaultReportingForExtension(
    const std::string& extension_id) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!enabled_ || !crx_file::id_util::IdIsValid(extension_id))
    return;

  prefs_->UpdateExtensionPref(extension_id, kStoreExtensionErrorsPref, nullptr);
}

void ErrorConsole::ReportError(std::unique_ptr<ExtensionError> error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!enabled_ || !crx_file::id_util::IdIsValid(error->extension_id()))
    return;

  DCHECK_GE(error->level(), extension_misc::kMinimumSeverityToReportError)
      << "Errors less than severity warning should not be reported.";

  int mask = GetMaskForExtension(error->extension_id());
  if (!(mask & (1 << error->type())))
    return;

  const ExtensionError* weak_error = errors_.AddError(std::move(error));
  for (auto& observer : observers_)
    observer.OnErrorAdded(weak_error);
}

void ErrorConsole::RemoveErrors(const ErrorMap::Filter& filter) {
  std::set<std::string> affected_ids;
  errors_.RemoveErrors(filter, &affected_ids);
  for (auto& observer : observers_)
    observer.OnErrorsRemoved(affected_ids);
}

const ErrorList& ErrorConsole::GetErrorsForExtension(
    const std::string& extension_id) const {
  return errors_.GetErrorsForExtension(extension_id);
}

void ErrorConsole::AddObserver(Observer* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  observers_.AddObserver(observer);
}

void ErrorConsole::RemoveObserver(Observer* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  observers_.RemoveObserver(observer);
}

bool ErrorConsole::IsEnabledForChromeExtensionsPage() const {
  return profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
}

bool ErrorConsole::IsEnabledForAppsDeveloperTools() const {
  return ExtensionRegistry::Get(profile_)->enabled_extensions()
      .Contains(kAppsDeveloperToolsExtensionId);
}

void ErrorConsole::CheckEnabled() {
  bool should_be_enabled = IsEnabledForChromeExtensionsPage() ||
                           IsEnabledForAppsDeveloperTools();
  if (should_be_enabled && !enabled_)
    Enable();
  if (!should_be_enabled && enabled_)
    Disable();
}

void ErrorConsole::Enable() {
  enabled_ = true;

  // We postpone the initialization of |prefs_| until now because they can be
  // nullptr in unit_tests. Any unit tests that enable the error console should
  // also create an ExtensionPrefs object.
  prefs_ = ExtensionPrefs::Get(profile_);

  notification_registrar_.Add(
      this,
      chrome::NOTIFICATION_PROFILE_DESTROYED,
      content::NotificationService::AllBrowserContextsAndSources());

  const ExtensionSet& extensions =
      ExtensionRegistry::Get(profile_)->enabled_extensions();
  for (ExtensionSet::const_iterator iter = extensions.begin();
       iter != extensions.end();
       ++iter) {
    AddManifestErrorsForExtension(iter->get());
  }
}

void ErrorConsole::Disable() {
  notification_registrar_.RemoveAll();
  errors_.RemoveAllErrors();
  enabled_ = false;
}

void ErrorConsole::OnPrefChanged() {
  CheckEnabled();
}

void ErrorConsole::OnExtensionUnloaded(content::BrowserContext* browser_context,
                                       const Extension* extension,
                                       UnloadedExtensionReason reason) {
  CheckEnabled();
}

void ErrorConsole::OnExtensionLoaded(content::BrowserContext* browser_context,
                                     const Extension* extension) {
  CheckEnabled();
}

void ErrorConsole::OnExtensionInstalled(
    content::BrowserContext* browser_context,
    const Extension* extension,
    bool is_update) {
  // We don't want to have manifest errors from previous installs. We want
  // to keep runtime errors, though, because extensions are reloaded on a
  // refresh of chrome:extensions, and we don't want to wipe our history
  // whenever that happens.
  errors_.RemoveErrors(ErrorMap::Filter::ErrorsForExtensionWithType(
      extension->id(), ExtensionError::MANIFEST_ERROR), nullptr);
  AddManifestErrorsForExtension(extension);
}

void ErrorConsole::OnExtensionUninstalled(
    content::BrowserContext* browser_context,
    const Extension* extension,
    extensions::UninstallReason reason) {
  errors_.RemoveErrors(ErrorMap::Filter::ErrorsForExtension(extension->id()),
                       nullptr);
}

void ErrorConsole::AddManifestErrorsForExtension(const Extension* extension) {
  const std::vector<InstallWarning>& warnings =
      extension->install_warnings();
  for (auto iter = warnings.begin(); iter != warnings.end(); ++iter) {
    ReportError(std::unique_ptr<ExtensionError>(new ManifestError(
        extension->id(), base::UTF8ToUTF16(iter->message),
        base::UTF8ToUTF16(iter->key), base::UTF8ToUTF16(iter->specific))));
  }
}

void ErrorConsole::Observe(int type,
                           const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
  DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
  Profile* profile = content::Source<Profile>(source).ptr();
  // If incognito profile which we are associated with is destroyed, also
  // destroy all incognito errors.
  if (profile->IsOffTheRecord() && profile_->IsSameProfile(profile))
    errors_.RemoveErrors(ErrorMap::Filter::IncognitoErrors(), nullptr);
}

int ErrorConsole::GetMaskForExtension(const std::string& extension_id) const {
  // Registered preferences take priority over everything else.
  int pref = 0;
  if (prefs_->ReadPrefAsInteger(extension_id, kStoreExtensionErrorsPref, &pref))
    return pref;

  // If the extension is unpacked, we report all error types by default.
  const Extension* extension =
      ExtensionRegistry::Get(profile_)->GetExtensionById(
          extension_id, ExtensionRegistry::EVERYTHING);
  if (extension && extension->location() == Manifest::UNPACKED)
    return (1 << ExtensionError::NUM_ERROR_TYPES) - 1;

  // Otherwise, use the default mask.
  return default_mask_;
}

}  // namespace extensions
