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

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

Powered by Google App Engine
This is Rietveld 408576698