Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Side by Side Diff: webkit/plugins/ppapi/ppb_file_io_impl.cc

Issue 7433006: Pepper quota support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/ppb_file_io_impl.h" 5 #include "webkit/plugins/ppapi/ppb_file_io_impl.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/file_util_proxy.h" 9 #include "base/file_util_proxy.h"
10 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
(...skipping 16 matching lines...) Expand all
27 27
28 using ppapi::PPTimeToTime; 28 using ppapi::PPTimeToTime;
29 using ppapi::TimeToPPTime; 29 using ppapi::TimeToPPTime;
30 using ppapi::thunk::EnterResourceNoLock; 30 using ppapi::thunk::EnterResourceNoLock;
31 using ppapi::thunk::PPB_FileIO_API; 31 using ppapi::thunk::PPB_FileIO_API;
32 using ppapi::thunk::PPB_FileRef_API; 32 using ppapi::thunk::PPB_FileRef_API;
33 33
34 namespace webkit { 34 namespace webkit {
35 namespace ppapi { 35 namespace ppapi {
36 36
37 namespace {
38 quota::StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) {
39 switch (type) {
40 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
41 return quota::kStorageTypePersistent;
42 case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
43 return quota::kStorageTypeTemporary;
44 default:
45 return quota::kStorageTypeUnknown;
46 }
47 NOTREACHED();
48 }
49 } // namespace
50
51 PPB_FileIO_Impl::PendingOperation::PendingOperation()
yzshen1 2011/07/21 22:23:34 Please use the same order as they are declared in
52 : type(UNKNOWN), offset(0), buffer(NULL), bytes_to_write(0) {}
yzshen1 2011/07/21 22:23:34 You miss |length|.
53
37 PPB_FileIO_Impl::CallbackEntry::CallbackEntry() 54 PPB_FileIO_Impl::CallbackEntry::CallbackEntry()
38 : read_buffer(NULL) { 55 : read_buffer(NULL) {
39 } 56 }
40 57
41 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry) 58 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry)
42 : callback(entry.callback), 59 : callback(entry.callback),
43 read_buffer(entry.read_buffer) { 60 read_buffer(entry.read_buffer) {
44 } 61 }
45 62
46 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() { 63 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() {
47 } 64 }
48 65
49 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance) 66 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance)
50 : Resource(instance), 67 : Resource(instance),
51 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), 68 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)),
52 file_(base::kInvalidPlatformFileValue), 69 file_(base::kInvalidPlatformFileValue),
53 pending_op_(OPERATION_NONE), 70 pending_op_(OPERATION_NONE),
54 info_(NULL) { 71 info_(NULL),
72 cached_available_space_(0),
yzshen1 2011/07/21 22:23:34 You miss quite a few members. Please initialize al
73 did_notify_will_update_(false),
74 pending_setlength_length_(-1) {
55 } 75 }
56 76
57 PPB_FileIO_Impl::~PPB_FileIO_Impl() { 77 PPB_FileIO_Impl::~PPB_FileIO_Impl() {
58 Close(); 78 Close();
59 } 79 }
60 80
61 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() { 81 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() {
62 return this; 82 return this;
63 } 83 }
64 84
(...skipping 17 matching lines...) Expand all
82 switch (file_system_type_) { 102 switch (file_system_type_) {
83 case PP_FILESYSTEMTYPE_EXTERNAL: 103 case PP_FILESYSTEMTYPE_EXTERNAL:
84 if (!instance()->delegate()->AsyncOpenFile( 104 if (!instance()->delegate()->AsyncOpenFile(
85 file_ref->GetSystemPath(), flags, 105 file_ref->GetSystemPath(), flags,
86 callback_factory_.NewCallback( 106 callback_factory_.NewCallback(
87 &PPB_FileIO_Impl::AsyncOpenFileCallback))) 107 &PPB_FileIO_Impl::AsyncOpenFileCallback)))
88 return PP_ERROR_FAILED; 108 return PP_ERROR_FAILED;
89 break; 109 break;
90 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: 110 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
91 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: 111 case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
112 path_url_ = file_ref->GetFileSystemURL();
92 if (!instance()->delegate()->AsyncOpenFileSystemURL( 113 if (!instance()->delegate()->AsyncOpenFileSystemURL(
93 file_ref->GetFileSystemURL(), flags, 114 path_url_, flags,
94 callback_factory_.NewCallback( 115 callback_factory_.NewCallback(
95 &PPB_FileIO_Impl::AsyncOpenFileCallback))) 116 &PPB_FileIO_Impl::AsyncOpenFileCallback)))
96 return PP_ERROR_FAILED; 117 return PP_ERROR_FAILED;
97 break; 118 break;
98 default: 119 default:
99 return PP_ERROR_FAILED; 120 return PP_ERROR_FAILED;
100 } 121 }
101 122
102 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 123 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
103 return PP_OK_COMPLETIONPENDING; 124 return PP_OK_COMPLETIONPENDING;
104 } 125 }
105 126
106 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info, 127 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info,
107 PP_CompletionCallback callback) { 128 PP_CompletionCallback callback) {
108 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 129 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
109 if (rv != PP_OK) 130 if (rv != PP_OK)
110 return rv; 131 return rv;
111 132
112 if (!info) 133 if (!info)
113 return PP_ERROR_BADARGUMENT; 134 return PP_ERROR_BADARGUMENT;
114 135
115 DCHECK(!info_); // If |info_|, a callback should be pending (caught above). 136 DCHECK(!info_); // If |info_|, a callback should be pending (caught above).
116 info_ = info; 137 info_ = info;
117 138
118 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( 139 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
119 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, 140 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_,
120 callback_factory_.NewCallback(&PPB_FileIO_Impl::QueryInfoCallback))) 141 callback_factory_.NewCallback(&PPB_FileIO_Impl::QueryInfoCallback)))
121 return PP_ERROR_FAILED; 142 return PP_ERROR_FAILED;
122 143
123 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 144 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
124 return PP_OK_COMPLETIONPENDING; 145 return PP_OK_COMPLETIONPENDING;
125 } 146 }
126 147
127 int32_t PPB_FileIO_Impl::Touch(PP_Time last_access_time, 148 int32_t PPB_FileIO_Impl::Touch(PP_Time last_access_time,
128 PP_Time last_modified_time, 149 PP_Time last_modified_time,
129 PP_CompletionCallback callback) { 150 PP_CompletionCallback callback) {
130 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 151 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
131 if (rv != PP_OK) 152 if (rv != PP_OK)
132 return rv; 153 return rv;
133 154
134 if (!base::FileUtilProxy::Touch( 155 if (!base::FileUtilProxy::Touch(
135 instance()->delegate()->GetFileThreadMessageLoopProxy(), 156 instance()->delegate()->GetFileThreadMessageLoopProxy(),
136 file_, PPTimeToTime(last_access_time), 157 file_, PPTimeToTime(last_access_time),
137 PPTimeToTime(last_modified_time), 158 PPTimeToTime(last_modified_time),
138 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) 159 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
139 return PP_ERROR_FAILED; 160 return PP_ERROR_FAILED;
140 161
141 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 162 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
142 return PP_OK_COMPLETIONPENDING; 163 return PP_OK_COMPLETIONPENDING;
143 } 164 }
144 165
145 int32_t PPB_FileIO_Impl::Read(int64_t offset, 166 int32_t PPB_FileIO_Impl::Read(int64_t offset,
146 char* buffer, 167 char* buffer,
147 int32_t bytes_to_read, 168 int32_t bytes_to_read,
148 PP_CompletionCallback callback) { 169 PP_CompletionCallback callback) {
149 int32_t rv = CommonCallValidation(true, OPERATION_READ, callback); 170 int32_t rv = CommonCallValidation(true, OPERATION_READ, callback);
150 if (rv != PP_OK) 171 if (rv != PP_OK)
151 return rv; 172 return rv;
152 173
153 if (!base::FileUtilProxy::Read( 174 if (!base::FileUtilProxy::Read(
154 instance()->delegate()->GetFileThreadMessageLoopProxy(), 175 instance()->delegate()->GetFileThreadMessageLoopProxy(),
155 file_, offset, bytes_to_read, 176 file_, offset, bytes_to_read,
156 callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadCallback))) 177 callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadCallback)))
157 return PP_ERROR_FAILED; 178 return PP_ERROR_FAILED;
158 179
159 RegisterCallback(OPERATION_READ, callback, buffer); 180 RegisterCallback(&callbacks_, OPERATION_READ, callback, buffer);
160 return PP_OK_COMPLETIONPENDING; 181 return PP_OK_COMPLETIONPENDING;
161 } 182 }
162 183
163 int32_t PPB_FileIO_Impl::Write(int64_t offset, 184 int32_t PPB_FileIO_Impl::Write(int64_t offset,
164 const char* buffer, 185 const char* buffer,
165 int32_t bytes_to_write, 186 int32_t bytes_to_write,
166 PP_CompletionCallback callback) { 187 PP_CompletionCallback callback) {
167 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback); 188 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback);
168 if (rv != PP_OK) 189 if (rv != PP_OK)
169 return rv; 190 return rv;
170 191
171 if (!base::FileUtilProxy::Write( 192 if (!DoesRequireQuotaCheck()) {
172 instance()->delegate()->GetFileThreadMessageLoopProxy(), 193 if (!base::FileUtilProxy::Write(
173 file_, offset, buffer, bytes_to_write, 194 instance()->delegate()->GetFileThreadMessageLoopProxy(),
174 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) 195 file_, offset, buffer, bytes_to_write,
196 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) {
197 return PP_ERROR_FAILED;
198 }
199 RegisterCallback(&callbacks_, OPERATION_WRITE, callback, NULL);
200 return PP_OK_COMPLETIONPENDING;
201 }
202
203 // Enqueue this request and query the quota.
204 PendingOperation op;
205 op.type = PendingOperation::WRITE;
206 op.offset = offset;
207 op.buffer = buffer;
208 op.bytes_to_write = bytes_to_write;
209 if (!QueryFileSizeAndQuota(op))
175 return PP_ERROR_FAILED; 210 return PP_ERROR_FAILED;
176 211
177 RegisterCallback(OPERATION_WRITE, callback, NULL); 212 RegisterCallback(&pending_quota_check_callbacks_,
213 OPERATION_WRITE, callback, NULL);
178 return PP_OK_COMPLETIONPENDING; 214 return PP_OK_COMPLETIONPENDING;
179 } 215 }
180 216
181 int32_t PPB_FileIO_Impl::SetLength(int64_t length, 217 int32_t PPB_FileIO_Impl::SetLength(int64_t length,
182 PP_CompletionCallback callback) { 218 PP_CompletionCallback callback) {
183 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 219 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
184 if (rv != PP_OK) 220 if (rv != PP_OK)
185 return rv; 221 return rv;
186 222
187 if (!base::FileUtilProxy::Truncate( 223 if (!DoesRequireQuotaCheck()) {
188 instance()->delegate()->GetFileThreadMessageLoopProxy(), 224 if (!base::FileUtilProxy::Truncate(
189 file_, length, 225 instance()->delegate()->GetFileThreadMessageLoopProxy(),
190 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) 226 file_, length,
227 callback_factory_.NewCallback(
228 &PPB_FileIO_Impl::SetLengthCallback))) {
229 return PP_ERROR_FAILED;
230 }
231 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
232 return PP_OK_COMPLETIONPENDING;
233 }
234
235 // Enqueue this request and query the quota.
236 PendingOperation op;
237 op.type = PendingOperation::SETLENGTH;
238 op.length = length;
239 if (!QueryFileSizeAndQuota(op))
191 return PP_ERROR_FAILED; 240 return PP_ERROR_FAILED;
192 241
193 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 242 RegisterCallback(&pending_quota_check_callbacks_,
243 OPERATION_EXCLUSIVE, callback, NULL);
194 return PP_OK_COMPLETIONPENDING; 244 return PP_OK_COMPLETIONPENDING;
195 } 245 }
196 246
197 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) { 247 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) {
198 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 248 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
199 if (rv != PP_OK) 249 if (rv != PP_OK)
200 return rv; 250 return rv;
201 251
202 if (!base::FileUtilProxy::Flush( 252 if (!base::FileUtilProxy::Flush(
203 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, 253 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_,
204 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) 254 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
205 return PP_ERROR_FAILED; 255 return PP_ERROR_FAILED;
206 256
207 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 257 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
208 return PP_OK_COMPLETIONPENDING; 258 return PP_OK_COMPLETIONPENDING;
209 } 259 }
210 260
211 void PPB_FileIO_Impl::Close() { 261 void PPB_FileIO_Impl::Close() {
212 if (file_ != base::kInvalidPlatformFileValue) { 262 if (file_ != base::kInvalidPlatformFileValue) {
213 base::FileUtilProxy::Close( 263 base::FileUtilProxy::Close(
214 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, NULL); 264 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, NULL);
215 file_ = base::kInvalidPlatformFileValue; 265 file_ = base::kInvalidPlatformFileValue;
216 } 266 }
217 } 267 }
218 268
219 int32_t PPB_FileIO_Impl::GetOSFileDescriptor() { 269 int32_t PPB_FileIO_Impl::GetOSFileDescriptor() {
220 #if defined(OS_POSIX) 270 #if defined(OS_POSIX)
221 return file_; 271 return file_;
222 #elif defined(OS_WIN) 272 #elif defined(OS_WIN)
223 return reinterpret_cast<uintptr_t>(file_); 273 return reinterpret_cast<uintptr_t>(file_);
224 #else 274 #else
225 #error "Platform not supported." 275 #error "Platform not supported."
226 #endif 276 #endif
227 } 277 }
228 278
229 int32_t PPB_FileIO_Impl::WillWrite(int64_t offset, 279 int32_t PPB_FileIO_Impl::WillWrite(int64_t offset,
230 int32_t bytes_to_write, 280 int32_t bytes_to_write,
231 PP_CompletionCallback callback) { 281 PP_CompletionCallback callback) {
232 // TODO(dumi): implement me 282 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback);
233 return PP_OK; 283 if (rv != PP_OK)
284 return rv;
285
286 if (!DoesRequireQuotaCheck()) {
287 PP_RunCompletionCallback(&callback, PP_OK);
288 return PP_OK;
289 }
290
291 PendingOperation op;
292 op.type = PendingOperation::WILL_WRITE;
293 op.offset = offset;
294 op.bytes_to_write = bytes_to_write;
295 if (!QueryFileSizeAndQuota(op))
296 return PP_ERROR_FAILED;
297
298 RegisterCallback(&pending_quota_check_callbacks_,
299 OPERATION_WRITE, callback, NULL);
300 return PP_OK_COMPLETIONPENDING;
234 } 301 }
235 302
236 int32_t PPB_FileIO_Impl::WillSetLength(int64_t length, 303 int32_t PPB_FileIO_Impl::WillSetLength(int64_t length,
237 PP_CompletionCallback callback) { 304 PP_CompletionCallback callback) {
238 // TODO(dumi): implement me 305 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
239 return PP_OK; 306 if (rv != PP_OK)
307 return rv;
308
309 if (!DoesRequireQuotaCheck()) {
310 PP_RunCompletionCallback(&callback, PP_OK);
311 return PP_OK;
312 }
313
314 PendingOperation op;
315 op.type = PendingOperation::WILL_SETLENGTH;
316 op.length = length;
317 if (!QueryFileSizeAndQuota(op))
318 return PP_ERROR_FAILED;
319
320 RegisterCallback(&pending_quota_check_callbacks_,
321 OPERATION_EXCLUSIVE, callback, NULL);
322 return PP_OK_COMPLETIONPENDING;
240 } 323 }
241 324
242 int32_t PPB_FileIO_Impl::CommonCallValidation(bool should_be_open, 325 int32_t PPB_FileIO_Impl::CommonCallValidation(bool should_be_open,
243 OperationType new_op, 326 OperationType new_op,
244 PP_CompletionCallback callback) { 327 PP_CompletionCallback callback) {
245 // Only asynchronous operation is supported. 328 // Only asynchronous operation is supported.
246 if (!callback.func) { 329 if (!callback.func) {
247 NOTIMPLEMENTED(); 330 NOTIMPLEMENTED();
248 return PP_ERROR_BADARGUMENT; 331 return PP_ERROR_BADARGUMENT;
249 } 332 }
250 333
251 if (should_be_open) { 334 if (should_be_open) {
252 if (file_ == base::kInvalidPlatformFileValue) 335 if (file_ == base::kInvalidPlatformFileValue)
253 return PP_ERROR_FAILED; 336 return PP_ERROR_FAILED;
254 } else { 337 } else {
255 if (file_ != base::kInvalidPlatformFileValue) 338 if (file_ != base::kInvalidPlatformFileValue)
256 return PP_ERROR_FAILED; 339 return PP_ERROR_FAILED;
257 } 340 }
258 341
259 if (pending_op_ != OPERATION_NONE && 342 if (pending_op_ != OPERATION_NONE &&
260 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) { 343 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) {
261 return PP_ERROR_INPROGRESS; 344 return PP_ERROR_INPROGRESS;
262 } 345 }
263 346
264 return PP_OK; 347 return PP_OK;
265 } 348 }
266 349
267 void PPB_FileIO_Impl::RegisterCallback(OperationType op, 350 void PPB_FileIO_Impl::RegisterCallback(std::queue<CallbackEntry>* callbacks,
351 OperationType op,
268 PP_CompletionCallback callback, 352 PP_CompletionCallback callback,
269 char* read_buffer) { 353 char* read_buffer) {
270 DCHECK(callback.func); 354 DCHECK(callback.func);
271 DCHECK(pending_op_ == OPERATION_NONE || 355 DCHECK(pending_op_ == OPERATION_NONE ||
272 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op)); 356 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op));
273 357
274 CallbackEntry entry; 358 CallbackEntry entry;
275 PP_Resource resource_id = GetReferenceNoAddRef(); 359 PP_Resource resource_id = GetReferenceNoAddRef();
276 CHECK(resource_id); 360 CHECK(resource_id);
277 entry.callback = new TrackedCompletionCallback( 361 entry.callback = new TrackedCompletionCallback(
278 instance()->module()->GetCallbackTracker(), resource_id, callback); 362 instance()->module()->GetCallbackTracker(), resource_id, callback);
279 entry.read_buffer = read_buffer; 363 entry.read_buffer = read_buffer;
280 364
281 callbacks_.push(entry); 365 callbacks->push(entry);
282 pending_op_ = op; 366 pending_op_ = op;
283 } 367 }
284 368
285 void PPB_FileIO_Impl::RunAndRemoveFirstPendingCallback(int32_t result) { 369 void PPB_FileIO_Impl::RunAndRemoveFirstPendingCallback(
286 DCHECK(!callbacks_.empty()); 370 std::queue<CallbackEntry>* callbacks, int32_t result) {
371 DCHECK(!callbacks->empty());
287 372
288 CallbackEntry front = callbacks_.front(); 373 CallbackEntry front = callbacks->front();
289 callbacks_.pop(); 374 callbacks->pop();
290 if (callbacks_.empty()) 375 if (callbacks->empty())
yzshen1 2011/07/21 22:23:34 pending_op_ can be set incorrectly. Consider the f
291 pending_op_ = OPERATION_NONE; 376 pending_op_ = OPERATION_NONE;
292 377
293 front.callback->Run(result); // Will complete abortively if necessary. 378 front.callback->Run(result); // Will complete abortively if necessary.
294 } 379 }
295 380
296 void PPB_FileIO_Impl::StatusCallback(base::PlatformFileError error_code) { 381 void PPB_FileIO_Impl::StatusCallback(base::PlatformFileError error_code) {
297 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 382 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
298 NOTREACHED(); 383 NOTREACHED();
299 return; 384 return;
300 } 385 }
301 386
302 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 387 RunAndRemoveFirstPendingCallback(
388 &callbacks_, PlatformFileErrorToPepperError(error_code));
303 } 389 }
304 390
305 void PPB_FileIO_Impl::AsyncOpenFileCallback( 391 void PPB_FileIO_Impl::AsyncOpenFileCallback(
306 base::PlatformFileError error_code, 392 base::PlatformFileError error_code,
307 base::PassPlatformFile file) { 393 base::PassPlatformFile file) {
308 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 394 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
309 NOTREACHED(); 395 NOTREACHED();
310 return; 396 return;
311 } 397 }
312 398
313 DCHECK(file_ == base::kInvalidPlatformFileValue); 399 DCHECK(file_ == base::kInvalidPlatformFileValue);
314 file_ = file.ReleaseValue(); 400 file_ = file.ReleaseValue();
315 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 401 RunAndRemoveFirstPendingCallback(
402 &callbacks_, PlatformFileErrorToPepperError(error_code));
316 } 403 }
317 404
318 void PPB_FileIO_Impl::QueryInfoCallback( 405 void PPB_FileIO_Impl::QueryInfoCallback(
319 base::PlatformFileError error_code, 406 base::PlatformFileError error_code,
320 const base::PlatformFileInfo& file_info) { 407 const base::PlatformFileInfo& file_info) {
321 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 408 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
322 NOTREACHED(); 409 NOTREACHED();
323 return; 410 return;
324 } 411 }
325 412
326 DCHECK(info_); 413 DCHECK(info_);
327 if (error_code == base::PLATFORM_FILE_OK) { 414 if (error_code == base::PLATFORM_FILE_OK) {
328 info_->size = file_info.size; 415 info_->size = file_info.size;
329 info_->creation_time = TimeToPPTime(file_info.creation_time); 416 info_->creation_time = TimeToPPTime(file_info.creation_time);
330 info_->last_access_time = TimeToPPTime(file_info.last_accessed); 417 info_->last_access_time = TimeToPPTime(file_info.last_accessed);
331 info_->last_modified_time = TimeToPPTime(file_info.last_modified); 418 info_->last_modified_time = TimeToPPTime(file_info.last_modified);
332 info_->system_type = file_system_type_; 419 info_->system_type = file_system_type_;
333 if (file_info.is_directory) 420 if (file_info.is_directory)
334 info_->type = PP_FILETYPE_DIRECTORY; 421 info_->type = PP_FILETYPE_DIRECTORY;
335 else 422 else
336 info_->type = PP_FILETYPE_REGULAR; 423 info_->type = PP_FILETYPE_REGULAR;
337 } 424 }
338 info_ = NULL; 425 info_ = NULL;
339 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 426 RunAndRemoveFirstPendingCallback(
427 &callbacks_, PlatformFileErrorToPepperError(error_code));
340 } 428 }
341 429
342 void PPB_FileIO_Impl::ReadCallback(base::PlatformFileError error_code, 430 void PPB_FileIO_Impl::ReadCallback(base::PlatformFileError error_code,
343 const char* data, int bytes_read) { 431 const char* data, int bytes_read) {
344 if (pending_op_ != OPERATION_READ || callbacks_.empty()) { 432 if (pending_op_ != OPERATION_READ || callbacks_.empty()) {
345 NOTREACHED(); 433 NOTREACHED();
346 return; 434 return;
347 } 435 }
348 436
349 char* read_buffer = callbacks_.front().read_buffer; 437 char* read_buffer = callbacks_.front().read_buffer;
350 DCHECK(data); 438 DCHECK(data);
351 DCHECK(read_buffer); 439 DCHECK(read_buffer);
352 440
353 int rv; 441 int rv;
354 if (error_code == base::PLATFORM_FILE_OK) { 442 if (error_code == base::PLATFORM_FILE_OK) {
355 rv = bytes_read; 443 rv = bytes_read;
356 if (file_ != base::kInvalidPlatformFileValue) 444 if (file_ != base::kInvalidPlatformFileValue)
357 memcpy(read_buffer, data, bytes_read); 445 memcpy(read_buffer, data, bytes_read);
358 } else { 446 } else {
359 rv = PlatformFileErrorToPepperError(error_code); 447 rv = PlatformFileErrorToPepperError(error_code);
360 } 448 }
361 449
362 RunAndRemoveFirstPendingCallback(rv); 450 RunAndRemoveFirstPendingCallback(&callbacks_, rv);
363 } 451 }
364 452
365 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code, 453 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code,
366 int bytes_written) { 454 int bytes_written) {
367 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) { 455 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) {
368 NOTREACHED(); 456 NOTREACHED();
369 return; 457 return;
370 } 458 }
371 459
460 if (DoesRequireQuotaCheck()) {
461 DCHECK(did_notify_will_update_);
462 DCHECK(!pending_write_offset_.empty());
463
464 // Update possible max file offset.
465 int64_t offset = pending_write_offset_.front();
466 pending_write_offset_.pop();
467 if (error_code == base::PLATFORM_FILE_OK)
468 max_written_offset_ = std::max(max_written_offset_,
469 offset + bytes_written);
470
471 // If we have no more pending writes, notify the browser that we did
472 // update the file.
473 if (pending_quota_checks_.empty() &&
474 pending_write_offset_.empty()) {
475 int64_t growth = max_written_offset_ - cached_file_size_;
476 if (growth > 0)
477 instance()->delegate()->DidUpdateFile(path_url_, growth);
478 did_notify_will_update_ = false;
479 }
480 }
481
372 if (error_code != base::PLATFORM_FILE_OK) { 482 if (error_code != base::PLATFORM_FILE_OK) {
373 RunAndRemoveFirstPendingCallback( 483 RunAndRemoveFirstPendingCallback(
374 PlatformFileErrorToPepperError(error_code)); 484 &callbacks_, PlatformFileErrorToPepperError(error_code));
375 } else { 485 } else {
376 RunAndRemoveFirstPendingCallback(bytes_written); 486 RunAndRemoveFirstPendingCallback(&callbacks_, bytes_written);
377 } 487 }
488 }
489
490 void PPB_FileIO_Impl::SetLengthCallback(
491 base::PlatformFileError error_code) {
492 if (callbacks_.empty()) {
493 NOTREACHED();
494 return;
495 }
496
497 if (DoesRequireQuotaCheck()) {
498 DCHECK_NE(-1, pending_setlength_length_);
499 DCHECK(did_notify_will_update_);
500 if (base::PLATFORM_FILE_OK == error_code) {
501 instance()->delegate()->DidUpdateFile(
502 path_url_, pending_setlength_length_ - cached_file_size_);
503 }
504 pending_setlength_length_ = -1;
505 did_notify_will_update_ = false;
506 }
507
508 RunAndRemoveFirstPendingCallback(
509 &callbacks_, PlatformFileErrorToPepperError(error_code));
510 }
511
512 bool PPB_FileIO_Impl::DoesRequireQuotaCheck() const {
513 return (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
514 file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT);
515 }
516
517 bool PPB_FileIO_Impl::QueryFileSizeAndQuota(const PendingOperation& op) {
518 pending_quota_checks_.push(op);
519 if (pending_quota_checks_.size() == 1) {
520 // This is the first call.
521 DCHECK(!did_notify_will_update_);
522 outstanding_quota_queries_ = 0;
523 outstanding_errors_ = 0;
524
525 // Query the file size.
526 ++outstanding_quota_queries_;
527 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
528 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_,
529 callback_factory_.NewCallback(
530 &PPB_FileIO_Impl::DidQueryInfoForQuota))) {
531 pending_quota_checks_.pop();
yzshen1 2011/07/21 22:23:34 Maybe you could push at the end of the method, so
kinuko 2011/07/26 16:27:46 Done (in quota_file_io.cc)
532 return false;
533 }
534
535 // Query the current available space.
536 ++outstanding_quota_queries_;
537 instance()->delegate()->QueryAvailableSpace(
538 GURL(path_url_.path()).GetOrigin(),
539 PPFileSystemTypeToQuotaStorageType(file_system_type_),
540 callback_factory_.NewCallback(
541 &PPB_FileIO_Impl::DidQueryAvailableSpace));
542 }
543 return true;
544 }
545
546 void PPB_FileIO_Impl::DidQueryInfoForQuota(
547 base::PlatformFileError error_code,
548 const base::PlatformFileInfo& file_info) {
549 if (error_code != base::PLATFORM_FILE_OK)
550 ++outstanding_errors_;
551 cached_file_size_ = max_written_offset_ = file_info.size;
552 DCHECK_GT(outstanding_quota_queries_, 0);
553 if (--outstanding_quota_queries_ == 0)
554 DidQueryFileSizeAndQuota();
555 }
556
557 void PPB_FileIO_Impl::DidQueryAvailableSpace(int64_t avail_space) {
558 cached_available_space_ = avail_space;
559 DCHECK_GT(outstanding_quota_queries_, 0);
560 if (--outstanding_quota_queries_ == 0)
561 DidQueryFileSizeAndQuota();
562 }
563
564 void PPB_FileIO_Impl::DidQueryFileSizeAndQuota() {
565 DCHECK(!pending_quota_checks_.empty());
566 while (!pending_quota_checks_.empty()) {
567 PendingOperation op = pending_quota_checks_.front();
568 pending_quota_checks_.pop();
569
570 switch (op.type) {
571 case PendingOperation::WRITE: {
572 int64_t growth = op.offset + op.bytes_to_write - cached_file_size_;
573 if (!CommonQuotaCheck(growth))
574 continue;
575 if (!base::FileUtilProxy::Write(
576 instance()->delegate()->GetFileThreadMessageLoopProxy(),
577 file_, op.offset, op.buffer, op.bytes_to_write,
578 callback_factory_.NewCallback(
579 &PPB_FileIO_Impl::WriteCallback))) {
580 RunAndRemoveFirstPendingCallback(
581 &pending_quota_check_callbacks_, PP_ERROR_FAILED);
582 continue;
583 }
584 pending_write_offset_.push(op.offset);
585 break;
586 }
587
588 case PendingOperation::SETLENGTH: {
589 int64_t growth = op.length - cached_file_size_;
590 if (!CommonQuotaCheck(growth))
591 continue;
592 if (!base::FileUtilProxy::Truncate(
593 instance()->delegate()->GetFileThreadMessageLoopProxy(),
594 file_, op.length,
595 callback_factory_.NewCallback(
596 &PPB_FileIO_Impl::SetLengthCallback))) {
597 RunAndRemoveFirstPendingCallback(
598 &pending_quota_check_callbacks_, PP_ERROR_FAILED);
599 continue;
600 }
601 DCHECK_EQ(-1, pending_setlength_length_);
602 pending_setlength_length_ = op.length;
603 break;
604 }
605
606 case PendingOperation::WILL_WRITE: {
607 int64_t growth = op.offset + op.bytes_to_write - cached_file_size_;
608 if (!CommonQuotaCheck(growth))
609 continue;
610 // TODO(kinuko) we should have a way to handle failure cases;
611 // currently we always update the usage upfront even if the actual
612 // write (which will be called after we run the callback) may fail.
613 pending_write_offset_.push(op.offset);
614 WriteCallback(base::PLATFORM_FILE_OK, op.bytes_to_write);
yzshen1 2011/07/21 22:23:34 You shouldn't call WriteCallback before moving the
615 break;
616 }
617
618 case PendingOperation::WILL_SETLENGTH: {
619 int64_t growth = op.length - cached_file_size_;
620 if (!CommonQuotaCheck(growth))
621 continue;
622 // TODO(kinuko) we should have a way to handle failure cases;
623 // currently we always update the usage upfront even if the actual
624 // truncate (which will be called after we run the callback) may fail.
625 pending_setlength_length_ = op.length;
626 SetLengthCallback(base::PLATFORM_FILE_OK);
yzshen1 2011/07/21 22:23:34 You shouldn't call SetLengthCallback before moving
kinuko 2011/07/26 16:27:46 Added tests that call WillWrite/WillSetLength in p
627 break;
628 }
629
630 default:
631 NOTREACHED();
632 continue;
633 }
634
635 DCHECK(did_notify_will_update_);
636 CallbackEntry entry = pending_quota_check_callbacks_.front();
637 pending_quota_check_callbacks_.pop();
638 callbacks_.push(entry);
639 }
640 }
641
642 bool PPB_FileIO_Impl::CommonQuotaCheck(int64_t growth) {
643 DCHECK(!pending_quota_check_callbacks_.empty());
644 if (outstanding_errors_ || growth > cached_available_space_) {
645 RunAndRemoveFirstPendingCallback(
646 &pending_quota_check_callbacks_,
647 PP_ERROR_NOQUOTA);
648 return false;
649 }
650 if (!did_notify_will_update_) {
651 instance()->delegate()->WillUpdateFile(path_url_);
652 did_notify_will_update_ = true;
653 }
654 return true;
378 } 655 }
379 656
380 } // namespace ppapi 657 } // namespace ppapi
381 } // namespace webkit 658 } // namespace webkit
OLDNEW
« webkit/plugins/ppapi/ppb_file_io_impl.h ('K') | « webkit/plugins/ppapi/ppb_file_io_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698