Misha Efimov | c1731b0 | 2018-01-16 21:46:51 | [diff] [blame] | 1 | // Copyright 2014 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 COMPONENTS_CRONET_CRONET_URL_REQUEST_H_ |
| 6 | #define COMPONENTS_CRONET_CRONET_URL_REQUEST_H_ |
| 7 | |
| 8 | #include <memory> |
| 9 | #include <string> |
| 10 | |
| 11 | #include "base/callback.h" |
| 12 | #include "base/location.h" |
| 13 | #include "base/macros.h" |
| 14 | #include "base/memory/ref_counted.h" |
| 15 | #include "base/time/time.h" |
| 16 | #include "net/base/request_priority.h" |
| 17 | #include "net/url_request/url_request.h" |
| 18 | #include "url/gurl.h" |
| 19 | |
| 20 | namespace net { |
| 21 | class HttpRequestHeaders; |
| 22 | enum LoadState; |
| 23 | class SSLCertRequestInfo; |
| 24 | class SSLInfo; |
| 25 | class UploadDataStream; |
| 26 | } // namespace net |
| 27 | |
| 28 | namespace cronet { |
| 29 | |
| 30 | class CronetURLRequestContext; |
| 31 | class TestUtil; |
| 32 | |
| 33 | // Wrapper around net::URLRequestContext. |
| 34 | // Created and configured from client thread. Start, ReadData, and Destroy are |
| 35 | // posted to network thread and all callbacks into the Callback() are |
| 36 | // done on the network thread. CronetUrlRequest client is expected to initiate |
| 37 | // the next step like FollowDeferredRedirect, ReadData or Destroy. Public |
| 38 | // methods can be called on any thread. |
| 39 | class CronetURLRequest { |
| 40 | public: |
| 41 | // Callback implemented by CronetURLRequest() caller and owned by |
| 42 | // CronetURLRequest::NetworkTasks. All callback methods are invoked on network |
| 43 | // thread. |
| 44 | class Callback { |
| 45 | public: |
| 46 | virtual ~Callback() = default; |
| 47 | |
| 48 | // Invoked whenever a redirect is encountered. This will only be invoked |
| 49 | // between the call to CronetURLRequest::Start() and |
| 50 | // Callback::OnResponseStarted(). The body of the redirect response, if |
| 51 | // it has one, will be ignored. |
| 52 | // |
| 53 | // The redirect will not be followed until |
| 54 | // CronetURLRequest::FollowDeferredRedirect() method is called, either |
| 55 | // synchronously or asynchronously. |
| 56 | virtual void OnReceivedRedirect(const std::string& new_location, |
| 57 | int http_status_code, |
| 58 | const std::string& http_status_text, |
| 59 | const net::HttpResponseHeaders* headers, |
| 60 | bool was_cached, |
| 61 | const std::string& negotiated_protocol, |
| 62 | const std::string& proxy_server, |
| 63 | int64_t received_byte_count) = 0; |
| 64 | |
| 65 | // Invoked when the final set of headers, after all redirects, is received. |
| 66 | // Will only be invoked once for each request. |
| 67 | // |
| 68 | // With the exception of Callback::OnCanceled(), |
| 69 | // no other Callback method will be invoked for the request, |
| 70 | // including Callback::OnSucceeded() and Callback::OnFailed(), until |
| 71 | // CronetUrlRequest::Read() is called to attempt to start reading the |
| 72 | // response body. |
| 73 | virtual void OnResponseStarted(int http_status_code, |
| 74 | const std::string& http_status_text, |
| 75 | const net::HttpResponseHeaders* headers, |
| 76 | bool was_cached, |
| 77 | const std::string& negotiated_protocol, |
Misha Efimov | f6fdcf86 | 2018-03-12 14:50:23 | [diff] [blame] | 78 | const std::string& proxy_server, |
| 79 | int64_t received_byte_count) = 0; |
Misha Efimov | c1731b0 | 2018-01-16 21:46:51 | [diff] [blame] | 80 | |
| 81 | // Invoked whenever part of the response body has been read. Only part of |
| 82 | // the buffer may be populated, even if the entire response body has not yet |
| 83 | // been consumed. |
| 84 | // |
| 85 | // With the exception of Callback::OnCanceled(), |
| 86 | // no other Callback method will be invoked for the request, |
| 87 | // including Callback::OnSucceeded() and Callback::OnFailed(), until |
| 88 | // CronetUrlRequest::Read() is called to attempt to continue reading the |
| 89 | // response body. |
| 90 | virtual void OnReadCompleted(scoped_refptr<net::IOBuffer> buffer, |
| 91 | int bytes_read, |
| 92 | int64_t received_byte_count) = 0; |
| 93 | |
| 94 | // Invoked when request is completed successfully. |
| 95 | virtual void OnSucceeded(int64_t received_byte_count) = 0; |
| 96 | |
| 97 | // Invoked if request failed for any reason after CronetURLRequest::Start(). |
| 98 | // |net_error| provides information about the failure. |quic_error| is only |
| 99 | // valid if |net_error| is net::QUIC_PROTOCOL_ERROR. |
| 100 | virtual void OnError(int net_error, |
| 101 | int quic_error, |
| 102 | const std::string& error_string, |
| 103 | int64_t received_byte_count) = 0; |
| 104 | |
| 105 | // Invoked if request was canceled via CronetURLRequest::Start(). |
| 106 | virtual void OnCanceled() = 0; |
| 107 | |
| 108 | // Invoked when request is destroyed. Once invoked, no other Callback |
| 109 | // methods will be invoked. |
| 110 | virtual void OnDestroyed() = 0; |
| 111 | |
| 112 | // Invoked right before request is destroyed to report collected metrics if |
| 113 | // |enable_metrics| is true in CronetURLRequest::CronetURLRequest(). |
| 114 | virtual void OnMetricsCollected(const base::Time& request_start_time, |
| 115 | const base::TimeTicks& request_start, |
| 116 | const base::TimeTicks& dns_start, |
| 117 | const base::TimeTicks& dns_end, |
| 118 | const base::TimeTicks& connect_start, |
| 119 | const base::TimeTicks& connect_end, |
| 120 | const base::TimeTicks& ssl_start, |
| 121 | const base::TimeTicks& ssl_end, |
| 122 | const base::TimeTicks& send_start, |
| 123 | const base::TimeTicks& send_end, |
| 124 | const base::TimeTicks& push_start, |
| 125 | const base::TimeTicks& push_end, |
| 126 | const base::TimeTicks& receive_headers_end, |
| 127 | const base::TimeTicks& request_end, |
| 128 | bool socket_reused, |
| 129 | int64_t sent_bytes_count, |
| 130 | int64_t received_bytes_count) = 0; |
| 131 | }; |
| 132 | // Invoked in response to CronetURLRequest::GetStatus() to allow multiple |
| 133 | // overlapping calls. The load states correspond to the lengthy periods of |
| 134 | // time that a request load may be blocked and unable to make progress. |
| 135 | using OnStatusCallback = base::OnceCallback<void(net::LoadState)>; |
| 136 | |
| 137 | // Bypasses cache if |disable_cache| is true. If context is not set up to |
| 138 | // use cache, |disable_cache| has no effect. |disable_connection_migration| |
| 139 | // causes connection migration to be disabled for this request if true. If |
| 140 | // global connection migration flag is not enabled, |
| 141 | // |disable_connection_migration| has no effect. |
| 142 | CronetURLRequest(CronetURLRequestContext* context, |
| 143 | std::unique_ptr<Callback> callback, |
| 144 | const GURL& url, |
| 145 | net::RequestPriority priority, |
| 146 | bool disable_cache, |
| 147 | bool disable_connection_migration, |
Paul Jensen | 4231294 | 2018-02-26 21:29:58 | [diff] [blame] | 148 | bool enable_metrics, |
| 149 | bool traffic_stats_tag_set, |
| 150 | int32_t traffic_stats_tag, |
| 151 | bool traffic_stats_uid_set, |
| 152 | int32_t traffic_stats_uid); |
Misha Efimov | c1731b0 | 2018-01-16 21:46:51 | [diff] [blame] | 153 | |
| 154 | // Methods called prior to Start are never called on network thread. |
| 155 | |
| 156 | // Sets the request method GET, POST etc. |
| 157 | bool SetHttpMethod(const std::string& method); |
| 158 | |
| 159 | // Adds a header to the request before it starts. |
| 160 | bool AddRequestHeader(const std::string& name, const std::string& value); |
| 161 | |
| 162 | // Adds a request body to the request before it starts. |
| 163 | void SetUpload(std::unique_ptr<net::UploadDataStream> upload); |
| 164 | |
| 165 | // Starts the request. |
| 166 | void Start(); |
| 167 | |
| 168 | // GetStatus invokes |on_status_callback| on network thread to allow multiple |
| 169 | // overlapping calls. |
| 170 | void GetStatus(OnStatusCallback on_status_callback) const; |
| 171 | |
| 172 | // Follows redirect. |
| 173 | void FollowDeferredRedirect(); |
| 174 | |
| 175 | // Reads more data. |
| 176 | bool ReadData(net::IOBuffer* buffer, int max_bytes); |
| 177 | |
| 178 | // Releases all resources for the request and deletes the object itself. |
| 179 | // |send_on_canceled| indicates whether OnCanceled callback should be |
| 180 | // issued to indicate when no more callbacks will be issued. |
| 181 | void Destroy(bool send_on_canceled); |
| 182 | |
| 183 | private: |
| 184 | friend class TestUtil; |
| 185 | |
| 186 | // Private destructor invoked fron NetworkTasks::Destroy() on network thread. |
| 187 | ~CronetURLRequest(); |
| 188 | |
| 189 | // NetworkTasks performs tasks on the network thread and owns objects that |
| 190 | // live on the network thread. |
| 191 | class NetworkTasks : public net::URLRequest::Delegate { |
| 192 | public: |
| 193 | // Invoked off the network thread. |
| 194 | NetworkTasks(std::unique_ptr<Callback> callback, |
| 195 | const GURL& url, |
| 196 | net::RequestPriority priority, |
| 197 | int load_flags, |
Paul Jensen | 4231294 | 2018-02-26 21:29:58 | [diff] [blame] | 198 | bool enable_metrics, |
| 199 | bool traffic_stats_tag_set, |
| 200 | int32_t traffic_stats_tag, |
| 201 | bool traffic_stats_uid_set, |
| 202 | int32_t traffic_stats_uid); |
Misha Efimov | c1731b0 | 2018-01-16 21:46:51 | [diff] [blame] | 203 | |
| 204 | // Invoked on the network thread. |
| 205 | ~NetworkTasks() override; |
| 206 | |
| 207 | // Starts the request. |
| 208 | void Start(CronetURLRequestContext* context, |
| 209 | const std::string& method, |
| 210 | std::unique_ptr<net::HttpRequestHeaders> request_headers, |
| 211 | std::unique_ptr<net::UploadDataStream> upload); |
| 212 | |
| 213 | // Gets status of the requrest and invokes |on_status_callback| to allow |
| 214 | // multiple overlapping calls. |
| 215 | void GetStatus(OnStatusCallback on_status_callback) const; |
| 216 | |
| 217 | // Follows redirect. |
| 218 | void FollowDeferredRedirect(); |
| 219 | |
| 220 | // Reads more data. |
| 221 | void ReadData(scoped_refptr<net::IOBuffer> read_buffer, int buffer_size); |
| 222 | |
| 223 | // Releases all resources for the request and deletes the |request|, which |
| 224 | // owns |this|, so |this| is also deleted. |
| 225 | // |send_on_canceled| indicates whether OnCanceled callback should be |
| 226 | // issued to indicate when no more callbacks will be issued. |
| 227 | void Destroy(CronetURLRequest* request, bool send_on_canceled); |
| 228 | |
| 229 | private: |
| 230 | friend class TestUtil; |
| 231 | |
| 232 | // net::URLRequest::Delegate implementations: |
| 233 | void OnReceivedRedirect(net::URLRequest* request, |
| 234 | const net::RedirectInfo& redirect_info, |
| 235 | bool* defer_redirect) override; |
| 236 | void OnCertificateRequested( |
| 237 | net::URLRequest* request, |
| 238 | net::SSLCertRequestInfo* cert_request_info) override; |
| 239 | void OnSSLCertificateError(net::URLRequest* request, |
| 240 | const net::SSLInfo& ssl_info, |
| 241 | bool fatal) override; |
| 242 | void OnResponseStarted(net::URLRequest* request, int net_error) override; |
| 243 | void OnReadCompleted(net::URLRequest* request, int bytes_read) override; |
| 244 | |
| 245 | // Report error and cancel request_adapter. |
| 246 | void ReportError(net::URLRequest* request, int net_error); |
| 247 | // Reports metrics collected. |
| 248 | void MaybeReportMetrics(); |
| 249 | |
| 250 | // Callback implemented by the client. |
| 251 | std::unique_ptr<CronetURLRequest::Callback> callback_; |
| 252 | |
| 253 | const GURL initial_url_; |
| 254 | const net::RequestPriority initial_priority_; |
| 255 | const int initial_load_flags_; |
Misha Efimov | f6fdcf86 | 2018-03-12 14:50:23 | [diff] [blame] | 256 | // Count of bytes received during redirect is added to received byte count. |
| 257 | int64_t received_byte_count_from_redirects_; |
Misha Efimov | c1731b0 | 2018-01-16 21:46:51 | [diff] [blame] | 258 | |
| 259 | // Whether detailed metrics should be collected and reported. |
| 260 | const bool enable_metrics_; |
| 261 | // Whether metrics have been reported. |
| 262 | bool metrics_reported_; |
| 263 | |
Paul Jensen | 4231294 | 2018-02-26 21:29:58 | [diff] [blame] | 264 | // Whether |traffic_stats_tag_| should be applied. |
| 265 | const bool traffic_stats_tag_set_; |
| 266 | // TrafficStats tag to apply to URLRequest. |
| 267 | const int32_t traffic_stats_tag_; |
| 268 | // Whether |traffic_stats_uid_| should be applied. |
| 269 | const bool traffic_stats_uid_set_; |
| 270 | // UID to be applied to URLRequest. |
| 271 | const int32_t traffic_stats_uid_; |
| 272 | |
Misha Efimov | c1731b0 | 2018-01-16 21:46:51 | [diff] [blame] | 273 | scoped_refptr<net::IOBuffer> read_buffer_; |
| 274 | std::unique_ptr<net::URLRequest> url_request_; |
| 275 | |
| 276 | THREAD_CHECKER(network_thread_checker_); |
| 277 | DISALLOW_COPY_AND_ASSIGN(NetworkTasks); |
| 278 | }; |
| 279 | |
| 280 | CronetURLRequestContext* context_; |
| 281 | // |network_tasks_| is invoked on network thread. |
| 282 | NetworkTasks network_tasks_; |
| 283 | |
| 284 | // Request parameters set off network thread before Start(). |
| 285 | std::string initial_method_; |
| 286 | std::unique_ptr<net::HttpRequestHeaders> initial_request_headers_; |
| 287 | std::unique_ptr<net::UploadDataStream> upload_; |
| 288 | |
| 289 | DISALLOW_COPY_AND_ASSIGN(CronetURLRequest); |
| 290 | }; |
| 291 | |
| 292 | } // namespace cronet |
| 293 | |
| 294 | #endif // COMPONENTS_CRONET_CRONET_URL_REQUEST_H_ |