blob: 9af0909ea904b1bfb6506cf235f7798e858df208 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_THROTTLE_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_THROTTLE_H_
#include <string>
#include <vector>
#include "base/strings/string_piece.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/request_priority.h"
#include "services/network/public/mojom/url_loader.mojom-forward.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "third_party/blink/public/common/common_export.h"
class GURL;
namespace net {
class HttpRequestHeaders;
struct RedirectInfo;
}
namespace network {
struct ResourceRequest;
struct URLLoaderCompletionStatus;
} // namespace network
namespace blink {
// A URLLoaderThrottle gets notified at various points during the process of
// loading a resource. At each stage, it has the opportunity to defer the
// resource load.
//
// Note that while a single throttle deferring a load at any given step will
// block the load from progressing further until a subsequent Delegate::Resume()
// call is made, it does NOT prevent subsequent throttles from processing the
// same step of the request if multiple throttles are affecting the load.
class BLINK_COMMON_EXPORT URLLoaderThrottle {
public:
// An interface for the throttle implementation to resume (when deferred) or
// cancel the resource load. Please note that these methods could be called
// in-band (i.e., inside URLLoaderThrottle notification methods such as
// WillStartRequest), or out-of-band.
//
// It is guaranteed that throttles calling these methods won't be destroyed
// synchronously.
class BLINK_COMMON_EXPORT Delegate {
public:
// Cancels the resource load with the specified error code and an optional,
// application-defined reason description.
virtual void CancelWithError(int error_code,
base::StringPiece custom_reason = "") = 0;
// Resumes the deferred resource load. It is a no-op if the resource load is
// not deferred or has already been canceled.
virtual void Resume() = 0;
virtual void SetPriority(net::RequestPriority priority);
// Updates the request headers which is deferred to be sent. This method
// needs to be called when the response is deferred on WillStartRequest or
// WillRedirectRequest and before calling Delegate::Resume().
virtual void UpdateDeferredRequestHeaders(
const net::HttpRequestHeaders& modified_request_headers,
const net::HttpRequestHeaders& modified_cors_exempt_request_headers);
// Updates the response head which is deferred to be sent. This method needs
// to be called when the response is deferred on
// URLLoaderThrottle::WillProcessResponse() and before calling
// Delegate::Resume().
virtual void UpdateDeferredResponseHead(
network::mojom::URLResponseHeadPtr new_response_head);
// Pauses/resumes reading response body if the resource is fetched from
// network.
virtual void PauseReadingBodyFromNet();
virtual void ResumeReadingBodyFromNet();
// Replaces the URLLoader and URLLoaderClient endpoints held by the
// ThrottlingURLLoader instance.
virtual void InterceptResponse(
mojo::PendingRemote<network::mojom::URLLoader> new_loader,
mojo::PendingReceiver<network::mojom::URLLoaderClient>
new_client_receiver,
mojo::PendingRemote<network::mojom::URLLoader>* original_loader,
mojo::PendingReceiver<network::mojom::URLLoaderClient>*
original_client_receiver);
// Restarts the URL loader using |additional_load_flags|.
//
// Restarting is only valid while executing within
// BeforeWillProcessResponse(), or during its deferred handling (before
// having called Resume()).
//
// When a URL loader is restarted, throttles will NOT have their
// WillStartRequest() method called again - that is only called for the
// initial request start.
//
// If multiple throttles call RestartWithFlags() then the URL loader will be
// restarted using a combined value of all of the |additional_load_flags|.
virtual void RestartWithFlags(int additional_load_flags);
// Restarts the URL loader using |additional_load_flags| and the unmodified
// URL if it was changed in WillStartRequest().
//
// If called on an URL loader that did not modify the URL in
// WillStartRequest(), this method has the same outcome as
// RestartWithFlags().
//
// Restarting is only valid while executing within
// BeforeWillProcessResponse(), or during its deferred handling (before
// having called Resume()).
//
// When a URL loader is restarted, throttles will NOT have their
// WillStartRequest() method called again - that is only called for the
// initial request start.
//
// If multiple throttles call RestartWithFlags() and
// RestartWithURLResetAndFlags() then the URL loader will be restarted
// using a combined value of all of the |additional_load_flags|.
virtual void RestartWithURLResetAndFlags(int additional_load_flags);
// Restarts the URL loader immediately using |additional_load_flags| and the
// unmodified URL if it was changed in WillStartRequest().
//
// Restarting is only valid before BeforeWillProcessResponse() is called.
virtual void RestartWithURLResetAndFlagsNow(int additional_load_flags);
// Restarts the URL loader immediately after adding the provided headers to
// the new request.
virtual void RestartWithModifiedHeadersNow(
const net::HttpRequestHeaders& modified_headers);
protected:
virtual ~Delegate();
};
virtual ~URLLoaderThrottle();
// Detaches this object from the current sequence in preparation for a move to
// a different sequence. If this method is called it must be before any of the
// Will* methods below and may only be called once.
virtual void DetachFromCurrentSequence();
// Called exactly once before the resource request is started.
//
// |request| needs to be modified before the callback returns (i.e.
// asynchronously touching the pointer in defer case is not valid)
// When |request->url| is modified it will make an internal redirect, which
// might have some side-effects: drop upload streams data might be dropped,
// redirect count may be reached.
//
// Implementations should be aware that throttling can happen multiple times
// for the same |request|, even after one instance of the same throttle
// subclass already modified the request. This happens, e.g., when a service
// worker initially elects to handle a request but then later falls back to
// network, so new throttles are created for another URLLoaderFactory to
// handle the request.
virtual void WillStartRequest(network::ResourceRequest* request, bool* defer);
// Called when the request was redirected. |redirect_info| contains the
// redirect responses's HTTP status code and some information about the new
// request that will be sent if the redirect is followed, including the new
// URL and new method.
//
// Request headers added to |to_be_removed_request_headers| will be removed
// before the redirect is followed. Headers added to
// |modified_request_headers| and |modified_cors_exempt_request_headers| will
// be merged into the existing request headers and cors_exempt_headers before
// the redirect is followed.
//
// If |redirect_info->new_url| is modified by a throttle, the request will be
// redirected to the new URL. Only one throttle can update this and it must
// have the same origin as |redirect_info->new_url|. See the comments for
// WillStartRequest on possible side-effects.
virtual void WillRedirectRequest(
net::RedirectInfo* redirect_info,
const network::mojom::URLResponseHead& response_head,
bool* defer,
std::vector<std::string>* to_be_removed_request_headers,
net::HttpRequestHeaders* modified_request_headers,
net::HttpRequestHeaders* modified_cors_exempt_request_headers);
// Called when the response headers and meta data are available.
// TODO(776312): Migrate this URL to URLResponseHead.
virtual void WillProcessResponse(
const GURL& response_url,
network::mojom::URLResponseHead* response_head,
bool* defer);
// Called prior WillProcessResponse() to allow throttles to restart the URL
// load by calling delegate_->RestartWithFlags().
//
// Having this method separate from WillProcessResponse() ensures that
// WillProcessResponse() is called at most once even in the presence of
// restarts.
virtual void BeforeWillProcessResponse(
const GURL& response_url,
const network::mojom::URLResponseHead& response_head,
bool* defer);
// Called if there is a non-OK net::Error in the completion status.
virtual void WillOnCompleteWithError(
const network::URLLoaderCompletionStatus& status,
bool* defer);
// Must return true if the throttle may make cross-scheme redirects
// (which is usually considered unsafe, so allowed only if the setting
// is made very explicitly).
virtual bool makes_unsafe_redirect();
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
protected:
URLLoaderThrottle();
Delegate* delegate_ = nullptr;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_THROTTLE_H_