| OLD | NEW |
| (Empty) | |
| 1 // This file is generated |
| 2 |
| 3 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 4 // Use of this source code is governed by a BSD-style license that can be |
| 5 // found in the LICENSE file. |
| 6 |
| 7 #include "platform/inspector_protocol/{{class_name}}.h" |
| 8 |
| 9 #include "platform/JSONParser.h" |
| 10 #include "platform/inspector_protocol/FrontendChannel.h" |
| 11 #include "wtf/text/CString.h" |
| 12 |
| 13 namespace blink { |
| 14 namespace protocol { |
| 15 |
| 16 using protocol::OptionalValue; |
| 17 |
| 18 class DispatcherImpl : public Dispatcher { |
| 19 public: |
| 20 DispatcherImpl(FrontendChannel* frontendChannel) |
| 21 : m_frontendChannel(frontendChannel) |
| 22 {% for domain in api.domains %} |
| 23 , m_{{domain.domain | lower}}Agent(0) |
| 24 {% endfor %} |
| 25 { |
| 26 {% for domain in api.domains %} |
| 27 {% for command in domain.commands %} |
| 28 {% if "redirect" in command %}{% continue %}{% endif %} |
| 29 {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{%
continue %}{% endif %} |
| 30 m_dispatchMap.add("{{domain.domain}}.{{command.name}}", &DispatcherImpl:
:{{domain.domain}}_{{command.name}}); |
| 31 {% endfor %} |
| 32 {% endfor %} |
| 33 |
| 34 // Initialize common errors. |
| 35 m_commonErrors.insert(ParseError, -32700); |
| 36 m_commonErrors.insert(InvalidRequest, -32600); |
| 37 m_commonErrors.insert(MethodNotFound, -32601); |
| 38 m_commonErrors.insert(InvalidParams, -32602); |
| 39 m_commonErrors.insert(InternalError, -32603); |
| 40 m_commonErrors.insert(ServerError, -32000); |
| 41 } |
| 42 |
| 43 virtual void clearFrontend() { m_frontendChannel = 0; } |
| 44 virtual void dispatch(int sessionId, const String& message); |
| 45 virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode,
const String& errorMessage, PassRefPtr<JSONValue> data) const; |
| 46 using Dispatcher::reportProtocolError; |
| 47 |
| 48 void sendResponse(int sessionId, int callId, const ErrorString& invocationEr
ror, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result); |
| 49 bool isActive() { return m_frontendChannel; } |
| 50 |
| 51 {% for domain in api.domains %} |
| 52 virtual void registerAgent({{domain.domain}}CommandHandler* agent) { ASSERT(
!m_{{domain.domain | lower}}Agent); m_{{domain.domain | lower}}Agent = agent; } |
| 53 {% endfor %} |
| 54 |
| 55 private: |
| 56 using CallHandler = void (DispatcherImpl::*)(int sessionId, int callId, JSON
Object* messageObject, JSONArray* protocolErrors); |
| 57 using DispatchMap = HashMap<String, CallHandler>; |
| 58 |
| 59 {% for domain in api.domains %} |
| 60 {% for command in domain.commands %} |
| 61 {% if "redirect" in command %}{% continue %}{% endif %} |
| 62 {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{%
continue %}{% endif %} |
| 63 void {{domain.domain}}_{{command.name}}(int sessionId, int callId, JSONObjec
t* requestMessageObject, JSONArray* protocolErrors); |
| 64 {% endfor %} |
| 65 {% endfor %} |
| 66 |
| 67 FrontendChannel* m_frontendChannel; |
| 68 |
| 69 {% for domain in api.domains %} |
| 70 {{domain.domain}}CommandHandler* m_{{domain.domain | lower}}Agent; |
| 71 {% endfor %} |
| 72 |
| 73 template<typename R, typename V, typename V0> |
| 74 static R getPropertyValueImpl(JSONObject* object, const char* name, bool* va
lueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JSONVal
ue*, V*), const char* type_name); |
| 75 |
| 76 static OptionalValue<int> getInteger(JSONObject* object, const char* name, b
ool isOptional, JSONArray* protocolErrors); |
| 77 static OptionalValue<double> getNumber(JSONObject* object, const char* name,
bool isOptional, JSONArray* protocolErrors); |
| 78 static OptionalValue<String> getString(JSONObject* object, const char* name,
bool isOptional, JSONArray* protocolErrors); |
| 79 static OptionalValue<bool> getBoolean(JSONObject* object, const char* name,
bool isOptional, JSONArray* protocolErrors); |
| 80 static PassRefPtr<JSONObject> getObject(JSONObject* object, const char* name
, bool isOptional, JSONArray* protocolErrors); |
| 81 static PassRefPtr<JSONArray> getArray(JSONObject* object, const char* name,
bool isOptional, JSONArray* protocolErrors); |
| 82 |
| 83 void sendResponse(int sessionId, int callId, ErrorString invocationError, Pa
ssRefPtr<JSONObject> result) |
| 84 { |
| 85 sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), re
sult); |
| 86 } |
| 87 |
| 88 void sendResponse(int sessionId, int callId, ErrorString invocationError) |
| 89 { |
| 90 sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), JS
ONObject::create()); |
| 91 } |
| 92 |
| 93 static const char InvalidParamsFormatString[]; |
| 94 |
| 95 DispatchMap m_dispatchMap; |
| 96 Vector<int> m_commonErrors; |
| 97 }; |
| 98 |
| 99 const char DispatcherImpl::InvalidParamsFormatString[] = "Some arguments of meth
od '%s' can't be processed"; |
| 100 {% for domain in api.domains %} |
| 101 {% for command in domain.commands %} |
| 102 {% if "redirect" in command %}{% continue %}{% endif %} |
| 103 {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{%
continue %}{% endif %} |
| 104 |
| 105 {% if "async" in command %} |
| 106 Dispatcher::{{domain.domain}}CommandHandler::{{command.name | to_title_case}}Cal
lback::{{command.name | to_title_case}}Callback(PassRefPtr<DispatcherImpl> backe
ndImpl, int sessionId, int id) : CallbackBase(backendImpl, sessionId, id) { } |
| 107 |
| 108 void Dispatcher::{{domain.domain}}CommandHandler::{{command.name | to_title_case
}}Callback::sendSuccess( |
| 109 {%- for parameter in command.returns -%} |
| 110 {%- if "optional" in parameter -%} |
| 111 {{resolve_type(parameter).optional_pass_type}} {{parameter.name}} |
| 112 {%- else -%} |
| 113 {{resolve_type(parameter).pass_type}} {{parameter.name}} |
| 114 {%- endif -%} |
| 115 {%- if not loop.last -%}, {% endif -%} |
| 116 {% endfor %}) |
| 117 { |
| 118 RefPtr<JSONObject> resultObject = JSONObject::create(); |
| 119 {% for parameter in command.returns %} |
| 120 {% if "optional" in parameter %} |
| 121 {{resolve_type(parameter).optional_type}} opt_{{parameter.name}} = {{paramet
er.name}}; |
| 122 if (hasValue({{parameter.name}})) |
| 123 resultObject->setValue("{{parameter.name}}", toValue({{resolve_type(para
meter).from_optional_out % ("opt_" + parameter.name)}})); |
| 124 {% else %} |
| 125 resultObject->setValue("{{parameter.name}}", toValue({{parameter.name}})); |
| 126 {% endif %} |
| 127 {% endfor %} |
| 128 sendIfActive(resultObject.release(), ErrorString(), PassRefPtr<JSONValue>())
; |
| 129 } |
| 130 {% endif %} |
| 131 |
| 132 void DispatcherImpl::{{domain.domain}}_{{command.name}}(int sessionId, int callI
d, JSONObject* requestMessageObject, JSONArray* protocolErrors) |
| 133 { |
| 134 if (!m_{{domain.domain | lower}}Agent) |
| 135 protocolErrors->pushString("Inspector handler is not available."); |
| 136 |
| 137 if (protocolErrors->length()) { |
| 138 reportProtocolError(sessionId, callId, InvalidParams, String::format(Inv
alidParamsFormatString, "{{domain.domain}}.{{command.name}}"), protocolErrors); |
| 139 return; |
| 140 } |
| 141 |
| 142 {% if "parameters" in command %} |
| 143 // Prepare input parameters. |
| 144 RefPtr<JSONObject> paramsContainer = requestMessageObject->getObject("params
"); |
| 145 JSONObject* paramsContainerPtr = paramsContainer.get(); |
| 146 {% for property in command.parameters %} |
| 147 {{resolve_type(property).optional_type}} in_{{property.name}} = {{resolve_ty
pe(property).json_getter % ("paramsContainerPtr, \"" + property.name + "\", " +
("true" if "optional" in property else "false") + ", protocolErrors")}}; |
| 148 {% endfor %} |
| 149 {% endif %} |
| 150 |
| 151 if (protocolErrors->length()) { |
| 152 reportProtocolError(sessionId, callId, InvalidParams, String::format(Inv
alidParamsFormatString, "{{domain.domain}}.{{command.name}}"), protocolErrors); |
| 153 return; |
| 154 } |
| 155 |
| 156 {% if "async" in command %} |
| 157 RefPtr<{{domain.domain}}CommandHandler::{{command.name | to_title_case}}Call
back> callback = adoptRef(new {{domain.domain}}CommandHandler::{{command.name |
to_title_case}}Callback(this, sessionId, callId)); |
| 158 {% elif "returns" in command %} |
| 159 // Declare output parameters. |
| 160 RefPtr<JSONObject> result = JSONObject::create(); |
| 161 {% for property in command.returns %} |
| 162 {% if "optional" in property %} |
| 163 {{resolve_type(property).optional_type}} out_{{property.name}}; |
| 164 {% else %} |
| 165 {{resolve_type(property).type}} out_{{property.name}}; |
| 166 {% endif %} |
| 167 {% endfor %} |
| 168 {% endif %} |
| 169 |
| 170 ErrorString error; |
| 171 m_{{domain.domain | lower}}Agent->{{command.name}}(&error |
| 172 {%- for property in command.parameters -%} |
| 173 {%- if "optional" in property -%} |
| 174 , {{resolve_type(property).to_pass_type % ("in_" + property.name)}} |
| 175 {%- else -%} |
| 176 , {{resolve_type(property).from_optional_out % ("in_" + property.name)}} |
| 177 {%- endif -%} |
| 178 {%- endfor %} |
| 179 {%- if "async" in command -%} |
| 180 , callback.release() |
| 181 {%- elif "returns" in command %} |
| 182 {%- for property in command.returns -%} |
| 183 , &out_{{property.name}} |
| 184 {%- endfor %} |
| 185 {% endif %}); |
| 186 {% if "returns" in command and not("async" in command) %} |
| 187 if (!error.length()) { |
| 188 {% for parameter in command.returns %} |
| 189 {% if "optional" in parameter %} |
| 190 if (hasValue(out_{{parameter.name}})) |
| 191 result->setValue("{{parameter.name}}", toValue({{resolve_type(parame
ter).from_optional_out % ("out_" + parameter.name)}})); |
| 192 {% else %} |
| 193 result->setValue("{{parameter.name}}", toValue(out_{{resolve_type(parame
ter).to_pass_type % parameter.name}})); |
| 194 {% endif %} |
| 195 {% endfor %} |
| 196 } |
| 197 sendResponse(sessionId, callId, error, result); |
| 198 {% elif not("async" in command) %} |
| 199 sendResponse(sessionId, callId, error); |
| 200 {% endif %} |
| 201 } |
| 202 {% endfor %} |
| 203 {% endfor %} |
| 204 |
| 205 PassRefPtr<Dispatcher> Dispatcher::create(FrontendChannel* frontendChannel) |
| 206 { |
| 207 return adoptRef(new DispatcherImpl(frontendChannel)); |
| 208 } |
| 209 |
| 210 void DispatcherImpl::dispatch(int sessionId, const String& message) |
| 211 { |
| 212 RefPtr<Dispatcher> protect(this); |
| 213 int callId = 0; |
| 214 RefPtr<JSONValue> parsedMessage = parseJSON(message); |
| 215 ASSERT(parsedMessage); |
| 216 RefPtr<JSONObject> messageObject = parsedMessage->asObject(); |
| 217 ASSERT(messageObject); |
| 218 |
| 219 RefPtr<JSONValue> callIdValue = messageObject->get("id"); |
| 220 bool success = callIdValue->asNumber(&callId); |
| 221 ASSERT_UNUSED(success, success); |
| 222 |
| 223 RefPtr<JSONValue> methodValue = messageObject->get("method"); |
| 224 String method; |
| 225 success = methodValue && methodValue->asString(&method); |
| 226 ASSERT_UNUSED(success, success); |
| 227 |
| 228 HashMap<String, CallHandler>::iterator it = m_dispatchMap.find(method); |
| 229 if (it == m_dispatchMap.end()) { |
| 230 reportProtocolError(sessionId, callId, MethodNotFound, "'" + method + "'
wasn't found"); |
| 231 return; |
| 232 } |
| 233 |
| 234 RefPtr<JSONArray> protocolErrors = JSONArray::create(); |
| 235 ((*this).*it->value)(sessionId, callId, messageObject.get(), protocolErrors.
get()); |
| 236 } |
| 237 |
| 238 void DispatcherImpl::sendResponse(int sessionId, int callId, const ErrorString&
invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result) |
| 239 { |
| 240 if (invocationError.length()) { |
| 241 reportProtocolError(sessionId, callId, ServerError, invocationError, err
orData); |
| 242 return; |
| 243 } |
| 244 |
| 245 RefPtr<JSONObject> responseMessage = JSONObject::create(); |
| 246 responseMessage->setNumber("id", callId); |
| 247 responseMessage->setObject("result", result); |
| 248 if (m_frontendChannel) |
| 249 m_frontendChannel->sendProtocolResponse(sessionId, callId, responseMessa
ge.release()); |
| 250 } |
| 251 |
| 252 void Dispatcher::reportProtocolError(int sessionId, int callId, CommonErrorCode
code, const String& errorMessage) const |
| 253 { |
| 254 reportProtocolError(sessionId, callId, code, errorMessage, PassRefPtr<JSONVa
lue>()); |
| 255 } |
| 256 |
| 257 void DispatcherImpl::reportProtocolError(int sessionId, int callId, CommonErrorC
ode code, const String& errorMessage, PassRefPtr<JSONValue> data) const |
| 258 { |
| 259 ASSERT(code >=0); |
| 260 ASSERT((unsigned)code < m_commonErrors.size()); |
| 261 ASSERT(m_commonErrors[code]); |
| 262 RefPtr<JSONObject> error = JSONObject::create(); |
| 263 error->setNumber("code", m_commonErrors[code]); |
| 264 error->setString("message", errorMessage); |
| 265 ASSERT(error); |
| 266 if (data) |
| 267 error->setValue("data", data); |
| 268 RefPtr<JSONObject> message = JSONObject::create(); |
| 269 message->setObject("error", error); |
| 270 message->setNumber("id", callId); |
| 271 if (m_frontendChannel) |
| 272 m_frontendChannel->sendProtocolResponse(sessionId, callId, message.relea
se()); |
| 273 } |
| 274 |
| 275 template<typename R, typename V, typename V0> |
| 276 R DispatcherImpl::getPropertyValueImpl(JSONObject* object, const char* name, boo
l* valueFound, JSONArray* protocolErrors, V0 initial_value, bool (*as_method)(JS
ONValue*, V*), const char* type_name) |
| 277 { |
| 278 ASSERT(protocolErrors); |
| 279 |
| 280 if (valueFound) |
| 281 *valueFound = false; |
| 282 |
| 283 V value = initial_value; |
| 284 |
| 285 if (!object) { |
| 286 if (!valueFound) { |
| 287 // Required parameter in missing params container. |
| 288 protocolErrors->pushString(String::format("'params' object must cont
ain required parameter '%s' with type '%s'.", name, type_name)); |
| 289 } |
| 290 return value; |
| 291 } |
| 292 |
| 293 JSONObject::const_iterator end = object->end(); |
| 294 JSONObject::const_iterator valueIterator = object->find(name); |
| 295 |
| 296 if (valueIterator == end) { |
| 297 if (!valueFound) |
| 298 protocolErrors->pushString(String::format("Parameter '%s' with type
'%s' was not found.", name, type_name)); |
| 299 return value; |
| 300 } |
| 301 |
| 302 if (!as_method(valueIterator->value.get(), &value)) |
| 303 protocolErrors->pushString(String::format("Parameter '%s' has wrong type
. It must be '%s'.", name, type_name)); |
| 304 else |
| 305 if (valueFound) |
| 306 *valueFound = true; |
| 307 return value; |
| 308 } |
| 309 |
| 310 struct AsMethodBridges { |
| 311 static bool asInteger(JSONValue* value, int* output) { return value->asNumbe
r(output); } |
| 312 static bool asNumber(JSONValue* value, double* output) { return value->asNum
ber(output); } |
| 313 static bool asString(JSONValue* value, String* output) { return value->asStr
ing(output); } |
| 314 static bool asBoolean(JSONValue* value, bool* output) { return value->asBool
ean(output); } |
| 315 static bool asObject(JSONValue* value, RefPtr<JSONObject>* output) { return
value->asObject(output); } |
| 316 static bool asArray(JSONValue* value, RefPtr<JSONArray>* output) { return va
lue->asArray(output); } |
| 317 }; |
| 318 |
| 319 OptionalValue<int> DispatcherImpl::getInteger(JSONObject* object, const char* na
me, bool isOptional, JSONArray* protocolErrors) |
| 320 { |
| 321 bool valueFound = false; |
| 322 int result = getPropertyValueImpl<int, int, int>(object, name, isOptional ?
&valueFound : 0, protocolErrors, 0, AsMethodBridges::asInteger, "Number"); |
| 323 return valueFound || !isOptional ? OptionalValue<int>(result) : OptionalValu
e<int>(); |
| 324 } |
| 325 |
| 326 OptionalValue<double> DispatcherImpl::getNumber(JSONObject* object, const char*
name, bool isOptional, JSONArray* protocolErrors) |
| 327 { |
| 328 bool valueFound = false; |
| 329 double result = getPropertyValueImpl<double, double, double>(object, name, i
sOptional ? &valueFound : 0, protocolErrors, 0, AsMethodBridges::asNumber, "Numb
er"); |
| 330 return valueFound || !isOptional ? OptionalValue<double>(result) : OptionalV
alue<double>(); |
| 331 } |
| 332 |
| 333 OptionalValue<String> DispatcherImpl::getString(JSONObject* object, const char*
name, bool isOptional, JSONArray* protocolErrors) |
| 334 { |
| 335 bool valueFound = false; |
| 336 String result = getPropertyValueImpl<String, String, String>(object, name, i
sOptional ? &valueFound : 0, protocolErrors, "", AsMethodBridges::asString, "Str
ing"); |
| 337 return valueFound || !isOptional ? OptionalValue<String>(result) : OptionalV
alue<String>(); |
| 338 } |
| 339 |
| 340 OptionalValue<bool> DispatcherImpl::getBoolean(JSONObject* object, const char* n
ame, bool isOptional, JSONArray* protocolErrors) |
| 341 { |
| 342 bool valueFound = false; |
| 343 bool result = getPropertyValueImpl<bool, bool, bool>(object, name, isOptiona
l ? &valueFound : 0, protocolErrors, false, AsMethodBridges::asBoolean, "Boolean
"); |
| 344 return valueFound || !isOptional ? OptionalValue<bool>(result) : OptionalVal
ue<bool>(); |
| 345 } |
| 346 |
| 347 PassRefPtr<JSONObject> DispatcherImpl::getObject(JSONObject* object, const char*
name, bool isOptional, JSONArray* protocolErrors) |
| 348 { |
| 349 bool valueFound = false; |
| 350 return getPropertyValueImpl<PassRefPtr<JSONObject>, RefPtr<JSONObject>, JSON
Object*>(object, name, isOptional ? &valueFound : 0, protocolErrors, 0, AsMethod
Bridges::asObject, "Object"); |
| 351 } |
| 352 |
| 353 PassRefPtr<JSONArray> DispatcherImpl::getArray(JSONObject* object, const char* n
ame, bool isOptional, JSONArray* protocolErrors) |
| 354 { |
| 355 bool valueFound = false; |
| 356 return getPropertyValueImpl<PassRefPtr<JSONArray>, RefPtr<JSONArray>, JSONAr
ray*>(object, name, isOptional ? &valueFound : 0, protocolErrors, 0, AsMethodBri
dges::asArray, "Array"); |
| 357 } |
| 358 |
| 359 bool Dispatcher::getCommandName(const String& message, String* result) |
| 360 { |
| 361 RefPtr<JSONValue> value = parseJSON(message); |
| 362 if (!value) |
| 363 return false; |
| 364 |
| 365 RefPtr<JSONObject> object = value->asObject(); |
| 366 if (!object) |
| 367 return false; |
| 368 |
| 369 if (!object->getString("method", result)) |
| 370 return false; |
| 371 |
| 372 return true; |
| 373 } |
| 374 |
| 375 Dispatcher::CallbackBase::CallbackBase(PassRefPtr<DispatcherImpl> backendImpl, i
nt sessionId, int id) |
| 376 : m_backendImpl(backendImpl), m_sessionId(sessionId), m_id(id), m_alreadySen
t(false) { } |
| 377 |
| 378 Dispatcher::CallbackBase::~CallbackBase() { } |
| 379 |
| 380 void Dispatcher::CallbackBase::sendFailure(const ErrorString& error) |
| 381 { |
| 382 ASSERT(error.length()); |
| 383 sendIfActive(nullptr, error, PassRefPtr<JSONValue>()); |
| 384 } |
| 385 |
| 386 bool Dispatcher::CallbackBase::isActive() |
| 387 { |
| 388 return !m_alreadySent && m_backendImpl->isActive(); |
| 389 } |
| 390 |
| 391 void Dispatcher::CallbackBase::sendIfActive(PassRefPtr<JSONObject> partialMessag
e, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData) |
| 392 { |
| 393 if (m_alreadySent) |
| 394 return; |
| 395 m_backendImpl->sendResponse(m_sessionId, m_id, invocationError, errorData, p
artialMessage); |
| 396 m_alreadySent = true; |
| 397 } |
| 398 |
| 399 } // namespace protocol |
| 400 } // namespace blink |
| OLD | NEW |