| Index: storage/browser/blob/blob_reader.cc
|
| diff --git a/storage/browser/blob/blob_reader.cc b/storage/browser/blob/blob_reader.cc
|
| index 43735ce472292ceff2e5d600c6d06de56b7a2a86..470d89462f5b43f59a88ec924d330075a69ed2c8 100644
|
| --- a/storage/browser/blob/blob_reader.cc
|
| +++ b/storage/browser/blob/blob_reader.cc
|
| @@ -48,8 +48,8 @@ BlobReader::BlobReader(
|
| file_task_runner_(file_task_runner),
|
| net_error_(net::OK),
|
| weak_factory_(this) {
|
| - if (blob_handle) {
|
| - blob_data_ = blob_handle->CreateSnapshot();
|
| + if (blob_handle && !blob_handle->IsBroken()) {
|
| + blob_handle_.reset(new BlobDataHandle(*blob_handle));
|
| }
|
| }
|
|
|
| @@ -61,58 +61,20 @@ BlobReader::Status BlobReader::CalculateSize(
|
| const net::CompletionCallback& done) {
|
| DCHECK(!total_size_calculated_);
|
| DCHECK(size_callback_.is_null());
|
| - if (!blob_data_.get()) {
|
| + if (!blob_handle_.get() || blob_handle_->IsBroken()) {
|
| return ReportError(net::ERR_FILE_NOT_FOUND);
|
| }
|
| -
|
| - net_error_ = net::OK;
|
| - total_size_ = 0;
|
| - const auto& items = blob_data_->items();
|
| - item_length_list_.resize(items.size());
|
| - pending_get_file_info_count_ = 0;
|
| - for (size_t i = 0; i < items.size(); ++i) {
|
| - const BlobDataItem& item = *items.at(i);
|
| - if (IsFileType(item.type())) {
|
| - ++pending_get_file_info_count_;
|
| - storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i);
|
| - if (!reader) {
|
| - return ReportError(net::ERR_FAILED);
|
| - }
|
| - int64_t length_output = reader->GetLength(base::Bind(
|
| - &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i));
|
| - if (length_output == net::ERR_IO_PENDING) {
|
| - continue;
|
| - }
|
| - if (length_output < 0) {
|
| - return ReportError(length_output);
|
| - }
|
| - // We got the length right away
|
| - --pending_get_file_info_count_;
|
| - uint64_t resolved_length;
|
| - if (!ResolveFileItemLength(item, length_output, &resolved_length)) {
|
| - return ReportError(net::ERR_FILE_NOT_FOUND);
|
| - }
|
| - if (!AddItemLength(i, resolved_length)) {
|
| - return ReportError(net::ERR_FAILED);
|
| - }
|
| - continue;
|
| - }
|
| -
|
| - if (!AddItemLength(i, item.length()))
|
| - return ReportError(net::ERR_FAILED);
|
| - }
|
| -
|
| - if (pending_get_file_info_count_ == 0) {
|
| - DidCountSize();
|
| - return Status::DONE;
|
| + if (blob_handle_->IsBeingBuilt()) {
|
| + blob_handle_->RunOnConstructionComplete(base::Bind(
|
| + &BlobReader::AsyncCalculateSize, weak_factory_.GetWeakPtr(), done));
|
| + return Status::IO_PENDING;
|
| }
|
| - // Note: We only set the callback if we know that we're an async operation.
|
| - size_callback_ = done;
|
| - return Status::IO_PENDING;
|
| + blob_data_ = blob_handle_->CreateSnapshot();
|
| + return CalculateSizeImpl(done);
|
| }
|
|
|
| BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) {
|
| - if (!blob_data_.get()) {
|
| + if (!blob_handle_.get() || blob_handle_->IsBroken()) {
|
| return ReportError(net::ERR_FILE_NOT_FOUND);
|
| }
|
| if (!total_size_calculated_) {
|
| @@ -219,6 +181,70 @@ BlobReader::Status BlobReader::ReportError(int net_error) {
|
| return Status::NET_ERROR;
|
| }
|
|
|
| +void BlobReader::AsyncCalculateSize(const net::CompletionCallback& done,
|
| + bool async_succeeded) {
|
| + if (!async_succeeded) {
|
| + InvalidateCallbacksAndDone(net::ERR_FAILED, done);
|
| + return;
|
| + }
|
| + DCHECK(!blob_handle_->IsBroken()) << "Callback should have returned false.";
|
| + blob_data_ = blob_handle_->CreateSnapshot();
|
| + Status size_status = CalculateSizeImpl(done);
|
| + if (size_status == Status::NET_ERROR)
|
| + InvalidateCallbacksAndDone(net_error_, done);
|
| +}
|
| +
|
| +BlobReader::Status BlobReader::CalculateSizeImpl(
|
| + const net::CompletionCallback& done) {
|
| + DCHECK(!total_size_calculated_);
|
| + DCHECK(size_callback_.is_null());
|
| +
|
| + net_error_ = net::OK;
|
| + total_size_ = 0;
|
| + const auto& items = blob_data_->items();
|
| + item_length_list_.resize(items.size());
|
| + pending_get_file_info_count_ = 0;
|
| + for (size_t i = 0; i < items.size(); ++i) {
|
| + const BlobDataItem& item = *items.at(i);
|
| + if (IsFileType(item.type())) {
|
| + ++pending_get_file_info_count_;
|
| + storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i);
|
| + if (!reader) {
|
| + return ReportError(net::ERR_FAILED);
|
| + }
|
| + int64_t length_output = reader->GetLength(base::Bind(
|
| + &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i));
|
| + if (length_output == net::ERR_IO_PENDING) {
|
| + continue;
|
| + }
|
| + if (length_output < 0) {
|
| + return ReportError(length_output);
|
| + }
|
| + // We got the length right away
|
| + --pending_get_file_info_count_;
|
| + uint64_t resolved_length;
|
| + if (!ResolveFileItemLength(item, length_output, &resolved_length)) {
|
| + return ReportError(net::ERR_FILE_NOT_FOUND);
|
| + }
|
| + if (!AddItemLength(i, resolved_length)) {
|
| + return ReportError(net::ERR_FAILED);
|
| + }
|
| + continue;
|
| + }
|
| +
|
| + if (!AddItemLength(i, item.length()))
|
| + return ReportError(net::ERR_FAILED);
|
| + }
|
| +
|
| + if (pending_get_file_info_count_ == 0) {
|
| + DidCountSize();
|
| + return Status::DONE;
|
| + }
|
| + // Note: We only set the callback if we know that we're an async operation.
|
| + size_callback_ = done;
|
| + return Status::IO_PENDING;
|
| +}
|
| +
|
| bool BlobReader::AddItemLength(size_t index, uint64_t item_length) {
|
| if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) {
|
| return false;
|
|
|