| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_reader.h" | 5 #include "storage/browser/blob/blob_reader.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 | 39 |
| 40 BlobReader::BlobReader( | 40 BlobReader::BlobReader( |
| 41 const BlobDataHandle* blob_handle, | 41 const BlobDataHandle* blob_handle, |
| 42 scoped_ptr<FileStreamReaderProvider> file_stream_provider, | 42 scoped_ptr<FileStreamReaderProvider> file_stream_provider, |
| 43 base::SequencedTaskRunner* file_task_runner) | 43 base::SequencedTaskRunner* file_task_runner) |
| 44 : file_stream_provider_(file_stream_provider.Pass()), | 44 : file_stream_provider_(file_stream_provider.Pass()), |
| 45 file_task_runner_(file_task_runner), | 45 file_task_runner_(file_task_runner), |
| 46 net_error_(net::OK), | 46 net_error_(net::OK), |
| 47 weak_factory_(this) { | 47 weak_factory_(this) { |
| 48 if (blob_handle) { | 48 if (blob_handle) { |
| 49 blob_data_ = blob_handle->CreateSnapshot().Pass(); | 49 blob_handle_.reset(new BlobDataHandle(*blob_handle)); |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 BlobReader::~BlobReader() { | 53 BlobReader::~BlobReader() { |
| 54 STLDeleteValues(&index_to_reader_); | 54 STLDeleteValues(&index_to_reader_); |
| 55 } | 55 } |
| 56 | 56 |
| 57 BlobReader::Status BlobReader::CalculateSize( | 57 BlobReader::Status BlobReader::CalculateSize( |
| 58 const net::CompletionCallback& done) { | 58 const net::CompletionCallback& done) { |
| 59 DCHECK(!total_size_calculated_); | 59 DCHECK(!total_size_calculated_); |
| 60 DCHECK(size_callback_.is_null()); | 60 DCHECK(size_callback_.is_null()); |
| 61 if (!blob_data_.get()) { | 61 if (!blob_handle_.get()) { |
| 62 return ReportError(net::ERR_FILE_NOT_FOUND); | 62 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 63 } | 63 } |
| 64 | 64 if (blob_handle_->IsAsyncConstructing()) { |
| 65 net_error_ = net::OK; | 65 blob_handle_->RunOnConstructionComplete(base::Bind( |
| 66 total_size_ = 0; | 66 &BlobReader::AsyncCalculateSize, weak_factory_.GetWeakPtr(), done)); |
| 67 const auto& items = blob_data_->items(); | 67 return Status::IO_PENDING; |
| 68 item_length_list_.resize(items.size()); | |
| 69 pending_get_file_info_count_ = 0; | |
| 70 for (size_t i = 0; i < items.size(); ++i) { | |
| 71 const BlobDataItem& item = *items.at(i); | |
| 72 if (IsFileType(item.type())) { | |
| 73 ++pending_get_file_info_count_; | |
| 74 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i); | |
| 75 if (!reader) { | |
| 76 return ReportError(net::ERR_FAILED); | |
| 77 } | |
| 78 int64_t length_output = reader->GetLength(base::Bind( | |
| 79 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i)); | |
| 80 if (length_output == net::ERR_IO_PENDING) { | |
| 81 continue; | |
| 82 } | |
| 83 if (length_output < 0) { | |
| 84 return ReportError(length_output); | |
| 85 } | |
| 86 // We got the length right away | |
| 87 --pending_get_file_info_count_; | |
| 88 uint64_t resolved_length; | |
| 89 if (!ResolveFileItemLength(item, length_output, &resolved_length)) { | |
| 90 return ReportError(net::ERR_FILE_NOT_FOUND); | |
| 91 } | |
| 92 if (!AddItemLength(i, resolved_length)) { | |
| 93 return ReportError(net::ERR_FAILED); | |
| 94 } | |
| 95 continue; | |
| 96 } | |
| 97 | |
| 98 if (!AddItemLength(i, item.length())) | |
| 99 return ReportError(net::ERR_FAILED); | |
| 100 } | 68 } |
| 101 | 69 blob_data_ = blob_handle_->CreateSnapshot().Pass(); |
| 102 if (pending_get_file_info_count_ == 0) { | 70 return CalculateSizeImpl(done); |
| 103 DidCountSize(); | |
| 104 return Status::DONE; | |
| 105 } | |
| 106 // Note: We only set the callback if we know that we're an async operation. | |
| 107 size_callback_ = done; | |
| 108 return Status::IO_PENDING; | |
| 109 } | 71 } |
| 110 | 72 |
| 111 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { | 73 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { |
| 112 if (!blob_data_.get()) { | 74 if (!blob_handle_.get()) { |
| 113 return ReportError(net::ERR_FILE_NOT_FOUND); | 75 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 114 } | 76 } |
| 115 if (!total_size_calculated_) { | 77 if (!total_size_calculated_) { |
| 116 return ReportError(net::ERR_FAILED); | 78 return ReportError(net::ERR_FAILED); |
| 117 } | 79 } |
| 118 if (offset + length > total_size_) { | 80 if (offset + length > total_size_) { |
| 119 return ReportError(net::ERR_FILE_NOT_FOUND); | 81 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 120 } | 82 } |
| 121 // Skip the initial items that are not in the range. | 83 // Skip the initial items that are not in the range. |
| 122 remaining_bytes_ = length; | 84 remaining_bytes_ = length; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 read_callback_.Reset(); | 171 read_callback_.Reset(); |
| 210 read_buf_ = nullptr; | 172 read_buf_ = nullptr; |
| 211 done.Run(net_error); | 173 done.Run(net_error); |
| 212 } | 174 } |
| 213 | 175 |
| 214 BlobReader::Status BlobReader::ReportError(int net_error) { | 176 BlobReader::Status BlobReader::ReportError(int net_error) { |
| 215 net_error_ = net_error; | 177 net_error_ = net_error; |
| 216 return Status::NET_ERROR; | 178 return Status::NET_ERROR; |
| 217 } | 179 } |
| 218 | 180 |
| 181 void BlobReader::AsyncCalculateSize(const net::CompletionCallback& done, |
| 182 bool async_succeeded) { |
| 183 if (!async_succeeded) { |
| 184 InvalidateCallbacksAndDone(net::ERR_FAILED, done); |
| 185 } |
| 186 blob_data_ = blob_handle_->CreateSnapshot().Pass(); |
| 187 Status size_status = CalculateSizeImpl(done); |
| 188 switch (size_status) { |
| 189 case Status::DONE: |
| 190 case Status::IO_PENDING: |
| 191 return; |
| 192 case Status::NET_ERROR: |
| 193 InvalidateCallbacksAndDone(net_error_, done); |
| 194 return; |
| 195 } |
| 196 } |
| 197 |
| 198 BlobReader::Status BlobReader::CalculateSizeImpl( |
| 199 const net::CompletionCallback& done) { |
| 200 DCHECK(!total_size_calculated_); |
| 201 DCHECK(size_callback_.is_null()); |
| 202 |
| 203 net_error_ = net::OK; |
| 204 total_size_ = 0; |
| 205 const auto& items = blob_data_->items(); |
| 206 item_length_list_.resize(items.size()); |
| 207 pending_get_file_info_count_ = 0; |
| 208 for (size_t i = 0; i < items.size(); ++i) { |
| 209 const BlobDataItem& item = *items.at(i); |
| 210 if (IsFileType(item.type())) { |
| 211 ++pending_get_file_info_count_; |
| 212 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i); |
| 213 if (!reader) { |
| 214 return ReportError(net::ERR_FAILED); |
| 215 } |
| 216 int64_t length_output = reader->GetLength(base::Bind( |
| 217 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i)); |
| 218 if (length_output == net::ERR_IO_PENDING) { |
| 219 continue; |
| 220 } |
| 221 if (length_output < 0) { |
| 222 return ReportError(length_output); |
| 223 } |
| 224 // We got the length right away |
| 225 --pending_get_file_info_count_; |
| 226 uint64_t resolved_length; |
| 227 if (!ResolveFileItemLength(item, length_output, &resolved_length)) { |
| 228 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 229 } |
| 230 if (!AddItemLength(i, resolved_length)) { |
| 231 return ReportError(net::ERR_FAILED); |
| 232 } |
| 233 continue; |
| 234 } |
| 235 |
| 236 if (!AddItemLength(i, item.length())) |
| 237 return ReportError(net::ERR_FAILED); |
| 238 } |
| 239 |
| 240 if (pending_get_file_info_count_ == 0) { |
| 241 DidCountSize(); |
| 242 return Status::DONE; |
| 243 } |
| 244 // Note: We only set the callback if we know that we're an async operation. |
| 245 size_callback_ = done; |
| 246 return Status::IO_PENDING; |
| 247 } |
| 248 |
| 219 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { | 249 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { |
| 220 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { | 250 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { |
| 221 return false; | 251 return false; |
| 222 } | 252 } |
| 223 | 253 |
| 224 // Cache the size and add it to the total size. | 254 // Cache the size and add it to the total size. |
| 225 DCHECK_LT(index, item_length_list_.size()); | 255 DCHECK_LT(index, item_length_list_.size()); |
| 226 item_length_list_[index] = item_length; | 256 item_length_list_[index] = item_length; |
| 227 total_size_ += item_length; | 257 total_size_ += item_length; |
| 228 return true; | 258 return true; |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 index_to_reader_.erase(found); | 590 index_to_reader_.erase(found); |
| 561 return; | 591 return; |
| 562 } | 592 } |
| 563 found->second = reader.release(); | 593 found->second = reader.release(); |
| 564 } else if (reader.get()) { | 594 } else if (reader.get()) { |
| 565 index_to_reader_[current_item_index_] = reader.release(); | 595 index_to_reader_[current_item_index_] = reader.release(); |
| 566 } | 596 } |
| 567 } | 597 } |
| 568 | 598 |
| 569 } // namespace storage | 599 } // namespace storage |
| OLD | NEW |