chromium/content/browser/devtools/devtools_url_loader_interceptor.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/342213636): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

#include "content/browser/devtools/devtools_url_loader_interceptor.h"

#include <memory>
#include <optional>
#include <string_view>

#include "base/barrier_closure.h"
#include "base/base64.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/no_destructor.h"
#include "base/strings/pattern.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/unguessable_token.h"
#include "content/browser/devtools/protocol/network.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/request_body_collector.h"
#include "content/browser/loader/download_utils_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_client.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
#include "net/base/load_flags.h"
#include "net/base/mime_sniffer.h"
#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_util.h"
#include "net/http/http_util.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/referrer_policy.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/header_util.h"
#include "services/network/public/cpp/record_ontransfersizeupdate_utils.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/early_hints.mojom.h"
#include "services/network/public/mojom/encoded_body_length.mojom-forward.h"
#include "services/network/public/mojom/encoded_body_length.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"

namespace content {

InterceptedRequestInfo::InterceptedRequestInfo() = default;

InterceptedRequestInfo::~InterceptedRequestInfo() = default;

DevToolsURLLoaderInterceptor::AuthChallengeResponse::AuthChallengeResponse(
    ResponseType response_type)
    :{}

DevToolsURLLoaderInterceptor::AuthChallengeResponse::AuthChallengeResponse(
    const std::u16string& username,
    const std::u16string& password)
    :{}

DevToolsURLLoaderInterceptor::FilterEntry::FilterEntry(
    const base::UnguessableToken& target_id,
    std::vector<Pattern> patterns,
    RequestInterceptedCallback callback)
    :{}

DevToolsURLLoaderInterceptor::FilterEntry::FilterEntry(FilterEntry&&) = default;
DevToolsURLLoaderInterceptor::FilterEntry::~FilterEntry() = default;

DevToolsURLLoaderInterceptor::Modifications::Modifications() = default;

DevToolsURLLoaderInterceptor::Modifications::Modifications(
    net::Error error_reason)
    :{}

DevToolsURLLoaderInterceptor::Modifications::Modifications(
    scoped_refptr<net::HttpResponseHeaders> response_headers,
    scoped_refptr<base::RefCountedMemory> response_body)
    :{}

DevToolsURLLoaderInterceptor::Modifications::Modifications(
    std::unique_ptr<AuthChallengeResponse> auth_challenge_response)
    :{}

DevToolsURLLoaderInterceptor::Modifications::Modifications(
    protocol::Maybe<std::string> modified_url,
    protocol::Maybe<std::string> modified_method,
    protocol::Maybe<protocol::Binary> modified_post_data,
    std::unique_ptr<HeadersVector> modified_headers,
    protocol::Maybe<bool> intercept_response)
    :{}

DevToolsURLLoaderInterceptor::Modifications::Modifications(
    std::optional<net::Error> error_reason,
    scoped_refptr<net::HttpResponseHeaders> response_headers,
    scoped_refptr<base::RefCountedMemory> response_body,
    size_t body_offset,
    protocol::Maybe<std::string> modified_url,
    protocol::Maybe<std::string> modified_method,
    protocol::Maybe<protocol::Binary> modified_post_data,
    std::unique_ptr<HeadersVector> modified_headers,
    std::unique_ptr<AuthChallengeResponse> auth_challenge_response)
    :{}

DevToolsURLLoaderInterceptor::Modifications::~Modifications() = default;

DevToolsURLLoaderInterceptor::Pattern::~Pattern() = default;

DevToolsURLLoaderInterceptor::Pattern::Pattern(const Pattern& other) = default;

DevToolsURLLoaderInterceptor::Pattern::Pattern(
    const std::string& url_pattern,
    base::flat_set<blink::mojom::ResourceType> resource_types,
    InterceptionStage interception_stage)
    :{}

bool DevToolsURLLoaderInterceptor::Pattern::Matches(
    const std::string& url,
    blink::mojom::ResourceType resource_type) const {}

struct CreateLoaderParameters {};

namespace {

RequestInterceptedCallback;
ContinueInterceptedRequestCallback;
GetResponseBodyCallback;
TakeResponseBodyPipeCallback;
Modifications;
InterceptionStage;
Response;
CredentialsMode;
FetchResponseType;

class BodyReader : public mojo::DataPipeDrainer::Client {};

void BodyReader::StartReading(mojo::ScopedDataPipeConsumerHandle body) {}

void BodyReader::OnDataComplete() {}

struct ResponseMetadata {};

void RemoveUnsafeRequestHeadersOnRedirect(net::HttpRequestHeaders& headers) {}

class HeadersOverride {};

}  // namespace

class InterceptionJob : public network::mojom::URLLoaderClient,
                        public network::mojom::URLLoader {};

void DevToolsURLLoaderInterceptor::CreateJob(
    const base::UnguessableToken& frame_token,
    int32_t process_id,
    bool is_download,
    const std::optional<std::string>& renderer_request_id,
    std::unique_ptr<CreateLoaderParameters> create_params,
    mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
    mojo::PendingRemote<network::mojom::URLLoaderClient> client,
    mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory,
    mojo::PendingRemote<network::mojom::CookieManager> cookie_manager) {}

DevToolsURLLoaderInterceptor::InterceptionStages
DevToolsURLLoaderInterceptor::GetInterceptionStages(
    const GURL& url,
    blink::mojom::ResourceType resource_type) const {}

class DevToolsURLLoaderFactoryProxy : public network::mojom::URLLoaderFactory {};

// This class owns itself and will delete self when any mojo
// connection is broken.
DevToolsURLLoaderFactoryProxy::DevToolsURLLoaderFactoryProxy(
    const base::UnguessableToken& frame_token,
    int32_t process_id,
    bool is_download,
    mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
    mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote,
    mojo::PendingRemote<network::mojom::CookieManager> cookie_manager,
    base::WeakPtr<DevToolsURLLoaderInterceptor> interceptor)
    :{}

DevToolsURLLoaderFactoryProxy::~DevToolsURLLoaderFactoryProxy() = default;

void DevToolsURLLoaderFactoryProxy::CreateLoaderAndStart(
    mojo::PendingReceiver<network::mojom::URLLoader> loader,
    int32_t request_id,
    uint32_t options,
    const network::ResourceRequest& request,
    mojo::PendingRemote<network::mojom::URLLoaderClient> client,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {}

void DevToolsURLLoaderFactoryProxy::Clone(
    mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {}

void DevToolsURLLoaderFactoryProxy::OnTargetFactoryError() {}

void DevToolsURLLoaderFactoryProxy::OnProxyBindingError() {}

// static
void DevToolsURLLoaderInterceptor::HandleAuthRequest(
    GlobalRequestID req_id,
    const net::AuthChallengeInfo& auth_info,
    HandleAuthRequestCallback callback) {}

DevToolsURLLoaderInterceptor::DevToolsURLLoaderInterceptor(
    RequestInterceptedCallback callback)
    :{}

DevToolsURLLoaderInterceptor::~DevToolsURLLoaderInterceptor() {}

void DevToolsURLLoaderInterceptor::SetPatterns(
    std::vector<DevToolsURLLoaderInterceptor::Pattern> patterns,
    bool handle_auth) {}

void DevToolsURLLoaderInterceptor::GetResponseBody(
    const std::string& interception_id,
    std::unique_ptr<GetResponseBodyCallback> callback) {}

void DevToolsURLLoaderInterceptor::TakeResponseBodyPipe(
    const std::string& interception_id,
    DevToolsURLLoaderInterceptor::TakeResponseBodyPipeCallback callback) {}

void DevToolsURLLoaderInterceptor::ContinueInterceptedRequest(
    const std::string& interception_id,
    std::unique_ptr<Modifications> modifications,
    std::unique_ptr<ContinueInterceptedRequestCallback> callback) {}

bool DevToolsURLLoaderInterceptor::CreateProxyForInterception(
    int process_id,
    StoragePartition* storage_partition,
    const base::UnguessableToken& frame_token,
    bool is_navigation,
    bool is_download,
    network::mojom::URLLoaderFactoryOverride* intercepting_factory) {}

InterceptionJob::InterceptionJob(
    DevToolsURLLoaderInterceptor* interceptor,
    const std::string& id,
    const base::UnguessableToken& frame_token,
    int process_id,
    const std::optional<std::string>& renderer_request_id,
    std::unique_ptr<CreateLoaderParameters> create_loader_params,
    bool is_download,
    mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
    mojo::PendingRemote<network::mojom::URLLoaderClient> client,
    mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory,
    mojo::PendingRemote<network::mojom::CookieManager> cookie_manager)
    :{}

bool InterceptionJob::StartJobAndMaybeNotify() {}

// FIXME(caseq): The logic in the three methods below is borrowed from
// CorsURLLoader as a matter of a quick and mergeable fix for crbug.com/1022173.
// This logic should be unified with CorsURLLoader.
network::mojom::FetchResponseType InterceptionJob::CalculateResponseTainting() {}

network::ResourceRequest InterceptionJob::GetResourceRequestForCookies() {}

void InterceptionJob::UpdateCORSFlag() {}

bool InterceptionJob::CanGetResponseBody(std::string* error_reason) {}

void InterceptionJob::GetResponseBody(
    std::unique_ptr<GetResponseBodyCallback> callback) {}

void InterceptionJob::TakeResponseBodyPipe(
    TakeResponseBodyPipeCallback callback) {}

void InterceptionJob::ContinueInterceptedRequest(
    std::unique_ptr<Modifications> modifications,
    std::unique_ptr<ContinueInterceptedRequestCallback> callback) {}

void InterceptionJob::Detach() {}

Response InterceptionJob::InnerContinueRequest(
    std::unique_ptr<Modifications> modifications) {}

void InterceptionJob::ProcessFollowRedirect(
    const net::HttpRequestHeaders& modified_cors_exempt_headers) {}

void InterceptionJob::ApplyModificationsToRequest(
    std::unique_ptr<Modifications> modifications) {}

void InterceptionJob::ProcessAuthResponse(
    const DevToolsURLLoaderInterceptor::AuthChallengeResponse& response) {}

Response InterceptionJob::ProcessResponseOverride(
    scoped_refptr<net::HttpResponseHeaders> headers,
    scoped_refptr<base::RefCountedMemory> body,
    size_t response_body_offset) {}

void InterceptionJob::ProcessSetCookies(const net::HttpResponseHeaders& headers,
                                        base::OnceClosure callback) {}

void InterceptionJob::ProcessRedirectByClient(const GURL& redirect_url) {}

void InterceptionJob::SendResponse(scoped_refptr<base::RefCountedMemory> body,
                                   size_t offset) {}

void InterceptionJob::ResponseBodyComplete() {}

void InterceptionJob::StartRequest() {}

void InterceptionJob::CancelRequest() {}

std::unique_ptr<InterceptedRequestInfo> InterceptionJob::BuildRequestInfo(
    const network::mojom::URLResponseHeadPtr& head) {}

void InterceptionJob::FetchCookies(base::OnceClosure callback) {}

void InterceptionJob::NotifyClient(
    std::unique_ptr<InterceptedRequestInfo> request_info) {}

void InterceptionJob::OnGotCookies(
    base::OnceClosure callback,
    const net::CookieAccessResultList& cookies_with_access_result,
    const net::CookieAccessResultList& excluded_cookies) {}

void InterceptionJob::OnGotRequestBodies(
    base::OnceClosure callback,
    std::vector<RequestBodyCollector::BodyEntry> bodies) {}

void InterceptionJob::CompleteNotifyingClient(
    std::unique_ptr<InterceptedRequestInfo> request_info) {}

void InterceptionJob::CompleteRequest(
    const network::URLLoaderCompletionStatus& status) {}

void InterceptionJob::Shutdown() {}

// URLLoader methods
void InterceptionJob::FollowRedirect(
    const std::vector<std::string>& removed_headers,
    const net::HttpRequestHeaders& modified_headers,
    const net::HttpRequestHeaders& modified_cors_exempt_headers,
    const std::optional<GURL>& new_url) {}

void InterceptionJob::SetPriority(net::RequestPriority priority,
                                  int32_t intra_priority_value) {}

void InterceptionJob::PauseReadingBodyFromNet() {}

void InterceptionJob::ResumeReadingBodyFromNet() {}

// URLLoaderClient methods
void InterceptionJob::OnReceiveEarlyHints(
    network::mojom::EarlyHintsPtr early_hints) {}

void InterceptionJob::OnReceiveResponse(
    network::mojom::URLResponseHeadPtr head,
    mojo::ScopedDataPipeConsumerHandle body,
    std::optional<mojo_base::BigBuffer> cached_metadata) {}

void InterceptionJob::OnReceiveRedirect(
    const net::RedirectInfo& redirect_info,
    network::mojom::URLResponseHeadPtr head) {}

void InterceptionJob::OnUploadProgress(int64_t current_position,
                                       int64_t total_size,
                                       OnUploadProgressCallback callback) {}

void InterceptionJob::OnTransferSizeUpdated(int32_t transfer_size_diff) {}

void InterceptionJob::StartLoadingResponseBody(
    mojo::ScopedDataPipeConsumerHandle body) {}

void InterceptionJob::OnComplete(
    const network::URLLoaderCompletionStatus& status) {}

void InterceptionJob::OnAuthRequest(
    const net::AuthChallengeInfo& auth_info,
    DevToolsURLLoaderInterceptor::HandleAuthRequestCallback callback) {}

}  // namespace content