/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/inspector/inspector_network_agent.h"

#include <memory>
#include <utility>

#include "base/containers/span.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "services/network/public/mojom/trust_tokens.mojom-blink.h"
#include "services/network/public/mojom/websocket.mojom-blink.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/mixed_content.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/public/platform/web_url_loader_client.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/inspector/network_resources_data.h"
#include "third_party/blink/renderer/core/inspector/protocol/Network.h"
#include "third_party/blink/renderer/core/inspector/request_debug_header_scope.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/render_blocking_behavior.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/inspector_protocol/crdtp/json.h"

using crdtp::SpanFrom;
using crdtp::json::ConvertCBORToJSON;

namespace blink {

using GetRequestPostDataCallback =
    protocol::Network::Backend::GetRequestPostDataCallback;
using GetResponseBodyCallback =
    protocol::Network::Backend::GetResponseBodyCallback;
using protocol::Response;

namespace {

#if defined(OS_ANDROID)
constexpr int kDefaultTotalBufferSize = 10 * 1000 * 1000;    // 10 MB
constexpr int kDefaultResourceBufferSize = 5 * 1000 * 1000;  // 5 MB
#else
constexpr int kDefaultTotalBufferSize = 100 * 1000 * 1000;    // 100 MB
constexpr int kDefaultResourceBufferSize = 10 * 1000 * 1000;  // 10 MB
#endif

// Pattern may contain stars ('*') which match to any (possibly empty) string.
// Stars implicitly assumed at the begin/end of pattern.
bool Matches(const String& url, const String& pattern) {
  Vector<String> parts;
  pattern.Split("*", parts);
  wtf_size_t pos = 0;
  for (const String& part : parts) {
    pos = url.Find(part, pos);
    if (pos == kNotFound)
      return false;
    pos += part.length();
  }
  return true;
}

bool LoadsFromCacheOnly(const ResourceRequest& request) {
  switch (request.GetCacheMode()) {
    case mojom::FetchCacheMode::kDefault:
    case mojom::FetchCacheMode::kNoStore:
    case mojom::FetchCacheMode::kValidateCache:
    case mojom::FetchCacheMode::kBypassCache:
    case mojom::FetchCacheMode::kForceCache:
      return false;
    case mojom::FetchCacheMode::kOnlyIfCached:
    case mojom::FetchCacheMode::kUnspecifiedOnlyIfCachedStrict:
    case mojom::FetchCacheMode::kUnspecifiedForceCacheMiss:
      return true;
  }
  NOTREACHED();
  return false;
}

protocol::Network::CertificateTransparencyCompliance
SerializeCTPolicyCompliance(
    ResourceResponse::CTPolicyCompliance ct_compliance) {
  switch (ct_compliance) {
    case ResourceResponse::kCTPolicyComplianceDetailsNotAvailable:
      return protocol::Network::CertificateTransparencyComplianceEnum::Unknown;
    case ResourceResponse::kCTPolicyComplies:
      return protocol::Network::CertificateTransparencyComplianceEnum::
          Compliant;
    case ResourceResponse::kCTPolicyDoesNotComply:
      return protocol::Network::CertificateTransparencyComplianceEnum::
          NotCompliant;
  }
  NOTREACHED();
  return protocol::Network::CertificateTransparencyComplianceEnum::Unknown;
}

static std::unique_ptr<protocol::Network::Headers> BuildObjectForHeaders(
    const HTTPHeaderMap& headers) {
  std::unique_ptr<protocol::DictionaryValue> headers_object =
      protocol::DictionaryValue::create();
  for (const auto& header : headers)
    headers_object->setString(header.key.GetString(), header.value);
  protocol::ErrorSupport errors;
  return protocol::Network::Headers::fromValue(headers_object.get(), &errors);
}

class InspectorFileReaderLoaderClient final : public FileReaderLoaderClient {
 public:
  InspectorFileReaderLoaderClient(
      scoped_refptr<BlobDataHandle> blob,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
      base::OnceCallback<void(scoped_refptr<SharedBuffer>)> callback)
      : blob_(std::move(blob)), callback_(std::move(callback)) {
    loader_ = std::make_unique<FileReaderLoader>(
        FileReaderLoader::kReadByClient, this, std::move(task_runner));
  }

  ~InspectorFileReaderLoaderClient() override = default;

  void Start() {
    raw_data_ = SharedBuffer::Create();
    loader_->Start(blob_);
  }

  void DidStartLoading() override {}

  void DidReceiveDataForClient(const char* data,
                               unsigned data_length) override {
    if (!data_length)
      return;
    raw_data_->Append(data, data_length);
  }

  void DidFinishLoading() override { Done(raw_data_); }

  void DidFail(FileErrorCode) override { Done(nullptr); }

 private:
  void Done(scoped_refptr<SharedBuffer> output) {
    std::move(callback_).Run(output);
    delete this;
  }

