// 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.

#include "extensions/browser/api/declarative_webrequest/webrequest_action.h"

#include <limits>
#include <utility>

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/api/declarative/deduping_factory.h"
#include "extensions/browser/api/declarative_webrequest/request_stage.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_condition.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
#include "extensions/browser/api/web_request/web_request_api_constants.h"
#include "extensions/browser/api/web_request/web_request_api_helpers.h"
#include "extensions/browser/api/web_request/web_request_permissions.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#include "extensions/browser/info_map.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
#include "third_party/re2/src/re2/re2.h"

using content::ResourceRequestInfo;

namespace extensions {

namespace helpers = extension_web_request_api_helpers;
namespace keys = declarative_webrequest_constants;

namespace {
// Error messages.
const char kIgnoreRulesRequiresParameterError[] =
    "IgnoreRules requires at least one parameter.";

const char kTransparentImageUrl[] = "data:image/png;base64,iVBORw0KGgoAAAANSUh"
    "EUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
const char kEmptyDocumentUrl[] = "data:text/html,";

#define INPUT_FORMAT_VALIDATE(test) do { \
    if (!(test)) { \
      *bad_message = true; \
      return scoped_refptr<const WebRequestAction>(NULL); \
    } \
  } while (0)

std::unique_ptr<helpers::RequestCookie> ParseRequestCookie(
    const base::DictionaryValue* dict) {
  std::unique_ptr<helpers::RequestCookie> result(new helpers::RequestCookie);
  std::string tmp;
  if (dict->GetString(keys::kNameKey, &tmp))
    result->name.reset(new std::string(tmp));
  if (dict->GetString(keys::kValueKey, &tmp))
    result->value.reset(new std::string(tmp));
  return result;
}

void ParseResponseCookieImpl(const base::DictionaryValue* dict,
                             helpers::ResponseCookie* cookie) {
  std::string string_tmp;
  int int_tmp = 0;
  bool bool_tmp = false;
  if (dict->GetString(keys::kNameKey, &string_tmp))
    cookie->name.reset(new std::string(string_tmp));
  if (dict->GetString(keys::kValueKey, &string_tmp))
    cookie->value.reset(new std::string(string_tmp));
  if (dict->GetString(keys::kExpiresKey, &string_tmp))
    cookie->expires.reset(new std::string(string_tmp));
  if (dict->GetInteger(keys::kMaxAgeKey, &int_tmp))
    cookie->max_age.reset(new int(int_tmp));
  if (dict->GetString(keys::kDomainKey, &string_tmp))
    cookie->domain.reset(new std::string(string_tmp));
  if (dict->GetString(keys::kPathKey, &string_tmp))
    cookie->path.reset(new std::string(string_tmp));
  if (dict->GetBoolean(keys::kSecureKey, &bool_tmp))
    cookie->secure.reset(new bool(bool_tmp));
  if (dict->GetBoolean(keys::kHttpOnlyKey, &bool_tmp))
    cookie->http_only.reset(new bool(bool_tmp));
}

std::unique_ptr<helpers::ResponseCookie> ParseResponseCookie(
    const base::DictionaryValue* dict) {
  std::unique_ptr<helpers::ResponseCookie> result(new helpers::ResponseCookie);
  ParseResponseCookieImpl(dict, result.get());
  return result;
}

std::unique_ptr<helpers::FilterResponseCookie> ParseFilterResponseCookie(
    const base::DictionaryValue* dict) {
  std::unique_ptr<helpers::FilterResponseCookie> result(
      new helpers::FilterResponseCookie);
  ParseResponseCookieImpl(dict, result.get());

  int int_tmp = 0;
  bool bool_tmp = false;
  if (dict->GetInteger(keys::kAgeUpperBoundKey, &int_tmp))
    result->age_upper_bound.reset(new int(int_tmp));
  if (dict->GetInteger(keys::kAgeLowerBoundKey, &int_tmp))
    result->age_lower_bound.reset(new int(int_tmp));
  if (dict->GetBoolean(keys::kSessionCookieKey, &bool_tmp))
    result->session_cookie.reset(new bool(bool_tmp));
  return result;
}

// Helper function for WebRequestActions that can be instantiated by just
// calling the constructor.
template <class T>
scoped_refptr<const WebRequestAction> CallConstructorFactoryMethod(
    const std::string& instance_type,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  return scoped_refptr<const WebRequestAction>(new T);
}

scoped_refptr<const WebRequestAction> CreateRedirectRequestAction(
    const std::string& instance_type,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(value->GetAsDictionary(&dict));
  std::string redirect_url_string;
  INPUT_FORMAT_VALIDATE(
      dict->GetString(keys::kRedirectUrlKey, &redirect_url_string));
  GURL redirect_url(redirect_url_string);
  return scoped_refptr<const WebRequestAction>(
      new WebRequestRedirectAction(redirect_url));
}

scoped_refptr<const WebRequestAction> CreateRedirectRequestByRegExAction(
    const std::string& instance_type,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(value->GetAsDictionary(&dict));
  std::string from;
  std::string to;
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kFromKey, &from));
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kToKey, &to));

  to = WebRequestRedirectByRegExAction::PerlToRe2Style(to);

  RE2::Options options;
  options.set_case_sensitive(false);
  std::unique_ptr<RE2> from_pattern(new RE2(from, options));

  if (!from_pattern->ok()) {
    *error = "Invalid pattern '" + from + "' -> '" + to + "'";
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  return scoped_refptr<const WebRequestAction>(
      new WebRequestRedirectByRegExAction(std::move(from_pattern), to));
}

