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.
5 #ifndef PPAPI_PROXY_PLUGIN_RESOURCE_H_
6 #define PPAPI_PROXY_PLUGIN_RESOURCE_H_
10 #include "base/basictypes.h"
11 #include "base/compiler_specific.h"
12 #include "base/memory/ref_counted.h"
13 #include "ipc/ipc_message.h"
14 #include "ipc/ipc_sender.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/proxy/connection.h"
17 #include "ppapi/proxy/plugin_resource_callback.h"
18 #include "ppapi/proxy/ppapi_message_utils.h"
19 #include "ppapi/proxy/ppapi_proxy_export.h"
20 #include "ppapi/proxy/resource_message_params.h"
21 #include "ppapi/proxy/resource_reply_thread_registrar.h"
22 #include "ppapi/shared_impl/resource.h"
23 #include "ppapi/shared_impl/tracked_callback.h"
27 class PluginDispatcher
;
29 class PPAPI_PROXY_EXPORT PluginResource
: public Resource
{
36 PluginResource(Connection connection
, PP_Instance instance
);
37 virtual ~PluginResource();
39 // Returns true if we've previously sent a create message to the browser
40 // or renderer. Generally resources will use these to tell if they should
41 // lazily send create messages.
42 bool sent_create_to_browser() const { return sent_create_to_browser_
; }
43 bool sent_create_to_renderer() const { return sent_create_to_renderer_
; }
45 // This handles a reply to a resource call. It works by looking up the
46 // callback that was registered when CallBrowser/CallRenderer was called
47 // and calling it with |params| and |msg|.
48 virtual void OnReplyReceived(const proxy::ResourceMessageReplyParams
& params
,
49 const IPC::Message
& msg
) OVERRIDE
;
51 // Resource overrides.
52 // Note: Subclasses shouldn't override these methods directly. Instead, they
53 // should implement LastPluginRefWasDeleted() or InstanceWasDeleted() to get
55 virtual void NotifyLastPluginRefWasDeleted() OVERRIDE
;
56 virtual void NotifyInstanceWasDeleted() OVERRIDE
;
59 // Sends a create message to the browser or renderer for the current resource.
60 void SendCreate(Destination dest
, const IPC::Message
& msg
);
62 // When the host returnes a resource to the plugin, it will create a pending
63 // ResourceHost and send an ID back to the plugin that identifies the pending
64 // object. The plugin uses this function to connect the plugin resource with
65 // the pending host resource. See also PpapiHostMsg_AttachToPendingHost. This
66 // is in lieu of sending a create message.
67 void AttachToPendingHost(Destination dest
, int pending_host_id
);
69 // Sends the given IPC message as a resource request to the host
70 // corresponding to this resource object and does not expect a reply.
71 void Post(Destination dest
, const IPC::Message
& msg
);
73 // Like Post() but expects a response. |callback| is a |base::Callback| that
74 // will be run when a reply message with a sequence number matching that of
75 // the call is received. |ReplyMsgClass| is the type of the reply message that
76 // is expected. An example of usage:
78 // Call<PpapiPluginMsg_MyResourceType_MyReplyMessage>(
80 // PpapiHostMsg_MyResourceType_MyRequestMessage(),
81 // base::Bind(&MyPluginResource::ReplyHandler, base::Unretained(this)));
83 // If a reply message to this call is received whose type does not match
84 // |ReplyMsgClass| (for example, in the case of an error), the callback will
85 // still be invoked but with the default values of the message parameters.
87 // Returns the new request's sequence number which can be used to identify
88 // the callback. This value will never be 0, which you can use to identify
89 // an invalid callback.
91 // Note: 1) When all plugin references to this resource are gone or the
92 // corresponding plugin instance is deleted, all pending callbacks
94 // 2) It is *not* recommended to let |callback| hold any reference to
95 // |this|, in which it will be stored. Otherwise, this object will
96 // live forever if we fail to clean up the callback. It is safe to
97 // use base::Unretained(this) or a weak pointer, because this object
98 // will outlive the callback.
99 template<typename ReplyMsgClass
, typename CallbackType
>
100 int32_t Call(Destination dest
,
101 const IPC::Message
& msg
,
102 const CallbackType
& callback
);
104 // Comparing with the previous Call() method, this method takes
105 // |reply_thread_hint| as a hint to determine which thread to handle the reply
108 // If |reply_thread_hint| is non-blocking, the reply message will be handled
109 // on the target thread of the callback; otherwise, it will be handled on the
112 // If handling a reply message will cause a TrackedCallback to be run, it is
113 // recommended to use this version of Call(). It eliminates unnecessary
114 // thread switching and therefore has better performance.
115 template<typename ReplyMsgClass
, typename CallbackType
>
116 int32_t Call(Destination dest
,
117 const IPC::Message
& msg
,
118 const CallbackType
& callback
,
119 scoped_refptr
<TrackedCallback
> reply_thread_hint
);
121 // Calls the browser/renderer with sync messages. Returns the pepper error
122 // code from the call.
123 // |ReplyMsgClass| is the type of the reply message that is expected. If it
124 // carries x parameters, then the method with x out parameters should be used.
125 // An example of usage:
127 // // Assuming the reply message carries a string and an integer.
128 // std::string param_1;
130 // int32_t result = SyncCall<PpapiPluginMsg_MyResourceType_MyReplyMessage>(
131 // RENDERER, PpapiHostMsg_MyResourceType_MyRequestMessage(),
132 // ¶m_1, ¶m_2);
133 template <class ReplyMsgClass
>
134 int32_t SyncCall(Destination dest
, const IPC::Message
& msg
);
135 template <class ReplyMsgClass
, class A
>
136 int32_t SyncCall(Destination dest
, const IPC::Message
& msg
, A
* a
);
137 template <class ReplyMsgClass
, class A
, class B
>
138 int32_t SyncCall(Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
);
139 template <class ReplyMsgClass
, class A
, class B
, class C
>
140 int32_t SyncCall(Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
, C
* c
);
141 template <class ReplyMsgClass
, class A
, class B
, class C
, class D
>
143 Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
, C
* c
, D
* d
);
144 template <class ReplyMsgClass
, class A
, class B
, class C
, class D
, class E
>
146 Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
, C
* c
, D
* d
, E
* e
);
148 int32_t GenericSyncCall(Destination dest
,
149 const IPC::Message
& msg
,
150 IPC::Message
* reply_msg
,
151 ResourceMessageReplyParams
* reply_params
);
153 const Connection
& connection() { return connection_
; }
156 IPC::Sender
* GetSender(Destination dest
) {
157 return dest
== RENDERER
? connection_
.renderer_sender
:
158 connection_
.browser_sender
;
161 // Helper function to send a |PpapiHostMsg_ResourceCall| to the given
162 // destination with |nested_msg| and |call_params|.
163 bool SendResourceCall(Destination dest
,
164 const ResourceMessageCallParams
& call_params
,
165 const IPC::Message
& nested_msg
);
167 int32_t GetNextSequence();
169 Connection connection_
;
171 // Use GetNextSequence to retrieve the next value.
172 int32_t next_sequence_number_
;
174 bool sent_create_to_browser_
;
175 bool sent_create_to_renderer_
;
177 typedef std::map
<int32_t, scoped_refptr
<PluginResourceCallbackBase
> >
179 CallbackMap callbacks_
;
181 scoped_refptr
<ResourceReplyThreadRegistrar
> resource_reply_thread_registrar_
;
183 DISALLOW_COPY_AND_ASSIGN(PluginResource
);
186 template<typename ReplyMsgClass
, typename CallbackType
>
187 int32_t PluginResource::Call(Destination dest
,
188 const IPC::Message
& msg
,
189 const CallbackType
& callback
) {
190 return Call
<ReplyMsgClass
>(dest
, msg
, callback
, NULL
);
193 template<typename ReplyMsgClass
, typename CallbackType
>
194 int32_t PluginResource::Call(
196 const IPC::Message
& msg
,
197 const CallbackType
& callback
,
198 scoped_refptr
<TrackedCallback
> reply_thread_hint
) {
199 TRACE_EVENT2("ppapi proxy", "PluginResource::Call",
200 "Class", IPC_MESSAGE_ID_CLASS(msg
.type()),
201 "Line", IPC_MESSAGE_ID_LINE(msg
.type()));
202 ResourceMessageCallParams
params(pp_resource(), next_sequence_number_
++);
203 // Stash the |callback| in |callbacks_| identified by the sequence number of
205 scoped_refptr
<PluginResourceCallbackBase
> plugin_callback(
206 new PluginResourceCallback
<ReplyMsgClass
, CallbackType
>(callback
));
207 callbacks_
.insert(std::make_pair(params
.sequence(), plugin_callback
));
208 params
.set_has_callback();
210 if (resource_reply_thread_registrar_
.get()) {
211 resource_reply_thread_registrar_
->Register(
212 pp_resource(), params
.sequence(), reply_thread_hint
);
214 SendResourceCall(dest
, params
, msg
);
215 return params
.sequence();
218 template <class ReplyMsgClass
>
219 int32_t PluginResource::SyncCall(Destination dest
, const IPC::Message
& msg
) {
221 ResourceMessageReplyParams reply_params
;
222 return GenericSyncCall(dest
, msg
, &reply
, &reply_params
);
225 template <class ReplyMsgClass
, class A
>
226 int32_t PluginResource::SyncCall(
227 Destination dest
, const IPC::Message
& msg
, A
* a
) {
229 ResourceMessageReplyParams reply_params
;
230 int32_t result
= GenericSyncCall(dest
, msg
, &reply
, &reply_params
);
232 if (UnpackMessage
<ReplyMsgClass
>(reply
, a
))
234 return PP_ERROR_FAILED
;
237 template <class ReplyMsgClass
, class A
, class B
>
238 int32_t PluginResource::SyncCall(
239 Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
) {
241 ResourceMessageReplyParams reply_params
;
242 int32_t result
= GenericSyncCall(dest
, msg
, &reply
, &reply_params
);
244 if (UnpackMessage
<ReplyMsgClass
>(reply
, a
, b
))
246 return PP_ERROR_FAILED
;
249 template <class ReplyMsgClass
, class A
, class B
, class C
>
250 int32_t PluginResource::SyncCall(
251 Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
, C
* c
) {
253 ResourceMessageReplyParams reply_params
;
254 int32_t result
= GenericSyncCall(dest
, msg
, &reply
, &reply_params
);
256 if (UnpackMessage
<ReplyMsgClass
>(reply
, a
, b
, c
))
258 return PP_ERROR_FAILED
;
261 template <class ReplyMsgClass
, class A
, class B
, class C
, class D
>
262 int32_t PluginResource::SyncCall(
263 Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
, C
* c
, D
* d
) {
265 ResourceMessageReplyParams reply_params
;
266 int32_t result
= GenericSyncCall(dest
, msg
, &reply
, &reply_params
);
268 if (UnpackMessage
<ReplyMsgClass
>(reply
, a
, b
, c
, d
))
270 return PP_ERROR_FAILED
;
273 template <class ReplyMsgClass
, class A
, class B
, class C
, class D
, class E
>
274 int32_t PluginResource::SyncCall(
275 Destination dest
, const IPC::Message
& msg
, A
* a
, B
* b
, C
* c
, D
* d
, E
* e
) {
277 ResourceMessageReplyParams reply_params
;
278 int32_t result
= GenericSyncCall(dest
, msg
, &reply
, &reply_params
);
280 if (UnpackMessage
<ReplyMsgClass
>(reply
, a
, b
, c
, d
, e
))
282 return PP_ERROR_FAILED
;
288 #endif // PPAPI_PROXY_PLUGIN_RESOURCE_H_