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