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 "storage/browser/blob/blob_url_request_job.h" | 5 #include "storage/browser/blob/blob_url_request_job.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
15 #include "base/files/file_util_proxy.h" | 15 #include "base/files/file_util_proxy.h" |
16 #include "base/format_macros.h" | 16 #include "base/format_macros.h" |
17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
18 #include "base/message_loop/message_loop_proxy.h" | 18 #include "base/message_loop/message_loop_proxy.h" |
19 #include "base/numerics/safe_conversions.h" | 19 #include "base/numerics/safe_conversions.h" |
20 #include "base/profiler/scoped_tracker.h" | 20 #include "base/profiler/scoped_tracker.h" |
21 #include "base/stl_util.h" | 21 #include "base/stl_util.h" |
22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
23 #include "base/strings/stringprintf.h" | 23 #include "base/strings/stringprintf.h" |
| 24 #include "base/trace_event/trace_event.h" |
24 #include "net/base/io_buffer.h" | 25 #include "net/base/io_buffer.h" |
25 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
26 #include "net/http/http_request_headers.h" | 27 #include "net/http/http_request_headers.h" |
27 #include "net/http/http_response_headers.h" | 28 #include "net/http/http_response_headers.h" |
28 #include "net/http/http_response_info.h" | 29 #include "net/http/http_response_info.h" |
29 #include "net/http/http_util.h" | 30 #include "net/http/http_util.h" |
30 #include "net/url_request/url_request.h" | 31 #include "net/url_request/url_request.h" |
31 #include "net/url_request/url_request_context.h" | 32 #include "net/url_request/url_request_context.h" |
32 #include "net/url_request/url_request_error_job.h" | 33 #include "net/url_request/url_request_error_job.h" |
33 #include "net/url_request/url_request_status.h" | 34 #include "net/url_request/url_request_status.h" |
(...skipping 29 matching lines...) Expand all Loading... |
63 file_system_context_(file_system_context), | 64 file_system_context_(file_system_context), |
64 file_thread_proxy_(file_thread_proxy), | 65 file_thread_proxy_(file_thread_proxy), |
65 total_size_(0), | 66 total_size_(0), |
66 remaining_bytes_(0), | 67 remaining_bytes_(0), |
67 pending_get_file_info_count_(0), | 68 pending_get_file_info_count_(0), |
68 current_item_index_(0), | 69 current_item_index_(0), |
69 current_item_offset_(0), | 70 current_item_offset_(0), |
70 error_(false), | 71 error_(false), |
71 byte_range_set_(false), | 72 byte_range_set_(false), |
72 weak_factory_(this) { | 73 weak_factory_(this) { |
| 74 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest", this, "uuid", |
| 75 blob_data_->uuid()); |
73 DCHECK(file_thread_proxy_.get()); | 76 DCHECK(file_thread_proxy_.get()); |
74 } | 77 } |
75 | 78 |
76 void BlobURLRequestJob::Start() { | 79 void BlobURLRequestJob::Start() { |
77 // Continue asynchronously. | 80 // Continue asynchronously. |
78 base::MessageLoop::current()->PostTask( | 81 base::MessageLoop::current()->PostTask( |
79 FROM_HERE, | 82 FROM_HERE, |
80 base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); | 83 base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); |
81 } | 84 } |
82 | 85 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 // because we need to do multipart encoding here. | 159 // because we need to do multipart encoding here. |
157 // TODO(jianli): Support multipart byte range requests. | 160 // TODO(jianli): Support multipart byte range requests. |
158 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); | 161 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); |
159 } | 162 } |
160 } | 163 } |
161 } | 164 } |
162 } | 165 } |
163 | 166 |
164 BlobURLRequestJob::~BlobURLRequestJob() { | 167 BlobURLRequestJob::~BlobURLRequestJob() { |
165 STLDeleteValues(&index_to_reader_); | 168 STLDeleteValues(&index_to_reader_); |
| 169 TRACE_EVENT_ASYNC_END1("Blob", "Request", this, "uuid", blob_data_->uuid()); |
166 } | 170 } |
167 | 171 |
168 void BlobURLRequestJob::DidStart() { | 172 void BlobURLRequestJob::DidStart() { |
| 173 current_file_chunk_number_ = 0; |
169 error_ = false; | 174 error_ = false; |
170 | 175 |
171 // We only support GET request per the spec. | 176 // We only support GET request per the spec. |
172 if (request()->method() != "GET") { | 177 if (request()->method() != "GET") { |
173 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); | 178 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); |
174 return; | 179 return; |
175 } | 180 } |
176 | 181 |
177 // If the blob data is not present, bail out. | 182 // If the blob data is not present, bail out. |
178 if (!blob_data_) { | 183 if (!blob_data_) { |
179 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 184 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
180 return; | 185 return; |
181 } | 186 } |
182 | 187 |
183 CountSize(); | 188 CountSize(); |
184 } | 189 } |
185 | 190 |
186 bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { | 191 bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { |
187 if (item_length > kint64max - total_size_) { | 192 if (item_length > kint64max - total_size_) { |
| 193 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::CountSize", this, "uuid", |
| 194 blob_data_->uuid()); |
188 NotifyFailure(net::ERR_FAILED); | 195 NotifyFailure(net::ERR_FAILED); |
189 return false; | 196 return false; |
190 } | 197 } |
191 | 198 |
192 // Cache the size and add it to the total size. | 199 // Cache the size and add it to the total size. |
193 DCHECK_LT(index, item_length_list_.size()); | 200 DCHECK_LT(index, item_length_list_.size()); |
194 item_length_list_[index] = item_length; | 201 item_length_list_[index] = item_length; |
195 total_size_ += item_length; | 202 total_size_ += item_length; |
196 return true; | 203 return true; |
197 } | 204 } |
198 | 205 |
199 void BlobURLRequestJob::CountSize() { | 206 void BlobURLRequestJob::CountSize() { |
| 207 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::CountSize", this, "uuid", |
| 208 blob_data_->uuid()); |
200 pending_get_file_info_count_ = 0; | 209 pending_get_file_info_count_ = 0; |
201 total_size_ = 0; | 210 total_size_ = 0; |
202 const auto& items = blob_data_->items(); | 211 const auto& items = blob_data_->items(); |
203 item_length_list_.resize(items.size()); | 212 item_length_list_.resize(items.size()); |
204 | 213 |
205 for (size_t i = 0; i < items.size(); ++i) { | 214 for (size_t i = 0; i < items.size(); ++i) { |
206 const BlobDataItem& item = *items.at(i); | 215 const BlobDataItem& item = *items.at(i); |
207 if (IsFileType(item.type())) { | 216 if (IsFileType(item.type())) { |
208 ++pending_get_file_info_count_; | 217 ++pending_get_file_info_count_; |
209 GetFileStreamReader(i)->GetLength( | 218 GetFileStreamReader(i)->GetLength( |
210 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, | 219 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, |
211 weak_factory_.GetWeakPtr(), i)); | 220 weak_factory_.GetWeakPtr(), i)); |
212 continue; | 221 continue; |
213 } | 222 } |
214 | 223 |
215 if (!AddItemLength(i, item.length())) | 224 if (!AddItemLength(i, item.length())) |
216 return; | 225 return; |
217 } | 226 } |
218 | 227 |
219 if (pending_get_file_info_count_ == 0) | 228 if (pending_get_file_info_count_ == 0) |
220 DidCountSize(net::OK); | 229 DidCountSize(net::OK); |
221 } | 230 } |
222 | 231 |
223 void BlobURLRequestJob::DidCountSize(int error) { | 232 void BlobURLRequestJob::DidCountSize(int error) { |
224 DCHECK(!error_); | 233 DCHECK(!error_); |
| 234 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::CountSize", this, "uuid", |
| 235 blob_data_->uuid()); |
225 | 236 |
226 // If an error occured, bail out. | 237 // If an error occured, bail out. |
227 if (error != net::OK) { | 238 if (error != net::OK) { |
228 NotifyFailure(error); | 239 NotifyFailure(error); |
229 return; | 240 return; |
230 } | 241 } |
231 | 242 |
232 // Apply the range requirement. | 243 // Apply the range requirement. |
233 if (!byte_range_.ComputeBounds(total_size_)) { | 244 if (!byte_range_.ComputeBounds(total_size_)) { |
234 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); | 245 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 remaining_bytes_ -= result; | 381 remaining_bytes_ -= result; |
371 DCHECK_GE(remaining_bytes_, 0); | 382 DCHECK_GE(remaining_bytes_, 0); |
372 | 383 |
373 // Adjust the read buffer. | 384 // Adjust the read buffer. |
374 read_buf_->DidConsume(result); | 385 read_buf_->DidConsume(result); |
375 DCHECK_GE(read_buf_->BytesRemaining(), 0); | 386 DCHECK_GE(read_buf_->BytesRemaining(), 0); |
376 } | 387 } |
377 | 388 |
378 bool BlobURLRequestJob::ReadBytesItem(const BlobDataItem& item, | 389 bool BlobURLRequestJob::ReadBytesItem(const BlobDataItem& item, |
379 int bytes_to_read) { | 390 int bytes_to_read) { |
| 391 TRACE_EVENT1("Blob", "BlobRequest::ReadBytesItem", "uuid", |
| 392 blob_data_->uuid()); |
380 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); | 393 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); |
381 | 394 |
382 memcpy(read_buf_->data(), | 395 memcpy(read_buf_->data(), |
383 item.bytes() + item.offset() + current_item_offset_, | 396 item.bytes() + item.offset() + current_item_offset_, |
384 bytes_to_read); | 397 bytes_to_read); |
385 | 398 |
386 AdvanceBytesRead(bytes_to_read); | 399 AdvanceBytesRead(bytes_to_read); |
387 return true; | 400 return true; |
388 } | 401 } |
389 | 402 |
390 bool BlobURLRequestJob::ReadFileItem(FileStreamReader* reader, | 403 bool BlobURLRequestJob::ReadFileItem(FileStreamReader* reader, |
391 int bytes_to_read) { | 404 int bytes_to_read) { |
392 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); | 405 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); |
393 DCHECK(reader); | 406 DCHECK(reader); |
394 const int result = reader->Read( | 407 int chunk_number = current_file_chunk_number_++; |
395 read_buf_.get(), | 408 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadFileItem", this, "uuid", |
396 bytes_to_read, | 409 blob_data_->uuid()); |
397 base::Bind(&BlobURLRequestJob::DidReadFile, base::Unretained(this))); | 410 const int result = |
| 411 reader->Read(read_buf_.get(), bytes_to_read, |
| 412 base::Bind(&BlobURLRequestJob::DidReadFile, |
| 413 base::Unretained(this), chunk_number)); |
398 if (result >= 0) { | 414 if (result >= 0) { |
399 // Data is immediately available. | 415 // Data is immediately available. |
400 if (GetStatus().is_io_pending()) | 416 if (GetStatus().is_io_pending()) |
401 DidReadFile(result); | 417 DidReadFile(chunk_number, result); |
402 else | 418 else |
403 AdvanceBytesRead(result); | 419 AdvanceBytesRead(result); |
404 return true; | 420 return true; |
405 } | 421 } |
406 if (result == net::ERR_IO_PENDING) | 422 if (result == net::ERR_IO_PENDING) |
407 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | 423 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
408 else | 424 else |
409 NotifyFailure(result); | 425 NotifyFailure(result); |
410 return false; | 426 return false; |
411 } | 427 } |
412 | 428 |
413 void BlobURLRequestJob::DidReadFile(int result) { | 429 void BlobURLRequestJob::DidReadFile(int chunk_number, int result) { |
| 430 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadFileItem", this, "uuid", |
| 431 blob_data_->uuid()); |
414 if (result <= 0) { | 432 if (result <= 0) { |
415 NotifyFailure(net::ERR_FAILED); | 433 NotifyFailure(net::ERR_FAILED); |
416 return; | 434 return; |
417 } | 435 } |
418 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status | 436 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status |
419 | 437 |
420 AdvanceBytesRead(result); | 438 AdvanceBytesRead(result); |
421 | 439 |
422 // If the read buffer is completely filled, we're done. | 440 // If the read buffer is completely filled, we're done. |
423 if (!read_buf_->BytesRemaining()) { | 441 if (!read_buf_->BytesRemaining()) { |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 .release(); | 619 .release(); |
602 break; | 620 break; |
603 default: | 621 default: |
604 NOTREACHED(); | 622 NOTREACHED(); |
605 } | 623 } |
606 DCHECK(reader); | 624 DCHECK(reader); |
607 index_to_reader_[index] = reader; | 625 index_to_reader_[index] = reader; |
608 } | 626 } |
609 | 627 |
610 } // namespace storage | 628 } // namespace storage |
OLD | NEW |