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

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: updated 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"
michaeln 2011/07/20 21:28:33 Are any plugins using the file descriptor base API
kinuko 2011/07/21 14:34:08 I guessed you meant this but also wished there mig
6 6
7 #include "base/callback.h"
8 #include "base/file_util.h" 7 #include "base/file_util.h"
9 #include "base/file_util_proxy.h" 8 #include "base/file_util_proxy.h"
10 #include "base/message_loop_proxy.h" 9 #include "base/message_loop_proxy.h"
11 #include "base/platform_file.h" 10 #include "base/platform_file.h"
12 #include "base/logging.h" 11 #include "base/logging.h"
13 #include "base/time.h" 12 #include "base/time.h"
14 #include "ppapi/c/ppb_file_io.h" 13 #include "ppapi/c/ppb_file_io.h"
15 #include "ppapi/c/trusted/ppb_file_io_trusted.h" 14 #include "ppapi/c/trusted/ppb_file_io_trusted.h"
16 #include "ppapi/c/pp_completion_callback.h" 15 #include "ppapi/c/pp_completion_callback.h"
17 #include "ppapi/c/pp_errors.h" 16 #include "ppapi/c/pp_errors.h"
18 #include "ppapi/shared_impl/time_conversion.h" 17 #include "ppapi/shared_impl/time_conversion.h"
19 #include "ppapi/thunk/enter.h" 18 #include "ppapi/thunk/enter.h"
20 #include "ppapi/thunk/ppb_file_ref_api.h" 19 #include "ppapi/thunk/ppb_file_ref_api.h"
20 #include "webkit/fileapi/file_system_util.h"
21 #include "webkit/plugins/ppapi/common.h" 21 #include "webkit/plugins/ppapi/common.h"
22 #include "webkit/plugins/ppapi/file_type_conversions.h" 22 #include "webkit/plugins/ppapi/file_type_conversions.h"
23 #include "webkit/plugins/ppapi/plugin_module.h" 23 #include "webkit/plugins/ppapi/plugin_module.h"
24 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 24 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
25 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h" 25 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
26 #include "webkit/plugins/ppapi/resource_tracker.h" 26 #include "webkit/plugins/ppapi/resource_tracker.h"
27 #include "webkit/quota/quota_client.h"
27 28
28 using ppapi::PPTimeToTime; 29 using ppapi::PPTimeToTime;
29 using ppapi::TimeToPPTime; 30 using ppapi::TimeToPPTime;
30 using ppapi::thunk::EnterResourceNoLock; 31 using ppapi::thunk::EnterResourceNoLock;
31 using ppapi::thunk::PPB_FileIO_API; 32 using ppapi::thunk::PPB_FileIO_API;
32 using ppapi::thunk::PPB_FileRef_API; 33 using ppapi::thunk::PPB_FileRef_API;
33 34
34 namespace webkit { 35 namespace webkit {
35 namespace ppapi { 36 namespace ppapi {
36 37
38 namespace {
39 quota::StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) {
40 switch (type) {
41 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
42 return quota::kStorageTypePersistent;
43 case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
44 return quota::kStorageTypeTemporary;
45 default:
46 return quota::kStorageTypeUnknown;
47 }
48 NOTREACHED();
49 }
50 } // namespace
51
52 PPB_FileIO_Impl::PendingOperation::PendingOperation()
53 : type(UNKNOWN), offset(0), buffer(NULL), bytes_to_write(0) {}
54
37 PPB_FileIO_Impl::CallbackEntry::CallbackEntry() 55 PPB_FileIO_Impl::CallbackEntry::CallbackEntry()
38 : read_buffer(NULL) { 56 : read_buffer(NULL) {
39 } 57 }
40 58
41 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry) 59 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry)
42 : callback(entry.callback), 60 : callback(entry.callback),
43 read_buffer(entry.read_buffer) { 61 read_buffer(entry.read_buffer) {
44 } 62 }
45 63
46 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() { 64 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() {
47 } 65 }
48 66
49 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance) 67 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance)
50 : Resource(instance), 68 : Resource(instance),
51 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), 69 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)),
52 file_(base::kInvalidPlatformFileValue), 70 file_(base::kInvalidPlatformFileValue),
71 file_size_(-1),
72 cached_available_space_(0),
53 pending_op_(OPERATION_NONE), 73 pending_op_(OPERATION_NONE),
54 info_(NULL) { 74 info_(NULL),
75 pending_setlength_length_(-1) {
55 } 76 }
56 77
57 PPB_FileIO_Impl::~PPB_FileIO_Impl() { 78 PPB_FileIO_Impl::~PPB_FileIO_Impl() {
58 Close(); 79 Close();
59 } 80 }
60 81
61 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() { 82 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() {
62 return this; 83 return this;
63 } 84 }
64 85
(...skipping 16 matching lines...) Expand all
81 file_system_type_ = file_ref->GetFileSystemType(); 102 file_system_type_ = file_ref->GetFileSystemType();
82 switch (file_system_type_) { 103 switch (file_system_type_) {
83 case PP_FILESYSTEMTYPE_EXTERNAL: 104 case PP_FILESYSTEMTYPE_EXTERNAL:
84 if (!instance()->delegate()->AsyncOpenFile( 105 if (!instance()->delegate()->AsyncOpenFile(
85 file_ref->GetSystemPath(), flags, 106 file_ref->GetSystemPath(), flags,
86 callback_factory_.NewCallback( 107 callback_factory_.NewCallback(
87 &PPB_FileIO_Impl::AsyncOpenFileCallback))) 108 &PPB_FileIO_Impl::AsyncOpenFileCallback)))
88 return PP_ERROR_FAILED; 109 return PP_ERROR_FAILED;
89 break; 110 break;
90 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: 111 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
91 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: 112 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: {
113 GURL root_url = file_ref->GetFileSystemURL();
92 if (!instance()->delegate()->AsyncOpenFileSystemURL( 114 if (!instance()->delegate()->AsyncOpenFileSystemURL(
93 file_ref->GetFileSystemURL(), flags, 115 root_url, flags,
94 callback_factory_.NewCallback( 116 callback_factory_.NewCallback(
95 &PPB_FileIO_Impl::AsyncOpenFileCallback))) 117 &PPB_FileIO_Impl::AsyncOpenFileCallback)))
96 return PP_ERROR_FAILED; 118 return PP_ERROR_FAILED;
119 origin_url_ = GURL(root_url.path()).GetOrigin();
97 break; 120 break;
121 }
98 default: 122 default:
99 return PP_ERROR_FAILED; 123 return PP_ERROR_FAILED;
100 } 124 }
101 125
102 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 126 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
103 return PP_OK_COMPLETIONPENDING; 127 return PP_OK_COMPLETIONPENDING;
104 } 128 }
105 129
106 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info, 130 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info,
107 PP_CompletionCallback callback) { 131 PP_CompletionCallback callback) {
108 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 132 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
109 if (rv != PP_OK) 133 if (rv != PP_OK)
110 return rv; 134 return rv;
111 135
112 if (!info) 136 if (!info)
113 return PP_ERROR_BADARGUMENT; 137 return PP_ERROR_BADARGUMENT;
114 138
115 DCHECK(!info_); // If |info_|, a callback should be pending (caught above). 139 DCHECK(!info_); // If |info_|, a callback should be pending (caught above).
116 info_ = info; 140 info_ = info;
117 141
118 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( 142 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
119 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, 143 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_,
120 callback_factory_.NewCallback(&PPB_FileIO_Impl::QueryInfoCallback))) 144 callback_factory_.NewCallback(&PPB_FileIO_Impl::QueryInfoCallback)))
121 return PP_ERROR_FAILED; 145 return PP_ERROR_FAILED;
122 146
123 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 147 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
124 return PP_OK_COMPLETIONPENDING; 148 return PP_OK_COMPLETIONPENDING;
125 } 149 }
126 150
127 int32_t PPB_FileIO_Impl::Touch(PP_Time last_access_time, 151 int32_t PPB_FileIO_Impl::Touch(PP_Time last_access_time,
128 PP_Time last_modified_time, 152 PP_Time last_modified_time,
129 PP_CompletionCallback callback) { 153 PP_CompletionCallback callback) {
130 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 154 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
131 if (rv != PP_OK) 155 if (rv != PP_OK)
132 return rv; 156 return rv;
133 157
134 if (!base::FileUtilProxy::Touch( 158 if (!base::FileUtilProxy::Touch(
135 instance()->delegate()->GetFileThreadMessageLoopProxy(), 159 instance()->delegate()->GetFileThreadMessageLoopProxy(),
136 file_, PPTimeToTime(last_access_time), 160 file_, PPTimeToTime(last_access_time),
137 PPTimeToTime(last_modified_time), 161 PPTimeToTime(last_modified_time),
138 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) 162 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
139 return PP_ERROR_FAILED; 163 return PP_ERROR_FAILED;
140 164
141 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 165 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
142 return PP_OK_COMPLETIONPENDING; 166 return PP_OK_COMPLETIONPENDING;
143 } 167 }
144 168
145 int32_t PPB_FileIO_Impl::Read(int64_t offset, 169 int32_t PPB_FileIO_Impl::Read(int64_t offset,
146 char* buffer, 170 char* buffer,
147 int32_t bytes_to_read, 171 int32_t bytes_to_read,
148 PP_CompletionCallback callback) { 172 PP_CompletionCallback callback) {
149 int32_t rv = CommonCallValidation(true, OPERATION_READ, callback); 173 int32_t rv = CommonCallValidation(true, OPERATION_READ, callback);
150 if (rv != PP_OK) 174 if (rv != PP_OK)
151 return rv; 175 return rv;
152 176
153 if (!base::FileUtilProxy::Read( 177 if (!base::FileUtilProxy::Read(
154 instance()->delegate()->GetFileThreadMessageLoopProxy(), 178 instance()->delegate()->GetFileThreadMessageLoopProxy(),
155 file_, offset, bytes_to_read, 179 file_, offset, bytes_to_read,
156 callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadCallback))) 180 callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadCallback)))
157 return PP_ERROR_FAILED; 181 return PP_ERROR_FAILED;
158 182
159 RegisterCallback(OPERATION_READ, callback, buffer); 183 RegisterCallback(&callbacks_, OPERATION_READ, callback, buffer);
160 return PP_OK_COMPLETIONPENDING; 184 return PP_OK_COMPLETIONPENDING;
161 } 185 }
162 186
163 int32_t PPB_FileIO_Impl::Write(int64_t offset, 187 int32_t PPB_FileIO_Impl::Write(int64_t offset,
164 const char* buffer, 188 const char* buffer,
165 int32_t bytes_to_write, 189 int32_t bytes_to_write,
166 PP_CompletionCallback callback) { 190 PP_CompletionCallback callback) {
167 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback); 191 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback);
168 if (rv != PP_OK) 192 if (rv != PP_OK)
169 return rv; 193 return rv;
170 194
171 if (!base::FileUtilProxy::Write( 195 int64_t expected_growth = offset + bytes_to_write - file_size_;
172 instance()->delegate()->GetFileThreadMessageLoopProxy(),
173 file_, offset, buffer, bytes_to_write,
174 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback)))
175 return PP_ERROR_FAILED;
176 196
177 RegisterCallback(OPERATION_WRITE, callback, NULL); 197 if (!DoesRequireQuotaCheck() ||
198 expected_growth <= cached_available_space_) {
199 // we're ok to go.
200 if (!base::FileUtilProxy::Write(
201 instance()->delegate()->GetFileThreadMessageLoopProxy(),
202 file_, offset, buffer, bytes_to_write,
203 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) {
204 return PP_ERROR_FAILED;
205 }
206 pending_write_offset_.push(offset);
207 RegisterCallback(&callbacks_, OPERATION_WRITE, callback, NULL);
208 return PP_OK_COMPLETIONPENDING;
209 }
210
211 // Enqueue this request and query the quota.
212 PendingOperation op;
213 op.type = PendingOperation::WRITE;
214 op.offset = offset;
215 op.buffer = buffer;
216 op.bytes_to_write = bytes_to_write;
217 QueryAvailableSpace(op);
218
219 RegisterCallback(&pending_quota_check_callbacks_,
yzshen1 2011/07/20 20:50:36 The problem is that write operations may be execut
kinuko 2011/07/21 14:34:08 I changed the code to either always or never queue
220 OPERATION_WRITE, callback, NULL);
178 return PP_OK_COMPLETIONPENDING; 221 return PP_OK_COMPLETIONPENDING;
179 } 222 }
180 223
181 int32_t PPB_FileIO_Impl::SetLength(int64_t length, 224 int32_t PPB_FileIO_Impl::SetLength(int64_t length,
182 PP_CompletionCallback callback) { 225 PP_CompletionCallback callback) {
183 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 226 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
184 if (rv != PP_OK) 227 if (rv != PP_OK)
185 return rv; 228 return rv;
186 229
187 if (!base::FileUtilProxy::Truncate( 230 DCHECK_EQ(-1, pending_setlength_length_);
188 instance()->delegate()->GetFileThreadMessageLoopProxy(), 231 int64_t expected_growth = length - file_size_;
189 file_, length,
190 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
191 return PP_ERROR_FAILED;
192 232
193 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 233 if (!DoesRequireQuotaCheck() ||
234 expected_growth <= cached_available_space_) {
235 if (!base::FileUtilProxy::Truncate(
236 instance()->delegate()->GetFileThreadMessageLoopProxy(),
237 file_, length,
238 callback_factory_.NewCallback(
239 &PPB_FileIO_Impl::SetLengthCallback))) {
240 return PP_ERROR_FAILED;
241 }
242 pending_setlength_length_ = length;
243 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
244 return PP_OK_COMPLETIONPENDING;
245 }
246
247 // Enqueue this request and query the quota.
248 PendingOperation op;
249 op.type = PendingOperation::SETLENGTH;
250 op.length = length;
251 QueryAvailableSpace(op);
252
253 RegisterCallback(&pending_quota_check_callbacks_,
254 OPERATION_EXCLUSIVE, callback, NULL);
194 return PP_OK_COMPLETIONPENDING; 255 return PP_OK_COMPLETIONPENDING;
195 } 256 }
196 257
197 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) { 258 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) {
198 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 259 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
199 if (rv != PP_OK) 260 if (rv != PP_OK)
200 return rv; 261 return rv;
201 262
202 if (!base::FileUtilProxy::Flush( 263 if (!base::FileUtilProxy::Flush(
203 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, 264 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_,
204 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) 265 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback)))
205 return PP_ERROR_FAILED; 266 return PP_ERROR_FAILED;
206 267
207 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 268 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL);
208 return PP_OK_COMPLETIONPENDING; 269 return PP_OK_COMPLETIONPENDING;
209 } 270 }
210 271
211 void PPB_FileIO_Impl::Close() { 272 void PPB_FileIO_Impl::Close() {
212 if (file_ != base::kInvalidPlatformFileValue) { 273 if (file_ != base::kInvalidPlatformFileValue) {
213 base::FileUtilProxy::Close( 274 base::FileUtilProxy::Close(
214 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, NULL); 275 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, NULL);
215 file_ = base::kInvalidPlatformFileValue; 276 file_ = base::kInvalidPlatformFileValue;
216 } 277 }
217 } 278 }
218 279
219 int32_t PPB_FileIO_Impl::GetOSFileDescriptor() { 280 int32_t PPB_FileIO_Impl::GetOSFileDescriptor() {
220 #if defined(OS_POSIX) 281 #if defined(OS_POSIX)
221 return file_; 282 return file_;
222 #elif defined(OS_WIN) 283 #elif defined(OS_WIN)
223 return reinterpret_cast<uintptr_t>(file_); 284 return reinterpret_cast<uintptr_t>(file_);
224 #else 285 #else
225 #error "Platform not supported." 286 #error "Platform not supported."
226 #endif 287 #endif
227 } 288 }
228 289
229 int32_t PPB_FileIO_Impl::WillWrite(int64_t offset, 290 int32_t PPB_FileIO_Impl::WillWrite(int64_t offset,
230 int32_t bytes_to_write, 291 int32_t bytes_to_write,
231 PP_CompletionCallback callback) { 292 PP_CompletionCallback callback) {
232 // TODO(dumi): implement me 293 // TODO(dumi): implement me
294 // Request quota.
michaeln 2011/07/20 21:28:33 Given the shape of the trusted APIs (there's a Wil
kinuko 2011/07/21 14:34:08 Hmm the successive write or truncate may fail, so
233 return PP_OK; 295 return PP_OK;
234 } 296 }
235 297
236 int32_t PPB_FileIO_Impl::WillSetLength(int64_t length, 298 int32_t PPB_FileIO_Impl::WillSetLength(int64_t length,
237 PP_CompletionCallback callback) { 299 PP_CompletionCallback callback) {
238 // TODO(dumi): implement me 300 // TODO(dumi): implement me
301 // Request quota.
239 return PP_OK; 302 return PP_OK;
240 } 303 }
241 304
242 int32_t PPB_FileIO_Impl::CommonCallValidation(bool should_be_open, 305 int32_t PPB_FileIO_Impl::CommonCallValidation(bool should_be_open,
243 OperationType new_op, 306 OperationType new_op,
244 PP_CompletionCallback callback) { 307 PP_CompletionCallback callback) {
245 // Only asynchronous operation is supported. 308 // Only asynchronous operation is supported.
246 if (!callback.func) { 309 if (!callback.func) {
247 NOTIMPLEMENTED(); 310 NOTIMPLEMENTED();
248 return PP_ERROR_BADARGUMENT; 311 return PP_ERROR_BADARGUMENT;
249 } 312 }
250 313
251 if (should_be_open) { 314 if (should_be_open) {
252 if (file_ == base::kInvalidPlatformFileValue) 315 if (file_ == base::kInvalidPlatformFileValue)
253 return PP_ERROR_FAILED; 316 return PP_ERROR_FAILED;
254 } else { 317 } else {
255 if (file_ != base::kInvalidPlatformFileValue) 318 if (file_ != base::kInvalidPlatformFileValue)
256 return PP_ERROR_FAILED; 319 return PP_ERROR_FAILED;
257 } 320 }
258 321
259 if (pending_op_ != OPERATION_NONE && 322 if (pending_op_ != OPERATION_NONE &&
260 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) { 323 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) {
261 return PP_ERROR_INPROGRESS; 324 return PP_ERROR_INPROGRESS;
262 } 325 }
263 326
264 return PP_OK; 327 return PP_OK;
265 } 328 }
266 329
267 void PPB_FileIO_Impl::RegisterCallback(OperationType op, 330 void PPB_FileIO_Impl::RegisterCallback(std::queue<CallbackEntry>* callbacks,
331 OperationType op,
268 PP_CompletionCallback callback, 332 PP_CompletionCallback callback,
269 char* read_buffer) { 333 char* read_buffer) {
270 DCHECK(callback.func); 334 DCHECK(callback.func);
271 DCHECK(pending_op_ == OPERATION_NONE || 335 DCHECK(pending_op_ == OPERATION_NONE ||
272 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op)); 336 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op));
273 337
274 CallbackEntry entry; 338 CallbackEntry entry;
275 PP_Resource resource_id = GetReferenceNoAddRef(); 339 PP_Resource resource_id = GetReferenceNoAddRef();
276 CHECK(resource_id); 340 CHECK(resource_id);
277 entry.callback = new TrackedCompletionCallback( 341 entry.callback = new TrackedCompletionCallback(
278 instance()->module()->GetCallbackTracker(), resource_id, callback); 342 instance()->module()->GetCallbackTracker(), resource_id, callback);
279 entry.read_buffer = read_buffer; 343 entry.read_buffer = read_buffer;
280 344
281 callbacks_.push(entry); 345 callbacks->push(entry);
282 pending_op_ = op; 346 pending_op_ = op;
283 } 347 }
284 348
285 void PPB_FileIO_Impl::RunAndRemoveFirstPendingCallback(int32_t result) { 349 void PPB_FileIO_Impl::RunAndRemoveFirstPendingCallback(
286 DCHECK(!callbacks_.empty()); 350 std::queue<CallbackEntry>* callbacks, int32_t result) {
351 DCHECK(!callbacks->empty());
287 352
288 CallbackEntry front = callbacks_.front(); 353 CallbackEntry front = callbacks->front();
289 callbacks_.pop(); 354 callbacks->pop();
290 if (callbacks_.empty()) 355 if (callbacks->empty())
291 pending_op_ = OPERATION_NONE; 356 pending_op_ = OPERATION_NONE;
292 357
293 front.callback->Run(result); // Will complete abortively if necessary. 358 front.callback->Run(result); // Will complete abortively if necessary.
294 } 359 }
295 360
296 void PPB_FileIO_Impl::StatusCallback(base::PlatformFileError error_code) { 361 void PPB_FileIO_Impl::StatusCallback(base::PlatformFileError error_code) {
297 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 362 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
298 NOTREACHED(); 363 NOTREACHED();
299 return; 364 return;
300 } 365 }
301 366
302 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 367 RunAndRemoveFirstPendingCallback(
368 &callbacks_, PlatformFileErrorToPepperError(error_code));
303 } 369 }
304 370
305 void PPB_FileIO_Impl::AsyncOpenFileCallback( 371 void PPB_FileIO_Impl::AsyncOpenFileCallback(
306 base::PlatformFileError error_code, 372 base::PlatformFileError error_code,
307 base::PassPlatformFile file) { 373 base::PassPlatformFile file,
374 int64_t file_size) {
308 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 375 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
309 NOTREACHED(); 376 NOTREACHED();
310 return; 377 return;
311 } 378 }
312 379
313 DCHECK(file_ == base::kInvalidPlatformFileValue); 380 DCHECK(file_ == base::kInvalidPlatformFileValue);
314 file_ = file.ReleaseValue(); 381 file_ = file.ReleaseValue();
315 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 382 file_size_ = file_size;
383 DCHECK(!DoesRequireQuotaCheck() ||
384 error_code != base::PLATFORM_FILE_OK ||
385 file_size_ >= 0);
386 RunAndRemoveFirstPendingCallback(
387 &callbacks_, PlatformFileErrorToPepperError(error_code));
316 } 388 }
317 389
318 void PPB_FileIO_Impl::QueryInfoCallback( 390 void PPB_FileIO_Impl::QueryInfoCallback(
319 base::PlatformFileError error_code, 391 base::PlatformFileError error_code,
320 const base::PlatformFileInfo& file_info) { 392 const base::PlatformFileInfo& file_info) {
321 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 393 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
322 NOTREACHED(); 394 NOTREACHED();
323 return; 395 return;
324 } 396 }
325 397
326 DCHECK(info_); 398 DCHECK(info_);
327 if (error_code == base::PLATFORM_FILE_OK) { 399 if (error_code == base::PLATFORM_FILE_OK) {
328 info_->size = file_info.size; 400 info_->size = file_info.size;
329 info_->creation_time = TimeToPPTime(file_info.creation_time); 401 info_->creation_time = TimeToPPTime(file_info.creation_time);
330 info_->last_access_time = TimeToPPTime(file_info.last_accessed); 402 info_->last_access_time = TimeToPPTime(file_info.last_accessed);
331 info_->last_modified_time = TimeToPPTime(file_info.last_modified); 403 info_->last_modified_time = TimeToPPTime(file_info.last_modified);
332 info_->system_type = file_system_type_; 404 info_->system_type = file_system_type_;
333 if (file_info.is_directory) 405 if (file_info.is_directory)
334 info_->type = PP_FILETYPE_DIRECTORY; 406 info_->type = PP_FILETYPE_DIRECTORY;
335 else 407 else
336 info_->type = PP_FILETYPE_REGULAR; 408 info_->type = PP_FILETYPE_REGULAR;
337 } 409 }
338 info_ = NULL; 410 info_ = NULL;
339 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 411 RunAndRemoveFirstPendingCallback(
412 &callbacks_, PlatformFileErrorToPepperError(error_code));
340 } 413 }
341 414
342 void PPB_FileIO_Impl::ReadCallback(base::PlatformFileError error_code, 415 void PPB_FileIO_Impl::ReadCallback(base::PlatformFileError error_code,
343 const char* data, int bytes_read) { 416 const char* data, int bytes_read) {
344 if (pending_op_ != OPERATION_READ || callbacks_.empty()) { 417 if (pending_op_ != OPERATION_READ || callbacks_.empty()) {
345 NOTREACHED(); 418 NOTREACHED();
346 return; 419 return;
347 } 420 }
348 421
349 char* read_buffer = callbacks_.front().read_buffer; 422 char* read_buffer = callbacks_.front().read_buffer;
350 DCHECK(data); 423 DCHECK(data);
351 DCHECK(read_buffer); 424 DCHECK(read_buffer);
352 425
353 int rv; 426 int rv;
354 if (error_code == base::PLATFORM_FILE_OK) { 427 if (error_code == base::PLATFORM_FILE_OK) {
355 rv = bytes_read; 428 rv = bytes_read;
356 if (file_ != base::kInvalidPlatformFileValue) 429 if (file_ != base::kInvalidPlatformFileValue)
357 memcpy(read_buffer, data, bytes_read); 430 memcpy(read_buffer, data, bytes_read);
358 } else { 431 } else {
359 rv = PlatformFileErrorToPepperError(error_code); 432 rv = PlatformFileErrorToPepperError(error_code);
360 } 433 }
361 434
362 RunAndRemoveFirstPendingCallback(rv); 435 RunAndRemoveFirstPendingCallback(&callbacks_, rv);
363 } 436 }
364 437
365 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code, 438 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code,
366 int bytes_written) { 439 int bytes_written) {
367 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) { 440 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) {
368 NOTREACHED(); 441 NOTREACHED();
369 return; 442 return;
370 } 443 }
371 444
445 DCHECK(!pending_write_offset_.empty());
446 int64_t offset = pending_write_offset_.front();
447 pending_write_offset_.pop();
448
372 if (error_code != base::PLATFORM_FILE_OK) { 449 if (error_code != base::PLATFORM_FILE_OK) {
373 RunAndRemoveFirstPendingCallback( 450 RunAndRemoveFirstPendingCallback(
374 PlatformFileErrorToPepperError(error_code)); 451 &callbacks_, PlatformFileErrorToPepperError(error_code));
375 } else { 452 } else {
376 RunAndRemoveFirstPendingCallback(bytes_written); 453 int64_t growth = offset + bytes_written - file_size_;
454 if (growth >= 0) {
455 if (DoesRequireQuotaCheck()) {
456 instance()->delegate()->NotifyStorageModified(
457 quota::QuotaClient::kFileSystem,
458 origin_url_,
459 PPFileSystemTypeToQuotaStorageType(file_system_type_),
460 growth);
461 }
462 file_size_ += growth;
463 }
464 RunAndRemoveFirstPendingCallback(&callbacks_, bytes_written);
465 }
466
467 // Reset the available space.
468 if (HasNoPendingWrites())
469 cached_available_space_ = 0;
470 }
471
472 void PPB_FileIO_Impl::SetLengthCallback(
473 base::PlatformFileError error_code) {
474 if (callbacks_.empty()) {
475 NOTREACHED();
476 return;
477 }
478
479 DCHECK_NE(-1, pending_setlength_length_);
480
481 if (base::PLATFORM_FILE_OK == error_code) {
482 if (DoesRequireQuotaCheck()) {
483 int64_t delta = pending_setlength_length_ - file_size_;
484 instance()->delegate()->NotifyStorageModified(
485 quota::QuotaClient::kFileSystem,
486 origin_url_,
487 PPFileSystemTypeToQuotaStorageType(file_system_type_),
488 delta);
489 }
490 file_size_ = pending_setlength_length_;
491 }
492
493 RunAndRemoveFirstPendingCallback(
494 &callbacks_, PlatformFileErrorToPepperError(error_code));
495
496 pending_setlength_length_ = -1;
michaeln 2011/07/20 21:28:33 If the caller's callback has invoked FileIO.SetLen
kinuko 2011/07/21 14:34:08 Good catch, fixed.
497 cached_available_space_ = 0;
498 }
499
500 bool PPB_FileIO_Impl::DoesRequireQuotaCheck() const {
501 return (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
502 file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT);
503 }
504
505 bool PPB_FileIO_Impl::HasNoPendingWrites() const {
506 return pending_quota_checks_.empty() &&
507 pending_write_offset_.empty() &&
508 pending_setlength_length_ == -1;
509 }
510
511 void PPB_FileIO_Impl::QueryAvailableSpace(const PendingOperation& op) {
512 pending_quota_checks_.push(op);
513 if (pending_quota_checks_.size() == 1) {
514 // This is the first one.
515 instance()->delegate()->QueryAvailableSpace(
516 origin_url_,
517 PPFileSystemTypeToQuotaStorageType(file_system_type_),
518 callback_factory_.NewCallback(
519 &PPB_FileIO_Impl::DidQueryAvailableSpace));
377 } 520 }
378 } 521 }
379 522
523 void PPB_FileIO_Impl::DidQueryAvailableSpace(int64_t avail_space) {
524 cached_available_space_ = avail_space;
525 DCHECK(!pending_quota_checks_.empty());
526
527 while (!pending_quota_checks_.empty()) {
528 DCHECK(!pending_quota_check_callbacks_.empty());
529 PendingOperation op = pending_quota_checks_.front();
530 pending_quota_checks_.pop();
531
532 switch (op.type) {
533 case PendingOperation::WRITE: {
534 int64_t growth = op.offset + op.bytes_to_write - file_size_;
535 if (growth > cached_available_space_) {
536 RunAndRemoveFirstPendingCallback(
537 &pending_quota_check_callbacks_,
538 PP_ERROR_NOQUOTA);
539 return;
michaeln 2011/07/20 21:28:33 What about other pending checks in the queue? Is i
kinuko 2011/07/21 14:34:08 Done.
540 }
541 if (!base::FileUtilProxy::Write(
542 instance()->delegate()->GetFileThreadMessageLoopProxy(),
543 file_, op.offset, op.buffer, op.bytes_to_write,
544 callback_factory_.NewCallback(
545 &PPB_FileIO_Impl::WriteCallback))) {
546 RunAndRemoveFirstPendingCallback(
547 &pending_quota_check_callbacks_, PP_ERROR_FAILED);
548 }
549 pending_write_offset_.push(op.offset);
550 break;
551 }
552
553 case PendingOperation::SETLENGTH: {
554 int64_t growth = op.length - file_size_;
555 if (growth > cached_available_space_) {
556 RunAndRemoveFirstPendingCallback(
557 &pending_quota_check_callbacks_,
558 PP_ERROR_NOQUOTA);
559 return;
560 }
561 if (!base::FileUtilProxy::Truncate(
562 instance()->delegate()->GetFileThreadMessageLoopProxy(),
563 file_, op.length,
564 callback_factory_.NewCallback(
565 &PPB_FileIO_Impl::SetLengthCallback))) {
566 RunAndRemoveFirstPendingCallback(
567 &pending_quota_check_callbacks_, PP_ERROR_FAILED);
568 }
569 DCHECK_EQ(-1, pending_setlength_length_);
570 pending_setlength_length_ = op.length;
571 break;
572 }
573
574 default:
575 NOTREACHED();
576 return;
577 }
578
579 CallbackEntry entry = pending_quota_check_callbacks_.front();
580 pending_quota_check_callbacks_.pop();
581 callbacks_.push(entry);
582 }
583 }
584
380 } // namespace ppapi 585 } // namespace ppapi
381 } // namespace webkit 586 } // namespace webkit
OLDNEW
« webkit/plugins/ppapi/plugin_delegate.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