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

Unified Diff: ppapi/proxy/filesystem_provider_resource.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: ppapi/proxy/filesystem_provider_resource.cc
diff --git a/ppapi/proxy/filesystem_provider_resource.cc b/ppapi/proxy/filesystem_provider_resource.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e112f31d8b143c65b9674e63ccbe27474ed47495
--- /dev/null
+++ b/ppapi/proxy/filesystem_provider_resource.cc
@@ -0,0 +1,1754 @@
+// 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 "ppapi/proxy/filesystem_provider_resource.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/numerics/safe_conversions.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+namespace ppapi {
+namespace proxy {
+namespace {
+
+const uint32_t kMaximumCachedReplies = 10;
+
+static std::string PP_ProviderErrorToString(PP_ProviderError_Dev enum_param) {
+ switch (enum_param) {
+ case PP_ProviderError_OK:
+ return "OK";
+ case PP_ProviderError_FAILED:
+ return "FAILED";
+ case PP_ProviderError_IN_USE:
+ return "IN_USE";
+ case PP_ProviderError_EXISTS:
+ return "EXISTS";
+ case PP_ProviderError_NOT_FOUND:
+ return "NOT_FOUND";
+ case PP_ProviderError_ACCESS_DENIED:
+ return "ACCESS_DENIED";
+ case PP_ProviderError_TOO_MANY_OPENED:
+ return "TOO_MANY_OPENED";
+ case PP_ProviderError_NO_MEMORY:
+ return "NO_MEMORY";
+ case PP_ProviderError_NO_SPACE:
+ return "NO_SPACE";
+ case PP_ProviderError_NOT_A_DIRECTORY:
+ return "NOT_A_DIRECTORY";
+ case PP_ProviderError_INVALID_OPERATION:
+ return "INVALID_OPERATION";
+ case PP_ProviderError_SECURITY:
+ return "SECURITY";
+ case PP_ProviderError_ABORT:
+ return "ABORT";
+ case PP_ProviderError_NOT_A_FILE:
+ return "NOT_A_FILE";
+ case PP_ProviderError_NOT_EMPTY:
+ return "NOT_EMPTY";
+ case PP_ProviderError_INVALID_URL:
+ return "INVALID_URL";
+ case PP_ProviderError_IO:
+ return "IO";
+ case PP_ProviderError_NONE:
+ return "";
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace
+
+FilesystemProviderResource::ShmChannelSynchronizer::ShmChannelSynchronizer(
+ uint32_t size, FlushResponseCallback callback)
+ : max_size(size),
+ ready(true),
+ callback(callback){
+}
+FilesystemProviderResource::ShmChannelSynchronizer::~ShmChannelSynchronizer() {
+}
+
+bool FilesystemProviderResource::ShmChannelSynchronizer::EnqueueResponse(
+ scoped_ptr<base::ListValue> response,
+ const char* data, uint32_t data_size) {
+ // If channel ready send it straight away
+ if (ready) {
+ // Flush Request
+ ready = !callback.Run(response.Pass(), data, data_size);
+ if(!ready)
+ return true;
+ }
+ // If channel is not ready or failed to send,
+ // cache the response
+ if( size() + 1 > max_size )
+ return false;
+
+ // TODO(sabin): Find a better way to cached data
+ scoped_ptr<base::BinaryValue> payload(
+ base::BinaryValue::CreateWithCopiedBuffer(static_cast< const char*>(data),
+ data_size));
+ if( !payload.get() )
+ return false;
+
+ response->Append(payload.release());
+ replies.push_back(response.release());
+
+ return true;
+}
+
+bool FilesystemProviderResource::ShmChannelSynchronizer::PushNextResponse() {
+ scoped_ptr<base::ListValue> response;
+ scoped_ptr<base::Value> payload;
+ while (size()>0 && ready ) {
+ // Try to push a response from the queue to
+ // the browser
+ response.reset(replies.front());
+ replies.weak_erase(replies.begin());
+
+ if(!response->Remove(response->GetSize()-1, &payload)||
+ !payload->IsType(base::Value::TYPE_BINARY))
+ continue;
+
+ base::BinaryValue* data = static_cast<base::BinaryValue*>(payload.get());
+ ready = !callback.Run(
+ response.Pass(),
+ data->GetBuffer(),
+ data->GetSize());
+ }
+ return !ready;
+}
+
+bool
+FilesystemProviderResource::ShmChannelSynchronizer::AckLastPushedResponse() {
+ return ready = true;
+}
+
+uint32_t FilesystemProviderResource::ShmChannelSynchronizer::size() {
+ return replies.size();
+}
+
+FilesystemProviderResource::ProvidedFilesystemInfo::ProvidedFilesystemInfo()
+ :filesystem_id("none"),
+ display_name("none"),
+ writable(false),opened_files_limit(0){
+}
+
+FilesystemProviderResource::ProvidedFilesystemInfo::~ProvidedFilesystemInfo() {
+}
+
+FilesystemProviderResource::ShmBuffer::ShmBuffer(
+ uint32_t read_size, uint32_t write_size,
+ scoped_ptr<base::SharedMemory> shm)
+ : read_size(read_size),write_size(write_size), shm(shm.Pass()) {
+ DCHECK(this->shm);
+}
+
+FilesystemProviderResource::ShmBuffer::~ShmBuffer() {
+}
+
+FilesystemProviderResource::RequestManager::RequestManager() {
+
+}
+
+FilesystemProviderResource::RequestManager::~RequestManager() {
+
+}
+
+void FilesystemProviderResource::RequestManager::AddRequest(
+ int32_t request_id, PP_OperationType_Dev operation ) {
+ requests_[ request_id ] = OperationStartTimePair(
+ operation,
+ std::chrono::system_clock::now() );
+}
+
+bool FilesystemProviderResource::RequestManager::RemoveRequest(
+ int32_t request_id, double *out_time_span) {
+ ListOfRequestsIterator it=requests_.find(request_id);
+ if (it==requests_.end())
+ return false;
+
+ // Compute operation time span
+ std::chrono::time_point<std::chrono::system_clock> now =
+ std::chrono::system_clock::now();
+ std::chrono::duration<double> elapsed_seconds = now - it->second.second;
+ if(out_time_span)
+ *out_time_span = elapsed_seconds.count();
+ requests_.erase( it );
+ return true;
+}
+
+FilesystemProviderResource::FilesystemProviderResource(
+ Connection connection,
+ PP_Instance instance )
+ :PluginResource( connection , instance ),
+ mounted_(false),
+ request_manager_(new RequestManager),
+ read_channel_controller_(
+ new ShmChannelSynchronizer(
+ kMaximumCachedReplies,
+ base::Bind(&FilesystemProviderResource::FlushReadResponse,
+ this))) {
+ DCHECK(request_manager_);
+ DCHECK(read_channel_controller_);
+ SendCreate(BROWSER, PpapiHostMsg_FilesystemProvider_Create() );
+}
+
+FilesystemProviderResource::~FilesystemProviderResource() {
+}
+
+
+thunk::PPB_FilesystemProvider_API*
+FilesystemProviderResource::AsPPB_FilesystemProvider_API() {
+ return this;
+}
+
+void FilesystemProviderResource::OnReplyReceived(
+ const ResourceMessageReplyParams &params, const IPC::Message &msg) {
+ if (params.sequence()) {
+ PluginResource::OnReplyReceived(params, msg);
+ return;
+ }
+ PPAPI_BEGIN_MESSAGE_MAP(FilesystemProviderResource, msg)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_FilesystemProvider_OperationRequest,
+ OnPluginMsgOperationRequest)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_FilesystemProvider_Buffers,
+ OnPluginMsgBuffersReady)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_0(
+ PpapiPluginMsg_FilesystemProvider_ReadAck,
+ OnPluginMsgReadAck)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED())
+ PPAPI_END_MESSAGE_MAP()
+}
+
+int32_t FilesystemProviderResource::Mount(
+ PP_Var filesystem_id,
+ PP_Var display_name,
+ PP_Bool writable,
+ int32_t opened_files_limit,
+ PP_ProviderError_Dev *error,
+ scoped_refptr<TrackedCallback> callback) {
+
+ if (error==nullptr)
+ return PP_ERROR_BADARGUMENT;
+ if ( mounted_ )
+ return PP_ERROR_ADDRESS_IN_USE;
+ if ( TrackedCallback::IsPending(mount_callback_) )
+ return PP_ERROR_INPROGRESS;
+
+ StringVar* string_var = nullptr;
+
+ const PP_Var *parameter_p[] = { &filesystem_id, &display_name };
+ std::string *value_p[] = {
+ &filesystem_info_.filesystem_id,
+ &filesystem_info_.display_name
+ };
+
+ for( uint32_t i = 0; i < sizeof( value_p ) / sizeof( value_p[0] ); i++ ) {
+ string_var = StringVar :: FromPPVar( *parameter_p[ i ] );
+ *value_p[ i ] = string_var ? string_var->value() : std::string();
+ }
+
+ filesystem_info_.writable = PP_ToBool( writable );
+ filesystem_info_.opened_files_limit = opened_files_limit;
+
+ // Remember the callback and the address of the return param
+ mount_callback_ = callback;
+ mount_callback_var_ = error;
+
+ // Send mount request to the browser
+ // and receive response in OnPluginMsgMountReply
+ scoped_ptr<base::ListValue> request(
+ filesystem_provider_internal::
+ PluginToBrowserTranslator::GenerateMountRequest(
+ filesystem_info_.filesystem_id, filesystem_info_.display_name,
+ filesystem_info_.writable,filesystem_info_.opened_files_limit));
+ if (!request.get())
+ return PP_ERROR_FAILED;
+
+ Call<PpapiPluginMsg_FilesystemProvider_MountReply>(
+ BROWSER,
+ PpapiHostMsg_FilesystemProvider_Mount(*request),
+ base::Bind(&FilesystemProviderResource::OnPluginMsgMountReply, this)
+ );
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FilesystemProviderResource::Unmount(
+ PP_Var filesystemId,
+ PP_ProviderError_Dev *error,
+ scoped_refptr<TrackedCallback> callback ) {
+ if ( !mounted_ )
+ return PP_ERROR_FAILED;
+ if ( TrackedCallback::IsPending(unmount_callback_) )
+ return PP_ERROR_INPROGRESS;
+
+ StringVar* string_var = nullptr;
+
+ string_var = StringVar::FromPPVar( filesystemId );
+ std::string fs_id = string_var ? string_var->value() : std::string();
+
+ if (fs_id!=filesystem_info_.filesystem_id)
+ return PP_ERROR_FAILED;
+
+ // Remember the unmount callback and the address of the return param
+ unmount_callback_ =callback;
+ unmount_callback_var_ =error;
+
+ Call < PpapiPluginMsg_FilesystemProvider_UnmountReply >(
+ BROWSER,
+ PpapiHostMsg_FilesystemProvider_Unmount( fs_id ),
+ base::Bind( &FilesystemProviderResource::OnPluginMsgUnmountReply,
+ this )
+ );
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+
+int32_t FilesystemProviderResource::SendSuccessResponse(
+ PP_OperationType_Dev operation_type,
+ int32_t request_id) {
+
+ scoped_ptr<base::ListValue> response;
+
+ switch( operation_type ) {
+ case PP_OperationType_GETMETADATA:
+ case PP_OperationType_READDIRECTORY:
+ case PP_OperationType_READFILE:
+ return PP_ERROR_BADARGUMENT;
+ default: {
+ // If we can't find a matching request from the browser
+ // bail out
+ double time_span = 0;
+ if( !request_manager_->RemoveRequest(request_id, &time_span) )//
+ return PP_ERROR_BADARGUMENT;
+ response = filesystem_provider_internal::
+ PluginToBrowserTranslator::GenerateSuccessResponse(
+ operation_type, filesystem_info_.filesystem_id,
+ request_id, time_span );
+ if(!response.get())
+ return PP_ERROR_FAILED;
+ }
+ }
+ Post(
+ BROWSER,
+ PpapiHostMsg_FilesystemProvider_OperationResponse(*response));
+ return PP_OK;
+}
+
+int32_t FilesystemProviderResource::SendErrorResponse(
+ PP_OperationType_Dev operation_type,
+ PP_ProviderError_Dev error,
+ int32_t request_id) {
+
+ double time_span = 0;
+ if( !request_manager_->RemoveRequest(request_id, &time_span) )
+ return PP_ERROR_BADARGUMENT;
+
+ scoped_ptr<base::ListValue> response(
+ filesystem_provider_internal::
+ PluginToBrowserTranslator::GenerateFailureResponse(
+ operation_type, error, filesystem_info_.filesystem_id, request_id,
+ time_span ));
+ if(!response.get())
+ return PP_ERROR_FAILED;
+
+ Post(
+ BROWSER,
+ PpapiHostMsg_FilesystemProvider_OperationResponse(*response));
+ return PP_OK;
+}
+
+int32_t FilesystemProviderResource::SendMetadataSuccessResponse(
+ const PP_EntryMetadata_Dev *metadata,
+ int32_t request_id) {
+ if(NULL==metadata)
+ return PP_ERROR_BADARGUMENT;
+
+ double time_span = 0;
+ if( !request_manager_->RemoveRequest(request_id, &time_span) )
+ return PP_ERROR_BADARGUMENT;
+
+ scoped_ptr<base::ListValue> response(
+ filesystem_provider_internal::
+ PluginToBrowserTranslator::GenerateMetadataResponse(
+ metadata, request_id, filesystem_info_.filesystem_id, time_span));
+ if(!response.get())
+ return PP_ERROR_FAILED;
+
+ Post(
+ BROWSER,
+ PpapiHostMsg_FilesystemProvider_OperationResponse(*response)
+ );
+ return PP_OK;
+}
+
+int32_t FilesystemProviderResource::SendReadDirectorySuccessResponse(
+ uint32_t array_size,
+ const PP_EntryMetadata_Dev entries[],
+ PP_Bool has_more, int32_t request_id) {
+
+ double time_span = 0;
+ if( !request_manager_->RemoveRequest(request_id, &time_span) )//
+ return PP_ERROR_BADARGUMENT;
+
+ scoped_ptr<base::ListValue> response(
+ filesystem_provider_internal::
+ PluginToBrowserTranslator::GenerateReadDirectoryResponse(
+ array_size, entries, has_more, request_id,
+ filesystem_info_.filesystem_id, time_span ));
+
+ if(!response.get())
+ return PP_ERROR_FAILED;
+ Post(
+ BROWSER,
+ PpapiHostMsg_FilesystemProvider_OperationResponse(*response) );
+ return PP_OK;
+}
+
+int32_t FilesystemProviderResource::SendReadFileSuccessResponse(
+ uint32_t data_size,
+ const void *data,
+ PP_Bool has_more,
+ int32_t request_id) {
+
+ double time_span = 0;
+ // Check if this is an answer to a previous request
+ if( !request_manager_->RemoveRequest(request_id, &time_span) )//
+ return PP_ERROR_BADARGUMENT;
+ // check if shared memory is ready and the right size
+ if(!read_write_buffer_.get())
+ return PP_ERROR_FAILED;
+ if(data_size > read_write_buffer_->read_size )
+ return PP_ERROR_MESSAGE_TOO_BIG;
+
+ scoped_ptr<base::ListValue> response(
+ filesystem_provider_internal::
+ PluginToBrowserTranslator::GenerateReadFileSuccessResponse(
+ data_size, PP_ToBool( has_more ), request_id, time_span,
+ filesystem_info_.filesystem_id));
+
+ if(!response.get())
+ return PP_ERROR_FAILED;
+
+ // Send response or enqueue it
+ if(!read_channel_controller_->EnqueueResponse(
+ response.Pass(), static_cast<const char*>(data),data_size))
+ return PP_ERROR_FAILED;
+ return PP_OK;
+}
+
+int32_t FilesystemProviderResource::GetNextRequest(
+ PP_FilesystemRequest* request, scoped_refptr<TrackedCallback> callback) {
+ if(TrackedCallback::IsPending(get_next_request_callback_))
+ return PP_ERROR_INPROGRESS;
+ // Retain the container address
+ get_next_request_callback_var_ = request;
+ // If buffered requests are pending return the first one
+ if(!received_requests_.empty()) {
+ if(!WriteRequest())
+ return PP_ERROR_FAILED;
+ // By returning PP_OK the callback is run
+ return PP_OK;
+ }
+ // Retain the callback for future execution
+ get_next_request_callback_=callback;
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FilesystemProviderResource::FreeWriteRequestBuffer(const void* buffer) {
+ using namespace filesystem_provider_internal;
+ WriteFileOperationTranslator* request=nullptr;
+ if(!buffer)
+ return PP_ERROR_BADARGUMENT;
+ for(ScopedVector<OperationTranslator>::iterator
+ it(received_write_requests_.begin());
+ it!=received_write_requests_.end();++it){
+ request = static_cast<WriteFileOperationTranslator*> (*it) ;
+ if(&request->data[0]==buffer){
+ received_write_requests_.erase(it);
+ return PP_OK;
+ }
+ }
+ return PP_ERROR_FAILED;
+}
+
+void FilesystemProviderResource::OnPluginMsgMountReply(
+ const ResourceMessageReplyParams &params,
+ PP_ProviderError_Dev error) {
+ if (TrackedCallback::IsPending(mount_callback_)) {
+ if (error==PP_ProviderError_NONE)
+ mounted_ = true;
+ *mount_callback_var_ = error;
+ mount_callback_->Run( params.result() );
+ }
+}
+
+void FilesystemProviderResource::OnPluginMsgUnmountReply(
+ const ResourceMessageReplyParams &params,
+ PP_ProviderError_Dev error) {
+ mounted_ = 0;
+ if (TrackedCallback::IsPending( unmount_callback_ )) {
+ *unmount_callback_var_ = error;
+ unmount_callback_->Run( params.result() );
+ }
+}
+
+void FilesystemProviderResource::OnPluginMsgOperationRequest(
+ const ResourceMessageParams &params,
+ const PP_OperationType_Dev &operation,
+ const base::ListValue &operationArgs) {
+using namespace filesystem_provider_internal;
+// We shall push the request
+ switch (operation) {
+ case PP_OperationType_ABORT: {
+ scoped_ptr<AbortOperationTranslator>
+ request = AbortOperationTranslator::PopulateFromRequest(
+ operationArgs);
+
+ if (request.get()) {
+ // Retain payload
+ request_manager_->RemoveRequest( request->operation_request_id, NULL);
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ } // PP_OperationType_ABORT
+ case PP_OperationType_CLOSEFILE: {
+ scoped_ptr< CloseFileOperationTranslator >
+ request = CloseFileOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }//PP_OperationType_CLOSEFILE
+ case PP_OperationType_COPYENTRY: {
+ scoped_ptr< CopyEntryOperationTranslator >
+ request = CopyEntryOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }// PP_OperationType_COPYENTRY
+ case PP_OperationType_CREATEDIRECTORY: {
+ scoped_ptr< CreateDirectoryOperationTranslator >
+ request = CreateDirectoryOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }// PP_OperationType_CREATEDIRECTORY
+ case PP_OperationType_CREATEFILE: {
+ scoped_ptr< CreateFileOperationTranslator >
+ request = CreateFileOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }// PP_OperationType_CREATEFILE
+ case PP_OperationType_DELETEENTRY: {
+ scoped_ptr< DeleteEntryOperationTranslator >
+ request = DeleteEntryOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }//PP_OperationType_DELETEENTRY
+ case PP_OperationType_GETMETADATA: {
+ scoped_ptr<GetMetadataOperationTranslator>
+ request = GetMetadataOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if ( request.get() ) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ } // PP_OperationType_GETMETADATA
+ case PP_OperationType_MOVEENTRY: {
+ scoped_ptr<MoveOperationTranslator>
+ request = MoveOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }// PP_OperationType_MOVEENTRY
+ case PP_OperationType_OPENFILE: {
+ scoped_ptr<OpenFileOperationTranslator>
+ request = OpenFileOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }// PP_OperationType_OpenFile
+ case PP_OperationType_READDIRECTORY: {
+ scoped_ptr<ReadDirectoryOperationTranslator>
+ request = ReadDirectoryOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }//PP_OperationType_READDIRECTORY
+ case PP_OperationType_READFILE: {
+ scoped_ptr<ReadFileOperationTranslator>
+ request = ReadFileOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }// PP_OperationType_READFILE
+ case PP_OperationType_TRUNCATEENTRY: {
+ scoped_ptr<TruncateOperationTranslator>
+ request = TruncateOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }//PP_OperationType_TRUNCATEENTRY
+ case PP_OperationType_UNMOUNT: {
+ scoped_ptr<UnmountOperationTranslator>
+ request = UnmountOperationTranslator::PopulateFromRequest(
+ operationArgs);
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ break;
+ }//PP_OperationType_UNMOUNT
+ case PP_OperationType_WRITEFILE: {
+ // If shared mem inited
+ if (read_write_buffer_.get()) {
+ scoped_ptr<WriteFileOperationTranslator>
+ request = WriteFileOperationTranslator::PopulateFromRequest(
+ operationArgs,
+ (char*)read_write_buffer_->shm->memory()+
+ read_write_buffer_->read_size
+ );
+ if (request.get()) {
+ request_manager_->AddRequest( request->request_id, operation);
+ received_requests_.push_back( request.Pass() );
+ }
+ }
+ // Send Ack for the request to the browser to signal that the shm
+ // channel can be reused.
+ Post(BROWSER, PpapiHostMsg_FilesystemProvider_WriteAck());
+ break;
+ }
+ default:
+ break;
+ }
+ if (!TrackedCallback::IsPending(get_next_request_callback_) ||
+ TrackedCallback::IsScheduledToRun(get_next_request_callback_) ||
+ !WriteRequest())
+ return;
+
+ // The plugin may call GetUIMessage in its callback
+ scoped_refptr<TrackedCallback> callback;
+ callback.swap(get_next_request_callback_);
+ // Run callback
+ callback->Run(PP_OK);
+}
+
+void FilesystemProviderResource::OnPluginMsgBuffersReady(
+ const ResourceMessageParams& params, uint32_t read_buffer_size,
+ uint32_t write_buffer_size ) {
+
+ std::vector<base::SharedMemoryHandle> shm_handles;
+ params.TakeAllSharedMemoryHandles(&shm_handles);
+
+ scoped_ptr<base::SharedMemory> shm(
+ new base::SharedMemory(shm_handles[0],false));
+ size_t buffer_size = read_buffer_size + write_buffer_size;
+ if(!shm->Map(buffer_size) )
+ return;
+ read_write_buffer_=
+ make_scoped_ptr(new ShmBuffer( read_buffer_size, write_buffer_size,
+ shm.Pass()));
+}
+
+// Received when the browser part acks the read from the shm buffer
+void FilesystemProviderResource::OnPluginMsgReadAck(
+ const ResourceMessageReplyParams& /*params*/) {
+
+ read_channel_controller_->AckLastPushedResponse();
+ read_channel_controller_->PushNextResponse();
+}
+
+bool FilesystemProviderResource::WriteRequest()
+{
+ if(!get_next_request_callback_var_)
+ return false;
+ scoped_ptr<PP_FilesystemRequest > request;
+ // The first request that we can decode we put it into the designated
+ // container for the filesystem provider implementation
+ while (received_requests_.size()>0) {
+ request = received_requests_.front()->ToFilesystemRequest();
+
+ if (!request.get()) {
+ // This request cannot be decoded
+ received_requests_.erase(received_requests_.begin());
+ } else {
+ break;
+ }
+ }
+ if(!request.get())
+ return false;
+
+ // If a write request with payload, move it to the write queue until
+ // the FS implementation frees it
+ if (request->operation_type == PP_OperationType_WRITEFILE &&
+ request->value.as_write_file.data_size) {
+ received_write_requests_.push_back(received_requests_.front());
+ received_requests_.weak_erase(received_requests_.begin());
+ // Other non-write requests or write requests that have no payload.
+ } else {
+ received_requests_.erase(received_requests_.begin());
+ }
+ *get_next_request_callback_var_ = *request;
+ get_next_request_callback_var_ = NULL;
+ return true;
+}
+
+bool FilesystemProviderResource::FlushReadResponse(
+ scoped_ptr<base::ListValue> response, const char*data, uint32_t data_size) {
+ if (!response.get() ||
+ data==NULL)
+ return false;
+ memcpy( read_write_buffer_->shm->memory(), data, data_size);
+
+ Post(BROWSER,
+ PpapiHostMsg_FilesystemProvider_OperationResponse(*response));
+
+ return true;
+}
+
+namespace filesystem_provider_internal{
+
+scoped_ptr<PP_FilesystemRequest>
+AbortOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_ABORT;
+ out->request_id = request_id;
+ return out.Pass();
+}
+
+// static
+scoped_ptr<AbortOperationTranslator>
+AbortOperationTranslator::PopulateFromRequest( const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<AbortOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ scoped_ptr<AbortOperationTranslator>();
+
+ scoped_ptr<AbortOperationTranslator> out(new AbortOperationTranslator());
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<AbortOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<AbortOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<AbortOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<AbortOperationTranslator>();
+
+ const base::Value* operation_request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion(
+ "operationRequestId", &operation_request_id_value))
+ return scoped_ptr<AbortOperationTranslator>();
+ if (!operation_request_id_value->GetAsInteger(&out->operation_request_id))
+ return scoped_ptr<AbortOperationTranslator>();
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+CloseFileOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+
+ out->operation_type = PP_OperationType_CLOSEFILE;
+ out->request_id = request_id;
+ out->value.as_close_file.open_request_id = open_request_id;
+
+ return out.Pass();
+}
+
+//static
+scoped_ptr<CloseFileOperationTranslator>
+CloseFileOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<CloseFileOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ scoped_ptr<CloseFileOperationTranslator>();
+
+ scoped_ptr<CloseFileOperationTranslator>
+ out(new CloseFileOperationTranslator());
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<CloseFileOperationTranslator>();
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<CloseFileOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<CloseFileOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<CloseFileOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<CloseFileOperationTranslator>();
+
+ const base::Value* open_request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("openRequestId", &open_request_id_value))
+ return scoped_ptr<CloseFileOperationTranslator>();
+ if (!open_request_id_value->GetAsInteger(&out->open_request_id))
+ return scoped_ptr<CloseFileOperationTranslator>();
+
+ return out.Pass();
+}
+
+//static
+scoped_ptr<PP_FilesystemRequest>
+GetMetadataOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_GETMETADATA;
+ out->request_id = request_id;
+ out->value.as_metadata.thumbnail = PP_FromBool( thumbnail );
+ snprintf(out->value.as_metadata.entry_path,
+ sizeof(out->value.as_metadata.entry_path),
+ "%s",
+ entry_path.c_str());
+ return out.Pass();
+}
+
+scoped_ptr<GetMetadataOperationTranslator>
+GetMetadataOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request ) {
+
+ if( request.empty() )
+ scoped_ptr<GetMetadataOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<GetMetadataOperationTranslator>();
+
+ scoped_ptr<GetMetadataOperationTranslator>
+ out(new GetMetadataOperationTranslator());
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<GetMetadataOperationTranslator>();
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ scoped_ptr<GetMetadataOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ scoped_ptr<GetMetadataOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ scoped_ptr<GetMetadataOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ scoped_ptr<GetMetadataOperationTranslator>();
+
+ const base::Value* entry_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("entryPath", &entry_path_value))
+ scoped_ptr<GetMetadataOperationTranslator>();
+ if (!entry_path_value->GetAsString(&out->entry_path))
+ scoped_ptr<GetMetadataOperationTranslator>();
+
+ const base::Value* thumbnail_value = NULL;
+ if (!dict->GetWithoutPathExpansion("thumbnail", &thumbnail_value))
+ scoped_ptr<GetMetadataOperationTranslator>();
+ if (!thumbnail_value->GetAsBoolean(&out->thumbnail))
+ scoped_ptr<GetMetadataOperationTranslator>();
+ return out.Pass();
+}
+
+
+scoped_ptr<PP_FilesystemRequest>
+CopyEntryOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ out->operation_type = PP_OperationType_COPYENTRY;
+ out->request_id = request_id;
+ snprintf( out->value.as_copy_entry.source_path,
+ sizeof(out->value.as_copy_entry.source_path),
+ "%s",
+ source_path.c_str() );
+ snprintf( out->value.as_copy_entry.target_path,
+ sizeof(out->value.as_copy_entry.target_path),
+ "%s",
+ target_path.c_str() );
+
+ return out.Pass();
+}
+
+// static
+scoped_ptr<CopyEntryOperationTranslator>
+CopyEntryOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<CopyEntryOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+
+ scoped_ptr<CopyEntryOperationTranslator>
+ out(new CopyEntryOperationTranslator());
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+
+ const base::Value* source_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("sourcePath", &source_path_value))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+ if (!source_path_value->GetAsString(&out->source_path))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+
+ const base::Value* target_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("targetPath", &target_path_value))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+ if (!target_path_value->GetAsString(&out->target_path))
+ return scoped_ptr<CopyEntryOperationTranslator>();
+ return out.Pass();
+
+}
+
+scoped_ptr<PP_FilesystemRequest>
+CreateDirectoryOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_CREATEDIRECTORY;
+ out->request_id = request_id;
+ snprintf(out->value.as_create_directory.directory_path,
+ sizeof(out->value.as_create_directory.directory_path),
+ "%s",
+ directory_path.c_str() );
+ out->value.as_create_directory.recursive = PP_FromBool(recursive);
+ return out.Pass();
+}
+
+scoped_ptr<CreateDirectoryOperationTranslator>
+CreateDirectoryOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<CreateDirectoryOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+
+ scoped_ptr<CreateDirectoryOperationTranslator>
+ out(new CreateDirectoryOperationTranslator());
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+
+ const base::Value* directory_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("directoryPath", &directory_path_value))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+ if (!directory_path_value->GetAsString(&out->directory_path))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+
+ const base::Value* recursive_value = NULL;
+ if (!dict->GetWithoutPathExpansion("recursive", &recursive_value))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+ if (!recursive_value->GetAsBoolean(&out->recursive))
+ return scoped_ptr<CreateDirectoryOperationTranslator>();
+
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+CreateFileOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_CREATEFILE;
+ out->request_id = request_id;
+ snprintf(out->value.as_create_file.file_path,
+ sizeof(out->value.as_create_file.file_path),
+ "%s",
+ file_path.c_str());
+ return out.Pass();
+}
+
+scoped_ptr<CreateFileOperationTranslator>
+CreateFileOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<CreateFileOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<CreateFileOperationTranslator>();
+
+ scoped_ptr<CreateFileOperationTranslator>
+ out(new CreateFileOperationTranslator());
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<CreateFileOperationTranslator>();
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<CreateFileOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<CreateFileOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<CreateFileOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<CreateFileOperationTranslator>();
+
+ const base::Value* file_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("filePath", &file_path_value))
+ return scoped_ptr<CreateFileOperationTranslator>();
+ if (!file_path_value->GetAsString(&out->file_path))
+ return scoped_ptr<CreateFileOperationTranslator>();
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+DeleteEntryOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ out->operation_type = PP_OperationType_DELETEENTRY;
+ out->request_id = request_id;
+ snprintf(out->value.as_delete_entry.entry_path,
+ sizeof(out->value.as_delete_entry.entry_path),
+ "%s",
+ entry_path.c_str());
+ out->value.as_delete_entry.recursive = PP_FromBool(recursive);
+ return out.Pass();
+}
+
+scoped_ptr<DeleteEntryOperationTranslator>
+DeleteEntryOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<DeleteEntryOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+
+
+ scoped_ptr<DeleteEntryOperationTranslator>
+ out(new DeleteEntryOperationTranslator());
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+
+ const base::Value* entry_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("entryPath", &entry_path_value))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+ if (!entry_path_value->GetAsString(&out->entry_path))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+
+ const base::Value* recursive_value = NULL;
+ if (!dict->GetWithoutPathExpansion("recursive", &recursive_value))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+ if (!recursive_value->GetAsBoolean(&out->recursive))
+ return scoped_ptr<DeleteEntryOperationTranslator>();
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+MoveOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_MOVEENTRY;
+ out->request_id = request_id;
+ snprintf(out->value.as_move_entry.source_path,
+ sizeof(out->value.as_move_entry.source_path),
+ "%s",
+ source_path.c_str());
+ snprintf(out->value.as_move_entry.target_path,
+ sizeof(out->value.as_move_entry.target_path),
+ "%s",
+ target_path.c_str());
+ return out.Pass();
+}
+
+scoped_ptr<MoveOperationTranslator>
+MoveOperationTranslator::PopulateFromRequest(const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<DeleteEntryOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<MoveOperationTranslator>();
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<MoveOperationTranslator>();
+
+ scoped_ptr<MoveOperationTranslator> out(new MoveOperationTranslator());
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<MoveOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<MoveOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<MoveOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<MoveOperationTranslator>();
+
+ const base::Value* source_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("sourcePath", &source_path_value))
+ return scoped_ptr<MoveOperationTranslator>();
+ if (!source_path_value->GetAsString(&out->source_path))
+ return scoped_ptr<MoveOperationTranslator>();
+
+ const base::Value* target_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("targetPath", &target_path_value))
+ return scoped_ptr<MoveOperationTranslator>();
+ if (!target_path_value->GetAsString(&out->target_path))
+ return scoped_ptr<MoveOperationTranslator>();
+ return out.Pass();
+}
+
+PP_OpenFileMode_Dev ParseOpenFileMode( const std::string &mode ) {
+ if (mode=="WRITE")
+ return PP_OpenFileMode_WRITE;
+ else if ( mode=="READ" )//( mode=="read")
+ return PP_OpenFileMode_READ;
+ else
+ return PP_OpenFileMode_NONE;
+}
+
+
+scoped_ptr<PP_FilesystemRequest>
+OpenFileOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_OPENFILE;
+ out->request_id = request_id;
+ snprintf( out->value.as_open_file.file_path,
+ sizeof(out->value.as_open_file.file_path),
+ "%s",
+ file_path.c_str());
+ out->value.as_open_file.mode = mode;
+ return out.Pass();
+}
+
+//static
+scoped_ptr<OpenFileOperationTranslator>
+OpenFileOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<OpenFileOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<OpenFileOperationTranslator>();
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<OpenFileOperationTranslator>();
+
+ scoped_ptr<OpenFileOperationTranslator>
+ out(new OpenFileOperationTranslator());
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<OpenFileOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<OpenFileOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<OpenFileOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<OpenFileOperationTranslator>();
+
+ const base::Value* file_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("filePath", &file_path_value))
+ return scoped_ptr<OpenFileOperationTranslator>();
+ if (!file_path_value->GetAsString(&out->file_path))
+ return scoped_ptr<OpenFileOperationTranslator>();
+
+ const base::Value* mode_value = NULL;
+ if (!dict->GetWithoutPathExpansion("mode", &mode_value))
+ return scoped_ptr<OpenFileOperationTranslator>();
+ std::string open_file_mode_as_string;
+ if (!mode_value->GetAsString(&open_file_mode_as_string))
+ return scoped_ptr<OpenFileOperationTranslator>();
+ out->mode = ParseOpenFileMode(open_file_mode_as_string);
+
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+ReadDirectoryOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_READDIRECTORY;
+ out->request_id = request_id;
+ snprintf(out->value.as_read_directory.directory_path,
+ sizeof(out->value.as_read_directory.directory_path),
+ "%s",
+ directory_path.c_str());
+ return out.Pass();
+}
+
+scoped_ptr<ReadDirectoryOperationTranslator>
+ReadDirectoryOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<ReadDirectoryOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+
+ scoped_ptr<ReadDirectoryOperationTranslator>
+ out(new ReadDirectoryOperationTranslator());
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+
+ const base::Value* directory_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("directoryPath", &directory_path_value))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+ if (!directory_path_value->GetAsString(&out->directory_path))
+ return scoped_ptr<ReadDirectoryOperationTranslator>();
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+ReadFileOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_READFILE;
+ out->request_id = request_id;
+ out->value.as_read_file.open_request_id = open_request_id;
+ out->value.as_read_file.offset = offset;
+ out->value.as_read_file.length = length;
+ return out.Pass();
+}
+
+scoped_ptr<ReadFileOperationTranslator>
+ReadFileOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ scoped_ptr<ReadFileOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<ReadFileOperationTranslator>();
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<ReadFileOperationTranslator>();
+ scoped_ptr<ReadFileOperationTranslator>
+ out(new ReadFileOperationTranslator());
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<ReadFileOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<ReadFileOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<ReadFileOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<ReadFileOperationTranslator>();
+
+ const base::Value* open_request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("openRequestId", &open_request_id_value))
+ return scoped_ptr<ReadFileOperationTranslator>();
+ if (!open_request_id_value->GetAsInteger(&out->open_request_id))
+ return scoped_ptr<ReadFileOperationTranslator>();
+
+ const base::Value* offset_value = NULL;
+ if (!dict->GetWithoutPathExpansion("offset", &offset_value))
+ return scoped_ptr<ReadFileOperationTranslator>();
+ if (!offset_value->GetAsDouble(&out->offset))
+ return scoped_ptr<ReadFileOperationTranslator>();
+
+ const base::Value* length_value = NULL;
+ if (!dict->GetWithoutPathExpansion("length", &length_value))
+ return scoped_ptr<ReadFileOperationTranslator>();
+ if (!length_value->GetAsDouble(&out->length))
+ return scoped_ptr<ReadFileOperationTranslator>();
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+TruncateOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_TRUNCATEENTRY;
+ out->request_id = request_id;
+ out->value.as_truncate.length = length;
+ snprintf( out->value.as_truncate.file_path,
+ sizeof(out->value.as_truncate.file_path),
+ "%s",
+ file_path.c_str());
+ return out.Pass();
+}
+
+scoped_ptr<TruncateOperationTranslator>
+TruncateOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+ if( request.empty() )
+ return scoped_ptr<TruncateOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<TruncateOperationTranslator>();
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY)) {
+ return scoped_ptr<TruncateOperationTranslator>();
+ }
+
+ scoped_ptr<TruncateOperationTranslator>
+ out(new TruncateOperationTranslator());
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<TruncateOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<TruncateOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<TruncateOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<TruncateOperationTranslator>();
+
+ const base::Value* file_path_value = NULL;
+ if (!dict->GetWithoutPathExpansion("filePath", &file_path_value))
+ return scoped_ptr<TruncateOperationTranslator>();
+ if (!file_path_value->GetAsString(&out->file_path))
+ return scoped_ptr<TruncateOperationTranslator>();
+
+ const base::Value* length_value = NULL;
+ if (!dict->GetWithoutPathExpansion("length", &length_value))
+ return scoped_ptr<TruncateOperationTranslator>();
+ if (!length_value->GetAsDouble(&out->length))
+ return scoped_ptr<TruncateOperationTranslator>();
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+UnmountOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_UNMOUNT;
+ out->request_id = request_id;
+ return out.Pass();
+}
+
+scoped_ptr<UnmountOperationTranslator>
+UnmountOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request) {
+
+ if( request.empty() )
+ return scoped_ptr<UnmountOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<UnmountOperationTranslator>();
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<UnmountOperationTranslator>();
+
+ scoped_ptr<UnmountOperationTranslator> out(new UnmountOperationTranslator());
+
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<UnmountOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<UnmountOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<UnmountOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<UnmountOperationTranslator>();
+ return out.Pass();
+}
+
+scoped_ptr<PP_FilesystemRequest>
+WriteFileOperationTranslator::ToFilesystemRequest() {
+ scoped_ptr<PP_FilesystemRequest> out(new PP_FilesystemRequest);
+ if(!out.get())
+ return scoped_ptr<PP_FilesystemRequest>();
+ out->operation_type = PP_OperationType_WRITEFILE;
+ out->request_id = request_id;
+ out->value.as_write_file.open_request_id = open_request_id;
+ out->value.as_write_file.offset = offset;
+ out->value.as_write_file.data_size = data.size();
+ // Pass the address
+ if(data.size())
+ out->value.as_write_file.data = &data[0];
+ else // or NULL if the browser sent an empty write request
+ out->value.as_write_file.data = NULL;
+ return out.Pass();
+}
+
+scoped_ptr<WriteFileOperationTranslator>
+WriteFileOperationTranslator::PopulateFromRequest(
+ const base::ListValue &request,
+ char* memory_address) {
+
+ if( request.empty() )
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ const base::Value *dict_value = nullptr;
+ if(!request.Get(0,&dict_value))
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ if (!dict_value->IsType(base::Value::TYPE_DICTIONARY))
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ scoped_ptr<WriteFileOperationTranslator>
+ out(new WriteFileOperationTranslator());
+ const base::DictionaryValue* dict =
+ static_cast<const base::DictionaryValue*>(dict_value);
+ const base::Value* file_system_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("fileSystemId", &file_system_id_value))
+ return scoped_ptr<WriteFileOperationTranslator>();
+ if (!file_system_id_value->GetAsString(&out->file_system_id))
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ const base::Value* request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("requestId", &request_id_value))
+ return scoped_ptr<WriteFileOperationTranslator>();
+ if (!request_id_value->GetAsInteger(&out->request_id))
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ const base::Value* open_request_id_value = NULL;
+ if (!dict->GetWithoutPathExpansion("openRequestId", &open_request_id_value))
+ return scoped_ptr<WriteFileOperationTranslator>();
+ if (!open_request_id_value->GetAsInteger(&out->open_request_id))
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ const base::Value* offset_value = NULL;
+ if (!dict->GetWithoutPathExpansion("offset", &offset_value))
+ return scoped_ptr<WriteFileOperationTranslator>();
+ if (!offset_value->GetAsDouble(&out->offset))
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ const base::Value* size_value = NULL;
+ if (!dict->GetWithoutPathExpansion("size", &size_value))
+ return scoped_ptr<WriteFileOperationTranslator>();
+ if (!size_value->GetAsDouble(&out->size))
+ return scoped_ptr<WriteFileOperationTranslator>();
+
+ // Buffer what will be cached until released by the FS implementation
+ out->data.assign(memory_address,
+ memory_address+static_cast<size_t>(out->size));
+ return out.Pass();
+}
+
+OperationTranslator::~OperationTranslator()
+{
+
+}
+
+scoped_ptr<base::ListValue>
+PluginToBrowserTranslator::GenerateReadFileSuccessResponse(
+ uint32_t data_size, bool has_more, int32_t request_id,
+ double time_span, const std::string& filesystem_id) {
+ size_t index = 0;
+ scoped_ptr<base::ListValue> response(new base::ListValue);
+ if( !response->Set(index++,
+ new base::FundamentalValue(PP_OperationType_READFILE))||
+ !response->Set(index++, new base::FundamentalValue(true))||// status = success
+ !response->Set(index++,
+ new base::StringValue(filesystem_id)) ||
+ !response->Set(index++, new base::FundamentalValue(request_id)) ||
+ !response->Set(index++, new base::FundamentalValue((double)data_size))||
+ !response->Set(index++, new base::FundamentalValue(has_more))||
+ !response->Set(index++, new base::FundamentalValue((int)time_span)))
+ return scoped_ptr<base::ListValue>();
+ return response.Pass();
+}
+
+scoped_ptr<base::ListValue>
+PluginToBrowserTranslator::GenerateMountRequest(
+ std::string filesystem_id, std::string display_name,
+ bool writable, int32_t opened_files_limit) {
+
+ scoped_ptr<base::DictionaryValue> payload(new base::DictionaryValue);
+ if(!payload.get())
+ return scoped_ptr<base::ListValue>();
+ payload->Set("fileSystemId",
+ new base::StringValue(filesystem_id));
+ payload->Set("displayName",
+ new base::StringValue(display_name));
+ payload->Set("writable",
+ new base::FundamentalValue(writable));
+ payload->Set("openedFilesLimit",
+ new base::FundamentalValue(opened_files_limit));
+ scoped_ptr<base::ListValue> response(new base::ListValue);
+ if(!response.get())
+ return scoped_ptr<base::ListValue>();
+ response->Set(0,payload.release());
+ return response.Pass();
+}
+
+scoped_ptr<base::ListValue>
+PluginToBrowserTranslator::GenerateSuccessResponse(
+ PP_OperationType_Dev operation_type,
+ const std::string &filesystem_id,
+ int32_t request_id, double time_span) {
+
+ scoped_ptr<base::ListValue> response(new base::ListValue);
+ if(!response.get())
+ return scoped_ptr<base::ListValue>();
+ size_t index = 0;
+ if ( !response->Set(index++, new base::FundamentalValue(operation_type))||
+ !response->Set(index++,
+ new base::FundamentalValue(true)) || // status = success
+ !response->Set(index++,
+ new base::StringValue(filesystem_id))||
+ !response->Set(index++, new base::FundamentalValue(request_id)) ||
+ !response->Set(index++, new base::FundamentalValue((int)time_span))) {
+ return scoped_ptr<base::ListValue>();
+ }
+ return response.Pass();
+}
+
+scoped_ptr<base::ListValue> PluginToBrowserTranslator::GenerateFailureResponse(
+ PP_OperationType_Dev operation_type, PP_ProviderError_Dev error,
+ const std::string &filesystem_id, int32_t request_id, double time_span) {
+ scoped_ptr<base::ListValue> response(new base::ListValue);
+ if(!response.get())
+ return scoped_ptr<base::ListValue>();
+ size_t index=0;
+ if ( !response->Set(index++, new base::FundamentalValue(operation_type)) ||
+ !response->Set(index++,
+ new base::FundamentalValue(false)) || // status = failure
+ !response->Set(index++,
+ new base::StringValue(filesystem_id)) ||
+ !response->Set(index++, new base::FundamentalValue(request_id)) ||
+ !response->Set(index++,
+ new base::StringValue(PP_ProviderErrorToString(error))) ||
+ !response->Set(index++, new base::FundamentalValue((int)time_span) ) )
+ return scoped_ptr<base::ListValue>();
+ return response.Pass();
+}
+
+scoped_ptr<base::ListValue> PluginToBrowserTranslator::GenerateMetadataResponse(
+ const PP_EntryMetadata_Dev *metadata, int32_t request_id,
+ const std::string &filesystem_id, double time_span) {
+
+ scoped_ptr<base::DictionaryValue> entry_metadata(new base::DictionaryValue);
+ if(!entry_metadata.get())
+ return scoped_ptr<base::ListValue>();
+
+ entry_metadata->SetBoolean( "isDirectory", PP_ToBool(metadata->is_directory));
+
+ entry_metadata->SetString("name",metadata->name[0]=='\0'?
+ "":metadata->name);
+ entry_metadata->SetString("mimeType", metadata->mime_type[0]=='\0'?
+ "":metadata->mime_type);
+ if(metadata->thumbnail[0]!='\0')
+ entry_metadata->SetString("thumbnail", metadata->thumbnail);
+ entry_metadata->SetDouble("size", metadata->size );
+
+ scoped_ptr<base::DictionaryValue>
+ modification_time(new base::DictionaryValue());
+ if(!modification_time.get())
+ return scoped_ptr<base::ListValue>();
+ modification_time->SetStringWithoutPathExpansion(
+ "value", metadata->modification_time);
+ entry_metadata->Set("modificationTime", modification_time.release());
+
+
+ scoped_ptr<base::ListValue> response(new base::ListValue);
+ size_t index = 0;
+ if (!response->Set(index++,
+ new base::FundamentalValue(PP_OperationType_GETMETADATA))||
+ !response->Set(index++, new base::FundamentalValue(true))|| //status = success
+ !response->Set(index++,
+ new base::StringValue(filesystem_id) ) ||
+ !response->Set(index++, new base::FundamentalValue(request_id) ) ||
+ !response->Set(index++, entry_metadata.release() ) ||
+ !response->Set(index++, new base::FundamentalValue((int)time_span) ) )
+ return scoped_ptr<base::ListValue>();
+ return response.Pass();
+}
+
+scoped_ptr<base::ListValue>
+PluginToBrowserTranslator::GenerateReadDirectoryResponse(
+ uint32_t array_size,
+ const PP_EntryMetadata_Dev entries[],
+ PP_Bool has_more, int32_t request_id,
+ const std::string &filesystem_id, double time_span) {
+
+ scoped_ptr<base::ListValue> response(new base::ListValue);
+ scoped_ptr<base::ListValue> list_value(new base::ListValue);
+ if(!list_value.get()||
+ !response.get())
+ return scoped_ptr<base::ListValue>();
+
+ for (uint32_t i = 0; i<array_size;++i) {
+ scoped_ptr<base::DictionaryValue>
+ entry_metadata(new base::DictionaryValue);
+ if(!entry_metadata.get())
+ return scoped_ptr<base::ListValue>();
+
+ entry_metadata->SetBoolean(
+ "isDirectory", PP_ToBool(entries[i].is_directory) );
+
+ entry_metadata->SetString("name",entries[i].name[0]=='\0'?
+ "":entries[i].name);
+ entry_metadata->SetString("mimeType", entries[i].mime_type[0]=='\0'?
+ "":entries[i].mime_type);
+ if(entries[i].thumbnail[0]!='\0')
+ entry_metadata->SetString("thumbnail", entries[i].thumbnail);
+ entry_metadata->SetDouble("size", entries[i].size );
+
+ scoped_ptr<base::DictionaryValue>
+ modification_time(new base::DictionaryValue());
+ if(!modification_time.get())
+ return scoped_ptr<base::ListValue>();
+
+ modification_time->SetStringWithoutPathExpansion(
+ "value", entries[i].modification_time);
+ entry_metadata->Set("modificationTime", modification_time.release());
+ list_value->Set(i,entry_metadata.release());
+ }
+
+ size_t index = 0;
+ if (!response->Set(index++,
+ new base::FundamentalValue(PP_OperationType_READDIRECTORY))||
+ !response->Set(index++,
+ new base::FundamentalValue(true))|| // status = success
+ !response->Set(index++,
+ new base::StringValue(filesystem_id) ) ||
+ !response->Set(index++, new base::FundamentalValue(request_id) ) ||
+ !response->Set(index++, list_value.release() ) ||
+ !response->Set(index++,
+ new base::FundamentalValue( PP_ToBool( has_more ) ) ) ||
+ !response->Set(index++, new base::FundamentalValue( (int)time_span ) ) )
+ return scoped_ptr<base::ListValue>();
+ return response.Pass();
+}
+} // namespace
+} // namespace proxy
+} // namespace ppapi

Powered by Google App Engine
This is Rietveld 408576698