scoped_refptr<const WebRequestAction> CreateSetRequestHeaderAction(
    const std::string& instance_type,
    const base::Value* json_value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(json_value->GetAsDictionary(&dict));
  std::string name;
  std::string value;
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kValueKey, &value));
  if (!net::HttpUtil::IsValidHeaderName(name)) {
    *error = extension_web_request_api_constants::kInvalidHeaderName;
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  if (!net::HttpUtil::IsValidHeaderValue(value)) {
    *error = ErrorUtils::FormatErrorMessage(
        extension_web_request_api_constants::kInvalidHeaderValue, name);
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  return scoped_refptr<const WebRequestAction>(
      new WebRequestSetRequestHeaderAction(name, value));
}

scoped_refptr<const WebRequestAction> CreateRemoveRequestHeaderAction(
    const std::string& instance_type,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(value->GetAsDictionary(&dict));
  std::string name;
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
  if (!net::HttpUtil::IsValidHeaderName(name)) {
    *error = extension_web_request_api_constants::kInvalidHeaderName;
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  return scoped_refptr<const WebRequestAction>(
      new WebRequestRemoveRequestHeaderAction(name));
}

scoped_refptr<const WebRequestAction> CreateAddResponseHeaderAction(
    const std::string& instance_type,
    const base::Value* json_value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(json_value->GetAsDictionary(&dict));
  std::string name;
  std::string value;
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kValueKey, &value));
  if (!net::HttpUtil::IsValidHeaderName(name)) {
    *error = extension_web_request_api_constants::kInvalidHeaderName;
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  if (!net::HttpUtil::IsValidHeaderValue(value)) {
    *error = ErrorUtils::FormatErrorMessage(
        extension_web_request_api_constants::kInvalidHeaderValue, name);
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  return scoped_refptr<const WebRequestAction>(
      new WebRequestAddResponseHeaderAction(name, value));
}

scoped_refptr<const WebRequestAction> CreateRemoveResponseHeaderAction(
    const std::string& instance_type,
    const base::Value* json_value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(json_value->GetAsDictionary(&dict));
  std::string name;
  std::string value;
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
  bool has_value = dict->GetString(keys::kValueKey, &value);
  if (!net::HttpUtil::IsValidHeaderName(name)) {
    *error = extension_web_request_api_constants::kInvalidHeaderName;
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  if (has_value && !net::HttpUtil::IsValidHeaderValue(value)) {
    *error = ErrorUtils::FormatErrorMessage(
        extension_web_request_api_constants::kInvalidHeaderValue, name);
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  return scoped_refptr<const WebRequestAction>(
      new WebRequestRemoveResponseHeaderAction(name, value, has_value));
}

scoped_refptr<const WebRequestAction> CreateIgnoreRulesAction(
    const std::string& instance_type,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(value->GetAsDictionary(&dict));
  bool has_parameter = false;
  int minimum_priority = std::numeric_limits<int>::min();
  std::string ignore_tag;
  if (dict->HasKey(keys::kLowerPriorityThanKey)) {
    INPUT_FORMAT_VALIDATE(
        dict->GetInteger(keys::kLowerPriorityThanKey, &minimum_priority));
    has_parameter = true;
  }
  if (dict->HasKey(keys::kHasTagKey)) {
    INPUT_FORMAT_VALIDATE(dict->GetString(keys::kHasTagKey, &ignore_tag));
    has_parameter = true;
  }
  if (!has_parameter) {
    *error = kIgnoreRulesRequiresParameterError;
    return scoped_refptr<const WebRequestAction>(NULL);
  }
  return scoped_refptr<const WebRequestAction>(
      new WebRequestIgnoreRulesAction(minimum_priority, ignore_tag));
}

scoped_refptr<const WebRequestAction> CreateRequestCookieAction(
    const std::string& instance_type,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  using extension_web_request_api_helpers::RequestCookieModification;

  const base::DictionaryValue* dict = NULL;
  CHECK(value->GetAsDictionary(&dict));

  linked_ptr<RequestCookieModification> modification(
      new RequestCookieModification);

  // Get modification type.
  if (instance_type == keys::kAddRequestCookieType)
    modification->type = helpers::ADD;
  else if (instance_type == keys::kEditRequestCookieType)
    modification->type = helpers::EDIT;
  else if (instance_type == keys::kRemoveRequestCookieType)
    modification->type = helpers::REMOVE;
  else
    INPUT_FORMAT_VALIDATE(false);

  // Get filter.
  if (modification->type == helpers::EDIT ||
      modification->type == helpers::REMOVE) {
    const base::DictionaryValue* filter = NULL;
    INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kFilterKey, &filter));
    modification->filter = ParseRequestCookie(filter);
  }

  // Get new value.
  if (modification->type == helpers::ADD) {
    const base::DictionaryValue* value = NULL;
    INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kCookieKey, &value));
    modification->modification = ParseRequestCookie(value);
  } else if (modification->type == helpers::EDIT) {
    const base::DictionaryValue* value = NULL;
    INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kModificationKey, &value));
    modification->modification = ParseRequestCookie(value);
  }

  return scoped_refptr<const WebRequestAction>(
      new WebRequestRequestCookieAction(modification));
}

