1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/proxy/plugin_message_filter.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "ipc/ipc_channel.h"
10#include "ppapi/proxy/ppapi_messages.h"
11#include "ppapi/proxy/resource_message_params.h"
12#include "ppapi/proxy/resource_reply_thread_registrar.h"
13#include "ppapi/shared_impl/ppapi_globals.h"
14#include "ppapi/shared_impl/proxy_lock.h"
15#include "ppapi/shared_impl/resource.h"
16#include "ppapi/shared_impl/resource_tracker.h"
17
18namespace ppapi {
19namespace proxy {
20
21PluginMessageFilter::PluginMessageFilter(
22    std::set<PP_Instance>* seen_instance_ids,
23    scoped_refptr<ResourceReplyThreadRegistrar> registrar)
24    : seen_instance_ids_(seen_instance_ids),
25      resource_reply_thread_registrar_(registrar),
26      sender_(NULL) {
27}
28
29PluginMessageFilter::~PluginMessageFilter() {
30}
31
32void PluginMessageFilter::OnFilterAdded(IPC::Sender* sender) {
33  sender_ = sender;
34}
35
36void PluginMessageFilter::OnFilterRemoved() {
37  sender_ = NULL;
38}
39
40bool PluginMessageFilter::OnMessageReceived(const IPC::Message& message) {
41  bool handled = true;
42  IPC_BEGIN_MESSAGE_MAP(PluginMessageFilter, message)
43    IPC_MESSAGE_HANDLER(PpapiMsg_ReserveInstanceId, OnMsgReserveInstanceId)
44    IPC_MESSAGE_HANDLER(PpapiPluginMsg_ResourceReply, OnMsgResourceReply)
45    IPC_MESSAGE_UNHANDLED(handled = false)
46  IPC_END_MESSAGE_MAP()
47  return handled;
48}
49
50bool PluginMessageFilter::Send(IPC::Message* msg) {
51  if (sender_)
52    return sender_->Send(msg);
53  delete msg;
54  return false;
55}
56
57// static
58void PluginMessageFilter::DispatchResourceReplyForTest(
59    const ResourceMessageReplyParams& reply_params,
60    const IPC::Message& nested_msg) {
61  DispatchResourceReply(reply_params, nested_msg);
62}
63
64void PluginMessageFilter::OnMsgReserveInstanceId(PP_Instance instance,
65                                                 bool* usable) {
66  // If |seen_instance_ids_| is set to NULL, we are not supposed to see this
67  // message.
68  CHECK(seen_instance_ids_);
69  // See the message definition for how this works.
70  if (seen_instance_ids_->find(instance) != seen_instance_ids_->end()) {
71    // Instance ID already seen, reject it.
72    *usable = false;
73    return;
74  }
75
76  // This instance ID is new so we can return that it's usable and mark it as
77  // used for future reference.
78  seen_instance_ids_->insert(instance);
79  *usable = true;
80}
81
82void PluginMessageFilter::OnMsgResourceReply(
83    const ResourceMessageReplyParams& reply_params,
84    const IPC::Message& nested_msg) {
85  scoped_refptr<base::MessageLoopProxy> target =
86      resource_reply_thread_registrar_->GetTargetThread(reply_params,
87                                                        nested_msg);
88
89  if (!target.get()) {
90    DispatchResourceReply(reply_params, nested_msg);
91  } else {
92    target->PostTask(
93        FROM_HERE,
94        base::Bind(&DispatchResourceReply, reply_params, nested_msg));
95  }
96}
97
98// static
99void PluginMessageFilter::DispatchResourceReply(
100    const ResourceMessageReplyParams& reply_params,
101    const IPC::Message& nested_msg) {
102  ProxyAutoLock lock;
103  Resource* resource = PpapiGlobals::Get()->GetResourceTracker()->GetResource(
104      reply_params.pp_resource());
105  if (!resource) {
106    DVLOG_IF(1, reply_params.sequence() != 0)
107        << "Pepper resource reply message received but the resource doesn't "
108           "exist (probably has been destroyed).";
109    return;
110  }
111  resource->OnReplyReceived(reply_params, nested_msg);
112}
113
114}  // namespace proxy
115}  // namespace ppapi
116