  scoped_refptr<BlobDataHandle> blob_;
  String mime_type_;
  String text_encoding_name_;
  base::OnceCallback<void(scoped_refptr<SharedBuffer>)> callback_;
  std::unique_ptr<FileReaderLoader> loader_;
  scoped_refptr<SharedBuffer> raw_data_;
  DISALLOW_COPY_AND_ASSIGN(InspectorFileReaderLoaderClient);
};

static void ResponseBodyFileReaderLoaderDone(
    const String& mime_type,
    const String& text_encoding_name,
    std::unique_ptr<GetResponseBodyCallback> callback,
    scoped_refptr<SharedBuffer> raw_data) {
  if (!raw_data) {
    callback->sendFailure(Response::ServerError("Couldn't read BLOB"));
    return;
  }
  String result;
  bool base64_encoded;
  if (InspectorPageAgent::SharedBufferContent(
          raw_data, mime_type, text_encoding_name, &result, &base64_encoded)) {
    callback->sendSuccess(result, base64_encoded);
  } else {
    callback->sendFailure(Response::ServerError("Couldn't encode data"));
  }
}

class InspectorPostBodyParser
    : public WTF::RefCounted<InspectorPostBodyParser> {
 public:
  InspectorPostBodyParser(
      std::unique_ptr<GetRequestPostDataCallback> callback,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner)
      : callback_(std::move(callback)),
        task_runner_(std::move(task_runner)),
        error_(false) {}

  void Parse(EncodedFormData* request_body) {
    if (!request_body || request_body->IsEmpty())
      return;

    parts_.Grow(request_body->Elements().size());
    for (wtf_size_t i = 0; i < request_body->Elements().size(); i++) {
      const FormDataElement& data = request_body->Elements()[i];
      switch (data.type_) {
        case FormDataElement::kData:
          parts_[i] = String::FromUTF8WithLatin1Fallback(data.data_.data(),
                                                         data.data_.size());
          break;
        case FormDataElement::kEncodedBlob:
          ReadDataBlob(data.optional_blob_data_handle_, &parts_[i]);
          break;
        case FormDataElement::kEncodedFile:
        case FormDataElement::kDataPipe:
          // Do nothing, not supported
          break;
      }
    }
  }

 private:
  friend class WTF::RefCounted<InspectorPostBodyParser>;

  ~InspectorPostBodyParser() {
    if (error_)
      return;
    StringBuilder result;
    for (const auto& part : parts_)
      result.Append(part);
    callback_->sendSuccess(result.ToString());
  }

  void BlobReadCallback(String* destination,
                        scoped_refptr<SharedBuffer> raw_data) {
    if (raw_data) {
      *destination = String::FromUTF8WithLatin1Fallback(raw_data->Data(),
                                                        raw_data->size());
    } else {
      error_ = true;
    }
  }

  void ReadDataBlob(scoped_refptr<blink::BlobDataHandle> blob_handle,
                    String* destination) {
    if (!blob_handle)
      return;
    auto* reader = new InspectorFileReaderLoaderClient(
        blob_handle, task_runner_,
        WTF::Bind(&InspectorPostBodyParser::BlobReadCallback,
                  WTF::RetainedRef(this), WTF::Unretained(destination)));
    reader->Start();
  }

  std::unique_ptr<GetRequestPostDataCallback> callback_;
  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  bool error_;
  Vector<String> parts_;
  DISALLOW_COPY_AND_ASSIGN(InspectorPostBodyParser);
};

KURL UrlWithoutFragment(const KURL& url) {
  KURL result = url;
  result.RemoveFragmentIdentifier();
  return result;
}

String MixedContentTypeForContextType(
    mojom::blink::MixedContentContextType context_type) {
  switch (context_type) {
    case mojom::blink::MixedContentContextType::kNotMixedContent:
      return protocol::Security::MixedContentTypeEnum::None;
    case mojom::blink::MixedContentContextType::kBlockable:
      return protocol::Security::MixedContentTypeEnum::Blockable;
    case mojom::blink::MixedContentContextType::kOptionallyBlockable:
    case mojom::blink::MixedContentContextType::kShouldBeBlockable:
      return protocol::Security::MixedContentTypeEnum::OptionallyBlockable;
  }

  return protocol::Security::MixedContentTypeEnum::None;
}

String ResourcePriorityJSON(ResourceLoadPriority priority) {
  switch (priority) {
    case ResourceLoadPriority::kVeryLow:
      return protocol::Network::ResourcePriorityEnum::VeryLow;
    case ResourceLoadPriority::kLow:
      return protocol::Network::ResourcePriorityEnum::Low;
    case ResourceLoadPriority::kMedium:
      return protocol::Network::ResourcePriorityEnum::Medium;
    case ResourceLoadPriority::kHigh:
      return protocol::Network::ResourcePriorityEnum::High;
    case ResourceLoadPriority::kVeryHigh:
      return protocol::Network::ResourcePriorityEnum::VeryHigh;
    case ResourceLoadPriority::kUnresolved:
      break;
  }
  NOTREACHED();
  return protocol::Network::ResourcePriorityEnum::Medium;
}

String BuildBlockedReason(ResourceRequestBlockedReason reason) {
  switch (reason) {
    case ResourceRequestBlockedReason::kCSP:
      return protocol::Network::BlockedReasonEnum::Csp;
    case ResourceRequestBlockedReason::kMixedContent:
      return protocol::Network::BlockedReasonEnum::MixedContent;
    case ResourceRequestBlockedReason::kOrigin:
      return protocol::Network::BlockedReasonEnum::Origin;
    case ResourceRequestBlockedReason::kInspector:
      return protocol::Network::BlockedReasonEnum::Inspector;
    case ResourceRequestBlockedReason::kSubresourceFilter:
      return protocol::Network::BlockedReasonEnum::SubresourceFilter;
    case ResourceRequestBlockedReason::kContentType:
      return protocol::Network::BlockedReasonEnum::ContentType;
    case ResourceRequestBlockedReason::kOther:
      return protocol::Network::BlockedReasonEnum::Other;
    case ResourceRequestBlockedReason::kCollapsedByClient:
      return protocol::Network::BlockedReasonEnum::CollapsedByClient;
    case blink::ResourceRequestBlockedReason::kCoepFrameResourceNeedsCoepHeader:
      return protocol::Network::BlockedReasonEnum::
          CoepFrameResourceNeedsCoepHeader;
    case blink::ResourceRequestBlockedReason::
        kCoopSandboxedIFrameCannotNavigateToCoopPage:
      return protocol::Network::BlockedReasonEnum::
          CoopSandboxedIframeCannotNavigateToCoopPage;
    case blink::ResourceRequestBlockedReason::kCorpNotSameOrigin:
      return protocol::Network::BlockedReasonEnum::CorpNotSameOrigin;
    case blink::ResourceRequestBlockedReason::
        kCorpNotSameOriginAfterDefaultedToSameOriginByCoep:
      return protocol::Network::BlockedReasonEnum::
          CorpNotSameOriginAfterDefaultedToSameOriginByCoep;
    case blink::ResourceRequestBlockedReason::kCorpNotSameSite:
      return protocol::Network::BlockedReasonEnum::CorpNotSameSite;
    case ResourceRequestBlockedReason::kConversionRequest:
      // This is actually never reached, as the conversion request
      // is marked as successful and no blocking reason is reported.
      NOTREACHED();
      return protocol::Network::BlockedReasonEnum::Other;
  }
  NOTREACHED();
  return protocol::Network::BlockedReasonEnum::Other;
}

String BuildCorsError(network::mojom::CorsError cors_error) {
  switch (cors_error) {
    case network::mojom::CorsError::kDisallowedByMode:
      return protocol::Network::CorsErrorEnum::DisallowedByMode;

    case network::mojom::CorsError::kInvalidResponse:
      return protocol::Network::CorsErrorEnum::InvalidResponse;

    case network::mojom::CorsError::kWildcardOriginNotAllowed:
      return protocol::Network::CorsErrorEnum::WildcardOriginNotAllowed;

    case network::mojom::CorsError::kMissingAllowOriginHeader:
      return protocol::Network::CorsErrorEnum::MissingAllowOriginHeader;

    case network::mojom::CorsError::kMultipleAllowOriginValues:
      return protocol::Network::CorsErrorEnum::MultipleAllowOriginValues;

    case network::mojom::CorsError::kInvalidAllowOriginValue:
      return protocol::Network::CorsErrorEnum::InvalidAllowOriginValue;

    case network::mojom::CorsError::kAllowOriginMismatch:
      return protocol::Network::CorsErrorEnum::AllowOriginMismatch;

    case network::mojom::CorsError::kInvalidAllowCredentials:
      return protocol::Network::CorsErrorEnum::InvalidAllowCredentials;

    case network::mojom::CorsError::kCorsDisabledScheme:
      return protocol::Network::CorsErrorEnum::CorsDisabledScheme;

    case network::mojom::CorsError::kPreflightInvalidStatus:
      return protocol::Network::CorsErrorEnum::PreflightInvalidStatus;

    case network::mojom::CorsError::kPreflightDisallowedRedirect:
      return protocol::Network::CorsErrorEnum::PreflightDisallowedRedirect;

    case network::mojom::CorsError::kPreflightWildcardOriginNotAllowed:
      return protocol::Network::CorsErrorEnum::
          PreflightWildcardOriginNotAllowed;

    case network::mojom::CorsError::kPreflightMissingAllowOriginHeader:
      return protocol::Network::CorsErrorEnum::
          PreflightMissingAllowOriginHeader;

    case network::mojom::CorsError::kPreflightMultipleAllowOriginValues:
      return protocol::Network::CorsErrorEnum::
          PreflightMultipleAllowOriginValues;

    case network::mojom::CorsError::kPreflightInvalidAllowOriginValue:
      return protocol::Network::CorsErrorEnum::PreflightInvalidAllowOriginValue;

    case network::mojom::CorsError::kPreflightAllowOriginMismatch:
      return protocol::Network::CorsErrorEnum::PreflightAllowOriginMismatch;

    case network::mojom::CorsError::kPreflightInvalidAllowCredentials:
      return protocol::Network::CorsErrorEnum::PreflightInvalidAllowCredentials;

    case network::mojom::CorsError::kPreflightMissingAllowExternal:
      return protocol::Network::CorsErrorEnum::PreflightMissingAllowExternal;

    case network::mojom::CorsError::kPreflightInvalidAllowExternal:
      return protocol::Network::CorsErrorEnum::PreflightInvalidAllowExternal;

    case network::mojom::CorsError::kInvalidAllowMethodsPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          InvalidAllowMethodsPreflightResponse;

    case network::mojom::CorsError::kInvalidAllowHeadersPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          InvalidAllowHeadersPreflightResponse;

    case network::mojom::CorsError::kMethodDisallowedByPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          MethodDisallowedByPreflightResponse;

    case network::mojom::CorsError::kHeaderDisallowedByPreflightResponse:
      return protocol::Network::CorsErrorEnum::
          HeaderDisallowedByPreflightResponse;

    case network::mojom::CorsError::kRedirectContainsCredentials:
      return protocol::Network::CorsErrorEnum::RedirectContainsCredentials;

    case network::mojom::CorsError::kInsecurePrivateNetwork:
      return protocol::Network::CorsErrorEnum::InsecurePrivateNetwork;
  }
}

std::unique_ptr<protocol::Network::CorsErrorStatus> BuildCorsErrorStatus(
    network::CorsErrorStatus status) {
  return protocol::Network::CorsErrorStatus::create()
      .setCorsError(BuildCorsError(status.cors_error))
      .setFailedParameter(String::FromUTF8(status.failed_parameter))
      .build();
}

String BuildServiceWorkerResponseSource(const ResourceResponse& response) {
  switch (response.GetServiceWorkerResponseSource()) {
    case network::mojom::FetchResponseSource::kCacheStorage:
      return protocol::Network::ServiceWorkerResponseSourceEnum::CacheStorage;
    case network::mojom::FetchResponseSource::kHttpCache:
      return protocol::Network::ServiceWorkerResponseSourceEnum::HttpCache;
    case network::mojom::FetchResponseSource::kNetwork:
      return protocol::Network::ServiceWorkerResponseSourceEnum::Network;
    case network::mojom::FetchResponseSource::kUnspecified:
      return protocol::Network::ServiceWorkerResponseSourceEnum::FallbackCode;
  }
}

WebConnectionType ToWebConnectionType(const String& connection_type) {
  if (connection_type == protocol::Network::ConnectionTypeEnum::None)
    return kWebConnectionTypeNone;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Cellular2g)
    return kWebConnectionTypeCellular2G;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Cellular3g)
    return kWebConnectionTypeCellular3G;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Cellular4g)
    return kWebConnectionTypeCellular4G;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Bluetooth)
    return kWebConnectionTypeBluetooth;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Ethernet)
    return kWebConnectionTypeEthernet;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Wifi)
    return kWebConnectionTypeWifi;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Wimax)
    return kWebConnectionTypeWimax;
  if (connection_type == protocol::Network::ConnectionTypeEnum::Other)
    return kWebConnectionTypeOther;
  return kWebConnectionTypeUnknown;
}

String GetReferrerPolicy(network::mojom::ReferrerPolicy policy) {
  switch (policy) {
    case network::mojom::ReferrerPolicy::kAlways:
      return protocol::Network::Request::ReferrerPolicyEnum::UnsafeUrl;
    case network::mojom::ReferrerPolicy::kDefault:
      return protocol::Network::Request::ReferrerPolicyEnum::
          StrictOriginWhenCrossOrigin;
    case network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade:
      return protocol::Network::Request::ReferrerPolicyEnum::
          NoReferrerWhenDowngrade;
    case network::mojom::ReferrerPolicy::kNever:
      return protocol::Network::Request::ReferrerPolicyEnum::NoReferrer;
    case network::mojom::ReferrerPolicy::kOrigin:
      return protocol::Network::Request::ReferrerPolicyEnum::Origin;
    case network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin:
      return protocol::Network::Request::ReferrerPolicyEnum::
          OriginWhenCrossOrigin;
    case network::mojom::ReferrerPolicy::kSameOrigin:
      return protocol::Network::Request::ReferrerPolicyEnum::SameOrigin;
    case network::mojom::ReferrerPolicy::kStrictOrigin:
      return protocol::Network::Request::ReferrerPolicyEnum::StrictOrigin;
    case network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin:
      return protocol::Network::Request::ReferrerPolicyEnum::
          StrictOriginWhenCrossOrigin;
  }

  return protocol::Network::Request::ReferrerPolicyEnum::
      NoReferrerWhenDowngrade;
}

std::unique_ptr<protocol::Network::WebSocketFrame> WebSocketMessageToProtocol(
    int op_code,
    bool masked,
    const char* payload,
    size_t payload_length) {
  return protocol::Network::WebSocketFrame::create()
      .setOpcode(op_code)
      .setMask(masked)
      // Only interpret the payload as UTF-8 when it's a text message
      .setPayloadData(
          op_code == 1
              ? String::FromUTF8WithLatin1Fallback(payload, payload_length)
              : Base64Encode(
                    base::as_bytes(base::make_span(payload, payload_length))))
      .build();
}

String GetTrustTokenOperationType(
    network::mojom::TrustTokenOperationType type) {
  switch (type) {
    case network::mojom::TrustTokenOperationType::kIssuance:
      return protocol::Network::TrustTokenOperationTypeEnum::Issuance;
    case network::mojom::TrustTokenOperationType::kRedemption:
      return protocol::Network::TrustTokenOperationTypeEnum::Redemption;
    case network::mojom::TrustTokenOperationType::kSigning:
      return protocol::Network::TrustTokenOperationTypeEnum::Signing;
  }
}

String GetTrustTokenRefreshPolicy(
    network::mojom::TrustTokenRefreshPolicy policy) {
  switch (policy) {
    case network::mojom::TrustTokenRefreshPolicy::kUseCached:
      return protocol::Network::TrustTokenParams::RefreshPolicyEnum::UseCached;
    case network::mojom::TrustTokenRefreshPolicy::kRefresh:
      return protocol::Network::TrustTokenParams::RefreshPolicyEnum::Refresh;
  }
}

