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(¶ms->{{param.name}}))) 23{%- elif param.kind|is_interface_request_kind -%} 24mojo::MakeRequest<{{param.kind.kind|get_name_for_kind}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(¶ms->{{param.name}}))) 25{%- elif param.kind|is_any_handle_kind -%} 26mojo::MakeScopedHandle(mojo::internal::FetchAndReset(¶ms->{{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(), ¶ms->{{param.name}}.ptr); 58{%- else %} 59 Serialize_(mojo::internal::Forward(in_{{param.name}}), builder.buffer(), ¶ms->{{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