scoped_refptr<const WebRequestAction> CreateResponseCookieAction(
    const std::string& instance_type,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  using extension_web_request_api_helpers::ResponseCookieModification;

  const base::DictionaryValue* dict = NULL;
  CHECK(value->GetAsDictionary(&dict));

  linked_ptr<ResponseCookieModification> modification(
      new ResponseCookieModification);

  // Get modification type.
  if (instance_type == keys::kAddResponseCookieType)
    modification->type = helpers::ADD;
  else if (instance_type == keys::kEditResponseCookieType)
    modification->type = helpers::EDIT;
  else if (instance_type == keys::kRemoveResponseCookieType)
    modification->type = helpers::REMOVE;
  else
    INPUT_FORMAT_VALIDATE(false);

  // Get filter.
  if (modification->type == helpers::EDIT ||
      modification->type == helpers::REMOVE) {
    const base::DictionaryValue* filter = NULL;
    INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kFilterKey, &filter));
    modification->filter = ParseFilterResponseCookie(filter);
  }

  // Get new value.
  if (modification->type == helpers::ADD) {
    const base::DictionaryValue* value = NULL;
    INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kCookieKey, &value));
    modification->modification = ParseResponseCookie(value);
  } else if (modification->type == helpers::EDIT) {
    const base::DictionaryValue* value = NULL;
    INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kModificationKey, &value));
    modification->modification = ParseResponseCookie(value);
  }

  return scoped_refptr<const WebRequestAction>(
      new WebRequestResponseCookieAction(modification));
}

scoped_refptr<const WebRequestAction> CreateSendMessageToExtensionAction(
    const std::string& name,
    const base::Value* value,
    std::string* error,
    bool* bad_message) {
  const base::DictionaryValue* dict = NULL;
  CHECK(value->GetAsDictionary(&dict));
  std::string message;
  INPUT_FORMAT_VALIDATE(dict->GetString(keys::kMessageKey, &message));
  return scoped_refptr<const WebRequestAction>(
      new WebRequestSendMessageToExtensionAction(message));
}

struct WebRequestActionFactory {
  DedupingFactory<WebRequestAction> factory;

