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