std::unique_ptr<protocol::Network::TrustTokenParams> BuildTrustTokenParams(
    const network::mojom::blink::TrustTokenParams& params) {
  auto protocol_params =
      protocol::Network::TrustTokenParams::create()
          .setType(GetTrustTokenOperationType(params.type))
          .setRefreshPolicy(GetTrustTokenRefreshPolicy(params.refresh_policy))
          .build();

  if (!params.issuers.IsEmpty()) {
    auto issuers = std::make_unique<protocol::Array<protocol::String>>();
    for (const auto& issuer : params.issuers) {
      issuers->push_back(issuer->ToString());
    }
    protocol_params->setIssuers(std::move(issuers));
  }

  return protocol_params;
}

void SetNetworkStateOverride(bool offline,
                             double latency,
                             double download_throughput,
                             double upload_throughput,
                             WebConnectionType type) {
  // TODO(dgozman): networkStateNotifier is per-process. It would be nice to
  // have per-frame override instead.
  if (offline || latency || download_throughput || upload_throughput) {
    GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(
        !offline, type, base::nullopt, latency,
        download_throughput / (1024 * 1024 / 8));
  } else {
    GetNetworkStateNotifier().ClearOverride();
  }
}

String IPAddressToString(const net::IPAddress& address) {
  String unbracketed = String::FromUTF8(address.ToString());
  if (!address.IsIPv6()) {
    return unbracketed;
  }

  return "[" + unbracketed + "]";
}

}  // namespace

void InspectorNetworkAgent::Restore() {
  if (enabled_.Get())
    Enable();
}

static std::unique_ptr<protocol::Network::ResourceTiming> BuildObjectForTiming(
    const ResourceLoadTiming& timing) {
  return protocol::Network::ResourceTiming::create()
      .setRequestTime(timing.RequestTime().since_origin().InSecondsF())
      .setProxyStart(timing.CalculateMillisecondDelta(timing.ProxyStart()))
      .setProxyEnd(timing.CalculateMillisecondDelta(timing.ProxyEnd()))
      .setDnsStart(timing.CalculateMillisecondDelta(timing.DnsStart()))
      .setDnsEnd(timing.CalculateMillisecondDelta(timing.DnsEnd()))
      .setConnectStart(timing.CalculateMillisecondDelta(timing.ConnectStart()))
      .setConnectEnd(timing.CalculateMillisecondDelta(timing.ConnectEnd()))
      .setSslStart(timing.CalculateMillisecondDelta(timing.SslStart()))
      .setSslEnd(timing.CalculateMillisecondDelta(timing.SslEnd()))
      .setWorkerStart(timing.CalculateMillisecondDelta(timing.WorkerStart()))
      .setWorkerReady(timing.CalculateMillisecondDelta(timing.WorkerReady()))
      .setWorkerFetchStart(
          timing.CalculateMillisecondDelta(timing.WorkerFetchStart()))
      .setWorkerRespondWithSettled(
          timing.CalculateMillisecondDelta(timing.WorkerRespondWithSettled()))
      .setSendStart(timing.CalculateMillisecondDelta(timing.SendStart()))
      .setSendEnd(timing.CalculateMillisecondDelta(timing.SendEnd()))
      .setReceiveHeadersEnd(
          timing.CalculateMillisecondDelta(timing.ReceiveHeadersEnd()))
      .setPushStart(timing.PushStart().since_origin().InSecondsF())
      .setPushEnd(timing.PushEnd().since_origin().InSecondsF())
      .build();
}

static bool FormDataToString(
    scoped_refptr<EncodedFormData> body,
    size_t max_body_size,
    protocol::Array<protocol::Network::PostDataEntry>* data_entries,
    String* content) {
  *content = "";
  if (!body || body->IsEmpty())
    return false;

  // SizeInBytes below doesn't support all element types, so first check if all
  // the body elements are of the right type.
  for (const auto& element : body->Elements()) {
    if (element.type_ != FormDataElement::kData)
      return true;
  }

  if (max_body_size != 0 && body->SizeInBytes() > max_body_size)
    return true;

  for (const auto& element : body->Elements()) {
    auto data_entry = protocol::Network::PostDataEntry::create().build();
    auto bytes = protocol::Binary::fromSpan(
        reinterpret_cast<const uint8_t*>(element.data_.data()),
        element.data_.size());
    data_entry->setBytes(std::move(bytes));
    data_entries->push_back(std::move(data_entry));
  }

  Vector<char> bytes;
  body->Flatten(bytes);
  *content = String::FromUTF8WithLatin1Fallback(bytes.data(), bytes.size());
  return true;
}

static std::unique_ptr<protocol::Network::Request>
BuildObjectForResourceRequest(const ResourceRequest& request,
                              scoped_refptr<EncodedFormData> post_data,
                              size_t max_body_size) {
  String data_string;
  auto data_entries =
      std::make_unique<protocol::Array<protocol::Network::PostDataEntry>>();
  bool has_post_data = FormDataToString(post_data, max_body_size,
                                        data_entries.get(), &data_string);
  KURL url = request.Url();
  // protocol::Network::Request doesn't have a separate referrer string member
  // like blink::ResourceRequest, so here we add ResourceRequest's referrer
  // string to the protocol request's headers manually.
  auto headers = request.HttpHeaderFields();

  // The request's referrer must be generated at this point.
  DCHECK_NE(request.ReferrerString(), Referrer::ClientReferrerString());
  headers.Set(http_names::kReferer, AtomicString(request.ReferrerString()));

  std::unique_ptr<protocol::Network::Request> result =
      protocol::Network::Request::create()
          .setUrl(UrlWithoutFragment(url).GetString())
          .setMethod(request.HttpMethod())
          .setHeaders(BuildObjectForHeaders(headers))
          .setInitialPriority(ResourcePriorityJSON(request.Priority()))
          .setReferrerPolicy(GetReferrerPolicy(request.GetReferrerPolicy()))
          .build();
  if (url.FragmentIdentifier())
    result->setUrlFragment("#" + url.FragmentIdentifier());
  if (!data_string.IsEmpty())
    result->setPostData(data_string);
  if (data_entries->size())
    result->setPostDataEntries(std::move(data_entries));
  if (has_post_data)
    result->setHasPostData(true);
  if (request.TrustTokenParams()) {
    result->setTrustTokenParams(
        BuildTrustTokenParams(*request.TrustTokenParams()));
  }
  return result;
}

static std::unique_ptr<protocol::Network::Response>
BuildObjectForResourceResponse(const ResourceResponse& response,
                               const Resource* cached_resource = nullptr,
                               bool* is_empty = nullptr) {
  if (response.IsNull())
    return nullptr;

  int status;
  String status_text;
  if (response.GetResourceLoadInfo() &&
      response.GetResourceLoadInfo()->http_status_code) {
    status = response.GetResourceLoadInfo()->http_status_code;
    status_text = response.GetResourceLoadInfo()->http_status_text;
  } else {
    status = response.HttpStatusCode();
    status_text = response.HttpStatusText();
  }
  HTTPHeaderMap headers_map;
  if (response.GetResourceLoadInfo() &&
      response.GetResourceLoadInfo()->response_headers.size())
    headers_map = response.GetResourceLoadInfo()->response_headers;
  else
    headers_map = response.HttpHeaderFields();

  int64_t encoded_data_length = response.EncodedDataLength();

  String security_state = protocol::Security::SecurityStateEnum::Unknown;
  switch (response.GetSecurityStyle()) {
    case SecurityStyle::kUnknown:
      security_state = protocol::Security::SecurityStateEnum::Unknown;
      break;
    case SecurityStyle::kNeutral:
      security_state = protocol::Security::SecurityStateEnum::Neutral;
      break;
    case SecurityStyle::kInsecure:
      security_state = protocol::Security::SecurityStateEnum::Insecure;
      break;
    case SecurityStyle::kSecure:
      security_state = protocol::Security::SecurityStateEnum::Secure;
      break;
    case SecurityStyle::kInsecureBroken:
      security_state = protocol::Security::SecurityStateEnum::InsecureBroken;
      break;
  }

  // Use mime type from cached resource in case the one in response is empty
  // or the response is a 304 Not Modified.
  String mime_type = response.MimeType();
  if (cached_resource &&
      (mime_type.IsEmpty() || response.HttpStatusCode() == 304))
    mime_type = cached_resource->GetResponse().MimeType();

  if (is_empty)
    *is_empty = !status && mime_type.IsEmpty() && !headers_map.size();

  std::unique_ptr<protocol::Network::Response> response_object =
      protocol::Network::Response::create()
          .setUrl(UrlWithoutFragment(response.CurrentRequestUrl()).GetString())
          .setStatus(status)
          .setStatusText(status_text)
          .setHeaders(BuildObjectForHeaders(headers_map))
          .setMimeType(mime_type)
          .setConnectionReused(response.ConnectionReused())
          .setConnectionId(response.ConnectionID())
          .setEncodedDataLength(encoded_data_length)
          .setSecurityState(security_state)
          .build();

  response_object->setFromDiskCache(response.WasCached());
  response_object->setFromServiceWorker(response.WasFetchedViaServiceWorker());
  if (response.WasFetchedViaServiceWorker()) {
    response_object->setServiceWorkerResponseSource(
        BuildServiceWorkerResponseSource(response));
  }
  if (!response.ResponseTime().is_null()) {
    response_object->setResponseTime(
        response.ResponseTime().ToJsTimeIgnoringNull());
  }
  if (!response.CacheStorageCacheName().IsEmpty()) {
    response_object->setCacheStorageCacheName(response.CacheStorageCacheName());
  }

  response_object->setFromPrefetchCache(response.WasInPrefetchCache());
  if (response.GetResourceLoadTiming())
    response_object->setTiming(
        BuildObjectForTiming(*response.GetResourceLoadTiming()));

  if (response.GetResourceLoadInfo()) {
    if (!response.GetResourceLoadInfo()->response_headers_text.IsEmpty()) {
      response_object->setHeadersText(
          response.GetResourceLoadInfo()->response_headers_text);
    }
    if (response.GetResourceLoadInfo()->request_headers.size()) {
      response_object->setRequestHeaders(BuildObjectForHeaders(
          response.GetResourceLoadInfo()->request_headers));
    }
    if (!response.GetResourceLoadInfo()->request_headers_text.IsEmpty()) {
      response_object->setRequestHeadersText(
          response.GetResourceLoadInfo()->request_headers_text);
    }
  }

  const net::IPEndPoint& remote_ip_endpoint = response.RemoteIPEndpoint();
  if (remote_ip_endpoint.address().IsValid()) {
    response_object->setRemoteIPAddress(
        IPAddressToString(remote_ip_endpoint.address()));
    response_object->setRemotePort(remote_ip_endpoint.port());
  }

  String protocol = response.AlpnNegotiatedProtocol();
  if (protocol.IsEmpty() || protocol == "unknown") {
    if (response.WasFetchedViaSPDY()) {
      protocol = "h2";
    } else if (response.IsHTTP()) {
      protocol = "http";
      if (response.HttpVersion() ==
          ResourceResponse::HTTPVersion::kHTTPVersion_0_9)
        protocol = "http/0.9";
      else if (response.HttpVersion() ==
               ResourceResponse::HTTPVersion::kHTTPVersion_1_0)
        protocol = "http/1.0";
      else if (response.HttpVersion() ==
               ResourceResponse::HTTPVersion::kHTTPVersion_1_1)
        protocol = "http/1.1";
    } else {
      protocol = response.CurrentRequestUrl().Protocol();
    }
  }
  response_object->setProtocol(protocol);

  const base::Optional<ResourceResponse::SecurityDetails>&
      response_security_details = response.GetSecurityDetails();
  if (response_security_details.has_value()) {
    auto san_list = std::make_unique<protocol::Array<String>>(
        response_security_details->san_list.begin(),
        response_security_details->san_list.end());

    auto signed_certificate_timestamp_list = std::make_unique<
        protocol::Array<protocol::Network::SignedCertificateTimestamp>>();
    for (auto const& sct : response_security_details->sct_list) {
      std::unique_ptr<protocol::Network::SignedCertificateTimestamp>
          signed_certificate_timestamp =
              protocol::Network::SignedCertificateTimestamp::create()
                  .setStatus(sct.status_)
                  .setOrigin(sct.origin_)
                  .setLogDescription(sct.log_description_)
                  .setLogId(sct.log_id_)
                  .setTimestamp(sct.timestamp_)
                  .setHashAlgorithm(sct.hash_algorithm_)
                  .setSignatureAlgorithm(sct.signature_algorithm_)
                  .setSignatureData(sct.signature_data_)
                  .build();
      signed_certificate_timestamp_list->emplace_back(
          std::move(signed_certificate_timestamp));
    }

    std::unique_ptr<protocol::Network::SecurityDetails> security_details =
        protocol::Network::SecurityDetails::create()
            .setProtocol(response_security_details->protocol)
            .setKeyExchange(response_security_details->key_exchange)
            .setCipher(response_security_details->cipher)
            .setSubjectName(response_security_details->subject_name)
            .setSanList(std::move(san_list))
            .setIssuer(response_security_details->issuer)
            .setValidFrom(response_security_details->valid_from)
            .setValidTo(response_security_details->valid_to)
            .setCertificateId(0)  // Keep this in protocol for compatability.
            .setSignedCertificateTimestampList(
                std::move(signed_certificate_timestamp_list))
            .setCertificateTransparencyCompliance(
                SerializeCTPolicyCompliance(response.GetCTPolicyCompliance()))
            .build();
    if (response_security_details->key_exchange_group.length() > 0)
      security_details->setKeyExchangeGroup(
          response_security_details->key_exchange_group);
    if (response_security_details->mac.length() > 0)
      security_details->setMac(response_security_details->mac);

    response_object->setSecurityDetails(std::move(security_details));
  }

  return response_object;
}

