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

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
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);
115 void DidCreateFile(const FilePath& file_path,
116 base::PlatformFileError error_code,
117 base::PassPlatformFile file_handle,
118 bool created);
113 void CreateTempFile(); 119 void CreateTempFile();
114 void DidCreateTempFile(base::PlatformFileError error_code, 120 void DidCreateTempFile(base::PlatformFileError error_code,
115 base::PassPlatformFile file_handle, 121 base::PassPlatformFile file_handle,
116 const FilePath& file_path); 122 const FilePath& file_path);
117 123
118 // Record |num_bytes_| response bytes in |core_->buffer_| to the file. 124 // Record |num_bytes_| response bytes in |core_->buffer_| to the file.
119 void WriteBuffer(int num_bytes); 125 void WriteBuffer(int num_bytes);
120 126
121 // Called when a write has been done. Continues writing if there are 127 // Called when a write has been done. Continues writing if there are
122 // any more bytes to write. Otherwise, initiates a read in core_. 128 // any more bytes to write. Otherwise, initiates a read in core_.
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 // True if the URLFetcher has been cancelled. 281 // True if the URLFetcher has been cancelled.
276 bool was_cancelled_; 282 bool was_cancelled_;
277 283
278 // If writing results to a file, |file_writer_| will manage creation, 284 // If writing results to a file, |file_writer_| will manage creation,
279 // writing, and destruction of that file. 285 // writing, and destruction of that file.
280 scoped_ptr<FileWriter> file_writer_; 286 scoped_ptr<FileWriter> file_writer_;
281 287
282 // Where should responses be saved? 288 // Where should responses be saved?
283 ResponseDestinationType response_destination_; 289 ResponseDestinationType response_destination_;
284 290
291 // Path to the file where the response is written.
292 FilePath response_destination_file_path_;
293
285 // If |automatically_retry_on_5xx_| is false, 5xx responses will be 294 // If |automatically_retry_on_5xx_| is false, 5xx responses will be
286 // propagated to the observer, if it is true URLFetcher will automatically 295 // propagated to the observer, if it is true URLFetcher will automatically
287 // re-execute the request, after the back-off delay has expired. 296 // re-execute the request, after the back-off delay has expired.
288 // true by default. 297 // true by default.
289 bool automatically_retry_on_5xx_; 298 bool automatically_retry_on_5xx_;
290 // Maximum retries allowed. 299 // Maximum retries allowed.
291 int max_retries_; 300 int max_retries_;
292 // Back-off time delay. 0 by default. 301 // Back-off time delay. 0 by default.
293 base::TimeDelta backoff_delay_; 302 base::TimeDelta backoff_delay_;
294 303
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 error_code_(base::PLATFORM_FILE_OK), 341 error_code_(base::PLATFORM_FILE_OK),
333 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 342 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
334 file_message_loop_proxy_(file_message_loop_proxy), 343 file_message_loop_proxy_(file_message_loop_proxy),
335 file_handle_(base::kInvalidPlatformFileValue) { 344 file_handle_(base::kInvalidPlatformFileValue) {
336 } 345 }
337 346
338 URLFetcherImpl::Core::FileWriter::~FileWriter() { 347 URLFetcherImpl::Core::FileWriter::~FileWriter() {
339 RemoveFile(); 348 RemoveFile();
340 } 349 }
341 350
342 void URLFetcherImpl::Core::FileWriter::CreateTempFile() { 351 void URLFetcherImpl::Core::FileWriter::CreateFileAtPath(
352 const FilePath& file_path) {
343 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); 353 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
344 DCHECK(file_message_loop_proxy_.get()); 354 DCHECK(file_message_loop_proxy_.get());
345 base::FileUtilProxy::CreateTemporary( 355 base::FileUtilProxy::CreateOrOpen(
346 file_message_loop_proxy_, 356 file_message_loop_proxy_,
347 0, // No additional file flags. 357 file_path,
348 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCreateTempFile, 358 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
349 weak_factory_.GetWeakPtr())); 359 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCreateFile,
360 weak_factory_.GetWeakPtr(),
361 file_path));
350 } 362 }
351 363
352 void URLFetcherImpl::Core::FileWriter::DidCreateTempFile( 364 void URLFetcherImpl::Core::FileWriter::DidCreateFile(
365 const FilePath& file_path,
353 base::PlatformFileError error_code, 366 base::PlatformFileError error_code,
354 base::PassPlatformFile file_handle, 367 base::PassPlatformFile file_handle,
355 const FilePath& file_path) { 368 bool created) {
willchan no longer on Chromium 2012/03/08 16:38:39 Is this just ignored? It's sorta weird that DidCre
hashimoto 2012/03/09 03:22:52 Added DidCreateFileInternal
356 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); 369 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
357 370
358 if (base::PLATFORM_FILE_OK != error_code) { 371 if (base::PLATFORM_FILE_OK != error_code) {
359 error_code_ = error_code; 372 error_code_ = error_code;
360 RemoveFile(); 373 RemoveFile();
361 core_->delegate_loop_proxy_->PostTask( 374 core_->delegate_loop_proxy_->PostTask(
362 FROM_HERE, base::Bind(&Core::InformDelegateFetchIsComplete, core_)); 375 FROM_HERE, base::Bind(&Core::InformDelegateFetchIsComplete, core_));
363 return; 376 return;
364 } 377 }
365 378
366 file_path_ = file_path; 379 file_path_ = file_path;
367 file_handle_ = file_handle.ReleaseValue(); 380 file_handle_ = file_handle.ReleaseValue();
368 total_bytes_written_ = 0; 381 total_bytes_written_ = 0;
369 382
370 core_->io_message_loop_proxy_->PostTask( 383 core_->io_message_loop_proxy_->PostTask(
371 FROM_HERE, base::Bind(&Core::StartURLRequestWhenAppropriate, core_)); 384 FROM_HERE, base::Bind(&Core::StartURLRequestWhenAppropriate, core_));
372 } 385 }
373 386
387 void URLFetcherImpl::Core::FileWriter::CreateTempFile() {
388 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
389 DCHECK(file_message_loop_proxy_.get());
390 base::FileUtilProxy::CreateTemporary(
391 file_message_loop_proxy_,
392 0, // No additional file flags.
393 base::Bind(&URLFetcherImpl::Core::FileWriter::DidCreateTempFile,
394 weak_factory_.GetWeakPtr()));
395 }
396
397 void URLFetcherImpl::Core::FileWriter::DidCreateTempFile(
398 base::PlatformFileError error_code,
399 base::PassPlatformFile file_handle,
400 const FilePath& file_path) {
401 const bool kCreated = true;
402 DidCreateFile(file_path, error_code, file_handle, kCreated);
403 }
404
374 void URLFetcherImpl::Core::FileWriter::WriteBuffer(int num_bytes) { 405 void URLFetcherImpl::Core::FileWriter::WriteBuffer(int num_bytes) {
375 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread()); 406 DCHECK(core_->io_message_loop_proxy_->BelongsToCurrentThread());
376 407
377 // Start writing to the file by setting the initial state 408 // Start writing to the file by setting the initial state
378 // of |pending_bytes_| and |buffer_offset_| to indicate that the 409 // of |pending_bytes_| and |buffer_offset_| to indicate that the
379 // entire buffer has not yet been written. 410 // entire buffer has not yet been written.
380 pending_bytes_ = num_bytes; 411 pending_bytes_ = num_bytes;
381 buffer_offset_ = 0; 412 buffer_offset_ = 0;
382 ContinueWrite(base::PLATFORM_FILE_OK, 0); 413 ContinueWrite(base::PLATFORM_FILE_OK, 0);
383 } 414 }
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 } 607 }
577 608
578 void URLFetcherImpl::Core::StartOnIOThread() { 609 void URLFetcherImpl::Core::StartOnIOThread() {
579 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 610 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
580 611
581 switch (response_destination_) { 612 switch (response_destination_) {
582 case STRING: 613 case STRING:
583 StartURLRequestWhenAppropriate(); 614 StartURLRequestWhenAppropriate();
584 break; 615 break;
585 616
586 case FILE: 617 case PERMANENT_FILE:
618 case TEMP_FILE:
587 DCHECK(file_message_loop_proxy_.get()) 619 DCHECK(file_message_loop_proxy_.get())
588 << "Need to set the file message loop proxy."; 620 << "Need to set the file message loop proxy.";
589 621
590 file_writer_.reset( 622 file_writer_.reset(new FileWriter(this, file_message_loop_proxy_));
591 new FileWriter(this, file_message_loop_proxy_));
592 623
593 // If the temp file is successfully created, 624 // If the file is successfully created,
594 // Core::StartURLRequestWhenAppropriate() will be called. 625 // Core::StartURLRequestWhenAppropriate() will be called.
595 file_writer_->CreateTempFile(); 626 switch (response_destination_) {
627 case PERMANENT_FILE:
628 file_writer_->CreateFileAtPath(response_destination_file_path_);
629 break;
630 case TEMP_FILE:
631 file_writer_->CreateTempFile();
632 break;
633 default:
634 NOTREACHED();
635 }
596 break; 636 break;
597 637
598 default: 638 default:
599 NOTREACHED(); 639 NOTREACHED();
600 } 640 }
601 } 641 }
602 642
603 void URLFetcherImpl::Core::Stop() { 643 void URLFetcherImpl::Core::Stop() {
604 if (delegate_loop_proxy_) // May be NULL in tests. 644 if (delegate_loop_proxy_) // May be NULL in tests.
605 DCHECK(delegate_loop_proxy_->BelongsToCurrentThread()); 645 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 702 // Return false if the write is pending, and the next read will
663 // be done later. 703 // be done later.
664 bool URLFetcherImpl::Core::WriteBuffer(int num_bytes) { 704 bool URLFetcherImpl::Core::WriteBuffer(int num_bytes) {
665 bool write_complete = false; 705 bool write_complete = false;
666 switch (response_destination_) { 706 switch (response_destination_) {
667 case STRING: 707 case STRING:
668 data_.append(buffer_->data(), num_bytes); 708 data_.append(buffer_->data(), num_bytes);
669 write_complete = true; 709 write_complete = true;
670 break; 710 break;
671 711
672 case FILE: 712 case PERMANENT_FILE:
713 case TEMP_FILE:
673 file_writer_->WriteBuffer(num_bytes); 714 file_writer_->WriteBuffer(num_bytes);
674 // WriteBuffer() sends a request the file thread. 715 // WriteBuffer() sends a request the file thread.
675 // The write is not done yet. 716 // The write is not done yet.
676 write_complete = false; 717 write_complete = false;
677 break; 718 break;
678 719
679 default: 720 default:
680 NOTREACHED(); 721 NOTREACHED();
681 } 722 }
682 return write_complete; 723 return write_complete;
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 1066
1026 int URLFetcherImpl::GetMaxRetries() const { 1067 int URLFetcherImpl::GetMaxRetries() const {
1027 return core_->max_retries_; 1068 return core_->max_retries_;
1028 } 1069 }
1029 1070
1030 1071
1031 base::TimeDelta URLFetcherImpl::GetBackoffDelay() const { 1072 base::TimeDelta URLFetcherImpl::GetBackoffDelay() const {
1032 return core_->backoff_delay_; 1073 return core_->backoff_delay_;
1033 } 1074 }
1034 1075
1076 void URLFetcherImpl::SaveResponseToFileAtPath(
1077 const FilePath& file_path,
1078 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) {
1079 core_->file_message_loop_proxy_ = file_message_loop_proxy;
willchan no longer on Chromium 2012/03/08 16:38:39 Please DCHECK that this executes on the delegate m
hashimoto 2012/03/09 03:22:52 Done.
1080 core_->response_destination_ = PERMANENT_FILE;
1081 core_->response_destination_file_path_ = file_path;
1082 }
1083
1035 void URLFetcherImpl::SaveResponseToTemporaryFile( 1084 void URLFetcherImpl::SaveResponseToTemporaryFile(
1036 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) { 1085 scoped_refptr<base::MessageLoopProxy> file_message_loop_proxy) {
1037 core_->file_message_loop_proxy_ = file_message_loop_proxy; 1086 core_->file_message_loop_proxy_ = file_message_loop_proxy;
1038 core_->response_destination_ = FILE; 1087 core_->response_destination_ = TEMP_FILE;
1039 } 1088 }
1040 1089
1041 net::HttpResponseHeaders* URLFetcherImpl::GetResponseHeaders() const { 1090 net::HttpResponseHeaders* URLFetcherImpl::GetResponseHeaders() const {
1042 return core_->response_headers_; 1091 return core_->response_headers_;
1043 } 1092 }
1044 1093
1045 void URLFetcherImpl::set_response_headers( 1094 void URLFetcherImpl::set_response_headers(
1046 scoped_refptr<net::HttpResponseHeaders> headers) { 1095 scoped_refptr<net::HttpResponseHeaders> headers) {
1047 core_->response_headers_ = headers; 1096 core_->response_headers_ = headers;
1048 } 1097 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 *out_response_string = core_->data_; 1168 *out_response_string = core_->data_;
1120 UMA_HISTOGRAM_MEMORY_KB("UrlFetcher.StringResponseSize", 1169 UMA_HISTOGRAM_MEMORY_KB("UrlFetcher.StringResponseSize",
1121 (core_->data_.length() / 1024)); 1170 (core_->data_.length() / 1024));
1122 1171
1123 return true; 1172 return true;
1124 } 1173 }
1125 1174
1126 bool URLFetcherImpl::GetResponseAsFilePath(bool take_ownership, 1175 bool URLFetcherImpl::GetResponseAsFilePath(bool take_ownership,
1127 FilePath* out_response_path) const { 1176 FilePath* out_response_path) const {
1128 DCHECK(core_->delegate_loop_proxy_->BelongsToCurrentThread()); 1177 DCHECK(core_->delegate_loop_proxy_->BelongsToCurrentThread());
1129 if (core_->response_destination_ != FILE || !core_->file_writer_.get()) 1178 const bool destination_is_file = core_->response_destination_ == TEMP_FILE ||
1179 core_->response_destination_ == PERMANENT_FILE;
1180 if (!destination_is_file || !core_->file_writer_.get())
1130 return false; 1181 return false;
1131 1182
1132 *out_response_path = core_->file_writer_->file_path(); 1183 *out_response_path = core_->file_writer_->file_path();
1133 1184
1134 if (take_ownership) { 1185 if (take_ownership) {
1135 core_->io_message_loop_proxy_->PostTask( 1186 core_->io_message_loop_proxy_->PostTask(
1136 FROM_HERE, base::Bind(&Core::DisownFile, core_.get())); 1187 FROM_HERE, base::Bind(&Core::DisownFile, core_.get()));
1137 } 1188 }
1138 return true; 1189 return true;
1139 } 1190 }
(...skipping 14 matching lines...) Expand all
1154 1205
1155 // static 1206 // static
1156 content::URLFetcherFactory* URLFetcherImpl::factory() { 1207 content::URLFetcherFactory* URLFetcherImpl::factory() {
1157 return g_factory; 1208 return g_factory;
1158 } 1209 }
1159 1210
1160 // static 1211 // static
1161 void URLFetcherImpl::set_factory(content::URLFetcherFactory* factory) { 1212 void URLFetcherImpl::set_factory(content::URLFetcherFactory* factory) {
1162 g_factory = factory; 1213 g_factory = factory;
1163 } 1214 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698