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