// Copyright (c) 2008-2009 The Chromium Embedded Framework 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 <algorithm>
#include <limits>
#include <string>
#include <utility>
#include <vector>

#include "libcef/browser/navigate_params.h"
#include "libcef/common/cef_messages.h"
#include "libcef/common/net/http_header_utils.h"
#include "libcef/common/net/upload_data.h"
#include "libcef/common/net_service/net_service_util.h"
#include "libcef/common/request_impl.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "components/navigation_interception/navigation_params.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/load_flags.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_util.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/data_element.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_security_policy.h"

namespace {

const char kReferrerLowerCase[] = "referer";
const char kCacheControlLowerCase[] = "cache-control";
const char kCacheControlDirectiveNoCacheLowerCase[] = "no-cache";
const char kCacheControlDirectiveNoStoreLowerCase[] = "no-store";
const char kCacheControlDirectiveOnlyIfCachedLowerCase[] = "only-if-cached";

// Mask of values that configure the cache policy.
const int kURCachePolicyMask =
    (UR_FLAG_SKIP_CACHE | UR_FLAG_ONLY_FROM_CACHE | UR_FLAG_DISABLE_CACHE);

// A subclass of net::UploadBytesElementReader that keeps the associated
// UploadElement alive until the request completes.
class BytesElementReader : public net::UploadBytesElementReader {
 public:
  explicit BytesElementReader(std::unique_ptr<net::UploadElement> element)
      : net::UploadBytesElementReader(element->bytes(),
                                      element->bytes_length()),
        element_(std::move(element)) {
    DCHECK_EQ(net::UploadElement::TYPE_BYTES, element_->type());
  }

 private:
  std::unique_ptr<net::UploadElement> element_;

  DISALLOW_COPY_AND_ASSIGN(BytesElementReader);
};

scoped_refptr<base::SequencedTaskRunner> GetFileTaskRunner() {
  return base::CreateSequencedTaskRunner(
      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}

// A subclass of net::UploadFileElementReader that keeps the associated
// UploadElement alive until the request completes.
class FileElementReader : public net::UploadFileElementReader {
 public:
  explicit FileElementReader(std::unique_ptr<net::UploadElement> element)
      : net::UploadFileElementReader(
            GetFileTaskRunner().get(),
            element->file_path(),
            element->file_range_offset(),
            element->file_range_length(),
            element->expected_file_modification_time()),
        element_(std::move(element)) {
    DCHECK_EQ(net::UploadElement::TYPE_FILE, element_->type());
  }

 private:
  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  std::unique_ptr<net::UploadElement> element_;

  DISALLOW_COPY_AND_ASSIGN(FileElementReader);
};

// Returns the cef_urlrequest_flags_t policy specified by the Cache-Control
// request header directives, if any. The directives are case-insensitive and
// some have an optional argument. Multiple directives are comma-separated.
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
// for details.
int GetCacheControlHeaderPolicy(CefRequest::HeaderMap headerMap) {
  std::string line;

  // Extract the Cache-Control header line.
  {
    CefRequest::HeaderMap::const_iterator it = headerMap.begin();
    for (; it != headerMap.end(); ++it) {
      if (base::LowerCaseEqualsASCII(it->first.ToString(),
                                     kCacheControlLowerCase)) {
        line = it->second;
        break;
      }
    }
  }

  int flags = 0;

  if (!line.empty()) {
    HttpHeaderUtils::MakeASCIILower(&line);

    std::vector<base::StringPiece> pieces = base::SplitStringPiece(
        line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    for (const auto& piece : pieces) {
      if (base::LowerCaseEqualsASCII(piece,
                                     kCacheControlDirectiveNoCacheLowerCase)) {
        flags |= UR_FLAG_SKIP_CACHE;
      } else if (base::LowerCaseEqualsASCII(
                     piece, kCacheControlDirectiveOnlyIfCachedLowerCase)) {
        flags |= UR_FLAG_ONLY_FROM_CACHE;
      } else if (base::LowerCaseEqualsASCII(
                     piece, kCacheControlDirectiveNoStoreLowerCase)) {
        flags |= UR_FLAG_DISABLE_CACHE;
      }
    }
  }

  return flags;
}

// Convert cef_urlrequest_flags_t to blink::WebCachePolicy.
blink::mojom::FetchCacheMode GetFetchCacheMode(int ur_flags) {
  const bool skip_cache{ur_flags & UR_FLAG_SKIP_CACHE};
  const bool only_from_cache{ur_flags & UR_FLAG_ONLY_FROM_CACHE};
  const bool disable_cache{ur_flags & UR_FLAG_DISABLE_CACHE};
  if (only_from_cache && (skip_cache || disable_cache)) {
    // The request will always fail because only_from_cache and
    // skip_cache/disable_cache are mutually exclusive.
    return blink::mojom::FetchCacheMode::kUnspecifiedForceCacheMiss;
  } else if (disable_cache) {
    // This additionally implies the skip_cache behavior.
    return blink::mojom::FetchCacheMode::kNoStore;
  } else if (skip_cache) {
    return blink::mojom::FetchCacheMode::kBypassCache;
  } else if (only_from_cache) {
    return blink::mojom::FetchCacheMode::kOnlyIfCached;
  }
  return blink::mojom::FetchCacheMode::kDefault;
}

blink::WebString FilePathStringToWebString(
    const base::FilePath::StringType& str) {
#if defined(OS_POSIX)
  return blink::WebString::FromUTF8(str);
#elif defined(OS_WIN)
  return blink::WebString::FromUTF16(str);
#endif
}

// Read |headers| into |map|.
void GetHeaderMap(const net::HttpRequestHeaders& headers,
                  CefRequest::HeaderMap& map) {
  map.clear();

  if (headers.IsEmpty())
    return;

  net::HttpRequestHeaders::Iterator it(headers);
  while (it.GetNext()) {
    const std::string& name = it.name();

    // Do not include Referer in the header map.
    if (!base::LowerCaseEqualsASCII(name, kReferrerLowerCase))
      map.insert(std::make_pair(name, it.value()));
  };
}

// Read |source| into |map|.
void GetHeaderMap(const CefRequest::HeaderMap& source,
                  CefRequest::HeaderMap& map) {
  map.clear();

  CefRequest::HeaderMap::const_iterator it = source.begin();
  for (; it != source.end(); ++it) {
    const CefString& name = it->first;

    // Do not include Referer in the header map.
    if (!base::LowerCaseEqualsASCII(name.ToString(), kReferrerLowerCase))
      map.insert(std::make_pair(name, it->second));
  }
}

// Type used in UploadDataStream.
typedef std::vector<std::unique_ptr<net::UploadElementReader>>
    UploadElementReaders;

}  // namespace

#define CHECK_READONLY_RETURN(val)         \
  if (read_only_) {                        \
    NOTREACHED() << "object is read only"; \
    return val;                            \
  }

#define CHECK_READONLY_RETURN_VOID()       \
  if (read_only_) {                        \
    NOTREACHED() << "object is read only"; \
    return;                                \
  }

#define SETBOOLFLAG(obj, flags, method, FLAG) \
  obj.method((flags & (FLAG)) == (FLAG))

// CefRequest -----------------------------------------------------------------

// static
CefRefPtr<CefRequest> CefRequest::Create() {
  CefRefPtr<CefRequest> request(new CefRequestImpl());
  return request;
}

// CefRequestImpl -------------------------------------------------------------

CefRequestImpl::CefRequestImpl() {
  // Verify that our enum matches Chromium's values.
  static_assert(static_cast<int>(REFERRER_POLICY_LAST_VALUE) ==
                    static_cast<int>(net::URLRequest::MAX_REFERRER_POLICY),
                "enum mismatch");

  base::AutoLock lock_scope(lock_);
  Reset();
}

bool CefRequestImpl::IsReadOnly() {
  base::AutoLock lock_scope(lock_);
  return read_only_;
}

CefString CefRequestImpl::GetURL() {
  base::AutoLock lock_scope(lock_);
  return url_.spec();
}

void CefRequestImpl::SetURL(const CefString& url) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  const GURL& new_url = GURL(url.ToString());
  if (url_ != new_url) {
    Changed(kChangedUrl);
    url_ = new_url;
  }
}

CefString CefRequestImpl::GetMethod() {
  base::AutoLock lock_scope(lock_);
  return method_;
}

void CefRequestImpl::SetMethod(const CefString& method) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  const std::string& new_method = method;
  if (method_ != new_method) {
    Changed(kChangedMethod);
    method_ = new_method;
  }
}

