Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: ppapi/proxy/plugin_dispatcher.cc

Issue 7740038: Use macros to define pepper interfaces (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: New patch Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/plugin_dispatcher.h ('k') | ppapi/proxy/plugin_dispatcher_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/plugin_dispatcher.h" 5 #include "ppapi/proxy/plugin_dispatcher.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "ipc/ipc_message.h" 12 #include "ipc/ipc_message.h"
13 #include "ipc/ipc_sync_channel.h" 13 #include "ipc/ipc_sync_channel.h"
14 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
15 #include "ppapi/c/pp_errors.h" 15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/proxy/interface_list.h"
16 #include "ppapi/proxy/interface_proxy.h" 17 #include "ppapi/proxy/interface_proxy.h"
17 #include "ppapi/proxy/plugin_message_filter.h" 18 #include "ppapi/proxy/plugin_message_filter.h"
18 #include "ppapi/proxy/plugin_resource_tracker.h" 19 #include "ppapi/proxy/plugin_resource_tracker.h"
19 #include "ppapi/proxy/plugin_var_serialization_rules.h" 20 #include "ppapi/proxy/plugin_var_serialization_rules.h"
20 #include "ppapi/proxy/ppapi_messages.h" 21 #include "ppapi/proxy/ppapi_messages.h"
21 #include "ppapi/proxy/ppb_char_set_proxy.h" 22 #include "ppapi/proxy/ppb_char_set_proxy.h"
22 #include "ppapi/proxy/ppb_cursor_control_proxy.h" 23 #include "ppapi/proxy/ppb_cursor_control_proxy.h"
23 #include "ppapi/proxy/ppb_font_proxy.h" 24 #include "ppapi/proxy/ppb_font_proxy.h"
24 #include "ppapi/proxy/ppb_instance_proxy.h" 25 #include "ppapi/proxy/ppb_instance_proxy.h"
25 #include "ppapi/proxy/ppp_class_proxy.h" 26 #include "ppapi/proxy/ppp_class_proxy.h"
(...skipping 16 matching lines...) Expand all
42 43
43 } // namespace 44 } // namespace
44 45
45 PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle, 46 PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
46 GetInterfaceFunc get_interface) 47 GetInterfaceFunc get_interface)
47 : Dispatcher(remote_process_handle, get_interface), 48 : Dispatcher(remote_process_handle, get_interface),
48 plugin_delegate_(NULL), 49 plugin_delegate_(NULL),
49 received_preferences_(false), 50 received_preferences_(false),
50 plugin_dispatcher_id_(0) { 51 plugin_dispatcher_id_(0) {
51 SetSerializationRules(new PluginVarSerializationRules); 52 SetSerializationRules(new PluginVarSerializationRules);
52
53 // As a plugin, we always support the PPP_Class interface. There's no
54 // GetInterface call or name for it, so we insert it into our table now.
55 target_proxies_[INTERFACE_ID_PPP_CLASS].reset(new PPP_Class_Proxy(this));
56
57 TrackerBase::Init(&PluginResourceTracker::GetTrackerBaseInstance); 53 TrackerBase::Init(&PluginResourceTracker::GetTrackerBaseInstance);
58 } 54 }
59 55
60 PluginDispatcher::~PluginDispatcher() { 56 PluginDispatcher::~PluginDispatcher() {
61 if (plugin_delegate_) 57 if (plugin_delegate_)
62 plugin_delegate_->Unregister(plugin_dispatcher_id_); 58 plugin_delegate_->Unregister(plugin_dispatcher_id_);
63 } 59 }
64 60
65 // static 61 // static
66 PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) { 62 PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) {
67 if (!g_instance_to_dispatcher) 63 if (!g_instance_to_dispatcher)
68 return NULL; 64 return NULL;
69 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find( 65 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
70 instance); 66 instance);
71 if (found == g_instance_to_dispatcher->end()) 67 if (found == g_instance_to_dispatcher->end())
72 return NULL; 68 return NULL;
73 return found->second; 69 return found->second;
74 } 70 }
75 71
76 // static 72 // static
77 PluginDispatcher* PluginDispatcher::GetForResource(const Resource* resource) { 73 PluginDispatcher* PluginDispatcher::GetForResource(const Resource* resource) {
78 return GetForInstance(resource->pp_instance()); 74 return GetForInstance(resource->pp_instance());
79 } 75 }
80 76
81 // static 77 // static
82 const void* PluginDispatcher::GetInterfaceFromDispatcher( 78 const void* PluginDispatcher::GetBrowserInterface(const char* interface) {
83 const char* dispatcher_interface) { 79 return InterfaceList::GetInstance()->GetInterfaceForPPB(interface);
84 // All interfaces the plugin requests of the browser are "PPB". 80 }
85 const InterfaceProxy::Info* info = GetPPBInterfaceInfo(dispatcher_interface); 81
86 if (!info) 82 const void* PluginDispatcher::GetPluginInterface(
87 return NULL; 83 const std::string& interface_name) {
88 return info->interface_ptr; 84 InterfaceMap::iterator found = plugin_interfaces_.find(interface_name);
85 if (found == plugin_interfaces_.end()) {
86 const void* ret = local_get_interface()(interface_name.c_str());
87 plugin_interfaces_.insert(std::make_pair(interface_name, ret));
88 return ret;
89 }
90 return found->second;
89 } 91 }
90 92
91 bool PluginDispatcher::InitPluginWithChannel( 93 bool PluginDispatcher::InitPluginWithChannel(
92 PluginDelegate* delegate, 94 PluginDelegate* delegate,
93 const IPC::ChannelHandle& channel_handle, 95 const IPC::ChannelHandle& channel_handle,
94 bool is_client) { 96 bool is_client) {
95 if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client)) 97 if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
96 return false; 98 return false;
97 plugin_delegate_ = delegate; 99 plugin_delegate_ = delegate;
98 plugin_dispatcher_id_ = plugin_delegate_->Register(this); 100 plugin_dispatcher_id_ = plugin_delegate_->Register(this);
(...skipping 21 matching lines...) Expand all
120 // Allowing all async messages to unblock the renderer means more reentrancy 122 // Allowing all async messages to unblock the renderer means more reentrancy
121 // there but gives correct ordering. 123 // there but gives correct ordering.
122 msg->set_unblock(true); 124 msg->set_unblock(true);
123 return Dispatcher::Send(msg); 125 return Dispatcher::Send(msg);
124 } 126 }
125 127
126 bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) { 128 bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
127 TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived", 129 TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived",
128 "Class", IPC_MESSAGE_ID_CLASS(msg.type()), 130 "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
129 "Line", IPC_MESSAGE_ID_LINE(msg.type())); 131 "Line", IPC_MESSAGE_ID_LINE(msg.type()));
130 // Handle common control messages.
131 if (Dispatcher::OnMessageReceived(msg))
132 return true;
133
134 if (msg.routing_id() == MSG_ROUTING_CONTROL) { 132 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
135 // Handle some plugin-specific control messages. 133 // Handle some plugin-specific control messages.
136 bool handled = true; 134 bool handled = true;
137 IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg) 135 IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
138 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface) 136 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
139 IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences) 137 IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences)
138 IPC_MESSAGE_UNHANDLED(handled = false);
140 IPC_END_MESSAGE_MAP() 139 IPC_END_MESSAGE_MAP()
141 return handled; 140 if (handled)
141 return true;
142 } 142 }
143 143 return Dispatcher::OnMessageReceived(msg);
144 if (msg.routing_id() <= 0 || msg.routing_id() >= INTERFACE_ID_COUNT) {
145 // Host is sending us garbage. Since it's supposed to be trusted, this
146 // isn't supposed to happen. Crash here in all builds in case the renderer
147 // is compromised.
148 CHECK(false);
149 return true;
150 }
151
152 // There are two cases:
153 //
154 // * The first case is that the host is calling a PPP interface. It will
155 // always do a check for the interface before sending messages, and this
156 // will create the necessary interface proxy at that time. So when we
157 // actually receive a message, we know such a proxy will exist.
158 //
159 // * The second case is that the host is sending a response to the plugin
160 // side of a PPB interface (some, like the URL loader, have complex
161 // response messages). Since the host is trusted and not supposed to be
162 // doing silly things, we can just create a PPB proxy project on demand the
163 // first time it's needed.
164
165 InterfaceProxy* proxy = target_proxies_[msg.routing_id()].get();
166 if (!proxy) {
167 // Handle the first time the host calls a PPB reply interface by
168 // autocreating it.
169 const InterfaceProxy::Info* info = GetPPBInterfaceInfo(
170 static_cast<InterfaceID>(msg.routing_id()));
171 if (!info) {
172 NOTREACHED();
173 return true;
174 }
175 proxy = info->create_proxy(this, NULL);
176 target_proxies_[info->id].reset(proxy);
177 }
178
179 return proxy->OnMessageReceived(msg);
180 } 144 }
181 145
182 void PluginDispatcher::OnChannelError() { 146 void PluginDispatcher::OnChannelError() {
183 Dispatcher::OnChannelError(); 147 Dispatcher::OnChannelError();
184 148
185 // The renderer has crashed or exited. This channel and all instances 149 // The renderer has crashed or exited. This channel and all instances
186 // associated with it are no longer valid. 150 // associated with it are no longer valid.
187 ForceFreeAllInstances(); 151 ForceFreeAllInstances();
188 // TODO(brettw) free resources too! 152 // TODO(brettw) free resources too!
189 delete this; 153 delete this;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 191
228 bool PluginDispatcher::SendToBrowser(IPC::Message* msg) { 192 bool PluginDispatcher::SendToBrowser(IPC::Message* msg) {
229 return plugin_delegate_->SendToBrowser(msg); 193 return plugin_delegate_->SendToBrowser(msg);
230 } 194 }
231 195
232 WebKitForwarding* PluginDispatcher::GetWebKitForwarding() { 196 WebKitForwarding* PluginDispatcher::GetWebKitForwarding() {
233 return plugin_delegate_->GetWebKitForwarding(); 197 return plugin_delegate_->GetWebKitForwarding();
234 } 198 }
235 199
236 FunctionGroupBase* PluginDispatcher::GetFunctionAPI(InterfaceID id) { 200 FunctionGroupBase* PluginDispatcher::GetFunctionAPI(InterfaceID id) {
237 scoped_ptr<FunctionGroupBase >& proxy = function_proxies_[id]; 201 return GetInterfaceProxy(id);
238
239 if (proxy.get())
240 return proxy.get();
241
242 if (id == INTERFACE_ID_PPB_CHAR_SET)
243 proxy.reset(new PPB_CharSet_Proxy(this, NULL));
244 else if(id == INTERFACE_ID_PPB_CURSORCONTROL)
245 proxy.reset(new PPB_CursorControl_Proxy(this, NULL));
246 else if (id == INTERFACE_ID_PPB_FONT)
247 proxy.reset(new PPB_Font_Proxy(this, NULL));
248 else if (id == INTERFACE_ID_PPB_INSTANCE)
249 proxy.reset(new PPB_Instance_Proxy(this, NULL));
250 else if (id == INTERFACE_ID_RESOURCE_CREATION)
251 proxy.reset(new ResourceCreationProxy(this));
252
253 return proxy.get();
254 } 202 }
255 203
256 void PluginDispatcher::ForceFreeAllInstances() { 204 void PluginDispatcher::ForceFreeAllInstances() {
257 if (!g_instance_to_dispatcher) 205 if (!g_instance_to_dispatcher)
258 return; 206 return;
259 207
260 // Iterating will remove each item from the map, so we need to make a copy 208 // Iterating will remove each item from the map, so we need to make a copy
261 // to avoid things changing out from under is. 209 // to avoid things changing out from under is.
262 InstanceToDispatcherMap temp_map = *g_instance_to_dispatcher; 210 InstanceToDispatcherMap temp_map = *g_instance_to_dispatcher;
263 for (InstanceToDispatcherMap::iterator i = temp_map.begin(); 211 for (InstanceToDispatcherMap::iterator i = temp_map.begin();
264 i != temp_map.end(); ++i) { 212 i != temp_map.end(); ++i) {
265 if (i->second == this) { 213 if (i->second == this) {
266 // Synthesize an "instance destroyed" message, this will notify the 214 // Synthesize an "instance destroyed" message, this will notify the
267 // plugin and also remove it from our list of tracked plugins. 215 // plugin and also remove it from our list of tracked plugins.
268 PpapiMsg_PPPInstance_DidDestroy msg(INTERFACE_ID_PPP_INSTANCE, i->first); 216 PpapiMsg_PPPInstance_DidDestroy msg(INTERFACE_ID_PPP_INSTANCE, i->first);
269 OnMessageReceived(msg); 217 OnMessageReceived(msg);
270 } 218 }
271 } 219 }
272 } 220 }
273 221
274 void PluginDispatcher::OnMsgSupportsInterface( 222 void PluginDispatcher::OnMsgSupportsInterface(
275 const std::string& interface_name, 223 const std::string& interface_name,
276 bool* result) { 224 bool* result) {
277 *result = false; 225 *result = !!GetPluginInterface(interface_name);
278
279 // Setup a proxy for receiving the messages from this interface.
280 const InterfaceProxy::Info* info = GetPPPInterfaceInfo(interface_name);
281 if (!info)
282 return; // Interface not supported by proxy.
283
284 // Check for a cached result.
285 if (target_proxies_[info->id].get()) {
286 *result = true;
287 return;
288 }
289
290 // Query the plugin & cache the result.
291 const void* interface_functions = GetLocalInterface(interface_name.c_str());
292 if (!interface_functions)
293 return;
294 target_proxies_[info->id].reset(
295 info->create_proxy(this, interface_functions));
296 *result = true;
297 } 226 }
298 227
299 void PluginDispatcher::OnMsgSetPreferences(const Preferences& prefs) { 228 void PluginDispatcher::OnMsgSetPreferences(const Preferences& prefs) {
300 // The renderer may send us preferences more than once (currently this 229 // The renderer may send us preferences more than once (currently this
301 // happens every time a new plugin instance is created). Since we don't have 230 // happens every time a new plugin instance is created). Since we don't have
302 // a way to signal to the plugin that the preferences have changed, changing 231 // a way to signal to the plugin that the preferences have changed, changing
303 // the default fonts and such in the middle of a running plugin could be 232 // the default fonts and such in the middle of a running plugin could be
304 // confusing to it. As a result, we never allow the preferences to be changed 233 // confusing to it. As a result, we never allow the preferences to be changed
305 // once they're set. The user will have to restart to get new font prefs 234 // once they're set. The user will have to restart to get new font prefs
306 // propogated to plugins. 235 // propogated to plugins.
307 if (!received_preferences_) { 236 if (!received_preferences_) {
308 received_preferences_ = true; 237 received_preferences_ = true;
309 preferences_ = prefs; 238 preferences_ = prefs;
310 } 239 }
311 } 240 }
312 241
313 } // namespace proxy 242 } // namespace proxy
314 } // namespace ppapi 243 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/plugin_dispatcher.h ('k') | ppapi/proxy/plugin_dispatcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698