summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/plugin_dispatcher.h
blob: 98f43a69fd8aad3519db4f637c0f72c8186307d3 (plain)
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// 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_PLUGIN_DISPATCHER_H_
#define PPAPI_PROXY_PLUGIN_DISPATCHER_H_

#include <set>
#include <string>

#include "base/basictypes.h"
#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/process.h"
#include "build/build_config.h"
#include "ppapi/c/dev/ppb_console_dev.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/dispatcher.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "ppapi/shared_impl/ppb_view_shared.h"
#include "ppapi/shared_impl/singleton_resource_id.h"
#include "ppapi/shared_impl/tracked_callback.h"

namespace ppapi {

struct Preferences;
class Resource;

namespace thunk {
class PPB_Instance_API;
class ResourceCreationAPI;
}

namespace proxy {

class FlashClipboardResource;
class FlashResource;
class GamepadResource;
class ResourceMessageReplyParams;

// Used to keep track of per-instance data.
struct InstanceData {
  InstanceData();
  ~InstanceData();

  ViewData view;

  // When non-NULL, indicates the callback to execute when mouse lock is lost.
  scoped_refptr<TrackedCallback> mouse_lock_callback;

  // A map of singleton resources which are lazily created.
  typedef std::map<SingletonResourceID, scoped_refptr<Resource> >
      SingletonResourceMap;
  SingletonResourceMap singleton_resources;

