// 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/callback.h" #include "base/containers/unique_ptr_adapters.h" #include "base/hash.h" #include "base/macros.h" #include "base/strings/string_piece.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_request_info.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" 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(); 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; using CancelRequestCallback = base::OnceCallback; virtual void OnBeforeRequest(const RequestId& 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)>; virtual void ShouldInterceptRequest( const RequestId& 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( const RequestId& id, const network::ResourceRequest& request, const GURL& redirect_url, net::HttpRequestHeaders* modified_headers, std::vector* 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( const RequestId& id, const network::ResourceRequest& request, const GURL& redirect_url, const network::ResourceResponseHead& head) {} 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 /* override_headers */, const GURL& /* redirect_url */)>; virtual void OnRequestResponse( const RequestId& id, network::ResourceRequest* request, const network::ResourceResponseHead& head, base::Optional redirect_info, OnRequestResponseResultCallback callback); // Called to optionally filter the response body. virtual mojo::ScopedDataPipeConsumerHandle OnFilterResponseBody( const RequestId& id, const network::ResourceRequest& request, mojo::ScopedDataPipeConsumerHandle body); // Called on completion notification from the loader (successful or not). virtual void OnRequestComplete( const RequestId& id, const network::ResourceRequest& request, const network::URLLoaderCompletionStatus& status) {} // Called on error. virtual void OnRequestError(const RequestId& id, const network::ResourceRequest& request, int error_code, bool safebrowsing_hit) {} private: DISALLOW_COPY_AND_ASSIGN(InterceptedRequestHandler); }; // 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() override; // Create a proxy object on the UI thread. static void CreateProxy( content::BrowserContext* browser_context, network::mojom::URLLoaderFactoryRequest* factory_request, network::mojom::TrustedURLLoaderHeaderClientPtrInfo* header_client, std::unique_ptr request_handler); // Create a proxy object on the IO thread. static ProxyURLLoaderFactory* CreateProxy( content::ResourceRequestInfo::WebContentsGetter web_contents_getter, network::mojom::URLLoaderFactoryRequest* factory_request, std::unique_ptr request_handler); // mojom::URLLoaderFactory methods: void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, int32_t routing_id, int32_t request_id, uint32_t options, const network::ResourceRequest& request, network::mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override; void Clone(network::mojom::URLLoaderFactoryRequest loader_request) override; // network::mojom::TrustedURLLoaderHeaderClient: void OnLoaderCreated( int32_t request_id, network::mojom::TrustedHeaderClientRequest request) override; private: friend class InterceptedRequest; friend class ResourceContextData; ProxyURLLoaderFactory( network::mojom::URLLoaderFactoryRequest loader_request, network::mojom::URLLoaderFactoryPtrInfo target_factory_info, network::mojom::TrustedURLLoaderHeaderClientRequest header_client_request, std::unique_ptr request_handler); static void CreateOnIOThread( network::mojom::URLLoaderFactoryRequest loader_request, network::mojom::URLLoaderFactoryPtrInfo target_factory_info, network::mojom::TrustedURLLoaderHeaderClientRequest header_client_request, content::ResourceContext* resource_context, std::unique_ptr request_handler); using DisconnectCallback = base::OnceCallback; void SetDisconnectCallback(DisconnectCallback on_disconnect); void OnTargetFactoryError(); void OnProxyBindingError(); void RemoveRequest(InterceptedRequest* request); void MaybeDestroySelf(); mojo::BindingSet proxy_bindings_; network::mojom::URLLoaderFactoryPtr target_factory_; mojo::Binding url_loader_header_client_binding_; std::unique_ptr request_handler_; DisconnectCallback on_disconnect_; // Map of request ID to request object. std::map> requests_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(ProxyURLLoaderFactory); }; } // namespace net_service #endif // CEF_LIBCEF_BROWSER_NET_SERVICE_PROXY_URL_LOADER_FACTORY_H_