InspectorNetworkAgent::~InspectorNetworkAgent() = default;

void InspectorNetworkAgent::Trace(Visitor* visitor) const {
  visitor->Trace(inspected_frames_);
  visitor->Trace(worker_global_scope_);
  visitor->Trace(resources_data_);
  visitor->Trace(replay_xhrs_);
  visitor->Trace(pending_xhr_replay_data_);
  InspectorBaseAgent::Trace(visitor);
}

void InspectorNetworkAgent::ShouldBlockRequest(const KURL& url, bool* result) {
  if (blocked_urls_.IsEmpty())
    return;

  String url_string = url.GetString();
  for (const String& blocked : blocked_urls_.Keys()) {
    if (Matches(url_string, blocked)) {
      *result = true;
      return;
    }
  }
}

void InspectorNetworkAgent::ShouldBypassServiceWorker(bool* result) {
  if (bypass_service_worker_.Get())
    *result = true;
}

void InspectorNetworkAgent::DidBlockRequest(
    const ResourceRequest& request,
    DocumentLoader* loader,
    const KURL& fetch_context_url,
    const FetchInitiatorInfo& initiator_info,
    ResourceRequestBlockedReason reason,
    ResourceType resource_type) {
  uint64_t identifier = request.InspectorId();
  if (identifier == 0UL) {
    NOTREACHED();
    // Defensively create a valid identifier.
    identifier = CreateUniqueIdentifier();
  }
  InspectorPageAgent::ResourceType type =
      InspectorPageAgent::ToResourceType(resource_type);

  WillSendRequestInternal(identifier, loader, fetch_context_url, request,
                          ResourceResponse(), initiator_info, type);

  String request_id = IdentifiersFactory::RequestId(loader, identifier);

  // Conversion Measurement API triggers recording of conversions
  // as redirects to a `/.well-known/register-conversion` url.
  // The redirect request is not actually executed
  // but stored internally and then aborted. As the redirect is blocked using
  // the ResourceRequestBlockedReason::kConversionRequest even when everything
  // worked out fine, we mark the request as successful, as to not confuse devs.
  if (reason == ResourceRequestBlockedReason::kConversionRequest) {
    GetFrontend()->loadingFinished(
        request_id, base::TimeTicks::Now().since_origin().InSecondsF(), 0);
    return;
  }

  String protocol_reason = BuildBlockedReason(reason);
  GetFrontend()->loadingFailed(
      request_id, base::TimeTicks::Now().since_origin().InSecondsF(),
      InspectorPageAgent::ResourceTypeJson(
          resources_data_->GetResourceType(request_id)),
      String(), false, protocol_reason);
}

void InspectorNetworkAgent::DidChangeResourcePriority(
    DocumentLoader* loader,
    uint64_t identifier,
    ResourceLoadPriority load_priority) {
  String request_id = IdentifiersFactory::RequestId(loader, identifier);
  GetFrontend()->resourceChangedPriority(
      request_id, ResourcePriorityJSON(load_priority),
      base::TimeTicks::Now().since_origin().InSecondsF());
}

void InspectorNetworkAgent::WillSendRequestInternal(
    uint64_t identifier,
    DocumentLoader* loader,
    const KURL& fetch_context_url,
    const ResourceRequest& request,
    const ResourceResponse& redirect_response,
    const FetchInitiatorInfo& initiator_info,
    InspectorPageAgent::ResourceType type) {
  CHECK_EQ(identifier, request.InspectorId());
  String loader_id = IdentifiersFactory::LoaderId(loader);
  String request_id = IdentifiersFactory::RequestId(loader, identifier);
  NetworkResourcesData::ResourceData const* data =
      resources_data_->Data(request_id);
  // Support for POST request redirect.
  scoped_refptr<EncodedFormData> post_data;
  if (data &&
      (redirect_response.HttpStatusCode() == net::HTTP_TEMPORARY_REDIRECT ||
       redirect_response.HttpStatusCode() == net::HTTP_PERMANENT_REDIRECT)) {
    post_data = data->PostData();
  } else if (request.HttpBody()) {
    post_data = request.HttpBody()->DeepCopy();
  }

  resources_data_->ResourceCreated(request_id, loader_id, request.Url(),
                                   post_data);
  if (initiator_info.name == fetch_initiator_type_names::kXmlhttprequest) {
    type = InspectorPageAgent::kXHRResource;
  } else if (initiator_info.name == fetch_initiator_type_names::kFetch) {
    type = InspectorPageAgent::kFetchResource;
  } else if (initiator_info.name == fetch_initiator_type_names::kBeacon ||
             initiator_info.name == fetch_initiator_type_names::kPing) {
    type = InspectorPageAgent::kPingResource;
  }

  if (pending_request_type_)
    type = *pending_request_type_;
  resources_data_->SetResourceType(request_id, type);

  String frame_id = loader && loader->GetFrame()
                        ? IdentifiersFactory::FrameId(loader->GetFrame())
                        : "";
  std::unique_ptr<protocol::Network::Initiator> initiator_object =
      BuildInitiatorObject(loader && loader->GetFrame()
                               ? loader->GetFrame()->GetDocument()
                               : nullptr,
                           initiator_info, std::numeric_limits<int>::max());

  std::unique_ptr<protocol::Network::Request> request_info(
      BuildObjectForResourceRequest(request, post_data,
                                    max_post_data_size_.Get()));

  // |loader| is null while inspecting worker.
  // TODO(horo): Refactor MixedContentChecker and set mixed content type even if
  // |loader| is null.
  if (loader) {
    request_info->setMixedContentType(MixedContentTypeForContextType(
        MixedContentChecker::ContextTypeForInspector(loader->GetFrame(),
                                                     request)));
  }

  request_info->setReferrerPolicy(
      GetReferrerPolicy(request.GetReferrerPolicy()));
  if (initiator_info.is_link_preload)
    request_info->setIsLinkPreload(true);

  String resource_type = InspectorPageAgent::ResourceTypeJson(type);
  String documentURL = loader
                           ? UrlWithoutFragment(loader->Url()).GetString()
                           : UrlWithoutFragment(fetch_context_url).GetString();
  Maybe<String> maybe_frame_id;
  if (!frame_id.IsEmpty())
    maybe_frame_id = frame_id;
  GetFrontend()->requestWillBeSent(
      request_id, loader_id, documentURL, std::move(request_info),
      base::TimeTicks::Now().since_origin().InSecondsF(),
      base::Time::Now().ToDoubleT(), std::move(initiator_object),
      BuildObjectForResourceResponse(redirect_response), resource_type,
      std::move(maybe_frame_id), request.HasUserGesture());
  if (is_handling_sync_xhr_)
    GetFrontend()->flush();

  if (pending_xhr_replay_data_) {
    resources_data_->SetXHRReplayData(request_id,
                                      pending_xhr_replay_data_.Get());
    pending_xhr_replay_data_.Clear();
  }
  pending_request_type_ = base::nullopt;
}

