OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/net/url_fetcher.h" | 5 #include "chrome/common/net/url_fetcher.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/file_path.h" | |
11 #include "base/file_util_proxy.h" | |
10 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/memory/scoped_callback_factory.h" | |
11 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
12 #include "base/message_loop_proxy.h" | 15 #include "base/message_loop_proxy.h" |
16 #include "base/platform_file.h" | |
13 #include "base/stl_util-inl.h" | 17 #include "base/stl_util-inl.h" |
14 #include "base/string_util.h" | 18 #include "base/string_util.h" |
15 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
20 #include "content/browser/browser_thread.h" | |
16 #include "googleurl/src/gurl.h" | 21 #include "googleurl/src/gurl.h" |
17 #include "net/base/load_flags.h" | 22 #include "net/base/load_flags.h" |
18 #include "net/base/io_buffer.h" | 23 #include "net/base/io_buffer.h" |
19 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
20 #include "net/base/host_port_pair.h" | 25 #include "net/base/host_port_pair.h" |
21 #include "net/http/http_request_headers.h" | 26 #include "net/http/http_request_headers.h" |
22 #include "net/http/http_response_headers.h" | 27 #include "net/http/http_response_headers.h" |
23 #include "net/url_request/url_request.h" | 28 #include "net/url_request/url_request.h" |
24 #include "net/url_request/url_request_context.h" | 29 #include "net/url_request/url_request_context.h" |
25 #include "net/url_request/url_request_context_getter.h" | 30 #include "net/url_request/url_request_context_getter.h" |
26 #include "net/url_request/url_request_throttler_manager.h" | 31 #include "net/url_request/url_request_throttler_manager.h" |
27 | 32 |
28 static const int kBufferSize = 4096; | 33 static const int kBufferSize = 4096; |
34 const int URLFetcher::kInvalidHttpResponseCode = -1; | |
29 | 35 |
30 class URLFetcher::Core | 36 class URLFetcher::Core |
31 : public base::RefCountedThreadSafe<URLFetcher::Core>, | 37 : public base::RefCountedThreadSafe<URLFetcher::Core>, |
32 public net::URLRequest::Delegate { | 38 public net::URLRequest::Delegate { |
33 public: | 39 public: |
34 // For POST requests, set |content_type| to the MIME type of the content | 40 // For POST requests, set |content_type| to the MIME type of the content |
35 // and set |content| to the data to upload. |flags| are flags to apply to | 41 // and set |content| to the data to upload. |flags| are flags to apply to |
36 // the load operation--these should be one or more of the LOAD_* flags | 42 // the load operation--these should be one or more of the LOAD_* flags |
37 // defined in net/base/load_flags.h. | 43 // defined in net/base/load_flags.h. |
38 Core(URLFetcher* fetcher, | 44 Core(URLFetcher* fetcher, |
(...skipping 14 matching lines...) Expand all Loading... | |
53 void Stop(); | 59 void Stop(); |
54 | 60 |
55 // Reports that the received content was malformed. | 61 // Reports that the received content was malformed. |
56 void ReceivedContentWasMalformed(); | 62 void ReceivedContentWasMalformed(); |
57 | 63 |
58 // Overridden from net::URLRequest::Delegate: | 64 // Overridden from net::URLRequest::Delegate: |
59 virtual void OnResponseStarted(net::URLRequest* request); | 65 virtual void OnResponseStarted(net::URLRequest* request); |
60 virtual void OnReadCompleted(net::URLRequest* request, int bytes_read); | 66 virtual void OnReadCompleted(net::URLRequest* request, int bytes_read); |
61 | 67 |
62 URLFetcher::Delegate* delegate() const { return delegate_; } | 68 URLFetcher::Delegate* delegate() const { return delegate_; } |
63 | |
64 static void CancelAll(); | 69 static void CancelAll(); |
65 | 70 |
66 private: | 71 private: |
67 friend class base::RefCountedThreadSafe<URLFetcher::Core>; | 72 friend class base::RefCountedThreadSafe<URLFetcher::Core>; |
68 | 73 |
69 class Registry { | 74 class Registry { |
70 public: | 75 public: |
71 Registry(); | 76 Registry(); |
72 ~Registry(); | 77 ~Registry(); |
73 | 78 |
74 void AddURLFetcherCore(Core* core); | 79 void AddURLFetcherCore(Core* core); |
75 void RemoveURLFetcherCore(Core* core); | 80 void RemoveURLFetcherCore(Core* core); |
76 | 81 |
77 void CancelAll(); | 82 void CancelAll(); |
78 | 83 |
79 int size() const { | 84 int size() const { |
80 return fetchers_.size(); | 85 return fetchers_.size(); |
81 } | 86 } |
82 | 87 |
83 private: | 88 private: |
84 std::set<Core*> fetchers_; | 89 std::set<Core*> fetchers_; |
85 | 90 |
86 DISALLOW_COPY_AND_ASSIGN(Registry); | 91 DISALLOW_COPY_AND_ASSIGN(Registry); |
87 }; | 92 }; |
88 | 93 |
94 // Class TempFileWriter encapsulates all state involved in writing | |
95 // response bytes to a temporary file. It is only used if | |
96 // |Core::response_destination_| == TEMP_FILE. | |
97 class TempFileWriter { | |
98 public: | |
99 TempFileWriter( | |
100 URLFetcher::Core* core, | |
101 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy); | |
102 | |
103 ~TempFileWriter(); | |
104 void CreateTempFile(); | |
105 void DidCreateTempFile(base::PlatformFileError error_code, | |
106 base::PassPlatformFile file_handle, | |
107 FilePath file_path); | |
108 void DidCloseTempFile(base::PlatformFileError error_code); | |
109 void DidReopenTempFile(base::PlatformFileError error_code, | |
110 base::PassPlatformFile file_handle, | |
111 bool created); | |
112 | |
113 // Record |num_bytes_| response bytes in |core_->buffer_| to the file. | |
114 void WriteBuffer(int num_bytes); | |
115 | |
116 // Called when a write has been done. Continues writing if there are | |
117 // any more bytes to write. Otherwise, initiates a read in core_. | |
118 void ContinueWrite(base::PlatformFileError error_code, | |
119 int bytes_written); | |
120 | |
121 // Drop ownership of the file at path |temp_file_|. This class | |
122 // will not delete it or write to it again. | |
123 void DisownTempFile(); | |
124 | |
125 // Remove any file created. | |
126 void Destroy(); | |
127 | |
128 const FilePath& temp_file() const { return temp_file_; } | |
129 int64 total_bytes_written() { return total_bytes_written_; } | |
130 base::PlatformFileError error_code() const { return error_code_; } | |
131 | |
132 private: | |
133 // The URLFetcher::Core which instantiated this class. | |
134 URLFetcher::Core* core_; | |
135 | |
136 // The last error encountered on a file operation. base::PLATFORM_FILE_OK | |
137 // if no error occurred. | |
138 base::PlatformFileError error_code_; | |
139 | |
140 // Callbacks are created for use with base::FileUtilProxy. | |
141 base::ScopedCallbackFactory<URLFetcher::Core::TempFileWriter> | |
142 callback_factory_; | |
143 | |
144 // Message loop on which file opperations should happen. | |
145 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_; | |
146 | |
147 // Path to the temporary file. This path is empty when there | |
148 // is no temp file. | |
149 FilePath temp_file_; | |
150 | |
151 // Handle to the temp file. | |
152 base::PlatformFile temp_file_handle_; | |
153 | |
154 // We always append to the file. Track the total number of bytes | |
155 // written, so that writes know the offset to give. | |
156 int64 total_bytes_written_; | |
157 | |
158 // How many bytes did the last Write() try to write? Needed so | |
159 // that if not all the bytes get written on a Write(), we can | |
160 // call Write() again with the rest. | |
161 int pending_bytes_; | |
162 | |
163 // When writing, how many bytes from the buffer have been successfully | |
164 // written so far? | |
165 int buffer_offset_; | |
166 }; | |
167 | |
89 virtual ~Core(); | 168 virtual ~Core(); |
90 | 169 |
91 // Wrapper functions that allow us to ensure actions happen on the right | 170 // Wrapper functions that allow us to ensure actions happen on the right |
92 // thread. | 171 // thread. |
93 void StartURLRequest(); | 172 void StartURLRequest(); |
94 void StartURLRequestWhenAppropriate(); | 173 void StartURLRequestWhenAppropriate(); |
95 void CancelURLRequest(); | 174 void CancelURLRequest(); |
96 void OnCompletedURLRequest(const net::URLRequestStatus& status); | 175 void OnCompletedURLRequest(const net::URLRequestStatus& status); |
176 void InformDelegateFetchIsComplete(); | |
97 void NotifyMalformedContent(); | 177 void NotifyMalformedContent(); |
98 | 178 |
99 // Deletes the request, removes it from the registry, and removes the | 179 // Deletes the request, removes it from the registry, and removes the |
100 // destruction observer. | 180 // destruction observer. |
101 void ReleaseRequest(); | 181 void ReleaseRequest(); |
102 | 182 |
103 // Returns the max value of exponential back-off release time for | 183 // Returns the max value of exponential back-off release time for |
104 // |original_url_| and |url_|. | 184 // |original_url_| and |url_|. |
105 base::TimeTicks GetBackoffReleaseTime(); | 185 base::TimeTicks GetBackoffReleaseTime(); |
106 | 186 |
107 void CompleteAddingUploadDataChunk(const std::string& data, | 187 void CompleteAddingUploadDataChunk(const std::string& data, |
108 bool is_last_chunk); | 188 bool is_last_chunk); |
109 | 189 |
110 // Adds a block of data to be uploaded in a POST body. This can only be called | 190 // Adds a block of data to be uploaded in a POST body. This can only be |
111 // after Start(). | 191 // called after Start(). |
112 void AppendChunkToUpload(const std::string& data, bool is_last_chunk); | 192 void AppendChunkToUpload(const std::string& data, bool is_last_chunk); |
113 | 193 |
194 // Store the response bytes in |buffer_| in the container indicated by | |
195 // |fetcher_->response_destination_|. Return true if the write has been | |
196 // done, and another read can overwrite |buffer_|. If this function | |
197 // returns false, it will post a task that will read more bytes once the | |
198 // write is complete. | |
199 bool WriteBuffer(int num_bytes); | |
200 | |
201 // Read response bytes from the request. | |
202 void ReadResponse(); | |
203 | |
114 URLFetcher* fetcher_; // Corresponding fetcher object | 204 URLFetcher* fetcher_; // Corresponding fetcher object |
115 GURL original_url_; // The URL we were asked to fetch | 205 GURL original_url_; // The URL we were asked to fetch |
116 GURL url_; // The URL we eventually wound up at | 206 GURL url_; // The URL we eventually wound up at |
117 RequestType request_type_; // What type of request is this? | 207 RequestType request_type_; // What type of request is this? |
208 net::URLRequestStatus status_; // Status of the request | |
118 URLFetcher::Delegate* delegate_; // Object to notify on completion | 209 URLFetcher::Delegate* delegate_; // Object to notify on completion |
119 scoped_refptr<base::MessageLoopProxy> delegate_loop_proxy_; | 210 scoped_refptr<base::MessageLoopProxy> delegate_loop_proxy_; |
120 // Message loop proxy of the creating | 211 // Message loop proxy of the creating |
121 // thread. | 212 // thread. |
122 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; | 213 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
123 // The message loop proxy for the thread | 214 // The message loop proxy for the thread |
124 // on which the request IO happens. | 215 // on which the request IO happens. |
216 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_; | |
217 // The message loop proxy for the thread | |
218 // on which file access happens. | |
125 scoped_ptr<net::URLRequest> request_; // The actual request this wraps | 219 scoped_ptr<net::URLRequest> request_; // The actual request this wraps |
126 int load_flags_; // Flags for the load operation | 220 int load_flags_; // Flags for the load operation |
127 int response_code_; // HTTP status code for the request | 221 int response_code_; // HTTP status code for the request |
128 std::string data_; // Results of the request | 222 std::string data_; // Results of the request, when we are |
223 // storing the response as a string. | |
129 scoped_refptr<net::IOBuffer> buffer_; | 224 scoped_refptr<net::IOBuffer> buffer_; |
130 // Read buffer | 225 // Read buffer |
131 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | 226 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
132 // Cookie/cache info for the request | 227 // Cookie/cache info for the request |
133 net::ResponseCookies cookies_; // Response cookies | 228 net::ResponseCookies cookies_; // Response cookies |
134 net::HttpRequestHeaders extra_request_headers_; | 229 net::HttpRequestHeaders extra_request_headers_; |
135 scoped_refptr<net::HttpResponseHeaders> response_headers_; | 230 scoped_refptr<net::HttpResponseHeaders> response_headers_; |
136 bool was_fetched_via_proxy_; | 231 bool was_fetched_via_proxy_; |
137 net::HostPortPair socket_address_; | 232 net::HostPortPair socket_address_; |
138 | 233 |
(...skipping 20 matching lines...) Expand all Loading... | |
159 // specified by the owner URLFetcher instance, we'll give up. | 254 // specified by the owner URLFetcher instance, we'll give up. |
160 int num_retries_; | 255 int num_retries_; |
161 | 256 |
162 // True if the URLFetcher has been cancelled. | 257 // True if the URLFetcher has been cancelled. |
163 bool was_cancelled_; | 258 bool was_cancelled_; |
164 | 259 |
165 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache | 260 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache |
166 // its value to be used by OnCompletedURLRequest on the creating thread. | 261 // its value to be used by OnCompletedURLRequest on the creating thread. |
167 base::TimeTicks backoff_release_time_; | 262 base::TimeTicks backoff_release_time_; |
168 | 263 |
264 // If writing results to a file, |temp_file_writer_| will manage creation, | |
265 // writing, and destruction of that file. | |
266 scoped_ptr<TempFileWriter> temp_file_writer_; | |
267 | |
169 static base::LazyInstance<Registry> g_registry; | 268 static base::LazyInstance<Registry> g_registry; |
170 | 269 |
171 friend class URLFetcher; | 270 friend class URLFetcher; |
172 DISALLOW_COPY_AND_ASSIGN(Core); | 271 DISALLOW_COPY_AND_ASSIGN(Core); |
173 }; | 272 }; |
174 | 273 |
175 URLFetcher::Core::Registry::Registry() {} | 274 URLFetcher::Core::Registry::Registry() {} |
176 URLFetcher::Core::Registry::~Registry() {} | 275 URLFetcher::Core::Registry::~Registry() {} |
177 | 276 |
178 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { | 277 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { |
179 DCHECK(!ContainsKey(fetchers_, core)); | 278 DCHECK(!ContainsKey(fetchers_, core)); |
180 fetchers_.insert(core); | 279 fetchers_.insert(core); |
181 } | 280 } |
182 | 281 |
183 void URLFetcher::Core::Registry::RemoveURLFetcherCore(Core* core) { | 282 void URLFetcher::Core::Registry::RemoveURLFetcherCore(Core* core) { |
184 DCHECK(ContainsKey(fetchers_, core)); | 283 DCHECK(ContainsKey(fetchers_, core)); |
185 fetchers_.erase(core); | 284 fetchers_.erase(core); |
186 } | 285 } |
187 | 286 |
188 void URLFetcher::Core::Registry::CancelAll() { | 287 void URLFetcher::Core::Registry::CancelAll() { |
189 while (!fetchers_.empty()) | 288 while (!fetchers_.empty()) |
190 (*fetchers_.begin())->CancelURLRequest(); | 289 (*fetchers_.begin())->CancelURLRequest(); |
191 } | 290 } |
192 | 291 |
193 // static | 292 // static |
194 base::LazyInstance<URLFetcher::Core::Registry> | 293 base::LazyInstance<URLFetcher::Core::Registry> |
195 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); | 294 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); |
196 | 295 |
296 URLFetcher::Core::TempFileWriter::TempFileWriter( | |
297 URLFetcher::Core* core, | |
298 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) | |
299 : core_(core), | |
300 error_code_(base::PLATFORM_FILE_OK), | |
301 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | |
302 file_message_loop_proxy_(file_message_loop_proxy) { | |
303 } | |
304 | |
305 URLFetcher::Core::TempFileWriter::~TempFileWriter() { | |
306 Destroy(); | |
307 } | |
308 | |
309 void URLFetcher::Core::TempFileWriter::CreateTempFile() { | |
310 CHECK(file_message_loop_proxy_.get()); | |
311 base::FileUtilProxy::CreateTemporary( | |
312 file_message_loop_proxy_, | |
313 callback_factory_.NewCallback( | |
314 &URLFetcher::Core::TempFileWriter::DidCreateTempFile)); | |
315 } | |
316 | |
317 void URLFetcher::Core::TempFileWriter::DidCreateTempFile( | |
318 base::PlatformFileError error_code, | |
319 base::PassPlatformFile file_handle, | |
320 FilePath file_path) { | |
321 if (base::PLATFORM_FILE_OK != error_code) { | |
322 error_code_ = error_code; | |
323 core_->InformDelegateFetchIsComplete(); | |
324 return; | |
325 } | |
326 | |
327 temp_file_ = file_path; | |
328 | |
329 // The file was opened with async writes enabled. FileUtilProxy::Write() | |
330 // treats a write that returns IO_PENDING as an error, and does not inform | |
331 // the caller. We need to close and reopen the file with asyncronus writes | |
332 // disabled. | |
333 // TODO(skerner): Make FileUtilProxy::Write() play nice with async IO. | |
334 base::FileUtilProxy::Close( | |
335 file_message_loop_proxy_, | |
336 file_handle.ReleaseValue(), | |
337 callback_factory_.NewCallback( | |
338 &URLFetcher::Core::TempFileWriter::DidCloseTempFile)); | |
339 } | |
340 | |
341 void URLFetcher::Core::TempFileWriter::DidCloseTempFile( | |
342 base::PlatformFileError error_code) { | |
343 if (base::PLATFORM_FILE_OK != error_code) { | |
344 error_code_ = error_code; | |
345 core_->InformDelegateFetchIsComplete(); | |
346 return; | |
347 } | |
348 | |
349 int file_flags = | |
350 base::PLATFORM_FILE_CREATE_ALWAYS | | |
351 base::PLATFORM_FILE_WRITE | | |
352 base::PLATFORM_FILE_TEMPORARY; | |
353 | |
354 base::FileUtilProxy::CreateOrOpen( | |
355 file_message_loop_proxy_, | |
356 temp_file_, | |
357 file_flags, | |
358 callback_factory_.NewCallback( | |
359 &URLFetcher::Core::TempFileWriter::DidReopenTempFile)); | |
360 } | |
361 | |
362 void URLFetcher::Core::TempFileWriter::DidReopenTempFile( | |
363 base::PlatformFileError error_code, | |
364 base::PassPlatformFile file_handle, | |
365 bool created) { | |
366 if (base::PLATFORM_FILE_OK != error_code) { | |
367 error_code_ = error_code; | |
368 core_->InformDelegateFetchIsComplete(); | |
369 return; | |
370 } | |
371 | |
372 temp_file_handle_ = file_handle.ReleaseValue(); | |
373 total_bytes_written_ = 0; | |
374 | |
375 core_->io_message_loop_proxy_->PostTask( | |
376 FROM_HERE, | |
377 NewRunnableMethod(core_, &Core::StartURLRequestWhenAppropriate)); | |
378 } | |
379 | |
380 void URLFetcher::Core::TempFileWriter::WriteBuffer(int num_bytes) { | |
381 // Start writing to the temp file by setting the initial state | |
382 // of |pending_bytes_| and |buffer_offset_| to indicate that the | |
383 // entire buffer has not yet been written. | |
384 pending_bytes_ = num_bytes; | |
385 buffer_offset_ = 0; | |
386 ContinueWrite(base::PLATFORM_FILE_OK, 0); | |
387 } | |
388 | |
389 void URLFetcher::Core::TempFileWriter::ContinueWrite( | |
390 base::PlatformFileError error_code, | |
391 int bytes_written) { | |
392 if (base::PLATFORM_FILE_OK != error_code) { | |
393 error_code_ = error_code; | |
394 core_->InformDelegateFetchIsComplete(); | |
willchan no longer on Chromium
2011/06/21 13:55:15
This code is wrong. The delegate can only be calle
| |
395 return; | |
396 } | |
397 | |
398 total_bytes_written_ += bytes_written; | |
399 buffer_offset_ += bytes_written; | |
400 pending_bytes_ -= bytes_written; | |
401 | |
402 if (pending_bytes_ > 0) { | |
403 base::FileUtilProxy::Write( | |
404 file_message_loop_proxy_, | |
405 temp_file_handle_, | |
406 total_bytes_written_, // Append to the end | |
407 (core_->buffer_->data() + buffer_offset_), | |
408 pending_bytes_, | |
409 callback_factory_.NewCallback( | |
410 &URLFetcher::Core::TempFileWriter::ContinueWrite)); | |
411 } else { | |
412 // Finished writing core_->buffer_ to the file. Read some more. | |
413 core_->ReadResponse(); | |
414 } | |
415 } | |
416 | |
417 void URLFetcher::Core::TempFileWriter::DisownTempFile() { | |
418 // Forget about any temp file by reseting the path. | |
419 if (!temp_file_.empty()) { | |
420 base::FileUtilProxy::Close( | |
421 file_message_loop_proxy_, | |
422 temp_file_handle_, | |
423 NULL); | |
424 temp_file_ = FilePath(); | |
425 } | |
426 } | |
427 | |
428 void URLFetcher::Core::TempFileWriter::Destroy() { | |
429 if (!temp_file_.empty()) { | |
430 base::FileUtilProxy::Close( | |
431 file_message_loop_proxy_, | |
432 temp_file_handle_, | |
433 NULL); | |
434 | |
435 base::FileUtilProxy::Delete( | |
436 file_message_loop_proxy_, | |
437 temp_file_, | |
438 false, // No need to recurse, as the path is to a file. | |
439 NULL); // No callback. | |
440 } | |
441 temp_file_ = FilePath(); | |
442 } | |
443 | |
197 // static | 444 // static |
198 URLFetcher::Factory* URLFetcher::factory_ = NULL; | 445 URLFetcher::Factory* URLFetcher::factory_ = NULL; |
199 | 446 |
447 void URLFetcher::Delegate::OnURLFetchComplete( | |
448 const URLFetcher* source, | |
449 const GURL& url, | |
450 const net::URLRequestStatus& status, | |
451 int response_code, | |
452 const net::ResponseCookies& cookies, | |
453 const std::string& data) { | |
454 NOTREACHED() << "If you don't implemnt this, the no-params version " | |
455 << "should also be implemented, in which case this " | |
456 << "method won't be called..."; | |
457 } | |
458 | |
459 // TODO(skerner): This default implementation will be removed, and the | |
460 // method made pure virtual, once all users of URLFetcher are updated | |
461 // to not expect response data as a string argument. | |
462 void URLFetcher::Delegate::OnURLFetchComplete(const URLFetcher* source) { | |
463 // A delegate that did not override this method is using the old | |
464 // parameter list to OnURLFetchComplete(). If a user asked to save | |
465 // the response to a file, they must use the new parameter list, | |
466 // in which case we can not get here. | |
467 std::string data; | |
468 CHECK(source->GetResponseAsString(&data)); | |
469 | |
470 // To avoid updating all callers, thunk to the old prototype for now. | |
471 OnURLFetchComplete(source, | |
472 source->url(), | |
473 source->status(), | |
474 source->response_code(), | |
475 source->cookies(), | |
476 data); | |
477 } | |
478 | |
200 // static | 479 // static |
201 bool URLFetcher::g_interception_enabled = false; | 480 bool URLFetcher::g_interception_enabled = false; |
202 | 481 |
203 URLFetcher::URLFetcher(const GURL& url, | 482 URLFetcher::URLFetcher(const GURL& url, |
204 RequestType request_type, | 483 RequestType request_type, |
205 Delegate* d) | 484 Delegate* d) |
206 : ALLOW_THIS_IN_INITIALIZER_LIST( | 485 : ALLOW_THIS_IN_INITIALIZER_LIST( |
207 core_(new Core(this, url, request_type, d))), | 486 core_(new Core(this, url, request_type, d))), |
208 automatically_retry_on_5xx_(true), | 487 automatically_retry_on_5xx_(true), |
209 max_retries_(0) { | 488 max_retries_(0), |
489 response_destination_(STRING) { | |
210 } | 490 } |
211 | 491 |
212 URLFetcher::~URLFetcher() { | 492 URLFetcher::~URLFetcher() { |
213 core_->Stop(); | 493 core_->Stop(); |
214 } | 494 } |
215 | 495 |
216 // static | 496 // static |
217 URLFetcher* URLFetcher::Create(int id, const GURL& url, | 497 URLFetcher* URLFetcher::Create(int id, const GURL& url, |
218 RequestType request_type, Delegate* d) { | 498 RequestType request_type, Delegate* d) { |
219 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : | 499 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : |
220 new URLFetcher(url, request_type, d); | 500 new URLFetcher(url, request_type, d); |
221 } | 501 } |
222 | 502 |
223 URLFetcher::Core::Core(URLFetcher* fetcher, | 503 URLFetcher::Core::Core(URLFetcher* fetcher, |
224 const GURL& original_url, | 504 const GURL& original_url, |
225 RequestType request_type, | 505 RequestType request_type, |
226 URLFetcher::Delegate* d) | 506 URLFetcher::Delegate* d) |
227 : fetcher_(fetcher), | 507 : fetcher_(fetcher), |
228 original_url_(original_url), | 508 original_url_(original_url), |
229 request_type_(request_type), | 509 request_type_(request_type), |
230 delegate_(d), | 510 delegate_(d), |
231 delegate_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()), | 511 delegate_loop_proxy_( |
512 base::MessageLoopProxy::CreateForCurrentThread()), | |
232 request_(NULL), | 513 request_(NULL), |
233 load_flags_(net::LOAD_NORMAL), | 514 load_flags_(net::LOAD_NORMAL), |
234 response_code_(-1), | 515 response_code_(URLFetcher::kInvalidHttpResponseCode), |
235 buffer_(new net::IOBuffer(kBufferSize)), | 516 buffer_(new net::IOBuffer(kBufferSize)), |
236 is_chunked_upload_(false), | 517 is_chunked_upload_(false), |
237 num_retries_(0), | 518 num_retries_(0), |
238 was_cancelled_(false) { | 519 was_cancelled_(false) { |
239 } | 520 } |
240 | 521 |
241 URLFetcher::Core::~Core() { | 522 URLFetcher::Core::~Core() { |
242 // |request_| should be NULL. If not, it's unsafe to delete it here since we | 523 // |request_| should be NULL. If not, it's unsafe to delete it here since we |
243 // may not be on the IO thread. | 524 // may not be on the IO thread. |
244 DCHECK(!request_.get()); | 525 DCHECK(!request_.get()); |
245 } | 526 } |
246 | 527 |
247 void URLFetcher::Core::Start() { | 528 void URLFetcher::Core::Start() { |
248 DCHECK(delegate_loop_proxy_); | 529 DCHECK(delegate_loop_proxy_); |
249 CHECK(request_context_getter_) << "We need an URLRequestContext!"; | 530 CHECK(request_context_getter_) << "We need an URLRequestContext!"; |
250 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); | 531 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); |
251 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; | 532 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; |
252 | 533 |
253 io_message_loop_proxy_->PostTask( | 534 switch (fetcher_->response_destination_) { |
254 FROM_HERE, | 535 case STRING: |
255 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); | 536 io_message_loop_proxy_->PostTask( |
537 FROM_HERE, | |
538 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); | |
539 break; | |
540 | |
541 case TEMP_FILE: | |
542 CHECK(file_message_loop_proxy_.get()) | |
543 << "Need to set the file message loop proxy."; | |
544 temp_file_writer_.reset( | |
545 new TempFileWriter(this, file_message_loop_proxy_)); | |
546 // CreateTempFile() will invoke Core::StartURLRequestWhenAppropriate | |
547 // once the file is created. | |
548 temp_file_writer_->CreateTempFile(); | |
549 break; | |
550 | |
551 default: | |
552 NOTREACHED(); | |
553 } | |
256 } | 554 } |
257 | 555 |
258 void URLFetcher::Core::Stop() { | 556 void URLFetcher::Core::Stop() { |
259 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); | 557 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); |
260 delegate_ = NULL; | 558 delegate_ = NULL; |
261 fetcher_ = NULL; | 559 fetcher_ = NULL; |
262 if (io_message_loop_proxy_.get()) { | 560 if (io_message_loop_proxy_.get()) { |
263 io_message_loop_proxy_->PostTask( | 561 io_message_loop_proxy_->PostTask( |
264 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); | 562 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); |
265 } | 563 } |
(...skipping 14 matching lines...) Expand all Loading... | |
280 void URLFetcher::Core::OnResponseStarted(net::URLRequest* request) { | 578 void URLFetcher::Core::OnResponseStarted(net::URLRequest* request) { |
281 DCHECK_EQ(request, request_.get()); | 579 DCHECK_EQ(request, request_.get()); |
282 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 580 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
283 if (request_->status().is_success()) { | 581 if (request_->status().is_success()) { |
284 response_code_ = request_->GetResponseCode(); | 582 response_code_ = request_->GetResponseCode(); |
285 response_headers_ = request_->response_headers(); | 583 response_headers_ = request_->response_headers(); |
286 socket_address_ = request_->GetSocketAddress(); | 584 socket_address_ = request_->GetSocketAddress(); |
287 was_fetched_via_proxy_ = request_->was_fetched_via_proxy(); | 585 was_fetched_via_proxy_ = request_->was_fetched_via_proxy(); |
288 } | 586 } |
289 | 587 |
290 int bytes_read = 0; | 588 ReadResponse(); |
291 // Some servers may treat HEAD requests as GET requests. To free up the | |
292 // network connection as soon as possible, signal that the request has | |
293 // completed immediately, without trying to read any data back (all we care | |
294 // about is the response code and headers, which we already have). | |
295 if (request_->status().is_success() && (request_type_ != HEAD)) | |
296 request_->Read(buffer_, kBufferSize, &bytes_read); | |
297 OnReadCompleted(request_.get(), bytes_read); | |
298 } | 589 } |
299 | 590 |
300 void URLFetcher::Core::CompleteAddingUploadDataChunk( | 591 void URLFetcher::Core::CompleteAddingUploadDataChunk( |
301 const std::string& content, bool is_last_chunk) { | 592 const std::string& content, bool is_last_chunk) { |
302 DCHECK(is_chunked_upload_); | 593 DCHECK(is_chunked_upload_); |
303 DCHECK(request_.get()); | 594 DCHECK(request_.get()); |
304 DCHECK(!content.empty()); | 595 DCHECK(!content.empty()); |
305 request_->AppendChunkToUpload(content.data(), | 596 request_->AppendChunkToUpload(content.data(), |
306 static_cast<int>(content.length()), | 597 static_cast<int>(content.length()), |
307 is_last_chunk); | 598 is_last_chunk); |
308 } | 599 } |
309 | 600 |
310 void URLFetcher::Core::AppendChunkToUpload(const std::string& content, | 601 void URLFetcher::Core::AppendChunkToUpload(const std::string& content, |
311 bool is_last_chunk) { | 602 bool is_last_chunk) { |
312 DCHECK(delegate_loop_proxy_); | 603 DCHECK(delegate_loop_proxy_); |
313 CHECK(io_message_loop_proxy_.get()); | 604 CHECK(io_message_loop_proxy_.get()); |
314 io_message_loop_proxy_->PostTask( | 605 io_message_loop_proxy_->PostTask( |
315 FROM_HERE, | 606 FROM_HERE, |
316 NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content, | 607 NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content, |
317 is_last_chunk)); | 608 is_last_chunk)); |
318 } | 609 } |
319 | 610 |
611 // Return true if the write was done and reading may continue. | |
612 // Return false if the write is pending, and the next read will | |
613 // be done later. | |
614 bool URLFetcher::Core::WriteBuffer(int num_bytes) { | |
615 bool write_complete = false; | |
616 switch (fetcher_->response_destination_) { | |
617 case STRING: | |
618 data_.append(buffer_->data(), num_bytes); | |
619 write_complete = true; | |
620 break; | |
621 | |
622 case TEMP_FILE: | |
623 temp_file_writer_->WriteBuffer(num_bytes); | |
624 // WriteBuffer() sends a request the file thread. | |
625 // The write is not done yet. | |
626 write_complete = false; | |
627 break; | |
628 | |
629 default: | |
630 NOTREACHED(); | |
631 } | |
632 return write_complete; | |
633 } | |
634 | |
320 void URLFetcher::Core::OnReadCompleted(net::URLRequest* request, | 635 void URLFetcher::Core::OnReadCompleted(net::URLRequest* request, |
321 int bytes_read) { | 636 int bytes_read) { |
322 DCHECK(request == request_); | 637 DCHECK(request == request_); |
323 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 638 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
324 | 639 |
325 url_ = request->url(); | 640 url_ = request->url(); |
326 url_throttler_entry_ = | 641 url_throttler_entry_ = |
327 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); | 642 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); |
328 | 643 |
644 bool waiting_on_write = false; | |
329 do { | 645 do { |
330 if (!request_->status().is_success() || bytes_read <= 0) | 646 if (!request_->status().is_success() || bytes_read <= 0) |
331 break; | 647 break; |
332 data_.append(buffer_->data(), bytes_read); | 648 |
649 if (!WriteBuffer(bytes_read)) { | |
650 // If WriteBuffer() returns false, we have a pending write to | |
651 // wait on before reading further. | |
652 waiting_on_write = true; | |
653 break; | |
654 } | |
333 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); | 655 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); |
334 | 656 |
335 if (request_->status().is_success()) | 657 if (request_->status().is_success()) |
336 request_->GetResponseCookies(&cookies_); | 658 request_->GetResponseCookies(&cookies_); |
337 | 659 |
338 // See comments re: HEAD requests in OnResponseStarted(). | 660 // See comments re: HEAD requests in ReadResponse(). |
339 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { | 661 if ((!request_->status().is_io_pending() && !waiting_on_write) || |
662 (request_type_ == HEAD)) { | |
340 backoff_release_time_ = GetBackoffReleaseTime(); | 663 backoff_release_time_ = GetBackoffReleaseTime(); |
341 | 664 |
342 bool posted = delegate_loop_proxy_->PostTask( | 665 bool posted = delegate_loop_proxy_->PostTask( |
343 FROM_HERE, | 666 FROM_HERE, |
344 NewRunnableMethod(this, | 667 NewRunnableMethod(this, |
345 &Core::OnCompletedURLRequest, | 668 &Core::OnCompletedURLRequest, |
346 request_->status())); | 669 request_->status())); |
347 // If the delegate message loop does not exist any more, then the delegate | 670 // If the delegate message loop does not exist any more, then the delegate |
348 // should be gone too. | 671 // should be gone too. |
349 DCHECK(posted || !delegate_); | 672 DCHECK(posted || !delegate_); |
350 ReleaseRequest(); | 673 ReleaseRequest(); |
351 } | 674 } |
352 } | 675 } |
353 | 676 |
677 void URLFetcher::Core::ReadResponse() { | |
678 // Some servers may treat HEAD requests as GET requests. To free up the | |
679 // network connection as soon as possible, signal that the request has | |
680 // completed immediately, without trying to read any data back (all we care | |
681 // about is the response code and headers, which we already have). | |
682 int bytes_read = 0; | |
683 if (request_->status().is_success() && (request_type_ != HEAD)) | |
684 request_->Read(buffer_, kBufferSize, &bytes_read); | |
685 OnReadCompleted(request_.get(), bytes_read); | |
686 } | |
687 | |
354 void URLFetcher::Core::StartURLRequest() { | 688 void URLFetcher::Core::StartURLRequest() { |
355 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 689 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
356 | 690 |
357 if (was_cancelled_) { | 691 if (was_cancelled_) { |
358 // Since StartURLRequest() is posted as a *delayed* task, it may | 692 // Since StartURLRequest() is posted as a *delayed* task, it may |
359 // run after the URLFetcher was already stopped. | 693 // run after the URLFetcher was already stopped. |
360 return; | 694 return; |
361 } | 695 } |
362 | 696 |
363 CHECK(request_context_getter_); | 697 CHECK(request_context_getter_); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
399 default: | 733 default: |
400 NOTREACHED(); | 734 NOTREACHED(); |
401 } | 735 } |
402 | 736 |
403 if (!extra_request_headers_.IsEmpty()) | 737 if (!extra_request_headers_.IsEmpty()) |
404 request_->SetExtraRequestHeaders(extra_request_headers_); | 738 request_->SetExtraRequestHeaders(extra_request_headers_); |
405 | 739 |
406 // There might be data left over from a previous request attempt. | 740 // There might be data left over from a previous request attempt. |
407 data_.clear(); | 741 data_.clear(); |
408 | 742 |
743 // If we are writing the response to a file, the only caller | |
744 // of this function should have created it and not written yet. | |
745 CHECK(!temp_file_writer_.get() || | |
746 temp_file_writer_->total_bytes_written() == 0); | |
747 | |
409 request_->Start(); | 748 request_->Start(); |
410 } | 749 } |
411 | 750 |
412 void URLFetcher::Core::StartURLRequestWhenAppropriate() { | 751 void URLFetcher::Core::StartURLRequestWhenAppropriate() { |
413 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 752 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
414 | 753 |
415 if (was_cancelled_) | 754 if (was_cancelled_) |
416 return; | 755 return; |
417 | 756 |
418 if (original_url_throttler_entry_ == NULL) { | 757 if (original_url_throttler_entry_ == NULL) { |
(...skipping 20 matching lines...) Expand all Loading... | |
439 if (request_.get()) { | 778 if (request_.get()) { |
440 request_->Cancel(); | 779 request_->Cancel(); |
441 ReleaseRequest(); | 780 ReleaseRequest(); |
442 } | 781 } |
443 // Release the reference to the request context. There could be multiple | 782 // Release the reference to the request context. There could be multiple |
444 // references to URLFetcher::Core at this point so it may take a while to | 783 // references to URLFetcher::Core at this point so it may take a while to |
445 // delete the object, but we cannot delay the destruction of the request | 784 // delete the object, but we cannot delay the destruction of the request |
446 // context. | 785 // context. |
447 request_context_getter_ = NULL; | 786 request_context_getter_ = NULL; |
448 was_cancelled_ = true; | 787 was_cancelled_ = true; |
788 temp_file_writer_.reset(); | |
449 } | 789 } |
450 | 790 |
451 void URLFetcher::Core::OnCompletedURLRequest( | 791 void URLFetcher::Core::OnCompletedURLRequest( |
452 const net::URLRequestStatus& status) { | 792 const net::URLRequestStatus& status) { |
453 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); | 793 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); |
454 | 794 |
795 // Save the status so that delegates can read it. | |
796 status_ = status; | |
797 | |
455 // Checks the response from server. | 798 // Checks the response from server. |
456 if (response_code_ >= 500 || | 799 if (response_code_ >= 500 || |
457 status.os_error() == net::ERR_TEMPORARILY_THROTTLED) { | 800 status.os_error() == net::ERR_TEMPORARILY_THROTTLED) { |
458 // When encountering a server error, we will send the request again | 801 // When encountering a server error, we will send the request again |
459 // after backoff time. | 802 // after backoff time. |
460 ++num_retries_; | 803 ++num_retries_; |
461 // Restarts the request if we still need to notify the delegate. | 804 // Restarts the request if we still need to notify the delegate. |
462 if (delegate_) { | 805 if (delegate_) { |
463 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); | 806 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); |
464 if (fetcher_->backoff_delay_ < base::TimeDelta()) | 807 if (fetcher_->backoff_delay_ < base::TimeDelta()) |
465 fetcher_->backoff_delay_ = base::TimeDelta(); | 808 fetcher_->backoff_delay_ = base::TimeDelta(); |
466 | 809 |
467 if (fetcher_->automatically_retry_on_5xx_ && | 810 if (fetcher_->automatically_retry_on_5xx_ && |
468 num_retries_ <= fetcher_->max_retries()) { | 811 num_retries_ <= fetcher_->max_retries()) { |
469 io_message_loop_proxy_->PostTask( | 812 io_message_loop_proxy_->PostTask( |
470 FROM_HERE, | 813 FROM_HERE, |
471 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); | 814 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); |
472 } else { | 815 } else { |
473 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 816 InformDelegateFetchIsComplete(); |
474 cookies_, data_); | |
475 } | 817 } |
476 } | 818 } |
477 } else { | 819 } else { |
478 if (delegate_) { | 820 if (delegate_) { |
479 fetcher_->backoff_delay_ = base::TimeDelta(); | 821 fetcher_->backoff_delay_ = base::TimeDelta(); |
480 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 822 InformDelegateFetchIsComplete(); |
481 cookies_, data_); | |
482 } | 823 } |
483 } | 824 } |
484 } | 825 } |
485 | 826 |
827 void URLFetcher::Core::InformDelegateFetchIsComplete() { | |
828 delegate_->OnURLFetchComplete(fetcher_); | |
829 } | |
830 | |
486 void URLFetcher::Core::NotifyMalformedContent() { | 831 void URLFetcher::Core::NotifyMalformedContent() { |
487 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 832 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
488 if (url_throttler_entry_ != NULL) | 833 if (url_throttler_entry_ != NULL) |
489 url_throttler_entry_->ReceivedContentWasMalformed(); | 834 url_throttler_entry_->ReceivedContentWasMalformed(); |
490 } | 835 } |
491 | 836 |
492 void URLFetcher::Core::ReleaseRequest() { | 837 void URLFetcher::Core::ReleaseRequest() { |
493 request_.reset(); | 838 request_.reset(); |
494 g_registry.Get().RemoveURLFetcherCore(this); | 839 g_registry.Get().RemoveURLFetcherCore(this); |
495 } | 840 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 | 902 |
558 void URLFetcher::set_request_context( | 903 void URLFetcher::set_request_context( |
559 net::URLRequestContextGetter* request_context_getter) { | 904 net::URLRequestContextGetter* request_context_getter) { |
560 core_->request_context_getter_ = request_context_getter; | 905 core_->request_context_getter_ = request_context_getter; |
561 } | 906 } |
562 | 907 |
563 void URLFetcher::set_automatically_retry_on_5xx(bool retry) { | 908 void URLFetcher::set_automatically_retry_on_5xx(bool retry) { |
564 automatically_retry_on_5xx_ = retry; | 909 automatically_retry_on_5xx_ = retry; |
565 } | 910 } |
566 | 911 |
912 void URLFetcher::SaveResponseToTemporaryFile( | |
913 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) { | |
914 core_->file_message_loop_proxy_ = file_message_loop_proxy; | |
915 response_destination_ = TEMP_FILE; | |
916 } | |
917 | |
567 net::HttpResponseHeaders* URLFetcher::response_headers() const { | 918 net::HttpResponseHeaders* URLFetcher::response_headers() const { |
568 return core_->response_headers_; | 919 return core_->response_headers_; |
569 } | 920 } |
570 | 921 |
571 // TODO(panayiotis): socket_address_ is written in the IO thread, | 922 // TODO(panayiotis): socket_address_ is written in the IO thread, |
572 // if this is accessed in the UI thread, this could result in a race. | 923 // if this is accessed in the UI thread, this could result in a race. |
573 // Same for response_headers_ above and was_fetched_via_proxy_ below. | 924 // Same for response_headers_ above and was_fetched_via_proxy_ below. |
574 net::HostPortPair URLFetcher::socket_address() const { | 925 net::HostPortPair URLFetcher::socket_address() const { |
575 return core_->socket_address_; | 926 return core_->socket_address_; |
576 } | 927 } |
577 | 928 |
578 bool URLFetcher::was_fetched_via_proxy() const { | 929 bool URLFetcher::was_fetched_via_proxy() const { |
579 return core_->was_fetched_via_proxy_; | 930 return core_->was_fetched_via_proxy_; |
580 } | 931 } |
581 | 932 |
582 void URLFetcher::Start() { | 933 void URLFetcher::Start() { |
583 core_->Start(); | 934 core_->Start(); |
584 } | 935 } |
585 | 936 |
586 const GURL& URLFetcher::url() const { | 937 const GURL& URLFetcher::url() const { |
587 return core_->url_; | 938 return core_->url_; |
588 } | 939 } |
589 | 940 |
941 const net::URLRequestStatus& URLFetcher::status() const { | |
942 return core_->status_; | |
943 } | |
944 | |
945 int URLFetcher::response_code() const { | |
946 return core_->response_code_; | |
947 } | |
948 | |
949 const net::ResponseCookies& URLFetcher::cookies() const { | |
950 return core_->cookies_; | |
951 } | |
952 | |
953 bool URLFetcher::FileErrorOccurred( | |
954 base::PlatformFileError* out_error_code) const { | |
955 | |
956 // Can't have a file error if no file is being created or written to. | |
957 if (!core_->temp_file_writer_.get()) { | |
958 return false; | |
959 } | |
960 | |
961 base::PlatformFileError error_code = core_->temp_file_writer_->error_code(); | |
962 if (error_code == base::PLATFORM_FILE_OK) | |
963 return false; | |
964 | |
965 *out_error_code = error_code; | |
966 return true; | |
967 } | |
968 | |
590 void URLFetcher::ReceivedContentWasMalformed() { | 969 void URLFetcher::ReceivedContentWasMalformed() { |
591 core_->ReceivedContentWasMalformed(); | 970 core_->ReceivedContentWasMalformed(); |
592 } | 971 } |
593 | 972 |
973 bool URLFetcher::GetResponseAsString(std::string* out_response_string) const { | |
974 if (response_destination_ != STRING) | |
975 return false; | |
976 | |
977 *out_response_string = core_->data_; | |
978 return true; | |
979 } | |
980 | |
981 bool URLFetcher::GetResponseAsFilePath(bool take_ownership, | |
982 FilePath* out_response_path) const { | |
983 if (response_destination_ != TEMP_FILE || !core_->temp_file_writer_.get()) | |
984 return false; | |
985 | |
986 *out_response_path = core_->temp_file_writer_->temp_file(); | |
987 | |
988 if (take_ownership) | |
989 core_->temp_file_writer_->DisownTempFile(); | |
990 | |
991 return true; | |
992 } | |
993 | |
594 // static | 994 // static |
595 void URLFetcher::CancelAll() { | 995 void URLFetcher::CancelAll() { |
596 Core::CancelAll(); | 996 Core::CancelAll(); |
597 } | 997 } |
598 | 998 |
599 // static | 999 // static |
600 int URLFetcher::GetNumFetcherCores() { | 1000 int URLFetcher::GetNumFetcherCores() { |
601 return Core::g_registry.Get().size(); | 1001 return Core::g_registry.Get().size(); |
602 } | 1002 } |
603 | 1003 |
604 URLFetcher::Delegate* URLFetcher::delegate() const { | 1004 URLFetcher::Delegate* URLFetcher::delegate() const { |
605 return core_->delegate(); | 1005 return core_->delegate(); |
606 } | 1006 } |
OLD | NEW |