void CefRequestImpl::SetReferrer(const CefString& referrer_url,
                                 ReferrerPolicy policy) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  const auto& sanitized_referrer = content::Referrer::SanitizeForRequest(
      url_, content::Referrer(GURL(referrer_url.ToString()),
                              NetReferrerPolicyToBlinkReferrerPolicy(policy)));
  const auto sanitized_policy =
      BlinkReferrerPolicyToNetReferrerPolicy(sanitized_referrer.policy);

  if (referrer_url_ != sanitized_referrer.url ||
      referrer_policy_ != sanitized_policy) {
    Changed(kChangedReferrer);
    referrer_url_ = sanitized_referrer.url;
    referrer_policy_ = sanitized_policy;
  }
}

CefString CefRequestImpl::GetReferrerURL() {
  base::AutoLock lock_scope(lock_);
  return referrer_url_.spec();
}

CefRequestImpl::ReferrerPolicy CefRequestImpl::GetReferrerPolicy() {
  base::AutoLock lock_scope(lock_);
  return referrer_policy_;
}

CefRefPtr<CefPostData> CefRequestImpl::GetPostData() {
  base::AutoLock lock_scope(lock_);
  return postdata_;
}

void CefRequestImpl::SetPostData(CefRefPtr<CefPostData> postData) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  Changed(kChangedPostData);
  postdata_ = postData;
}

void CefRequestImpl::GetHeaderMap(HeaderMap& headerMap) {
  base::AutoLock lock_scope(lock_);
  headerMap = headermap_;
}

void CefRequestImpl::SetHeaderMap(const HeaderMap& headerMap) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  Changed(kChangedHeaderMap);
  ::GetHeaderMap(headerMap, headermap_);
}

CefString CefRequestImpl::GetHeaderByName(const CefString& name) {
  base::AutoLock lock_scope(lock_);

  std::string nameLower = name;
  HttpHeaderUtils::MakeASCIILower(&nameLower);

  auto it = HttpHeaderUtils::FindHeaderInMap(nameLower, headermap_);
  if (it != headermap_.end())
    return it->second;

  return CefString();
}

void CefRequestImpl::SetHeaderByName(const CefString& name,
                                     const CefString& value,
                                     bool overwrite) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  std::string nameLower = name;
  HttpHeaderUtils::MakeASCIILower(&nameLower);

  // Do not include Referer in the header map.
  if (nameLower == kReferrerLowerCase)
    return;

  Changed(kChangedHeaderMap);

  // There may be multiple values, so remove any first.
  for (auto it = headermap_.begin(); it != headermap_.end();) {
    if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower)) {
      if (!overwrite)
        return;
      it = headermap_.erase(it);
    } else {
      ++it;
    }
  }

  headermap_.insert(std::make_pair(name, value));
}

