Updates version of android sdk and api installed and creates ARM and x86 AVD's.
[chromium-blink-merge.git] / ppapi / proxy / host_dispatcher.cc
blobf9d347168a7e1a8cbdd2769add83aaef150a5545
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/host_dispatcher.h"
7 #include <map>
9 #include "base/debug/trace_event.h"
10 #include "base/logging.h"
11 #include "ppapi/c/private/ppb_proxy_private.h"
12 #include "ppapi/c/ppb_var.h"
13 #include "ppapi/proxy/host_var_serialization_rules.h"
14 #include "ppapi/proxy/interface_list.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/proxy/resource_creation_proxy.h"
17 #include "ppapi/shared_impl/ppapi_globals.h"
19 namespace ppapi {
20 namespace proxy {
22 namespace {
24 typedef std::map<PP_Instance, HostDispatcher*> InstanceToDispatcherMap;
25 InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
27 typedef std::map<PP_Module, HostDispatcher*> ModuleToDispatcherMap;
28 ModuleToDispatcherMap* g_module_to_dispatcher = NULL;
30 PP_Bool ReserveInstanceID(PP_Module module, PP_Instance instance) {
31 // Default to returning true (usable) failure. Otherwise, if there's some
32 // kind of communication error or the plugin just crashed, we'll get into an
33 // infinite loop generating new instnace IDs since we think they're all in
34 // use.
35 ModuleToDispatcherMap::const_iterator found =
36 g_module_to_dispatcher->find(module);
37 if (found == g_module_to_dispatcher->end()) {
38 NOTREACHED();
39 return PP_TRUE;
42 bool usable = true;
43 if (!found->second->Send(new PpapiMsg_ReserveInstanceId(instance, &usable)))
44 return PP_TRUE;
45 return PP_FromBool(usable);
48 // Saves the state of the given bool and puts it back when it goes out of
49 // scope.
50 class BoolRestorer {
51 public:
52 BoolRestorer(bool* var) : var_(var), old_value_(*var) {
54 ~BoolRestorer() {
55 *var_ = old_value_;
57 private:
58 bool* var_;
59 bool old_value_;
62 } // namespace
64 HostDispatcher::HostDispatcher(PP_Module module,
65 PP_GetInterface_Func local_get_interface,
66 SyncMessageStatusReceiver* sync_status)
67 : Dispatcher(local_get_interface),
68 sync_status_(sync_status),
69 pp_module_(module),
70 ppb_proxy_(NULL),
71 allow_plugin_reentrancy_(false) {
72 if (!g_module_to_dispatcher)
73 g_module_to_dispatcher = new ModuleToDispatcherMap;
74 (*g_module_to_dispatcher)[pp_module_] = this;
76 SetSerializationRules(new HostVarSerializationRules);
78 ppb_proxy_ = reinterpret_cast<const PPB_Proxy_Private*>(
79 local_get_interface(PPB_PROXY_PRIVATE_INTERFACE));
80 DCHECK(ppb_proxy_) << "The proxy interface should always be supported.";
82 ppb_proxy_->SetReserveInstanceIDCallback(pp_module_, &ReserveInstanceID);
85 HostDispatcher::~HostDispatcher() {
86 g_module_to_dispatcher->erase(pp_module_);
89 bool HostDispatcher::InitHostWithChannel(
90 Delegate* delegate,
91 const IPC::ChannelHandle& channel_handle,
92 bool is_client,
93 const ppapi::Preferences& preferences) {
94 if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
95 return false;
96 AddIOThreadMessageFilter(sync_status_.get());
98 Send(new PpapiMsg_SetPreferences(preferences));
99 return true;
102 // static
103 HostDispatcher* HostDispatcher::GetForInstance(PP_Instance instance) {
104 if (!g_instance_to_dispatcher)
105 return NULL;
106 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
107 instance);
108 if (found == g_instance_to_dispatcher->end())
109 return NULL;
110 return found->second;
113 // static
114 void HostDispatcher::SetForInstance(PP_Instance instance,
115 HostDispatcher* dispatcher) {
116 if (!g_instance_to_dispatcher)
117 g_instance_to_dispatcher = new InstanceToDispatcherMap;
118 (*g_instance_to_dispatcher)[instance] = dispatcher;
121 // static
122 void HostDispatcher::RemoveForInstance(PP_Instance instance) {
123 if (!g_instance_to_dispatcher)
124 return;
125 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
126 instance);
127 if (found != g_instance_to_dispatcher->end())
128 g_instance_to_dispatcher->erase(found);
131 bool HostDispatcher::IsPlugin() const {
132 return false;
135 bool HostDispatcher::Send(IPC::Message* msg) {
136 TRACE_EVENT2("ppapi proxy", "HostDispatcher::Send",
137 "Class", IPC_MESSAGE_ID_CLASS(msg->type()),
138 "Line", IPC_MESSAGE_ID_LINE(msg->type()));
140 // Normal sync messages are set to unblock, which would normally cause the
141 // plugin to be reentered to process them. We only want to do this when we
142 // know the plugin is in a state to accept reentrancy. Since the plugin side
143 // never clears this flag on messages it sends, we can't get deadlock, but we
144 // may still get reentrancy in the host as a result.
145 if (!allow_plugin_reentrancy_)
146 msg->set_unblock(false);
148 if (msg->is_sync()) {
149 // Don't allow sending sync messages during module shutdown. Seee the "else"
150 // block below for why.
151 CHECK(!PP_ToBool(ppb_proxy()->IsInModuleDestructor(pp_module())));
153 // Prevent the dispatcher from going away during sync calls. Scenarios
154 // where this could happen include a Send for a sync message which while
155 // waiting for the reply, dispatches an incoming ExecuteScript call which
156 // destroys the plugin module and in turn the dispatcher.
157 ScopedModuleReference scoped_ref(this);
159 sync_status_->BeginBlockOnSyncMessage();
160 bool result = Dispatcher::Send(msg);
161 sync_status_->EndBlockOnSyncMessage();
163 return result;
164 } else {
165 // We don't want to have a scoped ref for async message cases since since
166 // async messages are sent during module desruction. In this case, the
167 // module will have a 0 refcount and addrefing and releasing it will
168 // reenter the destructor and it will crash.
169 return Dispatcher::Send(msg);
173 bool HostDispatcher::OnMessageReceived(const IPC::Message& msg) {
174 TRACE_EVENT2("ppapi proxy", "HostDispatcher::OnMessageReceived",
175 "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
176 "Line", IPC_MESSAGE_ID_LINE(msg.type()));
177 // We only want to allow reentrancy when the most recent message from the
178 // plugin was a scripting message. We save the old state of the flag on the
179 // stack in case we're (we are the host) being reentered ourselves. The flag
180 // is set to false here for all messages, and then the scripting API will
181 // explicitly set it to true during processing of those messages that can be
182 // reentered.
183 BoolRestorer restorer(&allow_plugin_reentrancy_);
184 allow_plugin_reentrancy_ = false;
186 bool handled = true;
187 IPC_BEGIN_MESSAGE_MAP(HostDispatcher, msg)
188 IPC_MESSAGE_HANDLER(PpapiHostMsg_LogWithSource, OnHostMsgLogWithSource)
189 IPC_MESSAGE_UNHANDLED(handled = false)
190 IPC_END_MESSAGE_MAP()
192 if (handled)
193 return true;
194 return Dispatcher::OnMessageReceived(msg);
197 void HostDispatcher::OnChannelError() {
198 Dispatcher::OnChannelError(); // Stop using the channel.
200 // Tell the host about the crash so it can clean up and display notification.
201 ppb_proxy_->PluginCrashed(pp_module());
204 const void* HostDispatcher::GetProxiedInterface(const std::string& iface_name) {
205 const void* proxied_interface =
206 InterfaceList::GetInstance()->GetInterfaceForPPP(iface_name);
207 if (!proxied_interface)
208 return NULL; // Don't have a proxy for this interface, don't query further.
210 PluginSupportedMap::iterator iter(plugin_supported_.find(iface_name));
211 if (iter == plugin_supported_.end()) {
212 // Need to query. Cache the result so we only do this once.
213 bool supported = false;
215 bool previous_reentrancy_value = allow_plugin_reentrancy_;
216 allow_plugin_reentrancy_ = true;
217 Send(new PpapiMsg_SupportsInterface(iface_name, &supported));
218 allow_plugin_reentrancy_ = previous_reentrancy_value;
220 std::pair<PluginSupportedMap::iterator, bool> iter_success_pair;
221 iter_success_pair = plugin_supported_.insert(
222 PluginSupportedMap::value_type(iface_name, supported));
223 iter = iter_success_pair.first;
225 if (iter->second)
226 return proxied_interface;
227 return NULL;
230 void HostDispatcher::OnInvalidMessageReceived() {
231 // TODO(brettw) bug 95345 kill the plugin when an invalid message is
232 // received.
235 void HostDispatcher::OnHostMsgLogWithSource(PP_Instance instance,
236 int int_log_level,
237 const std::string& source,
238 const std::string& value) {
239 PP_LogLevel_Dev level = static_cast<PP_LogLevel_Dev>(int_log_level);
240 if (instance) {
241 PpapiGlobals::Get()->LogWithSource(instance, level, source, value);
242 } else {
243 PpapiGlobals::Get()->BroadcastLogWithSource(pp_module_, level,
244 source, value);
248 // ScopedModuleReference -------------------------------------------------------
250 ScopedModuleReference::ScopedModuleReference(Dispatcher* dispatcher)
251 : dispatcher_(NULL) {
252 if (!dispatcher->IsPlugin()) {
253 dispatcher_ = static_cast<HostDispatcher*>(dispatcher);
254 dispatcher_->ppb_proxy()->AddRefModule(dispatcher_->pp_module());
258 ScopedModuleReference::~ScopedModuleReference() {
259 if (dispatcher_)
260 dispatcher_->ppb_proxy()->ReleaseModule(dispatcher_->pp_module());
263 } // namespace proxy
264 } // namespace ppapi