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

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: Various cleanups Created 5 years, 6 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/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 extensions::api::file_system_provider::ProviderError;
21 using chromeos::file_system_provider::ProvidedFileSystemInterface;
22 using chromeos::file_system_provider::Service;
23 using chromeos::file_system_provider::Source_Type;
24 using chromeos::PluginEventRouter;
25 using content::BrowserThread;
26 using ppapi::host::HostMessageContext;
27
28 #define MAKE_EVENT_ENTRY(x,handler,operation)\
29 std::pair<std::string,\
30 std::pair<DispatchEventImplCallback,PP_OperationType_Dev>>(\
31 extensions::api::file_system_provider::x::kEventName,\
32 std::pair<DispatchEventImplCallback,PP_OperationType_Dev>(\
33 base::Bind( &PepperFilesystemProviderBackendChromeOS::handler,\
34 weak_factory_.GetWeakPtr() ), operation ) )
35
36 namespace content {
37
38 namespace {
39
40 // TODO(sabin): find a way to get the size of the stream reader internal
41 // buffer from the backend
42 // Size of the stream reader internal buffer. At most this number of bytes will
43 // be read ahead of the requested data.
44 const uint32_t kReaderBufferSize = 512 * 1024; // 512KB.
45
46 // Size of the stream writer internal buffer. At most this number of bytes will
47 // be postponed for writing.
48 const uint32_t kWriterBufferSize = 512 * 1024; // 512KB.
49
50 // The number of requests that can be buffered
51 const uint32_t kMaximumCachedReplies = 10;
52
53 base::File::Error PP_ProviderErrorToFileError(
54 ProviderError error) {
55 switch (error) {
56 case ProviderError::PROVIDER_ERROR_OK:
57 return base::File::FILE_OK;
58 case ProviderError::PROVIDER_ERROR_FAILED:
59 return base::File::FILE_ERROR_FAILED;
60 case ProviderError::PROVIDER_ERROR_IN_USE:
61 return base::File::FILE_ERROR_IN_USE;
62 case ProviderError::PROVIDER_ERROR_EXISTS:
63 return base::File::FILE_ERROR_EXISTS;
64 case ProviderError::PROVIDER_ERROR_NOT_FOUND:
65 return base::File::FILE_ERROR_NOT_FOUND;
66 case ProviderError::PROVIDER_ERROR_ACCESS_DENIED:
67 return base::File::FILE_ERROR_ACCESS_DENIED;
68 case ProviderError::PROVIDER_ERROR_TOO_MANY_OPENED:
69 return base::File::FILE_ERROR_TOO_MANY_OPENED;
70 case ProviderError::PROVIDER_ERROR_NO_MEMORY:
71 return base::File::FILE_ERROR_NO_MEMORY;
72 case ProviderError::PROVIDER_ERROR_NO_SPACE:
73 return base::File::FILE_ERROR_NO_SPACE;
74 case ProviderError::PROVIDER_ERROR_NOT_A_DIRECTORY:
75 return base::File::FILE_ERROR_NOT_A_DIRECTORY;
76 case ProviderError::PROVIDER_ERROR_INVALID_OPERATION:
77 return base::File::FILE_ERROR_INVALID_OPERATION;
78 case ProviderError::PROVIDER_ERROR_SECURITY:
79 return base::File::FILE_ERROR_SECURITY;
80 case ProviderError::PROVIDER_ERROR_ABORT:
81 return base::File::FILE_ERROR_ABORT;
82 case ProviderError::PROVIDER_ERROR_NOT_A_FILE:
83 return base::File::FILE_ERROR_NOT_A_FILE;
84 case ProviderError::PROVIDER_ERROR_NOT_EMPTY:
85 return base::File::FILE_ERROR_NOT_EMPTY;
86 case ProviderError::PROVIDER_ERROR_INVALID_URL:
87 return base::File::FILE_ERROR_INVALID_URL;
88 case ProviderError::PROVIDER_ERROR_IO:
89 return base::File::FILE_ERROR_IO;
90 case ProviderError::PROVIDER_ERROR_NONE:
91 NOTREACHED();
92 }
93
94 return base::File::FILE_ERROR_FAILED;
95 }
96
97 } // namespace
98
99 PepperFilesystemProviderBackendChromeOS::
100 ProvidedFilesystemInfo::ProvidedFilesystemInfo()
101 :filesystem_id("none"),
102 display_name("none"),
103 plugin_name("none"),
104 writable(false),
105 opened_files_limit(0) {
106 }
107 PepperFilesystemProviderBackendChromeOS::ShmBuffer::ShmBuffer(
108 uint32_t size, scoped_ptr<base::SharedMemory> shm)
109 : size(size),shm(shm.Pass()) {
110 DCHECK(this->shm);
111 }
112
113 PepperFilesystemProviderBackendChromeOS::ShmBuffer::~ShmBuffer() {
114
115 }
116
117 PepperFilesystemProviderBackendChromeOS::
118 ShmChannelSynchronizer::ShmChannelSynchronizer(
119 uint32_t size, FlushRequestCallback callback)
120 : max_size(size),
121 ready(true),
122 callback(callback){
123 }
124 PepperFilesystemProviderBackendChromeOS::
125 ShmChannelSynchronizer::~ShmChannelSynchronizer() {
126 }
127
128 bool PepperFilesystemProviderBackendChromeOS::
129 ShmChannelSynchronizer::EnqueueRequest(
130 scoped_ptr<base::ListValue> response) {
131 // If channel ready send it straight away
132 if(ready) {
133 ready = !callback.Run(response.Pass());
134 if(!ready)
135 return true;
136 }
137 // If channel is not ready or failed to send
138 // cache the request
139 if(size() + 1 > max_size)
140 return false;
141 replies.push_back( response.Pass() );
142 return true;
143 }
144
145 bool PepperFilesystemProviderBackendChromeOS::
146 ShmChannelSynchronizer::PushNextRequest() {
147 // Try and send the request
148 scoped_ptr<base::ListValue> response;
149 while (size()>0 && ready ) {
150 response.reset(replies.front());
151 replies.weak_erase(replies.begin());
152 ready = !callback.Run(response.Pass());
153 }
154 return !ready;
155 }
156
157 bool
158 PepperFilesystemProviderBackendChromeOS::
159 ShmChannelSynchronizer::AckLastPushedRequest() {
160 return ready = true;
161 }
162
163 uint32_t PepperFilesystemProviderBackendChromeOS::
164 ShmChannelSynchronizer::size() {
165 return replies.size();
166 }
167
168
169
170 PepperFilesystemProviderBackendChromeOS::
171 PepperFilesystemProviderBackendChromeOS(
172 content::BrowserPpapiHost *host,
173 PP_Instance instance,
174 PP_Resource resource)
175 : mounted_(false),
176 host_(host ? host->GetPpapiHost() : nullptr),
177 resource_(resource),
178 write_channel_controller_(new ShmChannelSynchronizer(
179 kMaximumCachedReplies,
180 base::Bind(
181 &PepperFilesystemProviderBackendChromeOS::
182 FlushRequest,
183 base::Unretained(this)))),
184 weak_factory_(this) {
185
186 filesystem_info_.plugin_name = std::string("Plugin_") +
187 std::to_string(instance);
188
189 std::pair<
190 std::string, std::pair<DispatchEventImplCallback,PP_OperationType_Dev> >
191 ev[] ={
192 MAKE_EVENT_ENTRY(
193 OnAbortRequested,
194 SendOperationRequestToPlugin,
195 PP_OperationType_ABORT),
196 MAKE_EVENT_ENTRY(
197 OnCloseFileRequested,
198 SendOperationRequestToPlugin,
199 PP_OperationType_CLOSEFILE),
200 MAKE_EVENT_ENTRY(
201 OnCopyEntryRequested,
202 SendOperationRequestToPlugin,
203 PP_OperationType_COPYENTRY),
204 MAKE_EVENT_ENTRY(
205 OnCreateDirectoryRequested,
206 SendOperationRequestToPlugin,
207 PP_OperationType_CREATEDIRECTORY),
208 MAKE_EVENT_ENTRY(
209 OnCreateFileRequested,
210 SendOperationRequestToPlugin,
211 PP_OperationType_CREATEFILE),
212 MAKE_EVENT_ENTRY(
213 OnDeleteEntryRequested,
214 SendOperationRequestToPlugin,
215 PP_OperationType_DELETEENTRY),
216 MAKE_EVENT_ENTRY(
217 OnGetMetadataRequested,
218 SendOperationRequestToPlugin,
219 PP_OperationType_GETMETADATA),
220 MAKE_EVENT_ENTRY(
221 OnMoveEntryRequested,
222 SendOperationRequestToPlugin,
223 PP_OperationType_MOVEENTRY),
224 MAKE_EVENT_ENTRY(
225 OnOpenFileRequested,
226 SendOperationRequestToPlugin,
227 PP_OperationType_OPENFILE),
228 MAKE_EVENT_ENTRY(
229 OnReadDirectoryRequested,
230 SendOperationRequestToPlugin,
231 PP_OperationType_READDIRECTORY),
232 MAKE_EVENT_ENTRY(
233 OnReadFileRequested,
234 SendOperationRequestToPlugin,
235 PP_OperationType_READFILE),
236 MAKE_EVENT_ENTRY(
237 OnTruncateRequested,
238 SendOperationRequestToPlugin,
239 PP_OperationType_TRUNCATEENTRY),
240 MAKE_EVENT_ENTRY(
241 OnUnmountRequested,
242 SendOperationRequestToPlugin,
243 PP_OperationType_UNMOUNT),
244 MAKE_EVENT_ENTRY(
245 OnWriteFileRequested,
246 SendWriteRequestToPlugin,
247 PP_OperationType_WRITEFILE)
248 };
249
250 for ( size_t i = 0; i < sizeof( ev ) / sizeof( ev[0] ); ++i ) {
251 handlers_list_.insert( ev[i] );
252 events_.push_back( ev[i].first );
253 }
254 }
255
256 PepperFilesystemProviderBackendChromeOS::
257 ~PepperFilesystemProviderBackendChromeOS() {
258 // Unregister the filesystem if state indicates
259 // that we have a mounted filesystem
260 if (mounted_) {
261 // Unregister any registered event from the PluginEventRouter
262 UnregisterFilesystemEventListeners();
263 // Unregister the filesystem backend on the
264 // proper thread from Service
265 BrowserThread::PostTask(
266 BrowserThread::UI,
267 FROM_HERE,
268 base::Bind(
269 base::IgnoreResult(
270 &PepperFilesystemProviderBackendChromeOS::
271 UnregisterFilesystemOnUI),
272 filesystem_info_
273 )
274 );
275 }
276 }
277
278 // Called when PpapiHostMsg_FilesystemProvider_Mount is received
279 // Forwards request to RegisterFilesystemOnUI
280 // Response is sent from MountReplyOnIO
281 int32_t PepperFilesystemProviderBackendChromeOS::SendMountRequest(
282 ppapi::host::HostMessageContext *context,
283 const base::ListValue& request) {
284
285 base::File::Error status = base::File::FILE_OK;
286 if (mounted_)
287 status = base::File::FILE_ERROR_EXISTS;
288
289 scoped_ptr<MountOperationTranslator> mount_info =
290 MountOperationTranslator::PopulateFromResponse(request);
291 if ( !mount_info.get() )
292 status = base::File::FILE_ERROR_FAILED;
293
294 // Stop and send failure back to the plugin
295 if (status!=base::File::FILE_OK) {
296 MountReplyOnIO(
297 context->MakeReplyMessageContext(),
298 filesystem_info_, base::File::FILE_ERROR_EXISTS);
299 return PP_OK_COMPLETIONPENDING;
300 }
301 // Populate the wanted filesystem configuration
302 ProvidedFilesystemInfo filesystem_info;
303 filesystem_info.plugin_name = filesystem_info_.plugin_name;
304 filesystem_info.filesystem_id = mount_info->file_system_id;
305 filesystem_info.display_name = mount_info->display_name;
306 filesystem_info.writable = mount_info->writable;
307 filesystem_info.opened_files_limit = mount_info->opened_files_limit;
308 // Change thread to create the filesystem backend on the
309 // UI thread. The result of this action is to be interpreted
310 // on the IO thread.
311 BrowserThread::PostTaskAndReplyWithResult(
312 BrowserThread::UI,
313 FROM_HERE,
314 base::Bind(
315 // This creates a filesystem backend owned by the Service
316 // entity
317 &PepperFilesystemProviderBackendChromeOS::RegisterFilesystemOnUI,
318 filesystem_info),
319 // This is called after the above returns to interpret result
320 base::Bind(
321 &PepperFilesystemProviderBackendChromeOS::MountReplyOnIO,
322 weak_factory_.GetWeakPtr(),
323 context->MakeReplyMessageContext(),
324 filesystem_info
325 )
326 );
327 return PP_OK_COMPLETIONPENDING;
328 }
329
330 // Called when PpapiHostMsg_FilesystemProvider_Unmount is received
331 // Forwards request to UnregisterFilesystemOnUI
332 // Response is sent from MountReplyOnIO
333 int32_t PepperFilesystemProviderBackendChromeOS::SendUnmountRequest(
334 ppapi::host::HostMessageContext *context, std::string fsid) {
335
336 if(!mounted_) {
337 UnmountReplyOnIO(
338 context->MakeReplyMessageContext(),
339 base::File::FILE_ERROR_NOT_FOUND);
340 }
341
342 // Remove registered events from PluginEventRouter
343 UnregisterFilesystemEventListeners();
344
345 BrowserThread::PostTaskAndReplyWithResult(
346 BrowserThread::UI,
347 FROM_HERE,
348 base::Bind(
349 &PepperFilesystemProviderBackendChromeOS::UnregisterFilesystemOnUI,
350 filesystem_info_),
351 base::Bind( &PepperFilesystemProviderBackendChromeOS::UnmountReplyOnIO,
352 weak_factory_.GetWeakPtr(),
353 context->MakeReplyMessageContext())
354 );
355 return PP_OK_COMPLETIONPENDING;
356 }
357
358 int32_t PepperFilesystemProviderBackendChromeOS::OnPluginResponse(
359 ppapi::host::HostMessageContext* context,
360 const base::ListValue& plugin_response) {
361 scoped_ptr<base::ListValue> response( plugin_response.DeepCopy() );
362 if (!response.get())
363 return PP_ERROR_FAILED;
364 // Remove the custom "header" from the response
365 scoped_ptr<base::Value> operation_value = nullptr;
366 int operation_type = PP_OperationType_NONE;
367 if (!response->Remove(0,&operation_value))
368 return PP_ERROR_FAILED;
369 if (!operation_value->GetAsInteger(&operation_type))
370 return PP_ERROR_FAILED;
371 // Get the status of the operation
372 scoped_ptr<base::Value> status_value=nullptr;
373 bool status = false;
374 if (!response->Remove(0,&status_value))
375 return PP_ERROR_FAILED;
376 if (!status_value->GetAsBoolean(&status))
377 return PP_ERROR_FAILED;
378
379 if ( status ) {// success
380
381 if (operation_type==PP_OperationType_READFILE) { // a preprocess stage
382 AddFromSharedMemoryToMessage(*response);
383 // ACK the receipt and let the plugin know that if it has more
384 // requests it can send them
385 host_->SendUnsolicitedReply(
386 resource_,
387 PpapiPluginMsg_FilesystemProvider_ReadAck()
388 );
389 }
390 BrowserThread::PostTask(
391 BrowserThread::UI,
392 FROM_HERE,
393 base::Bind(
394 base::IgnoreResult(
395 &PepperFilesystemProviderBackendChromeOS::
396 OnGeneralSuccessResponse),
397 operation_type,
398 filesystem_info_,
399 base::Passed(response.Pass()))
400 );
401 } else { // failure
402 BrowserThread::PostTask(
403 BrowserThread::UI,
404 FROM_HERE,
405 base::Bind(
406 base::IgnoreResult(
407 &PepperFilesystemProviderBackendChromeOS::
408 OnGeneralErrorResponse),
409 filesystem_info_,
410 base::Passed(response.Pass()))
411 );
412 }
413
414 return PP_OK;
415 }
416
417 // Sends next cached request if there is any pending
418 int32_t PepperFilesystemProviderBackendChromeOS::OnPluginWriteAck(
419 ppapi::host::HostMessageContext* ) {
420 write_channel_controller_->AckLastPushedRequest();
421 write_channel_controller_->PushNextRequest();
422 return PP_OK;
423 }
424
425 // Add all events to the PluginEventRouter list of dispatchable events
426 void PepperFilesystemProviderBackendChromeOS::
427 RegisterFilesystemEventListeners() {
428 DCHECK_CURRENTLY_ON(BrowserThread::IO);
429
430 PluginEventRouter *router = PluginEventRouter::GetInstance();
431 if (router!=nullptr)
432 router->AddEventsListener( events_, this, filesystem_info_.plugin_name );
433 }
434 // Remove all events from the PluginEventRouter list of dispatchable events
435 void PepperFilesystemProviderBackendChromeOS::
436 UnregisterFilesystemEventListeners() {
437 DCHECK_CURRENTLY_ON(BrowserThread::IO);
438 PluginEventRouter *router = PluginEventRouter::GetInstance();
439 if (router!=nullptr)
440 router->RemoveEventsListeners( events_, this, filesystem_info_.plugin_name);
441 }
442
443 // Static
444 // Responsible with the creations and registration of a new provided filesystem
445 base::File::Error PepperFilesystemProviderBackendChromeOS::
446 RegisterFilesystemOnUI(
447 ProvidedFilesystemInfo filesystem_info)
448 {
449 DCHECK_CURRENTLY_ON(BrowserThread::UI);
450
451 Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
452 DCHECK(fs_service);
453
454 chromeos::file_system_provider::MountOptions options(
455 filesystem_info.filesystem_id, filesystem_info.display_name);
456
457 options.writable = filesystem_info.writable;
458 options.opened_files_limit = filesystem_info.opened_files_limit;
459 options.supports_notify_tag = false; // Check this
460
461 base::File::Error error = fs_service->MountFileSystem(
462 filesystem_info.plugin_name,
463 options,
464 Source_Type::plugin );
465
466 return error; // This will be interpreted by MountReplyOnIO
467 }
468
469 // Sends feedback to the plugin
470 // and sets state
471 void PepperFilesystemProviderBackendChromeOS::MountReplyOnIO(
472 ppapi::host::ReplyMessageContext reply_msg,
473 ProvidedFilesystemInfo filesystem_info,
474 base::File::Error err) {
475 DCHECK_CURRENTLY_ON(BrowserThread::IO);
476
477 // Do not register and send error back
478 if ( err != base::File::FILE_OK ) {
479 reply_msg.params.set_result(PP_OK);
480 host_->SendReply(
481 reply_msg,
482 PpapiPluginMsg_FilesystemProvider_MountReply( PP_ProviderError_FAILED )
483 );
484 return;
485 }
486
487 filesystem_info_.writable = filesystem_info.writable;
488 filesystem_info_.opened_files_limit = filesystem_info.opened_files_limit;
489 filesystem_info_.filesystem_id = filesystem_info.filesystem_id;
490 filesystem_info_.display_name = filesystem_info.display_name;
491 mounted_ = true;
492
493 // Initialize the shared memory buffers if needed
494 if (!read_write_buffer_.get())
495 InitializeMemoryBuffer();
496 RegisterFilesystemEventListeners();
497
498 reply_msg.params.set_result(PP_OK);
499 host_->SendReply(
500 reply_msg,
501 PpapiPluginMsg_FilesystemProvider_MountReply( PP_ProviderError_OK )
502 );
503 }
504
505 //static
506 // Responsible with removal of the filesystem backend
507 base::File::Error PepperFilesystemProviderBackendChromeOS::
508 UnregisterFilesystemOnUI(
509 ProvidedFilesystemInfo filesystem_info) {
510 DCHECK_CURRENTLY_ON(BrowserThread::UI);
511
512 Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
513 DCHECK(fs_service);
514
515 base::File::Error err = fs_service->UnmountFileSystem(
516 filesystem_info.plugin_name,
517 filesystem_info.filesystem_id,
518 chromeos::file_system_provider::Service::UNMOUNT_REASON_USER );
519
520 return err;
521 }
522
523 // Sends feedback to the plugin
524 // and resets state
525 void PepperFilesystemProviderBackendChromeOS::UnmountReplyOnIO(
526 ppapi::host::ReplyMessageContext reply_msg, base::File::Error err) {
527
528 reply_msg.params.set_result(PP_OK);
529 // Unregister all events
530 UnregisterFilesystemEventListeners();
531
532 mounted_ = false;
533 filesystem_info_.writable = false;
534 filesystem_info_.opened_files_limit = 0;
535 filesystem_info_.filesystem_id = "";
536 filesystem_info_.display_name = "";
537
538 // Send result to the plugin
539 host_->SendReply(
540 reply_msg,
541 PpapiPluginMsg_FilesystemProvider_MountReply( PP_ProviderError_OK )
542 );
543 }
544
545 // Handle events that are dispatched by the PluginEventRouter
546 void PepperFilesystemProviderBackendChromeOS::OnDispatchEvent(
547 std::string event_name, scoped_ptr<base::ListValue> event_args) {
548 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
549
550 ListOfHandlersIterator it = handlers_list_.find( event_name );
551 if ( it != handlers_list_.end() )
552 it->second.first.Run( it->second.second, event_args.Pass() );
553 }
554
555 // Sends requests to plugin
556 void PepperFilesystemProviderBackendChromeOS::SendOperationRequestToPlugin(
557 PP_OperationType_Dev operation_type,
558 scoped_ptr<base::ListValue> event_args) {
559
560 //TODO(sabin): Remove this when done testing
561 if(operation_type==PP_OperationType_OPENFILE)
562 time_stamp_=std::chrono::system_clock::now();
563 else if(operation_type==PP_OperationType_CLOSEFILE) {
564 std::chrono::duration<double> elapsed_seconds =
565 std::chrono::system_clock::now()-time_stamp_;
566 LOG(ERROR) <<"Read/Write operation time: "<< elapsed_seconds.count()<<
567 " seconds";
568 }
569
570 host_->SendUnsolicitedReply(
571 resource_,
572 PpapiPluginMsg_FilesystemProvider_OperationRequest(
573 operation_type,
574 *event_args)
575 );
576
577 }
578
579 void PepperFilesystemProviderBackendChromeOS::SendWriteRequestToPlugin(
580 PP_OperationType_Dev operation_type,
581 scoped_ptr<base::ListValue> request) {
582 // Handle write to filesystem
583 // Put the chunk into the shared memory buffer or cache it
584 // if channel is not free
585 // TODO(sabin): Send error back to backend if this fails
586 write_channel_controller_->EnqueueRequest(request.Pass());
587 }
588
589 // Transforms messages that are received from
590 // the plugin in response of filesystem operations and sends
591 // them back to the filesystem backend.
592 int32_t PepperFilesystemProviderBackendChromeOS::OnGeneralSuccessResponse(
593 int operation,
594 ProvidedFilesystemInfo filesystem_info,
595 scoped_ptr<base::ListValue> args) {
596
597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
598 Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
599 DCHECK(fs_service);
600
601 ProvidedFileSystemInterface* fs_interface =
602 fs_service->GetProvidedFileSystem(
603 filesystem_info.plugin_name,
604 filesystem_info.filesystem_id);
605
606 if (fs_interface==nullptr)
607 return PP_ERROR_FAILED;
608
609 switch(operation) {
610 case PP_OperationType_READDIRECTORY: {
611 using extensions::api::
612 file_system_provider_internal::ReadDirectoryRequestedSuccess::
613 Params;
614 scoped_ptr<Params> params(Params::Create(*args));
615 if(!params.get())
616 return PP_ERROR_FAILED;
617
618 const bool has_more = params->has_more;
619 if ( base::File::FILE_OK!=
620 fs_interface->GetRequestManager()->FulfillRequest(
621 params->request_id,
622 chromeos::file_system_provider::RequestValue::
623 CreateForReadDirectorySuccess(params.Pass()),
624 has_more)
625 )
626 return PP_ERROR_FAILED;
627 }
628 break;
629 case PP_OperationType_GETMETADATA: {
630 using extensions::api::file_system_provider_internal::
631 GetMetadataRequestedSuccess::Params;
632 scoped_ptr<Params> params(Params::Create(*args));
633 if(!params.get())
634 return PP_ERROR_FAILED;
635
636 if (base::File::FILE_OK!=
637 fs_interface->GetRequestManager()->FulfillRequest(
638 params->request_id,
639 chromeos::file_system_provider::RequestValue::
640 CreateForGetMetadataSuccess(params.Pass()),
641 false)
642 )
643 return PP_ERROR_FAILED;
644 }
645 break;
646 case PP_OperationType_READFILE: {
647 using extensions::api::file_system_provider_internal::
648 ReadFileRequestedSuccess::Params;
649 scoped_ptr<Params> params(Params::Create(*args));
650 if (!params.get())
651 return PP_ERROR_FAILED;
652
653 const bool has_more = params->has_more;
654 if (base::File::FILE_OK!=
655 fs_interface->GetRequestManager()->FulfillRequest(
656 params->request_id,
657 chromeos::file_system_provider::RequestValue::
658 CreateForReadFileSuccess(params.Pass()),
659 has_more) )
660 return PP_ERROR_FAILED;
661 }
662 break;
663 case PP_OperationType_UNMOUNT: {
664 using extensions::api::file_system_provider_internal::
665 UnmountRequestedSuccess::Params;
666 scoped_ptr<Params> params(Params::Create(*args));
667 if(!params.get())
668 return PP_ERROR_FAILED;
669
670 if (base::File::FILE_OK!=
671 fs_service->UnmountFileSystem(
672 filesystem_info.plugin_name, filesystem_info.filesystem_id,
673 chromeos::file_system_provider::Service::UNMOUNT_REASON_USER)
674 )
675 return PP_ERROR_FAILED;
676 }
677 break;
678 default: {
679 using extensions::api::file_system_provider_internal::
680 OperationRequestedSuccess::Params;
681 scoped_ptr<Params> params(Params::Create(*args));
682 if(!params.get())
683 return PP_ERROR_FAILED;
684
685 if (base::File::FILE_OK!=
686 fs_interface->GetRequestManager()->FulfillRequest(
687 params->request_id,
688 chromeos::file_system_provider::RequestValue::
689 CreateForOperationSuccess(params.Pass()),
690 false)
691 )
692 return PP_ERROR_FAILED;
693 }
694 break;
695 }
696 return PP_OK;
697 }
698
699 int32_t PepperFilesystemProviderBackendChromeOS::OnGeneralErrorResponse(
700 ProvidedFilesystemInfo filesystem_info,
701 scoped_ptr<base::ListValue> args) {
702
703 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
704
705 Service *fs_service = Service::Get(ProfileManager::GetActiveUserProfile());
706 DCHECK(fs_service);
707
708 ProvidedFileSystemInterface* fs_interface =
709 fs_service->GetProvidedFileSystem(
710 filesystem_info.plugin_name,
711 filesystem_info.filesystem_id);
712 if(fs_interface==nullptr)
713 return PP_ERROR_FAILED;
714
715 using extensions::api::file_system_provider_internal::
716 OperationRequestedError::Params;
717 scoped_ptr<Params> params(Params::Create(*args));
718 if(!params.get())
719 return PP_ERROR_FAILED;
720
721 const base::File::Error error = PP_ProviderErrorToFileError(params->error);
722
723 if( base::File::FILE_OK!=
724 fs_interface->GetRequestManager()->RejectRequest(
725 params->request_id,
726 chromeos::file_system_provider::RequestValue::
727 CreateForOperationError(params.Pass()),
728 error)
729 )
730 return PP_ERROR_FAILED;
731 return PP_OK;
732 }
733
734 bool PepperFilesystemProviderBackendChromeOS::FlushRequest(
735 scoped_ptr<base::ListValue> request) {
736 if(!request.get())
737 return false;
738
739 if(!AddFromMessageToSharedMemory(*request))
740 return false;
741
742 host_->SendUnsolicitedReply(
743 resource_,
744 PpapiPluginMsg_FilesystemProvider_OperationRequest(
745 PP_OperationType_WRITEFILE,
746 *request));
747 return true;
748 }
749
750 bool PepperFilesystemProviderBackendChromeOS::InitializeMemoryBuffer() {
751 // Already initialized
752 if(read_write_buffer_.get())
753 return false;
754 scoped_ptr<base::SharedMemory> buffer( new base::SharedMemory );
755 size_t size = kReaderBufferSize + kWriterBufferSize;
756 if (!buffer.get() ||
757 !buffer->CreateAndMapAnonymous(size))
758 return false;
759 read_write_buffer_=make_scoped_ptr(new ShmBuffer(size, buffer.Pass()));
760 if(!read_write_buffer_.get())
761 return false;
762 using ppapi::proxy::SerializedHandle;
763 std::vector<SerializedHandle> handles;
764 handles.push_back(
765 SerializedHandle(read_write_buffer_->shm->handle(), size ));
766 // Send a message to the plugin with the shared mem handle
767 host_->SendUnsolicitedReplyWithHandles(
768 resource_,
769 PpapiPluginMsg_FilesystemProvider_Buffers(
770 kReaderBufferSize,
771 kWriterBufferSize),
772 handles
773 );
774 return true;
775 }
776 bool PepperFilesystemProviderBackendChromeOS::AddFromSharedMemoryToMessage(
777 base::ListValue& message) {
778 DCHECK(read_write_buffer_.get());
779 double out = 0;
780 if(!message.GetDouble(2,&out))
781 return false;
782 size_t out_size = out;
783 if(out_size>kReaderBufferSize)
784 return false;
785
786 // Replace the size with the actual data
787 return message.Set(2, base::BinaryValue::CreateWithCopiedBuffer(
788 (const char*)read_write_buffer_->shm->memory(), out_size));
789 }
790
791 bool PepperFilesystemProviderBackendChromeOS::AddFromMessageToSharedMemory(
792 base::ListValue& message) {
793 if( !read_write_buffer_.get() )
794 return false;
795
796 base::Value *dict_value = nullptr;
797 if(!message.Get(0,&dict_value))
798 return false;
799
800 base::DictionaryValue* dict =
801 static_cast<base::DictionaryValue*>(dict_value);
802 const base::BinaryValue* binary_value = NULL;
803 if (!dict->GetBinary("data", &binary_value))
804 return false;
805 // This can be '0'
806 size_t binary_size =binary_value->GetSize();
807 // Skip the read buffer and copy to shared mem the buffer into
808 // the write portion of the buffer
809 if(binary_size>kWriterBufferSize)
810 return false;
811 memcpy( (char*)read_write_buffer_->shm->memory()+kReaderBufferSize,
812 binary_value->GetBuffer(),
813 binary_size);
814 dict->Remove( "data", nullptr );
815 dict->SetDouble( "size",binary_size);
816 return true;
817 }
818
819 scoped_ptr<MountOperationTranslator>
820 MountOperationTranslator::PopulateFromResponse(
821 const base::ListValue& request) {
822 const base::Value *dict_value = nullptr;
823 if(!request.Get(0,&dict_value))
824 return scoped_ptr<MountOperationTranslator>();
825
826 const base::DictionaryValue* dict =
827 static_cast<const base::DictionaryValue*>(dict_value);
828
829 scoped_ptr< MountOperationTranslator > out(new MountOperationTranslator);
830
831 const base::Value* data_value = nullptr;
832 if (!dict->GetWithoutPathExpansion("fileSystemId", &data_value) ||
833 !data_value->IsType(base::Value::TYPE_STRING))
834 return scoped_ptr<MountOperationTranslator>();
835 if (!data_value->GetAsString(&out->file_system_id))
836 return scoped_ptr<MountOperationTranslator>();
837 if (!dict->GetWithoutPathExpansion("displayName", &data_value) ||
838 !data_value->IsType(base::Value::TYPE_STRING))
839 return scoped_ptr<MountOperationTranslator>();
840 if (!data_value->GetAsString(&out->display_name))
841 return scoped_ptr<MountOperationTranslator>();
842 if (!dict->GetWithoutPathExpansion("writable", &data_value) ||
843 !data_value->IsType(base::Value::TYPE_BOOLEAN))
844 return scoped_ptr<MountOperationTranslator>();
845 if (!data_value->GetAsBoolean(&out->writable))
846 return scoped_ptr<MountOperationTranslator>();
847
848 if (!dict->GetWithoutPathExpansion("openedFilesLimit", &data_value) ||
849 !data_value->IsType(base::Value::TYPE_INTEGER))
850 return scoped_ptr<MountOperationTranslator>();
851 if (!data_value->GetAsInteger(&out->opened_files_limit))
852 return scoped_ptr<MountOperationTranslator>();
853
854 return out.Pass();
855 }
856
857 }// namespace content
858
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698