diff options
Diffstat (limited to 'libcef/browser/net_service/proxy_url_loader_factory.h')
-rw-r--r-- | libcef/browser/net_service/proxy_url_loader_factory.h | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/libcef/browser/net_service/proxy_url_loader_factory.h b/libcef/browser/net_service/proxy_url_loader_factory.h new file mode 100644 index 00000000..b9fdeae6 --- /dev/null +++ b/libcef/browser/net_service/proxy_url_loader_factory.h @@ -0,0 +1,229 @@ +// Copyright (c) 2019 The Chromium Embedded Framework Authors. Portions +// Copyright (c) 2018 The Chromium Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_PROXY_URL_LOADER_FACTORY_H_ +#define CEF_LIBCEF_BROWSER_NET_SERVICE_PROXY_URL_LOADER_FACTORY_H_ + +#include "libcef/browser/net_service/stream_reader_url_loader.h" + +#include "base/containers/unique_ptr_adapters.h" +#include "base/functional/callback.h" +#include "base/hash/hash.h" +#include "base/strings/string_piece.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/web_contents.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace content { +class ResourceContext; +} + +namespace net_service { + +class InterceptedRequest; +class ResourceContextData; + +// Implement this interface to to evaluate requests. All methods are called on +// the IO thread, and all callbacks must be executed on the IO thread. +class InterceptedRequestHandler { + public: + InterceptedRequestHandler(); + + InterceptedRequestHandler(const InterceptedRequestHandler&) = delete; + InterceptedRequestHandler& operator=(const InterceptedRequestHandler&) = + delete; + + virtual ~InterceptedRequestHandler(); + + // Optionally modify |request| and execute |callback| to continue the request. + // Set |intercept_request| to false if the request will not be intercepted. + // Set |intercept_only| to true if the loader should not proceed unless the + // request is intercepted. Keep a reference to |cancel_callback| and execute + // at any time to cancel the request. + using OnBeforeRequestResultCallback = + base::OnceCallback<void(bool /* intercept_request */, + bool /* intercept_only */)>; + using CancelRequestCallback = base::OnceCallback<void(int /* error_code */)>; + virtual void OnBeforeRequest(int32_t request_id, + network::ResourceRequest* request, + bool request_was_redirected, + OnBeforeRequestResultCallback callback, + CancelRequestCallback cancel_callback); + + // Optionally modify |request| and execute |callback| after determining if the + // request hould be intercepted. + using ShouldInterceptRequestResultCallback = + base::OnceCallback<void(std::unique_ptr<ResourceResponse>)>; + virtual void ShouldInterceptRequest( + int32_t request_id, + network::ResourceRequest* request, + ShouldInterceptRequestResultCallback callback); + + // Called to evaluate and optionally modify request headers. |request| is the + // current request information. |redirect_url| will be non-empty if this + // method is called in response to a redirect. The |modified_headers| and + // |removed_headers| may be modified. If non-empty the |modified_headers| + // values will be merged first, and then any |removed_headers| values will be + // removed. This comparison is case sensitive. + virtual void ProcessRequestHeaders( + int32_t request_id, + const network::ResourceRequest& request, + const GURL& redirect_url, + net::HttpRequestHeaders* modified_headers, + std::vector<std::string>* removed_headers) {} + + // Called to evaluate and optionally modify response headers. |request| is the + // current request information. |redirect_url| will be non-empty if this + // method is called in response to a redirect. Even though |head| is const the + // |head.headers| value is non-const and any changes will be passed to the + // client. + virtual void ProcessResponseHeaders(int32_t request_id, + const network::ResourceRequest& request, + const GURL& redirect_url, + net::HttpResponseHeaders* headers) {} + + enum class ResponseMode { + // Continue the request. + CONTINUE, + // Restart the request. + RESTART, + // Cancel the request. + CANCEL + }; + + // Called on response. |request| is the current request information. + // |redirect_info| will be non-empty for redirect responses. + // Optionally modify |request| and execute the callback as appropriate. + using OnRequestResponseResultCallback = base::OnceCallback<void( + ResponseMode /* response_mode */, + scoped_refptr<net::HttpResponseHeaders> /* override_headers */, + const GURL& /* redirect_url */)>; + virtual void OnRequestResponse( + int32_t request_id, + network::ResourceRequest* request, + net::HttpResponseHeaders* headers, + absl::optional<net::RedirectInfo> redirect_info, + OnRequestResponseResultCallback callback); + + // Called to optionally filter the response body. + virtual mojo::ScopedDataPipeConsumerHandle OnFilterResponseBody( + int32_t request_id, + const network::ResourceRequest& request, + mojo::ScopedDataPipeConsumerHandle body); + + // Called on completion notification from the loader (successful or not). + virtual void OnRequestComplete( + int32_t request_id, + const network::ResourceRequest& request, + const network::URLLoaderCompletionStatus& status) {} + + // Called on error. + virtual void OnRequestError(int32_t request_id, + const network::ResourceRequest& request, + int error_code, + bool safebrowsing_hit) {} +}; + +// URL Loader Factory that supports request/response interception, processing +// and callback invocation. +// Based on android_webview/browser/network_service/ +// aw_proxying_url_loader_factory.cc +class ProxyURLLoaderFactory + : public network::mojom::URLLoaderFactory, + public network::mojom::TrustedURLLoaderHeaderClient { + public: + ProxyURLLoaderFactory(const ProxyURLLoaderFactory&) = delete; + ProxyURLLoaderFactory& operator=(const ProxyURLLoaderFactory&) = delete; + + ~ProxyURLLoaderFactory() override; + + // Create a proxy object on the UI thread. + static void CreateProxy( + content::BrowserContext* browser_context, + mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver, + mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>* + header_client, + std::unique_ptr<InterceptedRequestHandler> request_handler); + + // Create a proxy object on the IO thread. + static void CreateProxy( + content::WebContents::Getter web_contents_getter, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_request, + std::unique_ptr<InterceptedRequestHandler> request_handler); + + // mojom::URLLoaderFactory methods: + void CreateLoaderAndStart( + mojo::PendingReceiver<network::mojom::URLLoader> receiver, + int32_t request_id, + uint32_t options, + const network::ResourceRequest& request, + mojo::PendingRemote<network::mojom::URLLoaderClient> client, + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) + override; + void Clone( + mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory) override; + + // network::mojom::TrustedURLLoaderHeaderClient: + void OnLoaderCreated( + int32_t request_id, + mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) + override; + void OnLoaderForCorsPreflightCreated( + const network::ResourceRequest& request, + mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) + override; + + private: + friend class InterceptedRequest; + friend class ResourceContextData; + + ProxyURLLoaderFactory( + mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver, + mojo::PendingRemote<network::mojom::URLLoaderFactory> + target_factory_remote, + mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient> + header_client_receiver, + std::unique_ptr<InterceptedRequestHandler> request_handler); + + static void CreateOnIOThread( + mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver, + mojo::PendingRemote<network::mojom::URLLoaderFactory> + target_factory_remote, + mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient> + header_client_receiver, + content::ResourceContext* resource_context, + std::unique_ptr<InterceptedRequestHandler> request_handler); + + using DisconnectCallback = base::OnceCallback<void(ProxyURLLoaderFactory*)>; + void SetDisconnectCallback(DisconnectCallback on_disconnect); + + void OnTargetFactoryError(); + void OnProxyBindingError(); + void RemoveRequest(InterceptedRequest* request); + void MaybeDestroySelf(); + + mojo::ReceiverSet<network::mojom::URLLoaderFactory> proxy_receivers_; + mojo::Remote<network::mojom::URLLoaderFactory> target_factory_; + mojo::Receiver<network::mojom::TrustedURLLoaderHeaderClient> + url_loader_header_client_receiver_{this}; + + std::unique_ptr<InterceptedRequestHandler> request_handler_; + + bool destroyed_ = false; + DisconnectCallback on_disconnect_; + + // Map of request ID to request object. + std::map<int32_t, std::unique_ptr<InterceptedRequest>> requests_; + + base::WeakPtrFactory<ProxyURLLoaderFactory> weak_factory_; +}; + +} // namespace net_service + +#endif // CEF_LIBCEF_BROWSER_NET_SERVICE_PROXY_URL_LOADER_FACTORY_H_ |