1 // Copyright 2017 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 #ifndef CONTENT_RENDERER_LOADER_SYNC_LOAD_CONTEXT_H_ 6 #define CONTENT_RENDERER_LOADER_SYNC_LOAD_CONTEXT_H_ 7 8 #include "base/macros.h" 9 #include "base/optional.h" 10 #include "base/single_thread_task_runner.h" 11 #include "base/synchronization/waitable_event_watcher.h" 12 #include "base/timer/timer.h" 13 #include "content/common/content_export.h" 14 #include "content/public/renderer/request_peer.h" 15 #include "content/renderer/loader/resource_dispatcher.h" 16 #include "mojo/public/cpp/bindings/remote.h" 17 #include "mojo/public/cpp/system/data_pipe.h" 18 #include "mojo/public/cpp/system/simple_watcher.h" 19 #include "net/traffic_annotation/network_traffic_annotation.h" 20 #include "services/network/public/cpp/shared_url_loader_factory.h" 21 #include "third_party/blink/public/mojom/blob/blob_registry.mojom.h" 22 23 namespace base { 24 class WaitableEvent; 25 } 26 27 namespace network { 28 struct ResourceRequest; 29 } 30 31 namespace blink { 32 class ResourceLoadInfoNotifierWrapper; 33 class URLLoaderThrottle; 34 struct SyncLoadResponse; 35 } 36 37 namespace content { 38 39 // This class owns the context necessary to perform an asynchronous request 40 // while the main thread is blocked so that it appears to be synchronous. 41 // There are a couple of modes to load a request: 42 // 1) kDataPipe; body is received on a data pipe passed on 43 // OnStartLoadingResponseBody(), and the body is set to response_.data. 44 // 2) kBlob: body is received on a data pipe passed on 45 // OnStartLoadingResponseBody(), and wraps the data pipe with a 46 // SerializedBlobPtr. 47 class CONTENT_EXPORT SyncLoadContext : public RequestPeer { 48 public: 49 // Begins a new asynchronous request on whatever sequence this method is 50 // called on. |completed_event| will be signalled when the request is complete 51 // and |response| will be populated with the response data. |abort_event| 52 // will be signalled from the main thread to abort the sync request on a 53 // worker thread when the worker thread is being terminated. 54 // The pointer whose address is `context_for_redirect` is held by the caller 55 // that is blocked on this method, so it will remain valid until the operation 56 // completes. If there are redirects, `context_for_redirect` will point to the 57 // callee context. 58 // If |download_to_blob_registry| is not null, it is used to 59 // redirect the download to a blob, with the resulting blob populated in 60 // |response|. 61 static void StartAsyncWithWaitableEvent( 62 std::unique_ptr<network::ResourceRequest> request, 63 int routing_id, 64 scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner, 65 const net::NetworkTrafficAnnotationTag& traffic_annotation, 66 uint32_t loader_options, 67 std::unique_ptr<network::PendingSharedURLLoaderFactory> 68 pending_url_loader_factory, 69 std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles, 70 blink::SyncLoadResponse* response, 71 SyncLoadContext** context_for_redirect, 72 base::WaitableEvent* completed_event, 73 base::WaitableEvent* abort_event, 74 base::TimeDelta timeout, 75 mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, 76 const std::vector<std::string>& cors_exempt_header_list, 77 std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper> 78 resource_load_info_notifier_wrapper); 79 80 ~SyncLoadContext() override; 81 82 void FollowRedirect(); 83 void CancelRedirect(); 84 85 private: 86 friend class SyncLoadContextTest; 87 88 SyncLoadContext( 89 network::ResourceRequest* request, 90 std::unique_ptr<network::PendingSharedURLLoaderFactory> 91 url_loader_factory, 92 blink::SyncLoadResponse* response, 93 SyncLoadContext** context_for_redirect, 94 base::WaitableEvent* completed_event, 95 base::WaitableEvent* abort_event, 96 base::TimeDelta timeout, 97 mojo::PendingRemote<blink::mojom::BlobRegistry> download_to_blob_registry, 98 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 99 const std::vector<std::string>& cors_exempt_header_list); 100 // RequestPeer implementation: 101 void OnUploadProgress(uint64_t position, uint64_t size) override; 102 bool OnReceivedRedirect(const net::RedirectInfo& redirect_info, 103 network::mojom::URLResponseHeadPtr head, 104 std::vector<std::string>*) override; 105 void OnReceivedResponse(network::mojom::URLResponseHeadPtr head) override; 106 void OnStartLoadingResponseBody( 107 mojo::ScopedDataPipeConsumerHandle body) override; 108 void OnTransferSizeUpdated(int transfer_size_diff) override; 109 void OnCompletedRequest( 110 const network::URLLoaderCompletionStatus& status) override; 111 void EvictFromBackForwardCache(blink::mojom::RendererEvictionReason) override; 112 113 void OnFinishCreatingBlob(blink::mojom::SerializedBlobPtr blob); 114 115 void OnBodyReadable(MojoResult, const mojo::HandleSignalsState&); 116 117 void OnAbort(base::WaitableEvent* event); 118 void OnTimeout(); 119 120 void CompleteRequest(); 121 bool Completed() const; 122 123 // This raw pointer will remain valid for the lifetime of this object because 124 // it remains on the stack until |event_| is signaled. 125 // Set to null after CompleteRequest() is called. 126 blink::SyncLoadResponse* response_; 127 128 // This raw pointer will be set to `this` when receiving redirects on 129 // independent thread and set to nullptr in `FollowRedirect()` or 130 // `CancelRedirect()` on the same thread after `redirect_or_response_event_` 131 // is signaled, which protects it against race condition. 132 SyncLoadContext** context_for_redirect_; 133 134 enum class Mode { kInitial, kDataPipe, kBlob }; 135 Mode mode_ = Mode::kInitial; 136 137 // Used when Mode::kDataPipe. 138 mojo::ScopedDataPipeConsumerHandle body_handle_; 139 mojo::SimpleWatcher body_watcher_; 140 141 // State necessary to run a request on an independent thread. 142 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; 143 std::unique_ptr<ResourceDispatcher> resource_dispatcher_; 144 145 // State for downloading to a blob. 146 mojo::Remote<blink::mojom::BlobRegistry> download_to_blob_registry_; 147 bool blob_response_started_ = false; 148 bool blob_finished_ = false; 149 bool request_completed_ = false; 150 151 int request_id_; 152 153 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 154 155 class SignalHelper; 156 std::unique_ptr<SignalHelper> signals_; 157 158 DISALLOW_COPY_AND_ASSIGN(SyncLoadContext); 159 }; 160 161 } // namespace content 162 163 #endif // CONTENT_RENDERER_LOADER_SYNC_LOAD_CONTEXT_H_ 164