Chromium Code Reviews| 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> |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "net/http/http_response_headers.h" | 27 #include "net/http/http_response_headers.h" |
| 28 #include "net/http/http_response_info.h" | 28 #include "net/http/http_response_info.h" |
| 29 #include "net/http/http_util.h" | 29 #include "net/http/http_util.h" |
| 30 #include "net/url_request/url_request.h" | 30 #include "net/url_request/url_request.h" |
| 31 #include "net/url_request/url_request_context.h" | 31 #include "net/url_request/url_request_context.h" |
| 32 #include "net/url_request/url_request_error_job.h" | 32 #include "net/url_request/url_request_error_job.h" |
| 33 #include "net/url_request/url_request_status.h" | 33 #include "net/url_request/url_request_status.h" |
| 34 #include "storage/browser/blob/file_stream_reader.h" | 34 #include "storage/browser/blob/file_stream_reader.h" |
| 35 #include "storage/browser/fileapi/file_system_context.h" | 35 #include "storage/browser/fileapi/file_system_context.h" |
| 36 #include "storage/browser/fileapi/file_system_url.h" | 36 #include "storage/browser/fileapi/file_system_url.h" |
| 37 #include "storage/common/data_element.h" | |
| 37 | 38 |
| 38 namespace storage { | 39 namespace storage { |
| 39 | 40 |
| 40 namespace { | 41 namespace { |
| 41 | 42 |
| 42 bool IsFileType(BlobData::Item::Type type) { | 43 bool IsFileType(DataElement::Type type) { |
| 43 switch (type) { | 44 switch (type) { |
| 44 case BlobData::Item::TYPE_FILE: | 45 case DataElement::TYPE_FILE: |
| 45 case BlobData::Item::TYPE_FILE_FILESYSTEM: | 46 case DataElement::TYPE_FILE_FILESYSTEM: |
| 46 return true; | 47 return true; |
| 47 default: | 48 default: |
| 48 return false; | 49 return false; |
| 49 } | 50 } |
| 50 } | 51 } |
| 51 | 52 |
| 52 } // namespace | 53 } // namespace |
| 53 | 54 |
| 54 BlobURLRequestJob::BlobURLRequestJob( | 55 BlobURLRequestJob::BlobURLRequestJob( |
| 55 net::URLRequest* request, | 56 net::URLRequest* request, |
| 56 net::NetworkDelegate* network_delegate, | 57 net::NetworkDelegate* network_delegate, |
| 57 const scoped_refptr<BlobData>& blob_data, | 58 scoped_ptr<BlobDataSnapshot> blob_data, |
| 58 storage::FileSystemContext* file_system_context, | 59 storage::FileSystemContext* file_system_context, |
| 59 base::MessageLoopProxy* file_thread_proxy) | 60 base::MessageLoopProxy* file_thread_proxy) |
| 60 : net::URLRequestJob(request, network_delegate), | 61 : net::URLRequestJob(request, network_delegate), |
| 61 blob_data_(blob_data), | 62 blob_data_(blob_data.Pass()), |
| 62 file_system_context_(file_system_context), | 63 file_system_context_(file_system_context), |
| 63 file_thread_proxy_(file_thread_proxy), | 64 file_thread_proxy_(file_thread_proxy), |
| 64 total_size_(0), | 65 total_size_(0), |
| 65 remaining_bytes_(0), | 66 remaining_bytes_(0), |
| 66 pending_get_file_info_count_(0), | 67 pending_get_file_info_count_(0), |
| 67 current_item_index_(0), | 68 current_item_index_(0), |
| 68 current_item_offset_(0), | 69 current_item_offset_(0), |
| 69 error_(false), | 70 error_(false), |
| 70 byte_range_set_(false), | 71 byte_range_set_(false), |
| 71 weak_factory_(this) { | 72 weak_factory_(this) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 void BlobURLRequestJob::DidStart() { | 168 void BlobURLRequestJob::DidStart() { |
| 168 error_ = false; | 169 error_ = false; |
| 169 | 170 |
| 170 // We only support GET request per the spec. | 171 // We only support GET request per the spec. |
| 171 if (request()->method() != "GET") { | 172 if (request()->method() != "GET") { |
| 172 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); | 173 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); |
| 173 return; | 174 return; |
| 174 } | 175 } |
| 175 | 176 |
| 176 // If the blob data is not present, bail out. | 177 // If the blob data is not present, bail out. |
| 177 if (!blob_data_.get()) { | 178 if (!blob_data_) { |
| 178 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 179 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
| 179 return; | 180 return; |
| 180 } | 181 } |
| 181 | 182 |
| 182 CountSize(); | 183 CountSize(); |
| 183 } | 184 } |
| 184 | 185 |
| 185 bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { | 186 bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { |
| 186 if (item_length > kint64max - total_size_) { | 187 if (item_length > kint64max - total_size_) { |
| 187 NotifyFailure(net::ERR_FAILED); | 188 NotifyFailure(net::ERR_FAILED); |
| 188 return false; | 189 return false; |
| 189 } | 190 } |
| 190 | 191 |
| 191 // Cache the size and add it to the total size. | 192 // Cache the size and add it to the total size. |
| 192 DCHECK_LT(index, item_length_list_.size()); | 193 DCHECK_LT(index, item_length_list_.size()); |
| 193 item_length_list_[index] = item_length; | 194 item_length_list_[index] = item_length; |
| 194 total_size_ += item_length; | 195 total_size_ += item_length; |
| 195 return true; | 196 return true; |
| 196 } | 197 } |
| 197 | 198 |
| 198 void BlobURLRequestJob::CountSize() { | 199 void BlobURLRequestJob::CountSize() { |
| 199 pending_get_file_info_count_ = 0; | 200 pending_get_file_info_count_ = 0; |
| 200 total_size_ = 0; | 201 total_size_ = 0; |
| 201 item_length_list_.resize(blob_data_->items().size()); | 202 const auto& items = blob_data_->items(); |
| 203 item_length_list_.resize(items.size()); | |
| 202 | 204 |
| 203 for (size_t i = 0; i < blob_data_->items().size(); ++i) { | 205 for (size_t i = 0; i < items.size(); ++i) { |
| 204 const BlobData::Item& item = blob_data_->items().at(i); | 206 const BlobDataItem& item = *items.at(i); |
| 205 if (IsFileType(item.type())) { | 207 if (IsFileType(item.type())) { |
| 206 ++pending_get_file_info_count_; | 208 ++pending_get_file_info_count_; |
| 207 GetFileStreamReader(i)->GetLength( | 209 GetFileStreamReader(i)->GetLength( |
| 208 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, | 210 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, |
| 209 weak_factory_.GetWeakPtr(), i)); | 211 weak_factory_.GetWeakPtr(), i)); |
| 210 continue; | 212 continue; |
| 211 } | 213 } |
| 212 | 214 |
| 213 if (!AddItemLength(i, item.length())) | 215 if (!AddItemLength(i, item.length())) |
| 214 return; | 216 return; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 return; | 252 return; |
| 251 | 253 |
| 252 if (result == net::ERR_UPLOAD_FILE_CHANGED) { | 254 if (result == net::ERR_UPLOAD_FILE_CHANGED) { |
| 253 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 255 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
| 254 return; | 256 return; |
| 255 } else if (result < 0) { | 257 } else if (result < 0) { |
| 256 NotifyFailure(result); | 258 NotifyFailure(result); |
| 257 return; | 259 return; |
| 258 } | 260 } |
| 259 | 261 |
| 260 DCHECK_LT(index, blob_data_->items().size()); | 262 auto& items = blob_data_->items(); |
|
michaeln
2015/01/22 02:18:09
const auto here too and below? (not sure the local
dmurph
2015/01/23 00:10:18
Changed here and elsewhere.
| |
| 261 const BlobData::Item& item = blob_data_->items().at(index); | 263 DCHECK_LT(index, items.size()); |
| 264 const BlobDataItem& item = *items.at(index); | |
| 262 DCHECK(IsFileType(item.type())); | 265 DCHECK(IsFileType(item.type())); |
| 263 | 266 |
| 264 uint64 file_length = result; | 267 uint64 file_length = result; |
| 265 uint64 item_offset = item.offset(); | 268 uint64 item_offset = item.offset(); |
| 266 uint64 item_length = item.length(); | 269 uint64 item_length = item.length(); |
| 267 | 270 |
| 268 if (item_offset > file_length) { | 271 if (item_offset > file_length) { |
| 269 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 272 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
| 270 return; | 273 return; |
| 271 } | 274 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 283 | 286 |
| 284 if (!AddItemLength(index, item_length)) | 287 if (!AddItemLength(index, item_length)) |
| 285 return; | 288 return; |
| 286 | 289 |
| 287 if (--pending_get_file_info_count_ == 0) | 290 if (--pending_get_file_info_count_ == 0) |
| 288 DidCountSize(net::OK); | 291 DidCountSize(net::OK); |
| 289 } | 292 } |
| 290 | 293 |
| 291 void BlobURLRequestJob::Seek(int64 offset) { | 294 void BlobURLRequestJob::Seek(int64 offset) { |
| 292 // Skip the initial items that are not in the range. | 295 // Skip the initial items that are not in the range. |
| 296 auto& items = blob_data_->items(); | |
| 293 for (current_item_index_ = 0; | 297 for (current_item_index_ = 0; |
| 294 current_item_index_ < blob_data_->items().size() && | 298 current_item_index_ < items.size() && |
| 295 offset >= item_length_list_[current_item_index_]; | 299 offset >= item_length_list_[current_item_index_]; |
| 296 ++current_item_index_) { | 300 ++current_item_index_) { |
| 297 offset -= item_length_list_[current_item_index_]; | 301 offset -= item_length_list_[current_item_index_]; |
| 298 } | 302 } |
| 299 | 303 |
| 300 // Set the offset that need to jump to for the first item in the range. | 304 // Set the offset that need to jump to for the first item in the range. |
| 301 current_item_offset_ = offset; | 305 current_item_offset_ = offset; |
| 302 | 306 |
| 303 if (offset == 0) | 307 if (offset == 0) |
| 304 return; | 308 return; |
| 305 | 309 |
| 306 // Adjust the offset of the first stream if it is of file type. | 310 // Adjust the offset of the first stream if it is of file type. |
| 307 const BlobData::Item& item = blob_data_->items().at(current_item_index_); | 311 const BlobDataItem& item = *items.at(current_item_index_); |
| 308 if (IsFileType(item.type())) { | 312 if (IsFileType(item.type())) { |
| 309 DeleteCurrentFileReader(); | 313 DeleteCurrentFileReader(); |
| 310 CreateFileStreamReader(current_item_index_, offset); | 314 CreateFileStreamReader(current_item_index_, offset); |
| 311 } | 315 } |
| 312 } | 316 } |
| 313 | 317 |
| 314 bool BlobURLRequestJob::ReadItem() { | 318 bool BlobURLRequestJob::ReadItem() { |
| 315 // Are we done with reading all the blob data? | 319 // Are we done with reading all the blob data? |
| 316 if (remaining_bytes_ == 0) | 320 if (remaining_bytes_ == 0) |
| 317 return true; | 321 return true; |
| 318 | 322 |
| 323 auto& items = blob_data_->items(); | |
| 319 // If we get to the last item but still expect something to read, bail out | 324 // If we get to the last item but still expect something to read, bail out |
| 320 // since something is wrong. | 325 // since something is wrong. |
| 321 if (current_item_index_ >= blob_data_->items().size()) { | 326 if (current_item_index_ >= items.size()) { |
| 322 NotifyFailure(net::ERR_FAILED); | 327 NotifyFailure(net::ERR_FAILED); |
| 323 return false; | 328 return false; |
| 324 } | 329 } |
| 325 | 330 |
| 326 // Compute the bytes to read for current item. | 331 // Compute the bytes to read for current item. |
| 327 int bytes_to_read = ComputeBytesToRead(); | 332 int bytes_to_read = ComputeBytesToRead(); |
| 328 | 333 |
| 329 // If nothing to read for current item, advance to next item. | 334 // If nothing to read for current item, advance to next item. |
| 330 if (bytes_to_read == 0) { | 335 if (bytes_to_read == 0) { |
| 331 AdvanceItem(); | 336 AdvanceItem(); |
| 332 return ReadItem(); | 337 return ReadItem(); |
| 333 } | 338 } |
| 334 | 339 |
| 335 // Do the reading. | 340 // Do the reading. |
| 336 const BlobData::Item& item = blob_data_->items().at(current_item_index_); | 341 const BlobDataItem& item = *items.at(current_item_index_); |
| 337 if (item.type() == BlobData::Item::TYPE_BYTES) | 342 if (item.type() == DataElement::TYPE_BYTES) |
| 338 return ReadBytesItem(item, bytes_to_read); | 343 return ReadBytesItem(item, bytes_to_read); |
| 339 if (IsFileType(item.type())) { | 344 if (IsFileType(item.type())) { |
| 340 return ReadFileItem(GetFileStreamReader(current_item_index_), | 345 return ReadFileItem(GetFileStreamReader(current_item_index_), |
| 341 bytes_to_read); | 346 bytes_to_read); |
| 342 } | 347 } |
| 343 NOTREACHED(); | 348 NOTREACHED(); |
| 344 return false; | 349 return false; |
| 345 } | 350 } |
| 346 | 351 |
| 347 void BlobURLRequestJob::AdvanceItem() { | 352 void BlobURLRequestJob::AdvanceItem() { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 363 | 368 |
| 364 // Subtract the remaining bytes. | 369 // Subtract the remaining bytes. |
| 365 remaining_bytes_ -= result; | 370 remaining_bytes_ -= result; |
| 366 DCHECK_GE(remaining_bytes_, 0); | 371 DCHECK_GE(remaining_bytes_, 0); |
| 367 | 372 |
| 368 // Adjust the read buffer. | 373 // Adjust the read buffer. |
| 369 read_buf_->DidConsume(result); | 374 read_buf_->DidConsume(result); |
| 370 DCHECK_GE(read_buf_->BytesRemaining(), 0); | 375 DCHECK_GE(read_buf_->BytesRemaining(), 0); |
| 371 } | 376 } |
| 372 | 377 |
| 373 bool BlobURLRequestJob::ReadBytesItem(const BlobData::Item& item, | 378 bool BlobURLRequestJob::ReadBytesItem(const BlobDataItem& item, |
| 374 int bytes_to_read) { | 379 int bytes_to_read) { |
| 375 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); | 380 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); |
| 376 | 381 |
| 377 memcpy(read_buf_->data(), | 382 memcpy(read_buf_->data(), |
| 378 item.bytes() + item.offset() + current_item_offset_, | 383 item.bytes() + item.offset() + current_item_offset_, |
| 379 bytes_to_read); | 384 bytes_to_read); |
| 380 | 385 |
| 381 AdvanceBytesRead(bytes_to_read); | 386 AdvanceBytesRead(bytes_to_read); |
| 382 return true; | 387 return true; |
| 383 } | 388 } |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 548 | 553 |
| 549 response_info_.reset(new net::HttpResponseInfo()); | 554 response_info_.reset(new net::HttpResponseInfo()); |
| 550 response_info_->headers = headers; | 555 response_info_->headers = headers; |
| 551 | 556 |
| 552 set_expected_content_size(remaining_bytes_); | 557 set_expected_content_size(remaining_bytes_); |
| 553 | 558 |
| 554 NotifyHeadersComplete(); | 559 NotifyHeadersComplete(); |
| 555 } | 560 } |
| 556 | 561 |
| 557 FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { | 562 FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { |
| 558 DCHECK_LT(index, blob_data_->items().size()); | 563 auto& items = blob_data_->items(); |
| 559 const BlobData::Item& item = blob_data_->items().at(index); | 564 DCHECK_LT(index, items.size()); |
| 565 const BlobDataItem& item = *items.at(index); | |
| 560 if (!IsFileType(item.type())) | 566 if (!IsFileType(item.type())) |
| 561 return NULL; | 567 return NULL; |
| 562 if (index_to_reader_.find(index) == index_to_reader_.end()) | 568 if (index_to_reader_.find(index) == index_to_reader_.end()) |
| 563 CreateFileStreamReader(index, 0); | 569 CreateFileStreamReader(index, 0); |
| 564 DCHECK(index_to_reader_[index]); | 570 DCHECK(index_to_reader_[index]); |
| 565 return index_to_reader_[index]; | 571 return index_to_reader_[index]; |
| 566 } | 572 } |
| 567 | 573 |
| 568 void BlobURLRequestJob::CreateFileStreamReader(size_t index, | 574 void BlobURLRequestJob::CreateFileStreamReader(size_t index, |
| 569 int64 additional_offset) { | 575 int64 additional_offset) { |
| 570 DCHECK_LT(index, blob_data_->items().size()); | 576 auto& items = blob_data_->items(); |
| 571 const BlobData::Item& item = blob_data_->items().at(index); | 577 DCHECK_LT(index, items.size()); |
| 578 const BlobDataItem& item = *items.at(index); | |
| 572 DCHECK(IsFileType(item.type())); | 579 DCHECK(IsFileType(item.type())); |
| 573 DCHECK_EQ(0U, index_to_reader_.count(index)); | 580 DCHECK_EQ(0U, index_to_reader_.count(index)); |
| 574 | 581 |
| 575 FileStreamReader* reader = NULL; | 582 FileStreamReader* reader = NULL; |
| 576 switch (item.type()) { | 583 switch (item.type()) { |
| 577 case BlobData::Item::TYPE_FILE: | 584 case DataElement::TYPE_FILE: |
| 578 reader = FileStreamReader::CreateForLocalFile( | 585 reader = FileStreamReader::CreateForLocalFile( |
| 579 file_thread_proxy_.get(), | 586 file_thread_proxy_.get(), |
| 580 item.path(), | 587 item.path(), |
| 581 item.offset() + additional_offset, | 588 item.offset() + additional_offset, |
| 582 item.expected_modification_time()); | 589 item.expected_modification_time()); |
| 583 break; | 590 break; |
| 584 case BlobData::Item::TYPE_FILE_FILESYSTEM: | 591 case DataElement::TYPE_FILE_FILESYSTEM: |
| 585 reader = file_system_context_ | 592 reader = file_system_context_ |
| 586 ->CreateFileStreamReader( | 593 ->CreateFileStreamReader( |
| 587 storage::FileSystemURL(file_system_context_->CrackURL( | 594 storage::FileSystemURL(file_system_context_->CrackURL( |
| 588 item.filesystem_url())), | 595 item.filesystem_url())), |
| 589 item.offset() + additional_offset, | 596 item.offset() + additional_offset, |
| 590 item.length() == std::numeric_limits<uint64>::max() | 597 item.length() == std::numeric_limits<uint64>::max() |
| 591 ? storage::kMaximumLength | 598 ? storage::kMaximumLength |
| 592 : item.length() - additional_offset, | 599 : item.length() - additional_offset, |
| 593 item.expected_modification_time()) | 600 item.expected_modification_time()) |
| 594 .release(); | 601 .release(); |
| 595 break; | 602 break; |
| 596 default: | 603 default: |
| 597 NOTREACHED(); | 604 NOTREACHED(); |
| 598 } | 605 } |
| 599 DCHECK(reader); | 606 DCHECK(reader); |
| 600 index_to_reader_[index] = reader; | 607 index_to_reader_[index] = reader; |
| 601 } | 608 } |
| 602 | 609 |
| 603 } // namespace storage | 610 } // namespace storage |
| OLD | NEW |