OLD | NEW |
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/host_dispatcher.h" | 5 #include "ppapi/proxy/host_dispatcher.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "ppapi/c/private/ppb_proxy_private.h" | 11 #include "ppapi/c/private/ppb_proxy_private.h" |
12 #include "ppapi/c/ppb_var.h" | 12 #include "ppapi/c/ppb_var.h" |
13 #include "ppapi/proxy/host_var_serialization_rules.h" | 13 #include "ppapi/proxy/host_var_serialization_rules.h" |
| 14 #include "ppapi/proxy/interface_list.h" |
14 #include "ppapi/proxy/ppapi_messages.h" | 15 #include "ppapi/proxy/ppapi_messages.h" |
15 #include "ppapi/proxy/resource_creation_proxy.h" | 16 #include "ppapi/proxy/resource_creation_proxy.h" |
16 | 17 |
17 namespace ppapi { | 18 namespace ppapi { |
18 namespace proxy { | 19 namespace proxy { |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 typedef std::map<PP_Instance, HostDispatcher*> InstanceToDispatcherMap; | 23 typedef std::map<PP_Instance, HostDispatcher*> InstanceToDispatcherMap; |
23 InstanceToDispatcherMap* g_instance_to_dispatcher = NULL; | 24 InstanceToDispatcherMap* g_instance_to_dispatcher = NULL; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 allow_plugin_reentrancy_(false) { | 69 allow_plugin_reentrancy_(false) { |
69 if (!g_module_to_dispatcher) | 70 if (!g_module_to_dispatcher) |
70 g_module_to_dispatcher = new ModuleToDispatcherMap; | 71 g_module_to_dispatcher = new ModuleToDispatcherMap; |
71 (*g_module_to_dispatcher)[pp_module_] = this; | 72 (*g_module_to_dispatcher)[pp_module_] = this; |
72 | 73 |
73 const PPB_Var* var_interface = | 74 const PPB_Var* var_interface = |
74 static_cast<const PPB_Var*>(local_get_interface(PPB_VAR_INTERFACE)); | 75 static_cast<const PPB_Var*>(local_get_interface(PPB_VAR_INTERFACE)); |
75 SetSerializationRules(new HostVarSerializationRules(var_interface, module)); | 76 SetSerializationRules(new HostVarSerializationRules(var_interface, module)); |
76 | 77 |
77 ppb_proxy_ = reinterpret_cast<const PPB_Proxy_Private*>( | 78 ppb_proxy_ = reinterpret_cast<const PPB_Proxy_Private*>( |
78 GetLocalInterface(PPB_PROXY_PRIVATE_INTERFACE)); | 79 local_get_interface(PPB_PROXY_PRIVATE_INTERFACE)); |
79 DCHECK(ppb_proxy_) << "The proxy interface should always be supported."; | 80 DCHECK(ppb_proxy_) << "The proxy interface should always be supported."; |
80 | 81 |
81 ppb_proxy_->SetReserveInstanceIDCallback(pp_module_, &ReserveInstanceID); | 82 ppb_proxy_->SetReserveInstanceIDCallback(pp_module_, &ReserveInstanceID); |
82 } | 83 } |
83 | 84 |
84 HostDispatcher::~HostDispatcher() { | 85 HostDispatcher::~HostDispatcher() { |
85 g_module_to_dispatcher->erase(pp_module_); | 86 g_module_to_dispatcher->erase(pp_module_); |
86 } | 87 } |
87 | 88 |
88 bool HostDispatcher::InitHostWithChannel( | 89 bool HostDispatcher::InitHostWithChannel( |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 "Line", IPC_MESSAGE_ID_LINE(msg.type())); | 150 "Line", IPC_MESSAGE_ID_LINE(msg.type())); |
150 // We only want to allow reentrancy when the most recent message from the | 151 // We only want to allow reentrancy when the most recent message from the |
151 // plugin was a scripting message. We save the old state of the flag on the | 152 // plugin was a scripting message. We save the old state of the flag on the |
152 // stack in case we're (we are the host) being reentered ourselves. The flag | 153 // stack in case we're (we are the host) being reentered ourselves. The flag |
153 // is set to false here for all messages, and then the scripting API will | 154 // is set to false here for all messages, and then the scripting API will |
154 // explicitly set it to true during processing of those messages that can be | 155 // explicitly set it to true during processing of those messages that can be |
155 // reentered. | 156 // reentered. |
156 BoolRestorer restorer(&allow_plugin_reentrancy_); | 157 BoolRestorer restorer(&allow_plugin_reentrancy_); |
157 allow_plugin_reentrancy_ = false; | 158 allow_plugin_reentrancy_ = false; |
158 | 159 |
159 // Handle common control messages. | 160 return Dispatcher::OnMessageReceived(msg); |
160 if (Dispatcher::OnMessageReceived(msg)) | |
161 return true; | |
162 | |
163 if (msg.routing_id() <= 0 || msg.routing_id() >= INTERFACE_ID_COUNT) { | |
164 NOTREACHED(); | |
165 // TODO(brettw): kill the plugin if it starts sending invalid messages? | |
166 return true; | |
167 } | |
168 | |
169 // New-style function proxies. | |
170 // TODO(brettw) this is hacked in for the routing for the types we've | |
171 // implemented in this style so far. When everything is implemented in this | |
172 // style, this function should be cleaned up. | |
173 if (msg.routing_id() == INTERFACE_ID_RESOURCE_CREATION) { | |
174 ResourceCreationProxy proxy(this); | |
175 return proxy.OnMessageReceived(msg); | |
176 } | |
177 | |
178 InterfaceProxy* proxy = target_proxies_[msg.routing_id()].get(); | |
179 if (!proxy) { | |
180 // Autocreate any proxy objects to handle requests from the plugin. Since | |
181 // we always support all known PPB_* interfaces (modulo the trusted bit), | |
182 // there's very little checking necessary. | |
183 const InterfaceProxy::Info* info = GetPPBInterfaceInfo( | |
184 static_cast<InterfaceID>(msg.routing_id())); | |
185 if (!info || | |
186 (info->is_trusted && disallow_trusted_interfaces())) | |
187 return true; | |
188 proxy = CreatePPBInterfaceProxy(info); | |
189 } | |
190 | |
191 return proxy->OnMessageReceived(msg); | |
192 } | 161 } |
193 | 162 |
194 void HostDispatcher::OnChannelError() { | 163 void HostDispatcher::OnChannelError() { |
195 Dispatcher::OnChannelError(); // Stop using the channel. | 164 Dispatcher::OnChannelError(); // Stop using the channel. |
196 | 165 |
197 // Tell the host about the crash so it can clean up and display notification. | 166 // Tell the host about the crash so it can clean up and display notification. |
198 ppb_proxy_->PluginCrashed(pp_module()); | 167 ppb_proxy_->PluginCrashed(pp_module()); |
199 } | 168 } |
200 | 169 |
201 const void* HostDispatcher::GetProxiedInterface(const std::string& interface) { | 170 const void* HostDispatcher::GetProxiedInterface(const std::string& interface) { |
202 // First see if we even have a proxy for this interface. | 171 const void* proxied_interface = |
203 const InterfaceProxy::Info* info = GetPPPInterfaceInfo(interface); | 172 InterfaceList::GetInstance()->GetInterfaceForPPP(interface); |
204 if (!info) | 173 if (!proxied_interface) |
205 return NULL; | 174 return NULL; // Don't have a proxy for this interface, don't query further. |
206 | 175 |
207 PluginIFSupportedMap::iterator iter(plugin_if_supported_.find(interface)); | 176 PluginSupportedMap::iterator iter(plugin_supported_.find(interface)); |
208 if (iter == plugin_if_supported_.end()) { | 177 if (iter == plugin_supported_.end()) { |
209 // Need to query. Cache the result so we only do this once. | 178 // Need to query. Cache the result so we only do this once. |
210 bool supported = false; | 179 bool supported = false; |
211 | 180 |
212 bool previous_reentrancy_value = allow_plugin_reentrancy_; | 181 bool previous_reentrancy_value = allow_plugin_reentrancy_; |
213 allow_plugin_reentrancy_ = true; | 182 allow_plugin_reentrancy_ = true; |
214 Send(new PpapiMsg_SupportsInterface(interface, &supported)); | 183 Send(new PpapiMsg_SupportsInterface(interface, &supported)); |
215 allow_plugin_reentrancy_ = previous_reentrancy_value; | 184 allow_plugin_reentrancy_ = previous_reentrancy_value; |
216 | 185 |
217 std::pair<PluginIFSupportedMap::iterator, bool> iter_success_pair; | 186 std::pair<PluginSupportedMap::iterator, bool> iter_success_pair; |
218 iter_success_pair = plugin_if_supported_.insert( | 187 iter_success_pair = plugin_supported_.insert( |
219 PluginIFSupportedMap::value_type(interface, supported)); | 188 PluginSupportedMap::value_type(interface, supported)); |
220 iter = iter_success_pair.first; | 189 iter = iter_success_pair.first; |
221 } | 190 } |
222 if (iter->second) | 191 if (iter->second) |
223 return info->interface_ptr; | 192 return proxied_interface; |
224 return NULL; | 193 return NULL; |
225 } | 194 } |
226 | 195 |
227 InterfaceProxy* HostDispatcher::GetOrCreatePPBInterfaceProxy( | 196 void HostDispatcher::OnInvalidMessageReceived() { |
228 InterfaceID id) { | 197 // TODO(brettw) bug 95345 kill the plugin when an invalid message is |
229 InterfaceProxy* proxy = target_proxies_[id].get(); | 198 // received. |
230 if (!proxy) { | |
231 const InterfaceProxy::Info* info = GetPPBInterfaceInfo(id); | |
232 if (!info) | |
233 return NULL; | |
234 | |
235 // Sanity check. This function won't normally be called for trusted | |
236 // interfaces, but in case somebody does this, we don't want to then give | |
237 // the plugin the ability to call that trusted interface (since the | |
238 // checking occurs at proxy-creation time). | |
239 if (info->is_trusted && disallow_trusted_interfaces()) | |
240 return NULL; | |
241 | |
242 proxy = CreatePPBInterfaceProxy(info); | |
243 } | |
244 return proxy; | |
245 } | |
246 | |
247 InterfaceProxy* HostDispatcher::CreatePPBInterfaceProxy( | |
248 const InterfaceProxy::Info* info) { | |
249 const void* local_interface = GetLocalInterface(info->name); | |
250 if (!local_interface) { | |
251 // This should always succeed since the browser should support the stuff | |
252 // the proxy does. If this happens, something is out of sync. | |
253 NOTREACHED(); | |
254 return NULL; | |
255 } | |
256 | |
257 InterfaceProxy* proxy = info->create_proxy(this, local_interface); | |
258 target_proxies_[info->id].reset(proxy); | |
259 return proxy; | |
260 } | 199 } |
261 | 200 |
262 // ScopedModuleReference ------------------------------------------------------- | 201 // ScopedModuleReference ------------------------------------------------------- |
263 | 202 |
264 ScopedModuleReference::ScopedModuleReference(Dispatcher* dispatcher) { | 203 ScopedModuleReference::ScopedModuleReference(Dispatcher* dispatcher) { |
265 DCHECK(!dispatcher->IsPlugin()); | 204 DCHECK(!dispatcher->IsPlugin()); |
266 dispatcher_ = static_cast<HostDispatcher*>(dispatcher); | 205 dispatcher_ = static_cast<HostDispatcher*>(dispatcher); |
267 dispatcher_->ppb_proxy()->AddRefModule(dispatcher_->pp_module()); | 206 dispatcher_->ppb_proxy()->AddRefModule(dispatcher_->pp_module()); |
268 } | 207 } |
269 | 208 |
270 ScopedModuleReference::~ScopedModuleReference() { | 209 ScopedModuleReference::~ScopedModuleReference() { |
271 dispatcher_->ppb_proxy()->ReleaseModule(dispatcher_->pp_module()); | 210 dispatcher_->ppb_proxy()->ReleaseModule(dispatcher_->pp_module()); |
272 } | 211 } |
273 | 212 |
274 } // namespace proxy | 213 } // namespace proxy |
275 } // namespace ppapi | 214 } // namespace ppapi |
OLD | NEW |