// Copyright (c) 2019 The Chromium Embedded Framework Authors. Portions
// Copyright (c) 2018 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 "libcef/common/net_service/net_service_util.h"

#include "libcef/common/time_util.h"

#include <set>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/parsed_cookie.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_request.h"

namespace net_service {

namespace {

// Determine the cookie domain to use for setting the specified cookie.
// From net/cookies/cookie_store.cc.
bool GetCookieDomain(const GURL& url,
                     const net::ParsedCookie& pc,
                     std::string* result) {
  std::string domain_string;
  if (pc.HasDomain())
    domain_string = pc.Domain();
  return net::cookie_util::GetCookieDomainWithString(url, domain_string,
                                                     result);
}

cef_cookie_same_site_t MakeCefCookieSameSite(net::CookieSameSite value) {
  switch (value) {
    case net::CookieSameSite::UNSPECIFIED:
      return CEF_COOKIE_SAME_SITE_UNSPECIFIED;
    case net::CookieSameSite::NO_RESTRICTION:
      return CEF_COOKIE_SAME_SITE_NO_RESTRICTION;
    case net::CookieSameSite::LAX_MODE:
      return CEF_COOKIE_SAME_SITE_LAX_MODE;
    case net::CookieSameSite::STRICT_MODE:
      return CEF_COOKIE_SAME_SITE_STRICT_MODE;
  }
}

cef_cookie_priority_t MakeCefCookiePriority(net::CookiePriority value) {
  switch (value) {
    case net::COOKIE_PRIORITY_LOW:
      return CEF_COOKIE_PRIORITY_LOW;
    case net::COOKIE_PRIORITY_MEDIUM:
      return CEF_COOKIE_PRIORITY_MEDIUM;
    case net::COOKIE_PRIORITY_HIGH:
      return CEF_COOKIE_PRIORITY_HIGH;
  }
}

}  // namespace

const char kHTTPLocationHeaderName[] = "Location";
const char kHTTPSetCookieHeaderName[] = "Set-Cookie";

const char kContentTypeApplicationFormURLEncoded[] =
    "application/x-www-form-urlencoded";

const char kHTTPHeaderSep[] = ": ";

std::string MakeHeader(const std::string& name, const std::string& value) {
  std::string header(name);
  header.append(kHTTPHeaderSep);
  header.append(value);
  return header;
}

std::string MakeStatusLine(int status_code,
                           const std::string& status_text,
                           bool for_replacement) {
  std::string status("HTTP/1.1 ");
  status.append(base::NumberToString(status_code));
  status.append(" ");

  if (status_text.empty()) {
    const std::string& text =
        net::GetHttpReasonPhrase(static_cast<net::HttpStatusCode>(status_code));
    DCHECK(!text.empty());
    status.append(text);
  } else {
    status.append(status_text);
  }

  if (!for_replacement) {
    // The HttpResponseHeaders constructor expects its input string to be
    // terminated by two NULs.
    status.append("\0\0", 2);
  }
  return status;
}

std::string MakeContentTypeValue(const std::string& mime_type,
                                 const std::string& charset) {
  DCHECK(!mime_type.empty());
  std::string value = mime_type;
  if (!charset.empty()) {
    value.append("; charset=");
    value.append(charset);
  }
  return value;
}

scoped_refptr<net::HttpResponseHeaders> MakeResponseHeaders(
    int status_code,
    const std::string& status_text,
    const std::string& mime_type,
    const std::string& charset,
    int64_t content_length,
    const std::multimap<std::string, std::string>& extra_headers,
    bool allow_existing_header_override) {
  if (status_code <= 0)
    status_code = 200;

  auto headers = WrapRefCounted(new net::HttpResponseHeaders(
      MakeStatusLine(status_code, status_text, false)));

  // Track the headers that have already been set. Perform all comparisons in
  // lowercase.
  std::set<std::string> set_headers_lowercase;
  if ((status_code >= 200 && status_code < 300) &&
      status_code != net::HTTP_NO_CONTENT &&
      status_code != net::HTTP_RESET_CONTENT) {
    if (!mime_type.empty()) {
      headers->AddHeader(MakeHeader(net::HttpRequestHeaders::kContentType,
                                    MakeContentTypeValue(mime_type, charset)));
      set_headers_lowercase.insert(
          base::ToLowerASCII(net::HttpRequestHeaders::kContentType));
    }

    if (content_length >= 0) {
      headers->AddHeader(MakeHeader(net::HttpRequestHeaders::kContentLength,
                                    base::NumberToString(content_length)));
      set_headers_lowercase.insert(
          base::ToLowerASCII(net::HttpRequestHeaders::kContentLength));
    }
  }

  for (const auto& pair : extra_headers) {
    if (!set_headers_lowercase.empty()) {
      // Check if the header has already been set.
      const std::string& name_lowercase = base::ToLowerASCII(pair.first);
      if (set_headers_lowercase.find(name_lowercase) !=
          set_headers_lowercase.end()) {
        if (allow_existing_header_override)
          headers->RemoveHeader(pair.first);
        else
          continue;
      }
    }

    headers->AddHeader(MakeHeader(pair.first, pair.second));
  }

  return headers;
}

net::RedirectInfo MakeRedirectInfo(const network::ResourceRequest& request,
                                   const net::HttpResponseHeaders* headers,
                                   const GURL& new_location,
                                   int status_code) {
  bool insecure_scheme_was_upgraded = false;

  GURL location = new_location;
  if (status_code == 0)
    status_code = net::HTTP_TEMPORARY_REDIRECT;

  // If this a redirect to HTTP of a request that had the
  // 'upgrade-insecure-requests' policy set, upgrade it to HTTPS.
  if (request.upgrade_if_insecure) {
    if (location.SchemeIs("http")) {
      insecure_scheme_was_upgraded = true;
      GURL::Replacements replacements;
      replacements.SetSchemeStr("https");
      location = location.ReplaceComponents(replacements);
    }
  }

  net::URLRequest::FirstPartyURLPolicy first_party_url_policy =
      request.update_first_party_url_on_redirect
          ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT
          : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
  return net::RedirectInfo::ComputeRedirectInfo(
      request.method, request.url, request.site_for_cookies,
      first_party_url_policy, request.referrer_policy, request.referrer.spec(),
      status_code, location,
      net::RedirectUtil::GetReferrerPolicyHeader(headers),
      insecure_scheme_was_upgraded);
}

net::CookieSameSite MakeCookieSameSite(cef_cookie_same_site_t value) {
  switch (value) {
    case CEF_COOKIE_SAME_SITE_UNSPECIFIED:
      return net::CookieSameSite::UNSPECIFIED;
    case CEF_COOKIE_SAME_SITE_NO_RESTRICTION:
      return net::CookieSameSite::NO_RESTRICTION;
    case CEF_COOKIE_SAME_SITE_LAX_MODE:
      return net::CookieSameSite::LAX_MODE;
    case CEF_COOKIE_SAME_SITE_STRICT_MODE:
      return net::CookieSameSite::STRICT_MODE;
  }
}

net::CookiePriority MakeCookiePriority(cef_cookie_priority_t value) {
  switch (value) {
    case CEF_COOKIE_PRIORITY_LOW:
      return net::COOKIE_PRIORITY_LOW;
    case CEF_COOKIE_PRIORITY_MEDIUM:
      return net::COOKIE_PRIORITY_MEDIUM;
    case CEF_COOKIE_PRIORITY_HIGH:
      return net::COOKIE_PRIORITY_HIGH;
  }
}

bool MakeCefCookie(const net::CanonicalCookie& cc, CefCookie& cookie) {
  CefString(&cookie.name).FromString(cc.Name());
  CefString(&cookie.value).FromString(cc.Value());
  CefString(&cookie.domain).FromString(cc.Domain());
  CefString(&cookie.path).FromString(cc.Path());
  cookie.secure = cc.IsSecure();
  cookie.httponly = cc.IsHttpOnly();
  cef_time_from_basetime(cc.CreationDate(), cookie.creation);
  cef_time_from_basetime(cc.LastAccessDate(), cookie.last_access);
  cookie.has_expires = cc.IsPersistent();
  if (cookie.has_expires)
    cef_time_from_basetime(cc.ExpiryDate(), cookie.expires);
  cookie.same_site = MakeCefCookieSameSite(cc.SameSite());
  cookie.priority = MakeCefCookiePriority(cc.Priority());

  return true;
}

bool MakeCefCookie(const GURL& url,
                   const std::string& cookie_line,
                   CefCookie& cookie) {
  // Parse the cookie.
  net::ParsedCookie pc(cookie_line);
  if (!pc.IsValid())
    return false;

  std::string cookie_domain;
  if (!GetCookieDomain(url, pc, &cookie_domain))
    return false;

  std::string path_string;
  if (pc.HasPath())
    path_string = pc.Path();
  std::string cookie_path =
      net::CanonicalCookie::CanonPathWithString(url, path_string);
  base::Time creation_time = base::Time::Now();
  base::Time cookie_expires =
      net::CanonicalCookie::CanonExpiration(pc, creation_time, creation_time);

  CefString(&cookie.name).FromString(pc.Name());
  CefString(&cookie.value).FromString(pc.Value());
  CefString(&cookie.domain).FromString(cookie_domain);
  CefString(&cookie.path).FromString(cookie_path);
  cookie.secure = pc.IsSecure();
  cookie.httponly = pc.IsHttpOnly();
  cef_time_from_basetime(creation_time, cookie.creation);
  cef_time_from_basetime(creation_time, cookie.last_access);
  cookie.has_expires = !cookie_expires.is_null();
  if (cookie.has_expires)
    cef_time_from_basetime(cookie_expires, cookie.expires);
  cookie.same_site = MakeCefCookieSameSite(pc.SameSite());
  cookie.priority = MakeCefCookiePriority(pc.Priority());

  return true;
}

}  // namespace net_service