OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "webkit/plugins/ppapi/quota_file_io.h" | 5 #include "webkit/plugins/ppapi/quota_file_io.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "base/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
9 #include "base/task.h" | 9 #include "base/task.h" |
10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 } | 76 } |
77 virtual ~WriteOperation() {} | 77 virtual ~WriteOperation() {} |
78 virtual void Run() OVERRIDE { | 78 virtual void Run() OVERRIDE { |
79 DCHECK(quota_io_); | 79 DCHECK(quota_io_); |
80 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { | 80 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { |
81 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 81 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
82 return; | 82 return; |
83 } | 83 } |
84 if (is_will_operation_) { | 84 if (is_will_operation_) { |
85 // Assuming the write will succeed. | 85 // Assuming the write will succeed. |
86 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 86 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); |
87 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
88 &WriteOperation::DidFinish, | |
89 base::PLATFORM_FILE_OK, bytes_to_write_)); | |
90 return; | 87 return; |
91 } | 88 } |
92 DCHECK(buffer_.get()); | 89 DCHECK(buffer_.get()); |
93 if (!base::FileUtilProxy::Write( | 90 if (!base::FileUtilProxy::Write( |
94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 91 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), |
95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 92 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 93 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { |
97 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 94 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
98 return; | 95 return; |
99 } | 96 } |
100 } | 97 } |
101 | 98 |
102 virtual void DidFail(PlatformFileError error) OVERRIDE { | 99 virtual void DidFail(PlatformFileError error) OVERRIDE { |
103 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 100 DidFinish(error, 0); |
104 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
105 &WriteOperation::DidFinish, error, 0)); | |
106 } | 101 } |
107 | 102 |
108 bool finished() const { return finished_; } | 103 bool finished() const { return finished_; } |
109 | 104 |
110 void RunCallback() { | 105 virtual void WillRunCallback() { |
111 DCHECK(callback_.get()); | 106 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( |
112 callback_->Run(status_, bytes_written_); | 107 FROM_HERE, runnable_factory_.NewRunnableMethod( |
113 callback_.reset(); | 108 &WriteOperation::RunCallback)); |
114 delete this; | |
115 } | 109 } |
116 | 110 |
117 private: | 111 private: |
118 void DidFinish(PlatformFileError status, int bytes_written) { | 112 void DidFinish(PlatformFileError status, int bytes_written) { |
119 finished_ = true; | 113 finished_ = true; |
120 status_ = status; | 114 status_ = status; |
121 bytes_written_ = bytes_written; | 115 bytes_written_ = bytes_written; |
122 int64_t max_offset = | 116 int64_t max_offset = |
123 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; | 117 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; |
124 // This may delete itself by calling RunCallback. | 118 // This may delete itself by calling RunCallback. |
125 quota_io_->DidWrite(this, max_offset); | 119 quota_io_->DidWrite(this, max_offset); |
126 } | 120 } |
127 | 121 |
122 virtual void RunCallback() { | |
123 DCHECK(callback_.get()); | |
124 callback_->Run(status_, bytes_written_); | |
125 callback_.reset(); | |
126 delete this; | |
127 } | |
128 | |
128 const int64_t offset_; | 129 const int64_t offset_; |
129 scoped_array<char> buffer_; | 130 scoped_array<char> buffer_; |
130 const int32_t bytes_to_write_; | 131 const int32_t bytes_to_write_; |
131 scoped_ptr<WriteCallback> callback_; | 132 scoped_ptr<WriteCallback> callback_; |
132 bool finished_; | 133 bool finished_; |
133 PlatformFileError status_; | 134 PlatformFileError status_; |
134 int64_t bytes_written_; | 135 int64_t bytes_written_; |
135 base::ScopedCallbackFactory<QuotaFileIO::WriteOperation> callback_factory_; | 136 base::ScopedCallbackFactory<WriteOperation> callback_factory_; |
136 ScopedRunnableMethodFactory<QuotaFileIO::WriteOperation> runnable_factory_; | 137 ScopedRunnableMethodFactory<WriteOperation> runnable_factory_; |
137 }; | 138 }; |
138 | 139 |
139 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { | 140 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { |
140 public: | 141 public: |
141 SetLengthOperation(QuotaFileIO* quota_io, | 142 SetLengthOperation(QuotaFileIO* quota_io, |
142 bool is_will_operation, | 143 bool is_will_operation, |
143 int64_t length, | 144 int64_t length, |
144 StatusCallback* callback) | 145 StatusCallback* callback) |
145 : PendingOperationBase(quota_io, is_will_operation), | 146 : PendingOperationBase(quota_io, is_will_operation), |
146 length_(length), | 147 length_(length), |
147 callback_(callback), | 148 callback_(callback), |
148 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 149 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} |
149 runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} | 150 |
151 protected: | |
yzshen1
2011/08/05 20:31:46
Is this 'protected' intended for all the methods b
kinuko
2011/08/08 11:21:12
Oops, this was a remnant of the other (reverted) c
| |
150 virtual ~SetLengthOperation() {} | 152 virtual ~SetLengthOperation() {} |
151 | 153 |
152 virtual void Run() OVERRIDE { | 154 virtual void Run() OVERRIDE { |
153 DCHECK(quota_io_); | 155 DCHECK(quota_io_); |
154 if (quota_io_->CheckIfExceedsQuota(length_)) { | 156 if (quota_io_->CheckIfExceedsQuota(length_)) { |
155 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 157 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
156 return; | 158 return; |
157 } | 159 } |
158 if (is_will_operation_) { | 160 if (is_will_operation_) { |
159 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 161 DidFinish(base::PLATFORM_FILE_OK); |
160 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
161 &SetLengthOperation::DidFinish, | |
162 base::PLATFORM_FILE_OK)); | |
163 return; | 162 return; |
164 } | 163 } |
165 if (!base::FileUtilProxy::Truncate( | 164 if (!base::FileUtilProxy::Truncate( |
166 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 165 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), |
167 quota_io_->file_, length_, | 166 quota_io_->file_, length_, |
168 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 167 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { |
169 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 168 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
170 return; | 169 return; |
171 } | 170 } |
172 } | 171 } |
173 | 172 |
174 virtual void DidFail(PlatformFileError error) OVERRIDE { | 173 virtual void DidFail(PlatformFileError error) OVERRIDE { |
175 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 174 DidFinish(error); |
176 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
177 &SetLengthOperation::DidFinish, error)); | |
178 } | 175 } |
179 | 176 |
180 private: | 177 private: |
181 void DidFinish(PlatformFileError status) { | 178 void DidFinish(PlatformFileError status) { |
182 quota_io_->DidSetLength(status, length_); | 179 quota_io_->DidSetLength(status, length_); |
183 DCHECK(callback_.get()); | 180 DCHECK(callback_.get()); |
184 callback_->Run(status); | 181 callback_->Run(status); |
185 callback_.reset(); | 182 callback_.reset(); |
186 delete this; | 183 delete this; |
187 } | 184 } |
188 | 185 |
189 int64_t length_; | 186 int64_t length_; |
190 scoped_ptr<StatusCallback> callback_; | 187 scoped_ptr<StatusCallback> callback_; |
191 base::ScopedCallbackFactory<QuotaFileIO::SetLengthOperation> | 188 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; |
192 callback_factory_; | |
193 ScopedRunnableMethodFactory<QuotaFileIO::SetLengthOperation> | |
194 runnable_factory_; | |
195 }; | 189 }; |
196 | 190 |
197 // QuotaFileIO -------------------------------------------------------------- | 191 // QuotaFileIO -------------------------------------------------------------- |
198 | 192 |
199 QuotaFileIO::QuotaFileIO( | 193 QuotaFileIO::QuotaFileIO( |
200 PluginInstance* instance, | 194 PluginInstance* instance, |
201 PlatformFile file, | 195 PlatformFile file, |
202 const GURL& file_url, | 196 const GURL& file_url, |
203 PP_FileSystemType type) | 197 PP_FileSystemType type) |
204 : instance_(instance), | 198 : instance_(instance), |
205 file_(file), | 199 file_(file), |
206 file_url_(file_url), | 200 file_url_(file_url), |
207 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 201 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
208 cached_file_size_(0), | 202 cached_file_size_(0), |
209 cached_available_space_(0), | 203 cached_available_space_(0), |
210 outstanding_quota_queries_(0), | 204 outstanding_quota_queries_(0), |
211 outstanding_errors_(0), | 205 outstanding_errors_(0), |
212 max_written_offset_(0), | 206 max_written_offset_(0), |
213 inflight_operations_(0), | 207 inflight_operations_(0), |
214 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 208 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
215 DCHECK(instance_); | 209 DCHECK(instance_); |
216 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 210 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
217 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 211 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
218 } | 212 } |
219 | 213 |
220 QuotaFileIO::~QuotaFileIO() { | 214 QuotaFileIO::~QuotaFileIO() { |
221 // Note that this doesn't dispatch pending callbacks. | 215 // Note that this doesn't dispatch pending callbacks. |
222 STLDeleteContainerPointers(pending_operations_.begin(), | 216 STLDeleteContainerPointers(pending_operations_.begin(), |
223 pending_operations_.end()); | 217 pending_operations_.end()); |
218 STLDeleteContainerPointers(pending_callbacks_.begin(), | |
219 pending_callbacks_.end()); | |
224 } | 220 } |
225 | 221 |
226 bool QuotaFileIO::Write( | 222 bool QuotaFileIO::Write( |
227 int64_t offset, const char* buffer, int32_t bytes_to_write, | 223 int64_t offset, const char* buffer, int32_t bytes_to_write, |
228 WriteCallback* callback) { | 224 WriteCallback* callback) { |
229 WriteOperation* op = new WriteOperation( | 225 WriteOperation* op = new WriteOperation( |
230 this, false, offset, buffer, bytes_to_write, callback); | 226 this, false, offset, buffer, bytes_to_write, callback); |
231 return RegisterOperationForQuotaChecks(op); | 227 return RegisterOperationForQuotaChecks(op); |
232 } | 228 } |
233 | 229 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) { | 291 void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) { |
296 cached_available_space_ = avail_space; | 292 cached_available_space_ = avail_space; |
297 DCHECK_GT(outstanding_quota_queries_, 0); | 293 DCHECK_GT(outstanding_quota_queries_, 0); |
298 if (--outstanding_quota_queries_ == 0) | 294 if (--outstanding_quota_queries_ == 0) |
299 DidQueryForQuotaCheck(); | 295 DidQueryForQuotaCheck(); |
300 } | 296 } |
301 | 297 |
302 void QuotaFileIO::DidQueryForQuotaCheck() { | 298 void QuotaFileIO::DidQueryForQuotaCheck() { |
303 DCHECK(!pending_operations_.empty()); | 299 DCHECK(!pending_operations_.empty()); |
304 DCHECK_GT(inflight_operations_, 0); | 300 DCHECK_GT(inflight_operations_, 0); |
305 for (std::deque<PendingOperationBase*>::iterator iter = | 301 while (!pending_operations_.empty()) { |
306 pending_operations_.begin(); | 302 PendingOperationBase* op = pending_operations_.front(); |
307 iter != pending_operations_.end(); | 303 pending_operations_.pop_front(); |
308 ++iter) { | 304 pending_callbacks_.push_back(op); |
309 PendingOperationBase* op = *iter; | |
310 if (outstanding_errors_ > 0) { | 305 if (outstanding_errors_ > 0) { |
311 op->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 306 op->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
312 continue; | 307 continue; |
313 } | 308 } |
314 op->Run(); | 309 op->Run(); |
315 } | 310 } |
316 } | 311 } |
317 | 312 |
318 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { | 313 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { |
319 DCHECK_GE(cached_file_size_, 0); | 314 DCHECK_GE(cached_file_size_, 0); |
320 DCHECK_GE(cached_available_space_, 0); | 315 DCHECK_GE(cached_available_space_, 0); |
321 return new_file_size - cached_file_size_ > cached_available_space_; | 316 return new_file_size - cached_file_size_ > cached_available_space_; |
322 } | 317 } |
323 | 318 |
324 void QuotaFileIO::WillUpdate() { | 319 void QuotaFileIO::WillUpdate() { |
325 if (inflight_operations_++ == 0) { | 320 if (inflight_operations_++ == 0) { |
326 instance_->delegate()->WillUpdateFile(file_url_); | 321 instance_->delegate()->WillUpdateFile(file_url_); |
327 DCHECK_EQ(0, max_written_offset_); | 322 DCHECK_EQ(0, max_written_offset_); |
328 } | 323 } |
329 } | 324 } |
330 | 325 |
331 void QuotaFileIO::DidWrite(WriteOperation* op, | 326 void QuotaFileIO::DidWrite(WriteOperation* op, |
332 int64_t written_offset_end) { | 327 int64_t written_offset_end) { |
333 max_written_offset_ = std::max(max_written_offset_, written_offset_end); | 328 max_written_offset_ = std::max(max_written_offset_, written_offset_end); |
334 DCHECK_GT(inflight_operations_, 0); | 329 DCHECK_GT(inflight_operations_, 0); |
335 DCHECK(!pending_operations_.empty()); | 330 DCHECK(!pending_callbacks_.empty()); |
336 // Fire callbacks for finished operations. | 331 // Fire callbacks for finished operations. |
337 while (!pending_operations_.empty()) { | 332 while (!pending_callbacks_.empty()) { |
338 WriteOperation* op = static_cast<WriteOperation*>( | 333 WriteOperation* op = static_cast<WriteOperation*>( |
339 pending_operations_.front()); | 334 pending_callbacks_.front()); |
340 if (!op->finished()) | 335 if (!op->finished()) |
341 break; | 336 break; |
342 op->RunCallback(); | 337 pending_callbacks_.pop_front(); |
343 pending_operations_.pop_front(); | 338 op->WillRunCallback(); |
344 } | 339 } |
345 // If we have no more pending writes, notify the browser that we did | 340 // If we have no more pending writes, notify the browser that we did |
346 // update the file. | 341 // update the file. |
347 if (--inflight_operations_ == 0) { | 342 if (--inflight_operations_ == 0) { |
348 DCHECK(pending_operations_.empty()); | 343 DCHECK(pending_operations_.empty()); |
349 int64_t growth = max_written_offset_ - cached_file_size_; | 344 int64_t growth = max_written_offset_ - cached_file_size_; |
350 growth = growth < 0 ? 0 : growth; | 345 growth = growth < 0 ? 0 : growth; |
351 instance_->delegate()->DidUpdateFile(file_url_, growth); | 346 instance_->delegate()->DidUpdateFile(file_url_, growth); |
352 max_written_offset_ = 0; | 347 max_written_offset_ = 0; |
353 } | 348 } |
354 } | 349 } |
355 | 350 |
356 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { | 351 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { |
357 DCHECK_EQ(1, inflight_operations_); | 352 DCHECK_EQ(1, inflight_operations_); |
358 pending_operations_.pop_front(); | 353 pending_callbacks_.pop_front(); |
359 DCHECK(pending_operations_.empty()); | 354 DCHECK(pending_callbacks_.empty()); |
360 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : | 355 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : |
361 new_file_size - cached_file_size_; | 356 new_file_size - cached_file_size_; |
362 instance_->delegate()->DidUpdateFile(file_url_, delta); | 357 instance_->delegate()->DidUpdateFile(file_url_, delta); |
363 inflight_operations_ = 0; | 358 inflight_operations_ = 0; |
364 } | 359 } |
365 | 360 |
366 } // namespace ppapi | 361 } // namespace ppapi |
367 } // namespace webkit | 362 } // namespace webkit |
OLD | NEW |