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

Side by Side Diff: content/common/net/url_fetcher_impl.cc

Issue 9585009: Add URLFetcher::SaveResponseToFileAtPath (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed nits Created 8 years, 9 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 | « content/common/net/url_fetcher_impl.h ('k') | content/common/net/url_fetcher_impl_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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 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 "content/common/net/url_fetcher_impl.h" 5 #include "content/common/net/url_fetcher_impl.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 return fetchers_.size(); 93 return fetchers_.size();
94 } 94 }
95 95
96 private: 96 private:
97 std::set<Core*> fetchers_; 97 std::set<Core*> fetchers_;
98 98
99 DISALLOW_COPY_AND_ASSIGN(Registry); 99 DISALLOW_COPY_AND_ASSIGN(Registry);
100 }; 100 };
101 101
102 // Class FileWriter encapsulates all state involved in writing response bytes 102 // Class FileWriter encapsulates all state involved in writing response bytes
103 // to a file. It is only used if |Core::response_destination_| == FILE. 103 // to a file. It is only used if |Core::response_destination_| == TEMP_FILE ||
104 // |Core::response_destination_| == PERMANENT_FILE.
104 // Each instance of FileWriter is owned by a URLFetcher::Core, which manages 105 // Each instance of FileWriter is owned by a URLFetcher::Core, which manages
105 // its lifetime and never transfers ownership. While writing to 106 // its lifetime and never transfers ownership. While writing to
106 // a file, all function calls happen on the IO thread. 107 // a file, all function calls happen on the IO thread.
107 class FileWriter { 108 class FileWriter {
108 public: 109 public:
109 FileWriter(URLFetcherImpl::Core* core, 110 FileWriter(URLFetcherImpl::Core* core,
110 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy); 111 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy);
111 112
112 ~FileWriter(); 113 ~FileWriter();
114 void CreateFileAtPath(const FilePath& file_path);
113 void CreateTempFile(); 115 void CreateTempFile();
114 void DidCreateTempFile(base::PlatformFileError error_code,
115 base::PassPlatformFile file_handle,
116 const FilePath& file_path);
117 116
118 // Record |num_bytes_| response bytes in |core_->buffer_| to the file. 117 // Record |num_bytes_| response bytes in |core_->buffer_| to the file.
119 void WriteBuffer(int num_bytes); 118 void WriteBuffer(int num_bytes);
120 119
121 // Called when a write has been done. Continues writing if there are 120 // Called when a write has been done. Continues writing if there are
122 // any more bytes to write. Otherwise, initiates a read in core_. 121 // any more bytes to write. Otherwise, initiates a read in core_.
123 void ContinueWrite(base::PlatformFileError error_code, int bytes_written); 122 void ContinueWrite(base::PlatformFileError error_code, int bytes_written);
124 123
125 // Drop ownership of the file at |file_path_|. 124 // Drop ownership of the file at |file_path_|.
126 // This class will not delete it or write to it again. 125 // This class will not delete it or write to it again.
127 void DisownFile(); 126 void DisownFile();
128 127
129 // Close the file if it is open. 128 // Close the file if it is open.
130 void CloseFileAndCompleteRequest(); 129 void CloseFileAndCompleteRequest();
131 130
132 // Remove the file if we have created one. 131 // Remove the file if we have created one.
133 void RemoveFile(); 132 void RemoveFile();
134 133
135 const FilePath& file_path() const { return file_path_; } 134 const FilePath& file_path() const { return file_path_; }
136 int64 total_bytes_written() { return total_bytes_written_; } 135 int64 total_bytes_written() { return total_bytes_written_; }
137 base::PlatformFileError error_code() const { return error_code_; } 136 base::PlatformFileError error_code() const { return error_code_; }
138 137
139 private: 138 private:
139 // Callback which gets the result of a permanent file creation.
140 void DidCreateFile(const FilePath& file_path,
141 base::PlatformFileError error_code,
142 base::PassPlatformFile file_handle,
143 bool created);
144 // Callback which gets the result of a temporary file creation.
145 void DidCreateTempFile(base::PlatformFileError error_code,
146 base::PassPlatformFile file_handle,
147 const FilePath& file_path);
148 // This method is used to implement DidCreateFile and DidCreateTempFile.
149 void DidCreateFileInternal(const FilePath& file_path,
150 base::PlatformFileError error_code,
151 base::PassPlatformFile file_handle);
152
140 // Callback which gets the result of closing the file. 153 // Callback which gets the result of closing the file.
141 void DidCloseFile(base::PlatformFileError error); 154 void DidCloseFile(base::PlatformFileError error);
142 155
143 // The URLFetcherImpl::Core which instantiated this class. 156 // The URLFetcherImpl::Core which instantiated this class.
144 URLFetcherImpl::Core* core_; 157 URLFetcherImpl::Core* core_;
145 158
146 // The last error encountered on a file operation. base::PLATFORM_FILE_OK 159 // The last error encountered on a file operation. base::PLATFORM_FILE_OK
147 // if no error occurred. 160 // if no error occurred.
148 base::PlatformFileError error_code_; 161 base::PlatformFileError error_code_;
149 162
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 // True if the URLFetcher has been cancelled. 288 // True if the URLFetcher has been cancelled.
276 bool was_cancelled_; 289 bool was_cancelled_;
277 290
278 // If writing results to a file, |file_writer_| will manage creation, 291 // If writing results to a file, |file_writer_| will manage creation,
279 // writing, and destruction of that file. 292 // writing, and destruction of that file.
280 scoped_ptr<FileWriter> file_writer_; 293 scoped_ptr<FileWriter> file_writer_;
281 294
282 // Where should responses be saved? 295 // Where should responses be saved?
283 ResponseDestinationType response_destination_; 296 ResponseDestinationType response_destination_;
284 297
298 // Path to the file where the response is written.
299 FilePath response_destination_file_path_;
300
285 // If |automatically_retry_on_5xx_| is false, 5xx responses will be 301 // If |automatically_retry_on_5xx_| is false, 5xx responses will be
286 // propagated to the observer, if it is true URLFetcher will automatically 302 // propagated to the observer, if it is true URLFetcher will automatically
287 // re-execute the request, after the back-off delay has expired. 303 // re-execute the request, after the back-off delay has expired.
288 // true by default. 304 // true by default.
289 bool automatically_retry_on_5xx_; 305 bool automatically_retry_on_5xx_;
290 // Maximum retries allowed. 306 // Maximum retries allowed.
291 int max_retries_; 307 int max_retries_;
292 // Back-off time delay. 0 by default. 308 // Back-off time delay. 0 by default.
293 base::TimeDelta backoff_delay_; 309 base::TimeDelta backoff_delay_;
294 310
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 error_code_(base::PLATFORM_FILE_OK), 348 error_code_(base::PLATFORM_FILE_OK),
333 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 349 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
334 file_message_loop_proxy_(file_message_loop_proxy), 350 file_message_loop_proxy_(file_message_loop_proxy),
335 file_handle_(base::kInvalidPlatformFileValue) { 351 file_handle_(base::kInvalidPlatformFileValue) {
336 } 352 }
337 353
338 URLFetcherImpl::Core::FileWriter::~FileWriter() { 354 URLFetcherImpl::Core::FileWriter::~FileWriter() {
339 RemoveFile(); 355 RemoveFile();
340 } 356 }
341 357
358 void URLFetcherImpl::Core::FileWriter::CreateFileAtPath(
359 const FilePath& file_path) {
360 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
361 DCHECK(file_message_loop_proxy_.get());
362 base::FileUtilProxy::CreateOrOpen(
363 file_message_loop_proxy_,
364 file_path,
365 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
366 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCreateFile,
367 weak_factory_.GetWeakPtr(),
368 file_path));
369 }
370
342 void URLFetcherImpl::Core::FileWriter::CreateTempFile() { 371 void URLFetcherImpl::Core::FileWriter::CreateTempFile() {
343 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); 372 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
344 DCHECK(file_message_loop_proxy_.get()); 373 DCHECK(file_message_loop_proxy_.get());
345 base::FileUtilProxy::CreateTemporary( 374 base::FileUtilProxy::CreateTemporary(
346 file_message_loop_proxy_, 375 file_message_loop_proxy_,
347 0, // No additional file flags. 376 0, // No additional file flags.
348 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCreateTempFile, 377 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCreateTempFile,
349 weak_factory_.GetWeakPtr())); 378 weak_factory_.GetWeakPtr()));
350 } 379 }
351 380
352 void URLFetcherImpl::Core::FileWriter::DidCreateTempFile(
353 base::PlatformFileError error_code,
354 base::PassPlatformFile file_handle,
355 const FilePath& file_path) {
356 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
357
358 if (base::PLATFORM_FILE_OK != error_code) {
359 error_code_ = error_code;
360 RemoveFile();
361 core_->delegate_loop_proxy_->PostTask(
362 FROM_HERE, base::Bind(&Core::InformDelegateFetchIsComplete, core_));
363 return;
364 }
365
366 file_path_ = file_path;
367 file_handle_ = file_handle.ReleaseValue();
368 total_bytes_written_ = 0;
369
370 core_->io_message_loop_proxy_->PostTask(
371 FROM_HERE, base::Bind(&Core::StartURLRequestWhenAppropriate, core_));
372 }
373
374 void URLFetcherImpl::Core::FileWriter::WriteBuffer(int num_bytes) { 381 void URLFetcherImpl::Core::FileWriter::WriteBuffer(int num_bytes) {
375 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); 382 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
376 383
377 // Start writing to the file by setting the initial state 384 // Start writing to the file by setting the initial state
378 // of |pending_bytes_| and |buffer_offset_| to indicate that the 385 // of |pending_bytes_| and |buffer_offset_| to indicate that the
379 // entire buffer has not yet been written. 386 // entire buffer has not yet been written.
380 pending_bytes_ = num_bytes; 387 pending_bytes_ = num_bytes;
381 buffer_offset_ = 0; 388 buffer_offset_ = 0;
382 ContinueWrite(base::PLATFORM_FILE_OK, 0); 389 ContinueWrite(base::PLATFORM_FILE_OK, 0);
383 } 390 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 450
444 if (file_handle_ != base::kInvalidPlatformFileValue) { 451 if (file_handle_ != base::kInvalidPlatformFileValue) {
445 base::FileUtilProxy::Close( 452 base::FileUtilProxy::Close(
446 file_message_loop_proxy_, file_handle_, 453 file_message_loop_proxy_, file_handle_,
447 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCloseFile, 454 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCloseFile,
448 weak_factory_.GetWeakPtr())); 455 weak_factory_.GetWeakPtr()));
449 file_handle_ = base::kInvalidPlatformFileValue; 456 file_handle_ = base::kInvalidPlatformFileValue;
450 } 457 }
451 } 458 }
452 459
460 void URLFetcherImpl::Core::FileWriter::DidCreateFile(
461 const FilePath& file_path,
462 base::PlatformFileError error_code,
463 base::PassPlatformFile file_handle,
464 bool created) {
465 DidCreateFileInternal(file_path, error_code, file_handle);
466 }
467
468 void URLFetcherImpl::Core::FileWriter::DidCreateTempFile(
469 base::PlatformFileError error_code,
470 base::PassPlatformFile file_handle,
471 const FilePath& file_path) {
472 DidCreateFileInternal(file_path, error_code, file_handle);
473 }
474
475 void URLFetcherImpl::Core::FileWriter::DidCreateFileInternal(
476 const FilePath& file_path,
477 base::PlatformFileError error_code,
478 base::PassPlatformFile file_handle) {
479 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
480
481 if (base::PLATFORM_FILE_OK != error_code) {
482 error_code_ = error_code;
483 RemoveFile();
484 core_->delegate_loop_proxy_->PostTask(
485 FROM_HERE, base::Bind(&Core::InformDelegateFetchIsComplete, core_));
486 return;
487 }
488
489 file_path_ = file_path;
490 file_handle_ = file_handle.ReleaseValue();
491 total_bytes_written_ = 0;
492
493 core_->io_message_loop_proxy_->PostTask(
494 FROM_HERE, base::Bind(&Core::StartURLRequestWhenAppropriate, core_));
495 }
496
453 void URLFetcherImpl::Core::FileWriter::DidCloseFile( 497 void URLFetcherImpl::Core::FileWriter::DidCloseFile(
454 base::PlatformFileError error_code) { 498 base::PlatformFileError error_code) {
455 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); 499 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
456 500
457 if (base::PLATFORM_FILE_OK != error_code) { 501 if (base::PLATFORM_FILE_OK != error_code) {
458 error_code_ = error_code; 502 error_code_ = error_code;
459 RemoveFile(); 503 RemoveFile();
460 core_->delegate_loop_proxy_->PostTask( 504 core_->delegate_loop_proxy_->PostTask(
461 FROM_HERE, base::Bind(&Core::InformDelegateFetchIsComplete, core_)); 505 FROM_HERE, base::Bind(&Core::InformDelegateFetchIsComplete, core_));
462 return; 506 return;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 } 620 }
577 621
578 void URLFetcherImpl::Core::StartOnIOThread() { 622 void URLFetcherImpl::Core::StartOnIOThread() {
579 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 623 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
580 624
581 switch (response_destination_) { 625 switch (response_destination_) {
582 case STRING: 626 case STRING:
583 StartURLRequestWhenAppropriate(); 627 StartURLRequestWhenAppropriate();
584 break; 628 break;
585 629
586 case FILE: 630 case PERMANENT_FILE:
631 case TEMP_FILE:
587 DCHECK(file_message_loop_proxy_.get()) 632 DCHECK(file_message_loop_proxy_.get())
588 << "Need to set the file message loop proxy."; 633 << "Need to set the file message loop proxy.";
589 634
590 file_writer_.reset( 635 file_writer_.reset(new FileWriter(this, file_message_loop_proxy_));
591 new FileWriter(this, file_message_loop_proxy_));
592 636
593 // If the temp file is successfully created, 637 // If the file is successfully created,
594 // Core::StartURLRequestWhenAppropriate() will be called. 638 // Core::StartURLRequestWhenAppropriate() will be called.
595 file_writer_->CreateTempFile(); 639 switch (response_destination_) {
640 case PERMANENT_FILE:
641 file_writer_->CreateFileAtPath(response_destination_file_path_);
642 break;
643 case TEMP_FILE:
644 file_writer_->CreateTempFile();
645 break;
646 default:
647 NOTREACHED();
648 }
596 break; 649 break;
597 650
598 default: 651 default:
599 NOTREACHED(); 652 NOTREACHED();
600 } 653 }
601 } 654 }
602 655
603 void URLFetcherImpl::Core::Stop() { 656 void URLFetcherImpl::Core::Stop() {
604 if (delegate_loop_proxy_) // May be NULL in tests. 657 if (delegate_loop_proxy_) // May be NULL in tests.
605 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); 658 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread());
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 // Return false if the write is pending, and the next read will 715 // Return false if the write is pending, and the next read will
663 // be done later. 716 // be done later.
664 bool URLFetcherImpl::Core::WriteBuffer(int num_bytes) { 717 bool URLFetcherImpl::Core::WriteBuffer(int num_bytes) {
665 bool write_complete = false; 718 bool write_complete = false;
666 switch (response_destination_) { 719 switch (response_destination_) {
667 case STRING: 720 case STRING:
668 data_.append(buffer_->data(), num_bytes); 721 data_.append(buffer_->data(), num_bytes);
669 write_complete = true; 722 write_complete = true;
670 break; 723 break;
671 724
672 case FILE: 725 case PERMANENT_FILE:
726 case TEMP_FILE:
673 file_writer_->WriteBuffer(num_bytes); 727 file_writer_->WriteBuffer(num_bytes);
674 // WriteBuffer() sends a request the file thread. 728 // WriteBuffer() sends a request the file thread.
675 // The write is not done yet. 729 // The write is not done yet.
676 write_complete = false; 730 write_complete = false;
677 break; 731 break;
678 732
679 default: 733 default:
680 NOTREACHED(); 734 NOTREACHED();
681 } 735 }
682 return write_complete; 736 return write_complete;
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 1079
1026 int URLFetcherImpl::GetMaxRetries() const { 1080 int URLFetcherImpl::GetMaxRetries() const {
1027 return core_->max_retries_; 1081 return core_->max_retries_;
1028 } 1082 }
1029 1083
1030 1084
1031 base::TimeDelta URLFetcherImpl::GetBackoffDelay() const { 1085 base::TimeDelta URLFetcherImpl::GetBackoffDelay() const {
1032 return core_->backoff_delay_; 1086 return core_->backoff_delay_;
1033 } 1087 }
1034 1088
1089 void URLFetcherImpl::SaveResponseToFileAtPath(
1090 const FilePath& file_path,
1091 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) {
1092 DCHECK(core_->delegate_loop_proxy_->BelongsToCurrentThread());
1093 core_->file_message_loop_proxy_ = file_message_loop_proxy;
1094 core_->response_destination_ = PERMANENT_FILE;
1095 core_->response_destination_file_path_ = file_path;
1096 }
1097
1035 void URLFetcherImpl::SaveResponseToTemporaryFile( 1098 void URLFetcherImpl::SaveResponseToTemporaryFile(
1036 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) { 1099 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) {
1100 DCHECK(core_->delegate_loop_proxy_->BelongsToCurrentThread());
1037 core_->file_message_loop_proxy_ = file_message_loop_proxy; 1101 core_->file_message_loop_proxy_ = file_message_loop_proxy;
1038 core_->response_destination_ = FILE; 1102 core_->response_destination_ = TEMP_FILE;
1039 } 1103 }
1040 1104
1041 net::HttpResponseHeaders* URLFetcherImpl::GetResponseHeaders() const { 1105 net::HttpResponseHeaders* URLFetcherImpl::GetResponseHeaders() const {
1042 return core_->response_headers_; 1106 return core_->response_headers_;
1043 } 1107 }
1044 1108
1045 void URLFetcherImpl::set_response_headers( 1109 void URLFetcherImpl::set_response_headers(
1046 scoped_refptr<net::HttpResponseHeaders> headers) { 1110 scoped_refptr<net::HttpResponseHeaders> headers) {
1047 core_->response_headers_ = headers; 1111 core_->response_headers_ = headers;
1048 } 1112 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 *out_response_string = core_->data_; 1183 *out_response_string = core_->data_;
1120 UMA_HISTOGRAM_MEMORY_KB("UrlFetcher.StringResponseSize", 1184 UMA_HISTOGRAM_MEMORY_KB("UrlFetcher.StringResponseSize",
1121 (core_->data_.length() / 1024)); 1185 (core_->data_.length() / 1024));
1122 1186
1123 return true; 1187 return true;
1124 } 1188 }
1125 1189
1126 bool URLFetcherImpl::GetResponseAsFilePath(bool take_ownership, 1190 bool URLFetcherImpl::GetResponseAsFilePath(bool take_ownership,
1127 FilePath* out_response_path) const { 1191 FilePath* out_response_path) const {
1128 DCHECK(core_->delegate_loop_proxy_->BelongsToCurrentThread()); 1192 DCHECK(core_->delegate_loop_proxy_->BelongsToCurrentThread());
1129 if (core_->response_destination_ != FILE || !core_->file_writer_.get()) 1193 const bool destination_is_file = core_->response_destination_ == TEMP_FILE ||
1194 core_->response_destination_ == PERMANENT_FILE;
1195 if (!destination_is_file || !core_->file_writer_.get())
1130 return false; 1196 return false;
1131 1197
1132 *out_response_path = core_->file_writer_->file_path(); 1198 *out_response_path = core_->file_writer_->file_path();
1133 1199
1134 if (take_ownership) { 1200 if (take_ownership) {
1135 core_->io_message_loop_proxy_->PostTask( 1201 core_->io_message_loop_proxy_->PostTask(
1136 FROM_HERE, base::Bind(&Core::DisownFile, core_.get())); 1202 FROM_HERE, base::Bind(&Core::DisownFile, core_.get()));
1137 } 1203 }
1138 return true; 1204 return true;
1139 } 1205 }
(...skipping 14 matching lines...) Expand all
1154 1220
1155 // static 1221 // static
1156 content::URLFetcherFactory* URLFetcherImpl::factory() { 1222 content::URLFetcherFactory* URLFetcherImpl::factory() {
1157 return g_factory; 1223 return g_factory;
1158 } 1224 }
1159 1225
1160 // static 1226 // static
1161 void URLFetcherImpl::set_factory(content::URLFetcherFactory* factory) { 1227 void URLFetcherImpl::set_factory(content::URLFetcherFactory* factory) {
1162 g_factory = factory; 1228 g_factory = factory;
1163 } 1229 }
OLDNEW
« no previous file with comments | « content/common/net/url_fetcher_impl.h ('k') | content/common/net/url_fetcher_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698