void InspectorNetworkAgent::WillSendNavigationRequest(
    uint64_t identifier,
    DocumentLoader* loader,
    const KURL& url,
    const AtomicString& http_method,
    EncodedFormData* http_body) {
  String loader_id = IdentifiersFactory::LoaderId(loader);
  String request_id = loader_id;
  NetworkResourcesData::ResourceData const* data =
      resources_data_->Data(request_id);
  // Support for POST request redirect.
  scoped_refptr<EncodedFormData> post_data;
  if (data)
    post_data = data->PostData();
  else if (http_body)
    post_data = http_body->DeepCopy();
  resources_data_->ResourceCreated(request_id, loader_id, url, post_data);
  resources_data_->SetResourceType(request_id,
                                   InspectorPageAgent::kDocumentResource);
}

// This method was pulled out of PrepareRequest(), because we want to be able
// to create DevTools issues before the PrepareRequest() call. We need these
// IDs to be set, to properly create a DevTools issue.
void InspectorNetworkAgent::SetDevToolsIds(
    ResourceRequest& request,
    const FetchInitiatorInfo& initiator_info) {
  // Network instrumentation ignores the requests initiated internally (these
  // are unexpected to the user and usually do not hit the remote server).
  // Ignore them and do not set the devtools id, so that other systems like
  // network interceptor in the browser do not mistakenly report it.
  if (initiator_info.name == fetch_initiator_type_names::kInternal)
    return;
  request.SetDevToolsToken(devtools_token_);

  // The loader parameter is for generating a browser generated ID for a browser
  // initiated request. We pass it null here because we are reporting a renderer
  // generated ID for a renderer initiated request.
  request.SetDevToolsId(IdentifiersFactory::RequestId(/* loader */ nullptr,
                                                      request.InspectorId()));
}

void InspectorNetworkAgent::PrepareRequest(DocumentLoader* loader,
                                           ResourceRequest& request,
                                           ResourceLoaderOptions& options,
                                           ResourceType resource_type) {
  // Ignore the request initiated internally.
  if (options.initiator_info.name == fetch_initiator_type_names::kInternal)
    return;

  if (!extra_request_headers_.IsEmpty()) {
    for (const WTF::String& key : extra_request_headers_.Keys()) {
      const WTF::String& value = extra_request_headers_.Get(key);
      AtomicString header_name = AtomicString(key);
      // When overriding referrer, also override referrer policy
      // for this request to assure the request will be allowed.
      // TODO: Should we store the referrer header somewhere other than
      // |extra_request_headers_|?
      if (header_name.LowerASCII() == http_names::kReferer.LowerASCII()) {
        request.SetReferrerString(value);
        request.SetReferrerPolicy(network::mojom::ReferrerPolicy::kAlways);
      } else {
        request.SetHttpHeaderField(header_name, AtomicString(value));
      }
    }
  }

  request.SetReportRawHeaders(true);

  if (cache_disabled_.Get()) {
    if (LoadsFromCacheOnly(request) &&
        request.GetRequestContext() !=
            mojom::blink::RequestContextType::INTERNAL) {
      request.SetCacheMode(mojom::FetchCacheMode::kUnspecifiedForceCacheMiss);
    } else {
      request.SetCacheMode(mojom::FetchCacheMode::kBypassCache);
    }
    request.SetShouldResetAppCache(true);
  }
  if (bypass_service_worker_.Get())
    request.SetSkipServiceWorker(true);

  if (attach_debug_stack_enabled_.Get()) {
    DCHECK(!request.GetDevToolsStackId().has_value());
    ExecutionContext* context = nullptr;
    if (worker_global_scope_) {
      context = worker_global_scope_.Get();
    } else if (loader && loader->GetFrame()) {
      context = loader->GetFrame()->GetDocument()->ExecutingWindow();
    }
    String stack_id =
        RequestDebugHeaderScope::CaptureStackIdForCurrentLocation(context);
    if (!stack_id.IsNull()) {
      request.SetDevToolsStackId(stack_id);
    }
  }
}

void InspectorNetworkAgent::WillSendRequest(
    uint64_t identifier,
    DocumentLoader* loader,
    const KURL& fetch_context_url,
    const ResourceRequest& request,
    const ResourceResponse& redirect_response,
    const FetchInitiatorInfo& initiator_info,
    ResourceType resource_type,
    RenderBlockingBehavior render_blocking_behavior) {
  // Ignore the request initiated internally.
  if (initiator_info.name == fetch_initiator_type_names::kInternal)
    return;

  InspectorPageAgent::ResourceType type =
      InspectorPageAgent::ToResourceType(resource_type);

  WillSendRequestInternal(identifier, loader, fetch_context_url, request,
                          redirect_response, initiator_info, type);
}

void InspectorNetworkAgent::MarkResourceAsCached(DocumentLoader* loader,
                                                 uint64_t identifier) {
  GetFrontend()->requestServedFromCache(
      IdentifiersFactory::RequestId(loader, identifier));
}

void InspectorNetworkAgent::DidReceiveResourceResponse(
    uint64_t identifier,
    DocumentLoader* loader,
    const ResourceResponse& response,
    const Resource* cached_resource) {
  String request_id = IdentifiersFactory::RequestId(loader, identifier);
  bool is_not_modified = response.HttpStatusCode() == 304;

  bool resource_is_empty = true;
  std::unique_ptr<protocol::Network::Response> resource_response =
      BuildObjectForResourceResponse(response, cached_resource,
                                     &resource_is_empty);

  InspectorPageAgent::ResourceType type =
      cached_resource
          ? InspectorPageAgent::ToResourceType(cached_resource->GetType())
          : InspectorPageAgent::kOtherResource;
  // Override with already discovered resource type.
  InspectorPageAgent::ResourceType saved_type =
      resources_data_->GetResourceType(request_id);
  if (saved_type == InspectorPageAgent::kScriptResource ||
      saved_type == InspectorPageAgent::kXHRResource ||
      saved_type == InspectorPageAgent::kDocumentResource ||
      saved_type == InspectorPageAgent::kFetchResource ||
      saved_type == InspectorPageAgent::kEventSourceResource ||
      saved_type == InspectorPageAgent::kPingResource) {
    type = saved_type;
  }

  // Resources are added to NetworkResourcesData as a WeakMember here and
  // removed in willDestroyResource() called in the prefinalizer of Resource.
  // Because NetworkResourceData retains weak references only, it
  // doesn't affect Resource lifetime.
  if (cached_resource)
    resources_data_->AddResource(request_id, cached_resource);
  String frame_id = loader && loader->GetFrame()
                        ? IdentifiersFactory::FrameId(loader->GetFrame())
                        : "";
  String loader_id = IdentifiersFactory::LoaderId(loader);
  resources_data_->ResponseReceived(request_id, frame_id, response);
  resources_data_->SetResourceType(request_id, type);

  const base::Optional<ResourceResponse::SecurityDetails>&
      response_security_details = response.GetSecurityDetails();
  if (response_security_details.has_value()) {
    resources_data_->SetCertificate(request_id,
                                    response_security_details->certificate);
  }

  if (IsNavigation(loader, identifier))
    return;
  if (resource_response && !resource_is_empty) {
    Maybe<String> maybe_frame_id;
    if (!frame_id.IsEmpty())
      maybe_frame_id = frame_id;
    GetFrontend()->responseReceived(
        request_id, loader_id,
        base::TimeTicks::Now().since_origin().InSecondsF(),
        InspectorPageAgent::ResourceTypeJson(type),
        std::move(resource_response), std::move(maybe_frame_id));
  }
  // If we revalidated the resource and got Not modified, send content length
  // following didReceiveResponse as there will be no calls to didReceiveData
  // from the network stack.
  if (is_not_modified && cached_resource && cached_resource->EncodedSize()) {
    DidReceiveData(identifier, loader, nullptr,
                   static_cast<int>(cached_resource->EncodedSize()));
  }
}

static bool IsErrorStatusCode(int status_code) {
  return status_code >= 400;
}

void InspectorNetworkAgent::DidReceiveData(uint64_t identifier,
                                           DocumentLoader* loader,
                                           const char* data,
                                           uint64_t data_length) {
  String request_id = IdentifiersFactory::RequestId(loader, identifier);

  if (data) {
    NetworkResourcesData::ResourceData const* resource_data =
        resources_data_->Data(request_id);
    if (resource_data && !resource_data->HasContent() &&
        (!resource_data->CachedResource() ||
         resource_data->CachedResource()->GetDataBufferingPolicy() ==
             kDoNotBufferData ||
         IsErrorStatusCode(resource_data->HttpStatusCode())))
      resources_data_->MaybeAddResourceData(request_id, data, data_length);
  }

  GetFrontend()->dataReceived(
      request_id, base::TimeTicks::Now().since_origin().InSecondsF(),
      static_cast<int>(data_length),
      static_cast<int>(
          resources_data_->GetAndClearPendingEncodedDataLength(request_id)));
}

void InspectorNetworkAgent::DidReceiveBlob(uint64_t identifier,
                                           DocumentLoader* loader,
                                           scoped_refptr<BlobDataHandle> blob) {
  String request_id = IdentifiersFactory::RequestId(loader, identifier);
  resources_data_->BlobReceived(request_id, std::move(blob));
}

void InspectorNetworkAgent::DidReceiveEncodedDataLength(
    DocumentLoader* loader,
    uint64_t identifier,
    size_t encoded_data_length) {
  String request_id = IdentifiersFactory::RequestId(loader, identifier);
  resources_data_->AddPendingEncodedDataLength(request_id, encoded_data_length);
}

void InspectorNetworkAgent::DidFinishLoading(
    uint64_t identifier,
    DocumentLoader* loader,
    base::TimeTicks monotonic_finish_time,
    int64_t encoded_data_length,
    int64_t decoded_body_length,
    bool should_report_corb_blocking) {
  String request_id = IdentifiersFactory::RequestId(loader, identifier);
  NetworkResourcesData::ResourceData const* resource_data =
      resources_data_->Data(request_id);

  int pending_encoded_data_length = static_cast<int>(
      resources_data_->GetAndClearPendingEncodedDataLength(request_id));
  if (pending_encoded_data_length > 0) {
    GetFrontend()->dataReceived(
        request_id, base::TimeTicks::Now().since_origin().InSecondsF(), 0,
        pending_encoded_data_length);
  }

  if (resource_data && !resource_data->HasContent() &&
      (!resource_data->CachedResource() ||
       resource_data->CachedResource()->GetDataBufferingPolicy() ==
           kDoNotBufferData ||
       IsErrorStatusCode(resource_data->HttpStatusCode()))) {
    resources_data_->MaybeAddResourceData(request_id, "", 0);
  }

  resources_data_->MaybeDecodeDataToContent(request_id);
  if (monotonic_finish_time.is_null())
    monotonic_finish_time = base::TimeTicks::Now();

  is_handling_sync_xhr_ = false;
  // TODO(npm): Use base::TimeTicks in Network.h.
  GetFrontend()->loadingFinished(
      request_id, monotonic_finish_time.since_origin().InSecondsF(),
      encoded_data_length, should_report_corb_blocking);
}

