1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
// Copyright 2012 The Chromium Authors
// 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/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/process/process.h"
#include "base/task/single_thread_task_runner.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(const HostDispatcher&) = delete;
HostDispatcher& operator=(const HostDispatcher&) = delete;
~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 OnceClosure that can be used to unregister the observer (the
// OnceClosure is bound to a weak pointer, so is safe to call even after the
// HostDispatcher is gone.)
base::OnceClosure 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_{this};
};
// 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(const ScopedModuleReference&) = delete;
ScopedModuleReference& operator=(const ScopedModuleReference&) = delete;
~ScopedModuleReference();
private:
HostDispatcher* dispatcher_;
};
} // namespace proxy
} // namespace ppapi
#endif // PPAPI_PROXY_HOST_DISPATCHER_H_
|