15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PPAPI_PROXY_HOST_DISPATCHER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PPAPI_PROXY_HOST_DISPATCHER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
1334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "base/memory/weak_ptr.h"
1434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "base/observer_list.h"
1558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ipc/message_filter.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_instance.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/dispatcher.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PPB_Proxy_Private;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Preferences;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PPAPI_PROXY_EXPORT HostDispatcher : public Dispatcher {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This interface receives notifications about sync messages being sent by
3134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // the dispatcher to the plugin process. Some parts of Chrome may need to
3234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // know whether we are sending a synchronous message to the plugin; e.g. to
3334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // detect a hung plugin or to avoid re-entering JavaScript.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that there can be nested sync messages, so the begin/end status
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // actually represents a stack of blocking messages.
3734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  class SyncMessageStatusObserver {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Notification that a sync message is about to be sent out.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void BeginBlockOnSyncMessage() = 0;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Notification that a sync message reply was received and the dispatcher
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is no longer blocked on a sync message.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void EndBlockOnSyncMessage() = 0;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   protected:
4734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    virtual ~SyncMessageStatusObserver() {}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Constructor for the renderer side. This will take a reference to the
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyncMessageStatusReceiver.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // You must call InitHostWithChannel after the constructor.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostDispatcher(PP_Module module,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 PP_GetInterface_Func local_get_interface,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const PpapiPermissions& permissions);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~HostDispatcher();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // You must call this function before anything else. Returns true on success.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The delegate pointer must outlive this class, ownership is not
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transferred.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool InitHostWithChannel(Delegate* delegate,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   base::ProcessId peer_pid,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const IPC::ChannelHandle& channel_handle,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool is_client,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const Preferences& preferences);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The host side maintains a mapping from PP_Instance to Dispatcher so
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that we can send the messages to the right channel.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static HostDispatcher* GetForInstance(PP_Instance instance);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SetForInstance(PP_Instance instance,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             HostDispatcher* dispatcher);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void RemoveForInstance(PP_Instance instance);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the host's notion of our PP_Module. This will be different than
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the plugin's notion of its PP_Module because the plugin process may be
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // used by multiple renderer processes.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use this value instead of a value from the plugin whenever talking to the
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // host.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Module pp_module() const { return pp_module_; }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dispatcher overrides.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsPlugin() const;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Send(IPC::Message* msg);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPC::Listener.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnChannelError() OVERRIDE;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Proxied version of calling GetInterface on the plugin. This will check
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the plugin supports the given interface (with caching) and returns the
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pointer to the proxied interface if it is supported. Returns NULL if the
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // given interface isn't supported by the plugin or the proxy.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* GetProxiedInterface(const std::string& iface_name);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the value below. Call this when processing a scripting message from
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the plugin that can be reentered. This is set to false at the beginning
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of processing of each message from the plugin.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_allow_plugin_reentrancy() {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_plugin_reentrancy_ = true;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the proxy interface for talking to the implementation.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_Proxy_Private* ppb_proxy() const { return ppb_proxy_; }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // Register an observer that will be invoked when the dispatcher begins
10834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // sending a sync message and finishes sending a sync message.
10934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // Returns a Closure that can be used to unregister the observer (the Closure
11034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // is bound to a weak pointer, so is safe to call even after the
11134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // HostDispatcher is gone.)
11234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  base::Closure AddSyncMessageStatusObserver(SyncMessageStatusObserver* obs);
11334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void AddFilter(IPC::Listener* listener);
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from Dispatcher.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnInvalidMessageReceived();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHostMsgLogWithSource(PP_Instance instance,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int int_log_level,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& source,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& value);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  void RemoveSyncMessageStatusObserver(SyncMessageStatusObserver* obs);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Module pp_module_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maps interface name to whether that interface is supported. If an interface
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // name is not in the map, that implies that we haven't queried for it yet.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef base::hash_map<std::string, bool> PluginSupportedMap;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginSupportedMap plugin_supported_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Guaranteed non-NULL.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_Proxy_Private* ppb_proxy_;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to true when the plugin is in a state that it can be reentered by a
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sync message from the host. We allow reentrancy only when we're processing
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a sync message from the renderer that is a scripting command. When the
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // plugin is in this state, it needs to accept reentrancy since scripting may
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ultimately call back into the plugin.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool allow_plugin_reentrancy_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  ObserverList<SyncMessageStatusObserver> sync_status_observer_list_;
14634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<IPC::Listener*> filters_;
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
14934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  base::WeakPtrFactory<HostDispatcher> weak_ptr_factory_;
15034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HostDispatcher);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Create this object on the stack to prevent the module (and hence the
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dispatcher) from being deleted out from under you. This is necessary when
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calling some scripting functions that may delete the plugin.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class does nothing if used on the plugin side.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedModuleReference {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ScopedModuleReference(Dispatcher* dispatcher);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ScopedModuleReference();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostDispatcher* dispatcher_;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedModuleReference);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace proxy
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // PPAPI_PROXY_HOST_DISPATCHER_H_
174