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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
11 #include "base/message_loop_proxy.h" | 11 #include "base/message_loop_proxy.h" |
12 #include "base/task.h" | 12 #include "base/task.h" |
13 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 13 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
14 #include "webkit/plugins/ppapi/resource_helper.h" | 14 #include "webkit/plugins/ppapi/resource_helper.h" |
15 #include "webkit/plugins/ppapi/resource_tracker.h" | 15 #include "webkit/plugins/ppapi/resource_tracker.h" |
16 | 16 |
| 17 using base::FileUtilProxy; |
17 using base::PlatformFile; | 18 using base::PlatformFile; |
18 using base::PlatformFileError; | 19 using base::PlatformFileError; |
19 using quota::StorageType; | 20 using quota::StorageType; |
20 | 21 |
21 namespace webkit { | 22 namespace webkit { |
22 namespace ppapi { | 23 namespace ppapi { |
23 | 24 |
24 namespace { | 25 namespace { |
25 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { | 26 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { |
26 switch (type) { | 27 switch (type) { |
(...skipping 29 matching lines...) Expand all Loading... |
56 const bool is_will_operation_; | 57 const bool is_will_operation_; |
57 }; | 58 }; |
58 | 59 |
59 class QuotaFileIO::WriteOperation : public PendingOperationBase { | 60 class QuotaFileIO::WriteOperation : public PendingOperationBase { |
60 public: | 61 public: |
61 WriteOperation(QuotaFileIO* quota_io, | 62 WriteOperation(QuotaFileIO* quota_io, |
62 bool is_will_operation, | 63 bool is_will_operation, |
63 int64_t offset, | 64 int64_t offset, |
64 const char* buffer, | 65 const char* buffer, |
65 int32_t bytes_to_write, | 66 int32_t bytes_to_write, |
66 WriteCallback* callback) | 67 const WriteCallback& callback) |
67 : PendingOperationBase(quota_io, is_will_operation), | 68 : PendingOperationBase(quota_io, is_will_operation), |
68 offset_(offset), | 69 offset_(offset), |
69 bytes_to_write_(bytes_to_write), | 70 bytes_to_write_(bytes_to_write), |
70 callback_(callback), | 71 callback_(callback), |
71 finished_(false), | 72 finished_(false), |
72 status_(base::PLATFORM_FILE_OK), | 73 status_(base::PLATFORM_FILE_OK), |
73 bytes_written_(0), | 74 bytes_written_(0), |
74 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 75 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
75 runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
76 if (!is_will_operation) { | 76 if (!is_will_operation) { |
77 // TODO(kinuko): check the API convention if we really need to keep a | 77 // TODO(kinuko): check the API convention if we really need to keep a |
78 // copy of the buffer during the async write operations. | 78 // copy of the buffer during the async write operations. |
79 buffer_.reset(new char[bytes_to_write]); | 79 buffer_.reset(new char[bytes_to_write]); |
80 memcpy(buffer_.get(), buffer, bytes_to_write); | 80 memcpy(buffer_.get(), buffer, bytes_to_write); |
81 } | 81 } |
82 } | 82 } |
83 virtual ~WriteOperation() {} | 83 virtual ~WriteOperation() {} |
84 virtual void Run() OVERRIDE { | 84 virtual void Run() OVERRIDE { |
85 DCHECK(quota_io_); | 85 DCHECK(quota_io_); |
86 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { | 86 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { |
87 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 87 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
88 return; | 88 return; |
89 } | 89 } |
90 if (is_will_operation_) { | 90 if (is_will_operation_) { |
91 // Assuming the write will succeed. | 91 // Assuming the write will succeed. |
92 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); | 92 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); |
93 return; | 93 return; |
94 } | 94 } |
95 DCHECK(buffer_.get()); | 95 DCHECK(buffer_.get()); |
96 | 96 |
97 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); | 97 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
98 if (!plugin_delegate) { | 98 if (!plugin_delegate) { |
99 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 99 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
100 return; | 100 return; |
101 } | 101 } |
102 | 102 |
103 if (!base::FileUtilProxy::Write( | 103 if (!FileUtilProxy::Write( |
104 plugin_delegate->GetFileThreadMessageLoopProxy(), | 104 plugin_delegate->GetFileThreadMessageLoopProxy(), |
105 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 105 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
106 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 106 base::Bind(&WriteOperation::DidFinish, |
| 107 weak_ptr_factory_.GetWeakPtr()))) { |
107 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 108 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
108 return; | 109 return; |
109 } | 110 } |
110 } | 111 } |
111 | 112 |
112 virtual void DidFail(PlatformFileError error) OVERRIDE { | 113 virtual void DidFail(PlatformFileError error) OVERRIDE { |
113 DidFinish(error, 0); | 114 DidFinish(error, 0); |
114 } | 115 } |
115 | 116 |
116 bool finished() const { return finished_; } | 117 bool finished() const { return finished_; } |
117 | 118 |
118 virtual void WillRunCallback() { | 119 virtual void WillRunCallback() { |
119 base::MessageLoopProxy::current()->PostTask( | 120 base::MessageLoopProxy::current()->PostTask( |
120 FROM_HERE, runnable_factory_.NewRunnableMethod( | 121 FROM_HERE, |
121 &WriteOperation::RunCallback)); | 122 base::Bind(&WriteOperation::RunCallback, |
| 123 weak_ptr_factory_.GetWeakPtr())); |
122 } | 124 } |
123 | 125 |
124 private: | 126 private: |
125 void DidFinish(PlatformFileError status, int bytes_written) { | 127 void DidFinish(PlatformFileError status, int bytes_written) { |
126 finished_ = true; | 128 finished_ = true; |
127 status_ = status; | 129 status_ = status; |
128 bytes_written_ = bytes_written; | 130 bytes_written_ = bytes_written; |
129 int64_t max_offset = | 131 int64_t max_offset = |
130 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; | 132 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; |
131 // This may delete itself by calling RunCallback. | 133 // This may delete itself by calling RunCallback. |
132 quota_io_->DidWrite(this, max_offset); | 134 quota_io_->DidWrite(this, max_offset); |
133 } | 135 } |
134 | 136 |
135 virtual void RunCallback() { | 137 virtual void RunCallback() { |
136 DCHECK(callback_.get()); | 138 DCHECK(!callback_.is_null()); |
137 callback_->Run(status_, bytes_written_); | 139 callback_.Run(status_, bytes_written_); |
138 callback_.reset(); | |
139 delete this; | |
140 } | 140 } |
141 | 141 |
142 const int64_t offset_; | 142 const int64_t offset_; |
143 scoped_array<char> buffer_; | 143 scoped_array<char> buffer_; |
144 const int32_t bytes_to_write_; | 144 const int32_t bytes_to_write_; |
145 scoped_ptr<WriteCallback> callback_; | 145 WriteCallback callback_; |
146 bool finished_; | 146 bool finished_; |
147 PlatformFileError status_; | 147 PlatformFileError status_; |
148 int64_t bytes_written_; | 148 int64_t bytes_written_; |
149 base::ScopedCallbackFactory<WriteOperation> callback_factory_; | 149 base::WeakPtrFactory<WriteOperation> weak_ptr_factory_; |
150 ScopedRunnableMethodFactory<WriteOperation> runnable_factory_; | |
151 }; | 150 }; |
152 | 151 |
153 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { | 152 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { |
154 public: | 153 public: |
155 SetLengthOperation(QuotaFileIO* quota_io, | 154 SetLengthOperation(QuotaFileIO* quota_io, |
156 bool is_will_operation, | 155 bool is_will_operation, |
157 int64_t length, | 156 int64_t length, |
158 StatusCallback* callback) | 157 const StatusCallback& callback) |
159 : PendingOperationBase(quota_io, is_will_operation), | 158 : PendingOperationBase(quota_io, is_will_operation), |
160 length_(length), | 159 length_(length), |
161 callback_(callback), | 160 callback_(callback), |
162 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} | 161 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} |
163 | 162 |
164 virtual ~SetLengthOperation() {} | 163 virtual ~SetLengthOperation() {} |
165 | 164 |
166 virtual void Run() OVERRIDE { | 165 virtual void Run() OVERRIDE { |
167 DCHECK(quota_io_); | 166 DCHECK(quota_io_); |
168 if (quota_io_->CheckIfExceedsQuota(length_)) { | 167 if (quota_io_->CheckIfExceedsQuota(length_)) { |
169 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 168 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
170 return; | 169 return; |
171 } | 170 } |
172 if (is_will_operation_) { | 171 if (is_will_operation_) { |
173 DidFinish(base::PLATFORM_FILE_OK); | 172 DidFinish(base::PLATFORM_FILE_OK); |
174 return; | 173 return; |
175 } | 174 } |
176 | 175 |
177 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); | 176 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
178 if (!plugin_delegate) { | 177 if (!plugin_delegate) { |
179 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 178 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
180 return; | 179 return; |
181 } | 180 } |
182 | 181 |
183 if (!base::FileUtilProxy::Truncate( | 182 if (!FileUtilProxy::PostFileTaskAndReplyStatus<bool, PlatformFileError>( |
184 plugin_delegate->GetFileThreadMessageLoopProxy(), | 183 plugin_delegate->GetFileThreadMessageLoopProxy(), |
185 quota_io_->file_, length_, | 184 FROM_HERE, |
186 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 185 base::Bind(&base::TruncatePlatformFile, |
| 186 quota_io_->file_, length_), |
| 187 base::Bind(&SetLengthOperation::DidFinish, |
| 188 weak_ptr_factory_.GetWeakPtr()))) { |
187 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 189 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
188 return; | 190 return; |
189 } | 191 } |
190 } | 192 } |
191 | 193 |
192 virtual void DidFail(PlatformFileError error) OVERRIDE { | 194 virtual void DidFail(PlatformFileError error) OVERRIDE { |
193 DidFinish(error); | 195 DidFinish(error); |
194 } | 196 } |
195 | 197 |
196 private: | 198 private: |
197 void DidFinish(PlatformFileError status) { | 199 void DidFinish(PlatformFileError status) { |
198 quota_io_->DidSetLength(status, length_); | 200 quota_io_->DidSetLength(status, length_); |
199 DCHECK(callback_.get()); | 201 DCHECK(!callback_.is_null()); |
200 callback_->Run(status); | 202 callback_.Run(status); |
201 callback_.reset(); | |
202 delete this; | |
203 } | 203 } |
204 | 204 |
205 int64_t length_; | 205 int64_t length_; |
206 scoped_ptr<StatusCallback> callback_; | 206 StatusCallback callback_; |
207 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; | 207 base::WeakPtrFactory<SetLengthOperation> weak_ptr_factory_; |
208 }; | 208 }; |
209 | 209 |
210 // QuotaFileIO -------------------------------------------------------------- | 210 // QuotaFileIO -------------------------------------------------------------- |
211 | 211 |
212 QuotaFileIO::QuotaFileIO( | 212 QuotaFileIO::QuotaFileIO( |
213 PP_Instance instance, | 213 PP_Instance instance, |
214 PlatformFile file, | 214 PlatformFile file, |
215 const GURL& file_url, | 215 const GURL& file_url, |
216 PP_FileSystemType type) | 216 PP_FileSystemType type) |
217 : pp_instance_(instance), | 217 : pp_instance_(instance), |
218 file_(file), | 218 file_(file), |
219 file_url_(file_url), | 219 file_url_(file_url), |
220 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 220 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
221 cached_file_size_(0), | 221 cached_file_size_(0), |
222 cached_available_space_(0), | 222 cached_available_space_(0), |
223 outstanding_quota_queries_(0), | 223 outstanding_quota_queries_(0), |
224 outstanding_errors_(0), | 224 outstanding_errors_(0), |
225 max_written_offset_(0), | 225 max_written_offset_(0), |
226 inflight_operations_(0), | 226 inflight_operations_(0), |
227 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | |
228 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 227 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
229 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 228 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
230 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 229 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
231 } | 230 } |
232 | 231 |
233 QuotaFileIO::~QuotaFileIO() { | 232 QuotaFileIO::~QuotaFileIO() { |
234 // Note that this doesn't dispatch pending callbacks. | 233 // Note that this doesn't dispatch pending callbacks. |
235 STLDeleteContainerPointers(pending_operations_.begin(), | 234 STLDeleteContainerPointers(pending_operations_.begin(), |
236 pending_operations_.end()); | 235 pending_operations_.end()); |
237 STLDeleteContainerPointers(pending_callbacks_.begin(), | 236 STLDeleteContainerPointers(pending_callbacks_.begin(), |
238 pending_callbacks_.end()); | 237 pending_callbacks_.end()); |
239 } | 238 } |
240 | 239 |
241 bool QuotaFileIO::Write( | 240 bool QuotaFileIO::Write( |
242 int64_t offset, const char* buffer, int32_t bytes_to_write, | 241 int64_t offset, const char* buffer, int32_t bytes_to_write, |
243 WriteCallback* callback) { | 242 const WriteCallback& callback) { |
244 if (bytes_to_write <= 0) { | 243 if (bytes_to_write <= 0) { |
245 delete callback; | |
246 return false; | 244 return false; |
247 } | 245 } |
248 WriteOperation* op = new WriteOperation( | 246 WriteOperation* op = new WriteOperation( |
249 this, false, offset, buffer, bytes_to_write, callback); | 247 this, false, offset, buffer, bytes_to_write, callback); |
250 return RegisterOperationForQuotaChecks(op); | 248 return RegisterOperationForQuotaChecks(op); |
251 } | 249 } |
252 | 250 |
253 bool QuotaFileIO::SetLength(int64_t length, StatusCallback* callback) { | 251 bool QuotaFileIO::SetLength(int64_t length, const StatusCallback& callback) { |
254 DCHECK(pending_operations_.empty()); | 252 DCHECK(pending_operations_.empty()); |
255 SetLengthOperation* op = new SetLengthOperation( | 253 SetLengthOperation* op = new SetLengthOperation( |
256 this, false, length, callback); | 254 this, false, length, callback); |
257 return RegisterOperationForQuotaChecks(op); | 255 return RegisterOperationForQuotaChecks(op); |
258 } | 256 } |
259 | 257 |
260 bool QuotaFileIO::WillWrite( | 258 bool QuotaFileIO::WillWrite( |
261 int64_t offset, int32_t bytes_to_write, WriteCallback* callback) { | 259 int64_t offset, int32_t bytes_to_write, const WriteCallback& callback) { |
262 WriteOperation* op = new WriteOperation( | 260 WriteOperation* op = new WriteOperation( |
263 this, true, offset, NULL, bytes_to_write, callback); | 261 this, true, offset, NULL, bytes_to_write, callback); |
264 return RegisterOperationForQuotaChecks(op); | 262 return RegisterOperationForQuotaChecks(op); |
265 } | 263 } |
266 | 264 |
267 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { | 265 bool QuotaFileIO::WillSetLength( |
| 266 int64_t length, const StatusCallback& callback) { |
268 DCHECK(pending_operations_.empty()); | 267 DCHECK(pending_operations_.empty()); |
269 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); | 268 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); |
270 return RegisterOperationForQuotaChecks(op); | 269 return RegisterOperationForQuotaChecks(op); |
271 } | 270 } |
272 | 271 |
273 PluginDelegate* QuotaFileIO::GetPluginDelegate() const { | 272 PluginDelegate* QuotaFileIO::GetPluginDelegate() const { |
274 PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance_); | 273 PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance_); |
275 if (instance) | 274 if (instance) |
276 return instance->delegate(); | 275 return instance->delegate(); |
277 return NULL; | 276 return NULL; |
278 } | 277 } |
279 | 278 |
280 bool QuotaFileIO::RegisterOperationForQuotaChecks( | 279 bool QuotaFileIO::RegisterOperationForQuotaChecks( |
281 PendingOperationBase* op_ptr) { | 280 PendingOperationBase* op_ptr) { |
282 scoped_ptr<PendingOperationBase> op(op_ptr); | 281 scoped_ptr<PendingOperationBase> op(op_ptr); |
283 if (pending_operations_.empty()) { | 282 if (pending_operations_.empty()) { |
284 // This is the first pending quota check. Run querying the file size | 283 // This is the first pending quota check. Run querying the file size |
285 // and available space. | 284 // and available space. |
286 outstanding_quota_queries_ = 0; | 285 outstanding_quota_queries_ = 0; |
287 outstanding_errors_ = 0; | 286 outstanding_errors_ = 0; |
288 | 287 |
289 PluginDelegate* plugin_delegate = GetPluginDelegate(); | 288 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
290 if (!plugin_delegate) | 289 if (!plugin_delegate) |
291 return false; | 290 return false; |
292 | 291 |
293 // Query the file size. | 292 // Query the file size. |
294 ++outstanding_quota_queries_; | 293 ++outstanding_quota_queries_; |
295 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | 294 if (!FileUtilProxy::GetFileInfoFromPlatformFile( |
296 plugin_delegate->GetFileThreadMessageLoopProxy(), file_, | 295 plugin_delegate->GetFileThreadMessageLoopProxy(), file_, |
297 callback_factory_.NewCallback( | 296 base::Bind(&QuotaFileIO::DidQueryInfoForQuota, |
298 &QuotaFileIO::DidQueryInfoForQuota))) { | 297 weak_ptr_factory_.GetWeakPtr()))) { |
299 // This makes the call fail synchronously; we do not fire the callback | 298 // This makes the call fail synchronously; we do not fire the callback |
300 // here but just delete the operation and return false. | 299 // here but just delete the operation and return false. |
301 return false; | 300 return false; |
302 } | 301 } |
303 | 302 |
304 // Query the current available space. | 303 // Query the current available space. |
305 ++outstanding_quota_queries_; | 304 ++outstanding_quota_queries_; |
306 plugin_delegate->QueryAvailableSpace( | 305 plugin_delegate->QueryAvailableSpace( |
307 GURL(file_url_.path()).GetOrigin(), storage_type_, | 306 GURL(file_url_.path()).GetOrigin(), storage_type_, |
308 base::Bind(&QuotaFileIO::DidQueryAvailableSpace, | 307 base::Bind(&QuotaFileIO::DidQueryAvailableSpace, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 | 396 |
398 | 397 |
399 PluginDelegate* plugin_delegate = GetPluginDelegate(); | 398 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
400 if (plugin_delegate) | 399 if (plugin_delegate) |
401 plugin_delegate->DidUpdateFile(file_url_, delta); | 400 plugin_delegate->DidUpdateFile(file_url_, delta); |
402 inflight_operations_ = 0; | 401 inflight_operations_ = 0; |
403 } | 402 } |
404 | 403 |
405 } // namespace ppapi | 404 } // namespace ppapi |
406 } // namespace webkit | 405 } // namespace webkit |
OLD | NEW |