1 // Copyright (c) 2019 The Chromium Embedded Framework Authors. Portions 2 // Copyright (c) 2018 The Chromium Authors. All rights reserved. Use of this 3 // source code is governed by a BSD-style license that can be found in the 4 // LICENSE file. 5 6 #ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_PROXY_URL_LOADER_FACTORY_H_ 7 #define CEF_LIBCEF_BROWSER_NET_SERVICE_PROXY_URL_LOADER_FACTORY_H_ 8 9 #include "libcef/browser/net_service/stream_reader_url_loader.h" 10 11 #include "base/callback.h" 12 #include "base/containers/unique_ptr_adapters.h" 13 #include "base/hash/hash.h" 14 #include "base/strings/string_piece.h" 15 #include "content/public/browser/content_browser_client.h" 16 #include "content/public/browser/web_contents.h" 17 #include "mojo/public/cpp/bindings/pending_receiver.h" 18 #include "mojo/public/cpp/bindings/receiver_set.h" 19 #include "services/network/public/mojom/network_context.mojom.h" 20 #include "services/network/public/mojom/url_loader_factory.mojom.h" 21 #include "third_party/abseil-cpp/absl/types/optional.h" 22 23 namespace content { 24 class ResourceContext; 25 } 26 27 namespace net_service { 28 29 class InterceptedRequest; 30 class ResourceContextData; 31 32 // Implement this interface to to evaluate requests. All methods are called on 33 // the IO thread, and all callbacks must be executed on the IO thread. 34 class InterceptedRequestHandler { 35 public: 36 InterceptedRequestHandler(); 37 38 InterceptedRequestHandler(const InterceptedRequestHandler&) = delete; 39 InterceptedRequestHandler& operator=(const InterceptedRequestHandler&) = 40 delete; 41 42 virtual ~InterceptedRequestHandler(); 43 44 // Optionally modify |request| and execute |callback| to continue the request. 45 // Set |intercept_request| to false if the request will not be intercepted. 46 // Set |intercept_only| to true if the loader should not proceed unless the 47 // request is intercepted. Keep a reference to |cancel_callback| and execute 48 // at any time to cancel the request. 49 using OnBeforeRequestResultCallback = 50 base::OnceCallback<void(bool /* intercept_request */, 51 bool /* intercept_only */)>; 52 using CancelRequestCallback = base::OnceCallback<void(int /* error_code */)>; 53 virtual void OnBeforeRequest(int32_t request_id, 54 network::ResourceRequest* request, 55 bool request_was_redirected, 56 OnBeforeRequestResultCallback callback, 57 CancelRequestCallback cancel_callback); 58 59 // Optionally modify |request| and execute |callback| after determining if the 60 // request hould be intercepted. 61 using ShouldInterceptRequestResultCallback = 62 base::OnceCallback<void(std::unique_ptr<ResourceResponse>)>; 63 virtual void ShouldInterceptRequest( 64 int32_t request_id, 65 network::ResourceRequest* request, 66 ShouldInterceptRequestResultCallback callback); 67 68 // Called to evaluate and optionally modify request headers. |request| is the 69 // current request information. |redirect_url| will be non-empty if this 70 // method is called in response to a redirect. The |modified_headers| and 71 // |removed_headers| may be modified. If non-empty the |modified_headers| 72 // values will be merged first, and then any |removed_headers| values will be 73 // removed. This comparison is case sensitive. ProcessRequestHeaders(int32_t request_id,const network::ResourceRequest & request,const GURL & redirect_url,net::HttpRequestHeaders * modified_headers,std::vector<std::string> * removed_headers)74 virtual void ProcessRequestHeaders( 75 int32_t request_id, 76 const network::ResourceRequest& request, 77 const GURL& redirect_url, 78 net::HttpRequestHeaders* modified_headers, 79 std::vector<std::string>* removed_headers) {} 80 81 // Called to evaluate and optionally modify response headers. |request| is the 82 // current request information. |redirect_url| will be non-empty if this 83 // method is called in response to a redirect. Even though |head| is const the 84 // |head.headers| value is non-const and any changes will be passed to the 85 // client. ProcessResponseHeaders(int32_t request_id,const network::ResourceRequest & request,const GURL & redirect_url,net::HttpResponseHeaders * headers)86 virtual void ProcessResponseHeaders(int32_t request_id, 87 const network::ResourceRequest& request, 88 const GURL& redirect_url, 89 net::HttpResponseHeaders* headers) {} 90 91 enum class ResponseMode { 92 // Continue the request. 93 CONTINUE, 94 // Restart the request. 95 RESTART, 96 // Cancel the request. 97 CANCEL 98 }; 99 100 // Called on response. |request| is the current request information. 101 // |redirect_info| will be non-empty for redirect responses. 102 // Optionally modify |request| and execute the callback as appropriate. 103 using OnRequestResponseResultCallback = base::OnceCallback<void( 104 ResponseMode /* response_mode */, 105 scoped_refptr<net::HttpResponseHeaders> /* override_headers */, 106 const GURL& /* redirect_url */)>; 107 virtual void OnRequestResponse( 108 int32_t request_id, 109 network::ResourceRequest* request, 110 net::HttpResponseHeaders* headers, 111 absl::optional<net::RedirectInfo> redirect_info, 112 OnRequestResponseResultCallback callback); 113 114 // Called to optionally filter the response body. 115 virtual mojo::ScopedDataPipeConsumerHandle OnFilterResponseBody( 116 int32_t request_id, 117 const network::ResourceRequest& request, 118 mojo::ScopedDataPipeConsumerHandle body); 119 120 // Called on completion notification from the loader (successful or not). OnRequestComplete(int32_t request_id,const network::ResourceRequest & request,const network::URLLoaderCompletionStatus & status)121 virtual void OnRequestComplete( 122 int32_t request_id, 123 const network::ResourceRequest& request, 124 const network::URLLoaderCompletionStatus& status) {} 125 126 // Called on error. OnRequestError(int32_t request_id,const network::ResourceRequest & request,int error_code,bool safebrowsing_hit)127 virtual void OnRequestError(int32_t request_id, 128 const network::ResourceRequest& request, 129 int error_code, 130 bool safebrowsing_hit) {} 131 }; 132 133 // URL Loader Factory that supports request/response interception, processing 134 // and callback invocation. 135 // Based on android_webview/browser/network_service/ 136 // aw_proxying_url_loader_factory.cc 137 class ProxyURLLoaderFactory 138 : public network::mojom::URLLoaderFactory, 139 public network::mojom::TrustedURLLoaderHeaderClient { 140 public: 141 ProxyURLLoaderFactory(const ProxyURLLoaderFactory&) = delete; 142 ProxyURLLoaderFactory& operator=(const ProxyURLLoaderFactory&) = delete; 143 144 ~ProxyURLLoaderFactory() override; 145 146 // Create a proxy object on the UI thread. 147 static void CreateProxy( 148 content::BrowserContext* browser_context, 149 mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver, 150 mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>* 151 header_client, 152 std::unique_ptr<InterceptedRequestHandler> request_handler); 153 154 // Create a proxy object on the IO thread. 155 static void CreateProxy( 156 content::WebContents::Getter web_contents_getter, 157 mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_request, 158 std::unique_ptr<InterceptedRequestHandler> request_handler); 159 160 // mojom::URLLoaderFactory methods: 161 void CreateLoaderAndStart( 162 mojo::PendingReceiver<network::mojom::URLLoader> receiver, 163 int32_t request_id, 164 uint32_t options, 165 const network::ResourceRequest& request, 166 mojo::PendingRemote<network::mojom::URLLoaderClient> client, 167 const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) 168 override; 169 void Clone( 170 mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory) override; 171 172 // network::mojom::TrustedURLLoaderHeaderClient: 173 void OnLoaderCreated( 174 int32_t request_id, 175 mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) 176 override; 177 void OnLoaderForCorsPreflightCreated( 178 const network::ResourceRequest& request, 179 mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) 180 override; 181 182 private: 183 friend class InterceptedRequest; 184 friend class ResourceContextData; 185 186 ProxyURLLoaderFactory( 187 mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver, 188 network::mojom::URLLoaderFactoryPtrInfo target_factory_info, 189 mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient> 190 header_client_receiver, 191 std::unique_ptr<InterceptedRequestHandler> request_handler); 192 193 static void CreateOnIOThread( 194 mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver, 195 network::mojom::URLLoaderFactoryPtrInfo target_factory_info, 196 mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient> 197 header_client_receiver, 198 content::ResourceContext* resource_context, 199 std::unique_ptr<InterceptedRequestHandler> request_handler); 200 201 using DisconnectCallback = base::OnceCallback<void(ProxyURLLoaderFactory*)>; 202 void SetDisconnectCallback(DisconnectCallback on_disconnect); 203 204 void OnTargetFactoryError(); 205 void OnProxyBindingError(); 206 void RemoveRequest(InterceptedRequest* request); 207 void MaybeDestroySelf(); 208 209 mojo::ReceiverSet<network::mojom::URLLoaderFactory> proxy_receivers_; 210 mojo::Remote<network::mojom::URLLoaderFactory> target_factory_; 211 mojo::Receiver<network::mojom::TrustedURLLoaderHeaderClient> 212 url_loader_header_client_receiver_{this}; 213 214 std::unique_ptr<InterceptedRequestHandler> request_handler_; 215 216 bool destroyed_ = false; 217 DisconnectCallback on_disconnect_; 218 219 // Map of request ID to request object. 220 std::map<int32_t, std::unique_ptr<InterceptedRequest>> requests_; 221 222 base::WeakPtrFactory<ProxyURLLoaderFactory> weak_factory_; 223 }; 224 225 } // namespace net_service 226 227 #endif // CEF_LIBCEF_BROWSER_NET_SERVICE_PROXY_URL_LOADER_FACTORY_H_ 228