- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / plugin_resource.h
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_PROXY_PLUGIN_RESOURCE_H_
6 #define PPAPI_PROXY_PLUGIN_RESOURCE_H_
7
8 #include <map>
9
10 #include "base/basictypes.h"
11 #include "base/compiler_specific.h"
12 #include "ipc/ipc_message.h"
13 #include "ipc/ipc_sender.h"
14 #include "ppapi/c/pp_errors.h"
15 #include "ppapi/proxy/connection.h"
16 #include "ppapi/proxy/plugin_resource_callback.h"
17 #include "ppapi/proxy/ppapi_message_utils.h"
18 #include "ppapi/proxy/ppapi_proxy_export.h"
19 #include "ppapi/proxy/resource_message_params.h"
20 #include "ppapi/shared_impl/resource.h"
21
22 namespace ppapi {
23 namespace proxy {
24
25 class PluginDispatcher;
26
27 class PPAPI_PROXY_EXPORT PluginResource : public Resource {
28  public:
29   enum Destination {
30     RENDERER = 0,
31     BROWSER = 1
32   };
33
34   PluginResource(Connection connection, PP_Instance instance);
35   virtual ~PluginResource();
36
37   // Returns true if we've previously sent a create message to the browser
38   // or renderer. Generally resources will use these to tell if they should
39   // lazily send create messages.
40   bool sent_create_to_browser() const { return sent_create_to_browser_; }
41   bool sent_create_to_renderer() const { return sent_create_to_renderer_; }
42
43   // This handles a reply to a resource call. It works by looking up the
44   // callback that was registered when CallBrowser/CallRenderer was called
45   // and calling it with |params| and |msg|.
46   virtual void OnReplyReceived(const proxy::ResourceMessageReplyParams& params,
47                                const IPC::Message& msg) OVERRIDE;
48
49   // Resource overrides.
50   // Note: Subclasses shouldn't override these methods directly. Instead, they
51   // should implement LastPluginRefWasDeleted() or InstanceWasDeleted() to get
52   // notified.
53   virtual void NotifyLastPluginRefWasDeleted() OVERRIDE;
54   virtual void NotifyInstanceWasDeleted() OVERRIDE;
55
56
57   // Sends a create message to the browser or renderer for the current resource.
58   void SendCreate(Destination dest, const IPC::Message& msg);
59
60   // When the host returnes a resource to the plugin, it will create a pending
61   // ResourceHost and send an ID back to the plugin that identifies the pending
62   // object. The plugin uses this function to connect the plugin resource with
63   // the pending host resource. See also PpapiHostMsg_AttachToPendingHost. This
64   // is in lieu of sending a create message.
65   void AttachToPendingHost(Destination dest, int pending_host_id);
66
67   // Sends the given IPC message as a resource request to the host
68   // corresponding to this resource object and does not expect a reply.
69   void Post(Destination dest, const IPC::Message& msg);
70
71   // Like Post() but expects a response. |callback| is a |base::Callback| that
72   // will be run when a reply message with a sequence number matching that of
73   // the call is received. |ReplyMsgClass| is the type of the reply message that
74   // is expected. An example of usage:
75   //
76   // Call<PpapiPluginMsg_MyResourceType_MyReplyMessage>(
77   //     BROWSER,
78   //     PpapiHostMsg_MyResourceType_MyRequestMessage(),
79   //     base::Bind(&MyPluginResource::ReplyHandler, base::Unretained(this)));
80   //
81   // If a reply message to this call is received whose type does not match
82   // |ReplyMsgClass| (for example, in the case of an error), the callback will
83   // still be invoked but with the default values of the message parameters.
84   //
85   // Returns the new request's sequence number which can be used to identify
86   // the callback. This value will never be 0, which you can use to identify
87   // an invalid callback.
88   //
89   // Note: 1) When all plugin references to this resource are gone or the
90   //          corresponding plugin instance is deleted, all pending callbacks
91   //          are abandoned.
92   //       2) It is *not* recommended to let |callback| hold any reference to
93   //          |this|, in which it will be stored. Otherwise, this object will
94   //          live forever if we fail to clean up the callback. It is safe to
95   //          use base::Unretained(this) or a weak pointer, because this object
96   //          will outlive the callback.
97   template<typename ReplyMsgClass, typename CallbackType>
98   int32_t Call(Destination dest,
99                const IPC::Message& msg,
100                const CallbackType& callback);
101
102   // Calls the browser/renderer with sync messages. Returns the pepper error
103   // code from the call.
104   // |ReplyMsgClass| is the type of the reply message that is expected. If it
105   // carries x parameters, then the method with x out parameters should be used.
106   // An example of usage:
107   //
108   // // Assuming the reply message carries a string and an integer.
109   // std::string param_1;
110   // int param_2 = 0;
111   // int32_t result = SyncCall<PpapiPluginMsg_MyResourceType_MyReplyMessage>(
112   //     RENDERER, PpapiHostMsg_MyResourceType_MyRequestMessage(),
113   //     &param_1, &param_2);
114   template <class ReplyMsgClass>
115   int32_t SyncCall(Destination dest, const IPC::Message& msg);
116   template <class ReplyMsgClass, class A>
117   int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a);
118   template <class ReplyMsgClass, class A, class B>
119   int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a, B* b);
120   template <class ReplyMsgClass, class A, class B, class C>
121   int32_t SyncCall(Destination dest, const IPC::Message& msg, A* a, B* b, C* c);
122   template <class ReplyMsgClass, class A, class B, class C, class D>
123   int32_t SyncCall(
124       Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d);
125   template <class ReplyMsgClass, class A, class B, class C, class D, class E>
126   int32_t SyncCall(
127       Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e);
128
129   int32_t GenericSyncCall(Destination dest,
130                           const IPC::Message& msg,
131                           IPC::Message* reply_msg,
132                           ResourceMessageReplyParams* reply_params);
133
134   const Connection& connection() { return connection_; }
135
136  private:
137   IPC::Sender* GetSender(Destination dest) {
138     return dest == RENDERER ? connection_.renderer_sender :
139                               connection_.browser_sender;
140   }
141
142   // Helper function to send a |PpapiHostMsg_ResourceCall| to the given
143   // destination with |nested_msg| and |call_params|.
144   bool SendResourceCall(Destination dest,
145                         const ResourceMessageCallParams& call_params,
146                         const IPC::Message& nested_msg);
147
148   int32_t GetNextSequence();
149
150   Connection connection_;
151
152   // Use GetNextSequence to retrieve the next value.
153   int32_t next_sequence_number_;
154
155   bool sent_create_to_browser_;
156   bool sent_create_to_renderer_;
157
158   typedef std::map<int32_t, scoped_refptr<PluginResourceCallbackBase> >
159       CallbackMap;
160   CallbackMap callbacks_;
161
162   DISALLOW_COPY_AND_ASSIGN(PluginResource);
163 };
164
165 template<typename ReplyMsgClass, typename CallbackType>
166 int32_t PluginResource::Call(Destination dest,
167                              const IPC::Message& msg,
168                              const CallbackType& callback) {
169   TRACE_EVENT2("ppapi proxy", "PluginResource::Call",
170                "Class", IPC_MESSAGE_ID_CLASS(msg.type()),
171                "Line", IPC_MESSAGE_ID_LINE(msg.type()));
172   ResourceMessageCallParams params(pp_resource(), next_sequence_number_++);
173   // Stash the |callback| in |callbacks_| identified by the sequence number of
174   // the call.
175   scoped_refptr<PluginResourceCallbackBase> plugin_callback(
176       new PluginResourceCallback<ReplyMsgClass, CallbackType>(callback));
177   callbacks_.insert(std::make_pair(params.sequence(), plugin_callback));
178   params.set_has_callback();
179   SendResourceCall(dest, params, msg);
180   return params.sequence();
181 }
182
183 template <class ReplyMsgClass>
184 int32_t PluginResource::SyncCall(Destination dest, const IPC::Message& msg) {
185   IPC::Message reply;
186   ResourceMessageReplyParams reply_params;
187   return GenericSyncCall(dest, msg, &reply, &reply_params);
188 }
189
190 template <class ReplyMsgClass, class A>
191 int32_t PluginResource::SyncCall(
192     Destination dest, const IPC::Message& msg, A* a) {
193   IPC::Message reply;
194   ResourceMessageReplyParams reply_params;
195   int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
196
197   if (UnpackMessage<ReplyMsgClass>(reply, a))
198     return result;
199   return PP_ERROR_FAILED;
200 }
201
202 template <class ReplyMsgClass, class A, class B>
203 int32_t PluginResource::SyncCall(
204     Destination dest, const IPC::Message& msg, A* a, B* b) {
205   IPC::Message reply;
206   ResourceMessageReplyParams reply_params;
207   int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
208
209   if (UnpackMessage<ReplyMsgClass>(reply, a, b))
210     return result;
211   return PP_ERROR_FAILED;
212 }
213
214 template <class ReplyMsgClass, class A, class B, class C>
215 int32_t PluginResource::SyncCall(
216     Destination dest, const IPC::Message& msg, A* a, B* b, C* c) {
217   IPC::Message reply;
218   ResourceMessageReplyParams reply_params;
219   int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
220
221   if (UnpackMessage<ReplyMsgClass>(reply, a, b, c))
222     return result;
223   return PP_ERROR_FAILED;
224 }
225
226 template <class ReplyMsgClass, class A, class B, class C, class D>
227 int32_t PluginResource::SyncCall(
228     Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d) {
229   IPC::Message reply;
230   ResourceMessageReplyParams reply_params;
231   int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
232
233   if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d))
234     return result;
235   return PP_ERROR_FAILED;
236 }
237
238 template <class ReplyMsgClass, class A, class B, class C, class D, class E>
239 int32_t PluginResource::SyncCall(
240     Destination dest, const IPC::Message& msg, A* a, B* b, C* c, D* d, E* e) {
241   IPC::Message reply;
242   ResourceMessageReplyParams reply_params;
243   int32_t result = GenericSyncCall(dest, msg, &reply, &reply_params);
244
245   if (UnpackMessage<ReplyMsgClass>(reply, a, b, c, d, e))
246     return result;
247   return PP_ERROR_FAILED;
248 }
249
250 }  // namespace proxy
251 }  // namespace ppapi
252
253 #endif  // PPAPI_PROXY_PLUGIN_RESOURCE_H_