OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |