blob: dba5253fc10eafe9a5dc5dfc56fa2b4613ecba43 [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_cursor_control_proxy.h"
[email protected]d259a8e2011-05-18 22:31:0923#include "ppapi/proxy/ppb_font_proxy.h"
[email protected]ceadc392011-06-15 23:04:2424#include "ppapi/proxy/ppb_instance_proxy.h"
[email protected]c2932f5e2010-11-03 03:22:3325#include "ppapi/proxy/ppp_class_proxy.h"
[email protected]6239d342011-05-06 22:55:4726#include "ppapi/proxy/resource_creation_proxy.h"
[email protected]7f8b26b2011-08-18 15:41:0127#include "ppapi/shared_impl/resource.h"
[email protected]c2932f5e2010-11-03 03:22:3328
[email protected]a08ebea2011-02-13 17:50:2029#if defined(OS_POSIX)
30#include "base/eintr_wrapper.h"
31#include "ipc/ipc_channel_posix.h"
32#endif
33
[email protected]4d2efd22011-08-18 21:58:0234namespace ppapi {
[email protected]c2932f5e2010-11-03 03:22:3335namespace proxy {
36
37namespace {
38
[email protected]465faa22011-02-08 16:31:4639typedef std::map<PP_Instance, PluginDispatcher*> InstanceToDispatcherMap;
40InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
[email protected]c2932f5e2010-11-03 03:22:3341
[email protected]c2932f5e2010-11-03 03:22:3342} // namespace
43
[email protected]06e0a342011-09-27 04:24:3044InstanceData::InstanceData()
[email protected]5732c7c2011-10-21 14:24:3145 : fullscreen(PP_FALSE), flash_fullscreen(PP_FALSE) {
[email protected]c7bf7452011-09-12 21:31:5046 memset(&position, 0, sizeof(position));
47}
48
[email protected]5d84d012010-12-02 17:17:2149PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
[email protected]a08ebea2011-02-13 17:50:2050 GetInterfaceFunc get_interface)
[email protected]d259a8e2011-05-18 22:31:0951 : Dispatcher(remote_process_handle, get_interface),
[email protected]208aad792011-05-26 19:05:2852 plugin_delegate_(NULL),
[email protected]373a95a2011-07-01 16:58:1453 received_preferences_(false),
54 plugin_dispatcher_id_(0) {
[email protected]4614f192011-01-21 00:26:4355 SetSerializationRules(new PluginVarSerializationRules);
[email protected]c2932f5e2010-11-03 03:22:3356}
57
58PluginDispatcher::~PluginDispatcher() {
[email protected]373a95a2011-07-01 16:58:1459 if (plugin_delegate_)
60 plugin_delegate_->Unregister(plugin_dispatcher_id_);
[email protected]c2932f5e2010-11-03 03:22:3361}
62
63// static
[email protected]4614f192011-01-21 00:26:4364PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) {
[email protected]465faa22011-02-08 16:31:4665 if (!g_instance_to_dispatcher)
66 return NULL;
67 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
68 instance);
69 if (found == g_instance_to_dispatcher->end())
70 return NULL;
71 return found->second;
[email protected]4614f192011-01-21 00:26:4372}
73
[email protected]a08ebea2011-02-13 17:50:2074// static
[email protected]7f8b26b2011-08-18 15:41:0175PluginDispatcher* PluginDispatcher::GetForResource(const Resource* resource) {
76 return GetForInstance(resource->pp_instance());
77}
78
79// static
[email protected]5c966022011-09-13 18:09:3780const void* PluginDispatcher::GetBrowserInterface(const char* interface_name) {
81 return InterfaceList::GetInstance()->GetInterfaceForPPB(interface_name);
82}
83
84const void* PluginDispatcher::GetPluginInterface(
85 const std::string& interface_name) {
86 InterfaceMap::iterator found = plugin_interfaces_.find(interface_name);
87 if (found == plugin_interfaces_.end()) {
88 const void* ret = local_get_interface()(interface_name.c_str());
89 plugin_interfaces_.insert(std::make_pair(interface_name, ret));
90 return ret;
91 }
92 return found->second;
[email protected]a08ebea2011-02-13 17:50:2093}
94
[email protected]e2614c62011-04-16 22:12:4595bool PluginDispatcher::InitPluginWithChannel(
[email protected]d259a8e2011-05-18 22:31:0996 PluginDelegate* delegate,
[email protected]2cc062242011-03-10 21:16:3497 const IPC::ChannelHandle& channel_handle,
98 bool is_client) {
99 if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
100 return false;
[email protected]d259a8e2011-05-18 22:31:09101 plugin_delegate_ = delegate;
[email protected]373a95a2011-07-01 16:58:14102 plugin_dispatcher_id_ = plugin_delegate_->Register(this);
[email protected]2cc062242011-03-10 21:16:34103
104 // The message filter will intercept and process certain messages directly
105 // on the I/O thread.
106 channel()->AddFilter(
107 new PluginMessageFilter(delegate->GetGloballySeenInstanceIDSet()));
108 return true;
109}
110
[email protected]7cf40912010-12-09 18:25:03111bool PluginDispatcher::IsPlugin() const {
112 return true;
113}
114
[email protected]b00bbb32011-03-30 19:02:14115bool PluginDispatcher::Send(IPC::Message* msg) {
[email protected]366ae242011-05-10 02:23:58116 TRACE_EVENT2("ppapi proxy", "PluginDispatcher::Send",
117 "Class", IPC_MESSAGE_ID_CLASS(msg->type()),
118 "Line", IPC_MESSAGE_ID_LINE(msg->type()));
[email protected]b00bbb32011-03-30 19:02:14119 // We always want plugin->renderer messages to arrive in-order. If some sync
120 // and some async messages are send in response to a synchronous
121 // renderer->plugin call, the sync reply will be processed before the async
122 // reply, and everything will be confused.
123 //
124 // Allowing all async messages to unblock the renderer means more reentrancy
125 // there but gives correct ordering.
126 msg->set_unblock(true);
127 return Dispatcher::Send(msg);
128}
129
[email protected]a95986a82010-12-24 06:19:28130bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
[email protected]366ae242011-05-10 02:23:58131 TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived",
132 "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
133 "Line", IPC_MESSAGE_ID_LINE(msg.type()));
[email protected]c2932f5e2010-11-03 03:22:33134 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
135 // Handle some plugin-specific control messages.
[email protected]a95986a82010-12-24 06:19:28136 bool handled = true;
[email protected]c2932f5e2010-11-03 03:22:33137 IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
[email protected]465faa22011-02-08 16:31:46138 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
[email protected]208aad792011-05-26 19:05:28139 IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences)
[email protected]5c966022011-09-13 18:09:37140 IPC_MESSAGE_UNHANDLED(handled = false);
[email protected]c2932f5e2010-11-03 03:22:33141 IPC_END_MESSAGE_MAP()
[email protected]5c966022011-09-13 18:09:37142 if (handled)
[email protected]37fe0362011-09-13 04:00:33143 return true;
[email protected]37fe0362011-09-13 04:00:33144 }
[email protected]5c966022011-09-13 18:09:37145 return Dispatcher::OnMessageReceived(msg);
[email protected]c2932f5e2010-11-03 03:22:33146}
147
[email protected]a08ebea2011-02-13 17:50:20148void PluginDispatcher::OnChannelError() {
[email protected]4f15d2842011-02-15 17:36:33149 Dispatcher::OnChannelError();
150
[email protected]4b417e52011-04-18 22:51:08151 // The renderer has crashed or exited. This channel and all instances
152 // associated with it are no longer valid.
[email protected]a08ebea2011-02-13 17:50:20153 ForceFreeAllInstances();
154 // TODO(brettw) free resources too!
155 delete this;
156}
157
[email protected]f56279c2011-02-02 18:12:31158void PluginDispatcher::DidCreateInstance(PP_Instance instance) {
[email protected]465faa22011-02-08 16:31:46159 if (!g_instance_to_dispatcher)
160 g_instance_to_dispatcher = new InstanceToDispatcherMap;
161 (*g_instance_to_dispatcher)[instance] = this;
162
[email protected]f56279c2011-02-02 18:12:31163 instance_map_[instance] = InstanceData();
164}
165
166void PluginDispatcher::DidDestroyInstance(PP_Instance instance) {
167 InstanceDataMap::iterator it = instance_map_.find(instance);
168 if (it != instance_map_.end())
169 instance_map_.erase(it);
[email protected]465faa22011-02-08 16:31:46170
171 if (g_instance_to_dispatcher) {
172 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
173 instance);
174 if (found != g_instance_to_dispatcher->end()) {
175 DCHECK(found->second == this);
176 g_instance_to_dispatcher->erase(found);
177 } else {
178 NOTREACHED();
179 }
180 }
[email protected]f56279c2011-02-02 18:12:31181}
182
183InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) {
184 InstanceDataMap::iterator it = instance_map_.find(instance);
185 return (it == instance_map_.end()) ? NULL : &it->second;
186}
187
[email protected]7a1f7c6f2011-05-10 21:17:48188void PluginDispatcher::PostToWebKitThread(
189 const tracked_objects::Location& from_here,
190 const base::Closure& task) {
[email protected]d259a8e2011-05-18 22:31:09191 return plugin_delegate_->PostToWebKitThread(from_here, task);
192}
193
194bool PluginDispatcher::SendToBrowser(IPC::Message* msg) {
195 return plugin_delegate_->SendToBrowser(msg);
[email protected]7a1f7c6f2011-05-10 21:17:48196}
197
[email protected]4d2efd22011-08-18 21:58:02198WebKitForwarding* PluginDispatcher::GetWebKitForwarding() {
[email protected]d259a8e2011-05-18 22:31:09199 return plugin_delegate_->GetWebKitForwarding();
[email protected]7a1f7c6f2011-05-10 21:17:48200}
201
[email protected]ac4b54d2011-10-20 23:09:28202FunctionGroupBase* PluginDispatcher::GetFunctionAPI(ApiID id) {
[email protected]5c966022011-09-13 18:09:37203 return GetInterfaceProxy(id);
[email protected]6239d342011-05-06 22:55:47204}
205
[email protected]a08ebea2011-02-13 17:50:20206void PluginDispatcher::ForceFreeAllInstances() {
[email protected]4f15d2842011-02-15 17:36:33207 if (!g_instance_to_dispatcher)
208 return;
209
210 // Iterating will remove each item from the map, so we need to make a copy
211 // to avoid things changing out from under is.
212 InstanceToDispatcherMap temp_map = *g_instance_to_dispatcher;
213 for (InstanceToDispatcherMap::iterator i = temp_map.begin();
214 i != temp_map.end(); ++i) {
215 if (i->second == this) {
216 // Synthesize an "instance destroyed" message, this will notify the
217 // plugin and also remove it from our list of tracked plugins.
[email protected]ac4b54d2011-10-20 23:09:28218 PpapiMsg_PPPInstance_DidDestroy msg(API_ID_PPP_INSTANCE, i->first);
[email protected]4585fbc2011-06-13 17:17:56219 OnMessageReceived(msg);
[email protected]4f15d2842011-02-15 17:36:33220 }
221 }
[email protected]176c73922010-12-03 17:32:19222}
223
[email protected]465faa22011-02-08 16:31:46224void PluginDispatcher::OnMsgSupportsInterface(
225 const std::string& interface_name,
226 bool* result) {
[email protected]5c966022011-09-13 18:09:37227 *result = !!GetPluginInterface(interface_name);
[email protected]465faa22011-02-08 16:31:46228}
229
[email protected]4d2efd22011-08-18 21:58:02230void PluginDispatcher::OnMsgSetPreferences(const Preferences& prefs) {
[email protected]208aad792011-05-26 19:05:28231 // The renderer may send us preferences more than once (currently this
232 // happens every time a new plugin instance is created). Since we don't have
233 // a way to signal to the plugin that the preferences have changed, changing
234 // the default fonts and such in the middle of a running plugin could be
235 // confusing to it. As a result, we never allow the preferences to be changed
236 // once they're set. The user will have to restart to get new font prefs
237 // propogated to plugins.
238 if (!received_preferences_) {
239 received_preferences_ = true;
240 preferences_ = prefs;
241 }
242}
243
[email protected]c2932f5e2010-11-03 03:22:33244} // namespace proxy
[email protected]4d2efd22011-08-18 21:58:02245} // namespace ppapi