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