void InspectorNetworkAgent::DidReceiveCorsRedirectResponse(
    uint64_t identifier,
    DocumentLoader* loader,
    const ResourceResponse& response,
    Resource* resource) {
  // Update the response and finish loading
  DidReceiveResourceResponse(identifier, loader, response, resource);
  DidFinishLoading(identifier, loader, base::TimeTicks(),
                   WebURLLoaderClient::kUnknownEncodedDataLength, 0, false);
}

void InspectorNetworkAgent::DidFailLoading(
    CoreProbeSink* sink,
    uint64_t identifier,
    DocumentLoader* loader,
    const ResourceError& error,
    const base::UnguessableToken& devtools_frame_or_worker_token) {
  String request_id = IdentifiersFactory::RequestId(loader, identifier);

  // A Trust Token redemption can be served from cache if a valid
  // Signed-Redemption-Record is present. In this case the request is aborted
  // with a special error code. Sementically, the request did succeed, so that
  // is what we report to the frontend.
  if (error.IsTrustTokenCacheHit()) {
    GetFrontend()->requestServedFromCache(request_id);
    GetFrontend()->loadingFinished(
        request_id, base::TimeTicks::Now().since_origin().InSecondsF(), 0);
    return;
  }

  bool canceled = error.IsCancellation();
  base::Optional<ResourceRequestBlockedReason> resource_request_blocked_reason =
      error.GetResourceRequestBlockedReason();
  protocol::Maybe<String> blocked_reason;
  if (resource_request_blocked_reason) {
    blocked_reason = BuildBlockedReason(*resource_request_blocked_reason);
  }
  auto cors_error_status = error.CorsErrorStatus();
  protocol::Maybe<protocol::Network::CorsErrorStatus>
      protocol_cors_error_status;
  if (cors_error_status) {
    protocol_cors_error_status = BuildCorsErrorStatus(*cors_error_status);
  }
  is_handling_sync_xhr_ = false;
  GetFrontend()->loadingFailed(
      request_id, base::TimeTicks::Now().since_origin().InSecondsF(),
      InspectorPageAgent::ResourceTypeJson(
          resources_data_->GetResourceType(request_id)),
      error.LocalizedDescription(), canceled, std::move(blocked_reason),
      std::move(protocol_cors_error_status));
}

void InspectorNetworkAgent::ScriptImported(uint64_t identifier,
                                           const String& source_string) {
  resources_data_->SetResourceContent(
      IdentifiersFactory::SubresourceRequestId(identifier), source_string);
}

void InspectorNetworkAgent::DidReceiveScriptResponse(uint64_t identifier) {
  resources_data_->SetResourceType(
      IdentifiersFactory::SubresourceRequestId(identifier),
      InspectorPageAgent::kScriptResource);
}

// static
bool InspectorNetworkAgent::IsNavigation(DocumentLoader* loader,
                                         uint64_t identifier) {
  return loader && loader->MainResourceIdentifier() == identifier;
}

void InspectorNetworkAgent::WillLoadXHR(ExecutionContext* execution_context,
                                        const AtomicString& method,
                                        const KURL& url,
                                        bool async,
                                        const HTTPHeaderMap& headers,
                                        bool include_credentials) {
  DCHECK(!pending_request_type_);
  pending_xhr_replay_data_ = MakeGarbageCollected<XHRReplayData>(
      execution_context, method, UrlWithoutFragment(url), async,
      include_credentials);
  for (const auto& header : headers)
    pending_xhr_replay_data_->AddHeader(header.key, header.value);
  DCHECK(!is_handling_sync_xhr_);
  if (!async)
    is_handling_sync_xhr_ = true;
}

void InspectorNetworkAgent::DidFinishXHR(XMLHttpRequest* xhr) {
  replay_xhrs_.erase(xhr);
}

void InspectorNetworkAgent::WillSendEventSourceRequest() {
  DCHECK(!pending_request_type_);
  pending_request_type_ = InspectorPageAgent::kEventSourceResource;
}

void InspectorNetworkAgent::WillDispatchEventSourceEvent(
    uint64_t identifier,
    const AtomicString& event_name,
    const AtomicString& event_id,
    const String& data) {
  GetFrontend()->eventSourceMessageReceived(
      IdentifiersFactory::SubresourceRequestId(identifier),
      base::TimeTicks::Now().since_origin().InSecondsF(),
      event_name.GetString(), event_id.GetString(), data);
}

std::unique_ptr<protocol::Network::Initiator>
InspectorNetworkAgent::BuildInitiatorObject(
    Document* document,
    const FetchInitiatorInfo& initiator_info,
    int max_async_depth) {
  if (initiator_info.is_imported_module && !initiator_info.referrer.IsEmpty()) {
    std::unique_ptr<protocol::Network::Initiator> initiator_object =
        protocol::Network::Initiator::create()
            .setType(protocol::Network::Initiator::TypeEnum::Script)
            .build();
    initiator_object->setUrl(initiator_info.referrer);
    initiator_object->setLineNumber(
        initiator_info.position.line_.ZeroBasedInt());
    initiator_object->setColumnNumber(
        initiator_info.position.column_.ZeroBasedInt());
    return initiator_object;
  }

  bool was_requested_by_stylesheet =
      initiator_info.name == fetch_initiator_type_names::kCSS ||
      initiator_info.name == fetch_initiator_type_names::kUacss;
  if (was_requested_by_stylesheet && !initiator_info.referrer.IsEmpty()) {
    std::unique_ptr<protocol::Network::Initiator> initiator_object =
        protocol::Network::Initiator::create()
            .setType(protocol::Network::Initiator::TypeEnum::Parser)
            .build();
    initiator_object->setUrl(initiator_info.referrer);
    return initiator_object;
  }

  // We skip stack checking for stylesheet-initiated requests as it may
  // represent the cause of a style recalculation rather than the actual
  // resources themselves. See crbug.com/918196.
  if (!was_requested_by_stylesheet) {
    std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
        current_stack_trace =
            SourceLocation::Capture(document ? document->GetExecutionContext()
                                             : nullptr)
                ->BuildInspectorObject(max_async_depth);
    if (current_stack_trace) {
      std::unique_ptr<protocol::Network::Initiator> initiator_object =
          protocol::Network::Initiator::create()
              .setType(protocol::Network::Initiator::TypeEnum::Script)
              .build();
      initiator_object->setStack(std::move(current_stack_trace));
      return initiator_object;
    }
  }

  while (document && !document->GetScriptableDocumentParser())
    document = document->LocalOwner() ? document->LocalOwner()->ownerDocument()
                                      : nullptr;
  if (document && document->GetScriptableDocumentParser()) {
    std::unique_ptr<protocol::Network::Initiator> initiator_object =
        protocol::Network::Initiator::create()
            .setType(protocol::Network::Initiator::TypeEnum::Parser)
            .build();
    initiator_object->setUrl(UrlWithoutFragment(document->Url()).GetString());
    if (TextPosition::BelowRangePosition() != initiator_info.position) {
      initiator_object->setLineNumber(
          initiator_info.position.line_.ZeroBasedInt());
      initiator_object->setColumnNumber(
          initiator_info.position.column_.ZeroBasedInt());
    } else {
      initiator_object->setLineNumber(document->GetScriptableDocumentParser()
                                          ->GetTextPosition()
                                          .line_.ZeroBasedInt());
      initiator_object->setColumnNumber(document->GetScriptableDocumentParser()
                                            ->GetTextPosition()
                                            .column_.ZeroBasedInt());
    }
    return initiator_object;
  }

  return protocol::Network::Initiator::create()
      .setType(protocol::Network::Initiator::TypeEnum::Other)
      .build();
}

void InspectorNetworkAgent::DidCreateWebSocket(
    ExecutionContext* execution_context,
    uint64_t identifier,
    const KURL& request_url,
    const String&) {
  std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
      current_stack_trace =
          SourceLocation::Capture(execution_context)->BuildInspectorObject();
  if (!current_stack_trace) {
    GetFrontend()->webSocketCreated(
        IdentifiersFactory::SubresourceRequestId(identifier),
        UrlWithoutFragment(request_url).GetString());
    return;
  }

  std::unique_ptr<protocol::Network::Initiator> initiator_object =
      protocol::Network::Initiator::create()
          .setType(protocol::Network::Initiator::TypeEnum::Script)
          .build();
  initiator_object->setStack(std::move(current_stack_trace));
  GetFrontend()->webSocketCreated(
      IdentifiersFactory::SubresourceRequestId(identifier),
      UrlWithoutFragment(request_url).GetString(), std::move(initiator_object));
}

void InspectorNetworkAgent::WillSendWebSocketHandshakeRequest(
    ExecutionContext*,
    uint64_t identifier,
    network::mojom::blink::WebSocketHandshakeRequest* request) {
  DCHECK(request);
  HTTPHeaderMap headers;
  for (auto& header : request->headers)
    headers.Add(AtomicString(header->name), AtomicString(header->value));
  std::unique_ptr<protocol::Network::WebSocketRequest> request_object =
      protocol::Network::WebSocketRequest::create()
          .setHeaders(BuildObjectForHeaders(headers))
          .build();
  GetFrontend()->webSocketWillSendHandshakeRequest(
      IdentifiersFactory::SubresourceRequestId(identifier),
      base::TimeTicks::Now().since_origin().InSecondsF(),
      base::Time::Now().ToDoubleT(), std::move(request_object));
}

