• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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