• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1{%- import "interface_macros.tmpl" as interface_macros %}
2{%- set class_name = interface.name %}
3{%- set proxy_name = interface.name ~ "Proxy" %}
4{%- set namespace_as_string = "%s"|format(namespace|replace(".","::")) %}
5
6{%- macro alloc_params(parameters) %}
7{%-   for param in parameters %}
8{%-     if param.kind|is_object_kind  %}
9{{param.kind|cpp_result_type}} p{{loop.index}};
10Deserialize_(params->{{param.name}}.ptr, &p{{loop.index}});
11{%      endif -%}
12{%-   endfor %}
13{%- endmacro %}
14
15{%- macro pass_params(parameters) %}
16{%-   for param in parameters %}
17{%-     if param.kind|is_string_kind -%}
18p{{loop.index}}
19{%-     elif param.kind|is_object_kind -%}
20p{{loop.index}}.Pass()
21{%-     elif param.kind|is_interface_kind -%}
22mojo::MakeProxy<{{param.kind|get_name_for_kind}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}})))
23{%-     elif param.kind|is_interface_request_kind -%}
24mojo::MakeRequest<{{param.kind.kind|get_name_for_kind}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}})))
25{%-     elif param.kind|is_any_handle_kind -%}
26mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}}))
27{%-     elif param.kind|is_enum_kind -%}
28static_cast<{{param.kind|cpp_wrapper_type}}>(params->{{param.name}})
29{%-     else -%}
30params->{{param.name}}
31{%-     endif -%}
32{%-     if not loop.last %}, {% endif %}
33{%-   endfor %}
34{%- endmacro %}
35
36{%- macro compute_payload_size(params_name, parameters) -%}
37  size_t payload_size =
38      mojo::internal::Align(sizeof({{params_name}}));
39{#--- Computes #}
40{%-   for param in parameters %}
41{%-     if param.kind|is_object_kind %}
42  payload_size += GetSerializedSize_(in_{{param.name}});
43{%-     endif %}
44{%-   endfor %}
45{%- endmacro %}
46
47{%- macro build_message(params_name, parameters, params_description) -%}
48  {# TODO(yzshen): Consider refactoring to share code with
49     struct_serialization_definition.tmpl #}
50  {{params_name}}* params =
51      {{params_name}}::New(builder.buffer());
52{#--- Sets #}
53{%   for param in parameters %}
54{%-     if param.kind|is_object_kind %}
55{%-       if param.kind|is_any_array_kind %}
56  mojo::SerializeArray_<{{param.kind|get_array_validate_params|indent(24)}}>(
57      mojo::internal::Forward(in_{{param.name}}), builder.buffer(), &params->{{param.name}}.ptr);
58{%-       else %}
59  Serialize_(mojo::internal::Forward(in_{{param.name}}), builder.buffer(), &params->{{param.name}}.ptr);
60{%-       endif %}
61{%-       if not param.kind|is_nullable_kind %}
62  MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
63      !params->{{param.name}}.ptr,
64      mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
65      "null {{param.name}} argument in {{params_description}}");
66{%-       endif %}
67{%-     elif param.kind|is_any_handle_kind %}
68{%-       if param.kind|is_interface_kind or
69             param.kind|is_interface_request_kind %}
70  // Delegate handle.
71  params->{{param.name}} = in_{{param.name}}.PassMessagePipe().release();
72{%-       else %}
73  params->{{param.name}} = in_{{param.name}}.release();
74{%-       endif %}
75{%-       if not param.kind|is_nullable_kind %}
76  MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
77      !params->{{param.name}}.is_valid(),
78      mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
79      "invalid {{param.name}} argument in {{params_description}}");
80{%-       endif %}
81{%-     else %}
82  params->{{param.name}} = in_{{param.name}};
83{%-     endif %}
84{%-   endfor %}
85  mojo::Message message;
86  params->EncodePointersAndHandles(message.mutable_handles());
87  builder.Finish(&message);
88{%- endmacro %}
89
90{#--- Begin #}
91const char* {{class_name}}::Name_ = "{{namespace_as_string}}::{{class_name}}";
92{#--- Constants #}
93{%  for constant in interface.constants %}
94const {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}} = {{constant|constant_value}};
95{%- endfor %}
96
97{#--- ForwardToCallback definition #}
98{%- for method in interface.methods -%}
99{%-   if method.response_parameters != None %}
100class {{class_name}}_{{method.name}}_ForwardToCallback
101    : public mojo::MessageReceiver {
102 public:
103  {{class_name}}_{{method.name}}_ForwardToCallback(
104      const {{interface_macros.declare_callback(method)}}& callback)
105      : callback_(callback) {
106  }
107  virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE;
108 private:
109  {{interface_macros.declare_callback(method)}} callback_;
110  MOJO_DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ForwardToCallback);
111};
112bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept(
113    mojo::Message* message) {
114  internal::{{class_name}}_{{method.name}}_ResponseParams_Data* params =
115      reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
116          message->mutable_payload());
117
118  params->DecodePointersAndHandles(message->mutable_handles());
119  {{alloc_params(method.response_parameters)|indent(2)}}
120  callback_.Run({{pass_params(method.response_parameters)}});
121  return true;
122}
123{%-   endif %}
124{%- endfor %}
125
126{{proxy_name}}::{{proxy_name}}(mojo::MessageReceiverWithResponder* receiver)
127    : receiver_(receiver) {
128}
129
130{#--- Proxy definitions #}
131
132{%- for method in interface.methods %}
133{%-   set message_name =
134          "internal::k%s_%s_Name"|format(interface.name, method.name) %}
135{%-   set params_name =
136          "internal::%s_%s_Params_Data"|format(interface.name, method.name) %}
137{%-   set params_description =
138          "%s.%s request"|format(interface.name, method.name) %}
139void {{proxy_name}}::{{method.name}}(
140    {{interface_macros.declare_request_params("in_", method)}}) {
141  {{compute_payload_size(params_name, method.parameters)}}
142
143{%- if method.response_parameters != None %}
144  mojo::internal::RequestMessageBuilder builder({{message_name}}, payload_size);
145{%- else %}
146  mojo::internal::MessageBuilder builder({{message_name}}, payload_size);
147{%- endif %}
148
149  {{build_message(params_name, method.parameters, params_description)}}
150
151{%- if method.response_parameters != None %}
152  mojo::MessageReceiver* responder =
153      new {{class_name}}_{{method.name}}_ForwardToCallback(callback);
154  if (!receiver_->AcceptWithResponder(&message, responder))
155    delete responder;
156{%- else %}
157  bool ok MOJO_ALLOW_UNUSED = receiver_->Accept(&message);
158  // This return value may be ignored as !ok implies the Connector has
159  // encountered an error, which will be visible through other means.
160{%- endif %}
161}
162{%- endfor %}
163
164{#--- ProxyToResponder definition #}
165{%- for method in interface.methods -%}
166{%-   if method.response_parameters != None %}
167{%-     set message_name =
168            "internal::k%s_%s_Name"|format(interface.name, method.name) %}
169{%-     set params_name =
170            "internal::%s_%s_ResponseParams_Data"|format(interface.name, method.name) %}
171{%-     set params_description =
172            "%s.%s response"|format(interface.name, method.name) %}
173class {{class_name}}_{{method.name}}_ProxyToResponder
174    : public {{interface_macros.declare_callback(method)}}::Runnable {
175 public:
176  virtual ~{{class_name}}_{{method.name}}_ProxyToResponder() {
177    delete responder_;
178  }
179
180  {{class_name}}_{{method.name}}_ProxyToResponder(
181      uint64_t request_id,
182      mojo::MessageReceiver* responder)
183      : request_id_(request_id),
184        responder_(responder) {
185  }
186
187  virtual void Run({{interface_macros.declare_params("in_", method.response_parameters)}}) const MOJO_OVERRIDE;
188
189 private:
190  uint64_t request_id_;
191  mutable mojo::MessageReceiver* responder_;
192  MOJO_DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ProxyToResponder);
193};
194void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
195    {{interface_macros.declare_params("in_", method.response_parameters)}}) const {
196  {{compute_payload_size(params_name, method.response_parameters)}}
197  mojo::internal::ResponseMessageBuilder builder(
198      {{message_name}}, payload_size, request_id_);
199  {{build_message(params_name, method.response_parameters, params_description)}}
200  bool ok MOJO_ALLOW_UNUSED = responder_->Accept(&message);
201  // TODO(darin): !ok returned here indicates a malformed message, and that may
202  // be good reason to close the connection. However, we don't have a way to do
203  // that from here. We should add a way.
204  delete responder_;
205  responder_ = NULL;
206}
207{%-   endif -%}
208{%- endfor %}
209
210{{class_name}}Stub::{{class_name}}Stub()
211    : sink_(NULL) {
212}
213
214{#--- Stub definition #}
215
216bool {{class_name}}Stub::Accept(mojo::Message* message) {
217{%- if interface.methods %}
218  switch (message->header()->name) {
219{%-   for method in interface.methods %}
220    case internal::k{{class_name}}_{{method.name}}_Name: {
221{%-     if method.response_parameters == None %}
222      internal::{{class_name}}_{{method.name}}_Params_Data* params =
223          reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
224              message->mutable_payload());
225
226      params->DecodePointersAndHandles(message->mutable_handles());
227      {{alloc_params(method.parameters)|indent(6)}}
228      sink_->{{method.name}}({{pass_params(method.parameters)}});
229      return true;
230{%-     else %}
231      break;
232{%-     endif %}
233    }
234{%-   endfor %}
235  }
236{%- endif %}
237  return false;
238}
239
240bool {{class_name}}Stub::AcceptWithResponder(
241    mojo::Message* message, mojo::MessageReceiver* responder) {
242{%- if interface.methods %}
243  switch (message->header()->name) {
244{%-   for method in interface.methods %}
245    case internal::k{{class_name}}_{{method.name}}_Name: {
246{%-     if method.response_parameters != None %}
247      internal::{{class_name}}_{{method.name}}_Params_Data* params =
248          reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
249              message->mutable_payload());
250
251      params->DecodePointersAndHandles(message->mutable_handles());
252      {{interface_macros.declare_callback(method)}}::Runnable* runnable =
253          new {{class_name}}_{{method.name}}_ProxyToResponder(
254              message->request_id(), responder);
255      {{interface_macros.declare_callback(method)}} callback(runnable);
256      {{alloc_params(method.parameters)|indent(6)}}
257      sink_->{{method.name}}(
258{%- if method.parameters -%}{{pass_params(method.parameters)}}, {% endif -%}callback);
259      return true;
260{%-     else %}
261      break;
262{%-     endif %}
263    }
264{%-   endfor %}
265  }
266{%- endif %}
267  return false;
268}
269
270{#--- Request validator definitions #}
271
272{{class_name}}RequestValidator::{{class_name}}RequestValidator(
273    mojo::MessageReceiver* sink) : MessageFilter(sink) {
274}
275
276bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
277{%- if interface.methods %}
278  switch (message->header()->name) {
279{%-   for method in interface.methods %}
280    case internal::k{{class_name}}_{{method.name}}_Name: {
281{%-     if method.response_parameters != None %}
282      if (!message->has_flag(mojo::internal::kMessageExpectsResponse))
283        break;
284{%-     else %}
285      if (message->has_flag(mojo::internal::kMessageExpectsResponse) ||
286          message->has_flag(mojo::internal::kMessageIsResponse)) {
287        break;
288      }
289{%-     endif %}
290      mojo::internal::BoundsChecker bounds_checker(
291          message->payload(), message->payload_num_bytes(),
292          message->handles()->size());
293      if (!internal::{{class_name}}_{{method.name}}_Params_Data::Validate(
294              message->payload(), &bounds_checker)) {
295        return false;
296      }
297      break;
298    }
299{%-   endfor %}
300  }
301{%- endif %}
302
303  return sink_->Accept(message);
304}
305
306{#--- Response validator definitions #}
307{% if interface|has_callbacks %}
308{{class_name}}ResponseValidator::{{class_name}}ResponseValidator(
309    mojo::MessageReceiver* sink) : MessageFilter(sink) {
310}
311
312bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
313{%- if interface.methods %}
314  switch (message->header()->name) {
315{%-   for method in interface.methods if method.response_parameters != None %}
316    case internal::k{{class_name}}_{{method.name}}_Name: {
317      if (!message->has_flag(mojo::internal::kMessageIsResponse))
318        break;
319      mojo::internal::BoundsChecker bounds_checker(
320          message->payload(), message->payload_num_bytes(),
321          message->handles()->size());
322      if (!internal::{{class_name}}_{{method.name}}_ResponseParams_Data::Validate(
323              message->payload(), &bounds_checker)) {
324        return false;
325      }
326      break;
327    }
328{%-   endfor %}
329  }
330{%- endif %}
331
332  return sink_->Accept(message);
333}
334{%- endif -%}
335