  WebRequestActionFactory() : factory(5) {
    factory.RegisterFactoryMethod(
        keys::kAddRequestCookieType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateRequestCookieAction);
    factory.RegisterFactoryMethod(
        keys::kAddResponseCookieType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateResponseCookieAction);
    factory.RegisterFactoryMethod(
        keys::kAddResponseHeaderType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateAddResponseHeaderAction);
    factory.RegisterFactoryMethod(
        keys::kCancelRequestType,
        DedupingFactory<WebRequestAction>::IS_NOT_PARAMETERIZED,
        &CallConstructorFactoryMethod<WebRequestCancelAction>);
    factory.RegisterFactoryMethod(
        keys::kEditRequestCookieType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateRequestCookieAction);
    factory.RegisterFactoryMethod(
        keys::kEditResponseCookieType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateResponseCookieAction);
    factory.RegisterFactoryMethod(
        keys::kRedirectByRegExType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateRedirectRequestByRegExAction);
    factory.RegisterFactoryMethod(
        keys::kRedirectRequestType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateRedirectRequestAction);
    factory.RegisterFactoryMethod(
        keys::kRedirectToTransparentImageType,
        DedupingFactory<WebRequestAction>::IS_NOT_PARAMETERIZED,
        &CallConstructorFactoryMethod<
            WebRequestRedirectToTransparentImageAction>);
    factory.RegisterFactoryMethod(
        keys::kRedirectToEmptyDocumentType,
        DedupingFactory<WebRequestAction>::IS_NOT_PARAMETERIZED,
        &CallConstructorFactoryMethod<WebRequestRedirectToEmptyDocumentAction>);
    factory.RegisterFactoryMethod(
        keys::kRemoveRequestCookieType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateRequestCookieAction);
    factory.RegisterFactoryMethod(
        keys::kRemoveResponseCookieType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateResponseCookieAction);
    factory.RegisterFactoryMethod(
        keys::kSetRequestHeaderType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateSetRequestHeaderAction);
    factory.RegisterFactoryMethod(
        keys::kRemoveRequestHeaderType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateRemoveRequestHeaderAction);
    factory.RegisterFactoryMethod(
        keys::kRemoveResponseHeaderType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateRemoveResponseHeaderAction);
    factory.RegisterFactoryMethod(
        keys::kIgnoreRulesType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateIgnoreRulesAction);
    factory.RegisterFactoryMethod(
        keys::kSendMessageToExtensionType,
        DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
        &CreateSendMessageToExtensionAction);
  }
};

base::LazyInstance<WebRequestActionFactory>::Leaky
    g_web_request_action_factory = LAZY_INSTANCE_INITIALIZER;

}  // namespace

//
// WebRequestAction
//

WebRequestAction::~WebRequestAction() {}

bool WebRequestAction::Equals(const WebRequestAction* other) const {
  return type() == other->type();
}

bool WebRequestAction::HasPermission(const InfoMap* extension_info_map,
                                     const std::string& extension_id,
                                     const net::URLRequest* request,
                                     bool crosses_incognito) const {
  if (WebRequestPermissions::HideRequest(extension_info_map, request))
    return false;

  // In unit tests we don't have an extension_info_map object here and skip host
  // permission checks.
  if (!extension_info_map)
    return true;

  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
  int process_id = info ? info->GetChildID() : 0;

  // The embedder can always access all hosts from within a <webview>.
  // The same is not true of extensions.
  if (WebViewRendererState::GetInstance()->IsGuest(process_id))
    return true;

  WebRequestPermissions::HostPermissionsCheck permission_check =
      WebRequestPermissions::REQUIRE_ALL_URLS;
  switch (host_permissions_strategy()) {
    case STRATEGY_DEFAULT:  // Default value is already set.
      break;
    case STRATEGY_NONE:
      permission_check = WebRequestPermissions::DO_NOT_CHECK_HOST;
      break;
    case STRATEGY_HOST:
      permission_check = WebRequestPermissions::REQUIRE_HOST_PERMISSION;
      break;
  }
  // TODO(devlin): Pass in the real tab id here.
  return WebRequestPermissions::CanExtensionAccessURL(
             extension_info_map, extension_id, request->url(), -1,
             crosses_incognito,
             permission_check) == PermissionsData::ACCESS_ALLOWED;
}

