1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading
6 
7 #ifndef CONTENT_RENDERER_LOADER_RESOURCE_DISPATCHER_H_
8 #define CONTENT_RENDERER_LOADER_RESOURCE_DISPATCHER_H_
9 
10 #include <stdint.h>
11 
12 #include <map>
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include "base/macros.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/time/time.h"
21 #include "content/common/content_export.h"
22 #include "mojo/public/cpp/system/data_pipe.h"
23 #include "net/base/host_port_pair.h"
24 #include "net/base/net_errors.h"
25 #include "net/base/request_priority.h"
26 #include "net/traffic_annotation/network_traffic_annotation.h"
27 #include "services/network/public/cpp/shared_url_loader_factory.h"
28 #include "services/network/public/mojom/fetch_api.mojom-forward.h"
29 #include "services/network/public/mojom/url_loader.mojom-forward.h"
30 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
31 #include "third_party/blink/public/common/loader/previews_state.h"
32 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
33 #include "third_party/blink/public/mojom/blob/blob_registry.mojom-forward.h"
34 #include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-forward.h"
35 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
36 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
37 #include "third_party/blink/public/platform/web_url_loader.h"
38 #include "third_party/blink/public/platform/web_url_request.h"
39 #include "url/gurl.h"
40 
41 namespace base {
42 class WaitableEvent;
43 }
44 
45 namespace blink {
46 class ResourceLoadInfoNotifierWrapper;
47 class ThrottlingURLLoader;
48 struct SyncLoadResponse;
49 }
50 
51 namespace net {
52 struct RedirectInfo;
53 }
54 
55 namespace network {
56 struct ResourceRequest;
57 struct URLLoaderCompletionStatus;
58 namespace mojom {
59 class URLLoaderFactory;
60 }
61 }
62 
63 namespace content {
64 class RequestPeer;
65 class ResourceDispatcherDelegate;
66 class URLLoaderClientImpl;
67 
68 // This class serves as a communication interface to the ResourceDispatcherHost
69 // in the browser process. It can be used from any child process.
70 // Virtual methods are for tests.
71 class CONTENT_EXPORT ResourceDispatcher {
72  public:
73   // Generates ids for requests initiated by child processes unique to the
74   // particular process, counted up from 0 (browser initiated requests count
75   // down from -2).
76   //
77   // Public to be used by URLLoaderFactory and/or URLLoader implementations with
78   // the need to perform additional requests besides the main request, e.g.,
79   // CORS preflight requests.
80   static int MakeRequestID();
81 
82   ResourceDispatcher();
83   virtual ~ResourceDispatcher();
84 
85   // Call this method to load the resource synchronously (i.e., in one shot).
86   // This is an alternative to the StartAsync method. Be warned that this method
87   // will block the calling thread until the resource is fully downloaded or an
88   // error occurs. It could block the calling thread for a long time, so only
89   // use this if you really need it!  There is also no way for the caller to
90   // interrupt this method. Errors are reported via the status field of the
91   // response parameter.
92   //
93   // |routing_id| is used to associated the bridge with a frame's network
94   // context.
95   // |timeout| is used to abort the sync request on timeouts. TimeDelta::Max()
96   // is interpreted as no-timeout.
97   // If |download_to_blob_registry| is not null, it is used to redirect the
98   // download to a blob.
99   virtual void StartSync(
100       std::unique_ptr<network::ResourceRequest> request,
101       int routing_id,
102       const net::NetworkTrafficAnnotationTag& traffic_annotation,
103       uint32_t loader_options,
104       blink::SyncLoadResponse* response,
105       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
106       std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
107       base::TimeDelta timeout,
108       mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry,
109       std::unique_ptr<RequestPeer> peer,
110       std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
111           resource_load_info_notifier_wrapper);
112 
113   // Call this method to initiate the request. If this method succeeds, then
114   // the peer's methods will be called asynchronously to report various events.
115   // Returns the request id. |url_loader_factory| must be non-null.
116   //
117   // |routing_id| is used to associated the bridge with a frame's network
118   // context.
119   //
120   // You need to pass a non-null |loading_task_runner| to specify task queue to
121   // execute loading tasks on.
122   virtual int StartAsync(
123       std::unique_ptr<network::ResourceRequest> request,
124       int routing_id,
125       scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
126       const net::NetworkTrafficAnnotationTag& traffic_annotation,
127       uint32_t loader_options,
128       std::unique_ptr<RequestPeer> peer,
129       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
130       std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles,
131       std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
132           resource_load_info_notifier_wrapper);
133 
134   // Removes a request from the |pending_requests_| list, returning true if the
135   // request was found and removed.
136   virtual bool RemovePendingRequest(
137       int request_id,
138       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
139 
140   // Cancels a request in the |pending_requests_| list.  The request will be
141   // removed from the dispatcher as well.
142   virtual void Cancel(int request_id,
143                       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
144 
145   // Toggles the is_deferred attribute for the specified request.
146   virtual void SetDefersLoading(int request_id,
147                                 blink::WebURLLoader::DeferType value);
148 
149   // Indicates the priority of the specified request changed.
150   void DidChangePriority(int request_id,
151                          net::RequestPriority new_priority,
152                          int intra_priority_value);
153 
154   // This does not take ownership of the delegate. It is expected that the
155   // delegate have a longer lifetime than the ResourceDispatcher.
set_delegate(ResourceDispatcherDelegate * delegate)156   void set_delegate(ResourceDispatcherDelegate* delegate) {
157     delegate_ = delegate;
158   }
159 
GetWeakPtr()160   base::WeakPtr<ResourceDispatcher> GetWeakPtr() {
161     return weak_factory_.GetWeakPtr();
162   }
163 
164   void OnTransferSizeUpdated(int request_id, int32_t transfer_size_diff);
165 
166   void EvictFromBackForwardCache(blink::mojom::RendererEvictionReason reason,
167                                  int request_id);
168 
169   // Sets the CORS exempt header list for sanity checking.
170   void SetCorsExemptHeaderList(const std::vector<std::string>& list);
171 
cors_exempt_header_list()172   std::vector<std::string> cors_exempt_header_list() const {
173     return cors_exempt_header_list_;
174   }
175 
176   // This is used only when |this| is created for a worker thread.
177   // Sets |terminate_sync_load_event_| which will be signaled from the main
178   // thread when the worker thread is being terminated so that the sync requests
179   // requested on the worker thread can be aborted.
set_terminate_sync_load_event(base::WaitableEvent * terminate_sync_load_event)180   void set_terminate_sync_load_event(
181       base::WaitableEvent* terminate_sync_load_event) {
182     terminate_sync_load_event_ = terminate_sync_load_event;
183   }
184 
185  private:
186   friend class URLLoaderClientImpl;
187   friend class URLResponseBodyConsumer;
188   friend class ResourceDispatcherTest;
189 
190   struct PendingRequestInfo {
191     PendingRequestInfo(std::unique_ptr<RequestPeer> peer,
192                        network::mojom::RequestDestination request_destination,
193                        int render_frame_id,
194                        const GURL& request_url,
195                        std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
196                            resource_load_info_notifier_wrapper);
197 
198     ~PendingRequestInfo();
199 
200     std::unique_ptr<RequestPeer> peer;
201     network::mojom::RequestDestination request_destination;
202     int render_frame_id;
203     blink::WebURLLoader::DeferType is_deferred =
204         blink::WebURLLoader::DeferType::kNotDeferred;
205     // Original requested url.
206     GURL url;
207     // The url, method and referrer of the latest response even in case of
208     // redirection.
209     GURL response_url;
210     bool has_pending_redirect = false;
211     base::TimeTicks local_request_start;
212     base::TimeTicks local_response_start;
213     base::TimeTicks remote_request_start;
214     net::LoadTimingInfo load_timing_info;
215     bool should_follow_redirect = true;
216     bool redirect_requires_loader_restart = false;
217     // Network error code the request completed with, or net::ERR_IO_PENDING if
218     // it's not completed. Used both to distinguish completion from
219     // cancellation, and to log histograms.
220     int net_error = net::ERR_IO_PENDING;
221     blink::PreviewsState previews_state =
222         blink::PreviewsTypes::PREVIEWS_UNSPECIFIED;
223 
224     // For mojo loading.
225     std::unique_ptr<blink::ThrottlingURLLoader> url_loader;
226     std::unique_ptr<URLLoaderClientImpl> url_loader_client;
227 
228     // The Client Hints headers that need to be removed from a redirect.
229     std::vector<std::string> removed_headers;
230 
231     // Used to notify the loading stats.
232     std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
233         resource_load_info_notifier_wrapper;
234   };
235   using PendingRequestMap = std::map<int, std::unique_ptr<PendingRequestInfo>>;
236 
237   // Helper to lookup the info based on the request_id.
238   // May return NULL if the request as been canceled from the client side.
239   PendingRequestInfo* GetPendingRequestInfo(int request_id);
240 
241   // Follows redirect, if any, for the given request.
242   void FollowPendingRedirect(PendingRequestInfo* request_info);
243 
244   // Message response handlers, called by the message handler for this process.
245   void OnUploadProgress(int request_id, int64_t position, int64_t size);
246   void OnReceivedResponse(int request_id, network::mojom::URLResponseHeadPtr);
247   void OnReceivedCachedMetadata(int request_id, mojo_base::BigBuffer data);
248   void OnReceivedRedirect(
249       int request_id,
250       const net::RedirectInfo& redirect_info,
251       network::mojom::URLResponseHeadPtr response_head,
252       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
253   void OnStartLoadingResponseBody(int request_id,
254                                   mojo::ScopedDataPipeConsumerHandle body);
255   void OnRequestComplete(int request_id,
256                          const network::URLLoaderCompletionStatus& status);
257 
258   void ToLocalURLResponseHead(
259       const PendingRequestInfo& request_info,
260       network::mojom::URLResponseHead& response_head) const;
261 
262   // All pending requests issued to the host
263   PendingRequestMap pending_requests_;
264 
265   ResourceDispatcherDelegate* delegate_;
266 
267   base::WaitableEvent* terminate_sync_load_event_ = nullptr;
268 
269   std::vector<std::string> cors_exempt_header_list_;
270 
271   base::WeakPtrFactory<ResourceDispatcher> weak_factory_{this};
272 
273   DISALLOW_COPY_AND_ASSIGN(ResourceDispatcher);
274 };
275 
276 }  // namespace content
277 
278 #endif  // CONTENT_RENDERER_LOADER_RESOURCE_DISPATCHER_H_
279