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

Side by Side Diff: content/renderer/pepper/pepper_file_io_host.cc

Issue 11419131: Refactor FileIO to the new design (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "content/renderer/pepper/pepper_file_io_host.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/file_util_proxy.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/host/dispatch_host_message.h"
14 #include "ppapi/host/ppapi_host.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/shared_impl/file_type_conversion.h"
17 #include "ppapi/shared_impl/file_type_conversion.h"
18 #include "ppapi/shared_impl/time_conversion.h"
19 #include "ppapi/shared_impl/time_conversion.h"
20 #include "webkit/fileapi/file_system_callback_dispatcher.h"
21 #include "webkit/plugins/ppapi/file_callbacks.h"
22 #include "webkit/plugins/ppapi/host_globals.h"
23 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
24 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
25 #include "webkit/plugins/ppapi/quota_file_io.h"
26
27 namespace content {
28
29 using ppapi::PPTimeToTime;
30 using ppapi::TimeToPPTime;
31 using ppapi::thunk::PPB_FileRef_API;
32 using webkit::ppapi::PPB_FileRef_Impl;
33 using webkit::ppapi::PluginDelegate;
34
35 namespace {
36
37 // The maximum size we'll support reading in one chunk. The renderer process
38 // must allocate a buffer sized according to the request of the plugin. To
39 // keep things from getting out of control, we cap the read size to this value.
40 // This should generally be OK since the API specifies that it may perform a
41 // partial read.
42 static const int32_t kMaxReadSize = 32 * 1024 * 1024; // 32MB
43
44 typedef base::Callback<void (base::PlatformFileError)> PlatformGeneralCallback;
45
46 class PlatformGeneralCallbackTranslator
47 : public fileapi::FileSystemCallbackDispatcher {
48 public:
49 PlatformGeneralCallbackTranslator(
50 const PlatformGeneralCallback& callback)
51 : callback_(callback) {}
52
53 virtual ~PlatformGeneralCallbackTranslator() {}
54
55 virtual void DidSucceed() OVERRIDE {
56 callback_.Run(base::PLATFORM_FILE_OK);
57 }
58
59 virtual void DidReadMetadata(
60 const base::PlatformFileInfo& file_info,
61 const FilePath& platform_path) OVERRIDE {
62 NOTREACHED();
63 }
64
65 virtual void DidReadDirectory(
66 const std::vector<base::FileUtilProxy::Entry>& entries,
67 bool has_more) OVERRIDE {
68 NOTREACHED();
69 }
70
71 virtual void DidOpenFileSystem(const std::string& name,
72 const GURL& root) OVERRIDE {
73 NOTREACHED();
74 }
75
76 virtual void DidFail(base::PlatformFileError error_code) OVERRIDE {
77 callback_.Run(error_code);
78 }
79
80 virtual void DidWrite(int64 bytes, bool complete) OVERRIDE {
81 NOTREACHED();
82 }
83
84 virtual void DidOpenFile(base::PlatformFile file) OVERRIDE {
85 NOTREACHED();
86 }
87
88 private:
89 PlatformGeneralCallback callback_;
90 };
91
92 int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) {
93 // On the plugin side, some callbacks expect a parameter that means different
94 // things depending on whether is negative or not. We translate for those
95 // callbacks here.
96 return pp_error == PP_OK ? byte_number : pp_error;
97 }
98
99 } // namespace
100
101 PepperFileIOHost::PepperFileIOHost(RendererPpapiHost* host,
102 PP_Instance instance,
103 PP_Resource resource)
104 : ResourceHost(host->GetPpapiHost(), instance, resource),
105 ppapi::PPB_FileIO_Shared(),
106 file_(base::kInvalidPlatformFileValue),
107 file_system_type_(PP_FILESYSTEMTYPE_INVALID),
108 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
109 // TODO: eliminate plugin_delegate_ as it's no longer needed.
110 webkit::ppapi::PluginInstance* plugin_instance =
111 webkit::ppapi::HostGlobals::Get()->GetInstance(instance);
112 plugin_delegate_ = plugin_instance ? plugin_instance->delegate() : NULL;
113 }
114
115 PepperFileIOHost::~PepperFileIOHost() {
116 }
117
118 int32_t PepperFileIOHost::OnResourceMessageReceived(
119 const IPC::Message& msg,
120 ppapi::host::HostMessageContext* context) {
121 IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
122 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
123 OnHostMsgOpen)
124 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Query,
125 OnHostMsgQuery)
126 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
127 OnHostMsgTouch)
128 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Read,
129 OnHostMsgRead)
130 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
131 OnHostMsgWrite)
132 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
133 OnHostMsgSetLength)
134 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush,
135 OnHostMsgFlush)
136 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close,
137 OnHostMsgClose)
138 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillWrite,
139 OnHostMsgWillWrite)
140 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillSetLength,
141 OnHostMsgWillSetLength)
142 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_GetOSFileDescriptor,
143 OnHostMsgGetOSFileDescriptor)
144 IPC_END_MESSAGE_MAP()
145 return PP_ERROR_FAILED;
146 }
147
148 int32_t PepperFileIOHost::OnHostMsgOpen(
149 ppapi::host::HostMessageContext* context,
150 PP_Resource file_ref_resource,
151 int32_t open_flags) {
152 temp_reply_context_ = context->MakeReplyMessageContext();
153 return DoOpen(file_ref_resource, open_flags);
154 }
155
156 int32_t PepperFileIOHost::OnHostMsgQuery(
157 ppapi::host::HostMessageContext* context) {
158 temp_reply_context_ = context->MakeReplyMessageContext();
159 return DoQuery();
160 }
161
162 int32_t PepperFileIOHost::OnHostMsgTouch(
163 ppapi::host::HostMessageContext* context,
164 PP_Time last_access_time,
165 PP_Time last_modified_time) {
166 temp_reply_context_ = context->MakeReplyMessageContext();
167 return DoTouch(last_access_time, last_modified_time);
168 }
169
170 int32_t PepperFileIOHost::OnHostMsgRead(
171 ppapi::host::HostMessageContext* context,
172 int64_t offset,
173 int32_t bytes_to_read) {
174
175 // Validate bytes_to_read before allocating below. This value is coming from
176 // the untrusted plugin.
177 if (bytes_to_read < 0) {
178 ppapi::host::ReplyMessageContext reply_context =
179 context->MakeReplyMessageContext();
180 reply_context.params.set_result(PP_ERROR_FAILED);
181 host()->SendReply(reply_context,
182 PpapiPluginMsg_FileIO_ReadComplete(std::string()));
183 return PP_OK_COMPLETIONPENDING;
184 }
185
186 temp_reply_context_ = context->MakeReplyMessageContext();
187 return DoRead(offset, std::min(bytes_to_read, kMaxReadSize));
188 }
189
190 int32_t PepperFileIOHost::OnHostMsgWrite(
191 ppapi::host::HostMessageContext* context,
192 int64_t offset,
193 const std::string& buffer) {
194 temp_reply_context_ = context->MakeReplyMessageContext();
195 return DoWrite(offset, buffer.c_str(), buffer.size());
196 }
197
198 int32_t PepperFileIOHost::OnHostMsgSetLength(
199 ppapi::host::HostMessageContext* context,
200 int64_t length) {
201 temp_reply_context_ = context->MakeReplyMessageContext();
202 return DoSetLength(length);
203 }
204
205 int32_t PepperFileIOHost::OnHostMsgFlush(
206 ppapi::host::HostMessageContext* context) {
207 temp_reply_context_ = context->MakeReplyMessageContext();
208 return DoFlush();
209 }
210
211 int32_t PepperFileIOHost::OnHostMsgClose(
212 ppapi::host::HostMessageContext* context) {
213 if (file_ != base::kInvalidPlatformFileValue && plugin_delegate_) {
214 base::FileUtilProxy::Close(
215 plugin_delegate_->GetFileThreadMessageLoopProxy(),
216 file_,
217 base::ResetAndReturn(&notify_close_file_callback_));
218 file_ = base::kInvalidPlatformFileValue;
219 quota_file_io_.reset();
220 }
221 return PP_OK;
222 }
223
224 int32_t PepperFileIOHost::OnHostMsgWillWrite(
225 ppapi::host::HostMessageContext* context,
226 int64_t offset,
227 int32_t bytes_to_write) {
228 int32_t rv = CommonPreCondition(true, OPERATION_EXCLUSIVE);
229 if (rv != PP_OK)
230 return rv;
231
232 if (!quota_file_io_.get())
233 return PP_OK;
234
235 if (!quota_file_io_->WillWrite(
236 offset, bytes_to_write,
237 base::Bind(&PepperFileIOHost::ExecutePlatformWillWriteCallback,
238 weak_factory_.GetWeakPtr(),
239 context->MakeReplyMessageContext())))
240 return PP_ERROR_FAILED;
241
242 return PP_OK_COMPLETIONPENDING;
243 }
244
245 int32_t PepperFileIOHost::OnHostMsgWillSetLength(
246 ppapi::host::HostMessageContext* context,
247 int64_t length) {
248 int32_t rv = CommonPreCondition(true, OPERATION_EXCLUSIVE);
249 if (rv != PP_OK)
250 return rv;
251
252 if (!quota_file_io_.get())
253 return PP_OK;
254
255 if (!quota_file_io_->WillSetLength(
256 length,
257 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
258 weak_factory_.GetWeakPtr(),
259 context->MakeReplyMessageContext())))
260 return PP_ERROR_FAILED;
261
262 return PP_OK_COMPLETIONPENDING;
263 }
264
265 int32_t PepperFileIOHost::OnHostMsgGetOSFileDescriptor(
266 ppapi::host::HostMessageContext* context) {
267 //if (!host()->IsRunningInProcess())
268 // return PP_ERROR_FAILED;
269 int32_t fd =
270 #if defined(OS_POSIX)
271 file_;
272 #elif defined(OS_WIN)
273 reinterpret_cast<uintptr_t>(file_);
274 #else
275 -1; // Platform not supported.
276 #endif
277 host()->SendReply(context->MakeReplyMessageContext(),
278 PpapiPluginMsg_FileIO_GetOSFileDescriptorReply(fd));
279 return PP_OK_COMPLETIONPENDING;
280 }
281
282 int32_t PepperFileIOHost::CommonPreCondition(bool should_be_open,
283 OperationType new_op) {
284 if (!plugin_delegate_ || !CheckOpenState(should_be_open))
285 return PP_ERROR_FAILED;
286 return PP_OK;
287 }
288
289 void PepperFileIOHost::CommonPostCondition(OperationType new_op) {
290 }
291
292 int32_t PepperFileIOHost::OpenValidated(
293 PP_Resource file_ref_resource,
294 PPB_FileRef_API* file_ref_api,
295 int32_t open_flags) {
296 int flags = 0;
297 if (!::ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags, &flags))
298 return PP_ERROR_BADARGUMENT;
299
300 PP_FileSystemType type = file_ref_api->GetFileSystemType();
301 if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
302 type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
303 type != PP_FILESYSTEMTYPE_EXTERNAL)
304 return PP_ERROR_FAILED;
305 file_system_type_ = type;
306
307 PPB_FileRef_Impl* file_ref = static_cast<PPB_FileRef_Impl*>(file_ref_api);
308 if (file_ref->HasValidFileSystem()) {
309 file_system_url_ = file_ref->GetFileSystemURL();
310 if (!plugin_delegate_->AsyncOpenFileSystemURL(
311 file_system_url_, flags,
312 base::Bind(
313 &PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback,
314 weak_factory_.GetWeakPtr(),
315 temp_reply_context_)))
316 return PP_ERROR_FAILED;
317 } else {
318 if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL)
319 return PP_ERROR_FAILED;
320 if (!plugin_delegate_->AsyncOpenFile(
321 file_ref->GetSystemPath(), flags,
322 base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
323 weak_factory_.GetWeakPtr(),
324 temp_reply_context_)))
325 return PP_ERROR_FAILED;
326 }
327
328 return PP_OK_COMPLETIONPENDING;
329 }
330
331 int32_t PepperFileIOHost::QueryValidated() {
332 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
333 plugin_delegate_->GetFileThreadMessageLoopProxy(), file_,
334 base::Bind(&PepperFileIOHost::ExecutePlatformQueryCallback,
335 weak_factory_.GetWeakPtr(),
336 temp_reply_context_)))
337 return PP_ERROR_FAILED;
338
339 return PP_OK_COMPLETIONPENDING;
340 }
341
342 int32_t PepperFileIOHost::TouchValidated(
343 PP_Time last_access_time,
344 PP_Time last_modified_time) {
345 if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
346 if (!plugin_delegate_->Touch(
347 file_system_url_,
348 PPTimeToTime(last_access_time),
349 PPTimeToTime(last_modified_time),
350 new PlatformGeneralCallbackTranslator(
351 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
352 weak_factory_.GetWeakPtr(),
353 temp_reply_context_))))
354 return PP_ERROR_FAILED;
355 return PP_OK_COMPLETIONPENDING;
356 }
357
358 // TODO(nhiroki): fix a failure of FileIO.Touch for an external filesystem on
359 // Mac and Linux due to sandbox restrictions (http://crbug.com/101128).
360 if (!base::FileUtilProxy::Touch(
361 plugin_delegate_->GetFileThreadMessageLoopProxy(),
362 file_, PPTimeToTime(last_access_time),
363 PPTimeToTime(last_modified_time),
364 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
365 weak_factory_.GetWeakPtr(),
366 temp_reply_context_)))
367 return PP_ERROR_FAILED;
368
369 return PP_OK_COMPLETIONPENDING;
370 }
371
372 int32_t PepperFileIOHost::ReadValidated(
373 int64_t offset,
374 int32_t max_read_length) {
375 if (!base::FileUtilProxy::Read(
376 plugin_delegate_->GetFileThreadMessageLoopProxy(), file_, offset,
377 max_read_length,
378 base::Bind(&PepperFileIOHost::ExecutePlatformReadCallback,
379 weak_factory_.GetWeakPtr(),
380 temp_reply_context_)))
381 return PP_ERROR_FAILED;
382
383 return PP_OK_COMPLETIONPENDING;
384 }
385
386 int32_t PepperFileIOHost::WriteValidated(
387 int64_t offset,
388 const char* buffer,
389 int32_t bytes_to_write) {
390 if (quota_file_io_.get()) {
391 if (!quota_file_io_->Write(
392 offset, buffer, bytes_to_write,
393 base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
394 weak_factory_.GetWeakPtr(),
395 temp_reply_context_)))
396 return PP_ERROR_FAILED;
397 } else {
398 if (!base::FileUtilProxy::Write(
399 plugin_delegate_->GetFileThreadMessageLoopProxy(), file_, offset,
400 buffer, bytes_to_write,
401 base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback,
402 weak_factory_.GetWeakPtr(),
403 temp_reply_context_)))
404 return PP_ERROR_FAILED;
405 }
406
407 return PP_OK_COMPLETIONPENDING;
408 }
409
410 int32_t PepperFileIOHost::SetLengthValidated(
411 int64_t length) {
412 if (quota_file_io_.get()) {
413 if (!quota_file_io_->SetLength(
414 length,
415 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
416 weak_factory_.GetWeakPtr(),
417 temp_reply_context_)))
418 return PP_ERROR_FAILED;
419 } else {
420 if (!base::FileUtilProxy::Truncate(
421 plugin_delegate_->GetFileThreadMessageLoopProxy(), file_, length,
422 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
423 weak_factory_.GetWeakPtr(),
424 temp_reply_context_)))
425 return PP_ERROR_FAILED;
426 }
427
428 return PP_OK_COMPLETIONPENDING;
429 }
430
431 int32_t PepperFileIOHost::FlushValidated() {
432 if (!base::FileUtilProxy::Flush(
433 plugin_delegate_->GetFileThreadMessageLoopProxy(), file_,
434 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
435 weak_factory_.GetWeakPtr(),
436 temp_reply_context_)))
437 return PP_ERROR_FAILED;
438
439 return PP_OK_COMPLETIONPENDING;
440 }
441
442 void PepperFileIOHost::ExecutePlatformGeneralCallback(
443 ppapi::host::ReplyMessageContext reply_context,
444 base::PlatformFileError error_code) {
445 reply_context.params.set_result(
446 ::ppapi::PlatformFileErrorToPepperError(error_code));
447 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralComplete());
448 }
449
450 void PepperFileIOHost::ExecutePlatformOpenFileCallback(
451 ppapi::host::ReplyMessageContext reply_context,
452 base::PlatformFileError error_code,
453 base::PassPlatformFile file) {
454 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
455 if (pp_error == PP_OK)
456 SetOpenSucceed();
457
458 DCHECK(file_ == base::kInvalidPlatformFileValue);
459 file_ = file.ReleaseValue();
460
461 DCHECK(!quota_file_io_.get());
462 if (file_ != base::kInvalidPlatformFileValue &&
463 (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
464 file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT)) {
465 quota_file_io_.reset(new webkit::ppapi::QuotaFileIO(
466 pp_instance(), file_, file_system_url_, file_system_type_));
467 }
468
469 reply_context.params.set_result(pp_error);
470 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenFileComplete());
471 }
472
473 void PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback(
474 ppapi::host::ReplyMessageContext reply_context,
475 base::PlatformFileError error_code,
476 base::PassPlatformFile file,
477 const PluginDelegate::NotifyCloseFileCallback& callback) {
478 if (error_code == base::PLATFORM_FILE_OK)
479 notify_close_file_callback_ = callback;
480 ExecutePlatformOpenFileCallback(reply_context, error_code, file);
481 }
482
483 void PepperFileIOHost::ExecutePlatformQueryCallback(
484 ppapi::host::ReplyMessageContext reply_context,
485 base::PlatformFileError error_code,
486 const base::PlatformFileInfo& file_info) {
487 PP_FileInfo pp_info;
488 pp_info.size = file_info.size;
489 pp_info.creation_time = TimeToPPTime(file_info.creation_time);
490 pp_info.last_access_time = TimeToPPTime(file_info.last_accessed);
491 pp_info.last_modified_time = TimeToPPTime(file_info.last_modified);
492 pp_info.system_type = file_system_type_;
493 if (file_info.is_directory)
494 pp_info.type = PP_FILETYPE_DIRECTORY;
495 else
496 pp_info.type = PP_FILETYPE_REGULAR;
497
498 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
499 reply_context.params.set_result(pp_error);
500 host()->SendReply(reply_context,
501 PpapiPluginMsg_FileIO_QueryComplete(pp_info));
502 }
503
504 void PepperFileIOHost::ExecutePlatformReadCallback(
505 ppapi::host::ReplyMessageContext reply_context,
506 base::PlatformFileError error_code,
507 const char* data, int bytes_read) {
508 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
509
510 // Only send the amount of data in the string that was actually read.
511 std::string buffer;
512 if (pp_error == PP_OK)
513 buffer.append(data, bytes_read);
514 reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_read));
515 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_ReadComplete(buffer));
516 }
517
518 void PepperFileIOHost::ExecutePlatformWriteCallback(
519 ppapi::host::ReplyMessageContext reply_context,
520 base::PlatformFileError error_code,
521 int bytes_written) {
522 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
523 reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
524 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralComplete());
525 }
526
527 void PepperFileIOHost::ExecutePlatformWillWriteCallback(
528 ppapi::host::ReplyMessageContext reply_context,
529 base::PlatformFileError error_code,
530 int bytes_written) {
531 // On the plugin side, the callback expects a parameter with different meaning
532 // depends on whether is negative or not. It is the result here. We
533 // translate for the callback.
534 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
535 reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
536 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralComplete());
537 }
538
539 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698