void InspectorNetworkAgent::DidReceiveWebSocketHandshakeResponse(
    ExecutionContext*,
    uint64_t identifier,
    network::mojom::blink::WebSocketHandshakeRequest* request,
    network::mojom::blink::WebSocketHandshakeResponse* response) {
  DCHECK(response);

  HTTPHeaderMap response_headers;
  for (auto& header : response->headers) {
    HTTPHeaderMap::AddResult add_result = response_headers.Add(
        AtomicString(header->name), AtomicString(header->value));
    if (!add_result.is_new_entry) {
      // Protocol expects the "\n" separated format.
      add_result.stored_value->value =
          add_result.stored_value->value + "\n" + header->value;
    }
  }

  std::unique_ptr<protocol::Network::WebSocketResponse> response_object =
      protocol::Network::WebSocketResponse::create()
          .setStatus(response->status_code)
          .setStatusText(response->status_text)
          .setHeaders(BuildObjectForHeaders(response_headers))
          .build();
  if (!response->headers_text.IsEmpty())
    response_object->setHeadersText(response->headers_text);

  if (request) {
    HTTPHeaderMap request_headers;
    for (auto& header : request->headers) {
      request_headers.Add(AtomicString(header->name),
                          AtomicString(header->value));
    }
    response_object->setRequestHeaders(BuildObjectForHeaders(request_headers));
    if (!request->headers_text.IsEmpty())
      response_object->setRequestHeadersText(request->headers_text);
  }

  GetFrontend()->webSocketHandshakeResponseReceived(
      IdentifiersFactory::SubresourceRequestId(identifier),
      base::TimeTicks::Now().since_origin().InSecondsF(),
      std::move(response_object));
}

void InspectorNetworkAgent::DidCloseWebSocket(ExecutionContext*,
                                              uint64_t identifier) {
  GetFrontend()->webSocketClosed(
      IdentifiersFactory::SubresourceRequestId(identifier),
      base::TimeTicks::Now().since_origin().InSecondsF());
}

void InspectorNetworkAgent::DidReceiveWebSocketMessage(
    uint64_t identifier,
    int op_code,
    bool masked,
    const Vector<base::span<const char>>& data) {
  size_t size = 0;
  for (const auto& span : data) {
    size += span.size();
  }
  Vector<char> flatten;
  flatten.ReserveCapacity(SafeCast<wtf_size_t>(size));
  for (const auto& span : data) {
    flatten.Append(span.data(), SafeCast<wtf_size_t>(span.size()));
  }
  GetFrontend()->webSocketFrameReceived(
      IdentifiersFactory::SubresourceRequestId(identifier),
      base::TimeTicks::Now().since_origin().InSecondsF(),
      WebSocketMessageToProtocol(op_code, masked, flatten.data(),
                                 flatten.size()));
}

void InspectorNetworkAgent::DidSendWebSocketMessage(uint64_t identifier,
                                                    int op_code,
                                                    bool masked,
                                                    const char* payload,
                                                    size_t payload_length) {
  GetFrontend()->webSocketFrameSent(
      IdentifiersFactory::RequestId(nullptr, identifier),
      base::TimeTicks::Now().since_origin().InSecondsF(),
      WebSocketMessageToProtocol(op_code, masked, payload, payload_length));
}

void InspectorNetworkAgent::DidReceiveWebSocketMessageError(
    uint64_t identifier,
    const String& error_message) {
  GetFrontend()->webSocketFrameError(
      IdentifiersFactory::RequestId(nullptr, identifier),
      base::TimeTicks::Now().since_origin().InSecondsF(), error_message);
}

void InspectorNetworkAgent::WebTransportCreated(
    ExecutionContext* execution_context,
    uint64_t transport_id,
    const KURL& request_url) {
  std::unique_ptr<v8_inspector::protocol::Runtime::API::StackTrace>
      current_stack_trace =
          SourceLocation::Capture(execution_context)->BuildInspectorObject();
  if (!current_stack_trace) {
    GetFrontend()->webTransportCreated(
        IdentifiersFactory::SubresourceRequestId(transport_id),
        UrlWithoutFragment(request_url).GetString(),
        base::TimeTicks::Now().since_origin().InSecondsF());
    return;
  }

  std::unique_ptr<protocol::Network::Initiator> initiator_object =
      protocol::Network::Initiator::create()
          .setType(protocol::Network::Initiator::TypeEnum::Script)
          .build();
  initiator_object->setStack(std::move(current_stack_trace));
  GetFrontend()->webTransportCreated(
      IdentifiersFactory::SubresourceRequestId(transport_id),
      UrlWithoutFragment(request_url).GetString(),
      base::TimeTicks::Now().since_origin().InSecondsF(),
      std::move(initiator_object));
}

void InspectorNetworkAgent::WebTransportConnectionEstablished(
    uint64_t transport_id) {
  GetFrontend()->webTransportConnectionEstablished(
      IdentifiersFactory::SubresourceRequestId(transport_id),
      base::TimeTicks::Now().since_origin().InSecondsF());
}

void InspectorNetworkAgent::WebTransportClosed(uint64_t transport_id) {
  GetFrontend()->webTransportClosed(
      IdentifiersFactory::SubresourceRequestId(transport_id),
      base::TimeTicks::Now().since_origin().InSecondsF());
}

Response InspectorNetworkAgent::enable(Maybe<int> total_buffer_size,
                                       Maybe<int> resource_buffer_size,
                                       Maybe<int> max_post_data_size) {
  total_buffer_size_.Set(total_buffer_size.fromMaybe(kDefaultTotalBufferSize));
  resource_buffer_size_.Set(
      resource_buffer_size.fromMaybe(kDefaultResourceBufferSize));
  max_post_data_size_.Set(max_post_data_size.fromMaybe(0));
  Enable();
  return Response::Success();
}

void InspectorNetworkAgent::Enable() {
  if (!GetFrontend())
    return;
  enabled_.Set(true);
  resources_data_->SetResourcesDataSizeLimits(total_buffer_size_.Get(),
                                              resource_buffer_size_.Get());
  instrumenting_agents_->AddInspectorNetworkAgent(this);
}

Response InspectorNetworkAgent::disable() {
  DCHECK(!pending_request_type_);
  if (IsMainThread())
    GetNetworkStateNotifier().ClearOverride();
  instrumenting_agents_->RemoveInspectorNetworkAgent(this);
  agent_state_.ClearAllFields();
  resources_data_->Clear();
  return Response::Success();
}

Response InspectorNetworkAgent::setExtraHTTPHeaders(
    std::unique_ptr<protocol::Network::Headers> headers) {
  extra_request_headers_.Clear();
  std::unique_ptr<protocol::DictionaryValue> in = headers->toValue();
  for (size_t i = 0; i < in->size(); ++i) {
    const auto& entry = in->at(i);
    String value;
    if (entry.second && entry.second->asString(&value))
      extra_request_headers_.Set(entry.first, value);
  }
  return Response::Success();
}

Response InspectorNetworkAgent::setAttachDebugStack(bool enabled) {
  if (enabled && !enabled_.Get())
    return Response::InvalidParams("Domain must be enabled");
  attach_debug_stack_enabled_.Set(enabled);
  return Response::Success();
}

bool InspectorNetworkAgent::CanGetResponseBodyBlob(const String& request_id) {
  NetworkResourcesData::ResourceData const* resource_data =
      resources_data_->Data(request_id);
  BlobDataHandle* blob =
      resource_data ? resource_data->DownloadedFileBlob() : nullptr;
  if (!blob)
    return false;
  if (worker_global_scope_)
    return true;
  LocalFrame* frame = IdentifiersFactory::FrameById(inspected_frames_,
                                                    resource_data->FrameId());
  return frame && frame->GetDocument();
}

void InspectorNetworkAgent::GetResponseBodyBlob(
    const String& request_id,
    std::unique_ptr<GetResponseBodyCallback> callback) {
  NetworkResourcesData::ResourceData const* resource_data =
      resources_data_->Data(request_id);
  BlobDataHandle* blob = resource_data->DownloadedFileBlob();
  ExecutionContext* context = GetTargetExecutionContext();
  if (!context) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  InspectorFileReaderLoaderClient* client = new InspectorFileReaderLoaderClient(
      blob, context->GetTaskRunner(TaskType::kFileReading),
      WTF::Bind(ResponseBodyFileReaderLoaderDone, resource_data->MimeType(),
                resource_data->TextEncodingName(), std::move(callback)));
  client->Start();
}

void InspectorNetworkAgent::getResponseBody(
    const String& request_id,
    std::unique_ptr<GetResponseBodyCallback> callback) {
  if (CanGetResponseBodyBlob(request_id)) {
    GetResponseBodyBlob(request_id, std::move(callback));
    return;
  }

  String content;
  bool base64_encoded;
  Response response = GetResponseBody(request_id, &content, &base64_encoded);
  if (response.IsSuccess()) {
    callback->sendSuccess(content, base64_encoded);
  } else {
    callback->sendFailure(response);
  }
}

Response InspectorNetworkAgent::setBlockedURLs(
    std::unique_ptr<protocol::Array<String>> urls) {
  blocked_urls_.Clear();
  for (const String& url : *urls)
    blocked_urls_.Set(url, true);
  return Response::Success();
}

Response InspectorNetworkAgent::replayXHR(const String& request_id) {
  String actual_request_id = request_id;

  XHRReplayData* xhr_replay_data = resources_data_->XhrReplayData(request_id);
  auto* data = resources_data_->Data(request_id);
  if (!xhr_replay_data || !data)
    return Response::ServerError("Given id does not correspond to XHR");

  ExecutionContext* execution_context = xhr_replay_data->GetExecutionContext();
  if (!execution_context || execution_context->IsContextDestroyed()) {
    resources_data_->SetXHRReplayData(request_id, nullptr);
    return Response::ServerError("Document is already detached");
  }

  XMLHttpRequest* xhr = XMLHttpRequest::Create(execution_context);

  execution_context->RemoveURLFromMemoryCache(xhr_replay_data->Url());

  xhr->open(xhr_replay_data->Method(), xhr_replay_data->Url(),
            xhr_replay_data->Async(), IGNORE_EXCEPTION_FOR_TESTING);
  if (xhr_replay_data->IncludeCredentials())
    xhr->setWithCredentials(true, IGNORE_EXCEPTION_FOR_TESTING);
  for (const auto& header : xhr_replay_data->Headers()) {
    xhr->setRequestHeader(header.key, header.value,
                          IGNORE_EXCEPTION_FOR_TESTING);
  }
  xhr->SendForInspectorXHRReplay(data ? data->PostData() : nullptr,
                                 IGNORE_EXCEPTION_FOR_TESTING);

  replay_xhrs_.insert(xhr);
  return Response::Success();
}

Response InspectorNetworkAgent::canClearBrowserCache(bool* result) {
  *result = true;
  return Response::Success();
}

Response InspectorNetworkAgent::canClearBrowserCookies(bool* result) {
  *result = true;
  return Response::Success();
}

