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

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

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