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

Unified Diff: content/browser/renderer_host/pepper/pepper_filesystem_provider_backend_chromeos.cc

Issue 1093383002: [WIP] Provided file system from NACL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Various cleanups Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/pepper/pepper_filesystem_provider_backend_chromeos.cc
diff --git a/content/browser/renderer_host/pepper/pepper_filesystem_provider_backend_chromeos.cc b/content/browser/renderer_host/pepper/pepper_filesystem_provider_backend_chromeos.cc
new file mode 100644
index 0000000000000000000000000000000000000000..28a5f7e9ef43537c4effe3f864ab06350fdc09a7
--- /dev/null
+++ b/content/browser/renderer_host/pepper/pepper_filesystem_provider_backend_chromeos.cc
@@ -0,0 +1,858 @@
+// Copyright 2015 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_filesystem_provider_backend_chromeos.h"
+
+#include <chrono>
+
+#include "base/memory/shared_memory.h"
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
+#include "chrome/browser/chromeos/file_system_provider/request_manager.h"
+#include "chrome/browser/chromeos/file_system_provider/service.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+using extensions::api::file_system_provider::ProviderError;
+using chromeos::file_system_provider::ProvidedFileSystemInterface;
+using chromeos::file_system_provider::Service;
+using chromeos::file_system_provider::Source_Type;
+using chromeos::PluginEventRouter;
+using content::BrowserThread;
+using ppapi::host::HostMessageContext;
+
+#define MAKE_EVENT_ENTRY(x,handler,operation)\
+ std::pair<std::string,\
+ std::pair<DispatchEventImplCallback,PP_OperationType_Dev>>(\
+ extensions::api::file_system_provider::x::kEventName,\
+ std::pair<DispatchEventImplCallback,PP_OperationType_Dev>(\
+ base::Bind( &PepperFilesystemProviderBackendChromeOS::handler,\
+ weak_factory_.GetWeakPtr() ), operation ) )
+
+namespace content {
+
+namespace {
+
+// TODO(sabin): find a way to get the size of the stream reader internal
+// buffer from the backend
+// Size of the stream reader internal buffer. At most this number of bytes will
+// be read ahead of the requested data.
+const uint32_t kReaderBufferSize = 512 * 1024; // 512KB.
+
+// Size of the stream writer internal buffer. At most this number of bytes will
+// be postponed for writing.
+const uint32_t kWriterBufferSize = 512 * 1024; // 512KB.
+
+// The number of requests that can be buffered
+const uint32_t kMaximumCachedReplies = 10;
+
+base::File::Error PP_ProviderErrorToFileError(
+ ProviderError error) {
+ switch (error) {
+ case ProviderError::PROVIDER_ERROR_OK:
+ return base::File::FILE_OK;
+ case ProviderError::PROVIDER_ERROR_FAILED:
+ return base::File::FILE_ERROR_FAILED;
+ case ProviderError::PROVIDER_ERROR_IN_USE:
+ return base::File::FILE_ERROR_IN_USE;
+ case ProviderError::PROVIDER_ERROR_EXISTS:
+ return base::File::FILE_ERROR_EXISTS;
+ case ProviderError::PROVIDER_ERROR_NOT_FOUND:
+ return base::File::FILE_ERROR_NOT_FOUND;
+ case ProviderError::PROVIDER_ERROR_ACCESS_DENIED:
+ return base::File::FILE_ERROR_ACCESS_DENIED;
+ case ProviderError::PROVIDER_ERROR_TOO_MANY_OPENED:
+ return base::File::FILE_ERROR_TOO_MANY_OPENED;
+ case ProviderError::PROVIDER_ERROR_NO_MEMORY:
+ return base::File::FILE_ERROR_NO_MEMORY;
+ case ProviderError::PROVIDER_ERROR_NO_SPACE:
+ return base::File::FILE_ERROR_NO_SPACE;
+ case ProviderError::PROVIDER_ERROR_NOT_A_DIRECTORY:
+ return base::File::FILE_ERROR_NOT_A_DIRECTORY;
+ case ProviderError::PROVIDER_ERROR_INVALID_OPERATION:
+ return base::File::FILE_ERROR_INVALID_OPERATION;
+ case ProviderError::PROVIDER_ERROR_SECURITY:
+ return base::File::FILE_ERROR_SECURITY;
+ case ProviderError::PROVIDER_ERROR_ABORT:
+ return base::File::FILE_ERROR_ABORT;
+ case ProviderError::PROVIDER_ERROR_NOT_A_FILE:
+ return base::File::FILE_ERROR_NOT_A_FILE;
+ case ProviderError::PROVIDER_ERROR_NOT_EMPTY:
+ return base::File::FILE_ERROR_NOT_EMPTY;
+ case ProviderError::PROVIDER_ERROR_INVALID_URL:
+ return base::File::FILE_ERROR_INVALID_URL;
+ case ProviderError::PROVIDER_ERROR_IO:
+ return base::File::FILE_ERROR_IO;
+ case ProviderError::PROVIDER_ERROR_NONE:
+ NOTREACHED();
+ }
+
+ return base::File::FILE_ERROR_FAILED;
+}
+
+} // namespace
+
+PepperFilesystemProviderBackendChromeOS::
+ ProvidedFilesystemInfo::ProvidedFilesystemInfo()
+ :filesystem_id("none"),
+ display_name("none"),
+ plugin_name("none"),
+ writable(false),
+ opened_files_limit(0) {
+}
+PepperFilesystemProviderBackendChromeOS::ShmBuffer::ShmBuffer(
+ uint32_t size, scoped_ptr<base::SharedMemory> shm)
+ : size(size),shm(shm.Pass()) {
+ DCHECK(this->shm);
+}
+
+PepperFilesystemProviderBackendChromeOS::ShmBuffer::~ShmBuffer() {
+
+}
+
+PepperFilesystemProviderBackendChromeOS::
+ ShmChannelSynchronizer::ShmChannelSynchronizer(
+ uint32_t size, FlushRequestCallback callback)
+ : max_size(size),
+ ready(true),
+ callback(callback){
+}
+PepperFilesystemProviderBackendChromeOS::
+ ShmChannelSynchronizer::~ShmChannelSynchronizer() {
+}
+
+bool PepperFilesystemProviderBackendChromeOS::
+ ShmChannelSynchronizer::EnqueueRequest(
+ scoped_ptr<base::ListValue> response) {
+ // If channel ready send it straight away
+ if(ready) {
+ ready = !callback.Run(response.Pass());
+ if(!ready)
+ return true;
+ }
+ // If channel is not ready or failed to send
+ // cache the request
+ if(size() + 1 > max_size)
+ return false;
+ replies.push_back( response.Pass() );
+ return true;
+}
+
+bool PepperFilesystemProviderBackendChromeOS::
+ ShmChannelSynchronizer::PushNextRequest() {
+ // Try and send the request
+ scoped_ptr<base::ListValue> response;
+ while (size()>0 && ready ) {
+ response.reset(replies.front());
+ replies.weak_erase(replies.begin());
+ ready = !callback.Run(response.Pass());
+ }
+ return !ready;
+}
+
+bool
+PepperFilesystemProviderBackendChromeOS::
+ ShmChannelSynchronizer::AckLastPushedRequest() {
+ return ready = true;
+}
+
+uint32_t PepperFilesystemProviderBackendChromeOS::
+ ShmChannelSynchronizer::size() {
+ return replies.size();
+}
+
+
+
+PepperFilesystemProviderBackendChromeOS::
+PepperFilesystemProviderBackendChromeOS(
+ content::BrowserPpapiHost *host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : mounted_(false),
+ host_(host ? host->GetPpapiHost() : nullptr),
+ resource_(resource),
+ write_channel_controller_(new ShmChannelSynchronizer(
+ kMaximumCachedReplies,
+ base::Bind(
+ &PepperFilesystemProviderBackendChromeOS::
+ FlushRequest,
+ base::Unretained(this)))),
+ weak_factory_(this) {
+
+ filesystem_info_.plugin_name = std::string("Plugin_") +
+ std::to_string(instance);
+
+ std::pair<
+ std::string, std::pair<DispatchEventImplCallback,PP_OperationType_Dev> >
+ ev[] ={
+ MAKE_EVENT_ENTRY(
+ OnAbortRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_ABORT),
+ MAKE_EVENT_ENTRY(
+ OnCloseFileRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_CLOSEFILE),
+ MAKE_EVENT_ENTRY(
+ OnCopyEntryRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_COPYENTRY),
+ MAKE_EVENT_ENTRY(
+ OnCreateDirectoryRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_CREATEDIRECTORY),
+ MAKE_EVENT_ENTRY(
+ OnCreateFileRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_CREATEFILE),
+ MAKE_EVENT_ENTRY(
+ OnDeleteEntryRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_DELETEENTRY),
+ MAKE_EVENT_ENTRY(
+ OnGetMetadataRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_GETMETADATA),
+ MAKE_EVENT_ENTRY(
+ OnMoveEntryRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_MOVEENTRY),
+ MAKE_EVENT_ENTRY(
+ OnOpenFileRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_OPENFILE),
+ MAKE_EVENT_ENTRY(
+ OnReadDirectoryRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_READDIRECTORY),
+ MAKE_EVENT_ENTRY(
+ OnReadFileRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_READFILE),
+ MAKE_EVENT_ENTRY(
+ OnTruncateRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_TRUNCATEENTRY),
+ MAKE_EVENT_ENTRY(
+ OnUnmountRequested,
+ SendOperationRequestToPlugin,
+ PP_OperationType_UNMOUNT),
+ MAKE_EVENT_ENTRY(
+ OnWriteFileRequested,
+ SendWriteRequestToPlugin,
+ PP_OperationType_WRITEFILE)
+ };
+
+ for ( size_t i = 0; i < sizeof( ev ) / sizeof( ev[0] ); ++i ) {
+ handlers_list_.insert( ev[i] );
+ events_.push_back( ev[i].first );
+ }
+}
+
+PepperFilesystemProviderBackendChromeOS::
+~PepperFilesystemProviderBackendChromeOS() {
+ // Unregister the filesystem if state indicates
+ // that we have a mounted filesystem
+ if (mounted_) {
+ // Unregister any registered event from the PluginEventRouter
+ UnregisterFilesystemEventListeners();
+ // Unregister the filesystem backend on the
+ // proper thread from Service
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(
+ &PepperFilesystemProviderBackendChromeOS::
+ UnregisterFilesystemOnUI),
+ filesystem_info_
+ )
+ );
+ }
+}
+
+// Called when PpapiHostMsg_FilesystemProvider_Mount is received
+// Forwards request to RegisterFilesystemOnUI
+// Response is sent from MountReplyOnIO
+int32_t PepperFilesystemProviderBackendChromeOS::SendMountRequest(
+ ppapi::host::HostMessageContext *context,
+ const base::ListValue& request) {
+
+ base::File::Error status = base::File::FILE_OK;
+ if (mounted_)
+ status = base::File::FILE_ERROR_EXISTS;
+
+ scoped_ptr<MountOperationTranslator> mount_info =
+ MountOperationTranslator::PopulateFromResponse(request);
+ if ( !mount_info.get() )
+ status = base::File::FILE_ERROR_FAILED;
+
+ // Stop and send failure back to the plugin
+ if (status!=base::File::FILE_OK) {
+ MountReplyOnIO(
+ context->MakeReplyMessageContext(),
+ filesystem_info_, base::File::FILE_ERROR_EXISTS);
+ return PP_OK_COMPLETIONPENDING;
+ }
+ // Populate the wanted filesystem configuration
+ ProvidedFilesystemInfo filesystem_info;
+ filesystem_info.plugin_name = filesystem_info_.plugin_name;
+ filesystem_info.filesystem_id = mount_info->file_system_id;
+ filesystem_info.display_name = mount_info->display_name;
+ filesystem_info.writable = mount_info->writable;
+ filesystem_info.opened_files_limit = mount_info->opened_files_limit;
+ // Change thread to create the filesystem backend on the
+ // UI thread. The result of this action is to be interpreted
+ // on the IO thread.
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ // This creates a filesystem backend owned by the Service
+ // entity
+ &PepperFilesystemProviderBackendChromeOS::RegisterFilesystemOnUI,
+ filesystem_info),
+ // This is called after the above returns to interpret result
+ base::Bind(
+ &PepperFilesystemProviderBackendChromeOS::MountReplyOnIO,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(),
+ filesystem_info
+ )
+ );
+ return PP_OK_COMPLETIONPENDING;
+}
+
+// Called when PpapiHostMsg_FilesystemProvider_Unmount is received
+// Forwards request to UnregisterFilesystemOnUI
+// Response is sent from MountReplyOnIO
+int32_t PepperFilesystemProviderBackendChromeOS::SendUnmountRequest(
+ ppapi::host::HostMessageContext *context, std::string fsid) {
+
+ if(!mounted_) {
+ UnmountReplyOnIO(
+ context->MakeReplyMessageContext(),
+ base::File::FILE_ERROR_NOT_FOUND);
+ }
+
+ // Remove registered events from PluginEventRouter
+ UnregisterFilesystemEventListeners();
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &PepperFilesystemProviderBackendChromeOS::UnregisterFilesystemOnUI,
+ filesystem_info_),
+ base::Bind( &PepperFilesystemProviderBackendChromeOS::UnmountReplyOnIO,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext())
+ );
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperFilesystemProviderBackendChromeOS::OnPluginResponse(
+ ppapi::host::HostMessageContext* context,
+ const base::ListValue& plugin_response) {
+ scoped_ptr<base::ListValue> response( plugin_response.DeepCopy() );
+ if (!response.get())
+ return PP_ERROR_FAILED;
+ // Remove the custom "header" from the response
+ scoped_ptr<base::Value> operation_value = nullptr;
+ int operation_type = PP_OperationType_NONE;
+ if (!response->Remove(0,&operation_value))
+ return PP_ERROR_FAILED;
+ if (!operation_value->GetAsInteger(&operation_type))
+ return PP_ERROR_FAILED;
+ // Get the status of the operation
+ scoped_ptr<base::Value> status_value=nullptr;
+ bool status = false;
+ if (!response->Remove(0,&status_value))
+ return PP_ERROR_FAILED;
+ if (!status_value->GetAsBoolean(&status))
+ return PP_ERROR_FAILED;
+
+ if ( status ) {// success
+
+ if (operation_type==PP_OperationType_READFILE) { // a preprocess stage
+ AddFromSharedMemoryToMessage(*response);
+ // ACK the receipt and let the plugin know that if it has more
+ // requests it can send them
+ host_->SendUnsolicitedReply(
+ resource_,
+ PpapiPluginMsg_FilesystemProvider_ReadAck()
+ );
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(
+ &PepperFilesystemProviderBackendChromeOS::
+ OnGeneralSuccessResponse),
+ operation_type,
+ filesystem_info_,
+ base::Passed(response.Pass()))
+ );
+ } else { // failure
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(
+ &PepperFilesystemProviderBackendChromeOS::
+ OnGeneralErrorResponse),
+ filesystem_info_,
+ base::Passed(response.Pass()))
+ );
+ }
+
+ return PP_OK;
+}
+
+// Sends next cached request if there is any pending
+int32_t PepperFilesystemProviderBackendChromeOS::OnPluginWriteAck(
+ ppapi::host::HostMessageContext* ) {
+ write_channel_controller_->AckLastPushedRequest();
+ write_channel_controller_->PushNextRequest();
+ return PP_OK;
+}
+
+// Add all events to the PluginEventRouter list of dispatchable events
+void PepperFilesystemProviderBackendChromeOS::
+RegisterFilesystemEventListeners() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ PluginEventRouter *router = PluginEventRouter::GetInstance();
+ if (router!=nullptr)
+ router->AddEventsListener( events_, this, filesystem_info_.plugin_name );
+}
+// Remove all events from the PluginEventRouter list of dispatchable events
+void PepperFilesystemProviderBackendChromeOS::
+UnregisterFilesystemEventListeners() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ PluginEventRouter *router = PluginEventRouter::GetInstance();
+ if (router!=nullptr)
+ router->RemoveEventsListeners( events_, this, filesystem_info_.plugin_name);
+}
+
+// Static
+// Responsible with the creations and registration of a new provided filesystem
+base::File::Error PepperFilesystemProviderBackendChromeOS::
+RegisterFilesystemOnUI(
+ ProvidedFilesystemInfo filesystem_info)
+{
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ chromeos::file_system_provider::MountOptions options(
+ filesystem_info.filesystem_id, filesystem_info.display_name);
+
+ options.writable = filesystem_info.writable;
+ options.opened_files_limit = filesystem_info.opened_files_limit;
+ options.supports_notify_tag = false; // Check this
+
+ base::File::Error error = fs_service->MountFileSystem(
+ filesystem_info.plugin_name,
+ options,
+ Source_Type::plugin );
+
+ return error; // This will be interpreted by MountReplyOnIO
+}
+
+// Sends feedback to the plugin
+// and sets state
+void PepperFilesystemProviderBackendChromeOS::MountReplyOnIO(
+ ppapi::host::ReplyMessageContext reply_msg,
+ ProvidedFilesystemInfo filesystem_info,
+ base::File::Error err) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Do not register and send error back
+ if ( err != base::File::FILE_OK ) {
+ reply_msg.params.set_result(PP_OK);
+ host_->SendReply(
+ reply_msg,
+ PpapiPluginMsg_FilesystemProvider_MountReply( PP_ProviderError_FAILED )
+ );
+ return;
+ }
+
+ filesystem_info_.writable = filesystem_info.writable;
+ filesystem_info_.opened_files_limit = filesystem_info.opened_files_limit;
+ filesystem_info_.filesystem_id = filesystem_info.filesystem_id;
+ filesystem_info_.display_name = filesystem_info.display_name;
+ mounted_ = true;
+
+ // Initialize the shared memory buffers if needed
+ if (!read_write_buffer_.get())
+ InitializeMemoryBuffer();
+ RegisterFilesystemEventListeners();
+
+ reply_msg.params.set_result(PP_OK);
+ host_->SendReply(
+ reply_msg,
+ PpapiPluginMsg_FilesystemProvider_MountReply( PP_ProviderError_OK )
+ );
+}
+
+//static
+// Responsible with removal of the filesystem backend
+base::File::Error PepperFilesystemProviderBackendChromeOS::
+UnregisterFilesystemOnUI(
+ ProvidedFilesystemInfo filesystem_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ base::File::Error err = fs_service->UnmountFileSystem(
+ filesystem_info.plugin_name,
+ filesystem_info.filesystem_id,
+ chromeos::file_system_provider::Service::UNMOUNT_REASON_USER );
+
+ return err;
+}
+
+// Sends feedback to the plugin
+// and resets state
+void PepperFilesystemProviderBackendChromeOS::UnmountReplyOnIO(
+ ppapi::host::ReplyMessageContext reply_msg, base::File::Error err) {
+
+ reply_msg.params.set_result(PP_OK);
+ // Unregister all events
+ UnregisterFilesystemEventListeners();
+
+ mounted_ = false;
+ filesystem_info_.writable = false;
+ filesystem_info_.opened_files_limit = 0;
+ filesystem_info_.filesystem_id = "";
+ filesystem_info_.display_name = "";
+
+ // Send result to the plugin
+ host_->SendReply(
+ reply_msg,
+ PpapiPluginMsg_FilesystemProvider_MountReply( PP_ProviderError_OK )
+ );
+}
+
+// Handle events that are dispatched by the PluginEventRouter
+void PepperFilesystemProviderBackendChromeOS::OnDispatchEvent(
+ std::string event_name, scoped_ptr<base::ListValue> event_args) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ ListOfHandlersIterator it = handlers_list_.find( event_name );
+ if ( it != handlers_list_.end() )
+ it->second.first.Run( it->second.second, event_args.Pass() );
+}
+
+// Sends requests to plugin
+void PepperFilesystemProviderBackendChromeOS::SendOperationRequestToPlugin(
+ PP_OperationType_Dev operation_type,
+ scoped_ptr<base::ListValue> event_args) {
+
+ //TODO(sabin): Remove this when done testing
+ if(operation_type==PP_OperationType_OPENFILE)
+ time_stamp_=std::chrono::system_clock::now();
+ else if(operation_type==PP_OperationType_CLOSEFILE) {
+ std::chrono::duration<double> elapsed_seconds =
+ std::chrono::system_clock::now()-time_stamp_;
+ LOG(ERROR) <<"Read/Write operation time: "<< elapsed_seconds.count()<<
+ " seconds";
+ }
+
+ host_->SendUnsolicitedReply(
+ resource_,
+ PpapiPluginMsg_FilesystemProvider_OperationRequest(
+ operation_type,
+ *event_args)
+ );
+
+}
+
+void PepperFilesystemProviderBackendChromeOS::SendWriteRequestToPlugin(
+ PP_OperationType_Dev operation_type,
+ scoped_ptr<base::ListValue> request) {
+ // Handle write to filesystem
+ // Put the chunk into the shared memory buffer or cache it
+ // if channel is not free
+ // TODO(sabin): Send error back to backend if this fails
+ write_channel_controller_->EnqueueRequest(request.Pass());
+}
+
+// Transforms messages that are received from
+// the plugin in response of filesystem operations and sends
+// them back to the filesystem backend.
+int32_t PepperFilesystemProviderBackendChromeOS::OnGeneralSuccessResponse(
+ int operation,
+ ProvidedFilesystemInfo filesystem_info,
+ scoped_ptr<base::ListValue> args) {
+
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ ProvidedFileSystemInterface* fs_interface =
+ fs_service->GetProvidedFileSystem(
+ filesystem_info.plugin_name,
+ filesystem_info.filesystem_id);
+
+ if (fs_interface==nullptr)
+ return PP_ERROR_FAILED;
+
+ switch(operation) {
+ case PP_OperationType_READDIRECTORY: {
+ using extensions::api::
+ file_system_provider_internal::ReadDirectoryRequestedSuccess::
+ Params;
+ scoped_ptr<Params> params(Params::Create(*args));
+ if(!params.get())
+ return PP_ERROR_FAILED;
+
+ const bool has_more = params->has_more;
+ if ( base::File::FILE_OK!=
+ fs_interface->GetRequestManager()->FulfillRequest(
+ params->request_id,
+ chromeos::file_system_provider::RequestValue::
+ CreateForReadDirectorySuccess(params.Pass()),
+ has_more)
+ )
+ return PP_ERROR_FAILED;
+ }
+ break;
+ case PP_OperationType_GETMETADATA: {
+ using extensions::api::file_system_provider_internal::
+ GetMetadataRequestedSuccess::Params;
+ scoped_ptr<Params> params(Params::Create(*args));
+ if(!params.get())
+ return PP_ERROR_FAILED;
+
+ if (base::File::FILE_OK!=
+ fs_interface->GetRequestManager()->FulfillRequest(
+ params->request_id,
+ chromeos::file_system_provider::RequestValue::
+ CreateForGetMetadataSuccess(params.Pass()),
+ false)
+ )
+ return PP_ERROR_FAILED;
+ }
+ break;
+ case PP_OperationType_READFILE: {
+ using extensions::api::file_system_provider_internal::
+ ReadFileRequestedSuccess::Params;
+ scoped_ptr<Params> params(Params::Create(*args));
+ if (!params.get())
+ return PP_ERROR_FAILED;
+
+ const bool has_more = params->has_more;
+ if (base::File::FILE_OK!=
+ fs_interface->GetRequestManager()->FulfillRequest(
+ params->request_id,
+ chromeos::file_system_provider::RequestValue::
+ CreateForReadFileSuccess(params.Pass()),
+ has_more) )
+ return PP_ERROR_FAILED;
+ }
+ break;
+ case PP_OperationType_UNMOUNT: {
+ using extensions::api::file_system_provider_internal::
+ UnmountRequestedSuccess::Params;
+ scoped_ptr<Params> params(Params::Create(*args));
+ if(!params.get())
+ return PP_ERROR_FAILED;
+
+ if (base::File::FILE_OK!=
+ fs_service->UnmountFileSystem(
+ filesystem_info.plugin_name, filesystem_info.filesystem_id,
+ chromeos::file_system_provider::Service::UNMOUNT_REASON_USER)
+ )
+ return PP_ERROR_FAILED;
+ }
+ break;
+ default: {
+ using extensions::api::file_system_provider_internal::
+ OperationRequestedSuccess::Params;
+ scoped_ptr<Params> params(Params::Create(*args));
+ if(!params.get())
+ return PP_ERROR_FAILED;
+
+ if (base::File::FILE_OK!=
+ fs_interface->GetRequestManager()->FulfillRequest(
+ params->request_id,
+ chromeos::file_system_provider::RequestValue::
+ CreateForOperationSuccess(params.Pass()),
+ false)
+ )
+ return PP_ERROR_FAILED;
+ }
+ break;
+ }
+ return PP_OK;
+}
+
+int32_t PepperFilesystemProviderBackendChromeOS::OnGeneralErrorResponse(
+ ProvidedFilesystemInfo filesystem_info,
+ scoped_ptr<base::ListValue> args) {
+
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ ProvidedFileSystemInterface* fs_interface =
+ fs_service->GetProvidedFileSystem(
+ filesystem_info.plugin_name,
+ filesystem_info.filesystem_id);
+ if(fs_interface==nullptr)
+ return PP_ERROR_FAILED;
+
+ using extensions::api::file_system_provider_internal::
+ OperationRequestedError::Params;
+ scoped_ptr<Params> params(Params::Create(*args));
+ if(!params.get())
+ return PP_ERROR_FAILED;
+
+ const base::File::Error error = PP_ProviderErrorToFileError(params->error);
+
+ if( base::File::FILE_OK!=
+ fs_interface->GetRequestManager()->RejectRequest(
+ params->request_id,
+ chromeos::file_system_provider::RequestValue::
+ CreateForOperationError(params.Pass()),
+ error)
+ )
+ return PP_ERROR_FAILED;
+ return PP_OK;
+}
+
+bool PepperFilesystemProviderBackendChromeOS::FlushRequest(
+ scoped_ptr<base::ListValue> request) {
+ if(!request.get())
+ return false;
+
+ if(!AddFromMessageToSharedMemory(*request))
+ return false;
+
+ host_->SendUnsolicitedReply(
+ resource_,
+ PpapiPluginMsg_FilesystemProvider_OperationRequest(
+ PP_OperationType_WRITEFILE,
+ *request));
+ return true;
+}
+
+bool PepperFilesystemProviderBackendChromeOS::InitializeMemoryBuffer() {
+ // Already initialized
+ if(read_write_buffer_.get())
+ return false;
+ scoped_ptr<base::SharedMemory> buffer( new base::SharedMemory );
+ size_t size = kReaderBufferSize + kWriterBufferSize;
+ if (!buffer.get() ||
+ !buffer->CreateAndMapAnonymous(size))
+ return false;
+ read_write_buffer_=make_scoped_ptr(new ShmBuffer(size, buffer.Pass()));
+ if(!read_write_buffer_.get())
+ return false;
+ using ppapi::proxy::SerializedHandle;
+ std::vector<SerializedHandle> handles;
+ handles.push_back(
+ SerializedHandle(read_write_buffer_->shm->handle(), size ));
+ // Send a message to the plugin with the shared mem handle
+ host_->SendUnsolicitedReplyWithHandles(
+ resource_,
+ PpapiPluginMsg_FilesystemProvider_Buffers(
+ kReaderBufferSize,
+ kWriterBufferSize),
+ handles
+ );
+ return true;
+}
+bool PepperFilesystemProviderBackendChromeOS::AddFromSharedMemoryToMessage(
+ base::ListValue& message) {
+ DCHECK(read_write_buffer_.get());
+ double out = 0;
+ if(!message.GetDouble(2,&out))
+ return false;
+ size_t out_size = out;
+ if(out_size>kReaderBufferSize)
+ return false;
+
+ // Replace the size with the actual data
+ return message.Set(2, base::BinaryValue::CreateWithCopiedBuffer(
+ (const char*)read_write_buffer_->shm->memory(), out_size));
+}
+
+bool PepperFilesystemProviderBackendChromeOS::AddFromMessageToSharedMemory(
+ base::ListValue& message) {
+ if( !read_write_buffer_.get() )
+ return false;
+
+ base::Value *dict_value = nullptr;
+ if(!message.Get(0,&dict_value))
+ return false;
+
+ base::DictionaryValue* dict =
+ static_cast<base::DictionaryValue*>(dict_value);
+ const base::BinaryValue* binary_value = NULL;
+ if (!dict->GetBinary("data", &binary_value))
+ return false;
+ // This can be '0'
+ size_t binary_size =binary_value->GetSize();
+ // Skip the read buffer and copy to shared mem the buffer into
+ // the write portion of the buffer
+ if(binary_size>kWriterBufferSize)
+ return false;
+ memcpy( (char*)read_write_buffer_->shm->memory()+kReaderBufferSize,
+ binary_value->GetBuffer(),
+ binary_size);
+ dict->Remove( "data", nullptr );
+ dict->SetDouble( "size",binary_size);
+ return true;
+}
+
+scoped_ptr<MountOperationTranslator>
+ MountOperationTranslator::PopulateFromResponse(
+ const base::ListValue& request) {
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<MountOperationTranslator>();
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+
+ scoped_ptr< MountOperationTranslator > out(new MountOperationTranslator);
+
+ const base::Value* data_value = nullptr;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &data_value) ||
+ !data_value->IsType(base::Value::TYPE_STRING))
+ return scoped_ptr<MountOperationTranslator>();
+ if (!data_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<MountOperationTranslator>();
+ if (!dict->GetWithoutPathExpansion("displayName", &data_value) ||
+ !data_value->IsType(base::Value::TYPE_STRING))
+ return scoped_ptr<MountOperationTranslator>();
+ if (!data_value->GetAsString(&out->display_name))
+ return scoped_ptr<MountOperationTranslator>();
+ if (!dict->GetWithoutPathExpansion("writable", &data_value) ||
+ !data_value->IsType(base::Value::TYPE_BOOLEAN))
+ return scoped_ptr<MountOperationTranslator>();
+ if (!data_value->GetAsBoolean(&out->writable))
+ return scoped_ptr<MountOperationTranslator>();
+
+ if (!dict->GetWithoutPathExpansion("openedFilesLimit", &data_value) ||
+ !data_value->IsType(base::Value::TYPE_INTEGER))
+ return scoped_ptr<MountOperationTranslator>();
+ if (!data_value->GetAsInteger(&out->opened_files_limit))
+ return scoped_ptr<MountOperationTranslator>();
+
+ return out.Pass();
+}
+
+}// namespace content
+

Powered by Google App Engine
This is Rietveld 408576698