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

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: Moved several modules to chromeos folder. Created 5 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 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..42fc8eb087299c64a2251ee0ce1d210cb959cad5
--- /dev/null
+++ b/content/browser/renderer_host/pepper/pepper_filesystem_provider_backend_chromeos.cc
@@ -0,0 +1,779 @@
+// 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/file_system_plugin/plugin_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 namespace chromeos::file_system_provider;
+using content::BrowserThread;
+using ppapi::host::HostMessageContext;
+
+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;
+
+RequestType PP_OperationToRequestType(int32_t operation_type) {
+ switch (operation_type) {
+ case PP_OperationType_ABORT:
+ return ABORT;
+ case PP_OperationType_ADDWATCHER:
+ return ADD_WATCHER;
+ case PP_OperationType_CLOSEFILE:
+ return CLOSE_FILE;
+ case PP_OperationType_COPYENTRY:
+ return COPY_ENTRY;
+ case PP_OperationType_CREATEDIRECTORY:
+ return CREATE_DIRECTORY;
+ case PP_OperationType_CREATEFILE:
+ return CREATE_FILE;
+ case PP_OperationType_DELETEENTRY:
+ return DELETE_ENTRY;
+ case PP_OperationType_GETMETADATA:
+ return GET_METADATA;
+ case PP_OperationType_MOVEENTRY:
+ return MOVE_ENTRY;
+ case PP_OperationType_OPENFILE:
+ return OPEN_FILE;
+ case PP_OperationType_READDIRECTORY:
+ return READ_DIRECTORY;
+ case PP_OperationType_READFILE:
+ return READ_FILE;
+ case PP_OperationType_REMOVEWATCHER:
+ return REMOVE_WATCHER;
+ case PP_OperationType_TRUNCATEENTRY:
+ return TRUNCATE;
+ case PP_OperationType_UNMOUNT:
+ return REQUEST_UNMOUNT;
+ case PP_OperationType_WRITEFILE:
+ return WRITE_FILE;
+ case PP_OperationType_NONE:
+ default:
+ break;
+ }
+ NOTREACHED();
+ return ABORT;
+}
+
+PP_OperationType_Dev RequestTypeToOperationType(int32_t operation_type) {
+ switch (operation_type) {
+ case ABORT:
+ return PP_OperationType_ABORT;
+ case ADD_WATCHER:
+ return PP_OperationType_ADDWATCHER;
+ case CLOSE_FILE:
+ return PP_OperationType_CLOSEFILE;
+ case COPY_ENTRY:
+ return PP_OperationType_COPYENTRY;
+ case CREATE_DIRECTORY:
+ return PP_OperationType_CREATEDIRECTORY;
+ case CREATE_FILE:
+ return PP_OperationType_CREATEFILE;
+ case DELETE_ENTRY:
+ return PP_OperationType_DELETEENTRY;
+ case GET_METADATA:
+ return PP_OperationType_GETMETADATA;
+ case MOVE_ENTRY:
+ return PP_OperationType_MOVEENTRY;
+ case OPEN_FILE:
+ return PP_OperationType_OPENFILE;
+ case READ_DIRECTORY:
+ return PP_OperationType_READDIRECTORY;
+ case READ_FILE:
+ return PP_OperationType_READFILE;
+ case REMOVE_WATCHER:
+ return PP_OperationType_REMOVEWATCHER;
+ case TRUNCATE:
+ return PP_OperationType_TRUNCATEENTRY;
+ case REQUEST_UNMOUNT:
+ return PP_OperationType_UNMOUNT;
+ case WRITE_FILE:
+ return PP_OperationType_WRITEFILE;
+ default:
+ break;
+ }
+ NOTREACHED();
+ return PP_OperationType_NONE;
+}
+
+} // 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::
+ ShmChannelController::ShmChannelController(
+ uint32_t size, FlushRequestCallback callback)
+ : max_size(size),
+ ready(true),
+ callback(callback){
+}
+PepperFilesystemProviderBackendChromeOS::
+ ShmChannelController::~ShmChannelController() {
+}
+
+bool PepperFilesystemProviderBackendChromeOS::
+ ShmChannelController::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::
+ ShmChannelController::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::
+ ShmChannelController::AckLastPushedRequest() {
+ return ready = true;
+}
+
+uint32_t PepperFilesystemProviderBackendChromeOS::
+ ShmChannelController::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 ShmChannelController(
+ kMaximumCachedReplies,
+ base::Bind(
+ &PepperFilesystemProviderBackendChromeOS::
+ FlushRequest,
+ base::Unretained(this)))),
+ weak_factory_(this) {
+
+ filesystem_info_.plugin_name = std::string("Plugin_") +
+ std::to_string(static_cast<size_t>(instance));
+}
+
+PepperFilesystemProviderBackendChromeOS::
+~PepperFilesystemProviderBackendChromeOS() {
+ // Unregister the filesystem if state indicates
+ // that we have a mounted filesystem
+ if (mounted_) {
+ // Unregister any registered event from the PluginEventRouter
+ UnregisterFilesystemListenedOperations();
+ // 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) {
+ using content::filesystem_provider_internal::MountOperationTranslator;
+
+ 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 desired filesystem configuration
+ ProvidedFilesystemInfo filesystem_info;
+ filesystem_info.writable = mount_info->writable;
+ filesystem_info.display_name = mount_info->display_name;
+ filesystem_info.plugin_name = filesystem_info_.plugin_name;
+ filesystem_info.filesystem_id = mount_info->file_system_id;
+ 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, const std::string& fsid) {
+
+ if(!mounted_) {
+ return PP_ERROR_FAILED;
+ }
+
+ // Remove registered events from PluginEventRouter
+ UnregisterFilesystemListenedOperations();
+
+ 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() ||
+ !mounted_)
+ return PP_ERROR_FAILED;
+
+ bool status;
+ int operation_type = PP_OperationType_NONE;
+ if (!PreprocessMessage(*response, status, operation_type))
+ return PP_ERROR_FAILED;
+ if ( status ) {// success
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(
+ &PepperFilesystemProviderBackendChromeOS::
+ OnSuccessResponse),
+ operation_type,
+ filesystem_info_,
+ base::Passed(response.Pass()))
+ );
+ } else { // failure
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(
+ &PepperFilesystemProviderBackendChromeOS::
+ OnErrorResponse),
+ 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;
+}
+
+int32_t PepperFilesystemProviderBackendChromeOS::OnPluginNotification(
+ ppapi::host::HostMessageContext* context, const base::ListValue& args) {
+ scoped_ptr<base::ListValue> message(args.DeepCopy());
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &PepperFilesystemProviderBackendChromeOS::
+ SendNotificationOnUI,
+ filesystem_info_, base::Passed(message.Pass())
+ )
+ );
+ return PP_OK;
+}
+
+void OnNotifyCompleted(base::File::Error /*result*/) {}
+
+void PepperFilesystemProviderBackendChromeOS::SendNotificationOnUI(
+ const ProvidedFilesystemInfo& file_system_info,
+ scoped_ptr<base::ListValue> args) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ PluginService *fs_service = PluginService::Get(
+ ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ ProvidedFileSystemAdapter* fs_backend =
+ fs_service->GetProvidedFileSystemAdapter(
+ file_system_info.plugin_name,
+ file_system_info.filesystem_id);
+ if (!fs_backend)
+ return;
+ fs_backend->PushChangeNotificationResponse(args.Pass(),
+ base::Bind(OnNotifyCompleted));
+}
+
+// Add all events to the PluginEventRouter list of dispatchable events
+void PepperFilesystemProviderBackendChromeOS::
+RegisterFilesystemListenedOperations() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::vector<RequestType> operations = {
+ REQUEST_UNMOUNT, GET_METADATA, READ_DIRECTORY, OPEN_FILE, CLOSE_FILE,
+ READ_FILE, CREATE_DIRECTORY, DELETE_ENTRY, CREATE_FILE, COPY_ENTRY,
+ MOVE_ENTRY, TRUNCATE, WRITE_FILE, ABORT, ADD_WATCHER, REMOVE_WATCHER
+ };
+ PluginOperationRouter *router = PluginOperationRouter::GetInstance();
+ if (router!=nullptr)
+ router->AddOperationsForListener( operations, this,
+ filesystem_info_.plugin_name );
+}
+using chromeos::file_system_provider::READ_DIRECTORY;
+// Remove all events from the PluginEventRouter list of dispatchable events
+void PepperFilesystemProviderBackendChromeOS::
+UnregisterFilesystemListenedOperations() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::vector<RequestType> operations = {
+ REQUEST_UNMOUNT, GET_METADATA, READ_DIRECTORY, OPEN_FILE, CLOSE_FILE,
+ READ_FILE, CREATE_DIRECTORY, DELETE_ENTRY, CREATE_FILE, COPY_ENTRY,
+ MOVE_ENTRY, TRUNCATE, WRITE_FILE, ABORT, ADD_WATCHER, REMOVE_WATCHER
+ };
+ PluginOperationRouter *router = PluginOperationRouter::GetInstance();
+ if (router!=nullptr)
+ router->RemoveOperationsForListener(operations,
+ 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);
+
+ PluginService *fs_service = PluginService::Get(
+ ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ chromeos::file_system_provider::MountOptions options(
+ filesystem_info.filesystem_id, filesystem_info.display_name);
+
+ // TODO(sabin): add support for watchers
+ options.supports_notify_tag = false;
+ options.writable = filesystem_info.writable;
+ options.opened_files_limit = filesystem_info.opened_files_limit;
+
+ base::File::Error error = fs_service->MountFileSystem(
+ filesystem_info.plugin_name,
+ options);
+
+ 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);
+
+ // If an error occured or we cannot initialize the shared memory
+ if ( err != base::File::FILE_OK ||
+ !InitializeMemoryBuffer()) {
+ reply_msg.params.set_result(PP_ERROR_FAILED);
+ host_->SendReply(
+ reply_msg,
+ PpapiPluginMsg_FilesystemProvider_MountReply()
+ );
+ // Undo the registration
+ if (err==base::File::FILE_OK) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(
+ &PepperFilesystemProviderBackendChromeOS::
+ UnregisterFilesystemOnUI),
+ filesystem_info
+ )
+ );
+ }
+ return;
+ }
+
+ RegisterFilesystemListenedOperations();
+ mounted_ = true;
+ filesystem_info_.writable = filesystem_info.writable;
+ filesystem_info_.display_name = filesystem_info.display_name;
+ filesystem_info_.filesystem_id = filesystem_info.filesystem_id;
+ filesystem_info_.opened_files_limit = filesystem_info.opened_files_limit;
+
+
+ reply_msg.params.set_result(PP_OK);
+ host_->SendReply(
+ reply_msg,
+ PpapiPluginMsg_FilesystemProvider_MountReply()
+ );
+}
+
+//static
+// Responsible with removal of the filesystem backend
+base::File::Error PepperFilesystemProviderBackendChromeOS::
+UnregisterFilesystemOnUI(
+ ProvidedFilesystemInfo filesystem_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ PluginService *fs_service = PluginService::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::PluginService::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
+ UnregisterFilesystemListenedOperations();
+
+ mounted_ = false;
+ // Send result to the plugin
+ host_->SendReply(
+ reply_msg,
+ PpapiPluginMsg_FilesystemProvider_UnmountReply()
+ );
+}
+
+void PepperFilesystemProviderBackendChromeOS::OnDispatchOperationRequest(
+ RequestType operation_type, scoped_ptr<base::ListValue> request) {
+ if ( operation_type==WRITE_FILE ) {
+ // 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());
+ } else {
+ //TODO(sabin): Remove this when done testing
+ if(operation_type==OPEN_FILE)
+ time_stamp_=std::chrono::system_clock::now();
+ else if(operation_type==CLOSE_FILE) {
+ 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(
+ RequestTypeToOperationType(operation_type),
+ *request)
+ );
+ }
+}
+
+// Transforms messages that are received from
+// the plugin in response of filesystem operations and sends
+// them back to the filesystem backend.
+int32_t PepperFilesystemProviderBackendChromeOS::OnSuccessResponse(
+ int operation,
+ const ProvidedFilesystemInfo& filesystem_info,
+ scoped_ptr<base::ListValue> response ) {
+
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ PluginService *fs_service = PluginService::Get(
+ ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ ProvidedFileSystemAdapter* fs_backend =
+ fs_service->GetProvidedFileSystemAdapter(
+ filesystem_info.plugin_name,
+ filesystem_info.filesystem_id);
+
+ if (fs_backend==nullptr)
+ return PP_ERROR_FAILED;
+ fs_backend->PushSuccessResponse( PP_OperationToRequestType(operation),
+ response.Pass());
+
+ return PP_OK;
+}
+
+int32_t PepperFilesystemProviderBackendChromeOS::OnErrorResponse(
+ const ProvidedFilesystemInfo& filesystem_info,
+ scoped_ptr<base::ListValue> response) {
+
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ PluginService *fs_service = PluginService::Get(
+ ProfileManager::GetActiveUserProfile());
+ DCHECK(fs_service);
+
+ ProvidedFileSystemAdapter* fs_backend =
+ fs_service->GetProvidedFileSystemAdapter(
+ filesystem_info.plugin_name,
+ filesystem_info.filesystem_id);
+ if(fs_backend==nullptr)
+ return PP_ERROR_FAILED;
+ fs_backend->PushErrorResponse(response.Pass());
+ 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 true;
+ 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
+ bool status = message.Set(2, base::BinaryValue::CreateWithCopiedBuffer(
+ (const char*)read_write_buffer_->shm->memory(), out_size));
+ SendReadAck();
+ return status;
+}
+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;
+}
+bool PepperFilesystemProviderBackendChromeOS::PreprocessMessage(
+ base::ListValue& message,
+ bool& message_status,
+ int& operation_type) {
+ // Remove the custom "header" from the response
+ scoped_ptr<base::Value> operation_value = nullptr;
+ if (!message.Remove(0,&operation_value))
+ return false;
+ if (!operation_value->GetAsInteger(&operation_type))
+ return false;
+ // Get the status of the operation
+ scoped_ptr<base::Value> status_value=nullptr;
+ if (!message.Remove(0,&status_value))
+ return false;
+ if (!status_value->GetAsBoolean(&message_status))
+ return false;
+ switch (operation_type) {
+ case PP_OperationType_READFILE:
+ if (!AddFromSharedMemoryToMessage(message))
+ return false;
+ break;
+ case PP_OperationType_UNMOUNT:
+ if ( message_status )
+ mounted_ = false;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+void PepperFilesystemProviderBackendChromeOS::SendReadAck() {
+ // ACK the receipt and let the plugin know that if it has more
+ // requests it can send them
+ if (host_)
+ host_->SendUnsolicitedReply(resource_,
+ PpapiPluginMsg_FilesystemProvider_ReadAck());
+}
+
+namespace filesystem_provider_internal {
+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 filesystem_provider_internal
+} // namespace content
+

Powered by Google App Engine
This is Rietveld 408576698