OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "webkit/glue/plugins/pepper_file_io.h" | |
6 | |
7 #include "base/callback.h" | |
8 #include "base/file_util.h" | |
9 #include "base/file_util_proxy.h" | |
10 #include "base/message_loop_proxy.h" | |
11 #include "base/platform_file.h" | |
12 #include "base/logging.h" | |
13 #include "base/time.h" | |
14 #include "ppapi/c/dev/ppb_file_io_dev.h" | |
15 #include "ppapi/c/dev/ppb_file_io_trusted_dev.h" | |
16 #include "ppapi/c/pp_completion_callback.h" | |
17 #include "ppapi/c/pp_errors.h" | |
18 #include "webkit/glue/plugins/pepper_common.h" | |
19 #include "webkit/glue/plugins/pepper_file_ref.h" | |
20 #include "webkit/glue/plugins/pepper_plugin_instance.h" | |
21 #include "webkit/glue/plugins/pepper_plugin_module.h" | |
22 #include "webkit/glue/plugins/pepper_resource_tracker.h" | |
23 | |
24 namespace pepper { | |
25 | |
26 namespace { | |
27 | |
28 PP_Resource Create(PP_Module module_id) { | |
29 PluginModule* module = ResourceTracker::Get()->GetModule(module_id); | |
30 if (!module) | |
31 return 0; | |
32 | |
33 FileIO* file_io = new FileIO(module); | |
34 return file_io->GetReference(); | |
35 } | |
36 | |
37 PP_Bool IsFileIO(PP_Resource resource) { | |
38 return BoolToPPBool(!!Resource::GetAs<FileIO>(resource)); | |
39 } | |
40 | |
41 int32_t Open(PP_Resource file_io_id, | |
42 PP_Resource file_ref_id, | |
43 int32_t open_flags, | |
44 PP_CompletionCallback callback) { | |
45 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
46 if (!file_io) | |
47 return PP_ERROR_BADRESOURCE; | |
48 | |
49 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
50 if (!file_ref) | |
51 return PP_ERROR_BADRESOURCE; | |
52 | |
53 return file_io->Open(file_ref, open_flags, callback); | |
54 } | |
55 | |
56 int32_t Query(PP_Resource file_io_id, | |
57 PP_FileInfo_Dev* info, | |
58 PP_CompletionCallback callback) { | |
59 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
60 if (!file_io) | |
61 return PP_ERROR_BADRESOURCE; | |
62 return file_io->Query(info, callback); | |
63 } | |
64 | |
65 int32_t Touch(PP_Resource file_io_id, | |
66 PP_Time last_access_time, | |
67 PP_Time last_modified_time, | |
68 PP_CompletionCallback callback) { | |
69 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
70 if (!file_io) | |
71 return PP_ERROR_BADRESOURCE; | |
72 return file_io->Touch(last_access_time, last_modified_time, callback); | |
73 } | |
74 | |
75 int32_t Read(PP_Resource file_io_id, | |
76 int64_t offset, | |
77 char* buffer, | |
78 int32_t bytes_to_read, | |
79 PP_CompletionCallback callback) { | |
80 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
81 if (!file_io) | |
82 return PP_ERROR_BADRESOURCE; | |
83 return file_io->Read(offset, buffer, bytes_to_read, callback); | |
84 } | |
85 | |
86 int32_t Write(PP_Resource file_io_id, | |
87 int64_t offset, | |
88 const char* buffer, | |
89 int32_t bytes_to_write, | |
90 PP_CompletionCallback callback) { | |
91 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
92 if (!file_io) | |
93 return PP_ERROR_BADRESOURCE; | |
94 return file_io->Write(offset, buffer, bytes_to_write, callback); | |
95 } | |
96 | |
97 int32_t SetLength(PP_Resource file_io_id, | |
98 int64_t length, | |
99 PP_CompletionCallback callback) { | |
100 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
101 if (!file_io) | |
102 return PP_ERROR_BADRESOURCE; | |
103 return file_io->SetLength(length, callback); | |
104 } | |
105 | |
106 int32_t Flush(PP_Resource file_io_id, | |
107 PP_CompletionCallback callback) { | |
108 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
109 if (!file_io) | |
110 return PP_ERROR_BADRESOURCE; | |
111 return file_io->Flush(callback); | |
112 } | |
113 | |
114 void Close(PP_Resource file_io_id) { | |
115 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
116 if (!file_io) | |
117 return; | |
118 file_io->Close(); | |
119 } | |
120 | |
121 const PPB_FileIO_Dev ppb_fileio = { | |
122 &Create, | |
123 &IsFileIO, | |
124 &Open, | |
125 &Query, | |
126 &Touch, | |
127 &Read, | |
128 &Write, | |
129 &SetLength, | |
130 &Flush, | |
131 &Close | |
132 }; | |
133 | |
134 int32_t GetOSFileDescriptor(PP_Resource file_io_id) { | |
135 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
136 if (!file_io) | |
137 return PP_ERROR_BADRESOURCE; | |
138 return file_io->GetOSFileDescriptor(); | |
139 } | |
140 | |
141 int32_t WillWrite(PP_Resource file_io_id, | |
142 int64_t offset, | |
143 int32_t bytes_to_write, | |
144 PP_CompletionCallback callback) { | |
145 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
146 if (!file_io) | |
147 return PP_ERROR_BADRESOURCE; | |
148 return file_io->WillWrite(offset, bytes_to_write, callback); | |
149 } | |
150 | |
151 int32_t WillSetLength(PP_Resource file_io_id, | |
152 int64_t length, | |
153 PP_CompletionCallback callback) { | |
154 scoped_refptr<FileIO> file_io(Resource::GetAs<FileIO>(file_io_id)); | |
155 if (!file_io) | |
156 return PP_ERROR_BADRESOURCE; | |
157 return file_io->WillSetLength(length, callback); | |
158 } | |
159 | |
160 const PPB_FileIOTrusted_Dev ppb_fileiotrusted = { | |
161 &GetOSFileDescriptor, | |
162 &WillWrite, | |
163 &WillSetLength | |
164 }; | |
165 | |
166 int PlatformFileErrorToPepperError(base::PlatformFileError error_code) { | |
167 switch (error_code) { | |
168 case base::PLATFORM_FILE_OK: | |
169 return PP_OK; | |
170 case base::PLATFORM_FILE_ERROR_EXISTS: | |
171 return PP_ERROR_FILEEXISTS; | |
172 case base::PLATFORM_FILE_ERROR_NOT_FOUND: | |
173 return PP_ERROR_FILENOTFOUND; | |
174 case base::PLATFORM_FILE_ERROR_ACCESS_DENIED: | |
175 return PP_ERROR_NOACCESS; | |
176 case base::PLATFORM_FILE_ERROR_NO_MEMORY: | |
177 return PP_ERROR_NOMEMORY; | |
178 case base::PLATFORM_FILE_ERROR_NO_SPACE: | |
179 return PP_ERROR_NOSPACE; | |
180 case base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY: | |
181 NOTREACHED(); | |
182 return PP_ERROR_FAILED; | |
183 default: | |
184 return PP_ERROR_FAILED; | |
185 } | |
186 } | |
187 | |
188 } // namespace | |
189 | |
190 FileIO::FileIO(PluginModule* module) | |
191 : Resource(module), | |
192 delegate_(module->GetSomeInstance()->delegate()), | |
193 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), | |
194 file_(base::kInvalidPlatformFileValue), | |
195 callback_(), | |
196 info_(NULL) { | |
197 } | |
198 | |
199 FileIO::~FileIO() { | |
200 Close(); | |
201 } | |
202 | |
203 // static | |
204 const PPB_FileIO_Dev* FileIO::GetInterface() { | |
205 return &ppb_fileio; | |
206 } | |
207 | |
208 // static | |
209 const PPB_FileIOTrusted_Dev* FileIO::GetTrustedInterface() { | |
210 return &ppb_fileiotrusted; | |
211 } | |
212 | |
213 FileIO* FileIO::AsFileIO() { | |
214 return this; | |
215 } | |
216 | |
217 int32_t FileIO::Open(FileRef* file_ref, | |
218 int32_t open_flags, | |
219 PP_CompletionCallback callback) { | |
220 if (file_ != base::kInvalidPlatformFileValue) | |
221 return PP_ERROR_FAILED; | |
222 | |
223 DCHECK(!callback_.func); | |
224 callback_ = callback; | |
225 | |
226 int flags = 0; | |
227 if (open_flags & PP_FILEOPENFLAG_READ) | |
228 flags |= base::PLATFORM_FILE_READ; | |
229 if (open_flags & PP_FILEOPENFLAG_WRITE) { | |
230 flags |= base::PLATFORM_FILE_WRITE; | |
231 flags |= base::PLATFORM_FILE_WRITE_ATTRIBUTES; | |
232 } | |
233 | |
234 if (open_flags & PP_FILEOPENFLAG_TRUNCATE) { | |
235 DCHECK(open_flags & PP_FILEOPENFLAG_WRITE); | |
236 flags |= base::PLATFORM_FILE_TRUNCATE; | |
237 } else if (open_flags & PP_FILEOPENFLAG_CREATE) { | |
238 if (open_flags & PP_FILEOPENFLAG_EXCLUSIVE) | |
239 flags |= base::PLATFORM_FILE_CREATE; | |
240 else | |
241 flags |= base::PLATFORM_FILE_OPEN_ALWAYS; | |
242 } else | |
243 flags |= base::PLATFORM_FILE_OPEN; | |
244 | |
245 file_system_type_ = file_ref->GetFileSystemType(); | |
246 if (!delegate_->AsyncOpenFile( | |
247 file_ref->GetSystemPath(), flags, | |
248 callback_factory_.NewCallback(&FileIO::AsyncOpenFileCallback))) | |
249 return PP_ERROR_FAILED; | |
250 | |
251 return PP_ERROR_WOULDBLOCK; | |
252 } | |
253 | |
254 int32_t FileIO::Query(PP_FileInfo_Dev* info, | |
255 PP_CompletionCallback callback) { | |
256 if (file_ == base::kInvalidPlatformFileValue) | |
257 return PP_ERROR_FAILED; | |
258 | |
259 DCHECK(!callback_.func); | |
260 callback_ = callback; | |
261 | |
262 DCHECK(!info_); | |
263 DCHECK(info); | |
264 info_ = info; | |
265 | |
266 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | |
267 delegate_->GetFileThreadMessageLoopProxy(), file_, | |
268 callback_factory_.NewCallback(&FileIO::QueryInfoCallback))) | |
269 return PP_ERROR_FAILED; | |
270 | |
271 return PP_ERROR_WOULDBLOCK; | |
272 } | |
273 | |
274 int32_t FileIO::Touch(PP_Time last_access_time, | |
275 PP_Time last_modified_time, | |
276 PP_CompletionCallback callback) { | |
277 if (file_ == base::kInvalidPlatformFileValue) | |
278 return PP_ERROR_FAILED; | |
279 | |
280 DCHECK(!callback_.func); | |
281 callback_ = callback; | |
282 | |
283 if (!base::FileUtilProxy::Touch( | |
284 delegate_->GetFileThreadMessageLoopProxy(), | |
285 file_, base::Time::FromDoubleT(last_access_time), | |
286 base::Time::FromDoubleT(last_modified_time), | |
287 callback_factory_.NewCallback(&FileIO::StatusCallback))) | |
288 return PP_ERROR_FAILED; | |
289 | |
290 return PP_ERROR_WOULDBLOCK; | |
291 } | |
292 | |
293 int32_t FileIO::Read(int64_t offset, | |
294 char* buffer, | |
295 int32_t bytes_to_read, | |
296 PP_CompletionCallback callback) { | |
297 if (file_ == base::kInvalidPlatformFileValue) | |
298 return PP_ERROR_FAILED; | |
299 | |
300 DCHECK(!callback_.func); | |
301 callback_ = callback; | |
302 | |
303 if (!base::FileUtilProxy::Read( | |
304 delegate_->GetFileThreadMessageLoopProxy(), | |
305 file_, offset, buffer, bytes_to_read, | |
306 callback_factory_.NewCallback(&FileIO::ReadWriteCallback))) | |
307 return PP_ERROR_FAILED; | |
308 | |
309 return PP_ERROR_WOULDBLOCK; | |
310 } | |
311 | |
312 int32_t FileIO::Write(int64_t offset, | |
313 const char* buffer, | |
314 int32_t bytes_to_write, | |
315 PP_CompletionCallback callback) { | |
316 if (file_ == base::kInvalidPlatformFileValue) | |
317 return PP_ERROR_FAILED; | |
318 | |
319 DCHECK(!callback_.func); | |
320 callback_ = callback; | |
321 | |
322 if (!base::FileUtilProxy::Write( | |
323 delegate_->GetFileThreadMessageLoopProxy(), | |
324 file_, offset, buffer, bytes_to_write, | |
325 callback_factory_.NewCallback(&FileIO::ReadWriteCallback))) | |
326 return PP_ERROR_FAILED; | |
327 | |
328 return PP_ERROR_WOULDBLOCK; | |
329 } | |
330 | |
331 int32_t FileIO::SetLength(int64_t length, | |
332 PP_CompletionCallback callback) { | |
333 if (file_ == base::kInvalidPlatformFileValue) | |
334 return PP_ERROR_FAILED; | |
335 | |
336 DCHECK(!callback_.func); | |
337 callback_ = callback; | |
338 | |
339 if (!base::FileUtilProxy::Truncate( | |
340 delegate_->GetFileThreadMessageLoopProxy(), | |
341 file_, length, | |
342 callback_factory_.NewCallback(&FileIO::StatusCallback))) | |
343 return PP_ERROR_FAILED; | |
344 | |
345 return PP_ERROR_WOULDBLOCK; | |
346 } | |
347 | |
348 int32_t FileIO::Flush(PP_CompletionCallback callback) { | |
349 if (file_ == base::kInvalidPlatformFileValue) | |
350 return PP_ERROR_FAILED; | |
351 | |
352 DCHECK(!callback_.func); | |
353 callback_ = callback; | |
354 | |
355 if (!base::FileUtilProxy::Flush( | |
356 delegate_->GetFileThreadMessageLoopProxy(), file_, | |
357 callback_factory_.NewCallback(&FileIO::StatusCallback))) | |
358 return PP_ERROR_FAILED; | |
359 | |
360 return PP_ERROR_WOULDBLOCK; | |
361 } | |
362 | |
363 void FileIO::Close() { | |
364 if (file_ != base::kInvalidPlatformFileValue) | |
365 base::FileUtilProxy::Close( | |
366 delegate_->GetFileThreadMessageLoopProxy(), file_, NULL); | |
367 } | |
368 | |
369 int32_t FileIO::GetOSFileDescriptor() { | |
370 #if defined(OS_POSIX) | |
371 return file_; | |
372 #elif defined(OS_WIN) | |
373 return reinterpret_cast<uintptr_t>(file_); | |
374 #else | |
375 #error "Platform not supported." | |
376 #endif | |
377 } | |
378 | |
379 int32_t FileIO::WillWrite(int64_t offset, | |
380 int32_t bytes_to_write, | |
381 PP_CompletionCallback callback) { | |
382 // TODO(dumi): implement me | |
383 return PP_OK; | |
384 } | |
385 | |
386 int32_t FileIO::WillSetLength(int64_t length, | |
387 PP_CompletionCallback callback) { | |
388 // TODO(dumi): implement me | |
389 return PP_OK; | |
390 } | |
391 | |
392 void FileIO::RunPendingCallback(int result) { | |
393 if (!callback_.func) | |
394 return; | |
395 | |
396 PP_CompletionCallback callback = {0}; | |
397 std::swap(callback, callback_); | |
398 PP_RunCompletionCallback(&callback, result); | |
399 } | |
400 | |
401 void FileIO::StatusCallback(base::PlatformFileError error_code) { | |
402 RunPendingCallback(PlatformFileErrorToPepperError(error_code)); | |
403 } | |
404 | |
405 void FileIO::AsyncOpenFileCallback(base::PlatformFileError error_code, | |
406 base::PlatformFile file) { | |
407 DCHECK(file_ == base::kInvalidPlatformFileValue); | |
408 file_ = file; | |
409 RunPendingCallback(PlatformFileErrorToPepperError(error_code)); | |
410 } | |
411 | |
412 void FileIO::QueryInfoCallback(base::PlatformFileError error_code, | |
413 const base::PlatformFileInfo& file_info) { | |
414 DCHECK(info_); | |
415 if (error_code == base::PLATFORM_FILE_OK) { | |
416 info_->size = file_info.size; | |
417 info_->creation_time = file_info.creation_time.ToDoubleT(); | |
418 info_->last_access_time = file_info.last_accessed.ToDoubleT(); | |
419 info_->last_modified_time = file_info.last_modified.ToDoubleT(); | |
420 info_->system_type = file_system_type_; | |
421 if (file_info.is_directory) | |
422 info_->type = PP_FILETYPE_DIRECTORY; | |
423 else | |
424 info_->type = PP_FILETYPE_REGULAR; | |
425 } | |
426 RunPendingCallback(PlatformFileErrorToPepperError(error_code)); | |
427 } | |
428 | |
429 void FileIO::ReadWriteCallback(base::PlatformFileError error_code, | |
430 int bytes_read_or_written) { | |
431 if (error_code != base::PLATFORM_FILE_OK) | |
432 RunPendingCallback(PlatformFileErrorToPepperError(error_code)); | |
433 else | |
434 RunPendingCallback(bytes_read_or_written); | |
435 } | |
436 | |
437 } // namespace pepper | |
OLD | NEW |