Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(329)

Side by Side Diff: chrome/common/net/url_fetcher.cc

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

Powered by Google App Engine
This is Rietveld 408576698