blob: 0ae8e2e2c9252bf30c80bb496ba030ecb8f1a7c6 [file] [log] [blame]
[email protected]b697e1a2011-01-06 22:20:281// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]c2932f5e2010-11-03 03:22:332// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/proxy/dispatcher.h"
6
7#include <string.h> // For memset.
8
9#include <map>
10
[email protected]709a847e2010-11-10 01:16:1111#include "base/compiler_specific.h"
[email protected]c2932f5e2010-11-03 03:22:3312#include "base/logging.h"
13#include "ipc/ipc_message.h"
14#include "ipc/ipc_sync_channel.h"
[email protected]43a40202010-11-12 16:25:0115#include "ppapi/c/dev/ppb_buffer_dev.h"
[email protected]9ca952d2010-11-11 20:43:5016#include "ppapi/c/dev/ppb_char_set_dev.h"
[email protected]a3010332010-11-12 07:09:3517#include "ppapi/c/dev/ppb_cursor_control_dev.h"
[email protected]43a40202010-11-12 16:25:0118#include "ppapi/c/dev/ppb_cursor_control_dev.h"
19#include "ppapi/c/dev/ppb_font_dev.h"
20#include "ppapi/c/dev/ppb_fullscreen_dev.h"
[email protected]a3010332010-11-12 07:09:3521#include "ppapi/c/dev/ppb_fullscreen_dev.h"
[email protected]799d1ab2010-11-09 17:16:2822#include "ppapi/c/dev/ppb_testing_dev.h"
[email protected]c2932f5e2010-11-03 03:22:3323#include "ppapi/c/dev/ppb_var_deprecated.h"
24#include "ppapi/c/pp_errors.h"
[email protected]b9a59842011-01-15 01:04:0025#include "ppapi/c/ppb_audio.h"
26#include "ppapi/c/ppb_audio_config.h"
[email protected]c2932f5e2010-11-03 03:22:3327#include "ppapi/c/ppb_core.h"
28#include "ppapi/c/ppb_graphics_2d.h"
29#include "ppapi/c/ppb_image_data.h"
30#include "ppapi/c/ppb_instance.h"
[email protected]5a3f62852010-11-10 21:43:0131#include "ppapi/c/ppb_url_loader.h"
32#include "ppapi/c/ppb_url_request_info.h"
33#include "ppapi/c/ppb_url_response_info.h"
[email protected]9ca952d2010-11-11 20:43:5034#include "ppapi/c/ppp_instance.h"
[email protected]b697e1a2011-01-06 22:20:2835#include "ppapi/c/private/ppb_flash.h"
[email protected]917a44b02011-01-13 17:07:2936#include "ppapi/c/private/ppb_pdf.h"
[email protected]5f2517612010-12-02 22:36:4837#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
[email protected]9ca952d2010-11-11 20:43:5038#include "ppapi/proxy/ppapi_messages.h"
[email protected]5d84d012010-12-02 17:17:2139#include "ppapi/proxy/ppb_audio_config_proxy.h"
40#include "ppapi/proxy/ppb_audio_proxy.h"
[email protected]43a40202010-11-12 16:25:0141#include "ppapi/proxy/ppb_buffer_proxy.h"
[email protected]9ca952d2010-11-11 20:43:5042#include "ppapi/proxy/ppb_char_set_proxy.h"
[email protected]c2932f5e2010-11-03 03:22:3343#include "ppapi/proxy/ppb_core_proxy.h"
[email protected]a3010332010-11-12 07:09:3544#include "ppapi/proxy/ppb_cursor_control_proxy.h"
[email protected]5f2517612010-12-02 22:36:4845#include "ppapi/proxy/ppb_flash_proxy.h"
[email protected]9ca952d2010-11-11 20:43:5046#include "ppapi/proxy/ppb_font_proxy.h"
[email protected]a3010332010-11-12 07:09:3547#include "ppapi/proxy/ppb_fullscreen_proxy.h"
[email protected]c2932f5e2010-11-03 03:22:3348#include "ppapi/proxy/ppb_graphics_2d_proxy.h"
49#include "ppapi/proxy/ppb_image_data_proxy.h"
50#include "ppapi/proxy/ppb_instance_proxy.h"
[email protected]43a40202010-11-12 16:25:0151#include "ppapi/proxy/ppb_pdf_proxy.h"
[email protected]799d1ab2010-11-09 17:16:2852#include "ppapi/proxy/ppb_testing_proxy.h"
53#include "ppapi/proxy/ppb_url_loader_proxy.h"
54#include "ppapi/proxy/ppb_url_request_info_proxy.h"
55#include "ppapi/proxy/ppb_url_response_info_proxy.h"
[email protected]c2932f5e2010-11-03 03:22:3356#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
57#include "ppapi/proxy/ppp_class_proxy.h"
58#include "ppapi/proxy/ppp_instance_proxy.h"
59#include "ppapi/proxy/var_serialization_rules.h"
[email protected]c2932f5e2010-11-03 03:22:3360
61namespace pp {
62namespace proxy {
63
[email protected]5d84d012010-12-02 17:17:2164Dispatcher::Dispatcher(base::ProcessHandle remote_process_handle,
65 GetInterfaceFunc local_get_interface)
[email protected]c2932f5e2010-11-03 03:22:3366 : pp_module_(0),
[email protected]5d84d012010-12-02 17:17:2167 remote_process_handle_(remote_process_handle),
[email protected]5f2517612010-12-02 22:36:4868 disallow_trusted_interfaces_(false), // TODO(brettw) make this settable.
[email protected]c2932f5e2010-11-03 03:22:3369 local_get_interface_(local_get_interface),
70 declared_supported_remote_interfaces_(false),
[email protected]709a847e2010-11-10 01:16:1171 callback_tracker_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
[email protected]c2932f5e2010-11-03 03:22:3372 memset(id_to_proxy_, 0,
73 static_cast<int>(INTERFACE_ID_COUNT) * sizeof(InterfaceProxy*));
74}
75
76Dispatcher::~Dispatcher() {
77}
78
79bool Dispatcher::InitWithChannel(MessageLoop* ipc_message_loop,
[email protected]42ce94e2010-12-08 19:28:0980 const IPC::ChannelHandle& channel_handle,
[email protected]c2932f5e2010-11-03 03:22:3381 bool is_client,
82 base::WaitableEvent* shutdown_event) {
83 IPC::Channel::Mode mode = is_client ? IPC::Channel::MODE_CLIENT
84 : IPC::Channel::MODE_SERVER;
[email protected]42ce94e2010-12-08 19:28:0985 channel_.reset(new IPC::SyncChannel(channel_handle, mode, this,
[email protected]c2932f5e2010-11-03 03:22:3386 ipc_message_loop, false, shutdown_event));
87 return true;
88}
89
[email protected]a95986a82010-12-24 06:19:2890bool Dispatcher::OnMessageReceived(const IPC::Message& msg) {
[email protected]c2932f5e2010-11-03 03:22:3391 // Control messages.
92 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
[email protected]a95986a82010-12-24 06:19:2893 bool handled = true;
[email protected]c2932f5e2010-11-03 03:22:3394 IPC_BEGIN_MESSAGE_MAP(Dispatcher, msg)
95 IPC_MESSAGE_HANDLER(PpapiMsg_DeclareInterfaces,
96 OnMsgDeclareInterfaces)
97 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
98 IPC_MESSAGE_FORWARD(PpapiMsg_ExecuteCallback, &callback_tracker_,
99 CallbackTracker::ReceiveExecuteSerializedCallback)
[email protected]a95986a82010-12-24 06:19:28100 IPC_MESSAGE_UNHANDLED(handled = false)
[email protected]c2932f5e2010-11-03 03:22:33101 IPC_END_MESSAGE_MAP()
[email protected]a95986a82010-12-24 06:19:28102 return handled;
[email protected]c2932f5e2010-11-03 03:22:33103 }
104
105 // Interface-specific messages.
106 if (msg.routing_id() > 0 && msg.routing_id() < INTERFACE_ID_COUNT) {
107 InterfaceProxy* proxy = id_to_proxy_[msg.routing_id()];
108 if (proxy)
[email protected]a95986a82010-12-24 06:19:28109 return proxy->OnMessageReceived(msg);
110
111 NOTREACHED();
[email protected]c2932f5e2010-11-03 03:22:33112 // TODO(brettw): kill the plugin if it starts sending invalid messages?
113 }
[email protected]a95986a82010-12-24 06:19:28114
115 return false;
[email protected]c2932f5e2010-11-03 03:22:33116}
117
118void Dispatcher::SetSerializationRules(
119 VarSerializationRules* var_serialization_rules) {
120 serialization_rules_.reset(var_serialization_rules);
121}
122
123void Dispatcher::InjectProxy(InterfaceID id,
124 const std::string& name,
125 InterfaceProxy* proxy) {
126 proxies_[name] = linked_ptr<InterfaceProxy>(proxy);
127 id_to_proxy_[id] = proxy;
128}
129
130const void* Dispatcher::GetLocalInterface(const char* interface) {
131 return local_get_interface_(interface);
132}
133
134const void* Dispatcher::GetProxiedInterface(const std::string& interface) {
135 // See if we already know about this interface and have created a host.
136 ProxyMap::const_iterator found = proxies_.find(interface);
137 if (found != proxies_.end())
138 return found->second->GetSourceInterface();
139
140 // When the remote side has sent us a declared list of all interfaces it
141 // supports and we don't have it in our list, we know the requested interface
142 // doesn't exist and we can return failure.
143 if (declared_supported_remote_interfaces_)
144 return NULL;
145
146 if (!RemoteSupportsTargetInterface(interface))
147 return NULL;
148
149 linked_ptr<InterfaceProxy> proxy(CreateProxyForInterface(interface, NULL));
150 if (!proxy.get())
151 return NULL; // Don't know how to proxy this interface.
152
153 // Save our proxy.
154 proxies_[interface] = proxy;
155 id_to_proxy_[proxy->GetInterfaceId()] = proxy.get();
156 return proxy->GetSourceInterface();
157}
158
159bool Dispatcher::Send(IPC::Message* msg) {
160 return channel_->Send(msg);
161}
162
163bool Dispatcher::RemoteSupportsTargetInterface(const std::string& interface) {
164 bool result = false;
165 Send(new PpapiMsg_SupportsInterface(interface, &result));
166 return result;
167}
168
169bool Dispatcher::IsInterfaceTrusted(const std::string& interface) {
170 // FIXME(brettw)
171 (void)interface;
172 return false;
173}
174
175bool Dispatcher::SetupProxyForTargetInterface(const std::string& interface) {
176 // If we already have a proxy that knows about the locally-implemented
177 // interface, we know it's supported and don't need to re-query.
178 ProxyMap::const_iterator found = proxies_.find(interface);
179 if (found != proxies_.end())
180 return true;
181
182 if (disallow_trusted_interfaces_ && IsInterfaceTrusted(interface))
183 return false;
184
185 // Create the proxy if it doesn't exist and set the local interface on it.
186 // This also handles the case where possibly an interface could be supported
187 // by both the local and remote side.
188 const void* interface_functions = local_get_interface_(interface.c_str());
189 if (!interface_functions)
190 return false;
191 InterfaceProxy* proxy = CreateProxyForInterface(interface,
192 interface_functions);
193 if (!proxy)
194 return false;
195
196 proxies_[interface] = linked_ptr<InterfaceProxy>(proxy);
197 id_to_proxy_[proxy->GetInterfaceId()] = proxy;
198 return true;
199}
200
201void Dispatcher::OnMsgSupportsInterface(const std::string& interface_name,
202 bool* result) {
203 *result = SetupProxyForTargetInterface(interface_name);
204}
205
206void Dispatcher::OnMsgDeclareInterfaces(
207 const std::vector<std::string>& interfaces) {
208 // Make proxies for all the interfaces it supports that we also support.
209 for (size_t i = 0; i < interfaces.size(); i++) {
210 // Possibly the plugin could request an interface before the "declare"
211 // message is received, so we could already have an entry for this
212 // interface. In this case, we can just skip to the next one.
213 if (proxies_.find(interfaces[i]) != proxies_.end())
214 continue;
215
216 linked_ptr<InterfaceProxy> proxy(CreateProxyForInterface(interfaces[i],
217 NULL));
218 if (!proxy.get()) {
219 // Since only the browser declares supported interfaces, we should never
220 // get one we don't support.
221 //NOTREACHED() << "Remote side declaring an unsupported proxy.";
222 continue;
223 }
224 proxies_[interfaces[i]] = proxy;
225 id_to_proxy_[proxy->GetInterfaceId()] = proxy.get();
226 }
227}
228
229InterfaceProxy* Dispatcher::CreateProxyForInterface(
230 const std::string& interface_name,
231 const void* interface_functions) {
[email protected]b9a59842011-01-15 01:04:00232 if (interface_name == PPB_AUDIO_CONFIG_INTERFACE)
[email protected]5d84d012010-12-02 17:17:21233 return new PPB_AudioConfig_Proxy(this, interface_functions);
[email protected]b9a59842011-01-15 01:04:00234 if (interface_name == PPB_AUDIO_INTERFACE)
[email protected]5d84d012010-12-02 17:17:21235 return new PPB_Audio_Proxy(this, interface_functions);
[email protected]43a40202010-11-12 16:25:01236 if (interface_name == PPB_BUFFER_DEV_INTERFACE)
237 return new PPB_Buffer_Proxy(this, interface_functions);
[email protected]9ca952d2010-11-11 20:43:50238 if (interface_name == PPB_CHAR_SET_DEV_INTERFACE)
239 return new PPB_CharSet_Proxy(this, interface_functions);
[email protected]c2932f5e2010-11-03 03:22:33240 if (interface_name == PPB_CORE_INTERFACE)
241 return new PPB_Core_Proxy(this, interface_functions);
[email protected]a3010332010-11-12 07:09:35242 if (interface_name == PPB_CURSOR_CONTROL_DEV_INTERFACE)
243 return new PPB_CursorControl_Proxy(this, interface_functions);
[email protected]9ca952d2010-11-11 20:43:50244 if (interface_name == PPB_FONT_DEV_INTERFACE)
245 return new PPB_Font_Proxy(this, interface_functions);
[email protected]a3010332010-11-12 07:09:35246 if (interface_name == PPB_FULLSCREEN_DEV_INTERFACE)
247 return new PPB_Fullscreen_Proxy(this, interface_functions);
[email protected]c2932f5e2010-11-03 03:22:33248 if (interface_name == PPB_GRAPHICS_2D_INTERFACE)
249 return new PPB_Graphics2D_Proxy(this, interface_functions);
250 if (interface_name == PPB_IMAGEDATA_INTERFACE)
251 return new PPB_ImageData_Proxy(this, interface_functions);
252 if (interface_name == PPB_INSTANCE_INTERFACE)
253 return new PPB_Instance_Proxy(this, interface_functions);
[email protected]799d1ab2010-11-09 17:16:28254 if (interface_name == PPB_TESTING_DEV_INTERFACE)
255 return new PPB_Testing_Proxy(this, interface_functions);
[email protected]5a3f62852010-11-10 21:43:01256 if (interface_name == PPB_URLLOADER_INTERFACE)
[email protected]799d1ab2010-11-09 17:16:28257 return new PPB_URLLoader_Proxy(this, interface_functions);
[email protected]5a3f62852010-11-10 21:43:01258 if (interface_name == PPB_URLREQUESTINFO_INTERFACE)
[email protected]799d1ab2010-11-09 17:16:28259 return new PPB_URLRequestInfo_Proxy(this, interface_functions);
[email protected]5a3f62852010-11-10 21:43:01260 if (interface_name == PPB_URLRESPONSEINFO_INTERFACE)
[email protected]799d1ab2010-11-09 17:16:28261 return new PPB_URLResponseInfo_Proxy(this, interface_functions);
[email protected]c2932f5e2010-11-03 03:22:33262 if (interface_name == PPB_VAR_DEPRECATED_INTERFACE)
263 return new PPB_Var_Deprecated_Proxy(this, interface_functions);
264 if (interface_name == PPP_INSTANCE_INTERFACE)
265 return new PPP_Instance_Proxy(this, interface_functions);
266
[email protected]5f2517612010-12-02 22:36:48267 // Trusted interfaces.
268 if (!disallow_trusted_interfaces_) {
[email protected]0bd753682010-12-16 18:15:52269 if (interface_name == PPB_FLASH_INTERFACE)
[email protected]5f2517612010-12-02 22:36:48270 return new PPB_Flash_Proxy(this, interface_functions);
[email protected]0bd753682010-12-16 18:15:52271 if (interface_name == PPB_PDF_INTERFACE)
272 return new PPB_PDF_Proxy(this, interface_functions);
[email protected]5f2517612010-12-02 22:36:48273 if (interface_name == PPB_URLLOADERTRUSTED_INTERFACE)
274 return new PPB_URLLoaderTrusted_Proxy(this, interface_functions);
275 }
276
[email protected]c2932f5e2010-11-03 03:22:33277 return NULL;
278}
279
280} // namespace proxy
281} // namespace pp
282