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#ifndef PPAPI_HOST_RESOURCE_MESSAGE_FILTER_H_
6#define PPAPI_HOST_RESOURCE_MESSAGE_FILTER_H_
7
8#include "base/memory/ref_counted.h"
9#include "ppapi/c/pp_stdint.h"
10#include "ppapi/host/host_message_context.h"
11#include "ppapi/host/ppapi_host_export.h"
12#include "ppapi/host/resource_message_handler.h"
13
14namespace base {
15class MessageLoopProxy;
16class TaskRunner;
17}
18
19namespace IPC {
20class Message;
21}
22
23namespace ppapi {
24namespace host {
25
26class ResourceHost;
27class ResourceMessageFilter;
28
29namespace internal {
30
31struct PPAPI_HOST_EXPORT ResourceMessageFilterDeleteTraits {
32  static void Destruct(const ResourceMessageFilter* filter);
33};
34
35}  // namespace internal
36
37// This is the base class of resource message filters that can handle resource
38// messages on another thread. ResourceHosts can handle most messages
39// directly, but if they need to handle something on a different thread it is
40// inconvenient. This class makes handling that case easier. This class is
41// similar to a BrowserMessageFilter but for resource messages. Note that the
42// liftetime of a ResourceHost is managed by a PpapiHost and may be destroyed
43// before or while your message is being processed on another thread.
44// If this is the case, the message handler will always be called but a reply
45// may not be sent back to the host.
46//
47// To handle a resource message on another thread you should implement a
48// subclass as follows:
49// class MyMessageFilter : public ResourceMessageFilter {
50//  protected:
51//   virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
52//       const IPC::Message& message) OVERRIDE {
53//     if (message.type() == MyMessage::ID)
54//       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
55//     return NULL;
56//   }
57//
58//   virtual int32_t OnResourceMessageReceived(
59//       const IPC::Message& msg,
60//       HostMessageContext* context) OVERRIDE {
61//     IPC_BEGIN_MESSAGE_MAP(MyMessageFilter, msg)
62//       PPAPI_DISPATCH_HOST_RESOURCE_CALL(MyMessage, OnMyMessage)
63//     IPC_END_MESSAGE_MAP()
64//     return PP_ERROR_FAILED;
65//   }
66//
67//  private:
68//   int32_t OnMyMessage(ppapi::host::HostMessageContext* context, ...) {
69//     // Will be run on the UI thread.
70//   }
71// }
72//
73// The filter should then be added in the resource host using:
74// AddFilter(make_scoped_refptr(new MyMessageFilter));
75class PPAPI_HOST_EXPORT ResourceMessageFilter
76    : public ResourceMessageHandler,
77      public base::RefCountedThreadSafe<
78          ResourceMessageFilter, internal::ResourceMessageFilterDeleteTraits> {
79 public:
80  // This object must be constructed on the same thread that a reply message
81  // should be sent, i.e. the IO thread when constructed in the browser process
82  // or the main thread when constructed in the renderer process. Since
83  // ResourceMessageFilters are usually constructed in the constructor of the
84  // owning ResourceHost, this will almost always be the case anyway.
85  // The object will be deleted on the creation thread.
86  ResourceMessageFilter();
87  // Test constructor. Allows you to specify the message loop which will be used
88  // to dispatch replies on.
89  ResourceMessageFilter(
90      scoped_refptr<base::MessageLoopProxy> reply_thread_message_loop_proxy);
91
92  // Called when a filter is added to a ResourceHost.
93  void OnFilterAdded(ResourceHost* resource_host);
94  // Called when a filter is removed from a ResourceHost.
95  void OnFilterDestroyed();
96
97  // This will dispatch the message handler on the target thread. It returns
98  // true if the message was handled by this filter and false otherwise.
99  virtual bool HandleMessage(const IPC::Message& msg,
100                             HostMessageContext* context) OVERRIDE;
101
102  // This can be called from any thread.
103  virtual void SendReply(const ReplyMessageContext& context,
104      const IPC::Message& msg) OVERRIDE;
105
106 protected:
107  virtual ~ResourceMessageFilter();
108
109  // Please see the comments of |resource_host_| for on which thread it can be
110  // used and when it is NULL.
111  ResourceHost* resource_host() const { return resource_host_; }
112
113  // If you want the message to be handled on another thread, return a non-null
114  // task runner which will target tasks accordingly.
115  virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
116      const IPC::Message& message);
117
118 private:
119  friend class base::DeleteHelper<ResourceMessageFilter>;
120  friend class base::RefCountedThreadSafe<
121      ResourceMessageFilter, internal::ResourceMessageFilterDeleteTraits>;
122  friend struct internal::ResourceMessageFilterDeleteTraits;
123
124  // This method is posted to the target thread and runs the message handler.
125  void DispatchMessage(const IPC::Message& msg,
126                       HostMessageContext context);
127
128  scoped_refptr<base::MessageLoopProxy> deletion_message_loop_proxy_;
129
130  // Message loop to send resource message replies on. This will be the message
131  // loop proxy of the IO thread for the browser process or the main thread for
132  // the renderer process.
133  scoped_refptr<base::MessageLoopProxy> reply_thread_message_loop_proxy_;
134
135  // Non-owning pointer to the resource host owning this filter. Should only be
136  // accessed from the thread which sends messages to the plugin resource (i.e.
137  // the IO thread for the browser process or the main thread for the renderer).
138  // This will be NULL upon creation of the filter and is set to the owning
139  // ResourceHost when |OnFilterAdded| is called. When the owning ResourceHost
140  // is destroyed, |OnFilterDestroyed| is called and this will be set to NULL.
141  ResourceHost* resource_host_;
142
143  DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter);
144};
145
146}  // namespace host
147}  // namespace ppapi
148
149#endif  // PPAPI_HOST_RESOURCE_MESSAGE_FILTER_H_
150