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