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

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

Issue 18063005: Do PPB_FileIO Query and Read in the plugin process. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to David's latest. Created 7 years, 4 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) 2012 The Chromium Authors. All rights reserved. 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 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 "content/renderer/pepper/pepper_file_io_host.h" 5 #include "content/renderer/pepper/pepper_file_io_host.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/files/file_util_proxy.h" 11 #include "base/files/file_util_proxy.h"
12 #include "content/public/common/content_client.h" 12 #include "content/public/common/content_client.h"
13 #include "content/public/renderer/content_renderer_client.h" 13 #include "content/public/renderer/content_renderer_client.h"
14 #include "ppapi/c/pp_errors.h" 14 #include "ppapi/c/pp_errors.h"
15 #include "ppapi/c/ppb_file_io.h"
15 #include "ppapi/host/dispatch_host_message.h" 16 #include "ppapi/host/dispatch_host_message.h"
16 #include "ppapi/host/ppapi_host.h" 17 #include "ppapi/host/ppapi_host.h"
17 #include "ppapi/proxy/ppapi_messages.h" 18 #include "ppapi/proxy/ppapi_messages.h"
18 #include "ppapi/shared_impl/file_type_conversion.h" 19 #include "ppapi/shared_impl/file_type_conversion.h"
19 #include "ppapi/shared_impl/time_conversion.h" 20 #include "ppapi/shared_impl/time_conversion.h"
20 #include "ppapi/thunk/enter.h" 21 #include "ppapi/thunk/enter.h"
21 #include "third_party/WebKit/public/web/WebPluginContainer.h" 22 #include "third_party/WebKit/public/web/WebPluginContainer.h"
22 #include "webkit/plugins/ppapi/host_globals.h" 23 #include "webkit/plugins/ppapi/host_globals.h"
23 #include "webkit/plugins/ppapi/ppapi_plugin_instance_impl.h" 24 #include "webkit/plugins/ppapi/ppapi_plugin_instance_impl.h"
24 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h" 25 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
(...skipping 26 matching lines...) Expand all
51 // callbacks here. 52 // callbacks here.
52 return pp_error == PP_OK ? byte_number : pp_error; 53 return pp_error == PP_OK ? byte_number : pp_error;
53 } 54 }
54 55
55 } // namespace 56 } // namespace
56 57
57 PepperFileIOHost::PepperFileIOHost(RendererPpapiHost* host, 58 PepperFileIOHost::PepperFileIOHost(RendererPpapiHost* host,
58 PP_Instance instance, 59 PP_Instance instance,
59 PP_Resource resource) 60 PP_Resource resource)
60 : ResourceHost(host->GetPpapiHost(), instance, resource), 61 : ResourceHost(host->GetPpapiHost(), instance, resource),
62 renderer_ppapi_host_(host),
61 plugin_delegate_(NULL), 63 plugin_delegate_(NULL),
62 file_(base::kInvalidPlatformFileValue), 64 file_(base::kInvalidPlatformFileValue),
63 file_system_type_(PP_FILESYSTEMTYPE_INVALID), 65 file_system_type_(PP_FILESYSTEMTYPE_INVALID),
64 quota_policy_(quota::kQuotaLimitTypeUnknown), 66 quota_policy_(quota::kQuotaLimitTypeUnknown),
65 is_running_in_process_(host->IsRunningInProcess()), 67 is_running_in_process_(host->IsRunningInProcess()),
66 open_flags_(0), 68 open_flags_(0),
67 weak_factory_(this) { 69 weak_factory_(this) {
68 // TODO(victorhsieh): eliminate plugin_delegate_ as it's no longer needed. 70 // TODO(victorhsieh): eliminate plugin_delegate_ as it's no longer needed.
69 webkit::ppapi::PluginInstanceImpl* plugin_instance = 71 webkit::ppapi::PluginInstanceImpl* plugin_instance =
70 webkit::ppapi::HostGlobals::Get()->GetInstance(instance); 72 webkit::ppapi::HostGlobals::Get()->GetInstance(instance);
71 plugin_delegate_ = plugin_instance ? plugin_instance->delegate() : NULL; 73 plugin_delegate_ = plugin_instance ? plugin_instance->delegate() : NULL;
72 } 74 }
73 75
74 PepperFileIOHost::~PepperFileIOHost() { 76 PepperFileIOHost::~PepperFileIOHost() {
75 OnHostMsgClose(NULL); 77 OnHostMsgClose(NULL);
76 } 78 }
77 79
78 int32_t PepperFileIOHost::OnResourceMessageReceived( 80 int32_t PepperFileIOHost::OnResourceMessageReceived(
79 const IPC::Message& msg, 81 const IPC::Message& msg,
80 ppapi::host::HostMessageContext* context) { 82 ppapi::host::HostMessageContext* context) {
81 IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg) 83 IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
82 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open, 84 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
83 OnHostMsgOpen) 85 OnHostMsgOpen)
84 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Query,
85 OnHostMsgQuery)
86 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch, 86 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
87 OnHostMsgTouch) 87 OnHostMsgTouch)
88 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Read,
89 OnHostMsgRead)
90 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write, 88 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
91 OnHostMsgWrite) 89 OnHostMsgWrite)
92 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength, 90 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
93 OnHostMsgSetLength) 91 OnHostMsgSetLength)
94 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush, 92 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush,
95 OnHostMsgFlush) 93 OnHostMsgFlush)
96 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close, 94 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close,
97 OnHostMsgClose) 95 OnHostMsgClose)
98 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillWrite, 96 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillWrite,
99 OnHostMsgWillWrite) 97 OnHostMsgWillWrite)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback, 152 base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
155 weak_factory_.GetWeakPtr(), 153 weak_factory_.GetWeakPtr(),
156 context->MakeReplyMessageContext()))) 154 context->MakeReplyMessageContext())))
157 return PP_ERROR_FAILED; 155 return PP_ERROR_FAILED;
158 } 156 }
159 157
160 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 158 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
161 return PP_OK_COMPLETIONPENDING; 159 return PP_OK_COMPLETIONPENDING;
162 } 160 }
163 161
164 int32_t PepperFileIOHost::OnHostMsgQuery(
165 ppapi::host::HostMessageContext* context) {
166 int32_t rv = state_manager_.CheckOperationState(
167 FileIOStateManager::OPERATION_EXCLUSIVE, true);
168 if (rv != PP_OK)
169 return rv;
170
171 if (!plugin_delegate_)
172 return PP_ERROR_FAILED;
173
174 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
175 plugin_delegate_->GetFileThreadMessageLoopProxy().get(),
176 file_,
177 base::Bind(&PepperFileIOHost::ExecutePlatformQueryCallback,
178 weak_factory_.GetWeakPtr(),
179 context->MakeReplyMessageContext())))
180 return PP_ERROR_FAILED;
181
182 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
183 return PP_OK_COMPLETIONPENDING;
184 }
185
186 int32_t PepperFileIOHost::OnHostMsgTouch( 162 int32_t PepperFileIOHost::OnHostMsgTouch(
187 ppapi::host::HostMessageContext* context, 163 ppapi::host::HostMessageContext* context,
188 PP_Time last_access_time, 164 PP_Time last_access_time,
189 PP_Time last_modified_time) { 165 PP_Time last_modified_time) {
190 int32_t rv = state_manager_.CheckOperationState( 166 int32_t rv = state_manager_.CheckOperationState(
191 FileIOStateManager::OPERATION_EXCLUSIVE, true); 167 FileIOStateManager::OPERATION_EXCLUSIVE, true);
192 if (rv != PP_OK) 168 if (rv != PP_OK)
193 return rv; 169 return rv;
194 170
195 if (!plugin_delegate_) 171 if (!plugin_delegate_)
(...skipping 20 matching lines...) Expand all
216 PPTimeToTime(last_modified_time), 192 PPTimeToTime(last_modified_time),
217 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, 193 base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback,
218 weak_factory_.GetWeakPtr(), 194 weak_factory_.GetWeakPtr(),
219 context->MakeReplyMessageContext()))) 195 context->MakeReplyMessageContext())))
220 return PP_ERROR_FAILED; 196 return PP_ERROR_FAILED;
221 197
222 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 198 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
223 return PP_OK_COMPLETIONPENDING; 199 return PP_OK_COMPLETIONPENDING;
224 } 200 }
225 201
226 int32_t PepperFileIOHost::OnHostMsgRead(
227 ppapi::host::HostMessageContext* context,
228 int64_t offset,
229 int32_t max_read_length) {
230 int32_t rv = state_manager_.CheckOperationState(
231 FileIOStateManager::OPERATION_READ, true);
232 if (rv != PP_OK)
233 return rv;
234
235 // Validate max_read_length before allocating below. This value is coming from
236 // the untrusted plugin.
237 if (max_read_length < 0) {
238 ReplyMessageContext reply_context = context->MakeReplyMessageContext();
239 reply_context.params.set_result(PP_ERROR_FAILED);
240 host()->SendReply(reply_context,
241 PpapiPluginMsg_FileIO_ReadReply(std::string()));
242 return PP_OK_COMPLETIONPENDING;
243 }
244
245 if (!plugin_delegate_)
246 return PP_ERROR_FAILED;
247
248 if (!base::FileUtilProxy::Read(
249 plugin_delegate_->GetFileThreadMessageLoopProxy().get(),
250 file_,
251 offset,
252 max_read_length,
253 base::Bind(&PepperFileIOHost::ExecutePlatformReadCallback,
254 weak_factory_.GetWeakPtr(),
255 context->MakeReplyMessageContext())))
256 return PP_ERROR_FAILED;
257
258 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
259 return PP_OK_COMPLETIONPENDING;
260 }
261
262 int32_t PepperFileIOHost::OnHostMsgWrite( 202 int32_t PepperFileIOHost::OnHostMsgWrite(
263 ppapi::host::HostMessageContext* context, 203 ppapi::host::HostMessageContext* context,
264 int64_t offset, 204 int64_t offset,
265 const std::string& buffer) { 205 const std::string& buffer) {
266 int32_t rv = state_manager_.CheckOperationState( 206 int32_t rv = state_manager_.CheckOperationState(
267 FileIOStateManager::OPERATION_WRITE, true); 207 FileIOStateManager::OPERATION_WRITE, true);
268 if (rv != PP_OK) 208 if (rv != PP_OK)
269 return rv; 209 return rv;
270 210
271 if (quota_file_io_) { 211 if (quota_file_io_) {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); 348 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
409 return PP_OK_COMPLETIONPENDING; 349 return PP_OK_COMPLETIONPENDING;
410 } 350 }
411 351
412 int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle( 352 int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
413 ppapi::host::HostMessageContext* context) { 353 ppapi::host::HostMessageContext* context) {
414 if (!is_running_in_process_ && 354 if (!is_running_in_process_ &&
415 quota_policy_ != quota::kQuotaLimitTypeUnlimited) 355 quota_policy_ != quota::kQuotaLimitTypeUnlimited)
416 return PP_ERROR_FAILED; 356 return PP_ERROR_FAILED;
417 357
418 RendererPpapiHost* renderer_ppapi_host =
419 RendererPpapiHost::GetForPPInstance(pp_instance());
420
421 // Whitelist to make it privately accessible. 358 // Whitelist to make it privately accessible.
422 if (!GetContentClient()->renderer()->IsPluginAllowedToCallRequestOSFileHandle( 359 if (!GetContentClient()->renderer()->IsPluginAllowedToCallRequestOSFileHandle(
423 renderer_ppapi_host->GetContainerForInstance(pp_instance()))) 360 renderer_ppapi_host_->GetContainerForInstance(pp_instance())))
424 return PP_ERROR_NOACCESS; 361 return PP_ERROR_NOACCESS;
425 362
426 IPC::PlatformFileForTransit file = 363 IPC::PlatformFileForTransit file =
427 renderer_ppapi_host->ShareHandleWithRemote(file_, false); 364 renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
428 if (file == IPC::InvalidPlatformFileForTransit()) 365 if (file == IPC::InvalidPlatformFileForTransit())
429 return PP_ERROR_FAILED; 366 return PP_ERROR_FAILED;
430 ppapi::host::ReplyMessageContext reply_context = 367 ppapi::host::ReplyMessageContext reply_context =
431 context->MakeReplyMessageContext(); 368 context->MakeReplyMessageContext();
432 ppapi::proxy::SerializedHandle file_handle; 369 ppapi::proxy::SerializedHandle file_handle;
433 file_handle.set_file_handle(file, open_flags_); 370 file_handle.set_file_handle(file, open_flags_);
434 reply_context.params.AppendHandle(file_handle); 371 reply_context.params.AppendHandle(file_handle);
435 host()->SendReply(reply_context, 372 host()->SendReply(reply_context,
436 PpapiPluginMsg_FileIO_RequestOSFileHandleReply()); 373 PpapiPluginMsg_FileIO_RequestOSFileHandleReply());
437 return PP_OK_COMPLETIONPENDING; 374 return PP_OK_COMPLETIONPENDING;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 base::PlatformFileError error_code, 407 base::PlatformFileError error_code,
471 base::PassPlatformFile file) { 408 base::PassPlatformFile file) {
472 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code); 409 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
473 if (pp_error == PP_OK) 410 if (pp_error == PP_OK)
474 state_manager_.SetOpenSucceed(); 411 state_manager_.SetOpenSucceed();
475 412
476 DCHECK(file_ == base::kInvalidPlatformFileValue); 413 DCHECK(file_ == base::kInvalidPlatformFileValue);
477 file_ = file.ReleaseValue(); 414 file_ = file.ReleaseValue();
478 415
479 DCHECK(!quota_file_io_.get()); 416 DCHECK(!quota_file_io_.get());
480 if (file_ != base::kInvalidPlatformFileValue && 417 if (file_ != base::kInvalidPlatformFileValue) {
481 (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY || 418 if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
482 file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT)) { 419 file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) {
483 quota_file_io_.reset(new webkit::ppapi::QuotaFileIO( 420 quota_file_io_.reset(new webkit::ppapi::QuotaFileIO(
484 pp_instance(), file_, file_system_url_, file_system_type_)); 421 pp_instance(), file_, file_system_url_, file_system_type_));
422 }
423
424 IPC::PlatformFileForTransit file_for_transit =
425 renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
426 if (!(file_for_transit == IPC::InvalidPlatformFileForTransit())) {
427 // Pass a good file descriptor over to the plugin process. This is used
428 // in the plugin for any other file operations that can be done there.
429 // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so
430 // the plugin can't bypass our quota checks.
431 int32_t no_write_flags =
432 open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND);
433 ppapi::proxy::SerializedHandle file_handle;
434 file_handle.set_file_handle(file_for_transit, no_write_flags);
435 reply_context.params.AppendHandle(file_handle);
436 }
485 } 437 }
486 438
487 reply_context.params.set_result(pp_error); 439 reply_context.params.set_result(pp_error);
488 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply()); 440 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply());
489 state_manager_.SetOperationFinished(); 441 state_manager_.SetOperationFinished();
490 } 442 }
491 443
492 void PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback( 444 void PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback(
493 ppapi::host::ReplyMessageContext reply_context, 445 ppapi::host::ReplyMessageContext reply_context,
494 base::PlatformFileError error_code, 446 base::PlatformFileError error_code,
495 base::PassPlatformFile file, 447 base::PassPlatformFile file,
496 quota::QuotaLimitType quota_policy, 448 quota::QuotaLimitType quota_policy,
497 const PluginDelegate::NotifyCloseFileCallback& callback) { 449 const PluginDelegate::NotifyCloseFileCallback& callback) {
498 if (error_code == base::PLATFORM_FILE_OK) 450 if (error_code == base::PLATFORM_FILE_OK)
499 notify_close_file_callback_ = callback; 451 notify_close_file_callback_ = callback;
500 quota_policy_ = quota_policy; 452 quota_policy_ = quota_policy;
501 ExecutePlatformOpenFileCallback(reply_context, error_code, file); 453 ExecutePlatformOpenFileCallback(reply_context, error_code, file);
502 } 454 }
503 455
504 void PepperFileIOHost::ExecutePlatformQueryCallback(
505 ppapi::host::ReplyMessageContext reply_context,
506 base::PlatformFileError error_code,
507 const base::PlatformFileInfo& file_info) {
508 PP_FileInfo pp_info;
509 ppapi::PlatformFileInfoToPepperFileInfo(file_info, file_system_type_,
510 &pp_info);
511
512 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
513 reply_context.params.set_result(pp_error);
514 host()->SendReply(reply_context,
515 PpapiPluginMsg_FileIO_QueryReply(pp_info));
516 state_manager_.SetOperationFinished();
517 }
518
519 void PepperFileIOHost::ExecutePlatformReadCallback(
520 ppapi::host::ReplyMessageContext reply_context,
521 base::PlatformFileError error_code,
522 const char* data, int bytes_read) {
523 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
524
525 // Only send the amount of data in the string that was actually read.
526 std::string buffer;
527 if (pp_error == PP_OK)
528 buffer.append(data, bytes_read);
529 reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_read));
530 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_ReadReply(buffer));
531 state_manager_.SetOperationFinished();
532 }
533
534 void PepperFileIOHost::ExecutePlatformWriteCallback( 456 void PepperFileIOHost::ExecutePlatformWriteCallback(
535 ppapi::host::ReplyMessageContext reply_context, 457 ppapi::host::ReplyMessageContext reply_context,
536 base::PlatformFileError error_code, 458 base::PlatformFileError error_code,
537 int bytes_written) { 459 int bytes_written) {
538 // On the plugin side, the callback expects a parameter with different meaning 460 // On the plugin side, the callback expects a parameter with different meaning
539 // depends on whether is negative or not. It is the result here. We translate 461 // depends on whether is negative or not. It is the result here. We translate
540 // for the callback. 462 // for the callback.
541 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code); 463 int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
542 reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written)); 464 reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
543 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply()); 465 host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
544 state_manager_.SetOperationFinished(); 466 state_manager_.SetOperationFinished();
545 } 467 }
546 468
547 } // namespace content 469 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698