Response InspectorNetworkAgent::emulateNetworkConditions(
    bool offline,
    double latency,
    double download_throughput,
    double upload_throughput,
    Maybe<String> connection_type) {
  WebConnectionType type = kWebConnectionTypeUnknown;
  if (connection_type.isJust()) {
    type = ToWebConnectionType(connection_type.fromJust());
    if (type == kWebConnectionTypeUnknown)
      return Response::ServerError("Unknown connection type");
  }

  if (worker_global_scope_) {
    if (worker_global_scope_->IsServiceWorkerGlobalScope() ||
        worker_global_scope_->IsSharedWorkerGlobalScope()) {
      // In service workers and shared workers, we don't inspect the main thread
      // so we must post a task there to make it possible to use
      // NetworkStateNotifier.
      PostCrossThreadTask(
          *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
          CrossThreadBindOnce(SetNetworkStateOverride, offline, latency,
                              download_throughput, upload_throughput, type));
      return Response::Success();
    }
    return Response::ServerError("Not supported");
  }

  SetNetworkStateOverride(offline, latency, download_throughput,
                          upload_throughput, type);

  return Response::Success();
}

Response InspectorNetworkAgent::setCacheDisabled(bool cache_disabled) {
  // TODO(ananta)
  // We should extract network cache state into a global entity which can be
  // queried from FrameLoader and other places.
  cache_disabled_.Set(cache_disabled);
  if (cache_disabled && IsMainThread())
    GetMemoryCache()->EvictResources();
  return Response::Success();
}

Response InspectorNetworkAgent::setBypassServiceWorker(bool bypass) {
  bypass_service_worker_.Set(bypass);
  return Response::Success();
}

Response InspectorNetworkAgent::setDataSizeLimitsForTest(int max_total,
                                                         int max_resource) {
  resources_data_->SetResourcesDataSizeLimits(max_total, max_resource);
  return Response::Success();
}

Response InspectorNetworkAgent::getCertificate(
    const String& origin,
    std::unique_ptr<protocol::Array<String>>* certificate) {
  *certificate = std::make_unique<protocol::Array<String>>();
  scoped_refptr<const SecurityOrigin> security_origin =
      SecurityOrigin::CreateFromString(origin);
  for (auto& resource : resources_data_->Resources()) {
    scoped_refptr<const SecurityOrigin> resource_origin =
        SecurityOrigin::Create(resource->RequestedURL());
    if (resource_origin->IsSameOriginWith(security_origin.get()) &&
        resource->Certificate().size()) {
      for (auto& cert : resource->Certificate()) {
        (*certificate)
            ->emplace_back(
                Base64Encode(base::as_bytes(base::make_span(cert.Latin1()))));
      }
      return Response::Success();
    }
  }
  return Response::Success();
}

void InspectorNetworkAgent::DidCommitLoad(LocalFrame* frame,
                                          DocumentLoader* loader) {
  DCHECK(IsMainThread());
  if (loader->GetFrame() != inspected_frames_->Root())
    return;

  if (cache_disabled_.Get())
    GetMemoryCache()->EvictResources();

  resources_data_->Clear(IdentifiersFactory::LoaderId(loader));
}

void InspectorNetworkAgent::FrameScheduledNavigation(LocalFrame* frame,
                                                     const KURL&,
                                                     base::TimeDelta,
                                                     ClientNavigationReason) {
  // For navigations, we limit async stack trace to depth 1 to avoid the
  // base::Value depth limits with Mojo serialization / parsing.
  // See http://crbug.com/809996.
  frame_navigation_initiator_map_.Set(
      IdentifiersFactory::FrameId(frame),
      BuildInitiatorObject(frame->GetDocument(), FetchInitiatorInfo(),
                           /*max_async_depth=*/1));
}

void InspectorNetworkAgent::FrameClearedScheduledNavigation(LocalFrame* frame) {
  frame_navigation_initiator_map_.erase(IdentifiersFactory::FrameId(frame));
}

Response InspectorNetworkAgent::GetResponseBody(const String& request_id,
                                                String* content,
                                                bool* base64_encoded) {
  NetworkResourcesData::ResourceData const* resource_data =
      resources_data_->Data(request_id);
  if (!resource_data) {
    return Response::ServerError("No resource with given identifier found");
  }

  if (resource_data->HasContent()) {
    *content = resource_data->Content();
    *base64_encoded = resource_data->Base64Encoded();
    return Response::Success();
  }

  if (resource_data->IsContentEvicted()) {
    return Response::ServerError(
        "Request content was evicted from inspector cache");
  }

  if (resource_data->Buffer() && !resource_data->TextEncodingName().IsNull()) {
    bool success = InspectorPageAgent::SharedBufferContent(
        resource_data->Buffer(), resource_data->MimeType(),
        resource_data->TextEncodingName(), content, base64_encoded);
    DCHECK(success);
    return Response::Success();
  }

  if (resource_data->CachedResource() &&
      InspectorPageAgent::CachedResourceContent(resource_data->CachedResource(),
                                                content, base64_encoded)) {
    return Response::Success();
  }

  return Response::ServerError(
      "No data found for resource with given identifier");
}

Response InspectorNetworkAgent::searchInResponseBody(
    const String& request_id,
    const String& query,
    Maybe<bool> case_sensitive,
    Maybe<bool> is_regex,
    std::unique_ptr<
        protocol::Array<v8_inspector::protocol::Debugger::API::SearchMatch>>*
        matches) {
  String content;
  bool base64_encoded;
  Response response = GetResponseBody(request_id, &content, &base64_encoded);
  if (!response.IsSuccess())
    return response;

  auto results = v8_session_->searchInTextByLines(
      ToV8InspectorStringView(content), ToV8InspectorStringView(query),
      case_sensitive.fromMaybe(false), is_regex.fromMaybe(false));
  *matches = std::make_unique<
      protocol::Array<v8_inspector::protocol::Debugger::API::SearchMatch>>(
      std::move(results));
  return Response::Success();
}

bool InspectorNetworkAgent::FetchResourceContent(Document* document,
                                                 const KURL& url,
                                                 String* content,
                                                 bool* base64_encoded) {
  DCHECK(document);
  DCHECK(IsMainThread());
  // First try to fetch content from the cached resource.
  Resource* cached_resource = document->Fetcher()->CachedResource(url);
  if (!cached_resource) {
    cached_resource = GetMemoryCache()->ResourceForURL(
        url, document->Fetcher()->GetCacheIdentifier(url));
  }
  if (cached_resource && InspectorPageAgent::CachedResourceContent(
                             cached_resource, content, base64_encoded))
    return true;

  // Then fall back to resource data.
  for (auto& resource : resources_data_->Resources()) {
    if (resource->RequestedURL() == url) {
      *content = resource->Content();
      *base64_encoded = resource->Base64Encoded();
      return true;
    }
  }
  return false;
}

String InspectorNetworkAgent::NavigationInitiatorInfo(LocalFrame* frame) {
  if (!enabled_.Get())
    return String();
  auto it =
      frame_navigation_initiator_map_.find(IdentifiersFactory::FrameId(frame));
  std::vector<uint8_t> cbor;
  if (it != frame_navigation_initiator_map_.end()) {
    it->value->AppendSerialized(&cbor);
  } else {
    // For navigations, we limit async stack trace to depth 1 to avoid the
    // base::Value depth limits with Mojo serialization / parsing.
    // See http://crbug.com/809996.
    BuildInitiatorObject(frame->GetDocument(), FetchInitiatorInfo(),
                         /*max_async_depth=*/1)
        ->AppendSerialized(&cbor);
  }
  std::vector<uint8_t> json;
  ConvertCBORToJSON(SpanFrom(cbor), &json);
  return String(reinterpret_cast<const char*>(json.data()), json.size());
}

InspectorNetworkAgent::InspectorNetworkAgent(
    InspectedFrames* inspected_frames,
    WorkerGlobalScope* worker_global_scope,
    v8_inspector::V8InspectorSession* v8_session)
    : inspected_frames_(inspected_frames),
      worker_global_scope_(worker_global_scope),
      v8_session_(v8_session),
      resources_data_(MakeGarbageCollected<NetworkResourcesData>(
          kDefaultTotalBufferSize,
          kDefaultResourceBufferSize)),
      devtools_token_(worker_global_scope_
                          ? worker_global_scope_->GetParentDevToolsToken()
                          : inspected_frames->Root()->GetDevToolsFrameToken()),
      enabled_(&agent_state_, /*default_value=*/false),
      cache_disabled_(&agent_state_, /*default_value=*/false),
      bypass_service_worker_(&agent_state_, /*default_value=*/false),
      blocked_urls_(&agent_state_, /*default_value=*/false),
      extra_request_headers_(&agent_state_, /*default_value=*/WTF::String()),
      attach_debug_stack_enabled_(&agent_state_, /*default_value=*/false),
      total_buffer_size_(&agent_state_,
                         /*default_value=*/kDefaultTotalBufferSize),
      resource_buffer_size_(&agent_state_,
                            /*default_value=*/kDefaultResourceBufferSize),
      max_post_data_size_(&agent_state_, /*default_value=*/0) {
  DCHECK((IsMainThread() && !worker_global_scope_) ||
         (!IsMainThread() && worker_global_scope_));
}

void InspectorNetworkAgent::ShouldForceCorsPreflight(bool* result) {
  if (cache_disabled_.Get())
    *result = true;
}

void InspectorNetworkAgent::getRequestPostData(
    const String& request_id,
    std::unique_ptr<GetRequestPostDataCallback> callback) {
  NetworkResourcesData::ResourceData const* resource_data =
      resources_data_->Data(request_id);
  if (!resource_data) {
    callback->sendFailure(
        Response::ServerError("No resource with given id was found"));
    return;
  }
  scoped_refptr<EncodedFormData> post_data = resource_data->PostData();
  if (!post_data || post_data->IsEmpty()) {
    callback->sendFailure(
        Response::ServerError("No post data available for the request"));
    return;
  }
  ExecutionContext* context = GetTargetExecutionContext();
  if (!context) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  scoped_refptr<InspectorPostBodyParser> parser =
      base::MakeRefCounted<InspectorPostBodyParser>(
          std::move(callback), context->GetTaskRunner(TaskType::kFileReading));
  // TODO(crbug.com/810554): Extend protocol to fetch body parts separately
  parser->Parse(post_data.get());
}

ExecutionContext* InspectorNetworkAgent::GetTargetExecutionContext() const {
  if (worker_global_scope_)
    return worker_global_scope_;
  DCHECK(inspected_frames_);
  return inspected_frames_->Root()->DomWindow();
}

void InspectorNetworkAgent::IsCacheDisabled(bool* is_cache_disabled) const {
  if (cache_disabled_.Get())
    *is_cache_disabled = true;
}

}  // namespace blink
