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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/pepper/pepper_filesystem_provider_backen d_chromeos.h"
6
7 #include <chrono>
8
9 #include "base/memory/shared_memory.h"
10 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info .h"
11 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
12 #include "chrome/browser/chromeos/file_system_provider/file_system_plugin/plugin _service.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "content/public/browser/browser_ppapi_host.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "ppapi/c/pp_errors.h"
17 #include "ppapi/host/ppapi_host.h"
18 #include "ppapi/proxy/ppapi_messages.h"
19
20 using namespace chromeos::file_system_provider;
21 using content::BrowserThread;
22 using ppapi::host::HostMessageContext;
23
24 namespace content {
25
26 namespace {
27
28 // TODO(sabin): find a way to get the size of the stream reader internal
29 // buffer from the backend
30 // Size of the stream reader internal buffer. At most this number of bytes will
31 // be read ahead of the requested data.
32 const uint32_t kReaderBufferSize = 512 * 1024; // 512KB.
33
34 // Size of the stream writer internal buffer. At most this number of bytes will
35 // be postponed for writing.
36 const uint32_t kWriterBufferSize = 512 * 1024; // 512KB.
37
38 // The number of requests that can be buffered
39 const uint32_t kMaximumCachedReplies = 10;
40
41 RequestType PP_OperationToRequestType(int32_t operation_type) {
42 switch (operation_type) {
43 case PP_OperationType_ABORT:
44 return ABORT;
45 case PP_OperationType_ADDWATCHER:
46 return ADD_WATCHER;
47 case PP_OperationType_CLOSEFILE:
48 return CLOSE_FILE;
49 case PP_OperationType_COPYENTRY:
50 return COPY_ENTRY;
51 case PP_OperationType_CREATEDIRECTORY:
52 return CREATE_DIRECTORY;
53 case PP_OperationType_CREATEFILE:
54 return CREATE_FILE;
55 case PP_OperationType_DELETEENTRY:
56 return DELETE_ENTRY;
57 case PP_OperationType_GETMETADATA:
58 return GET_METADATA;
59 case PP_OperationType_MOVEENTRY:
60 return MOVE_ENTRY;
61 case PP_OperationType_OPENFILE:
62 return OPEN_FILE;
63 case PP_OperationType_READDIRECTORY:
64 return READ_DIRECTORY;
65 case PP_OperationType_READFILE:
66 return READ_FILE;
67 case PP_OperationType_REMOVEWATCHER:
68 return REMOVE_WATCHER;
69 case PP_OperationType_TRUNCATEENTRY:
70 return TRUNCATE;
71 case PP_OperationType_UNMOUNT:
72 return REQUEST_UNMOUNT;
73 case PP_OperationType_WRITEFILE:
74 return WRITE_FILE;
75 case PP_OperationType_NONE:
76 default:
77 break;
78 }
79 NOTREACHED();
80 return ABORT;
81 }
82
83 PP_OperationType_Dev RequestTypeToOperationType(int32_t operation_type) {
84 switch (operation_type) {
85 case ABORT:
86 return PP_OperationType_ABORT;
87 case ADD_WATCHER:
88 return PP_OperationType_ADDWATCHER;
89 case CLOSE_FILE:
90 return PP_OperationType_CLOSEFILE;
91 case COPY_ENTRY:
92 return PP_OperationType_COPYENTRY;
93 case CREATE_DIRECTORY:
94 return PP_OperationType_CREATEDIRECTORY;
95 case CREATE_FILE:
96 return PP_OperationType_CREATEFILE;
97 case DELETE_ENTRY:
98 return PP_OperationType_DELETEENTRY;
99 case GET_METADATA:
100 return PP_OperationType_GETMETADATA;
101 case MOVE_ENTRY:
102 return PP_OperationType_MOVEENTRY;
103 case OPEN_FILE:
104 return PP_OperationType_OPENFILE;
105 case READ_DIRECTORY:
106 return PP_OperationType_READDIRECTORY;
107 case READ_FILE:
108 return PP_OperationType_READFILE;
109 case REMOVE_WATCHER:
110 return PP_OperationType_REMOVEWATCHER;
111 case TRUNCATE:
112 return PP_OperationType_TRUNCATEENTRY;
113 case REQUEST_UNMOUNT:
114 return PP_OperationType_UNMOUNT;
115 case WRITE_FILE:
116 return PP_OperationType_WRITEFILE;
117 default:
118 break;
119 }
120 NOTREACHED();
121 return PP_OperationType_NONE;
122 }
123
124 } // namespace
125
126 PepperFilesystemProviderBackendChromeOS::
127 ProvidedFilesystemInfo::ProvidedFilesystemInfo()
128 :filesystem_id("none"),
129 display_name("none"),
130 plugin_name("none"),
131 writable(false),
132 opened_files_limit(0) {
133 }
134 PepperFilesystemProviderBackendChromeOS::ShmBuffer::ShmBuffer(
135 uint32_t size, scoped_ptr<base::SharedMemory> shm)
136 : size(size),shm(shm.Pass()) {
137 DCHECK(this->shm);
138 }
139
140 PepperFilesystemProviderBackendChromeOS::ShmBuffer::~ShmBuffer() {
141
142 }
143
144 PepperFilesystemProviderBackendChromeOS::
145 ShmChannelController::ShmChannelController(
146 uint32_t size, FlushRequestCallback callback)
147 : max_size(size),
148 ready(true),
149 callback(callback){
150 }
151 PepperFilesystemProviderBackendChromeOS::
152 ShmChannelController::~ShmChannelController() {
153 }
154
155 bool PepperFilesystemProviderBackendChromeOS::
156 ShmChannelController::EnqueueRequest(
157 scoped_ptr<base::ListValue> response) {
158 // If channel ready send it straight away
159 if(ready) {
160 ready = !callback.Run(response.Pass());
161 if(!ready)
162 return true;
163 }
164 // If channel is not ready or failed to send
165 // cache the request
166 if(size() + 1 > max_size)
167 return false;
168 replies.push_back( response.Pass() );
169 return true;
170 }
171
172 bool PepperFilesystemProviderBackendChromeOS::
173 ShmChannelController::PushNextRequest() {
174 // Try and send the request
175 scoped_ptr<base::ListValue> response;
176 while (size()>0 && ready ) {
177 response.reset(replies.front());
178 replies.weak_erase(replies.begin());
179 ready = !callback.Run(response.Pass());
180 }
181 return !ready;
182 }
183
184 bool
185 PepperFilesystemProviderBackendChromeOS::
186 ShmChannelController::AckLastPushedRequest() {
187 return ready = true;
188 }
189
190 uint32_t PepperFilesystemProviderBackendChromeOS::
191 ShmChannelController::size() {
192 return replies.size();
193 }
194
195
196
197 PepperFilesystemProviderBackendChromeOS::
198 PepperFilesystemProviderBackendChromeOS(
199 content::BrowserPpapiHost *host,
200 PP_Instance instance,
201 PP_Resource resource)
202 : mounted_(false),
203 host_(host ? host->GetPpapiHost() : nullptr),
204 resource_(resource),
205 write_channel_controller_(new ShmChannelController(
206 kMaximumCachedReplies,
207 base::Bind(
208 &PepperFilesystemProviderBackendChromeOS::
209 FlushRequest,
210 base::Unretained(this)))),
211 weak_factory_(this) {
212
213 filesystem_info_.plugin_name = std::string("Plugin_") +
214 std::to_string(static_cast<size_t>(instance));
215 }
216
217 PepperFilesystemProviderBackendChromeOS::
218 ~PepperFilesystemProviderBackendChromeOS() {
219 // Unregister the filesystem if state indicates
220 // that we have a mounted filesystem
221 if (mounted_) {
222 // Unregister any registered event from the PluginEventRouter
223 UnregisterFilesystemListenedOperations();
224 // Unregister the filesystem backend on the
225 // proper thread from Service
226 BrowserThread::PostTask(
227 BrowserThread::UI,
228 FROM_HERE,
229 base::Bind(
230 base::IgnoreResult(
231 &PepperFilesystemProviderBackendChromeOS::
232 UnregisterFilesystemOnUI),
233 filesystem_info_
234 )
235 );
236 }
237 }
238
239 // Called when PpapiHostMsg_FilesystemProvider_Mount is received
240 // Forwards request to RegisterFilesystemOnUI
241 // Response is sent from MountReplyOnIO
242 int32_t PepperFilesystemProviderBackendChromeOS::SendMountRequest(
243 ppapi::host::HostMessageContext *context,
244 const base::ListValue& request) {
245 using content::filesystem_provider_internal::MountOperationTranslator;
246
247 base::File::Error status = base::File::FILE_OK;
248 if (mounted_)
249 status = base::File::FILE_ERROR_EXISTS;
250
251 scoped_ptr<MountOperationTranslator> mount_info =
252 MountOperationTranslator::PopulateFromResponse(request);
253 if ( !mount_info.get() )
254 status = base::File::FILE_ERROR_FAILED;
255
256 // Stop and send failure back to the plugin
257 if (status!=base::File::FILE_OK) {
258 MountReplyOnIO(
259 context->MakeReplyMessageContext(),
260 filesystem_info_, base::File::FILE_ERROR_EXISTS);
261 return PP_OK_COMPLETIONPENDING;
262 }
263 // Populate the desired filesystem configuration
264 ProvidedFilesystemInfo filesystem_info;
265 filesystem_info.writable = mount_info->writable;
266 filesystem_info.display_name = mount_info->display_name;
267 filesystem_info.plugin_name = filesystem_info_.plugin_name;
268 filesystem_info.filesystem_id = mount_info->file_system_id;
269 filesystem_info.opened_files_limit = mount_info->opened_files_limit;
270 // Change thread to create the filesystem backend on the
271 // UI thread. The result of this action is to be interpreted
272 // on the IO thread.
273 BrowserThread::PostTaskAndReplyWithResult(
274 BrowserThread::UI,
275 FROM_HERE,
276 base::Bind(
277 // This creates a filesystem backend owned by the Service
278 // entity
279 &PepperFilesystemProviderBackendChromeOS::RegisterFilesystemOnUI,
280 filesystem_info),
281 // This is called after the above returns to interpret result
282 base::Bind(
283 &PepperFilesystemProviderBackendChromeOS::MountReplyOnIO,
284 weak_factory_.GetWeakPtr(),
285 context->MakeReplyMessageContext(),
286 filesystem_info
287 )
288 );
289 return PP_OK_COMPLETIONPENDING;
290 }
291
292 // Called when PpapiHostMsg_FilesystemProvider_Unmount is received
293 // Forwards request to UnregisterFilesystemOnUI
294 // Response is sent from MountReplyOnIO
295 int32_t PepperFilesystemProviderBackendChromeOS::SendUnmountRequest(
296 ppapi::host::HostMessageContext *context, const std::string& fsid) {
297
298 if(!mounted_) {
299 return PP_ERROR_FAILED;
300 }
301
302 // Remove registered events from PluginEventRouter
303 UnregisterFilesystemListenedOperations();
304
305 BrowserThread::PostTaskAndReplyWithResult(
306 BrowserThread::UI,
307 FROM_HERE,
308 base::Bind(
309 &PepperFilesystemProviderBackendChromeOS::UnregisterFilesystemOnUI,
310 filesystem_info_),
311 base::Bind( &PepperFilesystemProviderBackendChromeOS::UnmountReplyOnIO,
312 weak_factory_.GetWeakPtr(),
313 context->MakeReplyMessageContext())
314 );
315 return PP_OK_COMPLETIONPENDING;
316 }
317
318 int32_t PepperFilesystemProviderBackendChromeOS::OnPluginResponse(
319 ppapi::host::HostMessageContext* context,
320 const base::ListValue& plugin_response) {
321 scoped_ptr<base::ListValue> response( plugin_response.DeepCopy() );
322
323 if (!response.get() ||
324 !mounted_)
325 return PP_ERROR_FAILED;
326
327 bool status;
328 int operation_type = PP_OperationType_NONE;
329 if (!PreprocessMessage(*response, status, operation_type))
330 return PP_ERROR_FAILED;
331 if ( status ) {// success
332 BrowserThread::PostTask(
333 BrowserThread::UI,
334 FROM_HERE,
335 base::Bind(
336 base::IgnoreResult(
337 &PepperFilesystemProviderBackendChromeOS::
338 OnSuccessResponse),
339 operation_type,
340 filesystem_info_,
341 base::Passed(response.Pass()))
342 );
343 } else { // failure
344 BrowserThread::PostTask(
345 BrowserThread::UI,
346 FROM_HERE,
347 base::Bind(
348 base::IgnoreResult(
349 &PepperFilesystemProviderBackendChromeOS::
350 OnErrorResponse),
351 filesystem_info_,
352 base::Passed(response.Pass()))
353 );
354 }
355
356 return PP_OK;
357 }
358
359 // Sends next cached request if there is any pending
360 int32_t PepperFilesystemProviderBackendChromeOS::OnPluginWriteAck(
361 ppapi::host::HostMessageContext* ) {
362 write_channel_controller_->AckLastPushedRequest();
363 write_channel_controller_->PushNextRequest();
364 return PP_OK;
365 }
366
367 int32_t PepperFilesystemProviderBackendChromeOS::OnPluginNotification(
368 ppapi::host::HostMessageContext* context, const base::ListValue& args) {
369 scoped_ptr<base::ListValue> message(args.DeepCopy());
370 BrowserThread::PostTask(
371 BrowserThread::UI,
372 FROM_HERE,
373 base::Bind(
374 &PepperFilesystemProviderBackendChromeOS::
375 SendNotificationOnUI,
376 filesystem_info_, base::Passed(message.Pass())
377 )
378 );
379 return PP_OK;
380 }
381
382 void OnNotifyCompleted(base::File::Error /*result*/) {}
383
384 void PepperFilesystemProviderBackendChromeOS::SendNotificationOnUI(
385 const ProvidedFilesystemInfo& file_system_info,
386 scoped_ptr<base::ListValue> args) {
387 DCHECK_CURRENTLY_ON(BrowserThread::UI);
388
389 PluginService *fs_service = PluginService::Get(
390 ProfileManager::GetActiveUserProfile());
391 DCHECK(fs_service);
392
393 ProvidedFileSystemAdapter* fs_backend =
394 fs_service->GetProvidedFileSystemAdapter(
395 file_system_info.plugin_name,
396 file_system_info.filesystem_id);
397 if (!fs_backend)
398 return;
399 fs_backend->PushChangeNotificationResponse(args.Pass(),
400 base::Bind(OnNotifyCompleted));
401 }
402
403 // Add all events to the PluginEventRouter list of dispatchable events
404 void PepperFilesystemProviderBackendChromeOS::
405 RegisterFilesystemListenedOperations() {
406 DCHECK_CURRENTLY_ON(BrowserThread::IO);
407 std::vector<RequestType> operations = {
408 REQUEST_UNMOUNT, GET_METADATA, READ_DIRECTORY, OPEN_FILE, CLOSE_FILE,
409 READ_FILE, CREATE_DIRECTORY, DELETE_ENTRY, CREATE_FILE, COPY_ENTRY,
410 MOVE_ENTRY, TRUNCATE, WRITE_FILE, ABORT, ADD_WATCHER, REMOVE_WATCHER
411 };
412 PluginOperationRouter *router = PluginOperationRouter::GetInstance();
413 if (router!=nullptr)
414 router->AddOperationsForListener( operations, this,
415 filesystem_info_.plugin_name );
416 }
417 using chromeos::file_system_provider::READ_DIRECTORY;
418 // Remove all events from the PluginEventRouter list of dispatchable events
419 void PepperFilesystemProviderBackendChromeOS::
420 UnregisterFilesystemListenedOperations() {
421 DCHECK_CURRENTLY_ON(BrowserThread::IO);
422 std::vector<RequestType> operations = {
423 REQUEST_UNMOUNT, GET_METADATA, READ_DIRECTORY, OPEN_FILE, CLOSE_FILE,
424 READ_FILE, CREATE_DIRECTORY, DELETE_ENTRY, CREATE_FILE, COPY_ENTRY,
425 MOVE_ENTRY, TRUNCATE, WRITE_FILE, ABORT, ADD_WATCHER, REMOVE_WATCHER
426 };
427 PluginOperationRouter *router = PluginOperationRouter::GetInstance();
428 if (router!=nullptr)
429 router->RemoveOperationsForListener(operations,
430 filesystem_info_.plugin_name);
431 }
432
433 // Static
434 // Responsible with the creations and registration of a new provided filesystem
435 base::File::Error PepperFilesystemProviderBackendChromeOS::
436 RegisterFilesystemOnUI(
437 ProvidedFilesystemInfo filesystem_info)
438 {
439 DCHECK_CURRENTLY_ON(BrowserThread::UI);
440
441 PluginService *fs_service = PluginService::Get(
442 ProfileManager::GetActiveUserProfile());
443 DCHECK(fs_service);
444
445 chromeos::file_system_provider::MountOptions options(
446 filesystem_info.filesystem_id, filesystem_info.display_name);
447
448 // TODO(sabin): add support for watchers
449 options.supports_notify_tag = false;
450 options.writable = filesystem_info.writable;
451 options.opened_files_limit = filesystem_info.opened_files_limit;
452
453 base::File::Error error = fs_service->MountFileSystem(
454 filesystem_info.plugin_name,
455 options);
456
457 return error; // This will be interpreted by MountReplyOnIO
458 }
459
460 // Sends feedback to the plugin
461 // and sets state
462 void PepperFilesystemProviderBackendChromeOS::MountReplyOnIO(
463 ppapi::host::ReplyMessageContext reply_msg,
464 ProvidedFilesystemInfo filesystem_info,
465 base::File::Error err) {
466 DCHECK_CURRENTLY_ON(BrowserThread::IO);
467
468 // If an error occured or we cannot initialize the shared memory
469 if ( err != base::File::FILE_OK ||
470 !InitializeMemoryBuffer()) {
471 reply_msg.params.set_result(PP_ERROR_FAILED);
472 host_->SendReply(
473 reply_msg,
474 PpapiPluginMsg_FilesystemProvider_MountReply()
475 );
476 // Undo the registration
477 if (err==base::File::FILE_OK) {
478 BrowserThread::PostTask(
479 BrowserThread::UI,
480 FROM_HERE,
481 base::Bind(
482 base::IgnoreResult(
483 &PepperFilesystemProviderBackendChromeOS::
484 UnregisterFilesystemOnUI),
485 filesystem_info
486 )
487 );
488 }
489 return;
490 }
491
492 RegisterFilesystemListenedOperations();
493 mounted_ = true;
494 filesystem_info_.writable = filesystem_info.writable;
495 filesystem_info_.display_name = filesystem_info.display_name;
496 filesystem_info_.filesystem_id = filesystem_info.filesystem_id;
497 filesystem_info_.opened_files_limit = filesystem_info.opened_files_limit;
498
499
500 reply_msg.params.set_result(PP_OK);
501 host_->SendReply(
502 reply_msg,
503 PpapiPluginMsg_FilesystemProvider_MountReply()
504 );
505 }
506
507 //static
508 // Responsible with removal of the filesystem backend
509 base::File::Error PepperFilesystemProviderBackendChromeOS::
510 UnregisterFilesystemOnUI(
511 ProvidedFilesystemInfo filesystem_info) {
512 DCHECK_CURRENTLY_ON(BrowserThread::UI);
513
514 PluginService *fs_service = PluginService::Get(
515 ProfileManager::GetActiveUserProfile());
516 DCHECK(fs_service);
517
518 base::File::Error err = fs_service->UnmountFileSystem(
519 filesystem_info.plugin_name,
520 filesystem_info.filesystem_id,
521 chromeos::file_system_provider::PluginService::UNMOUNT_REASON_USER );
522
523 return err;
524 }
525
526 // Sends feedback to the plugin
527 // and resets state
528 void PepperFilesystemProviderBackendChromeOS::UnmountReplyOnIO(
529 ppapi::host::ReplyMessageContext reply_msg, base::File::Error err) {
530
531 reply_msg.params.set_result(PP_OK);
532 // Unregister all events
533 UnregisterFilesystemListenedOperations();
534
535 mounted_ = false;
536 // Send result to the plugin
537 host_->SendReply(
538 reply_msg,
539 PpapiPluginMsg_FilesystemProvider_UnmountReply()
540 );
541 }
542
543 void PepperFilesystemProviderBackendChromeOS::OnDispatchOperationRequest(
544 RequestType operation_type, scoped_ptr<base::ListValue> request) {
545 if ( operation_type==WRITE_FILE ) {
546 // Handle write to filesystem
547 // Put the chunk into the shared memory buffer or cache it
548 // if channel is not free
549 // TODO(sabin): Send error back to backend if this fails
550 write_channel_controller_->EnqueueRequest(request.Pass());
551 } else {
552 //TODO(sabin): Remove this when done testing
553 if(operation_type==OPEN_FILE)
554 time_stamp_=std::chrono::system_clock::now();
555 else if(operation_type==CLOSE_FILE) {
556 std::chrono::duration<double> elapsed_seconds =
557 std::chrono::system_clock::now()-time_stamp_;
558 LOG(ERROR) <<"Read/Write operation time: "<< elapsed_seconds.count()<<
559 " seconds";
560 }
561 host_->SendUnsolicitedReply(
562 resource_,
563 PpapiPluginMsg_FilesystemProvider_OperationRequest(
564 RequestTypeToOperationType(operation_type),
565 *request)
566 );
567 }
568 }
569
570 // Transforms messages that are received from
571 // the plugin in response of filesystem operations and sends
572 // them back to the filesystem backend.
573 int32_t PepperFilesystemProviderBackendChromeOS::OnSuccessResponse(
574 int operation,
575 const ProvidedFilesystemInfo& filesystem_info,
576 scoped_ptr<base::ListValue> response ) {
577
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
579 PluginService *fs_service = PluginService::Get(
580 ProfileManager::GetActiveUserProfile());
581 DCHECK(fs_service);
582
583 ProvidedFileSystemAdapter* fs_backend =
584 fs_service->GetProvidedFileSystemAdapter(
585 filesystem_info.plugin_name,
586 filesystem_info.filesystem_id);
587
588 if (fs_backend==nullptr)
589 return PP_ERROR_FAILED;
590 fs_backend->PushSuccessResponse( PP_OperationToRequestType(operation),
591 response.Pass());
592
593 return PP_OK;
594 }
595
596 int32_t PepperFilesystemProviderBackendChromeOS::OnErrorResponse(
597 const ProvidedFilesystemInfo& filesystem_info,
598 scoped_ptr<base::ListValue> response) {
599
600 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
601
602 PluginService *fs_service = PluginService::Get(
603 ProfileManager::GetActiveUserProfile());
604 DCHECK(fs_service);
605
606 ProvidedFileSystemAdapter* fs_backend =
607 fs_service->GetProvidedFileSystemAdapter(
608 filesystem_info.plugin_name,
609 filesystem_info.filesystem_id);
610 if(fs_backend==nullptr)
611 return PP_ERROR_FAILED;
612 fs_backend->PushErrorResponse(response.Pass());
613 return PP_OK;
614 }
615
616 bool PepperFilesystemProviderBackendChromeOS::FlushRequest(
617 scoped_ptr<base::ListValue> request) {
618 if(!request.get())
619 return false;
620
621 if(!AddFromMessageToSharedMemory(*request))
622 return false;
623
624 host_->SendUnsolicitedReply(
625 resource_,
626 PpapiPluginMsg_FilesystemProvider_OperationRequest(
627 PP_OperationType_WRITEFILE,
628 *request));
629 return true;
630 }
631 bool PepperFilesystemProviderBackendChromeOS::InitializeMemoryBuffer() {
632 // Already initialized
633 if(read_write_buffer_.get())
634 return true;
635 scoped_ptr<base::SharedMemory> buffer( new base::SharedMemory );
636 size_t size = kReaderBufferSize + kWriterBufferSize;
637 if (!buffer.get() ||
638 !buffer->CreateAndMapAnonymous(size))
639 return false;
640 read_write_buffer_=make_scoped_ptr(new ShmBuffer(size, buffer.Pass()));
641 if(!read_write_buffer_.get())
642 return false;
643 using ppapi::proxy::SerializedHandle;
644 std::vector<SerializedHandle> handles;
645 handles.push_back(
646 SerializedHandle(read_write_buffer_->shm->handle(), size ));
647 // Send a message to the plugin with the shared mem handle
648 host_->SendUnsolicitedReplyWithHandles(
649 resource_,
650 PpapiPluginMsg_FilesystemProvider_Buffers(
651 kReaderBufferSize,
652 kWriterBufferSize),
653 handles
654 );
655 return true;
656 }
657 bool PepperFilesystemProviderBackendChromeOS::AddFromSharedMemoryToMessage(
658 base::ListValue& message) {
659 DCHECK(read_write_buffer_.get());
660 double out = 0;
661 if(!message.GetDouble(2,&out))
662 return false;
663 size_t out_size = out;
664 if(out_size>kReaderBufferSize)
665 return false;
666
667 // Replace the size with the actual data
668 bool status = message.Set(2, base::BinaryValue::CreateWithCopiedBuffer(
669 (const char*)read_write_buffer_->shm->memory(), out_size));
670 SendReadAck();
671 return status;
672 }
673 bool PepperFilesystemProviderBackendChromeOS::AddFromMessageToSharedMemory(
674 base::ListValue& message) {
675 if( !read_write_buffer_.get() )
676 return false;
677
678 base::Value *dict_value = nullptr;
679 if(!message.Get(0,&dict_value))
680 return false;
681
682 base::DictionaryValue* dict =
683 static_cast<base::DictionaryValue*>(dict_value);
684 const base::BinaryValue* binary_value = NULL;
685 if (!dict->GetBinary("data", &binary_value))
686 return false;
687 // This can be '0'
688 size_t binary_size =binary_value->GetSize();
689 // Skip the read buffer and copy to shared mem the buffer into
690 // the write portion of the buffer
691 if(binary_size>kWriterBufferSize)
692 return false;
693 memcpy( (char*)read_write_buffer_->shm->memory()+kReaderBufferSize,
694 binary_value->GetBuffer(),
695 binary_size);
696 dict->Remove( "data", nullptr );
697 dict->SetDouble( "size",binary_size);
698 return true;
699 }
700 bool PepperFilesystemProviderBackendChromeOS::PreprocessMessage(
701 base::ListValue& message,
702 bool& message_status,
703 int& operation_type) {
704 // Remove the custom "header" from the response
705 scoped_ptr<base::Value> operation_value = nullptr;
706 if (!message.Remove(0,&operation_value))
707 return false;
708 if (!operation_value->GetAsInteger(&operation_type))
709 return false;
710 // Get the status of the operation
711 scoped_ptr<base::Value> status_value=nullptr;
712 if (!message.Remove(0,&status_value))
713 return false;
714 if (!status_value->GetAsBoolean(&message_status))
715 return false;
716 switch (operation_type) {
717 case PP_OperationType_READFILE:
718 if (!AddFromSharedMemoryToMessage(message))
719 return false;
720 break;
721 case PP_OperationType_UNMOUNT:
722 if ( message_status )
723 mounted_ = false;
724 break;
725 default:
726 break;
727 }
728 return true;
729 }
730
731 void PepperFilesystemProviderBackendChromeOS::SendReadAck() {
732 // ACK the receipt and let the plugin know that if it has more
733 // requests it can send them
734 if (host_)
735 host_->SendUnsolicitedReply(resource_,
736 PpapiPluginMsg_FilesystemProvider_ReadAck());
737 }
738
739 namespace filesystem_provider_internal {
740 scoped_ptr<MountOperationTranslator>
741 MountOperationTranslator::PopulateFromResponse(
742 const base::ListValue& request) {
743 const base::Value *dict_value = nullptr;
744 if(!request.Get(0,&dict_value))
745 return scoped_ptr<MountOperationTranslator>();
746
747 const base::DictionaryValue* dict =
748 static_cast<const base::DictionaryValue*>(dict_value);
749
750 scoped_ptr< MountOperationTranslator > out(new MountOperationTranslator);
751
752 const base::Value* data_value = nullptr;
753 if (!dict->GetWithoutPathExpansion("fileSystemId", &data_value) ||
754 !data_value->IsType(base::Value::TYPE_STRING))
755 return scoped_ptr<MountOperationTranslator>();
756 if (!data_value->GetAsString(&out->file_system_id))
757 return scoped_ptr<MountOperationTranslator>();
758 if (!dict->GetWithoutPathExpansion("displayName", &data_value) ||
759 !data_value->IsType(base::Value::TYPE_STRING))
760 return scoped_ptr<MountOperationTranslator>();
761 if (!data_value->GetAsString(&out->display_name))
762 return scoped_ptr<MountOperationTranslator>();
763 if (!dict->GetWithoutPathExpansion("writable", &data_value) ||
764 !data_value->IsType(base::Value::TYPE_BOOLEAN))
765 return scoped_ptr<MountOperationTranslator>();
766 if (!data_value->GetAsBoolean(&out->writable))
767 return scoped_ptr<MountOperationTranslator>();
768
769 if (!dict->GetWithoutPathExpansion("openedFilesLimit", &data_value) ||
770 !data_value->IsType(base::Value::TYPE_INTEGER))
771 return scoped_ptr<MountOperationTranslator>();
772 if (!data_value->GetAsInteger(&out->opened_files_limit))
773 return scoped_ptr<MountOperationTranslator>();
774
775 return out.Pass();
776 }
777 } // namespace filesystem_provider_internal
778 } // namespace content
779
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698