Home | History | Annotate | Download | only in proxy
      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_
    254