1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef PPAPI_PROXY_HOST_DISPATCHER_H_ 6 #define PPAPI_PROXY_HOST_DISPATCHER_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/compiler_specific.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/process/process.h" 15 #include "ipc/message_filter.h" 16 #include "ppapi/c/pp_instance.h" 17 #include "ppapi/proxy/dispatcher.h" 18 19 struct PPB_Proxy_Private; 20 21 namespace ppapi { 22 23 struct Preferences; 24 25 namespace proxy { 26 27 class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher { 28 public: 29 // This interface receives notifications about sync messages being sent by 30 // the dispatcher to the plugin process. It is used to detect a hung plugin. 31 // 32 // Note that there can be nested sync messages, so the begin/end status 33 // actually represents a stack of blocking messages. 34 class SyncMessageStatusReceiver : public IPC::MessageFilter { 35 public: 36 // Notification that a sync message is about to be sent out. 37 virtual void BeginBlockOnSyncMessage() = 0; 38 39 // Notification that a sync message reply was received and the dispatcher 40 // is no longer blocked on a sync message. 41 virtual void EndBlockOnSyncMessage() = 0; 42 43 protected: ~SyncMessageStatusReceiver()44 virtual ~SyncMessageStatusReceiver() {} 45 }; 46 47 // Constructor for the renderer side. This will take a reference to the 48 // SyncMessageStatusReceiver. 49 // 50 // You must call InitHostWithChannel after the constructor. 51 HostDispatcher(PP_Module module, 52 PP_GetInterface_Func local_get_interface, 53 SyncMessageStatusReceiver* sync_status, 54 const PpapiPermissions& permissions); 55 ~HostDispatcher(); 56 57 // You must call this function before anything else. Returns true on success. 58 // The delegate pointer must outlive this class, ownership is not 59 // transferred. 60 virtual bool InitHostWithChannel(Delegate* delegate, 61 base::ProcessId peer_pid, 62 const IPC::ChannelHandle& channel_handle, 63 bool is_client, 64 const Preferences& preferences); 65 66 // The host side maintains a mapping from PP_Instance to Dispatcher so 67 // that we can send the messages to the right channel. 68 static HostDispatcher* GetForInstance(PP_Instance instance); 69 static void SetForInstance(PP_Instance instance, 70 HostDispatcher* dispatcher); 71 static void RemoveForInstance(PP_Instance instance); 72 73 // Returns the host's notion of our PP_Module. This will be different than 74 // the plugin's notion of its PP_Module because the plugin process may be 75 // used by multiple renderer processes. 76 // 77 // Use this value instead of a value from the plugin whenever talking to the 78 // host. pp_module()79 PP_Module pp_module() const { return pp_module_; } 80 81 // Dispatcher overrides. 82 virtual bool IsPlugin() const; 83 virtual bool Send(IPC::Message* msg); 84 85 // IPC::Listener. 86 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; 87 virtual void OnChannelError() OVERRIDE; 88 89 // Proxied version of calling GetInterface on the plugin. This will check 90 // if the plugin supports the given interface (with caching) and returns the 91 // pointer to the proxied interface if it is supported. Returns NULL if the 92 // given interface isn't supported by the plugin or the proxy. 93 const void* GetProxiedInterface(const std::string& iface_name); 94 95 // See the value below. Call this when processing a scripting message from 96 // the plugin that can be reentered. This is set to false at the beginning 97 // of processing of each message from the plugin. set_allow_plugin_reentrancy()98 void set_allow_plugin_reentrancy() { 99 allow_plugin_reentrancy_ = true; 100 } 101 102 // Returns the proxy interface for talking to the implementation. ppb_proxy()103 const PPB_Proxy_Private* ppb_proxy() const { return ppb_proxy_; } 104 105 void AddFilter(IPC::Listener* listener); 106 107 protected: 108 // Overridden from Dispatcher. 109 virtual void OnInvalidMessageReceived(); 110 111 private: 112 void OnHostMsgLogWithSource(PP_Instance instance, 113 int int_log_level, 114 const std::string& source, 115 const std::string& value); 116 117 scoped_refptr<SyncMessageStatusReceiver> sync_status_; 118 119 PP_Module pp_module_; 120 121 // Maps interface name to whether that interface is supported. If an interface 122 // name is not in the map, that implies that we haven't queried for it yet. 123 typedef base::hash_map<std::string, bool> PluginSupportedMap; 124 PluginSupportedMap plugin_supported_; 125 126 // Guaranteed non-NULL. 127 const PPB_Proxy_Private* ppb_proxy_; 128 129 // Set to true when the plugin is in a state that it can be reentered by a 130 // sync message from the host. We allow reentrancy only when we're processing 131 // a sync message from the renderer that is a scripting command. When the 132 // plugin is in this state, it needs to accept reentrancy since scripting may 133 // ultimately call back into the plugin. 134 bool allow_plugin_reentrancy_; 135 136 std::vector<IPC::Listener*> filters_; 137 138 DISALLOW_COPY_AND_ASSIGN(HostDispatcher); 139 }; 140 141 // Create this object on the stack to prevent the module (and hence the 142 // dispatcher) from being deleted out from under you. This is necessary when 143 // calling some scripting functions that may delete the plugin. 144 // 145 // This class does nothing if used on the plugin side. 146 class ScopedModuleReference { 147 public: 148 explicit ScopedModuleReference(Dispatcher* dispatcher); 149 ~ScopedModuleReference(); 150 151 private: 152 HostDispatcher* dispatcher_; 153 154 DISALLOW_COPY_AND_ASSIGN(ScopedModuleReference); 155 }; 156 157 } // namespace proxy 158 } // namespace ppapi 159 160 #endif // PPAPI_PROXY_HOST_DISPATCHER_H_ 161