1 // Copyright (c) 2011 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.
5 #include "ppapi/proxy/ppb_flash_file_proxy.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/message_loop_proxy.h"
14 #include "base/synchronization/lock.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "build/build_config.h"
17 #include "ipc/ipc_channel_proxy.h"
18 #include "ipc/ipc_message.h"
19 #include "ipc/ipc_sync_message.h"
20 #include "ppapi/c/pp_errors.h"
21 #include "ppapi/c/pp_file_info.h"
22 #include "ppapi/c/private/ppb_flash_file.h"
23 #include "ppapi/proxy/plugin_dispatcher.h"
24 #include "ppapi/proxy/ppapi_messages.h"
25 #include "ppapi/shared_impl/ppapi_globals.h"
26 #include "ppapi/shared_impl/resource.h"
27 #include "ppapi/shared_impl/resource_tracker.h"
34 // Given an error code and a handle result from a Pepper API call, converts to a
35 // PlatformFileForTransit by sharing with the other side, closing the original
36 // handle, possibly also updating the error value if an error occurred.
37 IPC::PlatformFileForTransit
PlatformFileToPlatformFileForTransit(
38 Dispatcher
* dispatcher
,
40 base::PlatformFile file
) {
42 return IPC::InvalidPlatformFileForTransit();
43 IPC::PlatformFileForTransit out_handle
=
44 dispatcher
->ShareHandleWithRemote(file
, true);
45 if (out_handle
== IPC::InvalidPlatformFileForTransit())
46 *error
= PP_ERROR_NOACCESS
;
50 void FreeDirContents(PP_Instance
/* instance */,
51 PP_DirContents_Dev
* contents
) {
52 for (int32_t i
= 0; i
< contents
->count
; ++i
)
53 delete[] contents
->entries
[i
].name
;
54 delete[] contents
->entries
;
60 // ModuleLocalThreadAdapter ----------------------------------------------------
61 // TODO(yzshen): Refactor to use IPC::SyncMessageFilter.
62 class ModuleLocalThreadAdapter
63 : public base::RefCountedThreadSafe
<ModuleLocalThreadAdapter
> {
66 ModuleLocalThreadAdapter();
68 void AddInstanceRouting(PP_Instance instance
, Dispatcher
* dispatcher
);
69 void ClearInstanceRouting(PP_Instance instance
);
70 void ClearFilter(Dispatcher
* dispatcher
, Filter
* filter
);
72 bool OnModuleLocalMessageReceived(const IPC::Message
& msg
);
74 // Called on the I/O thread when the channel is being destroyed and the
75 // given message will never be issued a reply.
76 void OnModuleLocalMessageFailed(int message_id
);
78 bool Send(PP_Instance instance
, IPC::Message
* msg
);
81 class Filter
: public IPC::ChannelProxy::MessageFilter
{
83 explicit Filter(Dispatcher
* dispatcher
);
86 void Send(IPC::Message
* msg
);
88 virtual void OnFilterAdded(IPC::Channel
* channel
);
89 virtual void OnFilterRemoved();
90 virtual bool OnMessageReceived(const IPC::Message
& message
);
93 // DO NOT DEREFERENCE! This is used only for tracking.
94 Dispatcher
* dispatcher_
;
96 IPC::Channel
* channel_
;
98 // Holds the IPC messages that were sent before the channel was connected.
99 // These will be sent ASAP.
100 std::vector
<IPC::Message
*> pre_connect_pending_messages_
;
102 // Holds the IDs of the sync messages we're currently waiting on for this
103 // channel. This tracking allows us to cancel those requests if the
104 // remote process crashes and we're cleaning up this filter (without just
105 // deadlocking the waiting thread(s).
106 std::set
<int> pending_requests_for_filter_
;
109 void SendFromIOThread(Dispatcher
* dispatcher
, IPC::Message
* msg
);
111 // Internal version of OnModuleLocalMessageFailed which assumes the lock
113 void OnModuleLocalMessageFailedLocked(int message_id
);
117 scoped_refptr
<base::MessageLoopProxy
> main_thread_
;
119 // Will be NULL before an instance routing is added.
120 scoped_refptr
<base::MessageLoopProxy
> io_thread_
;
122 typedef std::map
<PP_Instance
, Dispatcher
*> InstanceToDispatcher
;
123 InstanceToDispatcher instance_to_dispatcher_
;
125 // The filters are owned by the channel.
126 typedef std::map
<Dispatcher
*, Filter
*> DispatcherToFilter
;
127 DispatcherToFilter dispatcher_to_filter_
;
129 // Tracks all messages with currently waiting threads. This does not own
130 // the pointer, the pointer lifetime is managed by Send().
131 typedef std::map
<int, IPC::PendingSyncMsg
*> SyncRequestMap
;
132 SyncRequestMap pending_sync_requests_
;
135 ModuleLocalThreadAdapter
* g_module_local_thread_adapter
= NULL
;
137 ModuleLocalThreadAdapter::Filter::Filter(Dispatcher
* dispatcher
)
138 : dispatcher_(dispatcher
), channel_(NULL
) {
141 ModuleLocalThreadAdapter::Filter::~Filter() {
144 void ModuleLocalThreadAdapter::Filter::Send(IPC::Message
* msg
) {
146 int message_id
= IPC::SyncMessage::GetMessageId(*msg
);
147 if (channel_
->Send(msg
))
148 pending_requests_for_filter_
.insert(message_id
);
149 else // Message lost, notify adapter so it can unblock.
150 g_module_local_thread_adapter
->OnModuleLocalMessageFailed(message_id
);
152 // No channel, save this message for when it's connected.
153 pre_connect_pending_messages_
.push_back(msg
);
157 void ModuleLocalThreadAdapter::Filter::OnFilterAdded(IPC::Channel
* channel
) {
161 // Now that we have a channel, process all pending messages.
162 for (size_t i
= 0; i
< pre_connect_pending_messages_
.size(); i
++)
163 Send(pre_connect_pending_messages_
[i
]);
164 pre_connect_pending_messages_
.clear();
167 void ModuleLocalThreadAdapter::Filter::OnFilterRemoved() {
170 g_module_local_thread_adapter
->ClearFilter(dispatcher_
, this);
172 for (std::set
<int>::iterator i
= pending_requests_for_filter_
.begin();
173 i
!= pending_requests_for_filter_
.end(); ++i
) {
174 g_module_local_thread_adapter
->OnModuleLocalMessageFailed(*i
);
178 bool ModuleLocalThreadAdapter::Filter::OnMessageReceived(
179 const IPC::Message
& message
) {
180 if (!message
.is_reply() ||
181 message
.routing_id() != API_ID_PPB_FLASH_FILE_MODULELOCAL
)
184 if (g_module_local_thread_adapter
->OnModuleLocalMessageReceived(message
)) {
185 // The message was consumed, this means we can remove the message ID from
186 // the list of messages this channel is waiting on.
187 pending_requests_for_filter_
.erase(IPC::SyncMessage::GetMessageId(message
));
193 ModuleLocalThreadAdapter::ModuleLocalThreadAdapter()
194 : main_thread_(base::MessageLoopProxy::current()) {
197 void ModuleLocalThreadAdapter::AddInstanceRouting(PP_Instance instance
,
198 Dispatcher
* dispatcher
) {
199 base::AutoLock
lock(lock_
);
201 // Now that we've had contact with a dispatcher, we can set up the IO thread.
202 DCHECK(main_thread_
->BelongsToCurrentThread());
203 if (!io_thread_
.get())
204 io_thread_
= dispatcher
->GetIPCMessageLoop();
206 // Set up the instance -> dispatcher routing.
207 DCHECK(instance_to_dispatcher_
.find(instance
) ==
208 instance_to_dispatcher_
.end());
209 instance_to_dispatcher_
[instance
] = dispatcher
;
211 DispatcherToFilter::iterator found_filter
=
212 dispatcher_to_filter_
.find(dispatcher
);
213 if (found_filter
== dispatcher_to_filter_
.end()) {
214 // Need to set up a filter for this dispatcher to intercept the messages.
215 Filter
* filter
= new Filter(dispatcher
);
216 dispatcher_to_filter_
[dispatcher
] = filter
;
217 dispatcher
->AddIOThreadMessageFilter(filter
);
221 void ModuleLocalThreadAdapter::ClearInstanceRouting(PP_Instance instance
) {
222 // The dispatcher->filter mapping is cleaned up by ClearFilter which is
223 // initiated by the channel.
224 instance_to_dispatcher_
.erase(instance
);
227 void ModuleLocalThreadAdapter::ClearFilter(Dispatcher
* dispatcher
,
229 // DANGER! Don't dereference the dispatcher, it's just used to identify
230 // which filter to remove. The dispatcher may not even exist any more.
232 // Since the dispatcher may be gone, there's a potential for ambiguity if
233 // another one is created on the main thread before this code runs on the
234 // I/O thread. So we check that the filter matches to avoid this rare case.
235 base::AutoLock
lock(lock_
);
236 if (dispatcher_to_filter_
[dispatcher
] == filter
)
237 dispatcher_to_filter_
.erase(dispatcher
);
240 bool ModuleLocalThreadAdapter::OnModuleLocalMessageReceived(
241 const IPC::Message
& msg
) {
242 base::AutoLock
lock(lock_
);
244 int message_id
= IPC::SyncMessage::GetMessageId(msg
);
245 SyncRequestMap::iterator found
= pending_sync_requests_
.find(message_id
);
246 if (found
== pending_sync_requests_
.end()) {
247 // Not waiting for this event. This will happen for sync messages to the
248 // main thread which use the "regular" sync channel code path.
252 IPC::PendingSyncMsg
& info
= *found
->second
;
254 if (!msg
.is_reply_error())
255 info
.deserializer
->SerializeOutputParameters(msg
);
256 info
.done_event
->Signal();
260 void ModuleLocalThreadAdapter::OnModuleLocalMessageFailed(int message_id
) {
261 base::AutoLock
lock(lock_
);
262 OnModuleLocalMessageFailedLocked(message_id
);
265 bool ModuleLocalThreadAdapter::Send(PP_Instance instance
, IPC::Message
* msg
) {
266 // Compute the dispatcher corresponding to this message.
267 Dispatcher
* dispatcher
= NULL
;
269 base::AutoLock
lock(lock_
);
270 InstanceToDispatcher::iterator found
=
271 instance_to_dispatcher_
.find(instance
);
272 if (found
== instance_to_dispatcher_
.end()) {
277 dispatcher
= found
->second
;
280 if (main_thread_
->BelongsToCurrentThread()) {
281 // Easy case: We're on the same thread as the dispatcher, so we don't need
282 // a lock to access it, and we can just use the normal sync channel stuff
283 // to handle the message. Actually, we MUST use the normal sync channel
284 // stuff since there may be incoming sync messages that need processing.
285 // The code below doesn't handle any nested message loops.
286 return dispatcher
->Send(msg
);
289 // Background thread case
290 // ----------------------
291 // 1. Generate tracking info, stick in pending_sync_messages_map.
292 // 2. Kick off the request. This is done on the I/O thread.
293 // 3. Filter on the I/O thread notices reply, writes the reply data and
294 // signals the event. We block on the event while this is happening.
295 // 4. Remove tracking info.
297 // Generate the tracking info. and copied
298 IPC::SyncMessage
* sync_msg
= static_cast<IPC::SyncMessage
*>(msg
);
299 int message_id
= IPC::SyncMessage::GetMessageId(*sync_msg
);
300 base::WaitableEvent
event(true, false);
301 scoped_ptr
<IPC::MessageReplyDeserializer
> deserializer(
302 sync_msg
->GetReplyDeserializer()); // We own this pointer once retrieved.
303 IPC::PendingSyncMsg
info(message_id
, deserializer
.get(), &event
);
305 // Add the tracking information to our map.
307 base::AutoLock
lock(lock_
);
308 pending_sync_requests_
[message_id
] = &info
;
311 // This is a bit dangerous. We use the dispatcher pointer as the routing
312 // ID for this message. While we don't dereference it, there is an
313 // exceedingly remote possibility that while this is going to the background
314 // thread the connection will be shut down and a new one will be created with
315 // a dispatcher at the same address. It could potentially get sent to a
316 // random place, but it should actually still work (since the Flash file
317 // operations are global).
318 io_thread_
->PostTask(FROM_HERE
,
319 base::Bind(&ModuleLocalThreadAdapter::SendFromIOThread
, this,
322 // Now we block the current thread waiting for the reply.
326 // Clear our tracking info for this message now that we're done.
327 base::AutoLock
lock(lock_
);
328 DCHECK(pending_sync_requests_
.find(message_id
) !=
329 pending_sync_requests_
.end());
330 pending_sync_requests_
.erase(message_id
);
336 void ModuleLocalThreadAdapter::SendFromIOThread(Dispatcher
* dispatcher
,
338 // DO NOT DEREFERENCE DISPATCHER. Used as a lookup only.
339 base::AutoLock
lock(lock_
);
340 DispatcherToFilter::iterator found
= dispatcher_to_filter_
.find(dispatcher
);
342 // The dispatcher could have been destroyed by the time we got here since
343 // we're on another thread. Need to unblock the caller.
344 if (found
== dispatcher_to_filter_
.end()) {
345 OnModuleLocalMessageFailedLocked(IPC::SyncMessage::GetMessageId(*msg
));
350 // Takes ownership of pointer.
351 found
->second
->Send(msg
);
354 void ModuleLocalThreadAdapter::OnModuleLocalMessageFailedLocked(
356 lock_
.AssertAcquired();
358 // Unblock the thread waiting for the message that will never come.
359 SyncRequestMap::iterator found
= pending_sync_requests_
.find(message_id
);
360 if (found
== pending_sync_requests_
.end()) {
364 found
->second
->done_event
->Signal();
367 // PPB_Flash_File_ModuleLocal --------------------------------------------------
371 bool CreateThreadAdapterForInstance(PP_Instance instance
) {
372 if (!g_module_local_thread_adapter
) {
373 g_module_local_thread_adapter
= new ModuleLocalThreadAdapter();
374 g_module_local_thread_adapter
->AddRef(); // Leaked, this object is global.
377 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
382 g_module_local_thread_adapter
->AddInstanceRouting(instance
, dispatcher
);
386 void ClearThreadAdapterForInstance(PP_Instance instance
) {
387 if (g_module_local_thread_adapter
)
388 g_module_local_thread_adapter
->ClearInstanceRouting(instance
);
391 int32_t OpenModuleLocalFile(PP_Instance instance
,
394 PP_FileHandle
* file
) {
395 if (!g_module_local_thread_adapter
)
396 return PP_ERROR_FAILED
;
398 int32_t result
= PP_ERROR_FAILED
;
399 IPC::PlatformFileForTransit transit
;
400 g_module_local_thread_adapter
->Send(instance
,
401 new PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile(
402 API_ID_PPB_FLASH_FILE_MODULELOCAL
,
403 instance
, path
, mode
, &transit
, &result
));
404 *file
= IPC::PlatformFileForTransitToPlatformFile(transit
);
408 int32_t RenameModuleLocalFile(PP_Instance instance
,
409 const char* from_path
,
410 const char* to_path
) {
411 if (!g_module_local_thread_adapter
)
412 return PP_ERROR_FAILED
;
414 int32_t result
= PP_ERROR_FAILED
;
415 g_module_local_thread_adapter
->Send(instance
,
416 new PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile(
417 API_ID_PPB_FLASH_FILE_MODULELOCAL
,
418 instance
, from_path
, to_path
, &result
));
422 int32_t DeleteModuleLocalFileOrDir(PP_Instance instance
,
425 if (!g_module_local_thread_adapter
)
426 return PP_ERROR_FAILED
;
428 int32_t result
= PP_ERROR_FAILED
;
429 g_module_local_thread_adapter
->Send(instance
,
430 new PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir(
431 API_ID_PPB_FLASH_FILE_MODULELOCAL
,
432 instance
, path
, recursive
, &result
));
436 int32_t CreateModuleLocalDir(PP_Instance instance
, const char* path
) {
437 if (!g_module_local_thread_adapter
)
438 return PP_ERROR_FAILED
;
440 int32_t result
= PP_ERROR_FAILED
;
441 g_module_local_thread_adapter
->Send(instance
,
442 new PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir(
443 API_ID_PPB_FLASH_FILE_MODULELOCAL
, instance
, path
, &result
));
447 int32_t QueryModuleLocalFile(PP_Instance instance
,
450 if (!g_module_local_thread_adapter
)
451 return PP_ERROR_FAILED
;
453 int32_t result
= PP_ERROR_FAILED
;
454 g_module_local_thread_adapter
->Send(instance
,
455 new PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile(
456 API_ID_PPB_FLASH_FILE_MODULELOCAL
, instance
, path
,
461 int32_t GetModuleLocalDirContents(PP_Instance instance
,
463 PP_DirContents_Dev
** contents
) {
464 if (!g_module_local_thread_adapter
)
465 return PP_ERROR_FAILED
;
467 int32_t result
= PP_ERROR_FAILED
;
468 std::vector
<SerializedDirEntry
> entries
;
469 g_module_local_thread_adapter
->Send(instance
,
470 new PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents(
471 API_ID_PPB_FLASH_FILE_MODULELOCAL
,
472 instance
, path
, &entries
, &result
));
477 // Copy the serialized dir entries to the output struct.
478 *contents
= new PP_DirContents_Dev
;
479 (*contents
)->count
= static_cast<int32_t>(entries
.size());
480 (*contents
)->entries
= new PP_DirEntry_Dev
[entries
.size()];
481 for (size_t i
= 0; i
< entries
.size(); i
++) {
482 const SerializedDirEntry
& source
= entries
[i
];
483 PP_DirEntry_Dev
* dest
= &(*contents
)->entries
[i
];
485 char* name_copy
= new char[source
.name
.size() + 1];
486 memcpy(name_copy
, source
.name
.c_str(), source
.name
.size() + 1);
487 dest
->name
= name_copy
;
488 dest
->is_dir
= PP_FromBool(source
.is_dir
);
494 const PPB_Flash_File_ModuleLocal flash_file_modulelocal_interface
= {
495 &CreateThreadAdapterForInstance
,
496 &ClearThreadAdapterForInstance
,
497 &OpenModuleLocalFile
,
498 &RenameModuleLocalFile
,
499 &DeleteModuleLocalFileOrDir
,
500 &CreateModuleLocalDir
,
501 &QueryModuleLocalFile
,
502 &GetModuleLocalDirContents
,
506 InterfaceProxy
* CreateFlashFileModuleLocalProxy(Dispatcher
* dispatcher
) {
507 return new PPB_Flash_File_ModuleLocal_Proxy(dispatcher
);
512 PPB_Flash_File_ModuleLocal_Proxy::PPB_Flash_File_ModuleLocal_Proxy(
513 Dispatcher
* dispatcher
)
514 : InterfaceProxy(dispatcher
),
515 ppb_flash_file_module_local_impl_(NULL
) {
516 if (!dispatcher
->IsPlugin()) {
517 ppb_flash_file_module_local_impl_
=
518 static_cast<const PPB_Flash_File_ModuleLocal
*>(
519 dispatcher
->local_get_interface()(
520 PPB_FLASH_FILE_MODULELOCAL_INTERFACE
));
524 PPB_Flash_File_ModuleLocal_Proxy::~PPB_Flash_File_ModuleLocal_Proxy() {
528 const PPB_Flash_File_ModuleLocal
*
529 PPB_Flash_File_ModuleLocal_Proxy::GetInterface() {
530 return &flash_file_modulelocal_interface
;
533 bool PPB_Flash_File_ModuleLocal_Proxy::OnMessageReceived(
534 const IPC::Message
& msg
) {
536 IPC_BEGIN_MESSAGE_MAP(PPB_Flash_File_ModuleLocal_Proxy
, msg
)
537 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile
,
539 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile
,
541 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir
,
542 OnMsgDeleteFileOrDir
)
543 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir
,
545 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile
,
547 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents
,
549 IPC_MESSAGE_UNHANDLED(handled
= false)
550 IPC_END_MESSAGE_MAP()
551 // TODO(brettw) handle bad messages!
555 void PPB_Flash_File_ModuleLocal_Proxy::OnMsgOpenFile(
556 PP_Instance instance
,
557 const std::string
& path
,
559 IPC::PlatformFileForTransit
* file_handle
,
561 base::PlatformFile file
;
562 *result
= ppb_flash_file_module_local_impl_
->OpenFile(
563 instance
, path
.c_str(), mode
, &file
);
564 *file_handle
= PlatformFileToPlatformFileForTransit(
565 dispatcher(), result
, file
);
568 void PPB_Flash_File_ModuleLocal_Proxy::OnMsgRenameFile(
569 PP_Instance instance
,
570 const std::string
& from_path
,
571 const std::string
& to_path
,
573 *result
= ppb_flash_file_module_local_impl_
->RenameFile(
574 instance
, from_path
.c_str(), to_path
.c_str());
577 void PPB_Flash_File_ModuleLocal_Proxy::OnMsgDeleteFileOrDir(
578 PP_Instance instance
,
579 const std::string
& path
,
582 *result
= ppb_flash_file_module_local_impl_
->DeleteFileOrDir(
583 instance
, path
.c_str(), recursive
);
586 void PPB_Flash_File_ModuleLocal_Proxy::OnMsgCreateDir(PP_Instance instance
,
587 const std::string
& path
,
589 *result
= ppb_flash_file_module_local_impl_
->CreateDir(
590 instance
, path
.c_str());
593 void PPB_Flash_File_ModuleLocal_Proxy::OnMsgQueryFile(PP_Instance instance
,
594 const std::string
& path
,
597 *result
= ppb_flash_file_module_local_impl_
->QueryFile(
598 instance
, path
.c_str(), info
);
601 void PPB_Flash_File_ModuleLocal_Proxy::OnMsgGetDirContents(
602 PP_Instance instance
,
603 const std::string
& path
,
604 std::vector
<SerializedDirEntry
>* entries
,
606 PP_DirContents_Dev
* contents
= NULL
;
607 *result
= ppb_flash_file_module_local_impl_
->GetDirContents(
608 instance
, path
.c_str(), &contents
);
609 if (*result
!= PP_OK
)
612 // Convert the list of entries to the serialized version.
613 entries
->resize(contents
->count
);
614 for (int32_t i
= 0; i
< contents
->count
; i
++) {
615 (*entries
)[i
].name
.assign(contents
->entries
[i
].name
);
616 (*entries
)[i
].is_dir
= PP_ToBool(contents
->entries
[i
].is_dir
);
618 ppb_flash_file_module_local_impl_
->FreeDirContents(instance
, contents
);
621 // PPB_Flash_File_FileRef ------------------------------------------------------
625 int32_t OpenFileRefFile(PP_Resource file_ref_id
,
627 PP_FileHandle
* file
) {
629 PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_id
);
631 return PP_ERROR_BADRESOURCE
;
633 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForResource(file_ref
);
635 return PP_ERROR_BADARGUMENT
;
637 int32_t result
= PP_ERROR_FAILED
;
638 IPC::PlatformFileForTransit transit
;
639 dispatcher
->Send(new PpapiHostMsg_PPBFlashFile_FileRef_OpenFile(
640 API_ID_PPB_FLASH_FILE_FILEREF
,
641 file_ref
->host_resource(), mode
, &transit
, &result
));
642 *file
= IPC::PlatformFileForTransitToPlatformFile(transit
);
646 int32_t QueryFileRefFile(PP_Resource file_ref_id
,
649 PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_id
);
651 return PP_ERROR_BADRESOURCE
;
653 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForResource(file_ref
);
655 return PP_ERROR_BADARGUMENT
;
657 int32_t result
= PP_ERROR_FAILED
;
658 dispatcher
->Send(new PpapiHostMsg_PPBFlashFile_FileRef_QueryFile(
659 API_ID_PPB_FLASH_FILE_FILEREF
,
660 file_ref
->host_resource(), info
, &result
));
664 const PPB_Flash_File_FileRef flash_file_fileref_interface
= {
669 InterfaceProxy
* CreateFlashFileFileRefProxy(Dispatcher
* dispatcher
) {
670 return new PPB_Flash_File_FileRef_Proxy(dispatcher
);
675 PPB_Flash_File_FileRef_Proxy::PPB_Flash_File_FileRef_Proxy(
676 Dispatcher
* dispatcher
)
677 : InterfaceProxy(dispatcher
),
678 ppb_flash_file_fileref_impl_(NULL
) {
679 if (!dispatcher
->IsPlugin()) {
680 ppb_flash_file_fileref_impl_
= static_cast<const PPB_Flash_File_FileRef
*>(
681 dispatcher
->local_get_interface()(PPB_FLASH_FILE_FILEREF_INTERFACE
));
685 PPB_Flash_File_FileRef_Proxy::~PPB_Flash_File_FileRef_Proxy() {
689 const PPB_Flash_File_FileRef
* PPB_Flash_File_FileRef_Proxy::GetInterface() {
690 return &flash_file_fileref_interface
;
693 bool PPB_Flash_File_FileRef_Proxy::OnMessageReceived(
694 const IPC::Message
& msg
) {
696 IPC_BEGIN_MESSAGE_MAP(PPB_Flash_File_FileRef_Proxy
, msg
)
697 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_FileRef_OpenFile
,
699 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_FileRef_QueryFile
,
701 IPC_MESSAGE_UNHANDLED(handled
= false)
702 IPC_END_MESSAGE_MAP()
703 // TODO(brettw) handle bad messages!
707 void PPB_Flash_File_FileRef_Proxy::OnMsgOpenFile(
708 const HostResource
& host_resource
,
710 IPC::PlatformFileForTransit
* file_handle
,
712 base::PlatformFile file
;
713 *result
= ppb_flash_file_fileref_impl_
->OpenFile(
714 host_resource
.host_resource(), mode
, &file
);
715 *file_handle
= PlatformFileToPlatformFileForTransit(
716 dispatcher(), result
, file
);
719 void PPB_Flash_File_FileRef_Proxy::OnMsgQueryFile(
720 const HostResource
& host_resource
,
723 *result
= ppb_flash_file_fileref_impl_
->QueryFile(
724 host_resource
.host_resource(), info
);