plugin_dispatcher.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_dispatcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_channel.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppp_instance.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/flash_resource.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/flash_clipboard_resource.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/gamepad_resource.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/interface_list.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/interface_proxy.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_message_filter.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_resource_tracker.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_var_serialization_rules.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppb_instance_proxy.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppp_class_proxy.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/resource_creation_proxy.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/resource_message_params.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_NACL)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/eintr_wrapper.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_posix.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<PP_Instance, PluginDispatcher*> InstanceToDispatcherMap;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::set<PluginDispatcher*> DispatcherSet;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DispatcherSet* g_live_dispatchers = NULL;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InstanceData::InstanceData()
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : flash_fullscreen(PP_FALSE),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_request_surrounding_text_pending(false),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      should_do_request_surrounding_text(false) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InstanceData::~InstanceData() {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run any pending mouse lock callback to prevent leaks.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mouse_lock_callback)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mouse_lock_callback->Abort();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginDispatcher::PluginDispatcher(PP_GetInterface_Func get_interface,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const PpapiPermissions& permissions,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool incognito)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Dispatcher(get_interface, permissions),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      plugin_delegate_(NULL),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      received_preferences_(false),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      plugin_dispatcher_id_(0),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      incognito_(incognito) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetSerializationRules(new PluginVarSerializationRules(AsWeakPtr()));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_live_dispatchers)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_live_dispatchers = new DispatcherSet;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_live_dispatchers->insert(this);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginDispatcher::~PluginDispatcher() {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (plugin_delegate_)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_delegate_->Unregister(plugin_dispatcher_id_);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_live_dispatchers->erase(this);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_live_dispatchers->empty()) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete g_live_dispatchers;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_live_dispatchers = NULL;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_instance_to_dispatcher)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == g_instance_to_dispatcher->end())
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return found->second;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginDispatcher* PluginDispatcher::GetForResource(const Resource* resource) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetForInstance(resource->pp_instance());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void* PluginDispatcher::GetBrowserInterface(const char* interface_name) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!interface_name) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "|interface_name| is null. Did you forget to add "
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "the |interface_name()| template function to the interface's C++ "
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "wrapper?";
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return InterfaceList::GetInstance()->GetInterfaceForPPB(interface_name);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::LogWithSource(PP_Instance instance,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     PP_LogLevel_Dev level,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::string& source,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::string& value) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_live_dispatchers || !g_instance_to_dispatcher)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (instance) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InstanceToDispatcherMap::iterator found =
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_instance_to_dispatcher->find(instance);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found != g_instance_to_dispatcher->end()) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Send just to this specific dispatcher.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found->second->Send(new PpapiHostMsg_LogWithSource(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          instance, static_cast<int>(level), source, value));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Instance 0 or invalid, send to all dispatchers.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (DispatcherSet::iterator i = g_live_dispatchers->begin();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != g_live_dispatchers->end(); ++i) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*i)->Send(new PpapiHostMsg_LogWithSource(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        instance, static_cast<int>(level), source, value));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void* PluginDispatcher::GetPluginInterface(
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& interface_name) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InterfaceMap::iterator found = plugin_interfaces_.find(interface_name);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == plugin_interfaces_.end()) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* ret = local_get_interface()(interface_name.c_str());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_interfaces_.insert(std::make_pair(interface_name, ret));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return found->second;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginDispatcher::InitPluginWithChannel(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PluginDelegate* delegate,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::ChannelHandle& channel_handle,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_client) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Dispatcher::InitWithChannel(delegate, channel_handle, is_client))
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugin_delegate_ = delegate;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugin_dispatcher_id_ = plugin_delegate_->Register(this);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The message filter will intercept and process certain messages directly
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the I/O thread.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel()->AddFilter(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PluginMessageFilter(delegate->GetGloballySeenInstanceIDSet()));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginDispatcher::IsPlugin() const {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginDispatcher::Send(IPC::Message* msg) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PluginDispatcher::Send",
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(msg->type()),
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(msg->type()));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We always want plugin->renderer messages to arrive in-order. If some sync
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and some async messages are sent in response to a synchronous
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // renderer->plugin call, the sync reply will be processed before the async
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reply, and everything will be confused.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allowing all async messages to unblock the renderer means more reentrancy
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there but gives correct ordering.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't want reply messages to unblock however, as they will potentially
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // end up on the wrong queue - see crbug.com/122443
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!msg->is_reply())
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->set_unblock(true);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (msg->is_sync()) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Synchronous messages might be re-entrant, so we need to drop the lock.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyAutoUnlock unlock;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Dispatcher::Send(msg);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Dispatcher::Send(msg);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to grab the proxy lock to ensure that we don't collide with the
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // plugin making pepper calls on a different thread.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived",
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(msg.type()));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (msg.routing_id() == MSG_ROUTING_CONTROL) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Handle some plugin-specific control messages.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool handled = true;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(PpapiPluginMsg_ResourceReply, OnMsgResourceReply)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_UNHANDLED(handled = false);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (handled)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Dispatcher::OnMessageReceived(msg);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::OnChannelError() {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Dispatcher::OnChannelError();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The renderer has crashed or exited. This channel and all instances
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // associated with it are no longer valid.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ForceFreeAllInstances();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(brettw) free resources too!
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::DidCreateInstance(PP_Instance instance) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_instance_to_dispatcher)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_instance_to_dispatcher = new InstanceToDispatcherMap;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*g_instance_to_dispatcher)[instance] = this;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_map_[instance] = InstanceData();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::DidDestroyInstance(PP_Instance instance) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InstanceDataMap::iterator it = instance_map_.find(instance);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != instance_map_.end())
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance_map_.erase(it);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_instance_to_dispatcher) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        instance);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found != g_instance_to_dispatcher->end()) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(found->second == this);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_instance_to_dispatcher->erase(found);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InstanceDataMap::iterator it = instance_map_.find(instance);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (it == instance_map_.end()) ? NULL : &it->second;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)thunk::PPB_Instance_API* PluginDispatcher::GetInstanceAPI() {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<PPB_Instance_Proxy*>(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetInterfaceProxy(API_ID_PPB_INSTANCE));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)thunk::ResourceCreationAPI* PluginDispatcher::GetResourceCreationAPI() {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<ResourceCreationProxy*>(
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetInterfaceProxy(API_ID_RESOURCE_CREATION));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::DispatchResourceReply(
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ppapi::proxy::ResourceMessageReplyParams& reply_params,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& nested_msg) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to grab the proxy lock to ensure that we don't collide with the
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // plugin making pepper calls on a different thread.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoLock lock;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LockedDispatchResourceReply(reply_params, nested_msg);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::ForceFreeAllInstances() {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_instance_to_dispatcher)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Iterating will remove each item from the map, so we need to make a copy
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to avoid things changing out from under is.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InstanceToDispatcherMap temp_map = *g_instance_to_dispatcher;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (InstanceToDispatcherMap::iterator i = temp_map.begin();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != temp_map.end(); ++i) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->second == this) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Synthesize an "instance destroyed" message, this will notify the
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // plugin and also remove it from our list of tracked plugins.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PpapiMsg_PPPInstance_DidDestroy msg(API_ID_PPP_INSTANCE, i->first);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnMessageReceived(msg);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::OnMsgResourceReply(
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ppapi::proxy::ResourceMessageReplyParams& reply_params,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& nested_msg) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LockedDispatchResourceReply(reply_params, nested_msg);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::OnMsgSupportsInterface(
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& interface_name,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* result) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = !!GetPluginInterface(interface_name);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do fallback for PPP_Instance. This is a hack here and if we have more
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cases like this it should be generalized. The PPP_Instance proxy always
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // proxies the 1.1 interface, and then does fallback to 1.0 inside the
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // plugin process (see PPP_Instance_Proxy). So here we return true for
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // supporting the 1.1 interface if either 1.1 or 1.0 is supported.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!*result && interface_name == PPP_INSTANCE_INTERFACE)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = !!GetPluginInterface(PPP_INSTANCE_INTERFACE_1_0);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::OnMsgSetPreferences(const Preferences& prefs) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The renderer may send us preferences more than once (currently this
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // happens every time a new plugin instance is created). Since we don't have
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a way to signal to the plugin that the preferences have changed, changing
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the default fonts and such in the middle of a running plugin could be
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // confusing to it. As a result, we never allow the preferences to be changed
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // once they're set. The user will have to restart to get new font prefs
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // propogated to plugins.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!received_preferences_) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_preferences_ = true;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preferences_ = prefs;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginDispatcher::LockedDispatchResourceReply(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ppapi::proxy::ResourceMessageReplyParams& reply_params,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& nested_msg) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Resource* resource = PpapiGlobals::Get()->GetResourceTracker()->GetResource(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reply_params.pp_resource());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!resource) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reply_params.sequence())
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource->OnReplyReceived(reply_params, nested_msg);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace proxy
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
351