void CefRequestImpl::Set(const CefString& url,
                         const CefString& method,
                         CefRefPtr<CefPostData> postData,
                         const HeaderMap& headerMap) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  const GURL& new_url = GURL(url.ToString());
  if (url_ != new_url) {
    Changed(kChangedUrl);
    url_ = new_url;
  }
  const std::string& new_method = method;
  if (method_ != new_method) {
    Changed(kChangedMethod);
    method_ = new_method;
  }
  if (postdata_ != postData) {
    Changed(kChangedPostData);
    postdata_ = postData;
  }
  Changed(kChangedHeaderMap);
  ::GetHeaderMap(headerMap, headermap_);
}

int CefRequestImpl::GetFlags() {
  base::AutoLock lock_scope(lock_);
  return flags_;
}

void CefRequestImpl::SetFlags(int flags) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  if (flags_ != flags) {
    Changed(kChangedFlags);
    flags_ = flags;
  }
}

CefString CefRequestImpl::GetFirstPartyForCookies() {
  base::AutoLock lock_scope(lock_);
  return site_for_cookies_.RepresentativeUrl().spec();
}

void CefRequestImpl::SetFirstPartyForCookies(const CefString& url) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  auto new_site = net::SiteForCookies::FromUrl(GURL(url.ToString()));
  if (!new_site.IsEquivalent(site_for_cookies_)) {
    Changed(kChangedSiteForCookies);
    site_for_cookies_ = new_site;
  }
}

CefRequestImpl::ResourceType CefRequestImpl::GetResourceType() {
  base::AutoLock lock_scope(lock_);
  return resource_type_;
}

CefRequestImpl::TransitionType CefRequestImpl::GetTransitionType() {
  base::AutoLock lock_scope(lock_);
  return transition_type_;
}

uint64 CefRequestImpl::GetIdentifier() {
  base::AutoLock lock_scope(lock_);
  return identifier_;
}

void CefRequestImpl::Set(const network::ResourceRequest* request,
                         uint64 identifier) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  Reset();

  url_ = request->url;
  method_ = request->method;
  identifier_ = identifier;

  if (request->referrer.is_valid()) {
    const auto& sanitized_referrer = content::Referrer::SanitizeForRequest(
        request->url,
        content::Referrer(
            request->referrer,
            NetReferrerPolicyToBlinkReferrerPolicy(
                static_cast<cef_referrer_policy_t>(request->referrer_policy))));
    referrer_url_ = sanitized_referrer.url;
    referrer_policy_ =
        BlinkReferrerPolicyToNetReferrerPolicy(sanitized_referrer.policy);
  }

  // Transfer request headers.
  ::GetHeaderMap(request->headers, headermap_);

  // Transfer post data, if any.
  if (request->request_body) {
    postdata_ = CefPostData::Create();
    static_cast<CefPostDataImpl*>(postdata_.get())->Set(*request->request_body);
  }

  site_for_cookies_ = request->site_for_cookies;

  resource_type_ = static_cast<cef_resource_type_t>(request->resource_type);
  transition_type_ =
      static_cast<cef_transition_type_t>(request->transition_type);
}

void CefRequestImpl::Get(network::ResourceRequest* request,
                         bool changed_only) const {
  base::AutoLock lock_scope(lock_);

  if (ShouldSet(kChangedUrl, changed_only))
    request->url = url_;

  if (ShouldSet(kChangedMethod, changed_only))
    request->method = method_;

  if (ShouldSet(kChangedReferrer, changed_only)) {
    request->referrer = referrer_url_;
    request->referrer_policy =
        static_cast<net::URLRequest::ReferrerPolicy>(referrer_policy_);
  }

  if (ShouldSet(kChangedHeaderMap, changed_only)) {
    net::HttpRequestHeaders headers;
    headers.AddHeadersFromString(HttpHeaderUtils::GenerateHeaders(headermap_));
    request->headers.Swap(&headers);
  }

  if (ShouldSet(kChangedPostData, changed_only)) {
    if (postdata_.get()) {
      request->request_body =
          static_cast<CefPostDataImpl*>(postdata_.get())->GetBody();
    } else if (request->request_body) {
      request->request_body = nullptr;
    }
  }

  if (!site_for_cookies_.IsNull() &&
      ShouldSet(kChangedSiteForCookies, changed_only)) {
    request->site_for_cookies = site_for_cookies_;
  }

  if (ShouldSet(kChangedFlags, changed_only)) {
    int flags = flags_;
    if (!(flags & kURCachePolicyMask)) {
      // Only consider the Cache-Control directives when a cache policy is not
      // explicitly set on the request.
      flags |= GetCacheControlHeaderPolicy(headermap_);
    }

    int net_flags = 0;

    if (flags & UR_FLAG_SKIP_CACHE) {
      net_flags |= net::LOAD_BYPASS_CACHE;
    }
    if (flags & UR_FLAG_ONLY_FROM_CACHE) {
      net_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
    }
    if (flags & UR_FLAG_DISABLE_CACHE) {
      net_flags |= net::LOAD_DISABLE_CACHE;
    }

    if (!(flags & UR_FLAG_ALLOW_STORED_CREDENTIALS)) {
      net_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA |
                   net::LOAD_DO_NOT_SEND_COOKIES |
                   net::LOAD_DO_NOT_SAVE_COOKIES;
    }

    request->load_flags = net_flags;
  }
}

