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_STREAM_READER_URL_LOADER_H_ 7 #define CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_ 8 9 #include <map> 10 11 #include "base/callback.h" 12 #include "base/threading/thread_checker.h" 13 #include "mojo/public/cpp/bindings/remote.h" 14 #include "mojo/public/cpp/system/simple_watcher.h" 15 #include "net/http/http_byte_range.h" 16 #include "services/network/public/cpp/net_adapters.h" 17 #include "services/network/public/cpp/resource_request.h" 18 #include "services/network/public/mojom/network_context.mojom.h" 19 #include "services/network/public/mojom/url_loader.mojom.h" 20 #include "services/network/public/mojom/url_response_head.mojom.h" 21 22 namespace net_service { 23 24 class InputStreamReader; 25 26 // Abstract class representing an input stream. All methods are called in 27 // sequence on a worker thread, but not necessarily on the same thread. 28 class InputStream { 29 public: ~InputStream()30 virtual ~InputStream() {} 31 32 // Callback for asynchronous continuation of Skip(). If |bytes_skipped| > 0 33 // then either Skip() will be called again until the requested number of 34 // bytes have been skipped or the request will proceed. If |bytes_skipped| 35 // <= 0 the request will fail with net::ERR_REQUEST_RANGE_NOT_SATISFIABLE. 36 using SkipCallback = base::OnceCallback<void(int64_t /* bytes_skipped */)>; 37 38 // Skip over and discard |n| bytes of data from this input stream. If data 39 // is available immediately set |bytes_skipped| to the number of of bytes 40 // skipped and return true. To read the data at a later time set 41 // |bytes_skipped| to 0, return true and execute |callback| when the data is 42 // available. To indicate failure set |bytes_skipped| to < 0 (e.g. 43 // net::ERR_FAILED) and return false. 44 virtual bool Skip(int64_t n, 45 int64_t* bytes_skipped, 46 SkipCallback callback) = 0; 47 48 // Callback for asynchronous continuation of Read(). If |bytes_read| == 0 49 // the response will be considered complete. If |bytes_read| > 0 then Read() 50 // will be called again until the request is complete (based on either the 51 // result or the expected content length). If |bytes_read| < 0 then the 52 // request will fail and the |bytes_read| value will be treated as the error 53 // code. 54 using ReadCallback = base::OnceCallback<void(int /* bytes_read */)>; 55 56 // Read response data. If data is available immediately copy up to |length| 57 // bytes into |dest|, set |bytes_read| to the number of bytes copied, and 58 // return true. To read the data at a later time set |bytes_read| to 0, return 59 // true and execute |callback| when the data is available. To indicate 60 // response completion set |bytes_read| to 0 and return false. To indicate 61 // failure set |bytes_read| to < 0 (e.g. net::ERR_FAILED) and return false. 62 virtual bool Read(net::IOBuffer* dest, 63 int length, 64 int* bytes_read, 65 ReadCallback callback) = 0; 66 }; 67 68 // Abstract class for handling intercepted resource responses. All methods are 69 // called on the IO thread unless otherwise indicated. 70 class ResourceResponse { 71 public: ~ResourceResponse()72 virtual ~ResourceResponse() {} 73 74 // Callback for asynchronous continuation of Open(). If the InputStream is 75 // null the request will be canceled. 76 using OpenCallback = base::OnceCallback<void(std::unique_ptr<InputStream>)>; 77 78 // This method is called on a worker thread. Return true and execute 79 // |callback| to continue the request. Return false to cancel the request. 80 // |request| may be different from the request used to create the 81 // StreamReaderURLLoader if a redirect was followed. 82 virtual bool OpenInputStream(int32_t request_id, 83 const network::ResourceRequest& request, 84 OpenCallback callback) = 0; 85 86 // This method is called to populate the response headers. 87 using HeaderMap = std::multimap<std::string, std::string>; 88 virtual void GetResponseHeaders(int32_t request_id, 89 int* status_code, 90 std::string* reason_phrase, 91 std::string* mime_type, 92 std::string* charset, 93 int64_t* content_length, 94 HeaderMap* extra_headers) = 0; 95 }; 96 97 // Custom URLLoader implementation for loading network responses from stream. 98 // Methods are called on the IO thread unless otherwise indicated. 99 // Based on android_webview/browser/network_service/ 100 // android_stream_reader_url_loader.h 101 class StreamReaderURLLoader : public network::mojom::URLLoader { 102 public: 103 // Delegate abstraction for obtaining input streams. All methods are called 104 // on the IO thread unless otherwise indicated. 105 class Delegate : public ResourceResponse { 106 public: 107 // This method is called if the result of calling OpenInputStream was null. 108 // The |restarted| parameter is set to true if the request was restarted 109 // with a new loader. 110 virtual void OnInputStreamOpenFailed(int32_t request_id, 111 bool* restarted) = 0; 112 }; 113 114 StreamReaderURLLoader( 115 int32_t request_id, 116 const network::ResourceRequest& request, 117 mojo::PendingRemote<network::mojom::URLLoaderClient> client, 118 mojo::PendingRemote<network::mojom::TrustedHeaderClient> header_client, 119 const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, 120 std::unique_ptr<Delegate> response_delegate); 121 122 StreamReaderURLLoader(const StreamReaderURLLoader&) = delete; 123 StreamReaderURLLoader& operator=(const StreamReaderURLLoader&) = delete; 124 125 ~StreamReaderURLLoader() override; 126 127 void Start(); 128 129 void ContinueResponse(bool was_redirected); 130 131 // network::mojom::URLLoader methods: 132 void FollowRedirect( 133 const std::vector<std::string>& removed_headers, 134 const net::HttpRequestHeaders& modified_headers, 135 const net::HttpRequestHeaders& modified_cors_exempt_headers, 136 const absl::optional<GURL>& new_url) override; 137 void SetPriority(net::RequestPriority priority, 138 int intra_priority_value) override; 139 void PauseReadingBodyFromNet() override; 140 void ResumeReadingBodyFromNet() override; 141 142 private: 143 void ContinueWithRequestHeaders( 144 int32_t result, 145 const absl::optional<net::HttpRequestHeaders>& headers); 146 void OnInputStreamOpened(std::unique_ptr<Delegate> returned_delegate, 147 std::unique_ptr<InputStream> input_stream); 148 149 void OnReaderSkipCompleted(int64_t bytes_skipped); 150 void HeadersComplete(int status_code, int64_t expected_content_length); 151 void ContinueWithResponseHeaders( 152 network::mojom::URLResponseHeadPtr pending_response, 153 int32_t result, 154 const absl::optional<std::string>& headers, 155 const absl::optional<GURL>& redirect_url); 156 157 void SendBody(); 158 void ReadMore(); 159 void OnDataPipeWritable(MojoResult result); 160 void OnReaderReadCompleted(int bytes_read); 161 void RequestComplete(int status_code); 162 163 void CleanUp(); 164 165 bool ParseRange(const net::HttpRequestHeaders& headers); 166 bool byte_range_valid() const; 167 168 const int32_t request_id_; 169 170 size_t header_length_ = 0; 171 int64_t total_bytes_read_ = 0; 172 173 net::HttpByteRange byte_range_; 174 network::ResourceRequest request_; 175 mojo::Remote<network::mojom::URLLoaderClient> client_; 176 mojo::Remote<network::mojom::TrustedHeaderClient> header_client_; 177 const net::MutableNetworkTrafficAnnotationTag traffic_annotation_; 178 std::unique_ptr<Delegate> response_delegate_; 179 scoped_refptr<InputStreamReader> input_stream_reader_; 180 181 mojo::ScopedDataPipeProducerHandle producer_handle_; 182 scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_; 183 mojo::SimpleWatcher writable_handle_watcher_; 184 base::ThreadChecker thread_checker_; 185 186 scoped_refptr<base::SequencedTaskRunner> stream_work_task_runner_; 187 188 base::OnceClosure open_cancel_callback_; 189 190 base::WeakPtrFactory<StreamReaderURLLoader> weak_factory_; 191 }; 192 193 } // namespace net_service 194 195 #endif // CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_ 196