| // 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. | 
 |  | 
 | #ifndef PPAPI_PROXY_HOST_DISPATCHER_H_ | 
 | #define PPAPI_PROXY_HOST_DISPATCHER_H_ | 
 |  | 
 | #include <map> | 
 | #include <string> | 
 | #include <unordered_map> | 
 | #include <vector> | 
 |  | 
 | #include "base/compiler_specific.h" | 
 | #include "base/macros.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "base/observer_list.h" | 
 | #include "base/process/process.h" | 
 | #include "ipc/message_filter.h" | 
 | #include "ppapi/c/pp_instance.h" | 
 | #include "ppapi/proxy/dispatcher.h" | 
 |  | 
 | struct PPB_Proxy_Private; | 
 |  | 
 | namespace ppapi { | 
 |  | 
 | struct Preferences; | 
 |  | 
 | namespace proxy { | 
 |  | 
 | class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher { | 
 |  public: | 
 |   // This interface receives notifications about sync messages being sent by | 
 |   // the dispatcher to the plugin process. Some parts of Chrome may need to | 
 |   // know whether we are sending a synchronous message to the plugin; e.g. to | 
 |   // detect a hung plugin or to avoid re-entering JavaScript. | 
 |   // | 
 |   // Note that there can be nested sync messages, so the begin/end status | 
 |   // actually represents a stack of blocking messages. | 
 |   class SyncMessageStatusObserver { | 
 |    public: | 
 |     // Notification that a sync message is about to be sent out. | 
 |     virtual void BeginBlockOnSyncMessage() = 0; | 
 |  | 
 |     // Notification that a sync message reply was received and the dispatcher | 
 |     // is no longer blocked on a sync message. | 
 |     virtual void EndBlockOnSyncMessage() = 0; | 
 |  | 
 |    protected: | 
 |     virtual ~SyncMessageStatusObserver() {} | 
 |   }; | 
 |  | 
 |   // Constructor for the renderer side. This will take a reference to the | 
 |   // SyncMessageStatusReceiver. | 
 |   // | 
 |   // You must call InitHostWithChannel after the constructor. | 
 |   HostDispatcher(PP_Module module, | 
 |                  PP_GetInterface_Func local_get_interface, | 
 |                  const PpapiPermissions& permissions); | 
 |   ~HostDispatcher(); | 
 |  | 
 |   // You must call this function before anything else. Returns true on success. | 
 |   // The delegate pointer must outlive this class, ownership is not | 
 |   // transferred. | 
 |   virtual bool InitHostWithChannel( | 
 |       Delegate* delegate, | 
 |       base::ProcessId peer_pid, | 
 |       const IPC::ChannelHandle& channel_handle, | 
 |       bool is_client, | 
 |       const Preferences& preferences, | 
 |       scoped_refptr<base::SingleThreadTaskRunner> task_runner); | 
 |  | 
 |   // The host side maintains a mapping from PP_Instance to Dispatcher so | 
 |   // that we can send the messages to the right channel. | 
 |   static HostDispatcher* GetForInstance(PP_Instance instance); | 
 |   static void SetForInstance(PP_Instance instance, | 
 |                              HostDispatcher* dispatcher); | 
 |   static void RemoveForInstance(PP_Instance instance); | 
 |  | 
 |   // Returns the host's notion of our PP_Module. This will be different than | 
 |   // the plugin's notion of its PP_Module because the plugin process may be | 
 |   // used by multiple renderer processes. | 
 |   // | 
 |   // Use this value instead of a value from the plugin whenever talking to the | 
 |   // host. | 
 |   PP_Module pp_module() const { return pp_module_; } | 
 |  | 
 |   // Dispatcher overrides. | 
 |   bool IsPlugin() const override; | 
 |   bool Send(IPC::Message* msg) override; | 
 |  | 
 |   // IPC::Listener. | 
 |   bool OnMessageReceived(const IPC::Message& msg) override; | 
 |   void OnChannelError() override; | 
 |  | 
 |   // Proxied version of calling GetInterface on the plugin. This will check | 
 |   // if the plugin supports the given interface (with caching) and returns the | 
 |   // pointer to the proxied interface if it is supported. Returns NULL if the | 
 |   // given interface isn't supported by the plugin or the proxy. | 
 |   const void* GetProxiedInterface(const std::string& iface_name); | 
 |  | 
 |   // See the value below. Call this when processing a scripting message from | 
 |   // the plugin that can be reentered. This is set to false at the beginning | 
 |   // of processing of each message from the plugin. | 
 |   void set_allow_plugin_reentrancy() { | 
 |     allow_plugin_reentrancy_ = true; | 
 |   } | 
 |  | 
 |   // Returns the proxy interface for talking to the implementation. | 
 |   const PPB_Proxy_Private* ppb_proxy() const { return ppb_proxy_; } | 
 |  | 
 |   // Register an observer that will be invoked when the dispatcher begins | 
 |   // sending a sync message and finishes sending a sync message. | 
 |   // Returns a Closure that can be used to unregister the observer (the Closure | 
 |   // is bound to a weak pointer, so is safe to call even after the | 
 |   // HostDispatcher is gone.) | 
 |   base::Closure AddSyncMessageStatusObserver(SyncMessageStatusObserver* obs); | 
 |  | 
 |   void AddFilter(IPC::Listener* listener); | 
 |  | 
 |  protected: | 
 |   // Overridden from Dispatcher. | 
 |   void OnInvalidMessageReceived() override; | 
 |  | 
 |  private: | 
 |   void OnHostMsgLogWithSource(PP_Instance instance, | 
 |                               int int_log_level, | 
 |                               const std::string& source, | 
 |                               const std::string& value); | 
 |  | 
 |   void RemoveSyncMessageStatusObserver(SyncMessageStatusObserver* obs); | 
 |  | 
 |   PP_Module pp_module_; | 
 |  | 
 |   // Maps interface name to whether that interface is supported. If an interface | 
 |   // name is not in the map, that implies that we haven't queried for it yet. | 
 |   typedef std::unordered_map<std::string, bool> PluginSupportedMap; | 
 |   PluginSupportedMap plugin_supported_; | 
 |  | 
 |   // Guaranteed non-NULL. | 
 |   const PPB_Proxy_Private* ppb_proxy_; | 
 |  | 
 |   // Set to true when the plugin is in a state that it can be reentered by a | 
 |   // sync message from the host. We allow reentrancy only when we're processing | 
 |   // a sync message from the renderer that is a scripting command. When the | 
 |   // plugin is in this state, it needs to accept reentrancy since scripting may | 
 |   // ultimately call back into the plugin. | 
 |   bool allow_plugin_reentrancy_; | 
 |  | 
 |   base::ObserverList<SyncMessageStatusObserver>::Unchecked | 
 |       sync_status_observer_list_; | 
 |  | 
 |   std::vector<IPC::Listener*> filters_; | 
 |  | 
 |   base::WeakPtrFactory<HostDispatcher> weak_ptr_factory_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(HostDispatcher); | 
 | }; | 
 |  | 
 | // Create this object on the stack to prevent the module (and hence the | 
 | // dispatcher) from being deleted out from under you. This is necessary when | 
 | // calling some scripting functions that may delete the plugin. | 
 | // | 
 | // This class does nothing if used on the plugin side. | 
 | class ScopedModuleReference { | 
 |  public: | 
 |   explicit ScopedModuleReference(Dispatcher* dispatcher); | 
 |   ~ScopedModuleReference(); | 
 |  | 
 |  private: | 
 |   HostDispatcher* dispatcher_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(ScopedModuleReference); | 
 | }; | 
 |  | 
 | }  // namespace proxy | 
 | }  // namespace ppapi | 
 |  | 
 | #endif  // PPAPI_PROXY_HOST_DISPATCHER_H_ |