void CefRequestImpl::Set(const net::RedirectInfo& redirect_info) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  url_ = redirect_info.new_url;
  method_ = redirect_info.new_method;
  site_for_cookies_ = redirect_info.new_site_for_cookies;

  const auto& sanitized_referrer = content::Referrer::SanitizeForRequest(
      redirect_info.new_url,
      content::Referrer(GURL(redirect_info.new_referrer),
                        NetReferrerPolicyToBlinkReferrerPolicy(
                            static_cast<cef_referrer_policy_t>(
                                redirect_info.new_referrer_policy))));
  referrer_url_ = sanitized_referrer.url;
  referrer_policy_ =
      BlinkReferrerPolicyToNetReferrerPolicy(sanitized_referrer.policy);
}

void CefRequestImpl::Set(const net::HttpRequestHeaders& headers) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  ::GetHeaderMap(headers, headermap_);
}

void CefRequestImpl::Set(
    const navigation_interception::NavigationParams& params,
    bool is_main_frame) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  Reset();

  url_ = params.url();
  method_ = params.is_post() ? "POST" : "GET";

  const auto& sanitized_referrer =
      content::Referrer::SanitizeForRequest(params.url(), params.referrer());
  referrer_url_ = sanitized_referrer.url;
  referrer_policy_ =
      BlinkReferrerPolicyToNetReferrerPolicy(sanitized_referrer.policy);

  resource_type_ = is_main_frame ? RT_MAIN_FRAME : RT_SUB_FRAME;
  transition_type_ =
      static_cast<cef_transition_type_t>(params.transition_type());
}

// static
void CefRequestImpl::Get(const CefMsg_LoadRequest_Params& params,
                         blink::WebURLRequest& request) {
  request.SetUrl(params.url);
  request.SetRequestorOrigin(blink::WebSecurityOrigin::Create(params.url));
  if (!params.method.empty())
    request.SetHttpMethod(blink::WebString::FromASCII(params.method));

  if (params.referrer.is_valid()) {
    const blink::WebString& referrer =
        blink::WebSecurityPolicy::GenerateReferrerHeader(
            NetReferrerPolicyToBlinkReferrerPolicy(
                static_cast<cef_referrer_policy_t>(params.referrer_policy)),
            params.url, blink::WebString::FromUTF8(params.referrer.spec()));
    if (!referrer.IsEmpty()) {
      request.SetReferrerString(referrer);
      request.SetReferrerPolicy(NetReferrerPolicyToBlinkReferrerPolicy(
          static_cast<cef_referrer_policy_t>(params.referrer_policy)));
    }
  }

  CefRequest::HeaderMap headerMap;
  if (!params.headers.empty()) {
    for (net::HttpUtil::HeadersIterator i(params.headers.begin(),
                                          params.headers.end(), "\n\r");
         i.GetNext();) {
      request.AddHttpHeaderField(blink::WebString::FromUTF8(i.name()),
                                 blink::WebString::FromUTF8(i.values()));
      headerMap.insert(std::make_pair(i.name(), i.values()));
    }
  }

  if (params.upload_data.get()) {
    const base::string16& method = request.HttpMethod().Utf16();
    if (method == base::ASCIIToUTF16("GET") ||
        method == base::ASCIIToUTF16("HEAD")) {
      request.SetHttpMethod(blink::WebString::FromASCII("POST"));
    }

    // The comparison performed by httpHeaderField() is case insensitive.
    if (request
            .HttpHeaderField(blink::WebString::FromASCII(
                net::HttpRequestHeaders::kContentType))
            .length() == 0) {
      request.SetHttpHeaderField(
          blink::WebString::FromASCII(net::HttpRequestHeaders::kContentType),
          blink::WebString::FromASCII(
              net_service::kContentTypeApplicationFormURLEncoded));
    }

    blink::WebHTTPBody body;
    body.Initialize();

    for (const auto& element : params.upload_data->elements()) {
      if (element->type() == net::UploadElement::TYPE_BYTES) {
        blink::WebData data;
        data.Assign(element->bytes(), element->bytes_length());
        body.AppendData(data);
      } else if (element->type() == net::UploadElement::TYPE_FILE) {
        body.AppendFileRange(
            FilePathStringToWebString(element->file_path().value()),
            element->file_range_offset(), element->file_range_length(),
            element->expected_file_modification_time());
      } else {
        NOTREACHED();
      }
    }

    request.SetHttpBody(body);
  }

  if (!params.site_for_cookies.IsNull())
    request.SetSiteForCookies(params.site_for_cookies);

  int flags = params.load_flags;
  if (!(flags & kURCachePolicyMask)) {
    // Only consider the Cache-Control directives when a cache policy is not
    // explicitly set on the request.
    flags |= GetCacheControlHeaderPolicy(headerMap);
  }
  request.SetCacheMode(GetFetchCacheMode(flags));

  SETBOOLFLAG(request, params.load_flags, SetAllowStoredCredentials,
              UR_FLAG_ALLOW_STORED_CREDENTIALS);
  SETBOOLFLAG(request, params.load_flags, SetReportUploadProgress,
              UR_FLAG_REPORT_UPLOAD_PROGRESS);
}

