blob: d1b3476df6f692b5f5162c2923288cfbe4d99efe [file] [log] [blame]
[email protected]a08ebea2011-02-13 17:50:201// 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/plugin_dispatcher.h"
6
7#include <map>
8
[email protected]709a847e2010-11-10 01:16:119#include "base/compiler_specific.h"
[email protected]c2932f5e2010-11-03 03:22:3310#include "base/logging.h"
[email protected]aabfa652011-07-13 23:28:4411#include "base/message_loop.h"
[email protected]c2932f5e2010-11-03 03:22:3312#include "ipc/ipc_message.h"
13#include "ipc/ipc_sync_channel.h"
[email protected]366ae242011-05-10 02:23:5814#include "base/debug/trace_event.h"
[email protected]c2932f5e2010-11-03 03:22:3315#include "ppapi/c/pp_errors.h"
[email protected]5c966022011-09-13 18:09:3716#include "ppapi/proxy/interface_list.h"
[email protected]c2932f5e2010-11-03 03:22:3317#include "ppapi/proxy/interface_proxy.h"
[email protected]2cc062242011-03-10 21:16:3418#include "ppapi/proxy/plugin_message_filter.h"
[email protected]6239d342011-05-06 22:55:4719#include "ppapi/proxy/plugin_resource_tracker.h"
[email protected]c2932f5e2010-11-03 03:22:3320#include "ppapi/proxy/plugin_var_serialization_rules.h"
21#include "ppapi/proxy/ppapi_messages.h"
[email protected]9815108e2011-05-27 21:50:2822#include "ppapi/proxy/ppb_char_set_proxy.h"
23#include "ppapi/proxy/ppb_cursor_control_proxy.h"
[email protected]d259a8e2011-05-18 22:31:0924#include "ppapi/proxy/ppb_font_proxy.h"
[email protected]ceadc392011-06-15 23:04:2425#include "ppapi/proxy/ppb_instance_proxy.h"
[email protected]c2932f5e2010-11-03 03:22:3326#include "ppapi/proxy/ppp_class_proxy.h"
[email protected]6239d342011-05-06 22:55:4727#include "ppapi/proxy/resource_creation_proxy.h"
[email protected]7f8b26b2011-08-18 15:41:0128#include "ppapi/shared_impl/resource.h"
[email protected]6239d342011-05-06 22:55:4729#include "ppapi/shared_impl/tracker_base.h"
[email protected]c2932f5e2010-11-03 03:22:3330
[email protected]a08ebea2011-02-13 17:50:2031#if defined(OS_POSIX)
32#include "base/eintr_wrapper.h"
33#include "ipc/ipc_channel_posix.h"
34#endif
35
[email protected]4d2efd22011-08-18 21:58:0236namespace ppapi {
[email protected]c2932f5e2010-11-03 03:22:3337namespace proxy {
38
39namespace {
40
[email protected]465faa22011-02-08 16:31:4641typedef std::map<PP_Instance, PluginDispatcher*> InstanceToDispatcherMap;
42InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
[email protected]c2932f5e2010-11-03 03:22:3343
[email protected]c2932f5e2010-11-03 03:22:3344} // namespace
45
[email protected]06e0a342011-09-27 04:24:3046InstanceData::InstanceData()
47 : fullscreen(PP_FALSE), flash_fullscreen(PP_FALSE) {
[email protected]c7bf7452011-09-12 21:31:5048 memset(&position, 0, sizeof(position));
49}
50
[email protected]5d84d012010-12-02 17:17:2151PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
[email protected]a08ebea2011-02-13 17:50:2052 GetInterfaceFunc get_interface)
[email protected]d259a8e2011-05-18 22:31:0953 : Dispatcher(remote_process_handle, get_interface),
[email protected]208aad792011-05-26 19:05:2854 plugin_delegate_(NULL),
[email protected]373a95a2011-07-01 16:58:1455 received_preferences_(false),
56 plugin_dispatcher_id_(0) {
[email protected]4614f192011-01-21 00:26:4357 SetSerializationRules(new PluginVarSerializationRules);
[email protected]4d2efd22011-08-18 21:58:0258 TrackerBase::Init(&PluginResourceTracker::GetTrackerBaseInstance);
[email protected]c2932f5e2010-11-03 03:22:3359}
60
61PluginDispatcher::~PluginDispatcher() {
[email protected]373a95a2011-07-01 16:58:1462 if (plugin_delegate_)
63 plugin_delegate_->Unregister(plugin_dispatcher_id_);
[email protected]c2932f5e2010-11-03 03:22:3364}
65
66// static
[email protected]4614f192011-01-21 00:26:4367PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) {
[email protected]465faa22011-02-08 16:31:4668 if (!g_instance_to_dispatcher)
69 return NULL;
70 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
71 instance);
72 if (found == g_instance_to_dispatcher->end())
73 return NULL;
74 return found->second;
[email protected]4614f192011-01-21 00:26:4375}
76
[email protected]a08ebea2011-02-13 17:50:2077// static
[email protected]7f8b26b2011-08-18 15:41:0178PluginDispatcher* PluginDispatcher::GetForResource(const Resource* resource) {
79 return GetForInstance(resource->pp_instance());
80}
81
82// static
[email protected]5c966022011-09-13 18:09:3783const void* PluginDispatcher::GetBrowserInterface(const char* interface_name) {
84 return InterfaceList::GetInstance()->GetInterfaceForPPB(interface_name);
85}
86
87const void* PluginDispatcher::GetPluginInterface(
88 const std::string& interface_name) {
89 InterfaceMap::iterator found = plugin_interfaces_.find(interface_name);
90 if (found == plugin_interfaces_.end()) {
91 const void* ret = local_get_interface()(interface_name.c_str());
92 plugin_interfaces_.insert(std::make_pair(interface_name, ret));
93 return ret;
94 }
95 return found->second;
[email protected]a08ebea2011-02-13 17:50:2096}
97
[email protected]e2614c62011-04-16 22:12:4598bool PluginDispatcher::InitPluginWithChannel(
[email protected]d259a8e2011-05-18 22:31:0999 PluginDelegate* delegate,
[email protected]2cc062242011-03-10 21:16:34100 const IPC::ChannelHandle& channel_handle,
101 bool is_client) {
102 if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
103 return false;
[email protected]d259a8e2011-05-18 22:31:09104 plugin_delegate_ = delegate;
[email protected]373a95a2011-07-01 16:58:14105 plugin_dispatcher_id_ = plugin_delegate_->Register(this);
[email protected]2cc062242011-03-10 21:16:34106
107 // The message filter will intercept and process certain messages directly
108 // on the I/O thread.
109 channel()->AddFilter(
110 new PluginMessageFilter(delegate->GetGloballySeenInstanceIDSet()));
111 return true;
112}
113
[email protected]7cf40912010-12-09 18:25:03114bool PluginDispatcher::IsPlugin() const {
115 return true;
116}
117
[email protected]b00bbb32011-03-30 19:02:14118bool PluginDispatcher::Send(IPC::Message* msg) {
[email protected]366ae242011-05-10 02:23:58119 TRACE_EVENT2("ppapi proxy", "PluginDispatcher::Send",
120 "Class", IPC_MESSAGE_ID_CLASS(msg->type()),
121 "Line", IPC_MESSAGE_ID_LINE(msg->type()));
[email protected]b00bbb32011-03-30 19:02:14122 // We always want plugin->renderer messages to arrive in-order. If some sync
123 // and some async messages are send in response to a synchronous
124 // renderer->plugin call, the sync reply will be processed before the async
125 // reply, and everything will be confused.
126 //
127 // Allowing all async messages to unblock the renderer means more reentrancy
128 // there but gives correct ordering.
129 msg->set_unblock(true);
130 return Dispatcher::Send(msg);
131}
132
[email protected]a95986a82010-12-24 06:19:28133bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
[email protected]366ae242011-05-10 02:23:58134 TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived",
135 "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
136 "Line", IPC_MESSAGE_ID_LINE(msg.type()));
[email protected]c2932f5e2010-11-03 03:22:33137 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
138 // Handle some plugin-specific control messages.
[email protected]a95986a82010-12-24 06:19:28139 bool handled = true;
[email protected]c2932f5e2010-11-03 03:22:33140 IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
[email protected]465faa22011-02-08 16:31:46141 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
[email protected]208aad792011-05-26 19:05:28142 IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences)
[email protected]5c966022011-09-13 18:09:37143 IPC_MESSAGE_UNHANDLED(handled = false);
[email protected]c2932f5e2010-11-03 03:22:33144 IPC_END_MESSAGE_MAP()
[email protected]5c966022011-09-13 18:09:37145 if (handled)
[email protected]37fe0362011-09-13 04:00:33146 return true;
[email protected]37fe0362011-09-13 04:00:33147 }
[email protected]5c966022011-09-13 18:09:37148 return Dispatcher::OnMessageReceived(msg);
[email protected]c2932f5e2010-11-03 03:22:33149}
150
[email protected]a08ebea2011-02-13 17:50:20151void PluginDispatcher::OnChannelError() {
[email protected]4f15d2842011-02-15 17:36:33152 Dispatcher::OnChannelError();
153
[email protected]4b417e52011-04-18 22:51:08154 // The renderer has crashed or exited. This channel and all instances
155 // associated with it are no longer valid.
[email protected]a08ebea2011-02-13 17:50:20156 ForceFreeAllInstances();
157 // TODO(brettw) free resources too!
158 delete this;
159}
160
[email protected]f56279c2011-02-02 18:12:31161void PluginDispatcher::DidCreateInstance(PP_Instance instance) {
[email protected]465faa22011-02-08 16:31:46162 if (!g_instance_to_dispatcher)
163 g_instance_to_dispatcher = new InstanceToDispatcherMap;
164 (*g_instance_to_dispatcher)[instance] = this;
165
[email protected]f56279c2011-02-02 18:12:31166 instance_map_[instance] = InstanceData();
167}
168
169void PluginDispatcher::DidDestroyInstance(PP_Instance instance) {
170 InstanceDataMap::iterator it = instance_map_.find(instance);
171 if (it != instance_map_.end())
172 instance_map_.erase(it);
[email protected]465faa22011-02-08 16:31:46173
174 if (g_instance_to_dispatcher) {
175 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
176 instance);
177 if (found != g_instance_to_dispatcher->end()) {
178 DCHECK(found->second == this);
179 g_instance_to_dispatcher->erase(found);
180 } else {
181 NOTREACHED();
182 }
183 }
[email protected]f56279c2011-02-02 18:12:31184}
185
186InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) {
187 InstanceDataMap::iterator it = instance_map_.find(instance);
188 return (it == instance_map_.end()) ? NULL : &it->second;
189}
190
[email protected]7a1f7c6f2011-05-10 21:17:48191void PluginDispatcher::PostToWebKitThread(
192 const tracked_objects::Location& from_here,
193 const base::Closure& task) {
[email protected]d259a8e2011-05-18 22:31:09194 return plugin_delegate_->PostToWebKitThread(from_here, task);
195}
196
197bool PluginDispatcher::SendToBrowser(IPC::Message* msg) {
198 return plugin_delegate_->SendToBrowser(msg);
[email protected]7a1f7c6f2011-05-10 21:17:48199}
200
[email protected]4d2efd22011-08-18 21:58:02201WebKitForwarding* PluginDispatcher::GetWebKitForwarding() {
[email protected]d259a8e2011-05-18 22:31:09202 return plugin_delegate_->GetWebKitForwarding();
[email protected]7a1f7c6f2011-05-10 21:17:48203}
204
[email protected]4d2efd22011-08-18 21:58:02205FunctionGroupBase* PluginDispatcher::GetFunctionAPI(InterfaceID id) {
[email protected]5c966022011-09-13 18:09:37206 return GetInterfaceProxy(id);
[email protected]6239d342011-05-06 22:55:47207}
208
[email protected]a08ebea2011-02-13 17:50:20209void PluginDispatcher::ForceFreeAllInstances() {
[email protected]4f15d2842011-02-15 17:36:33210 if (!g_instance_to_dispatcher)
211 return;
212
213 // Iterating will remove each item from the map, so we need to make a copy
214 // to avoid things changing out from under is.
215 InstanceToDispatcherMap temp_map = *g_instance_to_dispatcher;
216 for (InstanceToDispatcherMap::iterator i = temp_map.begin();
217 i != temp_map.end(); ++i) {
218 if (i->second == this) {
219 // Synthesize an "instance destroyed" message, this will notify the
220 // plugin and also remove it from our list of tracked plugins.
[email protected]4585fbc2011-06-13 17:17:56221 PpapiMsg_PPPInstance_DidDestroy msg(INTERFACE_ID_PPP_INSTANCE, i->first);
222 OnMessageReceived(msg);
[email protected]4f15d2842011-02-15 17:36:33223 }
224 }
[email protected]176c73922010-12-03 17:32:19225}
226
[email protected]465faa22011-02-08 16:31:46227void PluginDispatcher::OnMsgSupportsInterface(
228 const std::string& interface_name,
229 bool* result) {
[email protected]5c966022011-09-13 18:09:37230 *result = !!GetPluginInterface(interface_name);
[email protected]465faa22011-02-08 16:31:46231}
232
[email protected]4d2efd22011-08-18 21:58:02233void PluginDispatcher::OnMsgSetPreferences(const Preferences& prefs) {
[email protected]208aad792011-05-26 19:05:28234 // The renderer may send us preferences more than once (currently this
235 // happens every time a new plugin instance is created). Since we don't have
236 // a way to signal to the plugin that the preferences have changed, changing
237 // the default fonts and such in the middle of a running plugin could be
238 // confusing to it. As a result, we never allow the preferences to be changed
239 // once they're set. The user will have to restart to get new font prefs
240 // propogated to plugins.
241 if (!received_preferences_) {
242 received_preferences_ = true;
243 preferences_ = prefs;
244 }
245}
246
[email protected]c2932f5e2010-11-03 03:22:33247} // namespace proxy
[email protected]4d2efd22011-08-18 21:58:02248} // namespace ppapi