forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdispatch_reply_message.h
203 lines (184 loc) · 8.87 KB
/
dispatch_reply_message.h
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// 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 <tuple>
#include <utility>
#include "base/callback.h"
#include "base/tuple.h"
#include "ipc/ipc_message_macros.h"
#include "ppapi/c/pp_errors.h"
namespace ppapi {
namespace proxy {
class ResourceMessageReplyParams;
template <typename ObjT, typename Method, typename TupleType, size_t... indices>
inline void DispatchResourceReplyImpl(ObjT* obj,
Method method,
const ResourceMessageReplyParams& params,
TupleType&& args_tuple,
std::index_sequence<indices...>) {
(obj->*method)(params,
std::get<indices>(std::forward<TupleType>(args_tuple))...);
}
// Runs |method| on |obj| with |params| and expanded |args_tuple|.
// I.e. Followings are equivalent.
// DispatchResourceReply(obj, &Obj::Method, params, std::tie(a, b, c));
// obj->Method(params, a, b, c);
template <typename ObjT, typename Method, typename TupleType>
inline void DispatchResourceReply(ObjT* obj,
Method method,
const ResourceMessageReplyParams& params,
TupleType&& args_tuple) {
constexpr size_t size = std::tuple_size<std::decay_t<TupleType>>::value;
DispatchResourceReplyImpl(obj, method, params,
std::forward<TupleType>(args_tuple),
std::make_index_sequence<size>());
}
template <typename CallbackType, typename TupleType, size_t... indices>
inline void DispatchResourceReplyImpl(CallbackType&& callback,
const ResourceMessageReplyParams& params,
TupleType&& args_tuple,
std::index_sequence<indices...>) {
std::forward<CallbackType>(callback).Run(
params, std::get<indices>(std::forward<TupleType>(args_tuple))...);
}
// Runs |callback| with |params| and expanded |args_tuple|.
// I.e. Followings are equivalent.
// DispatchResourceReply(callback, params, std::tie(a, b, c));
// callback.Run(params, a, b, c);
template <typename CallbackType, typename TupleType>
inline void DispatchResourceReply(CallbackType&& callback,
const ResourceMessageReplyParams& params,
TupleType&& args_tuple) {
constexpr size_t size = std::tuple_size<std::decay_t<TupleType>>::value;
DispatchResourceReplyImpl(std::forward<CallbackType>(callback), params,
std::forward<TupleType>(args_tuple),
std::make_index_sequence<size>());
}
// 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 <typename MsgClass, typename CallbackType>
void DispatchResourceReplyOrDefaultParams(
CallbackType&& callback,
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(std::forward<CallbackType>(callback), 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(std::forward<CallbackType>(callback), reply_params,
typename MsgClass::Schema::Param());
}
}
// 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_TYPE; \
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_