blob: ff2c1742a3a38b2fbee5706047d9d0949456e3fc [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001// 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#ifndef NET_URL_REQUEST_URL_FETCHER_CORE_H_
6#define NET_URL_REQUEST_URL_FETCHER_CORE_H_
7
8#include <set>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "base/debug/stack_trace.h"
14#include "base/file_path.h"
15#include "base/lazy_instance.h"
16#include "base/memory/ref_counted.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/memory/weak_ptr.h"
19#include "base/platform_file.h"
20#include "base/timer.h"
21#include "googleurl/src/gurl.h"
22#include "net/base/host_port_pair.h"
23#include "net/http/http_request_headers.h"
24#include "net/url_request/url_fetcher.h"
25#include "net/url_request/url_request.h"
26#include "net/url_request/url_request_status.h"
27
28namespace base {
29class SingleThreadTaskRunner;
30} // namespace base
31
32namespace net {
33class HttpResponseHeaders;
34class IOBuffer;
35class URLFetcherDelegate;
36class URLRequestContextGetter;
37class URLRequestThrottlerEntryInterface;
38
39class URLFetcherCore
40 : public base::RefCountedThreadSafe<URLFetcherCore>,
41 public URLRequest::Delegate {
42 public:
43 URLFetcherCore(URLFetcher* fetcher,
44 const GURL& original_url,
45 URLFetcher::RequestType request_type,
46 URLFetcherDelegate* d);
47
48 // Starts the load. It's important that this not happen in the constructor
49 // because it causes the IO thread to begin AddRef()ing and Release()ing
50 // us. If our caller hasn't had time to fully construct us and take a
51 // reference, the IO thread could interrupt things, run a task, Release()
52 // us, and destroy us, leaving the caller with an already-destroyed object
53 // when construction finishes.
54 void Start();
55
56 // Stops any in-progress load and ensures no callback will happen. It is
57 // safe to call this multiple times.
58 void Stop();
59
60 // URLFetcher-like functions.
61
62 // For POST requests, set |content_type| to the MIME type of the
63 // content and set |content| to the data to upload.
64 void SetUploadData(const std::string& upload_content_type,
65 const std::string& upload_content);
66 void SetChunkedUpload(const std::string& upload_content_type);
67 // Adds a block of data to be uploaded in a POST body. This can only be
68 // called after Start().
69 void AppendChunkToUpload(const std::string& data, bool is_last_chunk);
70 // |flags| are flags to apply to the load operation--these should be
71 // one or more of the LOAD_* flags defined in net/base/load_flags.h.
72 void SetLoadFlags(int load_flags);
73 int GetLoadFlags() const;
74 void SetReferrer(const std::string& referrer);
75 void SetExtraRequestHeaders(const std::string& extra_request_headers);
76 void AddExtraRequestHeader(const std::string& header_line);
77 void GetExtraRequestHeaders(HttpRequestHeaders* headers) const;
78 void SetRequestContext(URLRequestContextGetter* request_context_getter);
79 // Set the URL that should be consulted for the third-party cookie
80 // blocking policy.
81 void SetFirstPartyForCookies(const GURL& first_party_for_cookies);
82 // Set the key and data callback that is used when setting the user
83 // data on any URLRequest objects this object creates.
84 void SetURLRequestUserData(
85 const void* key,
86 const URLFetcher::CreateDataCallback& create_data_callback);
87 void SetStopOnRedirect(bool stop_on_redirect);
88 void SetAutomaticallyRetryOn5xx(bool retry);
89 void SetMaxRetriesOn5xx(int max_retries);
90 int GetMaxRetriesOn5xx() const;
91 base::TimeDelta GetBackoffDelay() const;
92 void SetAutomaticallyRetryOnNetworkChanges(int max_retries);
93 void SaveResponseToFileAtPath(
94 const FilePath& file_path,
95 scoped_refptr<base::TaskRunner> file_task_runner);
96 void SaveResponseToTemporaryFile(
97 scoped_refptr<base::TaskRunner> file_task_runner);
98#if defined(COBALT)
99 // Don't save the response.
100 void DiscardResponse();
101#endif
102 HttpResponseHeaders* GetResponseHeaders() const;
103 HostPortPair GetSocketAddress() const;
104 bool WasFetchedViaProxy() const;
105 const GURL& GetOriginalURL() const;
106 const GURL& GetURL() const;
107 const URLRequestStatus& GetStatus() const;
108 int GetResponseCode() const;
109 const ResponseCookies& GetCookies() const;
110 bool FileErrorOccurred(base::PlatformFileError* out_error_code) const;
111 // Reports that the received content was malformed (i.e. failed parsing
112 // or validation). This makes the throttling logic that does exponential
113 // back-off when servers are having problems treat the current request as
114 // a failure. Your call to this method will be ignored if your request is
115 // already considered a failure based on the HTTP response code or response
116 // headers.
117 void ReceivedContentWasMalformed();
118 bool GetResponseAsString(std::string* out_response_string) const;
119 bool GetResponseAsFilePath(bool take_ownership,
120 FilePath* out_response_path);
121
122 // Overridden from URLRequest::Delegate:
123 virtual void OnReceivedRedirect(URLRequest* request,
124 const GURL& new_url,
125 bool* defer_redirect) OVERRIDE;
126 virtual void OnResponseStarted(URLRequest* request) OVERRIDE;
127 virtual void OnReadCompleted(URLRequest* request,
128 int bytes_read) OVERRIDE;
129 virtual void OnCertificateRequested(
130 URLRequest* request,
131 SSLCertRequestInfo* cert_request_info) OVERRIDE;
132
133 URLFetcherDelegate* delegate() const { return delegate_; }
134 static void CancelAll();
135 static int GetNumFetcherCores();
136 static void SetEnableInterceptionForTests(bool enabled);
137 static void SetIgnoreCertificateRequests(bool ignored);
138
139 private:
140 friend class base::RefCountedThreadSafe<URLFetcherCore>;
141
142 // How should the response be stored?
143 enum ResponseDestinationType {
144 STRING, // Default: In a std::string
145 PERMANENT_FILE, // Write to a permanent file.
146 TEMP_FILE, // Write to a temporary file.
147#if defined(COBALT)
148 DISCARD, // Don't store the response.
149#endif
150 };
151
152 class Registry {
153 public:
154 Registry();
155 ~Registry();
156
157 void AddURLFetcherCore(URLFetcherCore* core);
158 void RemoveURLFetcherCore(URLFetcherCore* core);
159
160 void CancelAll();
161
162 int size() const {
163 return fetchers_.size();
164 }
165
166 private:
167 std::set<URLFetcherCore*> fetchers_;
168
169 DISALLOW_COPY_AND_ASSIGN(Registry);
170 };
171
172 // Class FileWriter encapsulates all state involved in writing
173 // response bytes to a file. It is only used if
174 // |URLFetcherCore::response_destination_| == TEMP_FILE ||
175 // |URLFetcherCore::response_destination_| == PERMANENT_FILE. Each
176 // instance of FileWriter is owned by a URLFetcherCore, which
177 // manages its lifetime and never transfers ownership. All file operations
178 // happen on |file_task_runner_|.
179 class FileWriter {
180 public:
181 FileWriter(URLFetcherCore* core,
182 scoped_refptr<base::TaskRunner> file_task_runner);
183 ~FileWriter();
184
185 void CreateFileAtPath(const FilePath& file_path);
186 void CreateTempFile();
187
188 // Record |num_bytes_| response bytes in |core_->buffer_| to the file.
189 void WriteBuffer(int num_bytes);
190
191 // Called when a write has been done. Continues writing if there are
192 // any more bytes to write. Otherwise, initiates a read in core_.
193 void ContinueWrite(base::PlatformFileError error_code, int bytes_written);
194
195 // Drop ownership of the file at |file_path_|.
196 // This class will not delete it or write to it again.
197 void DisownFile();
198
199 // Close the file if it is open.
200 void CloseFileAndCompleteRequest();
201
202 // Close the file if it is open and then delete it.
203 void CloseAndDeleteFile();
204
205 const FilePath& file_path() const { return file_path_; }
206 int64 total_bytes_written() { return total_bytes_written_; }
207 base::PlatformFileError error_code() const { return error_code_; }
208
209 private:
210 // Callback which gets the result of a permanent file creation.
211 void DidCreateFile(const FilePath& file_path,
212 base::PlatformFileError error_code,
213 base::PassPlatformFile file_handle,
214 bool created);
215 // Callback which gets the result of a temporary file creation.
216 void DidCreateTempFile(base::PlatformFileError error_code,
217 base::PassPlatformFile file_handle,
218 const FilePath& file_path);
219 // This method is used to implement DidCreateFile and DidCreateTempFile.
220 void DidCreateFileInternal(const FilePath& file_path,
221 base::PlatformFileError error_code,
222 base::PassPlatformFile file_handle);
223
224 // Callback which gets the result of closing the file.
225 void DidCloseFile(base::PlatformFileError error);
226
227 // Callback which gets the result of closing the file. Deletes the file if
228 // it has been created.
229 void DeleteFile(base::PlatformFileError error_code);
230
231 // The URLFetcherCore which instantiated this class.
232 URLFetcherCore* core_;
233
234 // The last error encountered on a file operation. base::PLATFORM_FILE_OK
235 // if no error occurred.
236 base::PlatformFileError error_code_;
237
238 // Callbacks are created for use with base::FileUtilProxy.
239 base::WeakPtrFactory<URLFetcherCore::FileWriter> weak_factory_;
240
241 // Task runner on which file operations should happen.
242 scoped_refptr<base::TaskRunner> file_task_runner_;
243
244 // Path to the file. This path is empty when there is no file.
245 FilePath file_path_;
246
247 // Handle to the file.
248 base::PlatformFile file_handle_;
249
250 // We always append to the file. Track the total number of bytes
251 // written, so that writes know the offset to give.
252 int64 total_bytes_written_;
253
254 // How many bytes did the last Write() try to write? Needed so
255 // that if not all the bytes get written on a Write(), we can
256 // call Write() again with the rest.
257 int pending_bytes_;
258
259 // When writing, how many bytes from the buffer have been successfully
260 // written so far?
261 int buffer_offset_;
262 };
263
264 virtual ~URLFetcherCore();
265
266 // Wrapper functions that allow us to ensure actions happen on the right
267 // thread.
268 void StartOnIOThread();
269 void StartURLRequest();
270 void StartURLRequestWhenAppropriate();
271 void CancelURLRequest();
272 void OnCompletedURLRequest(base::TimeDelta backoff_delay);
273 void InformDelegateFetchIsComplete();
274 void NotifyMalformedContent();
275 void RetryOrCompleteUrlFetch();
276
277 // Deletes the request, removes it from the registry, and removes the
278 // destruction observer.
279 void ReleaseRequest();
280
281 // Returns the max value of exponential back-off release time for
282 // |original_url_| and |url_|.
283 base::TimeTicks GetBackoffReleaseTime();
284
285 void CompleteAddingUploadDataChunk(const std::string& data,
286 bool is_last_chunk);
287
288 // Store the response bytes in |buffer_| in the container indicated by
289 // |response_destination_|. Return true if the write has been
290 // done, and another read can overwrite |buffer_|. If this function
291 // returns false, it will post a task that will read more bytes once the
292 // write is complete.
293 bool WriteBuffer(int num_bytes);
294
295 // Read response bytes from the request.
296 void ReadResponse();
297
298 // Drop ownership of any file managed by |file_path_|.
299 void DisownFile();
300
301 // Notify Delegate about the progress of upload/download.
302#if defined(COBALT)
303 void InformDelegateResponseStarted();
304 void InformDelegateResponseStartedInDelegateThread();
305#endif // defined(COBALT)
306 void InformDelegateUploadProgress();
307 void InformDelegateUploadProgressInDelegateThread(int64 current, int64 total);
308 void InformDelegateDownloadDataIfNecessary(int bytes_read);
309 void InformDelegateDownloadData();
310 void InformDelegateDownloadDataInDelegateThread(
311 scoped_ptr<std::string> download_data);
312
313 URLFetcher* fetcher_; // Corresponding fetcher object
314 GURL original_url_; // The URL we were asked to fetch
315 GURL url_; // The URL we eventually wound up at
316 URLFetcher::RequestType request_type_; // What type of request is this?
317 URLRequestStatus status_; // Status of the request
318 URLFetcherDelegate* delegate_; // Object to notify on completion
319 scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
320 // Task runner for the creating thread.
321 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
322 // Task runner for file access.
323 scoped_refptr<base::TaskRunner> file_task_runner_;
324 // Task runner for the thread
325 // on which file access happens.
326 scoped_ptr<URLRequest> request_; // The actual request this wraps
327 int load_flags_; // Flags for the load operation
328 int response_code_; // HTTP status code for the request
329 std::string data_; // Results of the request, when we are
330 // storing the response as a string.
331 scoped_refptr<IOBuffer> buffer_; // Read buffer
332 // Caches the data to be sent to the request thread to minimize task posting.
333 scoped_ptr<std::string> download_data_cache_;
334 scoped_refptr<URLRequestContextGetter> request_context_getter_;
335 // Cookie/cache info for the request
336 GURL first_party_for_cookies_; // The first party URL for the request
337 // The user data to add to each newly-created URLRequest.
338 const void* url_request_data_key_;
339 URLFetcher::CreateDataCallback url_request_create_data_callback_;
340 ResponseCookies cookies_; // Response cookies
341 HttpRequestHeaders extra_request_headers_;
342 scoped_refptr<HttpResponseHeaders> response_headers_;
343 bool was_fetched_via_proxy_;
344 HostPortPair socket_address_;
345
346 std::string upload_content_; // HTTP POST payload
347 std::string upload_content_type_; // MIME type of POST payload
348 std::string referrer_; // HTTP Referer header value
349 bool is_chunked_upload_; // True if using chunked transfer encoding
350
351 // Used to determine how long to wait before making a request or doing a
352 // retry.
353 //
354 // Both of them can only be accessed on the IO thread.
355 //
356 // We need not only the throttler entry for |original_URL|, but also
357 // the one for |url|. For example, consider the case that URL A
358 // redirects to URL B, for which the server returns a 500
359 // response. In this case, the exponential back-off release time of
360 // URL A won't increase. If we retry without considering the
361 // back-off constraint of URL B, we may send out too many requests
362 // for URL A in a short period of time.
363 //
364 // Both of these will be NULL if
365 // URLRequestContext::throttler_manager() is NULL.
366 scoped_refptr<URLRequestThrottlerEntryInterface>
367 original_url_throttler_entry_;
368 scoped_refptr<URLRequestThrottlerEntryInterface> url_throttler_entry_;
369
370 // True if the URLFetcher has been cancelled.
371 bool was_cancelled_;
372
373 // If writing results to a file, |file_writer_| will manage creation,
374 // writing, and destruction of that file.
375 scoped_ptr<FileWriter> file_writer_;
376
377 // Where should responses be saved?
378 ResponseDestinationType response_destination_;
379
380 // Path to the file where the response is written.
381 FilePath response_destination_file_path_;
382
383 // By default any server-initiated redirects are automatically followed. If
384 // this flag is set to true, however, a redirect will halt the fetch and call
385 // back to to the delegate immediately.
386 bool stop_on_redirect_;
387 // True when we're actually stopped due to a redirect halted by the above. We
388 // use this to ensure that |url_| is set to the redirect destination rather
389 // than the originally-fetched URL.
390 bool stopped_on_redirect_;
391
392 // If |automatically_retry_on_5xx_| is false, 5xx responses will be
393 // propagated to the observer, if it is true URLFetcher will automatically
394 // re-execute the request, after the back-off delay has expired.
395 // true by default.
396 bool automatically_retry_on_5xx_;
397 // |num_retries_on_5xx_| indicates how many times we've failed to successfully
398 // fetch this URL due to 5xx responses. Once this value exceeds the maximum
399 // number of retries specified by the owner URLFetcher instance,
400 // we'll give up.
401 int num_retries_on_5xx_;
402 // Maximum retries allowed when 5xx responses are received.
403 int max_retries_on_5xx_;
404 // Back-off time delay. 0 by default.
405 base::TimeDelta backoff_delay_;
406
407 // The number of retries that have been attempted due to ERR_NETWORK_CHANGED.
408 int num_retries_on_network_changes_;
409 // Maximum retries allowed when the request fails with ERR_NETWORK_CHANGED.
410 // 0 by default.
411 int max_retries_on_network_changes_;
412
413 // Timer to poll the progress of uploading for POST and PUT requests.
414 // When crbug.com/119629 is fixed, scoped_ptr is not necessary here.
415 scoped_ptr<base::RepeatingTimer<URLFetcherCore> >
416 upload_progress_checker_timer_;
417 // Number of bytes sent so far.
418 int64 current_upload_bytes_;
419 // Number of bytes received so far.
420 int64 current_response_bytes_;
421 // Total expected bytes to receive (-1 if it cannot be determined).
422 int64 total_response_bytes_;
423
424 // TODO(willchan): Get rid of this after debugging crbug.com/90971.
425 base::debug::StackTrace stack_trace_;
426
427 static base::LazyInstance<Registry> g_registry;
428
429 DISALLOW_COPY_AND_ASSIGN(URLFetcherCore);
430};
431
432} // namespace net
433
434#endif // NET_URL_REQUEST_URL_FETCHER_CORE_H_