// static
scoped_refptr<const WebRequestAction> WebRequestAction::Create(
    content::BrowserContext* browser_context,
    const Extension* extension,
    const base::Value& json_action,
    std::string* error,
    bool* bad_message) {
  *error = "";
  *bad_message = false;

  const base::DictionaryValue* action_dict = NULL;
  INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict));

  std::string instance_type;
  INPUT_FORMAT_VALIDATE(
      action_dict->GetString(keys::kInstanceTypeKey, &instance_type));

  WebRequestActionFactory& factory = g_web_request_action_factory.Get();
  return factory.factory.Instantiate(
      instance_type, action_dict, error, bad_message);
}

void WebRequestAction::Apply(const std::string& extension_id,
                             base::Time extension_install_time,
                             ApplyInfo* apply_info) const {
  if (!HasPermission(apply_info->extension_info_map, extension_id,
                     apply_info->request_data.request,
                     apply_info->crosses_incognito))
    return;
  if (stages() & apply_info->request_data.stage) {
    LinkedPtrEventResponseDelta delta = CreateDelta(
        apply_info->request_data, extension_id, extension_install_time);
    if (delta.get())
      apply_info->deltas->push_back(delta);
    if (type() == WebRequestAction::ACTION_IGNORE_RULES) {
      const WebRequestIgnoreRulesAction* ignore_action =
          static_cast<const WebRequestIgnoreRulesAction*>(this);
      if (!ignore_action->ignore_tag().empty())
        apply_info->ignored_tags->insert(ignore_action->ignore_tag());
    }
  }
}

WebRequestAction::WebRequestAction(int stages,
                                   Type type,
                                   int minimum_priority,
                                   HostPermissionsStrategy strategy)
    : stages_(stages),
      type_(type),
      minimum_priority_(minimum_priority),
      host_permissions_strategy_(strategy) {}

//
// WebRequestCancelAction
//

WebRequestCancelAction::WebRequestCancelAction()
    : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS |
                           ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED,
                       ACTION_CANCEL_REQUEST,
                       std::numeric_limits<int>::min(),
                       STRATEGY_NONE) {}

WebRequestCancelAction::~WebRequestCancelAction() {}

std::string WebRequestCancelAction::GetName() const {
  return keys::kCancelRequestType;
}

LinkedPtrEventResponseDelta WebRequestCancelAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  result->cancel = true;
  return result;
}

//
// WebRequestRedirectAction
//

WebRequestRedirectAction::WebRequestRedirectAction(const GURL& redirect_url)
    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                       ACTION_REDIRECT_REQUEST,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      redirect_url_(redirect_url) {}

WebRequestRedirectAction::~WebRequestRedirectAction() {}

bool WebRequestRedirectAction::Equals(const WebRequestAction* other) const {
  return WebRequestAction::Equals(other) &&
         redirect_url_ ==
             static_cast<const WebRequestRedirectAction*>(other)->redirect_url_;
}

std::string WebRequestRedirectAction::GetName() const {
  return keys::kRedirectRequestType;
}

LinkedPtrEventResponseDelta WebRequestRedirectAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  if (request_data.request->url() == redirect_url_)
    return LinkedPtrEventResponseDelta(NULL);
  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  result->new_url = redirect_url_;
  return result;
}

//
// WebRequestRedirectToTransparentImageAction
//

WebRequestRedirectToTransparentImageAction::
    WebRequestRedirectToTransparentImageAction()
    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                       ACTION_REDIRECT_TO_TRANSPARENT_IMAGE,
                       std::numeric_limits<int>::min(),
                       STRATEGY_NONE) {}

WebRequestRedirectToTransparentImageAction::
~WebRequestRedirectToTransparentImageAction() {}

std::string WebRequestRedirectToTransparentImageAction::GetName() const {
  return keys::kRedirectToTransparentImageType;
}

LinkedPtrEventResponseDelta
WebRequestRedirectToTransparentImageAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  result->new_url = GURL(kTransparentImageUrl);
  return result;
}

//
// WebRequestRedirectToEmptyDocumentAction
//

WebRequestRedirectToEmptyDocumentAction::
    WebRequestRedirectToEmptyDocumentAction()
    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                       ACTION_REDIRECT_TO_EMPTY_DOCUMENT,
                       std::numeric_limits<int>::min(),
                       STRATEGY_NONE) {}

WebRequestRedirectToEmptyDocumentAction::
~WebRequestRedirectToEmptyDocumentAction() {}

