| 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 DidCreateTemporaryFile(base::PlatformFileError error_code, |
| 106 base::PassPlatformFile file_handle, |
| 107 FilePath file_path); |
| 108 |
| 109 // Record |num_bytes_| response bytes in |core_->buffer_| to the file. |
| 110 void WriteBuffer(int num_bytes); |
| 111 |
| 112 // Called when a write has been done. Continues writing if there are |
| 113 // any more bytes to write. Otherwise, initiates a read in core_. |
| 114 void ContinueWrite(base::PlatformFileError error_code, |
| 115 int bytes_written); |
| 116 |
| 117 // Drop ownership of the file at path |temp_file_|. This class |
| 118 // will not delete it or write to it again. |
| 119 void DisownTempFile(); |
| 120 |
| 121 // Remove any file created. |
| 122 void Destroy(); |
| 123 |
| 124 const FilePath& temp_file() const { return temp_file_; } |
| 125 int64 total_bytes_written() { return total_bytes_written_; } |
| 126 base::PlatformFileError error_code() const { return error_code_; } |
| 127 |
| 128 private: |
| 129 // The URLFetcher::Core which instantiated this class. |
| 130 URLFetcher::Core* core_; |
| 131 |
| 132 // The last error encountered on a file operation. base::PLATFORM_FILE_OK |
| 133 // if no error occurred. |
| 134 base::PlatformFileError error_code_; |
| 135 |
| 136 // Callbacks are created for use with base::FileUtilProxy. |
| 137 base::ScopedCallbackFactory<URLFetcher::Core::TempFileWriter> |
| 138 callback_factory_; |
| 139 |
| 140 // Message loop on which file opperations should happen. |
| 141 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_; |
| 142 |
| 143 // Path to the temporary file. This path is empty when there |
| 144 // is no temp file. |
| 145 FilePath temp_file_; |
| 146 |
| 147 // Handle to the temp file. |
| 148 base::PlatformFile temp_file_handle_; |
| 149 |
| 150 // We always append to the file. Track the total number of bytes |
| 151 // written, so that writes know the offset to give. |
| 152 int64 total_bytes_written_; |
| 153 |
| 154 // How many bytes did the last Write() try to write? Needed so |
| 155 // that if not all the bytes get written on a Write(), we can |
| 156 // call Write() again with the rest. |
| 157 int pending_bytes_; |
| 158 |
| 159 // When writing, how many bytes from the buffer have been successfully |
| 160 // written so far? |
| 161 int buffer_offset_; |
| 162 }; |
| 163 |
| 89 virtual ~Core(); | 164 virtual ~Core(); |
| 90 | 165 |
| 91 // Wrapper functions that allow us to ensure actions happen on the right | 166 // Wrapper functions that allow us to ensure actions happen on the right |
| 92 // thread. | 167 // thread. |
| 93 void StartURLRequest(); | 168 void StartURLRequest(); |
| 94 void StartURLRequestWhenAppropriate(); | 169 void StartURLRequestWhenAppropriate(); |
| 95 void CancelURLRequest(); | 170 void CancelURLRequest(); |
| 96 void OnCompletedURLRequest(const net::URLRequestStatus& status); | 171 void OnCompletedURLRequest(const net::URLRequestStatus& status); |
| 172 void InformDelegateFetchIsComplete(); |
| 97 void NotifyMalformedContent(); | 173 void NotifyMalformedContent(); |
| 98 | 174 |
| 99 // Deletes the request, removes it from the registry, and removes the | 175 // Deletes the request, removes it from the registry, and removes the |
| 100 // destruction observer. | 176 // destruction observer. |
| 101 void ReleaseRequest(); | 177 void ReleaseRequest(); |
| 102 | 178 |
| 103 // Returns the max value of exponential back-off release time for | 179 // Returns the max value of exponential back-off release time for |
| 104 // |original_url_| and |url_|. | 180 // |original_url_| and |url_|. |
| 105 base::TimeTicks GetBackoffReleaseTime(); | 181 base::TimeTicks GetBackoffReleaseTime(); |
| 106 | 182 |
| 107 void CompleteAddingUploadDataChunk(const std::string& data, | 183 void CompleteAddingUploadDataChunk(const std::string& data, |
| 108 bool is_last_chunk); | 184 bool is_last_chunk); |
| 109 | 185 |
| 110 // Adds a block of data to be uploaded in a POST body. This can only be called | 186 // Adds a block of data to be uploaded in a POST body. This can only be |
| 111 // after Start(). | 187 // called after Start(). |
| 112 void AppendChunkToUpload(const std::string& data, bool is_last_chunk); | 188 void AppendChunkToUpload(const std::string& data, bool is_last_chunk); |
| 113 | 189 |
| 190 // Store the response bytes in |buffer_| in the container indicated by |
| 191 // |fetcher_->response_destination_|. Return true if the write has been |
| 192 // done, and another read can overwrite |buffer_|. If this function |
| 193 // returns false, it will post a task that will read more bytes once the |
| 194 // write is complete. |
| 195 bool WriteBuffer(int num_bytes); |
| 196 |
| 197 // Read response bytes from the request. |
| 198 void ReadResponse(); |
| 199 |
| 114 URLFetcher* fetcher_; // Corresponding fetcher object | 200 URLFetcher* fetcher_; // Corresponding fetcher object |
| 115 GURL original_url_; // The URL we were asked to fetch | 201 GURL original_url_; // The URL we were asked to fetch |
| 116 GURL url_; // The URL we eventually wound up at | 202 GURL url_; // The URL we eventually wound up at |
| 117 RequestType request_type_; // What type of request is this? | 203 RequestType request_type_; // What type of request is this? |
| 204 net::URLRequestStatus status_; // Status of the request |
| 118 URLFetcher::Delegate* delegate_; // Object to notify on completion | 205 URLFetcher::Delegate* delegate_; // Object to notify on completion |
| 119 scoped_refptr<base::MessageLoopProxy> delegate_loop_proxy_; | 206 scoped_refptr<base::MessageLoopProxy> delegate_loop_proxy_; |
| 120 // Message loop proxy of the creating | 207 // Message loop proxy of the creating |
| 121 // thread. | 208 // thread. |
| 122 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; | 209 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
| 123 // The message loop proxy for the thread | 210 // The message loop proxy for the thread |
| 124 // on which the request IO happens. | 211 // on which the request IO happens. |
| 212 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy_; |
| 213 // The message loop proxy for the thread |
| 214 // on which file access happens. |
| 125 scoped_ptr<net::URLRequest> request_; // The actual request this wraps | 215 scoped_ptr<net::URLRequest> request_; // The actual request this wraps |
| 126 int load_flags_; // Flags for the load operation | 216 int load_flags_; // Flags for the load operation |
| 127 int response_code_; // HTTP status code for the request | 217 int response_code_; // HTTP status code for the request |
| 128 std::string data_; // Results of the request | 218 std::string data_; // Results of the request, when we are |
| 219 // storing the response as a string. |
| 129 scoped_refptr<net::IOBuffer> buffer_; | 220 scoped_refptr<net::IOBuffer> buffer_; |
| 130 // Read buffer | 221 // Read buffer |
| 131 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | 222 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
| 132 // Cookie/cache info for the request | 223 // Cookie/cache info for the request |
| 133 net::ResponseCookies cookies_; // Response cookies | 224 net::ResponseCookies cookies_; // Response cookies |
| 134 net::HttpRequestHeaders extra_request_headers_; | 225 net::HttpRequestHeaders extra_request_headers_; |
| 135 scoped_refptr<net::HttpResponseHeaders> response_headers_; | 226 scoped_refptr<net::HttpResponseHeaders> response_headers_; |
| 136 bool was_fetched_via_proxy_; | 227 bool was_fetched_via_proxy_; |
| 137 net::HostPortPair socket_address_; | 228 net::HostPortPair socket_address_; |
| 138 | 229 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 159 // specified by the owner URLFetcher instance, we'll give up. | 250 // specified by the owner URLFetcher instance, we'll give up. |
| 160 int num_retries_; | 251 int num_retries_; |
| 161 | 252 |
| 162 // True if the URLFetcher has been cancelled. | 253 // True if the URLFetcher has been cancelled. |
| 163 bool was_cancelled_; | 254 bool was_cancelled_; |
| 164 | 255 |
| 165 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache | 256 // Since GetBackoffReleaseTime() can only be called on the IO thread, we cache |
| 166 // its value to be used by OnCompletedURLRequest on the creating thread. | 257 // its value to be used by OnCompletedURLRequest on the creating thread. |
| 167 base::TimeTicks backoff_release_time_; | 258 base::TimeTicks backoff_release_time_; |
| 168 | 259 |
| 260 // If writing results to a file, |temp_file_writer_| will manage creation, |
| 261 // writing, and destruction of that file. |
| 262 scoped_ptr<TempFileWriter> temp_file_writer_; |
| 263 |
| 169 static base::LazyInstance<Registry> g_registry; | 264 static base::LazyInstance<Registry> g_registry; |
| 170 | 265 |
| 171 friend class URLFetcher; | 266 friend class URLFetcher; |
| 172 DISALLOW_COPY_AND_ASSIGN(Core); | 267 DISALLOW_COPY_AND_ASSIGN(Core); |
| 173 }; | 268 }; |
| 174 | 269 |
| 175 URLFetcher::Core::Registry::Registry() {} | 270 URLFetcher::Core::Registry::Registry() {} |
| 176 URLFetcher::Core::Registry::~Registry() {} | 271 URLFetcher::Core::Registry::~Registry() {} |
| 177 | 272 |
| 178 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { | 273 void URLFetcher::Core::Registry::AddURLFetcherCore(Core* core) { |
| 179 DCHECK(!ContainsKey(fetchers_, core)); | 274 DCHECK(!ContainsKey(fetchers_, core)); |
| 180 fetchers_.insert(core); | 275 fetchers_.insert(core); |
| 181 } | 276 } |
| 182 | 277 |
| 183 void URLFetcher::Core::Registry::RemoveURLFetcherCore(Core* core) { | 278 void URLFetcher::Core::Registry::RemoveURLFetcherCore(Core* core) { |
| 184 DCHECK(ContainsKey(fetchers_, core)); | 279 DCHECK(ContainsKey(fetchers_, core)); |
| 185 fetchers_.erase(core); | 280 fetchers_.erase(core); |
| 186 } | 281 } |
| 187 | 282 |
| 188 void URLFetcher::Core::Registry::CancelAll() { | 283 void URLFetcher::Core::Registry::CancelAll() { |
| 189 while (!fetchers_.empty()) | 284 while (!fetchers_.empty()) |
| 190 (*fetchers_.begin())->CancelURLRequest(); | 285 (*fetchers_.begin())->CancelURLRequest(); |
| 191 } | 286 } |
| 192 | 287 |
| 193 // static | 288 // static |
| 194 base::LazyInstance<URLFetcher::Core::Registry> | 289 base::LazyInstance<URLFetcher::Core::Registry> |
| 195 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); | 290 URLFetcher::Core::g_registry(base::LINKER_INITIALIZED); |
| 196 | 291 |
| 292 URLFetcher::Core::TempFileWriter::TempFileWriter( |
| 293 URLFetcher::Core* core, |
| 294 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) |
| 295 : core_(core), |
| 296 error_code_(base::PLATFORM_FILE_OK), |
| 297 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 298 file_message_loop_proxy_(file_message_loop_proxy) { |
| 299 } |
| 300 |
| 301 URLFetcher::Core::TempFileWriter::~TempFileWriter() { |
| 302 Destroy(); |
| 303 } |
| 304 |
| 305 void URLFetcher::Core::TempFileWriter::CreateTempFile() { |
| 306 CHECK(file_message_loop_proxy_.get()); |
| 307 base::FileUtilProxy::CreateTemporary( |
| 308 file_message_loop_proxy_, |
| 309 callback_factory_.NewCallback( |
| 310 &URLFetcher::Core::TempFileWriter::DidCreateTemporaryFile)); |
| 311 } |
| 312 |
| 313 void URLFetcher::Core::TempFileWriter::DidCreateTemporaryFile( |
| 314 base::PlatformFileError error_code, |
| 315 base::PassPlatformFile file_handle, |
| 316 FilePath file_path) { |
| 317 if (base::PLATFORM_FILE_OK != error_code) { |
| 318 error_code_ = error_code; |
| 319 core_->InformDelegateFetchIsComplete(); |
| 320 return; |
| 321 } |
| 322 |
| 323 temp_file_handle_ = file_handle.ReleaseValue(); |
| 324 temp_file_ = file_path; |
| 325 total_bytes_written_ = 0; |
| 326 |
| 327 core_->io_message_loop_proxy_->PostTask( |
| 328 FROM_HERE, |
| 329 NewRunnableMethod(core_, &Core::StartURLRequestWhenAppropriate)); |
| 330 } |
| 331 |
| 332 void URLFetcher::Core::TempFileWriter::WriteBuffer(int num_bytes) { |
| 333 // Start writing to the temp file by setting the initial state |
| 334 // of |pending_bytes_| and |buffer_offset_| to indicate that the |
| 335 // entire buffer has not yet been written. |
| 336 pending_bytes_ = num_bytes; |
| 337 buffer_offset_ = 0; |
| 338 ContinueWrite(base::PLATFORM_FILE_OK, 0); |
| 339 } |
| 340 |
| 341 void URLFetcher::Core::TempFileWriter::ContinueWrite( |
| 342 base::PlatformFileError error_code, |
| 343 int bytes_written) { |
| 344 if (base::PLATFORM_FILE_OK != error_code) { |
| 345 error_code_ = error_code; |
| 346 core_->InformDelegateFetchIsComplete(); |
| 347 return; |
| 348 } |
| 349 |
| 350 total_bytes_written_ += bytes_written; |
| 351 buffer_offset_ += bytes_written; |
| 352 pending_bytes_ -= bytes_written; |
| 353 |
| 354 if (pending_bytes_ > 0) { |
| 355 base::FileUtilProxy::Write( |
| 356 file_message_loop_proxy_, |
| 357 temp_file_handle_, |
| 358 total_bytes_written_, // Append to the end |
| 359 (core_->buffer_->data() + buffer_offset_), |
| 360 pending_bytes_, |
| 361 callback_factory_.NewCallback( |
| 362 &URLFetcher::Core::TempFileWriter::ContinueWrite)); |
| 363 } else { |
| 364 // Finished writing core_->buffer_ to the file. Read some more. |
| 365 core_->ReadResponse(); |
| 366 } |
| 367 } |
| 368 |
| 369 void URLFetcher::Core::TempFileWriter::DisownTempFile() { |
| 370 // Forget about any temp file by reseting the path. |
| 371 temp_file_ = FilePath(); |
| 372 } |
| 373 |
| 374 void URLFetcher::Core::TempFileWriter::Destroy() { |
| 375 if (!temp_file_.empty()) { |
| 376 base::FileUtilProxy::Delete( |
| 377 file_message_loop_proxy_, |
| 378 temp_file_, |
| 379 false, // No need to recurse, as the path is to a file. |
| 380 NULL); // No callback. |
| 381 } |
| 382 temp_file_ = FilePath(); |
| 383 } |
| 384 |
| 197 // static | 385 // static |
| 198 URLFetcher::Factory* URLFetcher::factory_ = NULL; | 386 URLFetcher::Factory* URLFetcher::factory_ = NULL; |
| 199 | 387 |
| 388 void URLFetcher::Delegate::OnURLFetchComplete( |
| 389 const URLFetcher* source, |
| 390 const GURL& url, |
| 391 const net::URLRequestStatus& status, |
| 392 int response_code, |
| 393 const net::ResponseCookies& cookies, |
| 394 const std::string& data) { |
| 395 NOTREACHED() << "If you don't implemnt this, the no-params version " |
| 396 << "should also be implemented, in which case this " |
| 397 << "method won't be called..."; |
| 398 } |
| 399 |
| 400 // TODO(skerner): This default implementation will be removed, and the |
| 401 // method made pure virtual, once all users of URLFetcher are updated |
| 402 // to not expect response data as a string argument. |
| 403 void URLFetcher::Delegate::OnURLFetchComplete(const URLFetcher* source) { |
| 404 // A delegate that did not override this method is using the old |
| 405 // parameter list to OnURLFetchComplete(). If a user asked to save |
| 406 // the response to a file, they must use the new parameter list, |
| 407 // in which case we can not get here. |
| 408 std::string data; |
| 409 CHECK(source->GetResponseAsString(&data)); |
| 410 |
| 411 // To avoid updating all callers, thunk to the old prototype for now. |
| 412 OnURLFetchComplete(source, |
| 413 source->url(), |
| 414 source->status(), |
| 415 source->response_code(), |
| 416 source->cookies(), |
| 417 data); |
| 418 } |
| 419 |
| 200 // static | 420 // static |
| 201 bool URLFetcher::g_interception_enabled = false; | 421 bool URLFetcher::g_interception_enabled = false; |
| 202 | 422 |
| 203 URLFetcher::URLFetcher(const GURL& url, | 423 URLFetcher::URLFetcher(const GURL& url, |
| 204 RequestType request_type, | 424 RequestType request_type, |
| 205 Delegate* d) | 425 Delegate* d) |
| 206 : ALLOW_THIS_IN_INITIALIZER_LIST( | 426 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 207 core_(new Core(this, url, request_type, d))), | 427 core_(new Core(this, url, request_type, d))), |
| 208 automatically_retry_on_5xx_(true), | 428 automatically_retry_on_5xx_(true), |
| 209 max_retries_(0) { | 429 max_retries_(0), |
| 430 response_destination_(STRING) { |
| 210 } | 431 } |
| 211 | 432 |
| 212 URLFetcher::~URLFetcher() { | 433 URLFetcher::~URLFetcher() { |
| 213 core_->Stop(); | 434 core_->Stop(); |
| 214 } | 435 } |
| 215 | 436 |
| 216 // static | 437 // static |
| 217 URLFetcher* URLFetcher::Create(int id, const GURL& url, | 438 URLFetcher* URLFetcher::Create(int id, const GURL& url, |
| 218 RequestType request_type, Delegate* d) { | 439 RequestType request_type, Delegate* d) { |
| 219 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : | 440 return factory_ ? factory_->CreateURLFetcher(id, url, request_type, d) : |
| 220 new URLFetcher(url, request_type, d); | 441 new URLFetcher(url, request_type, d); |
| 221 } | 442 } |
| 222 | 443 |
| 223 URLFetcher::Core::Core(URLFetcher* fetcher, | 444 URLFetcher::Core::Core(URLFetcher* fetcher, |
| 224 const GURL& original_url, | 445 const GURL& original_url, |
| 225 RequestType request_type, | 446 RequestType request_type, |
| 226 URLFetcher::Delegate* d) | 447 URLFetcher::Delegate* d) |
| 227 : fetcher_(fetcher), | 448 : fetcher_(fetcher), |
| 228 original_url_(original_url), | 449 original_url_(original_url), |
| 229 request_type_(request_type), | 450 request_type_(request_type), |
| 230 delegate_(d), | 451 delegate_(d), |
| 231 delegate_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()), | 452 delegate_loop_proxy_( |
| 453 base::MessageLoopProxy::CreateForCurrentThread()), |
| 232 request_(NULL), | 454 request_(NULL), |
| 233 load_flags_(net::LOAD_NORMAL), | 455 load_flags_(net::LOAD_NORMAL), |
| 234 response_code_(-1), | 456 response_code_(URLFetcher::kInvalidHttpResponseCode), |
| 235 buffer_(new net::IOBuffer(kBufferSize)), | 457 buffer_(new net::IOBuffer(kBufferSize)), |
| 236 is_chunked_upload_(false), | 458 is_chunked_upload_(false), |
| 237 num_retries_(0), | 459 num_retries_(0), |
| 238 was_cancelled_(false) { | 460 was_cancelled_(false) { |
| 239 } | 461 } |
| 240 | 462 |
| 241 URLFetcher::Core::~Core() { | 463 URLFetcher::Core::~Core() { |
| 242 // |request_| should be NULL. If not, it's unsafe to delete it here since we | 464 // |request_| should be NULL. If not, it's unsafe to delete it here since we |
| 243 // may not be on the IO thread. | 465 // may not be on the IO thread. |
| 244 DCHECK(!request_.get()); | 466 DCHECK(!request_.get()); |
| 245 } | 467 } |
| 246 | 468 |
| 247 void URLFetcher::Core::Start() { | 469 void URLFetcher::Core::Start() { |
| 248 DCHECK(delegate_loop_proxy_); | 470 DCHECK(delegate_loop_proxy_); |
| 249 CHECK(request_context_getter_) << "We need an URLRequestContext!"; | 471 CHECK(request_context_getter_) << "We need an URLRequestContext!"; |
| 250 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); | 472 io_message_loop_proxy_ = request_context_getter_->GetIOMessageLoopProxy(); |
| 251 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; | 473 CHECK(io_message_loop_proxy_.get()) << "We need an IO message loop proxy"; |
| 252 | 474 |
| 253 io_message_loop_proxy_->PostTask( | 475 switch (fetcher_->response_destination_) { |
| 254 FROM_HERE, | 476 case STRING: |
| 255 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); | 477 io_message_loop_proxy_->PostTask( |
| 478 FROM_HERE, |
| 479 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); |
| 480 break; |
| 481 |
| 482 case TEMP_FILE: |
| 483 CHECK(file_message_loop_proxy_.get()) |
| 484 << "Need to set the file message loop proxy."; |
| 485 temp_file_writer_.reset( |
| 486 new TempFileWriter(this, file_message_loop_proxy_)); |
| 487 // CreateTempFile() will invoke Core::StartURLRequestWhenAppropriate |
| 488 // once the file is created. |
| 489 temp_file_writer_->CreateTempFile(); |
| 490 break; |
| 491 |
| 492 default: |
| 493 NOTREACHED(); |
| 494 } |
| 256 } | 495 } |
| 257 | 496 |
| 258 void URLFetcher::Core::Stop() { | 497 void URLFetcher::Core::Stop() { |
| 259 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); | 498 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); |
| 260 delegate_ = NULL; | 499 delegate_ = NULL; |
| 261 fetcher_ = NULL; | 500 fetcher_ = NULL; |
| 262 if (io_message_loop_proxy_.get()) { | 501 if (io_message_loop_proxy_.get()) { |
| 263 io_message_loop_proxy_->PostTask( | 502 io_message_loop_proxy_->PostTask( |
| 264 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); | 503 FROM_HERE, NewRunnableMethod(this, &Core::CancelURLRequest)); |
| 265 } | 504 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 280 void URLFetcher::Core::OnResponseStarted(net::URLRequest* request) { | 519 void URLFetcher::Core::OnResponseStarted(net::URLRequest* request) { |
| 281 DCHECK_EQ(request, request_.get()); | 520 DCHECK_EQ(request, request_.get()); |
| 282 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 521 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 283 if (request_->status().is_success()) { | 522 if (request_->status().is_success()) { |
| 284 response_code_ = request_->GetResponseCode(); | 523 response_code_ = request_->GetResponseCode(); |
| 285 response_headers_ = request_->response_headers(); | 524 response_headers_ = request_->response_headers(); |
| 286 socket_address_ = request_->GetSocketAddress(); | 525 socket_address_ = request_->GetSocketAddress(); |
| 287 was_fetched_via_proxy_ = request_->was_fetched_via_proxy(); | 526 was_fetched_via_proxy_ = request_->was_fetched_via_proxy(); |
| 288 } | 527 } |
| 289 | 528 |
| 290 int bytes_read = 0; | 529 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 } | 530 } |
| 299 | 531 |
| 300 void URLFetcher::Core::CompleteAddingUploadDataChunk( | 532 void URLFetcher::Core::CompleteAddingUploadDataChunk( |
| 301 const std::string& content, bool is_last_chunk) { | 533 const std::string& content, bool is_last_chunk) { |
| 302 DCHECK(is_chunked_upload_); | 534 DCHECK(is_chunked_upload_); |
| 303 DCHECK(request_.get()); | 535 DCHECK(request_.get()); |
| 304 DCHECK(!content.empty()); | 536 DCHECK(!content.empty()); |
| 305 request_->AppendChunkToUpload(content.data(), | 537 request_->AppendChunkToUpload(content.data(), |
| 306 static_cast<int>(content.length()), | 538 static_cast<int>(content.length()), |
| 307 is_last_chunk); | 539 is_last_chunk); |
| 308 } | 540 } |
| 309 | 541 |
| 310 void URLFetcher::Core::AppendChunkToUpload(const std::string& content, | 542 void URLFetcher::Core::AppendChunkToUpload(const std::string& content, |
| 311 bool is_last_chunk) { | 543 bool is_last_chunk) { |
| 312 DCHECK(delegate_loop_proxy_); | 544 DCHECK(delegate_loop_proxy_); |
| 313 CHECK(io_message_loop_proxy_.get()); | 545 CHECK(io_message_loop_proxy_.get()); |
| 314 io_message_loop_proxy_->PostTask( | 546 io_message_loop_proxy_->PostTask( |
| 315 FROM_HERE, | 547 FROM_HERE, |
| 316 NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content, | 548 NewRunnableMethod(this, &Core::CompleteAddingUploadDataChunk, content, |
| 317 is_last_chunk)); | 549 is_last_chunk)); |
| 318 } | 550 } |
| 319 | 551 |
| 552 // Return true if the write was done and reading may continue. |
| 553 // Return false if the write is pending, and the next read will |
| 554 // be done later. |
| 555 bool URLFetcher::Core::WriteBuffer(int num_bytes) { |
| 556 bool write_complete = false; |
| 557 switch (fetcher_->response_destination_) { |
| 558 case STRING: |
| 559 data_.append(buffer_->data(), num_bytes); |
| 560 write_complete = true; |
| 561 break; |
| 562 |
| 563 case TEMP_FILE: |
| 564 temp_file_writer_->WriteBuffer(num_bytes); |
| 565 // WriteBuffer() sends a request the file thread. |
| 566 // The write is not done yet. |
| 567 write_complete = false; |
| 568 break; |
| 569 |
| 570 default: |
| 571 NOTREACHED(); |
| 572 } |
| 573 return write_complete; |
| 574 } |
| 575 |
| 320 void URLFetcher::Core::OnReadCompleted(net::URLRequest* request, | 576 void URLFetcher::Core::OnReadCompleted(net::URLRequest* request, |
| 321 int bytes_read) { | 577 int bytes_read) { |
| 322 DCHECK(request == request_); | 578 DCHECK(request == request_); |
| 323 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 579 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 324 | 580 |
| 325 url_ = request->url(); | 581 url_ = request->url(); |
| 326 url_throttler_entry_ = | 582 url_throttler_entry_ = |
| 327 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); | 583 net::URLRequestThrottlerManager::GetInstance()->RegisterRequestUrl(url_); |
| 328 | 584 |
| 585 bool waiting_on_write = false; |
| 329 do { | 586 do { |
| 330 if (!request_->status().is_success() || bytes_read <= 0) | 587 if (!request_->status().is_success() || bytes_read <= 0) |
| 331 break; | 588 break; |
| 332 data_.append(buffer_->data(), bytes_read); | 589 |
| 590 if (!WriteBuffer(bytes_read)) { |
| 591 // If WriteBuffer() returns false, we have a pending write to |
| 592 // wait on before reading further. |
| 593 waiting_on_write = true; |
| 594 break; |
| 595 } |
| 333 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); | 596 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); |
| 334 | 597 |
| 335 if (request_->status().is_success()) | 598 if (request_->status().is_success()) |
| 336 request_->GetResponseCookies(&cookies_); | 599 request_->GetResponseCookies(&cookies_); |
| 337 | 600 |
| 338 // See comments re: HEAD requests in OnResponseStarted(). | 601 // See comments re: HEAD requests in ReadResponse(). |
| 339 if (!request_->status().is_io_pending() || (request_type_ == HEAD)) { | 602 if ((!request_->status().is_io_pending() && !waiting_on_write) || |
| 603 (request_type_ == HEAD)) { |
| 340 backoff_release_time_ = GetBackoffReleaseTime(); | 604 backoff_release_time_ = GetBackoffReleaseTime(); |
| 341 | 605 |
| 342 bool posted = delegate_loop_proxy_->PostTask( | 606 bool posted = delegate_loop_proxy_->PostTask( |
| 343 FROM_HERE, | 607 FROM_HERE, |
| 344 NewRunnableMethod(this, | 608 NewRunnableMethod(this, |
| 345 &Core::OnCompletedURLRequest, | 609 &Core::OnCompletedURLRequest, |
| 346 request_->status())); | 610 request_->status())); |
| 347 // If the delegate message loop does not exist any more, then the delegate | 611 // If the delegate message loop does not exist any more, then the delegate |
| 348 // should be gone too. | 612 // should be gone too. |
| 349 DCHECK(posted || !delegate_); | 613 DCHECK(posted || !delegate_); |
| 350 ReleaseRequest(); | 614 ReleaseRequest(); |
| 351 } | 615 } |
| 352 } | 616 } |
| 353 | 617 |
| 618 void URLFetcher::Core::ReadResponse() { |
| 619 // Some servers may treat HEAD requests as GET requests. To free up the |
| 620 // network connection as soon as possible, signal that the request has |
| 621 // completed immediately, without trying to read any data back (all we care |
| 622 // about is the response code and headers, which we already have). |
| 623 int bytes_read = 0; |
| 624 if (request_->status().is_success() && (request_type_ != HEAD)) |
| 625 request_->Read(buffer_, kBufferSize, &bytes_read); |
| 626 OnReadCompleted(request_.get(), bytes_read); |
| 627 } |
| 628 |
| 354 void URLFetcher::Core::StartURLRequest() { | 629 void URLFetcher::Core::StartURLRequest() { |
| 355 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 630 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 356 | 631 |
| 357 if (was_cancelled_) { | 632 if (was_cancelled_) { |
| 358 // Since StartURLRequest() is posted as a *delayed* task, it may | 633 // Since StartURLRequest() is posted as a *delayed* task, it may |
| 359 // run after the URLFetcher was already stopped. | 634 // run after the URLFetcher was already stopped. |
| 360 return; | 635 return; |
| 361 } | 636 } |
| 362 | 637 |
| 363 CHECK(request_context_getter_); | 638 CHECK(request_context_getter_); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 default: | 674 default: |
| 400 NOTREACHED(); | 675 NOTREACHED(); |
| 401 } | 676 } |
| 402 | 677 |
| 403 if (!extra_request_headers_.IsEmpty()) | 678 if (!extra_request_headers_.IsEmpty()) |
| 404 request_->SetExtraRequestHeaders(extra_request_headers_); | 679 request_->SetExtraRequestHeaders(extra_request_headers_); |
| 405 | 680 |
| 406 // There might be data left over from a previous request attempt. | 681 // There might be data left over from a previous request attempt. |
| 407 data_.clear(); | 682 data_.clear(); |
| 408 | 683 |
| 684 // If we are writing the response to a file, the only caller |
| 685 // of this function should have created it and not written yet. |
| 686 CHECK(!temp_file_writer_.get() || |
| 687 temp_file_writer_->total_bytes_written() == 0); |
| 688 |
| 409 request_->Start(); | 689 request_->Start(); |
| 410 } | 690 } |
| 411 | 691 |
| 412 void URLFetcher::Core::StartURLRequestWhenAppropriate() { | 692 void URLFetcher::Core::StartURLRequestWhenAppropriate() { |
| 413 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 693 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 414 | 694 |
| 415 if (was_cancelled_) | 695 if (was_cancelled_) |
| 416 return; | 696 return; |
| 417 | 697 |
| 418 if (original_url_throttler_entry_ == NULL) { | 698 if (original_url_throttler_entry_ == NULL) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 439 if (request_.get()) { | 719 if (request_.get()) { |
| 440 request_->Cancel(); | 720 request_->Cancel(); |
| 441 ReleaseRequest(); | 721 ReleaseRequest(); |
| 442 } | 722 } |
| 443 // Release the reference to the request context. There could be multiple | 723 // 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 | 724 // 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 | 725 // delete the object, but we cannot delay the destruction of the request |
| 446 // context. | 726 // context. |
| 447 request_context_getter_ = NULL; | 727 request_context_getter_ = NULL; |
| 448 was_cancelled_ = true; | 728 was_cancelled_ = true; |
| 729 temp_file_writer_.reset(); |
| 449 } | 730 } |
| 450 | 731 |
| 451 void URLFetcher::Core::OnCompletedURLRequest( | 732 void URLFetcher::Core::OnCompletedURLRequest( |
| 452 const net::URLRequestStatus& status) { | 733 const net::URLRequestStatus& status) { |
| 453 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); | 734 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); |
| 454 | 735 |
| 736 // Save the status so that delegates can read it. |
| 737 status_ = status; |
| 738 |
| 455 // Checks the response from server. | 739 // Checks the response from server. |
| 456 if (response_code_ >= 500 || | 740 if (response_code_ >= 500 || |
| 457 status.os_error() == net::ERR_TEMPORARILY_THROTTLED) { | 741 status.os_error() == net::ERR_TEMPORARILY_THROTTLED) { |
| 458 // When encountering a server error, we will send the request again | 742 // When encountering a server error, we will send the request again |
| 459 // after backoff time. | 743 // after backoff time. |
| 460 ++num_retries_; | 744 ++num_retries_; |
| 461 // Restarts the request if we still need to notify the delegate. | 745 // Restarts the request if we still need to notify the delegate. |
| 462 if (delegate_) { | 746 if (delegate_) { |
| 463 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); | 747 fetcher_->backoff_delay_ = backoff_release_time_ - base::TimeTicks::Now(); |
| 464 if (fetcher_->backoff_delay_ < base::TimeDelta()) | 748 if (fetcher_->backoff_delay_ < base::TimeDelta()) |
| 465 fetcher_->backoff_delay_ = base::TimeDelta(); | 749 fetcher_->backoff_delay_ = base::TimeDelta(); |
| 466 | 750 |
| 467 if (fetcher_->automatically_retry_on_5xx_ && | 751 if (fetcher_->automatically_retry_on_5xx_ && |
| 468 num_retries_ <= fetcher_->max_retries()) { | 752 num_retries_ <= fetcher_->max_retries()) { |
| 469 io_message_loop_proxy_->PostTask( | 753 io_message_loop_proxy_->PostTask( |
| 470 FROM_HERE, | 754 FROM_HERE, |
| 471 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); | 755 NewRunnableMethod(this, &Core::StartURLRequestWhenAppropriate)); |
| 472 } else { | 756 } else { |
| 473 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 757 InformDelegateFetchIsComplete(); |
| 474 cookies_, data_); | |
| 475 } | 758 } |
| 476 } | 759 } |
| 477 } else { | 760 } else { |
| 478 if (delegate_) { | 761 if (delegate_) { |
| 479 fetcher_->backoff_delay_ = base::TimeDelta(); | 762 fetcher_->backoff_delay_ = base::TimeDelta(); |
| 480 delegate_->OnURLFetchComplete(fetcher_, url_, status, response_code_, | 763 InformDelegateFetchIsComplete(); |
| 481 cookies_, data_); | |
| 482 } | 764 } |
| 483 } | 765 } |
| 484 } | 766 } |
| 485 | 767 |
| 768 void URLFetcher::Core::InformDelegateFetchIsComplete() { |
| 769 delegate_->OnURLFetchComplete(fetcher_); |
| 770 } |
| 771 |
| 486 void URLFetcher::Core::NotifyMalformedContent() { | 772 void URLFetcher::Core::NotifyMalformedContent() { |
| 487 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 773 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 488 if (url_throttler_entry_ != NULL) | 774 if (url_throttler_entry_ != NULL) |
| 489 url_throttler_entry_->ReceivedContentWasMalformed(); | 775 url_throttler_entry_->ReceivedContentWasMalformed(); |
| 490 } | 776 } |
| 491 | 777 |
| 492 void URLFetcher::Core::ReleaseRequest() { | 778 void URLFetcher::Core::ReleaseRequest() { |
| 493 request_.reset(); | 779 request_.reset(); |
| 494 g_registry.Get().RemoveURLFetcherCore(this); | 780 g_registry.Get().RemoveURLFetcherCore(this); |
| 495 } | 781 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 const std::string& extra_request_headers) { | 839 const std::string& extra_request_headers) { |
| 554 core_->extra_request_headers_.Clear(); | 840 core_->extra_request_headers_.Clear(); |
| 555 core_->extra_request_headers_.AddHeadersFromString(extra_request_headers); | 841 core_->extra_request_headers_.AddHeadersFromString(extra_request_headers); |
| 556 } | 842 } |
| 557 | 843 |
| 558 void URLFetcher::set_request_context( | 844 void URLFetcher::set_request_context( |
| 559 net::URLRequestContextGetter* request_context_getter) { | 845 net::URLRequestContextGetter* request_context_getter) { |
| 560 core_->request_context_getter_ = request_context_getter; | 846 core_->request_context_getter_ = request_context_getter; |
| 561 } | 847 } |
| 562 | 848 |
| 849 void URLFetcher::set_file_message_loop_proxy( |
| 850 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) { |
| 851 core_->file_message_loop_proxy_ = file_message_loop_proxy; |
| 852 } |
| 853 |
| 563 void URLFetcher::set_automatically_retry_on_5xx(bool retry) { | 854 void URLFetcher::set_automatically_retry_on_5xx(bool retry) { |
| 564 automatically_retry_on_5xx_ = retry; | 855 automatically_retry_on_5xx_ = retry; |
| 565 } | 856 } |
| 566 | 857 |
| 858 void URLFetcher::SaveResponseToTemporaryFile() { |
| 859 response_destination_ = TEMP_FILE; |
| 860 } |
| 861 |
| 567 net::HttpResponseHeaders* URLFetcher::response_headers() const { | 862 net::HttpResponseHeaders* URLFetcher::response_headers() const { |
| 568 return core_->response_headers_; | 863 return core_->response_headers_; |
| 569 } | 864 } |
| 570 | 865 |
| 571 // TODO(panayiotis): socket_address_ is written in the IO thread, | 866 // 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. | 867 // 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. | 868 // Same for response_headers_ above and was_fetched_via_proxy_ below. |
| 574 net::HostPortPair URLFetcher::socket_address() const { | 869 net::HostPortPair URLFetcher::socket_address() const { |
| 575 return core_->socket_address_; | 870 return core_->socket_address_; |
| 576 } | 871 } |
| 577 | 872 |
| 578 bool URLFetcher::was_fetched_via_proxy() const { | 873 bool URLFetcher::was_fetched_via_proxy() const { |
| 579 return core_->was_fetched_via_proxy_; | 874 return core_->was_fetched_via_proxy_; |
| 580 } | 875 } |
| 581 | 876 |
| 582 void URLFetcher::Start() { | 877 void URLFetcher::Start() { |
| 583 core_->Start(); | 878 core_->Start(); |
| 584 } | 879 } |
| 585 | 880 |
| 586 const GURL& URLFetcher::url() const { | 881 const GURL& URLFetcher::url() const { |
| 587 return core_->url_; | 882 return core_->url_; |
| 588 } | 883 } |
| 589 | 884 |
| 885 const net::URLRequestStatus& URLFetcher::status() const { |
| 886 return core_->status_; |
| 887 } |
| 888 |
| 889 int URLFetcher::response_code() const { |
| 890 return core_->response_code_; |
| 891 } |
| 892 |
| 893 const net::ResponseCookies& URLFetcher::cookies() const { |
| 894 return core_->cookies_; |
| 895 } |
| 896 |
| 897 bool URLFetcher::FileErrorOccurred( |
| 898 base::PlatformFileError* out_error_code) const { |
| 899 |
| 900 // Can't have a file error if no file is being created or written to. |
| 901 if (!core_->temp_file_writer_.get()) { |
| 902 return false; |
| 903 } |
| 904 |
| 905 base::PlatformFileError error_code = core_->temp_file_writer_->error_code(); |
| 906 if (error_code == base::PLATFORM_FILE_OK) |
| 907 return false; |
| 908 |
| 909 *out_error_code = error_code; |
| 910 return true; |
| 911 } |
| 912 |
| 590 void URLFetcher::ReceivedContentWasMalformed() { | 913 void URLFetcher::ReceivedContentWasMalformed() { |
| 591 core_->ReceivedContentWasMalformed(); | 914 core_->ReceivedContentWasMalformed(); |
| 592 } | 915 } |
| 593 | 916 |
| 917 bool URLFetcher::GetResponseAsString(std::string* out_response_string) const { |
| 918 if (response_destination_ != STRING) |
| 919 return false; |
| 920 |
| 921 *out_response_string = core_->data_; |
| 922 return true; |
| 923 } |
| 924 |
| 925 bool URLFetcher::GetResponseAsFilePath(bool take_ownership, |
| 926 FilePath* out_response_path) const { |
| 927 if (response_destination_ != TEMP_FILE || !core_->temp_file_writer_.get()) |
| 928 return false; |
| 929 |
| 930 *out_response_path = core_->temp_file_writer_->temp_file(); |
| 931 |
| 932 if (take_ownership) |
| 933 core_->temp_file_writer_->DisownTempFile(); |
| 934 |
| 935 return true; |
| 936 } |
| 937 |
| 594 // static | 938 // static |
| 595 void URLFetcher::CancelAll() { | 939 void URLFetcher::CancelAll() { |
| 596 Core::CancelAll(); | 940 Core::CancelAll(); |
| 597 } | 941 } |
| 598 | 942 |
| 599 // static | 943 // static |
| 600 int URLFetcher::GetNumFetcherCores() { | 944 int URLFetcher::GetNumFetcherCores() { |
| 601 return Core::g_registry.Get().size(); | 945 return Core::g_registry.Get().size(); |
| 602 } | 946 } |
| 603 | 947 |
| 604 URLFetcher::Delegate* URLFetcher::delegate() const { | 948 URLFetcher::Delegate* URLFetcher::delegate() const { |
| 605 return core_->delegate(); | 949 return core_->delegate(); |
| 606 } | 950 } |
| OLD | NEW |