void CefRequestImpl::Get(CefNavigateParams& params) const {
  base::AutoLock lock_scope(lock_);

  params.url = url_;
  params.method = method_;

  // Referrer policy will be applied later in the request pipeline.
  params.referrer.url = referrer_url_;
  params.referrer.policy =
      NetReferrerPolicyToBlinkReferrerPolicy(referrer_policy_);

  if (!headermap_.empty())
    params.headers = HttpHeaderUtils::GenerateHeaders(headermap_);

  if (postdata_) {
    CefPostDataImpl* impl = static_cast<CefPostDataImpl*>(postdata_.get());
    params.upload_data = new net::UploadData();
    impl->Get(*params.upload_data.get());
  }

  params.site_for_cookies = site_for_cookies_;
  params.load_flags = flags_;
}

void CefRequestImpl::SetReadOnly(bool read_only) {
  base::AutoLock lock_scope(lock_);
  if (read_only_ == read_only)
    return;

  read_only_ = read_only;

  if (postdata_.get())
    static_cast<CefPostDataImpl*>(postdata_.get())->SetReadOnly(read_only);
}

void CefRequestImpl::SetTrackChanges(bool track_changes,
                                     bool backup_on_change) {
  base::AutoLock lock_scope(lock_);
  if (track_changes_ == track_changes)
    return;

  if (!track_changes && backup_on_change_)
    backup_.reset();

  track_changes_ = track_changes;
  backup_on_change_ = track_changes ? backup_on_change : false;
  changes_ = kChangedNone;

  if (postdata_.get()) {
    static_cast<CefPostDataImpl*>(postdata_.get())
        ->SetTrackChanges(track_changes);
  }
}

void CefRequestImpl::RevertChanges() {
  base::AutoLock lock_scope(lock_);
  DCHECK(!read_only_);
  DCHECK(track_changes_);
  DCHECK(backup_on_change_);
  if (!backup_)
    return;

  // Restore the original values if a backup exists.
  if (backup_->backups_ & kChangedUrl)
    url_ = backup_->url_;
  if (backup_->backups_ & kChangedMethod)
    method_ = backup_->method_;
  if (backup_->backups_ & kChangedReferrer) {
    referrer_url_ = backup_->referrer_url_;
    referrer_policy_ = backup_->referrer_policy_;
  }
  if (backup_->backups_ & kChangedPostData)
    postdata_ = backup_->postdata_;
  if (backup_->backups_ & kChangedHeaderMap) {
    DCHECK(backup_->headermap_);
    headermap_.swap(*backup_->headermap_);
  }
  if (backup_->backups_ & kChangedFlags)
    flags_ = backup_->flags_;
  if (backup_->backups_ & kChangedSiteForCookies)
    site_for_cookies_ = backup_->site_for_cookies_;

  backup_.reset();
}

void CefRequestImpl::DiscardChanges() {
  base::AutoLock lock_scope(lock_);
  DCHECK(track_changes_);
  DCHECK(backup_on_change_);
  backup_.reset();
}

uint8_t CefRequestImpl::GetChanges() const {
  base::AutoLock lock_scope(lock_);

  uint8_t changes = changes_;
  if (postdata_.get() &&
      static_cast<CefPostDataImpl*>(postdata_.get())->HasChanges()) {
    changes |= kChangedPostData;
  }
  return changes;
}

// From content/child/web_url_loader_impl.cc
// static
network::mojom::ReferrerPolicy
CefRequestImpl::NetReferrerPolicyToBlinkReferrerPolicy(
    cef_referrer_policy_t net_policy) {
  switch (net_policy) {
    case REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
      return network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade;
    case REFERRER_POLICY_REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN:
      return network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin;
    case REFERRER_POLICY_ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN:
      return network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin;
    case REFERRER_POLICY_NEVER_CLEAR_REFERRER:
      return network::mojom::ReferrerPolicy::kAlways;
    case REFERRER_POLICY_ORIGIN:
      return network::mojom::ReferrerPolicy::kOrigin;
    case REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN:
      return network::mojom::ReferrerPolicy::kSameOrigin;
    case REFERRER_POLICY_ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
      return network::mojom::ReferrerPolicy::kStrictOrigin;
    case REFERRER_POLICY_NO_REFERRER:
      return network::mojom::ReferrerPolicy::kNever;
  }
  NOTREACHED();
  return network::mojom::ReferrerPolicy::kDefault;
}

// static
cef_referrer_policy_t CefRequestImpl::BlinkReferrerPolicyToNetReferrerPolicy(
    network::mojom::ReferrerPolicy blink_policy) {
  switch (blink_policy) {
    case network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade:
      return REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
    case network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin:
      return REFERRER_POLICY_REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
    case network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin:
      return REFERRER_POLICY_ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
    case network::mojom::ReferrerPolicy::kAlways:
      return REFERRER_POLICY_NEVER_CLEAR_REFERRER;
    case network::mojom::ReferrerPolicy::kOrigin:
      return REFERRER_POLICY_ORIGIN;
    case network::mojom::ReferrerPolicy::kSameOrigin:
      return REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN;
    case network::mojom::ReferrerPolicy::kStrictOrigin:
      return REFERRER_POLICY_ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
    case network::mojom::ReferrerPolicy::kNever:
      return REFERRER_POLICY_NO_REFERRER;
    case network::mojom::ReferrerPolicy::kDefault:
      return REFERRER_POLICY_DEFAULT;
  }
  NOTREACHED();
  return REFERRER_POLICY_DEFAULT;
}