std::string WebRequestRedirectToEmptyDocumentAction::GetName() const {
  return keys::kRedirectToEmptyDocumentType;
}

LinkedPtrEventResponseDelta
WebRequestRedirectToEmptyDocumentAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  result->new_url = GURL(kEmptyDocumentUrl);
  return result;
}

//
// WebRequestRedirectByRegExAction
//

WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction(
    std::unique_ptr<RE2> from_pattern,
    const std::string& to_pattern)
    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                       ACTION_REDIRECT_BY_REGEX_DOCUMENT,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      from_pattern_(std::move(from_pattern)),
      to_pattern_(to_pattern.data(), to_pattern.size()) {}

WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {}

// About the syntax of the two languages:
//
// ICU (Perl) states:
// $n The text of capture group n will be substituted for $n. n must be >= 0
//    and not greater than the number of capture groups. A $ not followed by a
//    digit has no special meaning, and will appear in the substitution text
//    as itself, a $.
// \  Treat the following character as a literal, suppressing any special
//    meaning. Backslash escaping in substitution text is only required for
//    '$' and '\', but may be used on any other character without bad effects.
//
// RE2, derived from RE2::Rewrite()
// \  May only be followed by a digit or another \. If followed by a single
//    digit, both characters represent the respective capture group. If followed
//    by another \, it is used as an escape sequence.

// static
std::string WebRequestRedirectByRegExAction::PerlToRe2Style(
    const std::string& perl) {
  std::string::const_iterator i = perl.begin();
  std::string result;
  while (i != perl.end()) {
    if (*i == '$') {
      ++i;
      if (i == perl.end()) {
        result += '$';
        return result;
      } else if (isdigit(*i)) {
        result += '\\';
        result += *i;
      } else {
        result += '$';
        result += *i;
      }
    } else if (*i == '\\') {
      ++i;
      if (i == perl.end()) {
        result += '\\';
      } else if (*i == '$') {
        result += '$';
      } else if (*i == '\\') {
        result += "\\\\";
      } else {
        result += *i;
      }
    } else {
      result += *i;
    }
    ++i;
  }
  return result;
}

bool WebRequestRedirectByRegExAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestRedirectByRegExAction* casted_other =
      static_cast<const WebRequestRedirectByRegExAction*>(other);
  return from_pattern_->pattern() == casted_other->from_pattern_->pattern() &&
         to_pattern_ == casted_other->to_pattern_;
}

std::string WebRequestRedirectByRegExAction::GetName() const {
  return keys::kRedirectByRegExType;
}

LinkedPtrEventResponseDelta WebRequestRedirectByRegExAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  CHECK(from_pattern_.get());

  const std::string& old_url = request_data.request->url().spec();
  std::string new_url = old_url;
  if (!RE2::Replace(&new_url, *from_pattern_, to_pattern_) ||
      new_url == old_url) {
    return LinkedPtrEventResponseDelta(NULL);
  }

  LinkedPtrEventResponseDelta result(
      new extension_web_request_api_helpers::EventResponseDelta(
          extension_id, extension_install_time));
  result->new_url = GURL(new_url);
  return result;
}

//
// WebRequestSetRequestHeaderAction
//

WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction(
    const std::string& name,
    const std::string& value)
    : WebRequestAction(ON_BEFORE_SEND_HEADERS,
                       ACTION_SET_REQUEST_HEADER,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      name_(name),
      value_(value) {}

WebRequestSetRequestHeaderAction::~WebRequestSetRequestHeaderAction() {}

bool WebRequestSetRequestHeaderAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestSetRequestHeaderAction* casted_other =
      static_cast<const WebRequestSetRequestHeaderAction*>(other);
  return name_ == casted_other->name_ && value_ == casted_other->value_;
}

std::string WebRequestSetRequestHeaderAction::GetName() const {
  return keys::kSetRequestHeaderType;
}


LinkedPtrEventResponseDelta
WebRequestSetRequestHeaderAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  result->modified_request_headers.SetHeader(name_, value_);
  return result;
}

//
// WebRequestRemoveRequestHeaderAction
//

