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_PLUGIN_DISPATCHER_H_ 6 #define PPAPI_PROXY_PLUGIN_DISPATCHER_H_ 7 8 #include <stdint.h> 9 10 #include <set> 11 #include <string> 12 #include <unordered_map> 13 14 #include "base/macros.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/process/process.h" 18 #include "build/build_config.h" 19 #include "ipc/ipc_sync_channel.h" 20 #include "ppapi/c/pp_instance.h" 21 #include "ppapi/c/pp_rect.h" 22 #include "ppapi/c/ppb_console.h" 23 #include "ppapi/proxy/dispatcher.h" 24 #include "ppapi/proxy/message_handler.h" 25 #include "ppapi/shared_impl/ppapi_preferences.h" 26 #include "ppapi/shared_impl/ppb_view_shared.h" 27 #include "ppapi/shared_impl/singleton_resource_id.h" 28 #include "ppapi/shared_impl/tracked_callback.h" 29 30 namespace IPC { 31 class SyncMessageFilter; 32 } 33 34 namespace ppapi { 35 36 struct Preferences; 37 class Resource; 38 39 namespace thunk { 40 class PPB_Instance_API; 41 class ResourceCreationAPI; 42 } 43 44 namespace proxy { 45 46 // Used to keep track of per-instance data. 47 struct PPAPI_PROXY_EXPORT InstanceData { 48 InstanceData(); 49 ~InstanceData(); 50 51 ViewData view; 52 53 // When non-NULL, indicates the callback to execute when mouse lock is lost. 54 scoped_refptr<TrackedCallback> mouse_lock_callback; 55 56 // A map of singleton resources which are lazily created. 57 typedef std::map<SingletonResourceID, scoped_refptr<Resource>> 58 SingletonResourceMap; 59 SingletonResourceMap singleton_resources; 60 61 // Calls to |RequestSurroundingText()| are done by posted tasks. Track whether 62 // a) a task is pending, to avoid redundant calls, and b) whether we should 63 // actually call |RequestSurroundingText()|, to avoid stale calls (i.e., 64 // calling when we shouldn't). 65 bool is_request_surrounding_text_pending; 66 bool should_do_request_surrounding_text; 67 68 // The message handler which should handle JavaScript->Plugin messages, if 69 // one has been registered, otherwise NULL. 70 std::unique_ptr<MessageHandler> message_handler; 71 72 // Flush info for PpapiCommandBufferProxy::OrderingBarrier(). 73 struct PPAPI_PROXY_EXPORT FlushInfo { 74 FlushInfo(); 75 ~FlushInfo(); 76 bool flush_pending; 77 HostResource resource; 78 int32_t put_offset; 79 }; 80 FlushInfo flush_info; 81 }; 82 83 class PPAPI_PROXY_EXPORT LockedSender { 84 public: 85 // Unlike |Send()|, this function continues to hold the Pepper proxy lock 86 // until we are finished sending |msg|, even if it is a synchronous message. 87 virtual bool SendAndStayLocked(IPC::Message* msg) = 0; 88 89 protected: ~LockedSender()90 virtual ~LockedSender() {} 91 }; 92 93 class PPAPI_PROXY_EXPORT PluginDispatcher 94 : public Dispatcher, 95 public LockedSender, 96 public base::SupportsWeakPtr<PluginDispatcher> { 97 public: 98 class PPAPI_PROXY_EXPORT PluginDelegate : public ProxyChannel::Delegate { 99 public: 100 // Returns the set used for globally uniquifying PP_Instances. This same 101 // set must be returned for all channels. 102 // 103 // DEREFERENCE ONLY ON THE I/O THREAD. 104 virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() = 0; 105 106 // Registers the plugin dispatcher and returns an ID. 107 // Plugin dispatcher IDs will be used to dispatch messages from the browser. 108 // Each call to Register() has to be matched with a call to Unregister(). 109 virtual uint32_t Register(PluginDispatcher* plugin_dispatcher) = 0; 110 virtual void Unregister(uint32_t plugin_dispatcher_id) = 0; 111 }; 112 113 class Sender : public IPC::Sender, 114 public base::RefCountedThreadSafe<PluginDispatcher::Sender> { 115 public: 116 Sender(base::WeakPtr<PluginDispatcher> plugin_dispatcher, 117 scoped_refptr<IPC::SyncMessageFilter> sync_filter); 118 ~Sender() override; 119 120 bool SendMessage(IPC::Message* msg); 121 122 // IPC::Sender 123 bool Send(IPC::Message* msg) override; 124 125 private: 126 base::WeakPtr<PluginDispatcher> plugin_dispatcher_; 127 scoped_refptr<IPC::SyncMessageFilter> sync_filter_; 128 129 DISALLOW_COPY_AND_ASSIGN(Sender); 130 }; 131 132 // Constructor for the plugin side. The init and shutdown functions will be 133 // will be automatically called when requested by the renderer side. The 134 // module ID will be set upon receipt of the InitializeModule message. 135 // 136 // Note about permissions: On the plugin side, the dispatcher and the plugin 137 // run in the same address space (including in nacl). This means that the 138 // permissions here are subject to malicious modification and bypass, and 139 // an exploited or malicious plugin could send any IPC messages and just 140 // bypass the permissions. All permissions must be checked "for realz" in the 141 // host process when receiving messages. We check them on the plugin side 142 // primarily to keep honest plugins honest, especially with respect to 143 // dev interfaces that they "shouldn't" be using. 144 // 145 // You must call InitPluginWithChannel after the constructor. 146 PluginDispatcher(PP_GetInterface_Func get_interface, 147 const PpapiPermissions& permissions, 148 bool incognito); 149 virtual ~PluginDispatcher(); 150 151 // The plugin side maintains a mapping from PP_Instance to Dispatcher so 152 // that we can send the messages to the right channel if there are multiple 153 // renderers sharing the same plugin. This mapping is maintained by 154 // DidCreateInstance/DidDestroyInstance. 155 static PluginDispatcher* GetForInstance(PP_Instance instance); 156 157 // Same as GetForInstance but retrieves the instance from the given resource 158 // object as a convenience. Returns NULL on failure. 159 static PluginDispatcher* GetForResource(const Resource* resource); 160 161 // Implements the GetInterface function for the plugin to call to retrieve 162 // a browser interface. 163 static const void* GetBrowserInterface(const char* interface_name); 164 165 // Logs the given log message to the given instance, or, if the instance is 166 // invalid, to all instances associated with all dispatchers. Used for 167 // global log messages. 168 static void LogWithSource(PP_Instance instance, 169 PP_LogLevel level, 170 const std::string& source, 171 const std::string& value); 172 173 const void* GetPluginInterface(const std::string& interface_name); 174 175 // You must call this function before anything else. Returns true on success. 176 // The delegate pointer must outlive this class, ownership is not 177 // transferred. 178 bool InitPluginWithChannel(PluginDelegate* delegate, 179 base::ProcessId peer_pid, 180 const IPC::ChannelHandle& channel_handle, 181 bool is_client); 182 183 // Dispatcher overrides. 184 bool IsPlugin() const override; 185 // Send the message to the renderer. If |msg| is a synchronous message, we 186 // will unlock the ProxyLock so that we can handle incoming messages from the 187 // renderer. 188 bool Send(IPC::Message* msg) override; 189 190 // Unlike |Send()|, this function continues to hold the Pepper proxy lock 191 // until we are finished sending |msg|, even if it is a synchronous message. 192 bool SendAndStayLocked(IPC::Message* msg) override; 193 194 // IPC::Listener implementation. 195 bool OnMessageReceived(const IPC::Message& msg) override; 196 void OnChannelError() override; 197 198 // Keeps track of which dispatcher to use for each instance, active instances 199 // and tracks associated data like the current size. 200 void DidCreateInstance(PP_Instance instance); 201 void DidDestroyInstance(PP_Instance instance); 202 203 // Gets the data for an existing instance, or NULL if the instance id doesn't 204 // correspond to a known instance. 205 InstanceData* GetInstanceData(PP_Instance instance); 206 207 // Returns the corresponding API. These are APIs not associated with a 208 // resource. Guaranteed non-NULL. 209 thunk::PPB_Instance_API* GetInstanceAPI(); 210 thunk::ResourceCreationAPI* GetResourceCreationAPI(); 211 212 // Returns the Preferences. preferences()213 const Preferences& preferences() const { return preferences_; } 214 plugin_dispatcher_id()215 uint32_t plugin_dispatcher_id() const { return plugin_dispatcher_id_; } incognito()216 bool incognito() const { return incognito_; } 217 sender()218 scoped_refptr<Sender> sender() { return sender_; } 219 220 private: 221 friend class PluginDispatcherTest; 222 223 // Notifies all live instances that they're now closed. This is used when 224 // a renderer crashes or some other error is received. 225 void ForceFreeAllInstances(); 226 227 // IPC message handlers. 228 void OnMsgSupportsInterface(const std::string& interface_name, bool* result); 229 void OnMsgSetPreferences(const Preferences& prefs); 230 231 PluginDelegate* plugin_delegate_; 232 233 // Contains all the plugin interfaces we've queried. The mapped value will 234 // be the pointer to the interface pointer supplied by the plugin if it's 235 // supported, or NULL if it's not supported. This allows us to cache failures 236 // and not req-query if a plugin doesn't support the interface. 237 typedef std::unordered_map<std::string, const void*> InterfaceMap; 238 InterfaceMap plugin_interfaces_; 239 240 typedef std::unordered_map<PP_Instance, std::unique_ptr<InstanceData>> 241 InstanceDataMap; 242 InstanceDataMap instance_map_; 243 244 // The preferences sent from the host. We only want to set this once, which 245 // is what the received_preferences_ indicates. See OnMsgSetPreferences. 246 bool received_preferences_; 247 Preferences preferences_; 248 249 uint32_t plugin_dispatcher_id_; 250 251 // Set to true when the instances associated with this dispatcher are 252 // incognito mode. 253 bool incognito_; 254 255 scoped_refptr<Sender> sender_; 256 257 DISALLOW_COPY_AND_ASSIGN(PluginDispatcher); 258 }; 259 260 } // namespace proxy 261 } // namespace ppapi 262 263 #endif // PPAPI_PROXY_PLUGIN_DISPATCHER_H_ 264