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> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/callback_helpers.h" |
14 #include "base/sequenced_task_runner.h" | 15 #include "base/sequenced_task_runner.h" |
15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
16 #include "base/time/time.h" | 17 #include "base/time/time.h" |
17 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
18 #include "net/base/io_buffer.h" | 19 #include "net/base/io_buffer.h" |
19 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
20 #include "net/disk_cache/disk_cache.h" | 21 #include "net/disk_cache/disk_cache.h" |
21 #include "storage/browser/blob/blob_data_handle.h" | 22 #include "storage/browser/blob/blob_data_handle.h" |
22 #include "storage/browser/blob/blob_data_snapshot.h" | 23 #include "storage/browser/blob/blob_data_snapshot.h" |
23 #include "storage/browser/fileapi/file_stream_reader.h" | 24 #include "storage/browser/fileapi/file_stream_reader.h" |
(...skipping 17 matching lines...) Expand all Loading... |
41 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {} | 42 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {} |
42 | 43 |
43 BlobReader::BlobReader( | 44 BlobReader::BlobReader( |
44 const BlobDataHandle* blob_handle, | 45 const BlobDataHandle* blob_handle, |
45 scoped_ptr<FileStreamReaderProvider> file_stream_provider, | 46 scoped_ptr<FileStreamReaderProvider> file_stream_provider, |
46 base::SequencedTaskRunner* file_task_runner) | 47 base::SequencedTaskRunner* file_task_runner) |
47 : file_stream_provider_(std::move(file_stream_provider)), | 48 : file_stream_provider_(std::move(file_stream_provider)), |
48 file_task_runner_(file_task_runner), | 49 file_task_runner_(file_task_runner), |
49 net_error_(net::OK), | 50 net_error_(net::OK), |
50 weak_factory_(this) { | 51 weak_factory_(this) { |
51 if (blob_handle) { | 52 if (blob_handle && !blob_handle->IsBroken()) { |
52 blob_data_ = blob_handle->CreateSnapshot(); | 53 blob_handle_.reset(new BlobDataHandle(*blob_handle)); |
53 } | 54 } |
54 } | 55 } |
55 | 56 |
56 BlobReader::~BlobReader() { | 57 BlobReader::~BlobReader() { |
57 STLDeleteValues(&index_to_reader_); | 58 STLDeleteValues(&index_to_reader_); |
58 } | 59 } |
59 | 60 |
60 BlobReader::Status BlobReader::CalculateSize( | 61 BlobReader::Status BlobReader::CalculateSize( |
61 const net::CompletionCallback& done) { | 62 const net::CompletionCallback& done) { |
62 DCHECK(!total_size_calculated_); | 63 DCHECK(!total_size_calculated_); |
63 DCHECK(size_callback_.is_null()); | 64 DCHECK(size_callback_.is_null()); |
64 if (!blob_data_.get()) { | 65 if (!blob_handle_.get() || blob_handle_->IsBroken()) { |
65 return ReportError(net::ERR_FILE_NOT_FOUND); | 66 return ReportError(net::ERR_FILE_NOT_FOUND); |
66 } | 67 } |
67 | 68 if (blob_handle_->IsBeingBuilt()) { |
68 net_error_ = net::OK; | 69 blob_handle_->RunOnConstructionComplete(base::Bind( |
69 total_size_ = 0; | 70 &BlobReader::AsyncCalculateSize, weak_factory_.GetWeakPtr(), done)); |
70 const auto& items = blob_data_->items(); | 71 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 } | 72 } |
104 | 73 blob_data_ = blob_handle_->CreateSnapshot(); |
105 if (pending_get_file_info_count_ == 0) { | 74 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 } | 75 } |
113 | 76 |
114 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { | 77 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { |
115 if (!blob_data_.get()) { | 78 if (!blob_handle_.get() || blob_handle_->IsBroken()) { |
116 return ReportError(net::ERR_FILE_NOT_FOUND); | 79 return ReportError(net::ERR_FILE_NOT_FOUND); |
117 } | 80 } |
118 if (!total_size_calculated_) { | 81 if (!total_size_calculated_) { |
119 return ReportError(net::ERR_FAILED); | 82 return ReportError(net::ERR_FAILED); |
120 } | 83 } |
121 if (offset + length > total_size_) { | 84 if (offset + length > total_size_) { |
122 return ReportError(net::ERR_FILE_NOT_FOUND); | 85 return ReportError(net::ERR_FILE_NOT_FOUND); |
123 } | 86 } |
124 // Skip the initial items that are not in the range. | 87 // Skip the initial items that are not in the range. |
125 remaining_bytes_ = length; | 88 remaining_bytes_ = length; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 read_callback_.Reset(); | 175 read_callback_.Reset(); |
213 read_buf_ = nullptr; | 176 read_buf_ = nullptr; |
214 done.Run(net_error); | 177 done.Run(net_error); |
215 } | 178 } |
216 | 179 |
217 BlobReader::Status BlobReader::ReportError(int net_error) { | 180 BlobReader::Status BlobReader::ReportError(int net_error) { |
218 net_error_ = net_error; | 181 net_error_ = net_error; |
219 return Status::NET_ERROR; | 182 return Status::NET_ERROR; |
220 } | 183 } |
221 | 184 |
| 185 void BlobReader::AsyncCalculateSize(const net::CompletionCallback& done, |
| 186 bool async_succeeded) { |
| 187 if (!async_succeeded) { |
| 188 InvalidateCallbacksAndDone(net::ERR_FAILED, done); |
| 189 return; |
| 190 } |
| 191 DCHECK(!blob_handle_->IsBroken()) << "Callback should have returned false."; |
| 192 blob_data_ = blob_handle_->CreateSnapshot(); |
| 193 Status size_status = CalculateSizeImpl(done); |
| 194 switch (size_status) { |
| 195 case Status::NET_ERROR: |
| 196 InvalidateCallbacksAndDone(net_error_, done); |
| 197 return; |
| 198 case Status::DONE: |
| 199 done.Run(net::OK); |
| 200 return; |
| 201 case Status::IO_PENDING: |
| 202 return; |
| 203 } |
| 204 } |
| 205 |
| 206 BlobReader::Status BlobReader::CalculateSizeImpl( |
| 207 const net::CompletionCallback& done) { |
| 208 DCHECK(!total_size_calculated_); |
| 209 DCHECK(size_callback_.is_null()); |
| 210 |
| 211 net_error_ = net::OK; |
| 212 total_size_ = 0; |
| 213 const auto& items = blob_data_->items(); |
| 214 item_length_list_.resize(items.size()); |
| 215 pending_get_file_info_count_ = 0; |
| 216 for (size_t i = 0; i < items.size(); ++i) { |
| 217 const BlobDataItem& item = *items.at(i); |
| 218 if (IsFileType(item.type())) { |
| 219 ++pending_get_file_info_count_; |
| 220 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i); |
| 221 if (!reader) { |
| 222 return ReportError(net::ERR_FAILED); |
| 223 } |
| 224 int64_t length_output = reader->GetLength(base::Bind( |
| 225 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i)); |
| 226 if (length_output == net::ERR_IO_PENDING) { |
| 227 continue; |
| 228 } |
| 229 if (length_output < 0) { |
| 230 return ReportError(length_output); |
| 231 } |
| 232 // We got the length right away |
| 233 --pending_get_file_info_count_; |
| 234 uint64_t resolved_length; |
| 235 if (!ResolveFileItemLength(item, length_output, &resolved_length)) { |
| 236 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 237 } |
| 238 if (!AddItemLength(i, resolved_length)) { |
| 239 return ReportError(net::ERR_FAILED); |
| 240 } |
| 241 continue; |
| 242 } |
| 243 |
| 244 if (!AddItemLength(i, item.length())) |
| 245 return ReportError(net::ERR_FAILED); |
| 246 } |
| 247 |
| 248 if (pending_get_file_info_count_ == 0) { |
| 249 DidCountSize(); |
| 250 return Status::DONE; |
| 251 } |
| 252 // Note: We only set the callback if we know that we're an async operation. |
| 253 size_callback_ = done; |
| 254 return Status::IO_PENDING; |
| 255 } |
| 256 |
222 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { | 257 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { |
223 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { | 258 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { |
224 return false; | 259 return false; |
225 } | 260 } |
226 | 261 |
227 // Cache the size and add it to the total size. | 262 // Cache the size and add it to the total size. |
228 DCHECK_LT(index, item_length_list_.size()); | 263 DCHECK_LT(index, item_length_list_.size()); |
229 item_length_list_[index] = item_length; | 264 item_length_list_[index] = item_length; |
230 total_size_ += item_length; | 265 total_size_ += item_length; |
231 return true; | 266 return true; |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 index_to_reader_.erase(found); | 595 index_to_reader_.erase(found); |
561 return; | 596 return; |
562 } | 597 } |
563 found->second = reader.release(); | 598 found->second = reader.release(); |
564 } else if (reader.get()) { | 599 } else if (reader.get()) { |
565 index_to_reader_[current_item_index_] = reader.release(); | 600 index_to_reader_[current_item_index_] = reader.release(); |
566 } | 601 } |
567 } | 602 } |
568 | 603 |
569 } // namespace storage | 604 } // namespace storage |
OLD | NEW |