summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/dispatch_reply_message.h
blob: ce4c6020ef447bbc67bd0aaa617c84ae395d997d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file provides infrastructure for dispatching messasges from host
// resource, inlcuding reply messages or unsolicited replies. Normal IPC Reply
// handlers can't take extra parameters. We want to take a
// ResourceMessageReplyParams as a parameter.

#ifndef PPAPI_PROXY_DISPATCH_REPLY_MESSAGE_H_
#define PPAPI_PROXY_DISPATCH_REPLY_MESSAGE_H_

#include "base/callback.h"
#include "base/profiler/scoped_profile.h"  // For TRACK_RUN_IN_IPC_HANDLER.
#include "ipc/ipc_message_macros.h"
#include "ppapi/c/pp_errors.h"

namespace ppapi {
namespace proxy {

class ResourceMessageReplyParams;

template <class ObjT, class Method>
inline void DispatchResourceReply(ObjT* obj, Method method,
                                  const ResourceMessageReplyParams& params,
                                  const Tuple0& arg) {
  (obj->*method)(params);
}

template <class ObjT, class Method, class A>
inline void DispatchResourceReply(ObjT* obj, Method method,
                                  const ResourceMessageReplyParams& params,
                                  const Tuple1<A>& arg) {
  (obj->*method)(params, arg.a);
}

template<class ObjT, class Method, class A, class B>
inline void DispatchResourceReply(ObjT* obj, Method method,
                                  const ResourceMessageReplyParams& params,
                                  const Tuple2<A, B>& arg) {
  (obj->*method)(params, arg.a, arg.b);
}

template<class ObjT, class Method, class A, class B, class C>
inline void DispatchResourceReply(ObjT* obj, Method method,
                                  const ResourceMessageReplyParams& params,
                                  const Tuple3<A, B, C>& arg) {
  (obj->*method)(params, arg.a, arg.b, arg.c);
}

template<class ObjT, class Method, class A, class B, class C, class D>
inline void DispatchResourceReply(ObjT* obj, Method method,
                                  const ResourceMessageReplyParams& params,
                                  const Tuple4<A, B, C, D>& arg) {
  (obj->*method)(params, arg.a, arg.b, arg.c, arg.d);
}

template<class ObjT, class Method, class A, class B, class C, class D, class E>
inline void DispatchResourceReply(ObjT* obj, Method method,
                                  const ResourceMessageReplyParams& params,
                                  const Tuple5<A, B, C, D, E>& arg) {
  (obj->*method)(params, arg.a, arg.b, arg.c, arg.d, arg.e);
}

// Used to dispatch resource replies. In most cases, you should not call this
// function to dispatch a resource reply manually, but instead use
// |PluginResource::CallBrowser|/|PluginResource::CallRenderer| with a
// |base::Callback| which will be called when a reply message is received
// (see plugin_resource.h).
//
// This function will call your callback with the nested reply message's
// parameters on success. On failure, your callback will be called with each
// parameter having its default constructed value.
//
// Resource replies are a bit weird in that the host will automatically
// generate a reply in error cases (when the call handler returns error rather
// than returning "completion pending"). This makes it more convenient to write
// the call message handlers. But this also means that the reply handler has to
// handle both the success case (when all of the reply message paramaters are
// specified) and the error case (when the nested reply message is empty).
// In both cases the resource will want to issue completion callbacks to the
// plugin.
//
// This function handles the error case by calling your reply handler with the
// default value for each paramater in the error case. In most situations this
// will be the right thing. You should always dispatch completion callbacks
// using the result code present in the ResourceMessageReplyParams.
template<class MsgClass, class ObjT, class Method>
void DispatchResourceReplyOrDefaultParams(
    ObjT* obj,
    Method method,
    const ResourceMessageReplyParams& reply_params,
    const IPC::Message& msg) {
  typename MsgClass::Schema::Param msg_params;
  // We either expect the nested message type to match, or that there is no
  // nested message. No nested message indicates a default reply sent from
  // the host: when the resource message handler returns an error, a reply
  // is implicitly sent with no nested message.
  DCHECK(msg.type() == MsgClass::ID || msg.type() == 0)
      << "Resource reply message of unexpected type.";
  if (msg.type() == MsgClass::ID && MsgClass::Read(&msg, &msg_params)) {
    // Message type matches and the parameters were successfully read.
    DispatchResourceReply(obj, method, reply_params, msg_params);
  } else {
    // The nested message is empty because the host handler didn't explicitly
    // send a reply (likely), or you screwed up and didn't use the correct
    // message type when calling this function (you should have hit the
    // assertion above, Einstein).
    //
    // Dispatch the reply function with the default parameters. We explicitly
    // use a new Params() structure since if the Read failed due to an invalid
    // message, the params could have been partially filled in.
    DispatchResourceReply(obj, method, reply_params,
        typename MsgClass::Schema::Param());
  }
}

// Template specialization for |Callback|s that only accept a
// |ResourceMessageReplyParams|. In this case |msg| shouldn't contain any
// arguments, so just call the |method| with the |reply_params|.
template<class MsgClass, class Method>
void DispatchResourceReplyOrDefaultParams(
    base::Callback<void(const ResourceMessageReplyParams&)>* obj,
    Method method,
    const ResourceMessageReplyParams& reply_params,
    const IPC::Message& msg) {
  DCHECK(msg.type() == MsgClass::ID || msg.type() == 0)
      << "Resource reply message of unexpected type.";
  (obj->*method)(reply_params);
}

// When using PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL* below, use this macro to
// begin the map instead of IPC_BEGIN_MESSAGE_MAP. The reason is that the macros
// in src/ipc are all closely tied together, and there might be errors for
// unused variables or other errors if they're used with these macros.
#define PPAPI_BEGIN_MESSAGE_MAP(class_name, msg) \
  { \
    typedef class_name _IpcMessageHandlerClass ALLOW_UNUSED; \
    const IPC::Message& ipc_message__ = msg; \
    switch (ipc_message__.type()) { \

// Note that this only works for message with 1 or more parameters. For
// 0-parameter messages you need to use the _0 version below (since there are
// no params in the message).
#define PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(msg_class, member_func) \
    case msg_class::ID: { \
      msg_class::Schema::Param p; \
      if (msg_class::Read(&ipc_message__, &p)) { \
        ppapi::proxy::DispatchResourceReply( \
            this, \
            &_IpcMessageHandlerClass::member_func, \
            params, p); \
      } else { \
        NOTREACHED(); \
      } \
      break; \
    }

#define PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_0(msg_class, member_func) \
  case msg_class::ID: { \
    member_func(params); \
    break; \
  }

#define PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(code) \
    default: { \
        code; \
    } \
    break;

#define PPAPI_END_MESSAGE_MAP() \
  } \
}

}  // namespace proxy
}  // namespace ppapi

#endif  // PPAPI_PROXY_DISPATCH_REPLY_MESSAGE_H_