void CefRequestImpl::Changed(uint8_t changes) {
  lock_.AssertAcquired();
  if (!track_changes_)
    return;

  if (backup_on_change_) {
    if (!backup_)
      backup_.reset(new Backup());

    // Set the backup values if not already set.
    if ((changes & kChangedUrl) && !(backup_->backups_ & kChangedUrl)) {
      backup_->url_ = url_;
      backup_->backups_ |= kChangedUrl;
    }
    if ((changes & kChangedMethod) && !(backup_->backups_ & kChangedMethod)) {
      backup_->method_ = method_;
      backup_->backups_ |= kChangedMethod;
    }
    if ((changes & kChangedReferrer) &&
        !(backup_->backups_ & kChangedReferrer)) {
      backup_->referrer_url_ = referrer_url_;
      backup_->referrer_policy_ = referrer_policy_;
      backup_->backups_ |= kChangedReferrer;
    }
    if ((changes & kChangedPostData) &&
        !(backup_->backups_ & kChangedPostData)) {
      backup_->postdata_ = postdata_;
      backup_->backups_ |= kChangedPostData;
    }
    if ((changes & kChangedHeaderMap) &&
        !(backup_->backups_ & kChangedHeaderMap)) {
      backup_->headermap_.reset(new HeaderMap());
      if (!headermap_.empty()) {
        backup_->headermap_->insert(headermap_.begin(), headermap_.end());
      }
      backup_->backups_ |= kChangedHeaderMap;
    }
    if ((changes & kChangedFlags) && !(backup_->backups_ & kChangedFlags)) {
      backup_->flags_ = flags_;
      backup_->backups_ |= kChangedFlags;
    }
    if ((changes & kChangedSiteForCookies) &&
        !(backup_->backups_ & kChangedSiteForCookies)) {
      backup_->site_for_cookies_ = site_for_cookies_;
      backup_->backups_ |= kChangedSiteForCookies;
    }
  }

  changes_ |= changes;
}

bool CefRequestImpl::ShouldSet(uint8_t changes, bool changed_only) const {
  lock_.AssertAcquired();

  // Always change if changes are not being tracked.
  if (!track_changes_)
    return true;

  // Always change if changed-only was not requested.
  if (!changed_only)
    return true;

  // Change if the |changes| bit flag has been set.
  if ((changes_ & changes) == changes)
    return true;

  if ((changes & kChangedPostData) == kChangedPostData) {
    // Change if the post data object was modified directly.
    if (postdata_.get() &&
        static_cast<CefPostDataImpl*>(postdata_.get())->HasChanges()) {
      return true;
    }
  }

  return false;
}

void CefRequestImpl::Reset() {
  lock_.AssertAcquired();
  DCHECK(!read_only_);

  url_ = GURL();
  method_ = "GET";
  referrer_url_ = GURL();
  referrer_policy_ = REFERRER_POLICY_DEFAULT;
  postdata_ = nullptr;
  headermap_.clear();
  resource_type_ = RT_SUB_RESOURCE;
  transition_type_ = TT_EXPLICIT;
  identifier_ = 0U;
  flags_ = UR_FLAG_NONE;
  site_for_cookies_ = net::SiteForCookies();

  changes_ = kChangedNone;
}

// CefPostData ----------------------------------------------------------------

// static
CefRefPtr<CefPostData> CefPostData::Create() {
  CefRefPtr<CefPostData> postdata(new CefPostDataImpl());
  return postdata;
}

// CefPostDataImpl ------------------------------------------------------------

CefPostDataImpl::CefPostDataImpl()
    : read_only_(false),
      has_excluded_elements_(false),
      track_changes_(false),
      has_changes_(false) {}

bool CefPostDataImpl::IsReadOnly() {
  base::AutoLock lock_scope(lock_);
  return read_only_;
}

bool CefPostDataImpl::HasExcludedElements() {
  base::AutoLock lock_scope(lock_);
  return has_excluded_elements_;
}

size_t CefPostDataImpl::GetElementCount() {
  base::AutoLock lock_scope(lock_);
  return elements_.size();
}

void CefPostDataImpl::GetElements(ElementVector& elements) {
  base::AutoLock lock_scope(lock_);
  elements = elements_;
}

bool CefPostDataImpl::RemoveElement(CefRefPtr<CefPostDataElement> element) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN(false);

  ElementVector::iterator it = elements_.begin();
  for (; it != elements_.end(); ++it) {
    if (it->get() == element.get()) {
      elements_.erase(it);
      Changed();
      return true;
    }
  }

  return false;
}

bool CefPostDataImpl::AddElement(CefRefPtr<CefPostDataElement> element) {
  bool found = false;

  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN(false);

  // check that the element isn't already in the list before adding
  ElementVector::const_iterator it = elements_.begin();
  for (; it != elements_.end(); ++it) {
    if (it->get() == element.get()) {
      found = true;
      break;
    }
  }

  if (!found) {
    elements_.push_back(element);
    Changed();
  }

  return !found;
}

void CefPostDataImpl::RemoveElements() {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();
  elements_.clear();
  Changed();
}

void CefPostDataImpl::Set(const network::ResourceRequestBody& body) {
  {
    base::AutoLock lock_scope(lock_);
    CHECK_READONLY_RETURN_VOID();
  }

  CefRefPtr<CefPostDataElement> postelem;

  for (const auto& element : *body.elements()) {
    postelem = CefPostDataElement::Create();
    static_cast<CefPostDataElementImpl*>(postelem.get())->Set(element);
    AddElement(postelem);
  }
}

scoped_refptr<network::ResourceRequestBody> CefPostDataImpl::GetBody() const {
  base::AutoLock lock_scope(lock_);

  scoped_refptr<network::ResourceRequestBody> body =
      new network::ResourceRequestBody();
  for (const auto& element : elements_) {
    static_cast<CefPostDataElementImpl*>(element.get())->Get(*body);
  }
  return body;
}

