Index: content/browser/renderer_host/pepper/pepper_file_io_host.cc |
diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/content/browser/renderer_host/pepper/pepper_file_io_host.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c66d57e6a3119cfb2bcd85e14e81fe1c5a979a03 |
--- /dev/null |
+++ b/content/browser/renderer_host/pepper/pepper_file_io_host.cc |
@@ -0,0 +1,545 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/renderer_host/pepper/pepper_file_io_host.h" |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/callback_helpers.h" |
+#include "base/command_line.h" |
bbudge
2013/10/22 17:25:37
Is this needed?
teravest
2013/10/23 16:54:27
Removed.
|
+#include "base/files/file_util_proxy.h" |
+#include "base/memory/weak_ptr.h" |
+#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h" |
+#include "content/browser/renderer_host/pepper/pepper_security_helper.h" |
+#include "content/browser/renderer_host/pepper/quota_file_io.h" |
+#include "content/common/fileapi/file_system_messages.h" |
+#include "content/common/sandbox_util.h" |
+#include "content/common/view_messages.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/content_browser_client.h" |
+#include "content/public/browser/render_process_host.h" |
+#include "content/public/browser/storage_partition.h" |
+#include "content/public/common/content_client.h" |
+#include "ppapi/c/pp_errors.h" |
+#include "ppapi/c/ppb_file_io.h" |
+#include "ppapi/host/dispatch_host_message.h" |
+#include "ppapi/host/ppapi_host.h" |
+#include "ppapi/proxy/ppapi_messages.h" |
+#include "ppapi/shared_impl/file_type_conversion.h" |
+#include "ppapi/shared_impl/time_conversion.h" |
+#include "webkit/browser/fileapi/file_observers.h" |
+#include "webkit/browser/fileapi/file_system_context.h" |
+#include "webkit/browser/fileapi/task_runner_bound_observer_list.h" |
+#include "webkit/browser/quota/quota_manager.h" |
+#include "webkit/common/fileapi/file_system_util.h" |
+ |
+namespace content { |
+ |
+using ppapi::FileIOStateManager; |
+using ppapi::PPTimeToTime; |
+ |
+namespace { |
+ |
+int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) { |
+ // On the plugin side, some callbacks expect a parameter that means different |
+ // things depending on whether it is negative or not. We translate for those |
+ // callbacks here. |
+ return pp_error == PP_OK ? byte_number : pp_error; |
+} |
+ |
+class QuotaFileIODelegate : public QuotaFileIO::Delegate { |
+ public: |
+ QuotaFileIODelegate(scoped_refptr<fileapi::FileSystemContext> context, |
+ int render_process_id) |
+ : context_(context), |
+ weak_factory_(this) { } |
+ virtual ~QuotaFileIODelegate() {} |
+ |
+ virtual void QueryAvailableSpace( |
+ const GURL& origin, |
+ quota::StorageType type, |
+ const AvailableSpaceCallback& callback) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ quota::QuotaManagerProxy* quota_manager_proxy = |
+ context_->quota_manager_proxy(); |
+ DCHECK(quota_manager_proxy); |
+ if (!quota_manager_proxy) { |
+ callback.Run(0); |
+ return; |
+ } |
+ quota::QuotaManager* qm = quota_manager_proxy->quota_manager(); |
+ DCHECK(qm); |
+ if (!qm) { |
+ callback.Run(0); |
+ return; |
+ } |
+ qm->GetUsageAndQuotaForWebApps( |
+ origin, |
+ type, |
+ base::Bind(&QuotaFileIODelegate::GotUsageAndQuotaForWebApps, |
+ weak_factory_.GetWeakPtr(), callback)); |
+ } |
+ |
+ void GotUsageAndQuotaForWebApps(const AvailableSpaceCallback& callback, |
+ quota::QuotaStatusCode code, |
+ int64 usage, |
+ int64 quota) { |
+ if (code == quota::kQuotaStatusOk) |
+ callback.Run(std::max(static_cast<int64>(0), quota - usage)); |
+ else |
+ callback.Run(0); |
+ } |
+ |
+ virtual void WillUpdateFile(const GURL& file_path) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ fileapi::FileSystemURL url(context_->CrackURL(file_path)); |
+ if (!url.is_valid()) |
+ return; |
+ const fileapi::UpdateObserverList* observers = |
+ context_->GetUpdateObservers(url.type()); |
+ if (!observers) |
+ return; |
+ observers->Notify(&fileapi::FileUpdateObserver::OnStartUpdate, |
+ MakeTuple(url)); |
+ } |
+ virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ fileapi::FileSystemURL url(context_->CrackURL(file_path)); |
+ if (!url.is_valid()) |
+ return; |
+ const fileapi::UpdateObserverList* observers = |
+ context_->GetUpdateObservers(url.type()); |
+ if (!observers) |
+ return; |
+ observers->Notify(&fileapi::FileUpdateObserver::OnUpdate, |
+ MakeTuple(url, delta)); |
+ observers->Notify(&fileapi::FileUpdateObserver::OnEndUpdate, |
+ MakeTuple(url)); |
+ } |
+ virtual scoped_refptr<base::MessageLoopProxy> |
+ GetFileThreadMessageLoopProxy() OVERRIDE { |
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE); |
+ } |
+ private: |
+ scoped_refptr<fileapi::FileSystemContext> context_; |
+ base::WeakPtrFactory<QuotaFileIODelegate> weak_factory_; |
+}; |
+ |
+// TODO(teravest): Don't duplicate code with PepperFileSystemBrowserHost. |
+scoped_refptr<fileapi::FileSystemContext> |
+GetFileSystemContextFromRenderId(int render_process_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ RenderProcessHost* render_process_host = |
bbudge
2013/10/22 17:25:37
Maybe change variable name to 'host' as in PepperF
teravest
2013/10/23 16:54:27
Done.
|
+ RenderProcessHost::FromID(render_process_id); |
+ if (!render_process_host) |
+ return NULL; |
+ StoragePartition* storage_partition = |
+ render_process_host->GetStoragePartition(); |
+ if (!storage_partition) |
+ return NULL; |
+ return storage_partition->GetFileSystemContext(); |
+} |
+ |
+} // namespace |
+ |
+PepperFileIOHost::PepperFileIOHost(BrowserPpapiHostImpl* host, |
+ PP_Instance instance, |
+ PP_Resource resource) |
+ : ResourceHost(host->GetPpapiHost(), instance, resource), |
+ browser_ppapi_host_(host), |
+ render_process_host_(NULL), |
+ file_(base::kInvalidPlatformFileValue), |
+ file_system_type_(PP_FILESYSTEMTYPE_INVALID), |
+ quota_policy_(quota::kQuotaLimitTypeUnknown), |
+ open_flags_(0), |
+ weak_factory_(this) { |
+ int unused; |
+ if (!host->GetRenderViewIDsForInstance(instance, |
+ &render_process_id_, |
+ &unused)) { |
+ render_process_id_ = -1; |
+ } |
+ file_message_loop_ = BrowserThread::GetMessageLoopProxyForThread( |
+ BrowserThread::FILE); |
+} |
+ |
+PepperFileIOHost::~PepperFileIOHost() { |
+ OnHostMsgClose(NULL); |
bbudge
2013/10/22 17:25:37
It might be cleaner to define a Close() method to
teravest
2013/10/23 16:54:27
I'll change this if you feel strongly, but I don't
bbudge
2013/10/23 17:04:52
OK
|
+} |
+ |
+int32_t PepperFileIOHost::OnResourceMessageReceived( |
+ const IPC::Message& msg, |
+ ppapi::host::HostMessageContext* context) { |
+ IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg) |
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open, |
+ OnHostMsgOpen) |
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch, |
+ OnHostMsgTouch) |
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write, |
+ OnHostMsgWrite) |
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength, |
+ OnHostMsgSetLength) |
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush, |
+ OnHostMsgFlush) |
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close, |
+ OnHostMsgClose) |
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle, |
+ OnHostMsgRequestOSFileHandle) |
+ IPC_END_MESSAGE_MAP() |
+ return PP_ERROR_FAILED; |
+} |
+ |
+int32_t PepperFileIOHost::OnHostMsgOpen( |
+ ppapi::host::HostMessageContext* context, |
+ PP_Resource file_ref_resource, |
+ int32_t open_flags) { |
+ int32_t rv = state_manager_.CheckOperationState( |
+ FileIOStateManager::OPERATION_EXCLUSIVE, false); |
+ if (rv != PP_OK) |
+ return rv; |
+ |
+ int platform_file_flags = 0; |
+ if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags, |
+ &platform_file_flags)) |
+ return PP_ERROR_BADARGUMENT; |
+ |
+ ppapi::host::ResourceHost* resource_host = |
+ host()->GetResourceHost(file_ref_resource); |
+ if (!resource_host || !resource_host->IsFileRefHost()) |
+ return PP_ERROR_BADRESOURCE; |
+ PepperFileRefHost* file_ref_host = |
+ static_cast<PepperFileRefHost*>(resource_host); |
+ if (file_ref_host->GetFileSystemType() == PP_FILESYSTEMTYPE_INVALID) |
+ return PP_ERROR_FAILED; |
+ |
+ open_flags_ = open_flags; |
+ file_system_type_ = file_ref_host->GetFileSystemType(); |
+ file_system_url_ = file_ref_host->GetFileSystemURL(); |
+ |
+ if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ fileapi::FileSystemURL url(file_ref_host->GetFileSystemURL()); |
+ if (!url.is_valid()) |
+ return PP_ERROR_BADARGUMENT; |
+ if (!CanOpenFileSystemURLWithPepperFlags(open_flags, |
+ render_process_id_, |
+ url)) |
+ return PP_ERROR_NOACCESS; |
+ |
+ BrowserThread::PostTaskAndReplyWithResult( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&GetFileSystemContextFromRenderId, render_process_id_), |
+ base::Bind(&PepperFileIOHost::GotFileSystemContext, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext(), |
+ platform_file_flags)); |
+ } else { |
+ base::FilePath path = file_ref_host->GetExternalFilePath(); |
+ if (!CanOpenWithPepperFlags(open_flags, render_process_id_, path)) |
+ return PP_ERROR_NOACCESS; |
+ base::FileUtilProxy::CreateOrOpen( |
+ file_message_loop_, |
+ path, |
+ platform_file_flags, |
+ base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext())); |
+ } |
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); |
+ return PP_OK_COMPLETIONPENDING; |
+} |
+ |
+void PepperFileIOHost::GotFileSystemContext( |
+ ppapi::host::ReplyMessageContext reply_context, |
+ int platform_file_flags, |
+ scoped_refptr<fileapi::FileSystemContext> file_system_context) { |
+ if (!file_system_context.get()) { |
+ reply_context.params.set_result(PP_ERROR_FAILED); |
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply()); |
+ return; |
+ } |
+ file_system_context_ = file_system_context; |
+ |
+ if (!file_system_context_->GetFileSystemBackend(file_system_url_.type())) { |
+ reply_context.params.set_result(PP_ERROR_FAILED); |
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply()); |
+ return; |
+ } |
+ quota_policy_ = quota::kQuotaLimitTypeUnknown; |
+ quota::QuotaManagerProxy* quota_manager_proxy = |
+ file_system_context_->quota_manager_proxy(); |
+ CHECK(quota_manager_proxy); |
+ CHECK(quota_manager_proxy->quota_manager()); |
+ if (quota_manager_proxy->quota_manager()->IsStorageUnlimited( |
+ file_system_url_.origin(), |
+ fileapi::FileSystemTypeToQuotaStorageType(file_system_url_.type()))) |
+ quota_policy_ = quota::kQuotaLimitTypeUnlimited; |
+ else |
+ quota_policy_ = quota::kQuotaLimitTypeLimited; |
+ file_system_operation_runner_ = |
+ file_system_context_->CreateFileSystemOperationRunner(); |
+ file_system_operation_runner_->OpenFile( |
+ file_system_url_, |
+ platform_file_flags, |
+ base::Bind(&PepperFileIOHost::DidOpenFile, |
+ weak_factory_.GetWeakPtr(), |
+ reply_context)); |
+} |
+ |
+void PepperFileIOHost::DidOpenFile( |
+ ppapi::host::ReplyMessageContext reply_context, |
+ base::PlatformFileError result, |
+ base::PlatformFile file, |
+ const base::Closure& on_close_callback) { |
+ if (result == base::PLATFORM_FILE_OK) |
+ on_close_callback_ = on_close_callback; |
bbudge
2013/10/22 17:25:37
on_close_callback_ doesn't seem to be used anywher
teravest
2013/10/23 16:54:27
Fixed.
|
+ ExecutePlatformOpenFileCallback( |
+ reply_context, result, base::PassPlatformFile(&file), true); |
+} |
+ |
+int32_t PepperFileIOHost::OnHostMsgTouch( |
+ ppapi::host::HostMessageContext* context, |
+ PP_Time last_access_time, |
+ PP_Time last_modified_time) { |
+ int32_t rv = state_manager_.CheckOperationState( |
+ FileIOStateManager::OPERATION_EXCLUSIVE, true); |
+ if (rv != PP_OK) |
+ return rv; |
+ |
+ if (!base::FileUtilProxy::Touch( |
+ file_message_loop_, |
+ file_, |
+ PPTimeToTime(last_access_time), |
+ PPTimeToTime(last_modified_time), |
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext()))) |
+ return PP_ERROR_FAILED; |
+ |
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); |
+ return PP_OK_COMPLETIONPENDING; |
+} |
+ |
+int32_t PepperFileIOHost::OnHostMsgWrite( |
+ ppapi::host::HostMessageContext* context, |
+ int64_t offset, |
+ const std::string& buffer) { |
+ int32_t rv = state_manager_.CheckOperationState( |
+ FileIOStateManager::OPERATION_WRITE, true); |
+ if (rv != PP_OK) |
+ return rv; |
+ |
+ if (quota_file_io_) { |
+ if (!quota_file_io_->Write( |
+ offset, buffer.c_str(), buffer.size(), |
+ base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext()))) |
+ return PP_ERROR_FAILED; |
+ } else { |
+ if (!base::FileUtilProxy::Write( |
+ file_message_loop_, |
+ file_, |
+ offset, |
+ buffer.c_str(), |
+ buffer.size(), |
+ base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext()))) |
+ return PP_ERROR_FAILED; |
+ } |
+ |
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE); |
+ return PP_OK_COMPLETIONPENDING; |
+} |
+ |
+int32_t PepperFileIOHost::OnHostMsgSetLength( |
+ ppapi::host::HostMessageContext* context, |
+ int64_t length) { |
+ int32_t rv = state_manager_.CheckOperationState( |
+ FileIOStateManager::OPERATION_EXCLUSIVE, true); |
+ if (rv != PP_OK) |
+ return rv; |
+ |
+ QuotaFileIO::StatusCallback cb = |
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext()); |
bbudge
2013/10/22 17:25:37
Could you factor out creating the callback in OnHo
teravest
2013/10/23 16:54:27
Done.
|
+ if (quota_file_io_) { |
+ if (!quota_file_io_->SetLength(length, cb)) |
+ return PP_ERROR_FAILED; |
+ } else { |
+ if (!base::FileUtilProxy::Truncate(file_message_loop_, file_, length, cb)) |
+ return PP_ERROR_FAILED; |
+ } |
+ |
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); |
+ return PP_OK_COMPLETIONPENDING; |
+} |
+ |
+int32_t PepperFileIOHost::OnHostMsgFlush( |
+ ppapi::host::HostMessageContext* context) { |
+ int32_t rv = state_manager_.CheckOperationState( |
+ FileIOStateManager::OPERATION_EXCLUSIVE, true); |
+ if (rv != PP_OK) |
+ return rv; |
+ |
+ if (!base::FileUtilProxy::Flush( |
+ file_message_loop_, |
+ file_, |
+ base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext()))) |
+ return PP_ERROR_FAILED; |
+ |
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); |
+ return PP_OK_COMPLETIONPENDING; |
+} |
+ |
+int32_t PepperFileIOHost::OnHostMsgClose( |
+ ppapi::host::HostMessageContext* context) { |
+ if (file_ != base::kInvalidPlatformFileValue) { |
+ base::FileUtilProxy::Close( |
+ file_message_loop_, |
+ file_, |
+ base::ResetAndReturn(¬ify_close_file_callback_)); |
kinuko
2013/10/23 07:16:04
No one sets this callback any more?
teravest
2013/10/23 16:54:27
Fixed.
|
+ file_ = base::kInvalidPlatformFileValue; |
+ quota_file_io_.reset(); |
+ } |
kinuko
2013/10/23 07:16:04
Please call on_close_callback_ here if it's non-nu
teravest
2013/10/23 16:54:27
Done. Thanks for catching this. I changed this sli
|
+ return PP_OK; |
+} |
+ |
+int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle( |
+ ppapi::host::HostMessageContext* context) { |
+ if (open_flags_ != PP_FILEOPENFLAG_READ && |
+ quota_policy_ != quota::kQuotaLimitTypeUnlimited) |
+ return PP_ERROR_FAILED; |
+ GetRenderProcessHost( |
+ base::Bind(&PepperFileIOHost::FinishRequestOSFileHandle, |
+ weak_factory_.GetWeakPtr(), |
+ context->MakeReplyMessageContext())); |
+ return PP_OK_COMPLETIONPENDING; |
+} |
+ |
+void PepperFileIOHost::FinishRequestOSFileHandle( |
+ ppapi::host::ReplyMessageContext reply_context, |
+ RenderProcessHost* render_process_host) { |
+ // Whitelist to make it privately accessible. |
+ if (!browser_ppapi_host_->external_plugin() || |
+ host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE) || |
+ GetContentClient()->browser()->IsPluginAllowedToCallRequestOSFileHandle( |
+ render_process_host->GetBrowserContext(), |
+ browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()))) { |
kinuko
2013/10/23 07:16:04
Instead of returning raw render_process_host ptr f
teravest
2013/10/23 16:54:27
The problem is that BrowserPpapiHost lives entirel
kinuko
2013/10/24 02:31:01
I see. Could we do this then: call BrowserPpapiHos
|
+ if (!AddFileToReplyContext(open_flags_, &reply_context)) |
+ reply_context.params.set_result(PP_ERROR_FAILED); |
+ } else { |
+ reply_context.params.set_result(PP_ERROR_NOACCESS); |
+ } |
+ host()->SendReply(reply_context, |
+ PpapiPluginMsg_FileIO_RequestOSFileHandleReply()); |
+} |
+ |
+void PepperFileIOHost::ExecutePlatformGeneralCallback( |
+ ppapi::host::ReplyMessageContext reply_context, |
+ base::PlatformFileError error_code) { |
+ reply_context.params.set_result( |
+ ppapi::PlatformFileErrorToPepperError(error_code)); |
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply()); |
+ state_manager_.SetOperationFinished(); |
+} |
+ |
+void PepperFileIOHost::ExecutePlatformOpenFileCallback( |
+ ppapi::host::ReplyMessageContext reply_context, |
+ base::PlatformFileError error_code, |
+ base::PassPlatformFile file, |
+ bool unused_created) { |
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code); |
+ if (pp_error == PP_OK) |
+ state_manager_.SetOpenSucceed(); |
+ |
+ DCHECK(file_ == base::kInvalidPlatformFileValue); |
+ file_ = file.ReleaseValue(); |
+ |
+ DCHECK(!quota_file_io_.get()); |
+ if (file_ != base::kInvalidPlatformFileValue) { |
+ if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY || |
+ file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) { |
+ quota_file_io_.reset(new QuotaFileIO( |
+ new QuotaFileIODelegate(file_system_context_, render_process_id_), |
+ file_, file_system_url_.ToGURL(), file_system_type_)); |
+ } |
+ int32_t flags_to_send = open_flags_; |
+ if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV)) { |
+ // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so |
+ // the plugin can't write and so bypass our quota checks. |
+ flags_to_send = |
+ open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND); |
+ } |
+ if (!AddFileToReplyContext(flags_to_send, &reply_context)) |
+ pp_error = PP_ERROR_FAILED; |
+ } |
+ reply_context.params.set_result(pp_error); |
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply()); |
+ state_manager_.SetOperationFinished(); |
+} |
+ |
+void PepperFileIOHost::ExecutePlatformWriteCallback( |
+ ppapi::host::ReplyMessageContext reply_context, |
+ base::PlatformFileError error_code, |
+ int bytes_written) { |
+ // On the plugin side, the callback expects a parameter with different meaning |
+ // depends on whether is negative or not. It is the result here. We translate |
+ // for the callback. |
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code); |
+ reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written)); |
+ host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply()); |
+ state_manager_.SetOperationFinished(); |
+} |
+ |
+void PepperFileIOHost::GetRenderProcessHost( |
+ base::Callback<void(RenderProcessHost*)> callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ if (render_process_host_) { |
kinuko
2013/10/23 07:16:04
We're caching this raw ptr on IO thread while it's
teravest
2013/10/23 16:54:27
I was thinking that RenderProcessHost::FromID was
|
+ callback.Run(render_process_host_); |
+ } else { |
+ BrowserThread::PostTaskAndReplyWithResult( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&RenderProcessHost::FromID, render_process_id_), |
+ base::Bind(&PepperFileIOHost::GotRenderProcessHost, |
+ weak_factory_.GetWeakPtr(), |
+ callback)); |
+ } |
+} |
+ |
+void PepperFileIOHost::GotRenderProcessHost( |
+ base::Callback<void(RenderProcessHost*)> callback, |
+ RenderProcessHost* host) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ render_process_host_ = host; |
+ callback.Run(render_process_host_); |
+} |
+ |
+bool PepperFileIOHost::AddFileToReplyContext( |
+ int32_t open_flags, |
+ ppapi::host::ReplyMessageContext* reply_context) const { |
+ base::ProcessId plugin_process_id; |
+ if (browser_ppapi_host_->external_plugin()) { |
+ plugin_process_id = |
+ base::GetProcId(browser_ppapi_host_->GetPluginProcessHandle()); |
+ } else { |
+ plugin_process_id = render_process_id_; |
+ } |
+ IPC::PlatformFileForTransit transit_file = BrokerGetFileHandleForProcess( |
+ file_, plugin_process_id, false); |
+ if (transit_file == IPC::InvalidPlatformFileForTransit()) |
+ return false; |
+ ppapi::proxy::SerializedHandle file_handle; |
+ file_handle.set_file_handle(transit_file, open_flags); |
+ reply_context->params.AppendHandle(file_handle); |
+ return true; |
+} |
+ |
+} // namespace content |