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