void CefPostDataImpl::Set(const net::UploadData& data) {
  {
    base::AutoLock lock_scope(lock_);
    CHECK_READONLY_RETURN_VOID();
  }

  CefRefPtr<CefPostDataElement> postelem;

  for (const auto& element : data.elements()) {
    postelem = CefPostDataElement::Create();
    static_cast<CefPostDataElementImpl*>(postelem.get())->Set(*element);
    AddElement(postelem);
  }
}

void CefPostDataImpl::Set(const net::UploadDataStream& data_stream) {
  {
    base::AutoLock lock_scope(lock_);
    CHECK_READONLY_RETURN_VOID();
  }

  CefRefPtr<CefPostDataElement> postelem;

  const UploadElementReaders* elements = data_stream.GetElementReaders();
  if (elements) {
    UploadElementReaders::const_iterator it = elements->begin();
    for (; it != elements->end(); ++it) {
      postelem = CefPostDataElement::Create();
      static_cast<CefPostDataElementImpl*>(postelem.get())->Set(**it);
      if (postelem->GetType() != PDE_TYPE_EMPTY)
        AddElement(postelem);
      else if (!has_excluded_elements_)
        has_excluded_elements_ = true;
    }
  }
}

void CefPostDataImpl::Get(net::UploadData& data) const {
  base::AutoLock lock_scope(lock_);

  net::UploadData::ElementsVector data_elements;
  for (const auto& element : elements_) {
    std::unique_ptr<net::UploadElement> data_element =
        std::make_unique<net::UploadElement>();
    static_cast<CefPostDataElementImpl*>(element.get())
        ->Get(*data_element.get());
    data_elements.push_back(std::move(data_element));
  }
  data.swap_elements(&data_elements);
}

std::unique_ptr<net::UploadDataStream> CefPostDataImpl::Get() const {
  base::AutoLock lock_scope(lock_);

  UploadElementReaders element_readers;
  for (const auto& element : elements_) {
    element_readers.push_back(
        static_cast<CefPostDataElementImpl*>(element.get())->Get());
  }

  return std::make_unique<net::ElementsUploadDataStream>(
      std::move(element_readers), 0);
}

void CefPostDataImpl::SetReadOnly(bool read_only) {
  base::AutoLock lock_scope(lock_);
  if (read_only_ == read_only)
    return;

  read_only_ = read_only;

  ElementVector::const_iterator it = elements_.begin();
  for (; it != elements_.end(); ++it) {
    static_cast<CefPostDataElementImpl*>(it->get())->SetReadOnly(read_only);
  }
}

void CefPostDataImpl::SetTrackChanges(bool track_changes) {
  base::AutoLock lock_scope(lock_);
  if (track_changes_ == track_changes)
    return;

  track_changes_ = track_changes;
  has_changes_ = false;

  ElementVector::const_iterator it = elements_.begin();
  for (; it != elements_.end(); ++it) {
    static_cast<CefPostDataElementImpl*>(it->get())->SetTrackChanges(
        track_changes);
  }
}

bool CefPostDataImpl::HasChanges() const {
  base::AutoLock lock_scope(lock_);
  if (has_changes_)
    return true;

  ElementVector::const_iterator it = elements_.begin();
  for (; it != elements_.end(); ++it) {
    if (static_cast<CefPostDataElementImpl*>(it->get())->HasChanges())
      return true;
  }

  return false;
}

void CefPostDataImpl::Changed() {
  lock_.AssertAcquired();
  if (track_changes_ && !has_changes_)
    has_changes_ = true;
}

// CefPostDataElement ---------------------------------------------------------

// static
CefRefPtr<CefPostDataElement> CefPostDataElement::Create() {
  CefRefPtr<CefPostDataElement> element(new CefPostDataElementImpl());
  return element;
}

// CefPostDataElementImpl -----------------------------------------------------

CefPostDataElementImpl::CefPostDataElementImpl()
    : type_(PDE_TYPE_EMPTY),
      read_only_(false),
      track_changes_(false),
      has_changes_(false) {
  memset(&data_, 0, sizeof(data_));
}

CefPostDataElementImpl::~CefPostDataElementImpl() {
  Cleanup();
}

bool CefPostDataElementImpl::IsReadOnly() {
  base::AutoLock lock_scope(lock_);
  return read_only_;
}

void CefPostDataElementImpl::SetToEmpty() {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  Cleanup();
  Changed();
}

void CefPostDataElementImpl::SetToFile(const CefString& fileName) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  // Clear any data currently in the element
  Cleanup();

  // Assign the new data
  type_ = PDE_TYPE_FILE;
  cef_string_copy(fileName.c_str(), fileName.length(), &data_.filename);

  Changed();
}

void CefPostDataElementImpl::SetToBytes(size_t size, const void* bytes) {
  base::AutoLock lock_scope(lock_);
  CHECK_READONLY_RETURN_VOID();

  // Clear any data currently in the element
  Cleanup();

  // Assign the new data
  void* data = malloc(size);
  DCHECK(data != nullptr);
  if (data == nullptr)
    return;

  memcpy(data, bytes, size);

  type_ = PDE_TYPE_BYTES;
  data_.bytes.bytes = data;
  data_.bytes.size = size;

  Changed();
}

CefPostDataElement::Type CefPostDataElementImpl::GetType() {
  base::AutoLock lock_scope(lock_);
  return type_;
}

