// Copyright (c) 2012 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.

// Implementation of the Chrome Extensions Proxy Settings API.

#include "chrome/browser/extensions/api/proxy/proxy_api.h"

#include <memory>
#include <utility>

#include "base/json/json_writer.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/proxy/proxy_api_constants.h"
#include "chrome/browser/extensions/api/proxy/proxy_api_helpers.h"
#include "chrome/browser/extensions/event_router_forwarder.h"
#include "chrome/browser/extensions/extension_service.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "net/base/net_errors.h"

namespace extensions {

namespace helpers = proxy_api_helpers;
namespace keys = proxy_api_constants;

// static
ProxyEventRouter* ProxyEventRouter::GetInstance() {
  return base::Singleton<ProxyEventRouter>::get();
}

ProxyEventRouter::ProxyEventRouter() {
}

ProxyEventRouter::~ProxyEventRouter() {
}

void ProxyEventRouter::OnProxyError(
    EventRouterForwarder* event_router,
    void* profile,
    int error_code) {
  std::unique_ptr<base::ListValue> args(new base::ListValue());
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  dict->SetBoolean(keys::kProxyEventFatal, true);
  dict->SetString(keys::kProxyEventError, net::ErrorToString(error_code));
  dict->SetString(keys::kProxyEventDetails, std::string());
  args->Append(std::move(dict));

  if (profile) {
    event_router->DispatchEventToRenderers(
        events::PROXY_ON_PROXY_ERROR, keys::kProxyEventOnProxyError,
        std::move(args), profile, true, GURL());
  } else {
    event_router->BroadcastEventToRenderers(events::PROXY_ON_PROXY_ERROR,
                                            keys::kProxyEventOnProxyError,
                                            std::move(args), GURL());
  }
}

void ProxyEventRouter::OnPACScriptError(
    EventRouterForwarder* event_router,
    void* profile,
    int line_number,
    const base::string16& error) {
  std::unique_ptr<base::ListValue> args(new base::ListValue());
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  dict->SetBoolean(keys::kProxyEventFatal, false);
  dict->SetString(keys::kProxyEventError,
                  net::ErrorToString(net::ERR_PAC_SCRIPT_FAILED));
  std::string error_msg;
  if (line_number != -1) {
    base::SStringPrintf(&error_msg,
                        "line: %d: %s",
                        line_number, base::UTF16ToUTF8(error).c_str());
  } else {
    error_msg = base::UTF16ToUTF8(error);
  }
  dict->SetString(keys::kProxyEventDetails, error_msg);
  args->Append(std::move(dict));

  if (profile) {
    event_router->DispatchEventToRenderers(
        events::PROXY_ON_PROXY_ERROR, keys::kProxyEventOnProxyError,
        std::move(args), profile, true, GURL());
  } else {
    event_router->BroadcastEventToRenderers(events::PROXY_ON_PROXY_ERROR,
                                            keys::kProxyEventOnProxyError,
                                            std::move(args), GURL());
  }
}

ProxyPrefTransformer::ProxyPrefTransformer() {
}

ProxyPrefTransformer::~ProxyPrefTransformer() {
}

base::Value* ProxyPrefTransformer::ExtensionToBrowserPref(
    const base::Value* extension_pref,
    std::string* error,
    bool* bad_message) {
  // When ExtensionToBrowserPref is called, the format of |extension_pref|
  // has been verified already by the extension API to match the schema
  // defined in the extension API JSON.
  CHECK(extension_pref->IsType(base::Value::TYPE_DICTIONARY));
  const base::DictionaryValue* config =
      static_cast<const base::DictionaryValue*>(extension_pref);

  // Extract the various pieces of information passed to
  // chrome.proxy.settings.set(). Several of these strings will
  // remain blank no respective values have been passed to set().
  // If a values has been passed to set but could not be parsed, we bail
  // out and return NULL.
  ProxyPrefs::ProxyMode mode_enum;
  bool pac_mandatory;
  std::string pac_url;
  std::string pac_data;
  std::string proxy_rules_string;
  std::string bypass_list;
  if (!helpers::GetProxyModeFromExtensionPref(
          config, &mode_enum, error, bad_message) ||
      !helpers::GetPacMandatoryFromExtensionPref(
          config, &pac_mandatory, error, bad_message) ||
      !helpers::GetPacUrlFromExtensionPref(
          config, &pac_url, error, bad_message) ||
      !helpers::GetPacDataFromExtensionPref(
          config, &pac_data, error, bad_message) ||
      !helpers::GetProxyRulesStringFromExtensionPref(
          config, &proxy_rules_string, error, bad_message) ||
      !helpers::GetBypassListFromExtensionPref(
          config, &bypass_list, error, bad_message)) {
    return NULL;
  }

  return helpers::CreateProxyConfigDict(
      mode_enum, pac_mandatory, pac_url, pac_data, proxy_rules_string,
      bypass_list, error);
}

base::Value* ProxyPrefTransformer::BrowserToExtensionPref(
    const base::Value* browser_pref) {
  CHECK(browser_pref->IsType(base::Value::TYPE_DICTIONARY));

  // This is a dictionary wrapper that exposes the proxy configuration stored in
  // the browser preferences.
  ProxyConfigDictionary config(
      static_cast<const base::DictionaryValue*>(browser_pref));

  ProxyPrefs::ProxyMode mode;
  if (!config.GetMode(&mode)) {
    LOG(ERROR) << "Cannot determine proxy mode.";
    return NULL;
  }

  // Build a new ProxyConfig instance as defined in the extension API.
  std::unique_ptr<base::DictionaryValue> extension_pref(
      new base::DictionaryValue);

  extension_pref->SetString(keys::kProxyConfigMode,
                            ProxyPrefs::ProxyModeToString(mode));

  switch (mode) {
    case ProxyPrefs::MODE_DIRECT:
    case ProxyPrefs::MODE_AUTO_DETECT:
    case ProxyPrefs::MODE_SYSTEM:
      // These modes have no further parameters.
      break;
    case ProxyPrefs::MODE_PAC_SCRIPT: {
      // A PAC URL either point to a PAC script or contain a base64 encoded
      // PAC script. In either case we build a PacScript dictionary as defined
      // in the extension API.
      base::DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config);
      if (!pac_dict)
        return NULL;
      extension_pref->Set(keys::kProxyConfigPacScript, pac_dict);
      break;
    }
    case ProxyPrefs::MODE_FIXED_SERVERS: {
      // Build ProxyRules dictionary according to the extension API.
      base::DictionaryValue* proxy_rules_dict =
          helpers::CreateProxyRulesDict(config);
      if (!proxy_rules_dict)
        return NULL;
      extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict);
      break;
    }
    case ProxyPrefs::kModeCount:
      NOTREACHED();
  }
  return extension_pref.release();
}

}  // namespace extensions