WebRequestRemoveRequestHeaderAction::WebRequestRemoveRequestHeaderAction(
    const std::string& name)
    : WebRequestAction(ON_BEFORE_SEND_HEADERS,
                       ACTION_REMOVE_REQUEST_HEADER,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      name_(name) {}

WebRequestRemoveRequestHeaderAction::~WebRequestRemoveRequestHeaderAction() {}

bool WebRequestRemoveRequestHeaderAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestRemoveRequestHeaderAction* casted_other =
      static_cast<const WebRequestRemoveRequestHeaderAction*>(other);
  return name_ == casted_other->name_;
}

std::string WebRequestRemoveRequestHeaderAction::GetName() const {
  return keys::kRemoveRequestHeaderType;
}

LinkedPtrEventResponseDelta
WebRequestRemoveRequestHeaderAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  result->deleted_request_headers.push_back(name_);
  return result;
}

//
// WebRequestAddResponseHeaderAction
//

WebRequestAddResponseHeaderAction::WebRequestAddResponseHeaderAction(
    const std::string& name,
    const std::string& value)
    : WebRequestAction(ON_HEADERS_RECEIVED,
                       ACTION_ADD_RESPONSE_HEADER,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      name_(name),
      value_(value) {}

WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {}

bool WebRequestAddResponseHeaderAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestAddResponseHeaderAction* casted_other =
      static_cast<const WebRequestAddResponseHeaderAction*>(other);
  return name_ == casted_other->name_ && value_ == casted_other->value_;
}

std::string WebRequestAddResponseHeaderAction::GetName() const {
  return keys::kAddResponseHeaderType;
}

LinkedPtrEventResponseDelta
WebRequestAddResponseHeaderAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  const net::HttpResponseHeaders* headers =
      request_data.original_response_headers;
  if (!headers)
    return LinkedPtrEventResponseDelta(NULL);

  // Don't generate the header if it exists already.
  if (headers->HasHeaderValue(name_, value_))
    return LinkedPtrEventResponseDelta(NULL);

  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  result->added_response_headers.push_back(make_pair(name_, value_));
  return result;
}

//
// WebRequestRemoveResponseHeaderAction
//

WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction(
    const std::string& name,
    const std::string& value,
    bool has_value)
    : WebRequestAction(ON_HEADERS_RECEIVED,
                       ACTION_REMOVE_RESPONSE_HEADER,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      name_(name),
      value_(value),
      has_value_(has_value) {}

WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {}

bool WebRequestRemoveResponseHeaderAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestRemoveResponseHeaderAction* casted_other =
      static_cast<const WebRequestRemoveResponseHeaderAction*>(other);
  return name_ == casted_other->name_ && value_ == casted_other->value_ &&
         has_value_ == casted_other->has_value_;
}

std::string WebRequestRemoveResponseHeaderAction::GetName() const {
  return keys::kRemoveResponseHeaderType;
}

LinkedPtrEventResponseDelta
WebRequestRemoveResponseHeaderAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  const net::HttpResponseHeaders* headers =
      request_data.original_response_headers;
  if (!headers)
    return LinkedPtrEventResponseDelta(NULL);

  LinkedPtrEventResponseDelta result(
      new helpers::EventResponseDelta(extension_id, extension_install_time));
  size_t iter = 0;
  std::string current_value;
  while (headers->EnumerateHeader(&iter, name_, &current_value)) {
    if (has_value_ && !base::EqualsCaseInsensitiveASCII(current_value, value_))
      continue;
    result->deleted_response_headers.push_back(make_pair(name_, current_value));
  }
  return result;
}

//
// WebRequestIgnoreRulesAction
//

WebRequestIgnoreRulesAction::WebRequestIgnoreRulesAction(
    int minimum_priority,
    const std::string& ignore_tag)
    : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS |
                           ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED,
                       ACTION_IGNORE_RULES,
                       minimum_priority,
                       STRATEGY_NONE),
      ignore_tag_(ignore_tag) {}

WebRequestIgnoreRulesAction::~WebRequestIgnoreRulesAction() {}

bool WebRequestIgnoreRulesAction::Equals(const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestIgnoreRulesAction* casted_other =
      static_cast<const WebRequestIgnoreRulesAction*>(other);
  return minimum_priority() == casted_other->minimum_priority() &&
         ignore_tag_ == casted_other->ignore_tag_;
}

std::string WebRequestIgnoreRulesAction::GetName() const {
  return keys::kIgnoreRulesType;
}

LinkedPtrEventResponseDelta WebRequestIgnoreRulesAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  return LinkedPtrEventResponseDelta(NULL);
}

//
// WebRequestRequestCookieAction
//