CefString CefPostDataElementImpl::GetFile() {
  base::AutoLock lock_scope(lock_);
  DCHECK(type_ == PDE_TYPE_FILE);
  CefString filename;
  if (type_ == PDE_TYPE_FILE)
    filename.FromString(data_.filename.str, data_.filename.length, false);
  return filename;
}

size_t CefPostDataElementImpl::GetBytesCount() {
  base::AutoLock lock_scope(lock_);
  DCHECK(type_ == PDE_TYPE_BYTES);
  size_t size = 0;
  if (type_ == PDE_TYPE_BYTES)
    size = data_.bytes.size;
  return size;
}

size_t CefPostDataElementImpl::GetBytes(size_t size, void* bytes) {
  base::AutoLock lock_scope(lock_);
  DCHECK(type_ == PDE_TYPE_BYTES);
  size_t rv = 0;
  if (type_ == PDE_TYPE_BYTES) {
    rv = (size < data_.bytes.size ? size : data_.bytes.size);
    memcpy(bytes, data_.bytes.bytes, rv);
  }
  return rv;
}

void CefPostDataElementImpl::Set(const network::DataElement& element) {
  {
    base::AutoLock lock_scope(lock_);
    CHECK_READONLY_RETURN_VOID();
  }

  if (element.type() == network::mojom::DataElementType::kBytes) {
    SetToBytes(element.length(), element.bytes());
  } else if (element.type() == network::mojom::DataElementType::kFile) {
    SetToFile(element.path().value());
  }
}

void CefPostDataElementImpl::Get(network::ResourceRequestBody& body) const {
  base::AutoLock lock_scope(lock_);

  if (type_ == PDE_TYPE_BYTES) {
    body.AppendBytes(static_cast<char*>(data_.bytes.bytes), data_.bytes.size);
  } else if (type_ == PDE_TYPE_FILE) {
    base::FilePath path = base::FilePath(CefString(&data_.filename));
    body.AppendFileRange(path, 0, std::numeric_limits<uint64_t>::max(),
                         base::Time());
  } else {
    NOTREACHED();
  }
}

void CefPostDataElementImpl::Set(const net::UploadElement& element) {
  {
    base::AutoLock lock_scope(lock_);
    CHECK_READONLY_RETURN_VOID();
  }

  if (element.type() == net::UploadElement::TYPE_BYTES) {
    SetToBytes(element.bytes_length(), element.bytes());
  } else if (element.type() == net::UploadElement::TYPE_FILE) {
    SetToFile(element.file_path().value());
  } else {
    NOTREACHED();
  }
}

void CefPostDataElementImpl::Set(
    const net::UploadElementReader& element_reader) {
  {
    base::AutoLock lock_scope(lock_);
    CHECK_READONLY_RETURN_VOID();
  }

  const net::UploadBytesElementReader* bytes_reader =
      element_reader.AsBytesReader();
  if (bytes_reader) {
    SetToBytes(bytes_reader->length(), bytes_reader->bytes());
    return;
  }

  const net::UploadFileElementReader* file_reader =
      element_reader.AsFileReader();
  if (file_reader) {
    SetToFile(file_reader->path().value());
    return;
  }

  // Chunked uploads cannot currently be represented.
  SetToEmpty();
}

void CefPostDataElementImpl::Get(net::UploadElement& element) const {
  base::AutoLock lock_scope(lock_);

  if (type_ == PDE_TYPE_BYTES) {
    element.SetToBytes(static_cast<char*>(data_.bytes.bytes), data_.bytes.size);
  } else if (type_ == PDE_TYPE_FILE) {
    base::FilePath path = base::FilePath(CefString(&data_.filename));
    element.SetToFilePath(path);
  } else {
    NOTREACHED();
  }
}

std::unique_ptr<net::UploadElementReader> CefPostDataElementImpl::Get() const {
  base::AutoLock lock_scope(lock_);

  if (type_ == PDE_TYPE_BYTES) {
    net::UploadElement* element = new net::UploadElement();
    element->SetToBytes(static_cast<char*>(data_.bytes.bytes),
                        data_.bytes.size);
    return std::make_unique<BytesElementReader>(base::WrapUnique(element));
  } else if (type_ == PDE_TYPE_FILE) {
    net::UploadElement* element = new net::UploadElement();
    base::FilePath path = base::FilePath(CefString(&data_.filename));
    element->SetToFilePath(path);
    return std::make_unique<FileElementReader>(base::WrapUnique(element));
  } else {
    NOTREACHED();
    return nullptr;
  }
}

void CefPostDataElementImpl::SetReadOnly(bool read_only) {
  base::AutoLock lock_scope(lock_);
  if (read_only_ == read_only)
    return;

  read_only_ = read_only;
}

void CefPostDataElementImpl::SetTrackChanges(bool track_changes) {
  base::AutoLock lock_scope(lock_);
  if (track_changes_ == track_changes)
    return;

  track_changes_ = track_changes;
  has_changes_ = false;
}

bool CefPostDataElementImpl::HasChanges() const {
  base::AutoLock lock_scope(lock_);
  return has_changes_;
}

void CefPostDataElementImpl::Changed() {
  lock_.AssertAcquired();
  if (track_changes_ && !has_changes_)
    has_changes_ = true;
}

void CefPostDataElementImpl::Cleanup() {
  if (type_ == PDE_TYPE_EMPTY)
    return;

  if (type_ == PDE_TYPE_BYTES)
    free(data_.bytes.bytes);
  else if (type_ == PDE_TYPE_FILE)
    cef_string_clear(&data_.filename);
  type_ = PDE_TYPE_EMPTY;
  memset(&data_, 0, sizeof(data_));
}
