diff options
25 files changed, 1180 insertions, 1229 deletions
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index d8d5728..dd43216 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -88,8 +88,6 @@ 'proxy/ppb_file_ref_proxy.h', 'proxy/ppb_file_system_proxy.cc', 'proxy/ppb_file_system_proxy.h', - 'proxy/ppb_flash_file_proxy.cc', - 'proxy/ppb_flash_file_proxy.h', 'proxy/ppb_flash_proxy.cc', 'proxy/ppb_flash_proxy.h', 'proxy/ppb_flash_menu_proxy.cc', diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi index 3d7ea8a..c39a711 100644 --- a/ppapi/ppapi_shared.gypi +++ b/ppapi/ppapi_shared.gypi @@ -183,6 +183,8 @@ 'thunk/ppb_find_thunk.cc', 'thunk/ppb_flash_api.h', 'thunk/ppb_flash_clipboard_thunk.cc', + 'thunk/ppb_flash_file_fileref_thunk.cc', + 'thunk/ppb_flash_file_modulelocal_thunk.cc', 'thunk/ppb_flash_fullscreen_thunk.cc', 'thunk/ppb_flash_menu_api.h', 'thunk/ppb_flash_menu_thunk.cc', diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 530ff26..281c557 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -79,7 +79,6 @@ #include "ppapi/proxy/ppb_file_io_proxy.h" #include "ppapi/proxy/ppb_file_ref_proxy.h" #include "ppapi/proxy/ppb_file_system_proxy.h" -#include "ppapi/proxy/ppb_flash_file_proxy.h" #include "ppapi/proxy/ppb_flash_menu_proxy.h" #include "ppapi/proxy/ppb_flash_message_loop_proxy.h" #include "ppapi/proxy/ppb_flash_proxy.h" @@ -215,8 +214,6 @@ InterfaceList::InterfaceList() { PPB_Var_Shared::GetVarInterface1_0()); #if !defined(OS_NACL) - AddFlashInterfaces(); - // PPB (browser) interfaces. // Do not add more stuff here, they should be added to interface_list*.h // TODO(brettw) remove these. @@ -301,34 +298,6 @@ const void* InterfaceList::GetInterfaceForPPP(const std::string& name) const { return found->second.iface; } -#if !defined(OS_NACL) -void InterfaceList::AddFlashInterfaces() { - AddProxy(API_ID_PPB_FLASH_FILE_FILEREF, - &ProxyFactory<PPB_Flash_File_FileRef_Proxy>); - AddPPB(PPB_FLASH_FILE_FILEREF_INTERFACE, API_ID_PPB_FLASH_FILE_FILEREF, - PPB_Flash_File_FileRef_Proxy::GetInterface()); - - AddProxy(API_ID_PPB_FLASH_FILE_MODULELOCAL, - &ProxyFactory<PPB_Flash_File_ModuleLocal_Proxy>); - AddPPB(PPB_FLASH_FILE_MODULELOCAL_INTERFACE, - API_ID_PPB_FLASH_FILE_MODULELOCAL, - PPB_Flash_File_ModuleLocal_Proxy::GetInterface()); - - AddProxy(API_ID_PPB_FLASH_MENU, &ProxyFactory<PPB_Flash_Menu_Proxy>); - AddPPB(PPB_FLASH_MENU_INTERFACE_0_2, API_ID_PPB_FLASH_MENU, - thunk::GetPPB_Flash_Menu_0_2_Thunk()); - - AddProxy(API_ID_PPB_FLASH_MESSAGELOOP, - &ProxyFactory<PPB_Flash_MessageLoop_Proxy>); - AddPPB(PPB_FLASH_MESSAGELOOP_INTERFACE_0_1, API_ID_PPB_FLASH_MESSAGELOOP, - thunk::GetPPB_Flash_MessageLoop_0_1_Thunk()); - - // Only add the interface; PPB_TCPSocket_Private provides the API ID's proxy. - AddPPB(PPB_FLASH_TCPSOCKET_INTERFACE_0_2, API_ID_PPB_TCPSOCKET_PRIVATE, - thunk::GetPPB_TCPSocket_Private_0_3_Thunk()); -} -#endif // !defined(OS_NACL) - void InterfaceList::AddProxy(ApiID id, InterfaceProxy::Factory factory) { // For interfaces with no corresponding _Proxy objects, the macros will diff --git a/ppapi/proxy/interface_list.h b/ppapi/proxy/interface_list.h index 82f70da..3863234 100644 --- a/ppapi/proxy/interface_list.h +++ b/ppapi/proxy/interface_list.h @@ -52,14 +52,6 @@ class InterfaceList { typedef std::map<std::string, InterfaceInfo> NameToInterfaceInfoMap; -#if !defined(OS_NACL) - // Registers the Flash-specific interfaces. - // - // TODO(brettw) these should be moved somewhere separately so we can compile - // the proxy for NaCl without Flash interface support. - void AddFlashInterfaces(); -#endif // !defined(OS_NACL) - void AddProxy(ApiID id, InterfaceProxy::Factory factory); void AddPPB(const char* name, ApiID id, const void* iface); diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 412aec0..bc058f3 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -1192,51 +1192,49 @@ IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFlash_WriteClipboardData, int /* clipboard_type */, std::vector<int> /* formats */, std::vector<ppapi::proxy::SerializedVar> /* data */) - -// PPB_Flash_File_FileRef. -IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBFlashFile_FileRef_OpenFile, - ppapi::HostResource /* file_ref */, - int32_t /* mode */, - IPC::PlatformFileForTransit /* file_handle */, - int32_t /* result */) -IPC_SYNC_MESSAGE_ROUTED1_2(PpapiHostMsg_PPBFlashFile_FileRef_QueryFile, - ppapi::HostResource /* file_ref */, - PP_FileInfo /* info */, - int32_t /* result */) - -// PPB_Flash_File_ModuleLocal. -IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile, +IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBFlash_OpenFile, PP_Instance /* instance */, std::string /* path */, int32_t /* mode */, IPC::PlatformFileForTransit /* file_handle */, int32_t /* result */) -IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile, +IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFlash_RenameFile, PP_Instance /* instance */, std::string /* path_from */, std::string /* path_to */, int32_t /* result */) IPC_SYNC_MESSAGE_ROUTED3_1( - PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir, + PpapiHostMsg_PPBFlash_DeleteFileOrDir, PP_Instance /* instance */, std::string /* path */, PP_Bool /* recursive */, int32_t /* result */) -IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir, +IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlash_CreateDir, PP_Instance /* instance */, std::string /* path */, int32_t /* result */) -IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile, +IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBFlash_QueryFile, PP_Instance /* instance */, std::string /* path */, PP_FileInfo /* info */, int32_t /* result */) IPC_SYNC_MESSAGE_ROUTED2_2( - PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents, + PpapiHostMsg_PPBFlash_GetDirContents, PP_Instance /* instance */, std::string /* path */, std::vector<ppapi::proxy::SerializedDirEntry> /* entries */, int32_t /* result */) +IPC_SYNC_MESSAGE_ROUTED3_2(PpapiHostMsg_PPBFlash_OpenFileRef, + PP_Instance /* instance */, + ppapi::HostResource /* file_ref */, + int32_t /* mode */, + IPC::PlatformFileForTransit /* file_handle */, + int32_t /* result */) +IPC_SYNC_MESSAGE_ROUTED2_2(PpapiHostMsg_PPBFlash_QueryFileRef, + PP_Instance /* instance */, + ppapi::HostResource /* file_ref */, + PP_FileInfo /* info */, + int32_t /* result */) // PPB_Flash_Menu IPC_SYNC_MESSAGE_ROUTED2_1(PpapiHostMsg_PPBFlashMenu_Create, diff --git a/ppapi/proxy/ppb_flash_file_proxy.cc b/ppapi/proxy/ppb_flash_file_proxy.cc deleted file mode 100644 index 0849053..0000000 --- a/ppapi/proxy/ppb_flash_file_proxy.cc +++ /dev/null @@ -1,728 +0,0 @@ -// Copyright (c) 2011 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/ppb_flash_file_proxy.h" - -#include <map> -#include <set> -#include <vector> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop_proxy.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "build/build_config.h" -#include "ipc/ipc_channel_proxy.h" -#include "ipc/ipc_message.h" -#include "ipc/ipc_sync_message.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/c/pp_file_info.h" -#include "ppapi/c/private/ppb_flash_file.h" -#include "ppapi/proxy/plugin_dispatcher.h" -#include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/shared_impl/ppapi_globals.h" -#include "ppapi/shared_impl/resource.h" -#include "ppapi/shared_impl/resource_tracker.h" - -namespace ppapi { -namespace proxy { - -namespace { - -// Given an error code and a handle result from a Pepper API call, converts to a -// PlatformFileForTransit by sharing with the other side, closing the original -// handle, possibly also updating the error value if an error occurred. -IPC::PlatformFileForTransit PlatformFileToPlatformFileForTransit( - Dispatcher* dispatcher, - int32_t* error, - base::PlatformFile file) { - if (*error != PP_OK) - return IPC::InvalidPlatformFileForTransit(); - IPC::PlatformFileForTransit out_handle = - dispatcher->ShareHandleWithRemote(file, true); - if (out_handle == IPC::InvalidPlatformFileForTransit()) - *error = PP_ERROR_NOACCESS; - return out_handle; -} - -void FreeDirContents(PP_Instance /* instance */, - PP_DirContents_Dev* contents) { - for (int32_t i = 0; i < contents->count; ++i) - delete[] contents->entries[i].name; - delete[] contents->entries; - delete contents; -} - -} // namespace - -// ModuleLocalThreadAdapter ---------------------------------------------------- -// TODO(yzshen): Refactor to use IPC::SyncMessageFilter. -class ModuleLocalThreadAdapter - : public base::RefCountedThreadSafe<ModuleLocalThreadAdapter> { - class Filter; - public: - ModuleLocalThreadAdapter(); - - void AddInstanceRouting(PP_Instance instance, Dispatcher* dispatcher); - void ClearInstanceRouting(PP_Instance instance); - void ClearFilter(Dispatcher* dispatcher, Filter* filter); - - bool OnModuleLocalMessageReceived(const IPC::Message& msg); - - // Called on the I/O thread when the channel is being destroyed and the - // given message will never be issued a reply. - void OnModuleLocalMessageFailed(int message_id); - - bool Send(PP_Instance instance, IPC::Message* msg); - - private: - class Filter : public IPC::ChannelProxy::MessageFilter { - public: - explicit Filter(Dispatcher* dispatcher); - ~Filter(); - - void Send(IPC::Message* msg); - - virtual void OnFilterAdded(IPC::Channel* channel); - virtual void OnFilterRemoved(); - virtual bool OnMessageReceived(const IPC::Message& message); - - private: - // DO NOT DEREFERENCE! This is used only for tracking. - Dispatcher* dispatcher_; - - IPC::Channel* channel_; - - // Holds the IPC messages that were sent before the channel was connected. - // These will be sent ASAP. - std::vector<IPC::Message*> pre_connect_pending_messages_; - - // Holds the IDs of the sync messages we're currently waiting on for this - // channel. This tracking allows us to cancel those requests if the - // remote process crashes and we're cleaning up this filter (without just - // deadlocking the waiting thread(s). - std::set<int> pending_requests_for_filter_; - }; - - void SendFromIOThread(Dispatcher* dispatcher, IPC::Message* msg); - - // Internal version of OnModuleLocalMessageFailed which assumes the lock - // is already held. - void OnModuleLocalMessageFailedLocked(int message_id); - - base::Lock lock_; - - scoped_refptr<base::MessageLoopProxy> main_thread_; - - // Will be NULL before an instance routing is added. - scoped_refptr<base::MessageLoopProxy> io_thread_; - - typedef std::map<PP_Instance, Dispatcher*> InstanceToDispatcher; - InstanceToDispatcher instance_to_dispatcher_; - - // The filters are owned by the channel. - typedef std::map<Dispatcher*, Filter*> DispatcherToFilter; - DispatcherToFilter dispatcher_to_filter_; - - // Tracks all messages with currently waiting threads. This does not own - // the pointer, the pointer lifetime is managed by Send(). - typedef std::map<int, IPC::PendingSyncMsg*> SyncRequestMap; - SyncRequestMap pending_sync_requests_; -}; - -ModuleLocalThreadAdapter* g_module_local_thread_adapter = NULL; - -ModuleLocalThreadAdapter::Filter::Filter(Dispatcher* dispatcher) - : dispatcher_(dispatcher), channel_(NULL) { -} - -ModuleLocalThreadAdapter::Filter::~Filter() { -} - -void ModuleLocalThreadAdapter::Filter::Send(IPC::Message* msg) { - if (channel_) { - int message_id = IPC::SyncMessage::GetMessageId(*msg); - if (channel_->Send(msg)) - pending_requests_for_filter_.insert(message_id); - else // Message lost, notify adapter so it can unblock. - g_module_local_thread_adapter->OnModuleLocalMessageFailed(message_id); - } else { - // No channel, save this message for when it's connected. - pre_connect_pending_messages_.push_back(msg); - } -} - -void ModuleLocalThreadAdapter::Filter::OnFilterAdded(IPC::Channel* channel) { - DCHECK(!channel_); - channel_ = channel; - - // Now that we have a channel, process all pending messages. - for (size_t i = 0; i < pre_connect_pending_messages_.size(); i++) - Send(pre_connect_pending_messages_[i]); - pre_connect_pending_messages_.clear(); -} - -void ModuleLocalThreadAdapter::Filter::OnFilterRemoved() { - DCHECK(channel_); - channel_ = NULL; - g_module_local_thread_adapter->ClearFilter(dispatcher_, this); - - for (std::set<int>::iterator i = pending_requests_for_filter_.begin(); - i != pending_requests_for_filter_.end(); ++i) { - g_module_local_thread_adapter->OnModuleLocalMessageFailed(*i); - } -} - -bool ModuleLocalThreadAdapter::Filter::OnMessageReceived( - const IPC::Message& message) { - if (!message.is_reply() || - message.routing_id() != API_ID_PPB_FLASH_FILE_MODULELOCAL) - return false; - - if (g_module_local_thread_adapter->OnModuleLocalMessageReceived(message)) { - // The message was consumed, this means we can remove the message ID from - // the list of messages this channel is waiting on. - pending_requests_for_filter_.erase(IPC::SyncMessage::GetMessageId(message)); - return true; - } - return false; -} - -ModuleLocalThreadAdapter::ModuleLocalThreadAdapter() - : main_thread_(base::MessageLoopProxy::current()) { -} - -void ModuleLocalThreadAdapter::AddInstanceRouting(PP_Instance instance, - Dispatcher* dispatcher) { - base::AutoLock lock(lock_); - - // Now that we've had contact with a dispatcher, we can set up the IO thread. - DCHECK(main_thread_->BelongsToCurrentThread()); - if (!io_thread_.get()) - io_thread_ = dispatcher->GetIPCMessageLoop(); - - // Set up the instance -> dispatcher routing. - DCHECK(instance_to_dispatcher_.find(instance) == - instance_to_dispatcher_.end()); - instance_to_dispatcher_[instance] = dispatcher; - - DispatcherToFilter::iterator found_filter = - dispatcher_to_filter_.find(dispatcher); - if (found_filter == dispatcher_to_filter_.end()) { - // Need to set up a filter for this dispatcher to intercept the messages. - Filter* filter = new Filter(dispatcher); - dispatcher_to_filter_[dispatcher] = filter; - dispatcher->AddIOThreadMessageFilter(filter); - } -} - -void ModuleLocalThreadAdapter::ClearInstanceRouting(PP_Instance instance) { - // The dispatcher->filter mapping is cleaned up by ClearFilter which is - // initiated by the channel. - instance_to_dispatcher_.erase(instance); -} - -void ModuleLocalThreadAdapter::ClearFilter(Dispatcher* dispatcher, - Filter* filter) { - // DANGER! Don't dereference the dispatcher, it's just used to identify - // which filter to remove. The dispatcher may not even exist any more. - // - // Since the dispatcher may be gone, there's a potential for ambiguity if - // another one is created on the main thread before this code runs on the - // I/O thread. So we check that the filter matches to avoid this rare case. - base::AutoLock lock(lock_); - if (dispatcher_to_filter_[dispatcher] == filter) - dispatcher_to_filter_.erase(dispatcher); -} - -bool ModuleLocalThreadAdapter::OnModuleLocalMessageReceived( - const IPC::Message& msg) { - base::AutoLock lock(lock_); - - int message_id = IPC::SyncMessage::GetMessageId(msg); - SyncRequestMap::iterator found = pending_sync_requests_.find(message_id); - if (found == pending_sync_requests_.end()) { - // Not waiting for this event. This will happen for sync messages to the - // main thread which use the "regular" sync channel code path. - return false; - } - - IPC::PendingSyncMsg& info = *found->second; - - if (!msg.is_reply_error()) - info.deserializer->SerializeOutputParameters(msg); - info.done_event->Signal(); - return true; -} - -void ModuleLocalThreadAdapter::OnModuleLocalMessageFailed(int message_id) { - base::AutoLock lock(lock_); - OnModuleLocalMessageFailedLocked(message_id); -} - -bool ModuleLocalThreadAdapter::Send(PP_Instance instance, IPC::Message* msg) { - // Compute the dispatcher corresponding to this message. - Dispatcher* dispatcher = NULL; - { - base::AutoLock lock(lock_); - InstanceToDispatcher::iterator found = - instance_to_dispatcher_.find(instance); - if (found == instance_to_dispatcher_.end()) { - NOTREACHED(); - delete msg; - return false; - } - dispatcher = found->second; - } - - if (main_thread_->BelongsToCurrentThread()) { - // Easy case: We're on the same thread as the dispatcher, so we don't need - // a lock to access it, and we can just use the normal sync channel stuff - // to handle the message. Actually, we MUST use the normal sync channel - // stuff since there may be incoming sync messages that need processing. - // The code below doesn't handle any nested message loops. - return dispatcher->Send(msg); - } - - // Background thread case - // ---------------------- - // 1. Generate tracking info, stick in pending_sync_messages_map. - // 2. Kick off the request. This is done on the I/O thread. - // 3. Filter on the I/O thread notices reply, writes the reply data and - // signals the event. We block on the event while this is happening. - // 4. Remove tracking info. - - // Generate the tracking info. and copied - IPC::SyncMessage* sync_msg = static_cast<IPC::SyncMessage*>(msg); - int message_id = IPC::SyncMessage::GetMessageId(*sync_msg); - base::WaitableEvent event(true, false); - scoped_ptr<IPC::MessageReplyDeserializer> deserializer( - sync_msg->GetReplyDeserializer()); // We own this pointer once retrieved. - IPC::PendingSyncMsg info(message_id, deserializer.get(), &event); - - // Add the tracking information to our map. - { - base::AutoLock lock(lock_); - pending_sync_requests_[message_id] = &info; - } - - // This is a bit dangerous. We use the dispatcher pointer as the routing - // ID for this message. While we don't dereference it, there is an - // exceedingly remote possibility that while this is going to the background - // thread the connection will be shut down and a new one will be created with - // a dispatcher at the same address. It could potentially get sent to a - // random place, but it should actually still work (since the Flash file - // operations are global). - io_thread_->PostTask(FROM_HERE, - base::Bind(&ModuleLocalThreadAdapter::SendFromIOThread, this, - dispatcher, msg)); - - // Now we block the current thread waiting for the reply. - event.Wait(); - - { - // Clear our tracking info for this message now that we're done. - base::AutoLock lock(lock_); - DCHECK(pending_sync_requests_.find(message_id) != - pending_sync_requests_.end()); - pending_sync_requests_.erase(message_id); - } - - return true; -} - -void ModuleLocalThreadAdapter::SendFromIOThread(Dispatcher* dispatcher, - IPC::Message* msg) { - // DO NOT DEREFERENCE DISPATCHER. Used as a lookup only. - base::AutoLock lock(lock_); - DispatcherToFilter::iterator found = dispatcher_to_filter_.find(dispatcher); - - // The dispatcher could have been destroyed by the time we got here since - // we're on another thread. Need to unblock the caller. - if (found == dispatcher_to_filter_.end()) { - OnModuleLocalMessageFailedLocked(IPC::SyncMessage::GetMessageId(*msg)); - delete msg; - return; - } - - // Takes ownership of pointer. - found->second->Send(msg); -} - -void ModuleLocalThreadAdapter::OnModuleLocalMessageFailedLocked( - int message_id) { - lock_.AssertAcquired(); - - // Unblock the thread waiting for the message that will never come. - SyncRequestMap::iterator found = pending_sync_requests_.find(message_id); - if (found == pending_sync_requests_.end()) { - NOTREACHED(); - return; - } - found->second->done_event->Signal(); -} - -// PPB_Flash_File_ModuleLocal -------------------------------------------------- - -namespace { - -bool CreateThreadAdapterForInstance(PP_Instance instance) { - if (!g_module_local_thread_adapter) { - g_module_local_thread_adapter = new ModuleLocalThreadAdapter(); - g_module_local_thread_adapter->AddRef(); // Leaked, this object is global. - } - - PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); - if (!dispatcher) { - NOTREACHED(); - return false; - } - g_module_local_thread_adapter->AddInstanceRouting(instance, dispatcher); - return true; -} - -void ClearThreadAdapterForInstance(PP_Instance instance) { - if (g_module_local_thread_adapter) - g_module_local_thread_adapter->ClearInstanceRouting(instance); -} - -int32_t OpenModuleLocalFile(PP_Instance instance, - const char* path, - int32_t mode, - PP_FileHandle* file) { - if (!g_module_local_thread_adapter) - return PP_ERROR_FAILED; - - int32_t result = PP_ERROR_FAILED; - IPC::PlatformFileForTransit transit; - g_module_local_thread_adapter->Send(instance, - new PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile( - API_ID_PPB_FLASH_FILE_MODULELOCAL, - instance, path, mode, &transit, &result)); - *file = IPC::PlatformFileForTransitToPlatformFile(transit); - return result; -} - -int32_t RenameModuleLocalFile(PP_Instance instance, - const char* from_path, - const char* to_path) { - if (!g_module_local_thread_adapter) - return PP_ERROR_FAILED; - - int32_t result = PP_ERROR_FAILED; - g_module_local_thread_adapter->Send(instance, - new PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile( - API_ID_PPB_FLASH_FILE_MODULELOCAL, - instance, from_path, to_path, &result)); - return result; -} - -int32_t DeleteModuleLocalFileOrDir(PP_Instance instance, - const char* path, - PP_Bool recursive) { - if (!g_module_local_thread_adapter) - return PP_ERROR_FAILED; - - int32_t result = PP_ERROR_FAILED; - g_module_local_thread_adapter->Send(instance, - new PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir( - API_ID_PPB_FLASH_FILE_MODULELOCAL, - instance, path, recursive, &result)); - return result; -} - -int32_t CreateModuleLocalDir(PP_Instance instance, const char* path) { - if (!g_module_local_thread_adapter) - return PP_ERROR_FAILED; - - int32_t result = PP_ERROR_FAILED; - g_module_local_thread_adapter->Send(instance, - new PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir( - API_ID_PPB_FLASH_FILE_MODULELOCAL, instance, path, &result)); - return result; -} - -int32_t QueryModuleLocalFile(PP_Instance instance, - const char* path, - PP_FileInfo* info) { - if (!g_module_local_thread_adapter) - return PP_ERROR_FAILED; - - int32_t result = PP_ERROR_FAILED; - g_module_local_thread_adapter->Send(instance, - new PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile( - API_ID_PPB_FLASH_FILE_MODULELOCAL, instance, path, - info, &result)); - return result; -} - -int32_t GetModuleLocalDirContents(PP_Instance instance, - const char* path, - PP_DirContents_Dev** contents) { - if (!g_module_local_thread_adapter) - return PP_ERROR_FAILED; - - int32_t result = PP_ERROR_FAILED; - std::vector<SerializedDirEntry> entries; - g_module_local_thread_adapter->Send(instance, - new PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents( - API_ID_PPB_FLASH_FILE_MODULELOCAL, - instance, path, &entries, &result)); - - if (result != PP_OK) - return result; - - // Copy the serialized dir entries to the output struct. - *contents = new PP_DirContents_Dev; - (*contents)->count = static_cast<int32_t>(entries.size()); - (*contents)->entries = new PP_DirEntry_Dev[entries.size()]; - for (size_t i = 0; i < entries.size(); i++) { - const SerializedDirEntry& source = entries[i]; - PP_DirEntry_Dev* dest = &(*contents)->entries[i]; - - char* name_copy = new char[source.name.size() + 1]; - memcpy(name_copy, source.name.c_str(), source.name.size() + 1); - dest->name = name_copy; - dest->is_dir = PP_FromBool(source.is_dir); - } - - return result; -} - -const PPB_Flash_File_ModuleLocal flash_file_modulelocal_interface = { - &CreateThreadAdapterForInstance, - &ClearThreadAdapterForInstance, - &OpenModuleLocalFile, - &RenameModuleLocalFile, - &DeleteModuleLocalFileOrDir, - &CreateModuleLocalDir, - &QueryModuleLocalFile, - &GetModuleLocalDirContents, - &FreeDirContents, -}; - -InterfaceProxy* CreateFlashFileModuleLocalProxy(Dispatcher* dispatcher) { - return new PPB_Flash_File_ModuleLocal_Proxy(dispatcher); -} - -} // namespace - -PPB_Flash_File_ModuleLocal_Proxy::PPB_Flash_File_ModuleLocal_Proxy( - Dispatcher* dispatcher) - : InterfaceProxy(dispatcher), - ppb_flash_file_module_local_impl_(NULL) { - if (!dispatcher->IsPlugin()) { - ppb_flash_file_module_local_impl_ = - static_cast<const PPB_Flash_File_ModuleLocal*>( - dispatcher->local_get_interface()( - PPB_FLASH_FILE_MODULELOCAL_INTERFACE)); - } -} - -PPB_Flash_File_ModuleLocal_Proxy::~PPB_Flash_File_ModuleLocal_Proxy() { -} - -// static -const PPB_Flash_File_ModuleLocal* -PPB_Flash_File_ModuleLocal_Proxy::GetInterface() { - return &flash_file_modulelocal_interface; -} - -bool PPB_Flash_File_ModuleLocal_Proxy::OnMessageReceived( - const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PPB_Flash_File_ModuleLocal_Proxy, msg) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_OpenFile, - OnMsgOpenFile) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_RenameFile, - OnMsgRenameFile) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_DeleteFileOrDir, - OnMsgDeleteFileOrDir) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_CreateDir, - OnMsgCreateDir) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_QueryFile, - OnMsgQueryFile) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_ModuleLocal_GetDirContents, - OnMsgGetDirContents) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - // TODO(brettw) handle bad messages! - return handled; -} - -void PPB_Flash_File_ModuleLocal_Proxy::OnMsgOpenFile( - PP_Instance instance, - const std::string& path, - int32_t mode, - IPC::PlatformFileForTransit* file_handle, - int32_t* result) { - base::PlatformFile file; - *result = ppb_flash_file_module_local_impl_->OpenFile( - instance, path.c_str(), mode, &file); - *file_handle = PlatformFileToPlatformFileForTransit( - dispatcher(), result, file); -} - -void PPB_Flash_File_ModuleLocal_Proxy::OnMsgRenameFile( - PP_Instance instance, - const std::string& from_path, - const std::string& to_path, - int32_t* result) { - *result = ppb_flash_file_module_local_impl_->RenameFile( - instance, from_path.c_str(), to_path.c_str()); -} - -void PPB_Flash_File_ModuleLocal_Proxy::OnMsgDeleteFileOrDir( - PP_Instance instance, - const std::string& path, - PP_Bool recursive, - int32_t* result) { - *result = ppb_flash_file_module_local_impl_->DeleteFileOrDir( - instance, path.c_str(), recursive); -} - -void PPB_Flash_File_ModuleLocal_Proxy::OnMsgCreateDir(PP_Instance instance, - const std::string& path, - int32_t* result) { - *result = ppb_flash_file_module_local_impl_->CreateDir( - instance, path.c_str()); -} - -void PPB_Flash_File_ModuleLocal_Proxy::OnMsgQueryFile(PP_Instance instance, - const std::string& path, - PP_FileInfo* info, - int32_t* result) { - *result = ppb_flash_file_module_local_impl_->QueryFile( - instance, path.c_str(), info); -} - -void PPB_Flash_File_ModuleLocal_Proxy::OnMsgGetDirContents( - PP_Instance instance, - const std::string& path, - std::vector<SerializedDirEntry>* entries, - int32_t* result) { - PP_DirContents_Dev* contents = NULL; - *result = ppb_flash_file_module_local_impl_->GetDirContents( - instance, path.c_str(), &contents); - if (*result != PP_OK) - return; - - // Convert the list of entries to the serialized version. - entries->resize(contents->count); - for (int32_t i = 0; i < contents->count; i++) { - (*entries)[i].name.assign(contents->entries[i].name); - (*entries)[i].is_dir = PP_ToBool(contents->entries[i].is_dir); - } - ppb_flash_file_module_local_impl_->FreeDirContents(instance, contents); -} - -// PPB_Flash_File_FileRef ------------------------------------------------------ - -namespace { - -int32_t OpenFileRefFile(PP_Resource file_ref_id, - int32_t mode, - PP_FileHandle* file) { - Resource* file_ref = - PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_id); - if (!file_ref) - return PP_ERROR_BADRESOURCE; - - PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(file_ref); - if (!dispatcher) - return PP_ERROR_BADARGUMENT; - - int32_t result = PP_ERROR_FAILED; - IPC::PlatformFileForTransit transit; - dispatcher->Send(new PpapiHostMsg_PPBFlashFile_FileRef_OpenFile( - API_ID_PPB_FLASH_FILE_FILEREF, - file_ref->host_resource(), mode, &transit, &result)); - *file = IPC::PlatformFileForTransitToPlatformFile(transit); - return result; -} - -int32_t QueryFileRefFile(PP_Resource file_ref_id, - PP_FileInfo* info) { - Resource* file_ref = - PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_id); - if (!file_ref) - return PP_ERROR_BADRESOURCE; - - PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(file_ref); - if (!dispatcher) - return PP_ERROR_BADARGUMENT; - - int32_t result = PP_ERROR_FAILED; - dispatcher->Send(new PpapiHostMsg_PPBFlashFile_FileRef_QueryFile( - API_ID_PPB_FLASH_FILE_FILEREF, - file_ref->host_resource(), info, &result)); - return result; -} - -const PPB_Flash_File_FileRef flash_file_fileref_interface = { - &OpenFileRefFile, - &QueryFileRefFile, -}; - -InterfaceProxy* CreateFlashFileFileRefProxy(Dispatcher* dispatcher) { - return new PPB_Flash_File_FileRef_Proxy(dispatcher); -} - -} // namespace - -PPB_Flash_File_FileRef_Proxy::PPB_Flash_File_FileRef_Proxy( - Dispatcher* dispatcher) - : InterfaceProxy(dispatcher), - ppb_flash_file_fileref_impl_(NULL) { - if (!dispatcher->IsPlugin()) { - ppb_flash_file_fileref_impl_ = static_cast<const PPB_Flash_File_FileRef*>( - dispatcher->local_get_interface()(PPB_FLASH_FILE_FILEREF_INTERFACE)); - } -} - -PPB_Flash_File_FileRef_Proxy::~PPB_Flash_File_FileRef_Proxy() { -} - -// static -const PPB_Flash_File_FileRef* PPB_Flash_File_FileRef_Proxy::GetInterface() { - return &flash_file_fileref_interface; -} - -bool PPB_Flash_File_FileRef_Proxy::OnMessageReceived( - const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PPB_Flash_File_FileRef_Proxy, msg) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_FileRef_OpenFile, - OnMsgOpenFile) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashFile_FileRef_QueryFile, - OnMsgQueryFile) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - // TODO(brettw) handle bad messages! - return handled; -} - -void PPB_Flash_File_FileRef_Proxy::OnMsgOpenFile( - const HostResource& host_resource, - int32_t mode, - IPC::PlatformFileForTransit* file_handle, - int32_t* result) { - base::PlatformFile file; - *result = ppb_flash_file_fileref_impl_->OpenFile( - host_resource.host_resource(), mode, &file); - *file_handle = PlatformFileToPlatformFileForTransit( - dispatcher(), result, file); -} - -void PPB_Flash_File_FileRef_Proxy::OnMsgQueryFile( - const HostResource& host_resource, - PP_FileInfo* info, - int32_t* result) { - *result = ppb_flash_file_fileref_impl_->QueryFile( - host_resource.host_resource(), info); -} - -} // namespace proxy -} // namespace ppapi diff --git a/ppapi/proxy/ppb_flash_file_proxy.h b/ppapi/proxy/ppb_flash_file_proxy.h deleted file mode 100644 index 63ab624..0000000 --- a/ppapi/proxy/ppb_flash_file_proxy.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef PPAPI_PPB_FLASH_FILE_PROXY_H_ -#define PPAPI_PPB_FLASH_FILE_PROXY_H_ - -#include <string> -#include <vector> - -#include "ipc/ipc_platform_file.h" -#include "ppapi/c/pp_instance.h" -#include "ppapi/c/pp_module.h" -#include "ppapi/proxy/interface_proxy.h" - -struct PP_FileInfo; -struct PPB_Flash_File_FileRef; -struct PPB_Flash_File_ModuleLocal; - -namespace ppapi { - -class HostResource; - -namespace proxy { - -struct SerializedDirEntry; - -class PPB_Flash_File_ModuleLocal_Proxy : public InterfaceProxy { - public: - PPB_Flash_File_ModuleLocal_Proxy(Dispatcher* dispatcher); - virtual ~PPB_Flash_File_ModuleLocal_Proxy(); - - static const PPB_Flash_File_ModuleLocal* GetInterface(); - - // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg); - - private: - // Message handlers. - void OnMsgOpenFile(PP_Instance instance, - const std::string& path, - int32_t mode, - IPC::PlatformFileForTransit* file_handle, - int32_t* result); - void OnMsgRenameFile(PP_Instance instance, - const std::string& path_from, - const std::string& path_to, - int32_t* result); - void OnMsgDeleteFileOrDir(PP_Instance instance, - const std::string& path, - PP_Bool recursive, - int32_t* result); - void OnMsgCreateDir(PP_Instance instance, - const std::string& path, - int32_t* result); - void OnMsgQueryFile(PP_Instance instance, - const std::string& path, - PP_FileInfo* info, - int32_t* result); - void OnMsgGetDirContents(PP_Instance instance, - const std::string& path, - std::vector<SerializedDirEntry>* entries, - int32_t* result); - - // When this proxy is in the host side, this value caches the interface - // pointer so we don't have to retrieve it from the dispatcher each time. - // In the plugin, this value is always NULL. - const PPB_Flash_File_ModuleLocal* ppb_flash_file_module_local_impl_; - - DISALLOW_COPY_AND_ASSIGN(PPB_Flash_File_ModuleLocal_Proxy); -}; - -class PPB_Flash_File_FileRef_Proxy : public InterfaceProxy { - public: - PPB_Flash_File_FileRef_Proxy(Dispatcher* dispatcher); - virtual ~PPB_Flash_File_FileRef_Proxy(); - - static const PPB_Flash_File_FileRef* GetInterface(); - - // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg); - - private: - // Message handlers. - void OnMsgOpenFile(const ppapi::HostResource& host_resource, - int32_t mode, - IPC::PlatformFileForTransit* file_handle, - int32_t* result); - void OnMsgQueryFile(const ppapi::HostResource& host_resource, - PP_FileInfo* info, - int32_t* result); - - // When this proxy is in the host side, this value caches the interface - // pointer so we don't have to retrieve it from the dispatcher each time. - // In the plugin, this value is always NULL. - const PPB_Flash_File_FileRef* ppb_flash_file_fileref_impl_; - - DISALLOW_COPY_AND_ASSIGN(PPB_Flash_File_FileRef_Proxy); -}; - -} // namespace proxy -} // namespace ppapi - -#endif // PPAPI_PPB_FLASH_FILE_PROXY_H_ diff --git a/ppapi/proxy/ppb_flash_menu_proxy.h b/ppapi/proxy/ppb_flash_menu_proxy.h index df23da1..8c20774 100644 --- a/ppapi/proxy/ppb_flash_menu_proxy.h +++ b/ppapi/proxy/ppb_flash_menu_proxy.h @@ -31,6 +31,8 @@ class PPB_Flash_Menu_Proxy : public InterfaceProxy { // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg); + static const ApiID kApiID = API_ID_PPB_FLASH_MENU; + private: struct ShowRequest; diff --git a/ppapi/proxy/ppb_flash_message_loop_proxy.h b/ppapi/proxy/ppb_flash_message_loop_proxy.h index aaf33f9..238f106 100644 --- a/ppapi/proxy/ppb_flash_message_loop_proxy.h +++ b/ppapi/proxy/ppb_flash_message_loop_proxy.h @@ -35,6 +35,8 @@ class PPB_Flash_MessageLoop_Proxy // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + static const ApiID kApiID = API_ID_PPB_FLASH_MESSAGELOOP; + private: void OnMsgCreate(PP_Instance instance, ppapi::HostResource* resource); void OnMsgRun(const ppapi::HostResource& flash_message_loop, diff --git a/ppapi/proxy/ppb_flash_proxy.cc b/ppapi/proxy/ppb_flash_proxy.cc index 9c91830..3db3dab 100644 --- a/ppapi/proxy/ppb_flash_proxy.cc +++ b/ppapi/proxy/ppb_flash_proxy.cc @@ -4,9 +4,15 @@ #include "ppapi/proxy/ppb_flash_proxy.h" +#include <map> +#include <set> + #include "base/logging.h" +#include "base/memory/ref_counted.h" #include "base/message_loop.h" +#include "base/synchronization/lock.h" #include "base/time.h" +#include "ipc/ipc_channel_proxy.h" #include "ppapi/c/dev/ppb_font_dev.h" #include "ppapi/c/dev/ppb_var_deprecated.h" #include "ppapi/c/pp_errors.h" @@ -31,10 +37,337 @@ #include "ppapi/thunk/resource_creation_api.h" using ppapi::thunk::EnterInstanceNoLock; +using ppapi::thunk::EnterResourceNoLock; namespace ppapi { namespace proxy { +namespace { + +IPC::PlatformFileForTransit PlatformFileToPlatformFileForTransit( + Dispatcher* dispatcher, + int32_t* error, + base::PlatformFile file) { + if (*error != PP_OK) + return IPC::InvalidPlatformFileForTransit(); + IPC::PlatformFileForTransit out_handle = + dispatcher->ShareHandleWithRemote(file, true); + if (out_handle == IPC::InvalidPlatformFileForTransit()) + *error = PP_ERROR_NOACCESS; + return out_handle; +} + +// ModuleLocalThreadAdapter ---------------------------------------------------- +// TODO(yzshen): Refactor to use IPC::SyncMessageFilter. +class ModuleLocalThreadAdapter + : public base::RefCountedThreadSafe<ModuleLocalThreadAdapter> { + class Filter; + public: + ModuleLocalThreadAdapter(); + + void AddInstanceRouting(PP_Instance instance, Dispatcher* dispatcher); + void ClearInstanceRouting(PP_Instance instance); + void ClearFilter(Dispatcher* dispatcher, Filter* filter); + + bool OnModuleLocalMessageReceived(const IPC::Message& msg); + + // Called on the I/O thread when the channel is being destroyed and the + // given message will never be issued a reply. + void OnModuleLocalMessageFailed(int message_id); + + bool Send(PP_Instance instance, IPC::Message* msg); + + private: + class Filter : public IPC::ChannelProxy::MessageFilter { + public: + explicit Filter(Dispatcher* dispatcher); + ~Filter(); + + void Send(IPC::Message* msg); + + virtual void OnFilterAdded(IPC::Channel* channel); + virtual void OnFilterRemoved(); + virtual bool OnMessageReceived(const IPC::Message& message); + + private: + // DO NOT DEREFERENCE! This is used only for tracking. + Dispatcher* dispatcher_; + + IPC::Channel* channel_; + + // Holds the IPC messages that were sent before the channel was connected. + // These will be sent ASAP. + std::vector<IPC::Message*> pre_connect_pending_messages_; + + // Holds the IDs of the sync messages we're currently waiting on for this + // channel. This tracking allows us to cancel those requests if the + // remote process crashes and we're cleaning up this filter (without just + // deadlocking the waiting thread(s). + std::set<int> pending_requests_for_filter_; + }; + + void SendFromIOThread(Dispatcher* dispatcher, IPC::Message* msg); + + // Internal version of OnModuleLocalMessageFailed which assumes the lock + // is already held. + void OnModuleLocalMessageFailedLocked(int message_id); + + base::Lock lock_; + + scoped_refptr<base::MessageLoopProxy> main_thread_; + + // Will be NULL before an instance routing is added. + scoped_refptr<base::MessageLoopProxy> io_thread_; + + typedef std::map<PP_Instance, Dispatcher*> InstanceToDispatcher; + InstanceToDispatcher instance_to_dispatcher_; + + // The filters are owned by the channel. + typedef std::map<Dispatcher*, Filter*> DispatcherToFilter; + DispatcherToFilter dispatcher_to_filter_; + + // Tracks all messages with currently waiting threads. This does not own + // the pointer, the pointer lifetime is managed by Send(). + typedef std::map<int, IPC::PendingSyncMsg*> SyncRequestMap; + SyncRequestMap pending_sync_requests_; +}; + +ModuleLocalThreadAdapter* g_module_local_thread_adapter = NULL; + +ModuleLocalThreadAdapter::Filter::Filter(Dispatcher* dispatcher) + : dispatcher_(dispatcher), channel_(NULL) { +} + +ModuleLocalThreadAdapter::Filter::~Filter() { +} + +void ModuleLocalThreadAdapter::Filter::Send(IPC::Message* msg) { + if (channel_) { + int message_id = IPC::SyncMessage::GetMessageId(*msg); + if (channel_->Send(msg)) + pending_requests_for_filter_.insert(message_id); + else // Message lost, notify adapter so it can unblock. + g_module_local_thread_adapter->OnModuleLocalMessageFailed(message_id); + } else { + // No channel, save this message for when it's connected. + pre_connect_pending_messages_.push_back(msg); + } +} + +void ModuleLocalThreadAdapter::Filter::OnFilterAdded(IPC::Channel* channel) { + DCHECK(!channel_); + channel_ = channel; + + // Now that we have a channel, process all pending messages. + for (size_t i = 0; i < pre_connect_pending_messages_.size(); i++) + Send(pre_connect_pending_messages_[i]); + pre_connect_pending_messages_.clear(); +} + +void ModuleLocalThreadAdapter::Filter::OnFilterRemoved() { + DCHECK(channel_); + channel_ = NULL; + g_module_local_thread_adapter->ClearFilter(dispatcher_, this); + + for (std::set<int>::iterator i = pending_requests_for_filter_.begin(); + i != pending_requests_for_filter_.end(); ++i) { + g_module_local_thread_adapter->OnModuleLocalMessageFailed(*i); + } +} + +bool ModuleLocalThreadAdapter::Filter::OnMessageReceived( + const IPC::Message& message) { + if (!message.is_reply() || + message.routing_id() != API_ID_PPB_FLASH) + return false; + + if (g_module_local_thread_adapter->OnModuleLocalMessageReceived(message)) { + // The message was consumed, this means we can remove the message ID from + // the list of messages this channel is waiting on. + pending_requests_for_filter_.erase(IPC::SyncMessage::GetMessageId(message)); + return true; + } + return false; +} + +ModuleLocalThreadAdapter::ModuleLocalThreadAdapter() + : main_thread_(base::MessageLoopProxy::current()) { +} + +void ModuleLocalThreadAdapter::AddInstanceRouting(PP_Instance instance, + Dispatcher* dispatcher) { + base::AutoLock lock(lock_); + + // Now that we've had contact with a dispatcher, we can set up the IO thread. + DCHECK(main_thread_->BelongsToCurrentThread()); + if (!io_thread_.get()) + io_thread_ = dispatcher->GetIPCMessageLoop(); + + // Set up the instance -> dispatcher routing. + DCHECK(instance_to_dispatcher_.find(instance) == + instance_to_dispatcher_.end()); + instance_to_dispatcher_[instance] = dispatcher; + + DispatcherToFilter::iterator found_filter = + dispatcher_to_filter_.find(dispatcher); + if (found_filter == dispatcher_to_filter_.end()) { + // Need to set up a filter for this dispatcher to intercept the messages. + Filter* filter = new Filter(dispatcher); + dispatcher_to_filter_[dispatcher] = filter; + dispatcher->AddIOThreadMessageFilter(filter); + } +} + +void ModuleLocalThreadAdapter::ClearInstanceRouting(PP_Instance instance) { + // The dispatcher->filter mapping is cleaned up by ClearFilter which is + // initiated by the channel. + instance_to_dispatcher_.erase(instance); +} + +void ModuleLocalThreadAdapter::ClearFilter(Dispatcher* dispatcher, + Filter* filter) { + // DANGER! Don't dereference the dispatcher, it's just used to identify + // which filter to remove. The dispatcher may not even exist any more. + // + // Since the dispatcher may be gone, there's a potential for ambiguity if + // another one is created on the main thread before this code runs on the + // I/O thread. So we check that the filter matches to avoid this rare case. + base::AutoLock lock(lock_); + if (dispatcher_to_filter_[dispatcher] == filter) + dispatcher_to_filter_.erase(dispatcher); +} + +bool ModuleLocalThreadAdapter::OnModuleLocalMessageReceived( + const IPC::Message& msg) { + base::AutoLock lock(lock_); + + int message_id = IPC::SyncMessage::GetMessageId(msg); + SyncRequestMap::iterator found = pending_sync_requests_.find(message_id); + if (found == pending_sync_requests_.end()) { + // Not waiting for this event. This will happen for sync messages to the + // main thread which use the "regular" sync channel code path. + return false; + } + + IPC::PendingSyncMsg& info = *found->second; + + if (!msg.is_reply_error()) + info.deserializer->SerializeOutputParameters(msg); + info.done_event->Signal(); + return true; +} + +void ModuleLocalThreadAdapter::OnModuleLocalMessageFailed(int message_id) { + base::AutoLock lock(lock_); + OnModuleLocalMessageFailedLocked(message_id); +} + +bool ModuleLocalThreadAdapter::Send(PP_Instance instance, IPC::Message* msg) { + // Compute the dispatcher corresponding to this message. + Dispatcher* dispatcher = NULL; + { + base::AutoLock lock(lock_); + InstanceToDispatcher::iterator found = + instance_to_dispatcher_.find(instance); + if (found == instance_to_dispatcher_.end()) { + NOTREACHED(); + delete msg; + return false; + } + dispatcher = found->second; + } + + if (main_thread_->BelongsToCurrentThread()) { + // Easy case: We're on the same thread as the dispatcher, so we don't need + // a lock to access it, and we can just use the normal sync channel stuff + // to handle the message. Actually, we MUST use the normal sync channel + // stuff since there may be incoming sync messages that need processing. + // The code below doesn't handle any nested message loops. + return dispatcher->Send(msg); + } + + // Background thread case + // ---------------------- + // 1. Generate tracking info, stick in pending_sync_messages_map. + // 2. Kick off the request. This is done on the I/O thread. + // 3. Filter on the I/O thread notices reply, writes the reply data and + // signals the event. We block on the event while this is happening. + // 4. Remove tracking info. + + // Generate the tracking info. and copied + IPC::SyncMessage* sync_msg = static_cast<IPC::SyncMessage*>(msg); + int message_id = IPC::SyncMessage::GetMessageId(*sync_msg); + base::WaitableEvent event(true, false); + scoped_ptr<IPC::MessageReplyDeserializer> deserializer( + sync_msg->GetReplyDeserializer()); // We own this pointer once retrieved. + IPC::PendingSyncMsg info(message_id, deserializer.get(), &event); + + // Add the tracking information to our map. + { + base::AutoLock lock(lock_); + pending_sync_requests_[message_id] = &info; + } + + // This is a bit dangerous. We use the dispatcher pointer as the routing + // ID for this message. While we don't dereference it, there is an + // exceedingly remote possibility that while this is going to the background + // thread the connection will be shut down and a new one will be created with + // a dispatcher at the same address. It could potentially get sent to a + // random place, but it should actually still work (since the Flash file + // operations are global). + io_thread_->PostTask(FROM_HERE, + base::Bind(&ModuleLocalThreadAdapter::SendFromIOThread, this, + dispatcher, msg)); + + // Now we block the current thread waiting for the reply. + event.Wait(); + + { + // Clear our tracking info for this message now that we're done. + base::AutoLock lock(lock_); + DCHECK(pending_sync_requests_.find(message_id) != + pending_sync_requests_.end()); + pending_sync_requests_.erase(message_id); + } + + return true; +} + +void ModuleLocalThreadAdapter::SendFromIOThread(Dispatcher* dispatcher, + IPC::Message* msg) { + // DO NOT DEREFERENCE DISPATCHER. Used as a lookup only. + base::AutoLock lock(lock_); + DispatcherToFilter::iterator found = dispatcher_to_filter_.find(dispatcher); + + // The dispatcher could have been destroyed by the time we got here since + // we're on another thread. Need to unblock the caller. + if (found == dispatcher_to_filter_.end()) { + OnModuleLocalMessageFailedLocked(IPC::SyncMessage::GetMessageId(*msg)); + delete msg; + return; + } + + // Takes ownership of pointer. + found->second->Send(msg); +} + +void ModuleLocalThreadAdapter::OnModuleLocalMessageFailedLocked( + int message_id) { + lock_.AssertAcquired(); + + // Unblock the thread waiting for the message that will never come. + SyncRequestMap::iterator found = pending_sync_requests_.find(message_id); + if (found == pending_sync_requests_.end()) { + NOTREACHED(); + return; + } + found->second->done_event->Signal(); +} + +} // namespace + +// ----------------------------------------------------------------------------- + PPB_Flash_Proxy::PPB_Flash_Proxy(Dispatcher* dispatcher) : InterfaceProxy(dispatcher) { } @@ -75,6 +408,22 @@ bool PPB_Flash_Proxy::OnMessageReceived(const IPC::Message& msg) { OnHostMsgReadClipboardData) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_WriteClipboardData, OnHostMsgWriteClipboardData) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_OpenFile, + OnHostMsgOpenFile) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_RenameFile, + OnHostMsgRenameFile) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_DeleteFileOrDir, + OnHostMsgDeleteFileOrDir) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_CreateDir, + OnHostMsgCreateDir) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QueryFile, + OnHostMsgQueryFile) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetDirContents, + OnHostMsgGetDirContents) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_OpenFileRef, + OnHostMsgOpenFileRef) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QueryFileRef, + OnHostMsgQueryFileRef) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() // TODO(brettw) handle bad messages! @@ -268,6 +617,155 @@ int32_t PPB_Flash_Proxy::WriteClipboardData( return PP_OK; } +bool PPB_Flash_Proxy::CreateThreadAdapterForInstance(PP_Instance instance) { + if (!g_module_local_thread_adapter) { + g_module_local_thread_adapter = new ModuleLocalThreadAdapter(); + g_module_local_thread_adapter->AddRef(); // Leaked, this object is global. + } + + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); + if (!dispatcher) { + NOTREACHED(); + return false; + } + g_module_local_thread_adapter->AddInstanceRouting(instance, dispatcher); + return true; +} + +void PPB_Flash_Proxy::ClearThreadAdapterForInstance(PP_Instance instance) { + if (g_module_local_thread_adapter) + g_module_local_thread_adapter->ClearInstanceRouting(instance); +} + +int32_t PPB_Flash_Proxy::OpenFile(PP_Instance instance, + const char* path, + int32_t mode, + PP_FileHandle* file) { + if (!g_module_local_thread_adapter) + return PP_ERROR_FAILED; + + int32_t result = PP_ERROR_FAILED; + IPC::PlatformFileForTransit transit; + g_module_local_thread_adapter->Send(instance, + new PpapiHostMsg_PPBFlash_OpenFile( + API_ID_PPB_FLASH, instance, path, mode, &transit, &result)); + *file = IPC::PlatformFileForTransitToPlatformFile(transit); + return result; +} + +int32_t PPB_Flash_Proxy::RenameFile(PP_Instance instance, + const char* path_from, + const char* path_to) { + if (!g_module_local_thread_adapter) + return PP_ERROR_FAILED; + + int32_t result = PP_ERROR_FAILED; + g_module_local_thread_adapter->Send(instance, + new PpapiHostMsg_PPBFlash_RenameFile( + API_ID_PPB_FLASH, instance, path_from, path_to, &result)); + return result; +} + +int32_t PPB_Flash_Proxy::DeleteFileOrDir(PP_Instance instance, + const char* path, + PP_Bool recursive) { + if (!g_module_local_thread_adapter) + return PP_ERROR_FAILED; + + int32_t result = PP_ERROR_FAILED; + g_module_local_thread_adapter->Send(instance, + new PpapiHostMsg_PPBFlash_DeleteFileOrDir( + API_ID_PPB_FLASH, instance, path, recursive, &result)); + return result; +} + +int32_t PPB_Flash_Proxy::CreateDir(PP_Instance instance, const char* path) { + if (!g_module_local_thread_adapter) + return PP_ERROR_FAILED; + + int32_t result = PP_ERROR_FAILED; + g_module_local_thread_adapter->Send(instance, + new PpapiHostMsg_PPBFlash_CreateDir( + API_ID_PPB_FLASH, instance, path, &result)); + return result; +} + +int32_t PPB_Flash_Proxy::QueryFile(PP_Instance instance, + const char* path, + PP_FileInfo* info) { + if (!g_module_local_thread_adapter) + return PP_ERROR_FAILED; + + int32_t result = PP_ERROR_FAILED; + g_module_local_thread_adapter->Send(instance, + new PpapiHostMsg_PPBFlash_QueryFile( + API_ID_PPB_FLASH, instance, path, info, &result)); + return result; +} + +int32_t PPB_Flash_Proxy::GetDirContents(PP_Instance instance, + const char* path, + PP_DirContents_Dev** contents) { + if (!g_module_local_thread_adapter) + return PP_ERROR_FAILED; + + int32_t result = PP_ERROR_FAILED; + std::vector<SerializedDirEntry> entries; + g_module_local_thread_adapter->Send(instance, + new PpapiHostMsg_PPBFlash_GetDirContents( + API_ID_PPB_FLASH, instance, path, &entries, &result)); + + if (result != PP_OK) + return result; + + // Copy the serialized dir entries to the output struct. + *contents = new PP_DirContents_Dev; + (*contents)->count = static_cast<int32_t>(entries.size()); + (*contents)->entries = new PP_DirEntry_Dev[entries.size()]; + for (size_t i = 0; i < entries.size(); i++) { + const SerializedDirEntry& source = entries[i]; + PP_DirEntry_Dev* dest = &(*contents)->entries[i]; + + char* name_copy = new char[source.name.size() + 1]; + memcpy(name_copy, source.name.c_str(), source.name.size() + 1); + dest->name = name_copy; + dest->is_dir = PP_FromBool(source.is_dir); + } + + return result; +} + +int32_t PPB_Flash_Proxy::OpenFileRef(PP_Instance instance, + PP_Resource file_ref_id, + int32_t mode, + PP_FileHandle* file) { + EnterResourceNoLock<PPB_FileRef> enter(file_ref_id, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + + int32_t result = PP_ERROR_FAILED; + IPC::PlatformFileForTransit transit; + dispatcher()->Send(new PpapiHostMsg_PPBFlash_OpenFileRef( + API_ID_PPB_FLASH, instance, enter.resource()->host_resource(), mode, + &transit, &result)); + *file = IPC::PlatformFileForTransitToPlatformFile(transit); + return result; +} + +int32_t PPB_Flash_Proxy::QueryFileRef(PP_Instance instance, + PP_Resource file_ref_id, + PP_FileInfo* info) { + EnterResourceNoLock<PPB_FileRef> enter(file_ref_id, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + + int32_t result = PP_ERROR_FAILED; + dispatcher()->Send(new PpapiHostMsg_PPBFlash_QueryFileRef( + API_ID_PPB_FLASH, instance, enter.resource()->host_resource(), info, + &result)); + return result; +} + PP_Bool PPB_Flash_Proxy::FlashIsFullscreen(PP_Instance instance) { InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())-> GetInstanceData(instance); @@ -500,5 +998,133 @@ void PPB_Flash_Proxy::OnHostMsgWriteClipboardData( } } +void PPB_Flash_Proxy::OnHostMsgOpenFile( + PP_Instance instance, + const std::string& path, + int32_t mode, + IPC::PlatformFileForTransit* file_handle, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + base::PlatformFile file; + *result = enter.functions()->GetFlashAPI()->OpenFile( + instance, path.c_str(), mode, &file); + *file_handle = PlatformFileToPlatformFileForTransit( + dispatcher(), result, file); + } else { + *result = PP_ERROR_BADARGUMENT; + } +} + +void PPB_Flash_Proxy::OnHostMsgRenameFile(PP_Instance instance, + const std::string& from_path, + const std::string& to_path, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + *result = enter.functions()->GetFlashAPI()->RenameFile( + instance, from_path.c_str(), to_path.c_str()); + } else { + *result = PP_ERROR_BADARGUMENT; + } +} + +void PPB_Flash_Proxy::OnHostMsgDeleteFileOrDir(PP_Instance instance, + const std::string& path, + PP_Bool recursive, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + *result = enter.functions()->GetFlashAPI()->DeleteFileOrDir( + instance, path.c_str(), recursive); + } else { + *result = PP_ERROR_BADARGUMENT; + } +} + +void PPB_Flash_Proxy::OnHostMsgCreateDir(PP_Instance instance, + const std::string& path, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + *result = enter.functions()->GetFlashAPI()->CreateDir( + instance, path.c_str()); + } else { + *result = PP_ERROR_BADARGUMENT; + } +} + +void PPB_Flash_Proxy::OnHostMsgQueryFile(PP_Instance instance, + const std::string& path, + PP_FileInfo* info, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.succeeded()) { + *result = enter.functions()->GetFlashAPI()->QueryFile( + instance, path.c_str(), info); + } else { + *result = PP_ERROR_BADARGUMENT; + } +} + +void PPB_Flash_Proxy::OnHostMsgGetDirContents( + PP_Instance instance, + const std::string& path, + std::vector<SerializedDirEntry>* entries, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.failed()) { + *result = PP_ERROR_BADARGUMENT; + return; + } + + PP_DirContents_Dev* contents = NULL; + *result = enter.functions()->GetFlashAPI()->GetDirContents( + instance, path.c_str(), &contents); + if (*result != PP_OK) + return; + + // Convert the list of entries to the serialized version. + entries->resize(contents->count); + for (int32_t i = 0; i < contents->count; i++) { + (*entries)[i].name.assign(contents->entries[i].name); + (*entries)[i].is_dir = PP_ToBool(contents->entries[i].is_dir); + } + enter.functions()->GetFlashAPI()->FreeDirContents(instance, contents); +} + +void PPB_Flash_Proxy::OnHostMsgOpenFileRef( + PP_Instance instance, + const HostResource& host_resource, + int32_t mode, + IPC::PlatformFileForTransit* file_handle, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.failed()) { + *result = PP_ERROR_BADARGUMENT; + return; + } + + base::PlatformFile file; + *result = enter.functions()->GetFlashAPI()->OpenFileRef( + instance, host_resource.host_resource(), mode, &file); + *file_handle = PlatformFileToPlatformFileForTransit(dispatcher(), + result, file); +} + +void PPB_Flash_Proxy::OnHostMsgQueryFileRef( + PP_Instance instance, + const HostResource& host_resource, + PP_FileInfo* info, + int32_t* result) { + EnterInstanceNoLock enter(instance); + if (enter.failed()) { + *result = PP_ERROR_BADARGUMENT; + return; + } + *result = enter.functions()->GetFlashAPI()->QueryFileRef( + instance, host_resource.host_resource(), info); +} + } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/ppb_flash_proxy.h b/ppapi/proxy/ppb_flash_proxy.h index 5541697..29c6a67 100644 --- a/ppapi/proxy/ppb_flash_proxy.h +++ b/ppapi/proxy/ppb_flash_proxy.h @@ -27,6 +27,7 @@ struct PPB_URLRequestInfo_Data; namespace proxy { struct PPBFlash_DrawGlyphs_Params; +struct SerializedDirEntry; class SerializedVarReturnValue; class PPB_Flash_Proxy : public InterfaceProxy, public PPB_Flash_Shared { @@ -77,6 +78,32 @@ class PPB_Flash_Proxy : public InterfaceProxy, public PPB_Flash_Shared { uint32_t data_item_count, const PP_Flash_Clipboard_Format formats[], const PP_Var data_items[]) OVERRIDE; + virtual bool CreateThreadAdapterForInstance(PP_Instance instance) OVERRIDE; + virtual void ClearThreadAdapterForInstance(PP_Instance instance) OVERRIDE; + virtual int32_t OpenFile(PP_Instance instance, + const char* path, + int32_t mode, + PP_FileHandle* file) OVERRIDE; + virtual int32_t RenameFile(PP_Instance instance, + const char* path_from, + const char* path_to) OVERRIDE; + virtual int32_t DeleteFileOrDir(PP_Instance instance, + const char* path, + PP_Bool recursive) OVERRIDE; + virtual int32_t CreateDir(PP_Instance instance, const char* path) OVERRIDE; + virtual int32_t QueryFile(PP_Instance instance, + const char* path, + PP_FileInfo* info) OVERRIDE; + virtual int32_t GetDirContents(PP_Instance instance, + const char* path, + PP_DirContents_Dev** contents) OVERRIDE; + virtual int32_t OpenFileRef(PP_Instance instance, + PP_Resource file_ref, + int32_t mode, + PP_FileHandle* file) OVERRIDE; + virtual int32_t QueryFileRef(PP_Instance instance, + PP_Resource file_ref, + PP_FileInfo* info) OVERRIDE; virtual PP_Bool FlashIsFullscreen(PP_Instance instance) OVERRIDE; virtual PP_Bool FlashSetFullscreen(PP_Instance instance, PP_Bool fullscreen) OVERRIDE; @@ -125,6 +152,39 @@ class PPB_Flash_Proxy : public InterfaceProxy, public PPB_Flash_Shared { int clipboard_type, const std::vector<int>& formats, SerializedVarVectorReceiveInput data_items); + void OnHostMsgOpenFile(PP_Instance instance, + const std::string& path, + int32_t mode, + IPC::PlatformFileForTransit* file_handle, + int32_t* result); + void OnHostMsgRenameFile(PP_Instance instance, + const std::string& path_from, + const std::string& path_to, + int32_t* result); + void OnHostMsgDeleteFileOrDir(PP_Instance instance, + const std::string& path, + PP_Bool recursive, + int32_t* result); + void OnHostMsgCreateDir(PP_Instance instance, + const std::string& path, + int32_t* result); + void OnHostMsgQueryFile(PP_Instance instance, + const std::string& path, + PP_FileInfo* info, + int32_t* result); + void OnHostMsgGetDirContents(PP_Instance instance, + const std::string& path, + std::vector<SerializedDirEntry>* entries, + int32_t* result); + void OnHostMsgOpenFileRef(PP_Instance instance, + const ppapi::HostResource& host_resource, + int32_t mode, + IPC::PlatformFileForTransit* file_handle, + int32_t* result); + void OnHostMsgQueryFileRef(PP_Instance instance, + const ppapi::HostResource& host_resource, + PP_FileInfo* info, + int32_t* result); DISALLOW_COPY_AND_ASSIGN(PPB_Flash_Proxy); }; diff --git a/ppapi/shared_impl/api_id.h b/ppapi/shared_impl/api_id.h index be4be56..d83c085 100644 --- a/ppapi/shared_impl/api_id.h +++ b/ppapi/shared_impl/api_id.h @@ -25,8 +25,6 @@ enum ApiID { API_ID_PPB_FILE_REF, API_ID_PPB_FILE_SYSTEM, API_ID_PPB_FLASH, - API_ID_PPB_FLASH_FILE_FILEREF, - API_ID_PPB_FLASH_FILE_MODULELOCAL, API_ID_PPB_FLASH_MENU, API_ID_PPB_FLASH_MESSAGELOOP, API_ID_PPB_FONT, diff --git a/ppapi/shared_impl/ppb_flash_shared.cc b/ppapi/shared_impl/ppb_flash_shared.cc index c0504bf..e78392c 100644 --- a/ppapi/shared_impl/ppb_flash_shared.cc +++ b/ppapi/shared_impl/ppb_flash_shared.cc @@ -12,6 +12,14 @@ PPB_Flash_Shared::PPB_Flash_Shared() { PPB_Flash_Shared::~PPB_Flash_Shared() { } +void PPB_Flash_Shared::FreeDirContents(PP_Instance instance, + PP_DirContents_Dev* contents) { + for (int32_t i = 0; i < contents->count; ++i) + delete[] contents->entries[i].name; + delete[] contents->entries; + delete contents; +} + // static bool PPB_Flash_Shared::IsValidClipboardType( PP_Flash_Clipboard_Type clipboard_type) { diff --git a/ppapi/shared_impl/ppb_flash_shared.h b/ppapi/shared_impl/ppb_flash_shared.h index b7de3bd..dfd209d 100644 --- a/ppapi/shared_impl/ppb_flash_shared.h +++ b/ppapi/shared_impl/ppb_flash_shared.h @@ -17,6 +17,10 @@ class PPAPI_SHARED_EXPORT PPB_Flash_Shared : public thunk::PPB_Flash_API { PPB_Flash_Shared(); virtual ~PPB_Flash_Shared(); + // Shared implementation of PPB_Flash_API. + virtual void FreeDirContents(PP_Instance instance, + PP_DirContents_Dev* contents) OVERRIDE; + protected: static bool IsValidClipboardType(PP_Flash_Clipboard_Type clipboard_type); static bool IsValidClipboardFormat(PP_Flash_Clipboard_Format format); diff --git a/ppapi/thunk/interfaces_ppb_private_flash.h b/ppapi/thunk/interfaces_ppb_private_flash.h index 1a96fbc..4f13d1c 100644 --- a/ppapi/thunk/interfaces_ppb_private_flash.h +++ b/ppapi/thunk/interfaces_ppb_private_flash.h @@ -8,7 +8,6 @@ #include "ppapi/thunk/interfaces_preamble.h" PROXIED_API(PPB_Flash) - PROXIED_IFACE(PPB_Flash, PPB_FLASH_INTERFACE_11_0, PPB_Flash_11) @@ -21,7 +20,6 @@ PROXIED_IFACE(PPB_Flash, PROXIED_IFACE(PPB_Flash, PPB_FLASH_INTERFACE_12_2, PPB_Flash_12_2) - PROXIED_IFACE(PPB_Flash, PPB_FLASH_CLIPBOARD_INTERFACE_3_LEGACY, PPB_Flash_Clipboard_3_0) @@ -31,5 +29,26 @@ PROXIED_IFACE(PPB_Flash, PROXIED_IFACE(PPB_Flash, PPB_FLASH_CLIPBOARD_INTERFACE_4_0, PPB_Flash_Clipboard_4_0) +PROXIED_IFACE(PPB_Flash, + PPB_FLASH_FILE_MODULELOCAL_INTERFACE, + PPB_Flash_File_ModuleLocal) +PROXIED_IFACE(PPB_Flash, + PPB_FLASH_FILE_FILEREF_INTERFACE, + PPB_Flash_File_FileRef) + +PROXIED_API(PPB_Flash_Menu) +PROXIED_IFACE(PPB_Flash_Menu, + PPB_FLASH_MENU_INTERFACE_0_2, + PPB_Flash_Menu_0_2) + +PROXIED_API(PPB_Flash_MessageLoop) +PROXIED_IFACE(PPB_Flash_MessageLoop, + PPB_FLASH_MESSAGELOOP_INTERFACE_0_1, + PPB_Flash_MessageLoop_0_1) + +// TCPSocketPrivate is defined in the normal private interfaces. +PROXIED_IFACE(PPB_TCPSocket_Private, + PPB_FLASH_TCPSOCKET_INTERFACE_0_2, + PPB_TCPSocket_Private_0_3) #include "ppapi/thunk/interfaces_postamble.h" diff --git a/ppapi/thunk/ppb_flash_api.h b/ppapi/thunk/ppb_flash_api.h index b54bba3..1760480 100644 --- a/ppapi/thunk/ppb_flash_api.h +++ b/ppapi/thunk/ppb_flash_api.h @@ -7,6 +7,7 @@ #include "ppapi/c/private/ppb_flash.h" #include "ppapi/c/private/ppb_flash_clipboard.h" +#include "ppapi/c/private/ppb_flash_file.h" #include "ppapi/thunk/ppapi_thunk_export.h" namespace ppapi { @@ -57,6 +58,38 @@ class PPAPI_THUNK_EXPORT PPB_Flash_API { const PP_Flash_Clipboard_Format formats[], const PP_Var data_items[]) = 0; + // FlashFile_ModuleLocal. + virtual bool CreateThreadAdapterForInstance(PP_Instance instance) = 0; + virtual void ClearThreadAdapterForInstance(PP_Instance instance) = 0; + virtual int32_t OpenFile(PP_Instance instance, + const char* path, + int32_t mode, + PP_FileHandle* file) = 0; + virtual int32_t RenameFile(PP_Instance instance, + const char* path_from, + const char* path_to) = 0; + virtual int32_t DeleteFileOrDir(PP_Instance instance, + const char* path, + PP_Bool recursive) = 0; + virtual int32_t CreateDir(PP_Instance instance, const char* path) = 0; + virtual int32_t QueryFile(PP_Instance instance, + const char* path, + PP_FileInfo* info) = 0; + virtual int32_t GetDirContents(PP_Instance instance, + const char* path, + PP_DirContents_Dev** contents) = 0; + virtual void FreeDirContents(PP_Instance instance, + PP_DirContents_Dev* contents) = 0; + + // FlashFile_FileRef. + virtual int32_t OpenFileRef(PP_Instance instance, + PP_Resource file_ref, + int32_t mode, + PP_FileHandle* file) = 0; + virtual int32_t QueryFileRef(PP_Instance instance, + PP_Resource file_ref, + PP_FileInfo* info) = 0; + // FlashFullscreen. virtual PP_Bool FlashIsFullscreen(PP_Instance instance) = 0; virtual PP_Bool FlashSetFullscreen(PP_Instance instance, diff --git a/ppapi/thunk/ppb_flash_file_fileref_thunk.cc b/ppapi/thunk/ppb_flash_file_fileref_thunk.cc new file mode 100644 index 0000000..2b380c7 --- /dev/null +++ b/ppapi/thunk/ppb_flash_file_fileref_thunk.cc @@ -0,0 +1,60 @@ +// Copyright (c) 2012 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/c/pp_errors.h" +#include "ppapi/c/private/ppb_flash_file.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_file_ref_api.h" +#include "ppapi/thunk/ppb_flash_api.h" +#include "ppapi/thunk/ppb_instance_api.h" +#include "ppapi/thunk/thunk.h" + +namespace ppapi { +namespace thunk { + +namespace { + +// Returns 0 on failure. +PP_Instance GetInstanceFromFileRef(PP_Resource file_ref) { + thunk::EnterResource<thunk::PPB_FileRef_API> enter(file_ref, true); + if (enter.failed()) + return 0; + return enter.resource()->pp_instance(); +} + +int32_t OpenFile(PP_Resource file_ref_id, int32_t mode, PP_FileHandle* file) { + // TODO(brettw): this function should take an instance. + // To work around this, use the PP_Instance from the resource. + PP_Instance instance = GetInstanceFromFileRef(file_ref_id); + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->OpenFileRef(instance, file_ref_id, + mode, file); +} + +int32_t QueryFile(PP_Resource file_ref_id, struct PP_FileInfo* info) { + // TODO(brettw): this function should take an instance. + // To work around this, use the PP_Instance from the resource. + PP_Instance instance = GetInstanceFromFileRef(file_ref_id); + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->QueryFileRef(instance, file_ref_id, + info); +} + +const PPB_Flash_File_FileRef g_ppb_flash_file_fileref_thunk = { + &OpenFile, + &QueryFile +}; + +} // namespace + +const PPB_Flash_File_FileRef* GetPPB_Flash_File_FileRef_Thunk() { + return &g_ppb_flash_file_fileref_thunk; +} + +} // namespace thunk +} // namespace ppapi diff --git a/ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc b/ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc new file mode 100644 index 0000000..6338779 --- /dev/null +++ b/ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc @@ -0,0 +1,115 @@ +// Copyright (c) 2012 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/c/pp_errors.h" +#include "ppapi/c/private/ppb_flash_file.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_flash_api.h" +#include "ppapi/thunk/ppb_instance_api.h" +#include "ppapi/thunk/thunk.h" + +namespace ppapi { +namespace thunk { + +namespace { + +bool CreateThreadAdapterForInstance(PP_Instance instance) { + EnterInstance enter(instance); + if (enter.failed()) + return false; + return enter.functions()->GetFlashAPI()->CreateThreadAdapterForInstance( + instance); +} + +void ClearThreadAdapterForInstance(PP_Instance instance) { + EnterInstance enter(instance); + if (enter.succeeded()) { + return enter.functions()->GetFlashAPI()->ClearThreadAdapterForInstance( + instance); + } +} + +int32_t OpenFile(PP_Instance instance, + const char* path, + int32_t mode, + PP_FileHandle* file) { + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->OpenFile(instance, path, mode, file); +} + +int32_t RenameFile(PP_Instance instance, + const char* path_from, + const char* path_to) { + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->RenameFile(instance, + path_from, path_to); +} + +int32_t DeleteFileOrDir(PP_Instance instance, + const char* path, + PP_Bool recursive) { + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->DeleteFileOrDir(instance, path, + recursive); +} + +int32_t CreateDir(PP_Instance instance, const char* path) { + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->CreateDir(instance, path); +} + +int32_t QueryFile(PP_Instance instance, const char* path, PP_FileInfo* info) { + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->QueryFile(instance, path, info); +} + +int32_t GetDirContents(PP_Instance instance, + const char* path, + PP_DirContents_Dev** contents) { + EnterInstance enter(instance); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + return enter.functions()->GetFlashAPI()->GetDirContents(instance, path, + contents); +} + +void FreeDirContents(PP_Instance instance, + PP_DirContents_Dev* contents) { + EnterInstance enter(instance); + if (enter.succeeded()) { + return enter.functions()->GetFlashAPI()->FreeDirContents(instance, + contents); + } +} + +const PPB_Flash_File_ModuleLocal g_ppb_flash_file_modulelocal_thunk = { + &CreateThreadAdapterForInstance, + &ClearThreadAdapterForInstance, + &OpenFile, + &RenameFile, + &DeleteFileOrDir, + &CreateDir, + &QueryFile, + &GetDirContents, + &FreeDirContents +}; + +} // namespace + +const PPB_Flash_File_ModuleLocal* GetPPB_Flash_File_ModuleLocal_Thunk() { + return &g_ppb_flash_file_modulelocal_thunk; +} + +} // namespace thunk +} // namespace ppapi diff --git a/ppapi/thunk/thunk.h b/ppapi/thunk/thunk.h index 09a7e5f..09086de 100644 --- a/ppapi/thunk/thunk.h +++ b/ppapi/thunk/thunk.h @@ -60,13 +60,6 @@ PPAPI_THUNK_EXPORT const PPB_BufferTrusted_0_1* GetPPB_BufferTrusted_0_1_Thunk(); PPAPI_THUNK_EXPORT const PPB_FileChooserTrusted_0_5* GetPPB_FileChooser_Trusted_0_5_Thunk(); -PPAPI_THUNK_EXPORT const PPB_Flash_Clipboard_4_0* - GetPPB_Flash_Clipboard_4_0_Thunk(); -PPAPI_THUNK_EXPORT const PPB_Flash_Clipboard_3_0* - GetPPB_Flash_Clipboard_3_0_Thunk(); -PPAPI_THUNK_EXPORT const PPB_Flash_Menu_0_2* GetPPB_Flash_Menu_0_2_Thunk(); -PPAPI_THUNK_EXPORT const PPB_Flash_MessageLoop_0_1* - GetPPB_Flash_MessageLoop_0_1_Thunk(); PPAPI_THUNK_EXPORT const PPB_Graphics3DTrusted_1_0* GetPPB_Graphics3DTrusted_1_0_Thunk(); PPAPI_THUNK_EXPORT const PPB_HostResolver_Private_0_1* diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index 79d3134..856888b 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -271,8 +271,6 @@ '../plugins/ppapi/ppb_file_ref_impl.h', '../plugins/ppapi/ppb_file_system_impl.cc', '../plugins/ppapi/ppb_file_system_impl.h', - '../plugins/ppapi/ppb_flash_file_impl.cc', - '../plugins/ppapi/ppb_flash_file_impl.h', '../plugins/ppapi/ppb_flash_impl.cc', '../plugins/ppapi/ppb_flash_impl.h', '../plugins/ppapi/ppb_flash_menu_impl.cc', diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc index f68b79a..d2215bd 100644 --- a/webkit/plugins/ppapi/plugin_module.cc +++ b/webkit/plugins/ppapi/plugin_module.cc @@ -109,7 +109,6 @@ #include "webkit/plugins/ppapi/ppapi_interface_factory.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" #include "webkit/plugins/ppapi/ppb_directory_reader_impl.h" -#include "webkit/plugins/ppapi/ppb_flash_file_impl.h" #include "webkit/plugins/ppapi/ppb_flash_impl.h" #include "webkit/plugins/ppapi/ppb_flash_menu_impl.h" #include "webkit/plugins/ppapi/ppb_gpu_blacklist_private_impl.h" @@ -310,16 +309,6 @@ const void* GetInterface(const char* name) { return ::ppapi::thunk::GetPPB_BufferTrusted_0_1_Thunk(); if (strcmp(name, PPB_CORE_INTERFACE_1_0) == 0) return &core_interface; - if (strcmp(name, PPB_FLASH_FILE_FILEREF_INTERFACE) == 0) - return PPB_Flash_File_FileRef_Impl::GetInterface(); - if (strcmp(name, PPB_FLASH_FILE_MODULELOCAL_INTERFACE) == 0) - return PPB_Flash_File_ModuleLocal_Impl::GetInterface(); - if (strcmp(name, PPB_FLASH_MENU_INTERFACE_0_2) == 0) - return ::ppapi::thunk::GetPPB_Flash_Menu_0_2_Thunk(); - if (strcmp(name, PPB_FLASH_MESSAGELOOP_INTERFACE_0_1) == 0) - return ::ppapi::thunk::GetPPB_Flash_MessageLoop_0_1_Thunk(); - if (strcmp(name, PPB_FLASH_TCPSOCKET_INTERFACE_0_2) == 0) - return ::ppapi::thunk::GetPPB_TCPSocket_Private_0_3_Thunk(); if (strcmp(name, PPB_FULLSCREEN_DEV_INTERFACE_0_5) == 0) return ::ppapi::thunk::GetPPB_Fullscreen_1_0_Thunk(); if (strcmp(name, PPB_GPU_BLACKLIST_INTERFACE) == 0) diff --git a/webkit/plugins/ppapi/ppb_flash_file_impl.cc b/webkit/plugins/ppapi/ppb_flash_file_impl.cc deleted file mode 100644 index 46d9786..0000000 --- a/webkit/plugins/ppapi/ppb_flash_file_impl.cc +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright (c) 2011 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 "webkit/plugins/ppapi/ppb_flash_file_impl.h" - -#include <string.h> - -#include <string> - -#include "ppapi/c/pp_file_info.h" -#include "ppapi/c/ppb_file_io.h" -#include "ppapi/c/private/ppb_flash_file.h" -#include "ppapi/shared_impl/file_type_conversion.h" -#include "ppapi/shared_impl/time_conversion.h" -#include "ppapi/thunk/enter.h" -#include "webkit/plugins/ppapi/common.h" -#include "webkit/plugins/ppapi/file_path.h" -#include "webkit/plugins/ppapi/host_globals.h" -#include "webkit/plugins/ppapi/plugin_delegate.h" -#include "webkit/plugins/ppapi/plugin_module.h" -#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" -#include "webkit/plugins/ppapi/ppb_file_ref_impl.h" -#include "webkit/plugins/ppapi/resource_helper.h" - -#if defined(OS_WIN) -#include "base/utf_string_conversions.h" -#endif - -using ppapi::thunk::EnterResource; -using ppapi::thunk::PPB_FileRef_API; -using ppapi::TimeToPPTime; - -namespace webkit { -namespace ppapi { - -namespace { - -void FreeDirContents(PP_Instance instance, PP_DirContents_Dev* contents) { - DCHECK(contents); - for (int32_t i = 0; i < contents->count; ++i) { - delete [] contents->entries[i].name; - } - delete [] contents->entries; - delete contents; -} - -} // namespace - -// PPB_Flash_File_ModuleLocal_Impl --------------------------------------------- - -namespace { - -bool CreateThreadAdapterForInstance(PP_Instance instance) { - return false; // No multithreaded access allowed. -} - -void ClearThreadAdapterForInstance(PP_Instance instance) { -} - -int32_t OpenModuleLocalFile(PP_Instance pp_instance, - const char* path, - int32_t mode, - PP_FileHandle* file) { - int flags = 0; - if (!path || - !::ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, &flags) || - !file) - return PP_ERROR_BADARGUMENT; - - PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); - if (!instance) - return PP_ERROR_FAILED; - - base::PlatformFile base_file; - base::PlatformFileError result = instance->delegate()->OpenFile( - PepperFilePath::MakeModuleLocal(instance->module(), path), - flags, - &base_file); - *file = base_file; - return ::ppapi::PlatformFileErrorToPepperError(result); -} - -int32_t RenameModuleLocalFile(PP_Instance pp_instance, - const char* from_path, - const char* to_path) { - if (!from_path || !to_path) - return PP_ERROR_BADARGUMENT; - - PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); - if (!instance) - return PP_ERROR_FAILED; - - base::PlatformFileError result = instance->delegate()->RenameFile( - PepperFilePath::MakeModuleLocal(instance->module(), from_path), - PepperFilePath::MakeModuleLocal(instance->module(), to_path)); - return ::ppapi::PlatformFileErrorToPepperError(result); -} - -int32_t DeleteModuleLocalFileOrDir(PP_Instance pp_instance, - const char* path, - PP_Bool recursive) { - if (!path) - return PP_ERROR_BADARGUMENT; - - PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); - if (!instance) - return PP_ERROR_FAILED; - - base::PlatformFileError result = instance->delegate()->DeleteFileOrDir( - PepperFilePath::MakeModuleLocal(instance->module(), path), - PPBoolToBool(recursive)); - return ::ppapi::PlatformFileErrorToPepperError(result); -} - -int32_t CreateModuleLocalDir(PP_Instance pp_instance, const char* path) { - if (!path) - return PP_ERROR_BADARGUMENT; - - PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); - if (!instance) - return PP_ERROR_FAILED; - - base::PlatformFileError result = instance->delegate()->CreateDir( - PepperFilePath::MakeModuleLocal(instance->module(), path)); - return ::ppapi::PlatformFileErrorToPepperError(result); -} - -int32_t QueryModuleLocalFile(PP_Instance pp_instance, - const char* path, - PP_FileInfo* info) { - if (!path || !info) - return PP_ERROR_BADARGUMENT; - - PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); - if (!instance) - return PP_ERROR_FAILED; - - base::PlatformFileInfo file_info; - base::PlatformFileError result = instance->delegate()->QueryFile( - PepperFilePath::MakeModuleLocal(instance->module(), path), - &file_info); - if (result == base::PLATFORM_FILE_OK) { - info->size = file_info.size; - info->creation_time = TimeToPPTime(file_info.creation_time); - info->last_access_time = TimeToPPTime(file_info.last_accessed); - info->last_modified_time = TimeToPPTime(file_info.last_modified); - info->system_type = PP_FILESYSTEMTYPE_EXTERNAL; - if (file_info.is_directory) - info->type = PP_FILETYPE_DIRECTORY; - else - info->type = PP_FILETYPE_REGULAR; - } - return ::ppapi::PlatformFileErrorToPepperError(result); -} - -int32_t GetModuleLocalDirContents(PP_Instance pp_instance, - const char* path, - PP_DirContents_Dev** contents) { - if (!path || !contents) - return PP_ERROR_BADARGUMENT; - PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); - if (!instance) - return PP_ERROR_FAILED; - - *contents = NULL; - DirContents pepper_contents; - base::PlatformFileError result = instance->delegate()->GetDirContents( - PepperFilePath::MakeModuleLocal(instance->module(), path), - &pepper_contents); - - if (result != base::PLATFORM_FILE_OK) - return ::ppapi::PlatformFileErrorToPepperError(result); - - *contents = new PP_DirContents_Dev; - size_t count = pepper_contents.size(); - (*contents)->count = count; - (*contents)->entries = new PP_DirEntry_Dev[count]; - for (size_t i = 0; i < count; ++i) { - PP_DirEntry_Dev& entry = (*contents)->entries[i]; -#if defined(OS_WIN) - const std::string& name = UTF16ToUTF8(pepper_contents[i].name.value()); -#else - const std::string& name = pepper_contents[i].name.value(); -#endif - size_t size = name.size() + 1; - char* name_copy = new char[size]; - memcpy(name_copy, name.c_str(), size); - entry.name = name_copy; - entry.is_dir = BoolToPPBool(pepper_contents[i].is_dir); - } - return PP_OK; -} - -const PPB_Flash_File_ModuleLocal ppb_flash_file_modulelocal = { - &CreateThreadAdapterForInstance, - &ClearThreadAdapterForInstance, - &OpenModuleLocalFile, - &RenameModuleLocalFile, - &DeleteModuleLocalFileOrDir, - &CreateModuleLocalDir, - &QueryModuleLocalFile, - &GetModuleLocalDirContents, - &FreeDirContents, -}; - -} // namespace - -// static -const PPB_Flash_File_ModuleLocal* - PPB_Flash_File_ModuleLocal_Impl::GetInterface() { - return &ppb_flash_file_modulelocal; -} - -// PPB_Flash_File_FileRef_Impl ------------------------------------------------- - -namespace { - -int32_t OpenFileRefFile(PP_Resource file_ref_id, - int32_t mode, - PP_FileHandle* file) { - int flags = 0; - if (!::ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, &flags) || !file) - return PP_ERROR_BADARGUMENT; - - EnterResource<PPB_FileRef_API> enter(file_ref_id, true); - if (enter.failed()) - return PP_ERROR_BADRESOURCE; - PPB_FileRef_Impl* file_ref = static_cast<PPB_FileRef_Impl*>(enter.object()); - - PluginInstance* instance = ResourceHelper::GetPluginInstance(file_ref); - if (!instance) - return PP_ERROR_FAILED; - - base::PlatformFile base_file; - base::PlatformFileError result = instance->delegate()->OpenFile( - PepperFilePath::MakeAbsolute(file_ref->GetSystemPath()), - flags, - &base_file); - *file = base_file; - return ::ppapi::PlatformFileErrorToPepperError(result); -} - -int32_t QueryFileRefFile(PP_Resource file_ref_id, - PP_FileInfo* info) { - EnterResource<PPB_FileRef_API> enter(file_ref_id, true); - if (enter.failed()) - return PP_ERROR_BADRESOURCE; - PPB_FileRef_Impl* file_ref = static_cast<PPB_FileRef_Impl*>(enter.object()); - - PluginInstance* instance = ResourceHelper::GetPluginInstance(file_ref); - if (!instance) - return PP_ERROR_FAILED; - - base::PlatformFileInfo file_info; - base::PlatformFileError result = instance->delegate()->QueryFile( - PepperFilePath::MakeAbsolute(file_ref->GetSystemPath()), - &file_info); - if (result == base::PLATFORM_FILE_OK) { - info->size = file_info.size; - info->creation_time = TimeToPPTime(file_info.creation_time); - info->last_access_time = TimeToPPTime(file_info.last_accessed); - info->last_modified_time = TimeToPPTime(file_info.last_modified); - info->system_type = PP_FILESYSTEMTYPE_EXTERNAL; - if (file_info.is_directory) - info->type = PP_FILETYPE_DIRECTORY; - else - info->type = PP_FILETYPE_REGULAR; - } - return ::ppapi::PlatformFileErrorToPepperError(result); -} - -const PPB_Flash_File_FileRef ppb_flash_file_fileref = { - &OpenFileRefFile, - &QueryFileRefFile, -}; - -} // namespace - -// static -const PPB_Flash_File_FileRef* PPB_Flash_File_FileRef_Impl::GetInterface() { - return &ppb_flash_file_fileref; -} - -} // namespace ppapi -} // namespace webkit diff --git a/webkit/plugins/ppapi/ppb_flash_file_impl.h b/webkit/plugins/ppapi/ppb_flash_file_impl.h deleted file mode 100644 index ddfba9d..0000000 --- a/webkit/plugins/ppapi/ppb_flash_file_impl.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef WEBKIT_PLUGINS_PPAPI_PPB_FLASH_FILE_IMPL_H_ -#define WEBKIT_PLUGINS_PPAPI_PPB_FLASH_FILE_IMPL_H_ - -struct PPB_Flash_File_FileRef; -struct PPB_Flash_File_ModuleLocal; - -namespace webkit { -namespace ppapi { - -class PPB_Flash_File_ModuleLocal_Impl { - public: - static const PPB_Flash_File_ModuleLocal* GetInterface(); -}; - -class PPB_Flash_File_FileRef_Impl { - public: - static const PPB_Flash_File_FileRef* GetInterface(); -}; - -} // namespace ppapi -} // namespace webkit - -#endif // WEBKIT_PLUGINS_PPAPI_PPB_FLASH_FILE_IMPL_H_ diff --git a/webkit/plugins/ppapi/ppb_flash_impl.cc b/webkit/plugins/ppapi/ppb_flash_impl.cc index 16780ca..3b2d633 100644 --- a/webkit/plugins/ppapi/ppb_flash_impl.cc +++ b/webkit/plugins/ppapi/ppb_flash_impl.cc @@ -13,9 +13,11 @@ #include "googleurl/src/gurl.h" #include "ppapi/c/dev/ppb_font_dev.h" #include "ppapi/c/private/ppb_flash.h" +#include "ppapi/shared_impl/file_type_conversion.h" #include "ppapi/shared_impl/time_conversion.h" #include "ppapi/shared_impl/var.h" #include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_file_ref_api.h" #include "ppapi/thunk/ppb_image_data_api.h" #include "skia/ext/platform_canvas.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -28,17 +30,22 @@ #include "webkit/glue/clipboard_client.h" #include "webkit/glue/scoped_clipboard_writer_glue.h" #include "webkit/plugins/ppapi/common.h" +#include "webkit/plugins/ppapi/file_path.h" #include "webkit/plugins/ppapi/host_globals.h" #include "webkit/plugins/ppapi/plugin_delegate.h" #include "webkit/plugins/ppapi/plugin_module.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/ppb_file_ref_impl.h" #include "webkit/plugins/ppapi/ppb_url_request_info_impl.h" #include "webkit/plugins/ppapi/resource_helper.h" #include "webkit/plugins/ppapi/ppb_image_data_impl.h" using ppapi::PPTimeToTime; using ppapi::StringVar; +using ppapi::TimeToPPTime; +using ppapi::thunk::EnterResource; using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_FileRef_API; using ppapi::thunk::PPB_ImageData_API; using ppapi::thunk::PPB_URLRequestInfo_API; @@ -366,6 +373,203 @@ int32_t PPB_Flash_Impl::WriteClipboardData( return PP_OK; } +bool PPB_Flash_Impl::CreateThreadAdapterForInstance(PP_Instance instance) { + return false; // No multithreaded access allowed. +} + +void PPB_Flash_Impl::ClearThreadAdapterForInstance(PP_Instance instance) { +} + +int32_t PPB_Flash_Impl::OpenFile(PP_Instance pp_instance, + const char* path, + int32_t mode, + PP_FileHandle* file) { + int flags = 0; + if (!path || + !::ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, &flags) || + !file) + return PP_ERROR_BADARGUMENT; + + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + base::PlatformFile base_file; + base::PlatformFileError result = instance->delegate()->OpenFile( + PepperFilePath::MakeModuleLocal(instance->module(), path), + flags, + &base_file); + *file = base_file; + return ::ppapi::PlatformFileErrorToPepperError(result); +} + +int32_t PPB_Flash_Impl::RenameFile(PP_Instance pp_instance, + const char* path_from, + const char* path_to) { + if (!path_from || !path_to) + return PP_ERROR_BADARGUMENT; + + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + base::PlatformFileError result = instance->delegate()->RenameFile( + PepperFilePath::MakeModuleLocal(instance->module(), path_from), + PepperFilePath::MakeModuleLocal(instance->module(), path_to)); + return ::ppapi::PlatformFileErrorToPepperError(result); +} + +int32_t PPB_Flash_Impl::DeleteFileOrDir(PP_Instance pp_instance, + const char* path, + PP_Bool recursive) { + if (!path) + return PP_ERROR_BADARGUMENT; + + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + base::PlatformFileError result = instance->delegate()->DeleteFileOrDir( + PepperFilePath::MakeModuleLocal(instance->module(), path), + PPBoolToBool(recursive)); + return ::ppapi::PlatformFileErrorToPepperError(result); +} + +int32_t PPB_Flash_Impl::CreateDir(PP_Instance pp_instance, const char* path) { + if (!path) + return PP_ERROR_BADARGUMENT; + + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + base::PlatformFileError result = instance->delegate()->CreateDir( + PepperFilePath::MakeModuleLocal(instance->module(), path)); + return ::ppapi::PlatformFileErrorToPepperError(result); +} + +int32_t PPB_Flash_Impl::QueryFile(PP_Instance pp_instance, + const char* path, + PP_FileInfo* info) { + if (!path || !info) + return PP_ERROR_BADARGUMENT; + + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + base::PlatformFileInfo file_info; + base::PlatformFileError result = instance->delegate()->QueryFile( + PepperFilePath::MakeModuleLocal(instance->module(), path), + &file_info); + if (result == base::PLATFORM_FILE_OK) { + info->size = file_info.size; + info->creation_time = TimeToPPTime(file_info.creation_time); + info->last_access_time = TimeToPPTime(file_info.last_accessed); + info->last_modified_time = TimeToPPTime(file_info.last_modified); + info->system_type = PP_FILESYSTEMTYPE_EXTERNAL; + if (file_info.is_directory) + info->type = PP_FILETYPE_DIRECTORY; + else + info->type = PP_FILETYPE_REGULAR; + } + return ::ppapi::PlatformFileErrorToPepperError(result); +} + +int32_t PPB_Flash_Impl::GetDirContents(PP_Instance pp_instance, + const char* path, + PP_DirContents_Dev** contents) { + if (!path || !contents) + return PP_ERROR_BADARGUMENT; + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + *contents = NULL; + DirContents pepper_contents; + base::PlatformFileError result = instance->delegate()->GetDirContents( + PepperFilePath::MakeModuleLocal(instance->module(), path), + &pepper_contents); + + if (result != base::PLATFORM_FILE_OK) + return ::ppapi::PlatformFileErrorToPepperError(result); + + *contents = new PP_DirContents_Dev; + size_t count = pepper_contents.size(); + (*contents)->count = count; + (*contents)->entries = new PP_DirEntry_Dev[count]; + for (size_t i = 0; i < count; ++i) { + PP_DirEntry_Dev& entry = (*contents)->entries[i]; +#if defined(OS_WIN) + const std::string& name = UTF16ToUTF8(pepper_contents[i].name.value()); +#else + const std::string& name = pepper_contents[i].name.value(); +#endif + size_t size = name.size() + 1; + char* name_copy = new char[size]; + memcpy(name_copy, name.c_str(), size); + entry.name = name_copy; + entry.is_dir = BoolToPPBool(pepper_contents[i].is_dir); + } + return PP_OK; +} + +int32_t PPB_Flash_Impl::OpenFileRef(PP_Instance pp_instance, + PP_Resource file_ref_id, + int32_t mode, + PP_FileHandle* file) { + int flags = 0; + if (!::ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, &flags) || !file) + return PP_ERROR_BADARGUMENT; + + EnterResourceNoLock<PPB_FileRef_API> enter(file_ref_id, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + PPB_FileRef_Impl* file_ref = static_cast<PPB_FileRef_Impl*>(enter.object()); + + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + base::PlatformFile base_file; + base::PlatformFileError result = instance->delegate()->OpenFile( + PepperFilePath::MakeAbsolute(file_ref->GetSystemPath()), + flags, + &base_file); + *file = base_file; + return ::ppapi::PlatformFileErrorToPepperError(result); +} + +int32_t PPB_Flash_Impl::QueryFileRef(PP_Instance pp_instance, + PP_Resource file_ref_id, + PP_FileInfo* info) { + EnterResource<PPB_FileRef_API> enter(file_ref_id, true); + if (enter.failed()) + return PP_ERROR_BADRESOURCE; + PPB_FileRef_Impl* file_ref = static_cast<PPB_FileRef_Impl*>(enter.object()); + + PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); + if (!instance) + return PP_ERROR_FAILED; + + base::PlatformFileInfo file_info; + base::PlatformFileError result = instance->delegate()->QueryFile( + PepperFilePath::MakeAbsolute(file_ref->GetSystemPath()), + &file_info); + if (result == base::PLATFORM_FILE_OK) { + info->size = file_info.size; + info->creation_time = TimeToPPTime(file_info.creation_time); + info->last_access_time = TimeToPPTime(file_info.last_accessed); + info->last_modified_time = TimeToPPTime(file_info.last_modified); + info->system_type = PP_FILESYSTEMTYPE_EXTERNAL; + if (file_info.is_directory) + info->type = PP_FILETYPE_DIRECTORY; + else + info->type = PP_FILETYPE_REGULAR; + } + return ::ppapi::PlatformFileErrorToPepperError(result); +} + PP_Bool PPB_Flash_Impl::FlashIsFullscreen(PP_Instance instance) { return PP_FromBool(instance_->flash_fullscreen()); } diff --git a/webkit/plugins/ppapi/ppb_flash_impl.h b/webkit/plugins/ppapi/ppb_flash_impl.h index 911f5ae..57abf90 100644 --- a/webkit/plugins/ppapi/ppb_flash_impl.h +++ b/webkit/plugins/ppapi/ppb_flash_impl.h @@ -67,6 +67,32 @@ class PPB_Flash_Impl : public ::ppapi::PPB_Flash_Shared { uint32_t data_item_count, const PP_Flash_Clipboard_Format formats[], const PP_Var data_items[]) OVERRIDE; + virtual bool CreateThreadAdapterForInstance(PP_Instance instance) OVERRIDE; + virtual void ClearThreadAdapterForInstance(PP_Instance instance) OVERRIDE; + virtual int32_t OpenFile(PP_Instance instance, + const char* path, + int32_t mode, + PP_FileHandle* file) OVERRIDE; + virtual int32_t RenameFile(PP_Instance instance, + const char* path_from, + const char* path_to) OVERRIDE; + virtual int32_t DeleteFileOrDir(PP_Instance instance, + const char* path, + PP_Bool recursive) OVERRIDE; + virtual int32_t CreateDir(PP_Instance instance, const char* path) OVERRIDE; + virtual int32_t QueryFile(PP_Instance instance, + const char* path, + PP_FileInfo* info) OVERRIDE; + virtual int32_t GetDirContents(PP_Instance instance, + const char* path, + PP_DirContents_Dev** contents) OVERRIDE; + virtual int32_t OpenFileRef(PP_Instance instance, + PP_Resource file_ref, + int32_t mode, + PP_FileHandle* file) OVERRIDE; + virtual int32_t QueryFileRef(PP_Instance instance, + PP_Resource file_ref, + PP_FileInfo* info) OVERRIDE; virtual PP_Bool FlashIsFullscreen(PP_Instance instance) OVERRIDE; virtual PP_Bool FlashSetFullscreen(PP_Instance instance, PP_Bool fullscreen) OVERRIDE; |