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

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

Powered by Google App Engine
This is Rietveld 408576698