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/host/ppapi_host.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/host/host_factory.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/host/host_message_context.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/host/instance_message_filter.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/host/resource_host.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/resource_message_params.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/proxy/serialized_handle.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/host_resource.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace host {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using proxy::SerializedHandle;
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Put a cap on the maximum number of resources so we don't explode if the
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// renderer starts spamming us.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxResourcesPerPlugin = 1 << 14;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PpapiHost::PpapiHost(IPC::Sender* sender,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const PpapiPermissions& perms)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : sender_(sender),
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      permissions_(perms),
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_pending_resource_host_id_(1) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PpapiHost::~PpapiHost() {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete these explicitly before destruction since then the host is still
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // technically alive in case one of the filters accesses us from the
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destructor.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_message_filters_.clear();
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The resources may also want to use us in their destructors.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  resources_.clear();
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_resource_hosts_.clear();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PpapiHost::Send(IPC::Message* msg) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sender_->Send(msg);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PpapiHost::OnMessageReceived(const IPC::Message& msg) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(PpapiHost, msg)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_ResourceCall,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnHostMsgResourceCall)
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_InProcessResourceCall,
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        OnHostMsgInProcessResourceCall)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiHostMsg_ResourceSyncCall,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    OnHostMsgResourceSyncCall)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_ResourceCreated,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnHostMsgResourceCreated)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_AttachToPendingHost,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnHostMsgAttachToPendingHost)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_ResourceDestroyed,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnHostMsgResourceDestroyed)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handled) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < instance_message_filters_.size(); i++) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (instance_message_filters_[i]->OnInstanceMessageReceived(msg)) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handled = true;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::SendReply(const ReplyMessageContext& context,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const IPC::Message& msg) {
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PpapiHost::SendReply",
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(msg.type()));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context.sync_reply_msg) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PpapiHostMsg_ResourceSyncCall::WriteReplyParams(context.sync_reply_msg,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    context.params, msg);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(context.sync_reply_msg);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (context.routing_id != MSG_ROUTING_NONE) {
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      Send(new PpapiHostMsg_InProcessResourceReply(context.routing_id,
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                   context.params,
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                   msg));
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    } else {
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      Send(new PpapiPluginMsg_ResourceReply(context.params, msg));
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::SendUnsolicitedReply(PP_Resource resource,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const IPC::Message& msg) {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SendUnsolicitedReplyWithHandles(
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      resource, msg, std::vector<SerializedHandle>());
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PpapiHost::SendUnsolicitedReplyWithHandles(
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_Resource resource,
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const IPC::Message& msg,
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::vector<SerializedHandle>& handles) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PpapiHost::SendUnsolicitedReplyWithHandles",
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(msg.type()));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(resource);  // If this fails, host is probably pending.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy::ResourceMessageReplyParams params(resource, 0);
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::vector<SerializedHandle>::const_iterator it = handles.begin();
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      it != handles.end(); ++it) {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    params.AppendHandle(*it);
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new PpapiPluginMsg_ResourceReply(params, msg));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<ResourceHost> PpapiHost::CreateResourceHost(
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const proxy::ResourceMessageCallParams& params,
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PP_Instance instance,
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IPC::Message& nested_msg) {
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<ResourceHost> resource_host;
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!host_factory_filters_.empty());  // Caller forgot to add a factory.
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < host_factory_filters_.size(); i++) {
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    resource_host = host_factory_filters_[i]->CreateResourceHost(
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        this, params, instance, nested_msg).Pass();
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (resource_host.get())
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return resource_host.Pass();
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int PpapiHost::AddPendingResourceHost(scoped_ptr<ResourceHost> resource_host) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The resource ID should not be assigned.
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!resource_host.get() || resource_host->pp_resource() != 0) {
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NOTREACHED();
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_resource_hosts_.size() + resources_.size()
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      >= kMaxResourcesPerPlugin) {
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pending_id = next_pending_resource_host_id_++;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_resource_hosts_[pending_id] =
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      linked_ptr<ResourceHost>(resource_host.release());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return pending_id;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::AddHostFactoryFilter(scoped_ptr<HostFactory> filter) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host_factory_filters_.push_back(filter.release());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::AddInstanceMessageFilter(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<InstanceMessageFilter> filter) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_message_filters_.push_back(filter.release());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::OnHostMsgResourceCall(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const proxy::ResourceMessageCallParams& params,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& nested_msg) {
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PpapiHost::OnHostMsgResourceCall",
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(nested_msg.type()),
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(nested_msg.type()));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostMessageContext context(params);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandleResourceCall(params, nested_msg, &context);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void PpapiHost::OnHostMsgInProcessResourceCall(
178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int routing_id,
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const proxy::ResourceMessageCallParams& params,
180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const IPC::Message& nested_msg) {
181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PpapiHost::OnHostMsgInProcessResourceCall",
182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(nested_msg.type()),
183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(nested_msg.type()));
184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  HostMessageContext context(routing_id, params);
185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  HandleResourceCall(params, nested_msg, &context);
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::OnHostMsgResourceSyncCall(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const proxy::ResourceMessageCallParams& params,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& nested_msg,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::Message* reply_msg) {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PpapiHost::OnHostMsgResourceSyncCall",
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(nested_msg.type()),
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(nested_msg.type()));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sync messages should always have callback set because they always expect
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a reply from the host.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(params.has_callback());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stash the |reply_msg| in the context so that it can be used to reply
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the sync message.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostMessageContext context(params, reply_msg);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandleResourceCall(params, nested_msg, &context);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::HandleResourceCall(
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const proxy::ResourceMessageCallParams& params,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& nested_msg,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostMessageContext* context) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceHost* resource_host = GetResourceHost(params.pp_resource());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (resource_host) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // CAUTION: Handling the message may cause the destruction of this object.
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resource_host->HandleMessage(nested_msg, context);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (context->params.has_callback()) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ReplyMessageContext reply_context = context->MakeReplyMessageContext();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reply_context.params.set_result(PP_ERROR_BADRESOURCE);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendReply(reply_context, context->reply_msg);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::OnHostMsgResourceCreated(
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const proxy::ResourceMessageCallParams& params,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Instance instance,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& nested_msg) {
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TRACE_EVENT2("ppapi proxy", "PpapiHost::OnHostMsgResourceCreated",
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Class", IPC_MESSAGE_ID_CLASS(nested_msg.type()),
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               "Line", IPC_MESSAGE_ID_LINE(nested_msg.type()));
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (pending_resource_hosts_.size() + resources_.size()
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      >= kMaxResourcesPerPlugin) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run through all filters until one grabs this message.
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<ResourceHost> resource_host = CreateResourceHost(params, instance,
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                              nested_msg);
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!resource_host.get()) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Resource should have been assigned a nonzero PP_Resource.
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(resource_host->pp_resource());
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resources_[params.pp_resource()] =
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      linked_ptr<ResourceHost>(resource_host.release());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PpapiHost::OnHostMsgAttachToPendingHost(PP_Resource pp_resource,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             int pending_host_id) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PendingHostResourceMap::iterator found =
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_resource_hosts_.find(pending_host_id);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (found == pending_resource_hosts_.end()) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Plugin sent a bad ID.
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  found->second->SetPPResourceForPendingHost(pp_resource);
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  resources_[pp_resource] = found->second;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_resource_hosts_.erase(found);
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PpapiHost::OnHostMsgResourceDestroyed(PP_Resource resource) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceMap::iterator found = resources_.find(resource);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == resources_.end()) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Invoking the HostResource destructor might result in looking up the
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // PP_Resource in resources_. std::map is not well specified as to whether the
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // element will be there or not. Therefore, we delay destruction of the
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // HostResource until after we've made sure the map no longer contains
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |resource|.
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  linked_ptr<ResourceHost> delete_at_end_of_scope(found->second);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resources_.erase(found);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourceHost* PpapiHost::GetResourceHost(PP_Resource resource) const {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResourceMap::const_iterator found = resources_.find(resource);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return found == resources_.end() ? NULL : found->second.get();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace host
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
286