WebRequestRequestCookieAction::WebRequestRequestCookieAction(
    linked_ptr<RequestCookieModification> request_cookie_modification)
    : WebRequestAction(ON_BEFORE_SEND_HEADERS,
                       ACTION_MODIFY_REQUEST_COOKIE,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      request_cookie_modification_(request_cookie_modification) {
  CHECK(request_cookie_modification_.get());
}

WebRequestRequestCookieAction::~WebRequestRequestCookieAction() {}

bool WebRequestRequestCookieAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestRequestCookieAction* casted_other =
      static_cast<const WebRequestRequestCookieAction*>(other);
  return helpers::NullableEquals(
      request_cookie_modification_.get(),
      casted_other->request_cookie_modification_.get());
}

std::string WebRequestRequestCookieAction::GetName() const {
  switch (request_cookie_modification_->type) {
    case helpers::ADD:
      return keys::kAddRequestCookieType;
    case helpers::EDIT:
      return keys::kEditRequestCookieType;
    case helpers::REMOVE:
      return keys::kRemoveRequestCookieType;
  }
  NOTREACHED();
  return "";
}

LinkedPtrEventResponseDelta WebRequestRequestCookieAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new extension_web_request_api_helpers::EventResponseDelta(
          extension_id, extension_install_time));
  result->request_cookie_modifications.push_back(
      request_cookie_modification_);
  return result;
}

//
// WebRequestResponseCookieAction
//

WebRequestResponseCookieAction::WebRequestResponseCookieAction(
    linked_ptr<ResponseCookieModification> response_cookie_modification)
    : WebRequestAction(ON_HEADERS_RECEIVED,
                       ACTION_MODIFY_RESPONSE_COOKIE,
                       std::numeric_limits<int>::min(),
                       STRATEGY_DEFAULT),
      response_cookie_modification_(response_cookie_modification) {
  CHECK(response_cookie_modification_.get());
}

WebRequestResponseCookieAction::~WebRequestResponseCookieAction() {}

bool WebRequestResponseCookieAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestResponseCookieAction* casted_other =
      static_cast<const WebRequestResponseCookieAction*>(other);
  return helpers::NullableEquals(
      response_cookie_modification_.get(),
      casted_other->response_cookie_modification_.get());
}

std::string WebRequestResponseCookieAction::GetName() const {
  switch (response_cookie_modification_->type) {
    case helpers::ADD:
      return keys::kAddResponseCookieType;
    case helpers::EDIT:
      return keys::kEditResponseCookieType;
    case helpers::REMOVE:
      return keys::kRemoveResponseCookieType;
  }
  NOTREACHED();
  return "";
}

LinkedPtrEventResponseDelta WebRequestResponseCookieAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new extension_web_request_api_helpers::EventResponseDelta(
          extension_id, extension_install_time));
  result->response_cookie_modifications.push_back(
      response_cookie_modification_);
  return result;
}

//
// WebRequestSendMessageToExtensionAction
//

WebRequestSendMessageToExtensionAction::WebRequestSendMessageToExtensionAction(
    const std::string& message)
    : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS |
                           ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED,
                       ACTION_SEND_MESSAGE_TO_EXTENSION,
                       std::numeric_limits<int>::min(),
                       STRATEGY_HOST),
      message_(message) {}

WebRequestSendMessageToExtensionAction::
~WebRequestSendMessageToExtensionAction() {}

bool WebRequestSendMessageToExtensionAction::Equals(
    const WebRequestAction* other) const {
  if (!WebRequestAction::Equals(other))
    return false;
  const WebRequestSendMessageToExtensionAction* casted_other =
      static_cast<const WebRequestSendMessageToExtensionAction*>(other);
  return message_ == casted_other->message_;
}

std::string WebRequestSendMessageToExtensionAction::GetName() const {
  return keys::kSendMessageToExtensionType;
}

LinkedPtrEventResponseDelta WebRequestSendMessageToExtensionAction::CreateDelta(
    const WebRequestData& request_data,
    const std::string& extension_id,
    const base::Time& extension_install_time) const {
  CHECK(request_data.stage & stages());
  LinkedPtrEventResponseDelta result(
      new extension_web_request_api_helpers::EventResponseDelta(
          extension_id, extension_install_time));
  result->messages_to_extension.insert(message_);
  return result;
}

}  // namespace extensions
