1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/host/resource_message_filter.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
9#include "base/message_loop/message_loop_proxy.h"
10#include "base/task_runner.h"
11#include "ipc/ipc_message.h"
12#include "ppapi/c/pp_errors.h"
13#include "ppapi/host/ppapi_host.h"
14#include "ppapi/host/resource_host.h"
15
16namespace ppapi {
17namespace host {
18
19namespace internal {
20
21// static
22void ResourceMessageFilterDeleteTraits::Destruct(
23    const ResourceMessageFilter* filter) {
24  if (!filter->deletion_message_loop_proxy_->BelongsToCurrentThread()) {
25    // During shutdown the object may not be deleted, but it should be okay to
26    // leak in that case.
27    filter->deletion_message_loop_proxy_->DeleteSoon(FROM_HERE, filter);
28  } else {
29    delete filter;
30  }
31}
32
33}  // namespace internal
34
35ResourceMessageFilter::ResourceMessageFilter()
36    : deletion_message_loop_proxy_(
37          base::MessageLoop::current()->message_loop_proxy()),
38      reply_thread_message_loop_proxy_(
39          base::MessageLoop::current()->message_loop_proxy()),
40      resource_host_(NULL) {
41}
42
43ResourceMessageFilter::ResourceMessageFilter(
44    scoped_refptr<base::MessageLoopProxy> reply_thread_message_loop_proxy)
45    : deletion_message_loop_proxy_(
46          base::MessageLoop::current()->message_loop_proxy()),
47      reply_thread_message_loop_proxy_(reply_thread_message_loop_proxy),
48      resource_host_(NULL) {
49}
50
51ResourceMessageFilter::~ResourceMessageFilter() {
52}
53
54void ResourceMessageFilter::OnFilterAdded(ResourceHost* resource_host) {
55  resource_host_ = resource_host;
56}
57
58void ResourceMessageFilter::OnFilterDestroyed() {
59  resource_host_ = NULL;
60}
61
62bool ResourceMessageFilter::HandleMessage(const IPC::Message& msg,
63                                          HostMessageContext* context) {
64  scoped_refptr<base::TaskRunner> runner = OverrideTaskRunnerForMessage(msg);
65  if (runner.get()) {
66    if (runner->RunsTasksOnCurrentThread()) {
67      DispatchMessage(msg, *context);
68    } else {
69      // TODO(raymes): We need to make a copy so the context can be used on
70      // other threads. It would be better to have a thread-safe refcounted
71      // context.
72      HostMessageContext context_copy = *context;
73      runner->PostTask(FROM_HERE, base::Bind(
74          &ResourceMessageFilter::DispatchMessage, this, msg, context_copy));
75    }
76    return true;
77  }
78
79  return false;
80}
81
82void ResourceMessageFilter::SendReply(const ReplyMessageContext& context,
83                                      const IPC::Message& msg) {
84  if (!reply_thread_message_loop_proxy_->BelongsToCurrentThread()) {
85    reply_thread_message_loop_proxy_->PostTask(FROM_HERE,
86        base::Bind(&ResourceMessageFilter::SendReply, this, context, msg));
87    return;
88  }
89  if (resource_host_)
90    resource_host_->SendReply(context, msg);
91}
92
93scoped_refptr<base::TaskRunner>
94ResourceMessageFilter::OverrideTaskRunnerForMessage(const IPC::Message& msg) {
95  return NULL;
96}
97
98void ResourceMessageFilter::DispatchMessage(const IPC::Message& msg,
99                                            HostMessageContext context) {
100  RunMessageHandlerAndReply(msg, &context);
101}
102
103}  // namespace host
104}  // namespace ppapi
105