  // Calls to |RequestSurroundingText()| are done by posted tasks. Track whether
  // a) a task is pending, to avoid redundant calls, and b) whether we should
  // actually call |RequestSurroundingText()|, to avoid stale calls (i.e.,
  // calling when we shouldn't).
  bool is_request_surrounding_text_pending;
  bool should_do_request_surrounding_text;
};

class PPAPI_PROXY_EXPORT PluginDispatcher
    : public Dispatcher,
      public base::SupportsWeakPtr<PluginDispatcher> {
 public:
  class PPAPI_PROXY_EXPORT PluginDelegate : public ProxyChannel::Delegate {
   public:
    // Returns the set used for globally uniquifying PP_Instances. This same
    // set must be returned for all channels.
    //
    // DEREFERENCE ONLY ON THE I/O THREAD.
    virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() = 0;

    // Registers the plugin dispatcher and returns an ID.
    // Plugin dispatcher IDs will be used to dispatch messages from the browser.
    // Each call to Register() has to be matched with a call to Unregister().
    virtual uint32 Register(PluginDispatcher* plugin_dispatcher) = 0;
    virtual void Unregister(uint32 plugin_dispatcher_id) = 0;
  };

  // Constructor for the plugin side. The init and shutdown functions will be
  // will be automatically called when requested by the renderer side. The
  // module ID will be set upon receipt of the InitializeModule message.
  //
  // Note about permissions: On the plugin side, the dispatcher and the plugin
  // run in the same address space (including in nacl). This means that the
  // permissions here are subject to malicious modification and bypass, and
  // an exploited or malicious plugin could send any IPC messages and just
  // bypass the permissions. All permissions must be checked "for realz" in the
  // host process when receiving messages. We check them on the plugin side
  // primarily to keep honest plugins honest, especially with respect to
  // dev interfaces that they "shouldn't" be using.
  //
  // You must call InitPluginWithChannel after the constructor.
  PluginDispatcher(PP_GetInterface_Func get_interface,
                   const PpapiPermissions& permissions,
                   bool incognito);
  virtual ~PluginDispatcher();

  // The plugin side maintains a mapping from PP_Instance to Dispatcher so
  // that we can send the messages to the right channel if there are multiple
  // renderers sharing the same plugin. This mapping is maintained by
  // DidCreateInstance/DidDestroyInstance.
  static PluginDispatcher* GetForInstance(PP_Instance instance);

  // Same as GetForInstance but retrieves the instance from the given resource
  // object as a convenience. Returns NULL on failure.
  static PluginDispatcher* GetForResource(const Resource* resource);

  // Implements the GetInterface function for the plugin to call to retrieve
  // a browser interface.
  static const void* GetBrowserInterface(const char* interface_name);

  // Logs the given log message to the given instance, or, if the instance is
  // invalid, to all instances associated with all dispatchers. Used for
  // global log messages.
  static void LogWithSource(PP_Instance instance,
                            PP_LogLevel_Dev level,
                            const std::string& source,
                            const std::string& value);

  const void* GetPluginInterface(const std::string& interface_name);

  // You must call this function before anything else. Returns true on success.
  // The delegate pointer must outlive this class, ownership is not
  // transferred.
  bool InitPluginWithChannel(PluginDelegate* delegate,
                             const IPC::ChannelHandle& channel_handle,
                             bool is_client);

  // Dispatcher overrides.
  virtual bool IsPlugin() const;
  virtual bool Send(IPC::Message* msg);

  // IPC::Listener implementation.
  virtual bool OnMessageReceived(const IPC::Message& msg);
  virtual void OnChannelError();

  // Keeps track of which dispatcher to use for each instance, active instances
  // and tracks associated data like the current size.
  void DidCreateInstance(PP_Instance instance);
  void DidDestroyInstance(PP_Instance instance);

  // Gets the data for an existing instance, or NULL if the instance id doesn't
  // correspond to a known instance.
  InstanceData* GetInstanceData(PP_Instance instance);

  // Returns the corresponding API. These are APIs not associated with a
  // resource. Guaranteed non-NULL.
  thunk::PPB_Instance_API* GetInstanceAPI();
  thunk::ResourceCreationAPI* GetResourceCreationAPI();

  // Returns the Preferences.
  const Preferences& preferences() const { return preferences_; }

  uint32 plugin_dispatcher_id() const { return plugin_dispatcher_id_; }
  bool incognito() const { return incognito_; }

  // Dispatches the given resource message to the appropriate resource in the
  // plugin process. This should be wired to the various channels that messages
  // come in from various other processes.
  static void DispatchResourceReply(
      const ppapi::proxy::ResourceMessageReplyParams& reply_params,
      const IPC::Message& nested_msg);

 private:
  friend class PluginDispatcherTest;

  // Notifies all live instances that they're now closed. This is used when
  // a renderer crashes or some other error is received.
  void ForceFreeAllInstances();

  // IPC message handlers.
  void OnMsgResourceReply(
      const ppapi::proxy::ResourceMessageReplyParams& reply_params,
      const IPC::Message& nested_msg);
  void OnMsgSupportsInterface(const std::string& interface_name, bool* result);
  void OnMsgSetPreferences(const Preferences& prefs);

  // Internal backed for DispatchResourceReply.
  static void LockedDispatchResourceReply(
      const ppapi::proxy::ResourceMessageReplyParams& reply_params,
      const IPC::Message& nested_msg);

  PluginDelegate* plugin_delegate_;

  // Contains all the plugin interfaces we've queried. The mapped value will
  // be the pointer to the interface pointer supplied by the plugin if it's
  // supported, or NULL if it's not supported. This allows us to cache failures
  // and not req-query if a plugin doesn't support the interface.
  typedef base::hash_map<std::string, const void*> InterfaceMap;
  InterfaceMap plugin_interfaces_;

  typedef base::hash_map<PP_Instance, InstanceData> InstanceDataMap;
  InstanceDataMap instance_map_;

  // The preferences sent from the host. We only want to set this once, which
  // is what the received_preferences_ indicates. See OnMsgSetPreferences.
  bool received_preferences_;
  Preferences preferences_;

  uint32 plugin_dispatcher_id_;

  // Set to true when the instances associated with this dispatcher are
  // incognito mode.
  bool incognito_;

  DISALLOW_COPY_AND_ASSIGN(PluginDispatcher);
};

}  // namespace proxy
}  // namespace ppapi

#endif  // PPAPI_PROXY_PLUGIN_DISPATCHER_H_