mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			231 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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 <optional>
 | |
| #include <string_view>
 | |
| 
 | |
| #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 "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/cpp/url_loader_factory_builder.h"
 | |
| #include "services/network/public/mojom/network_context.mojom.h"
 | |
| #include "services/network/public/mojom/url_loader_factory.mojom.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,
 | |
|                                  std::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,
 | |
|       network::URLLoaderFactoryBuilder& factory_builder,
 | |
|       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_
 |