1// This file is generated by DispatcherBase_cpp.template. 2 3// Copyright 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 "DispatcherBase.h" 8//#include "Parser.h" 9 10{% for namespace in config.protocol.namespace %} 11namespace {{namespace}} { 12{% endfor %} 13 14// static 15DispatchResponse DispatchResponse::OK() 16{ 17 DispatchResponse result; 18 result.m_status = kSuccess; 19 result.m_errorCode = kParseError; 20 return result; 21} 22 23// static 24DispatchResponse DispatchResponse::Error(const String& error) 25{ 26 DispatchResponse result; 27 result.m_status = kError; 28 result.m_errorCode = kServerError; 29 result.m_errorMessage = error; 30 return result; 31} 32 33// static 34DispatchResponse DispatchResponse::InternalError() 35{ 36 DispatchResponse result; 37 result.m_status = kError; 38 result.m_errorCode = kInternalError; 39 result.m_errorMessage = "Internal error"; 40 return result; 41} 42 43// static 44DispatchResponse DispatchResponse::InvalidParams(const String& error) 45{ 46 DispatchResponse result; 47 result.m_status = kError; 48 result.m_errorCode = kInvalidParams; 49 result.m_errorMessage = error; 50 return result; 51} 52 53// static 54DispatchResponse DispatchResponse::FallThrough() 55{ 56 DispatchResponse result; 57 result.m_status = kFallThrough; 58 result.m_errorCode = kParseError; 59 return result; 60} 61 62// static 63const char DispatcherBase::kInvalidParamsString[] = "Invalid parameters"; 64 65DispatcherBase::WeakPtr::WeakPtr(DispatcherBase* dispatcher) : m_dispatcher(dispatcher) { } 66 67DispatcherBase::WeakPtr::~WeakPtr() 68{ 69 if (m_dispatcher) 70 m_dispatcher->m_weakPtrs.erase(this); 71} 72 73DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, const String& method, const ProtocolMessage& message) 74 : m_backendImpl(std::move(backendImpl)) 75 , m_callId(callId) 76 , m_method(method) 77 , m_message(message) { } 78 79DispatcherBase::Callback::~Callback() = default; 80 81void DispatcherBase::Callback::dispose() 82{ 83 m_backendImpl = nullptr; 84} 85 86void DispatcherBase::Callback::sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const DispatchResponse& response) 87{ 88 if (!m_backendImpl || !m_backendImpl->get()) 89 return; 90 m_backendImpl->get()->sendResponse(m_callId, response, std::move(partialMessage)); 91 m_backendImpl = nullptr; 92} 93 94void DispatcherBase::Callback::fallThroughIfActive() 95{ 96 if (!m_backendImpl || !m_backendImpl->get()) 97 return; 98 m_backendImpl->get()->channel()->fallThrough(m_callId, m_method, m_message); 99 m_backendImpl = nullptr; 100} 101 102DispatcherBase::DispatcherBase(FrontendChannel* frontendChannel) 103 : m_frontendChannel(frontendChannel) { } 104 105DispatcherBase::~DispatcherBase() 106{ 107 clearFrontend(); 108} 109 110void DispatcherBase::sendResponse(int callId, const DispatchResponse& response, std::unique_ptr<protocol::DictionaryValue> result) 111{ 112 if (!m_frontendChannel) 113 return; 114 if (response.status() == DispatchResponse::kError) { 115 reportProtocolError(callId, response.errorCode(), response.errorMessage(), nullptr); 116 return; 117 } 118 m_frontendChannel->sendProtocolResponse(callId, InternalResponse::createResponse(callId, std::move(result))); 119} 120 121void DispatcherBase::sendResponse(int callId, const DispatchResponse& response) 122{ 123 sendResponse(callId, response, DictionaryValue::create()); 124} 125 126namespace { 127 128class ProtocolError : public Serializable { 129public: 130 static std::unique_ptr<ProtocolError> createErrorResponse(int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors) 131 { 132 std::unique_ptr<ProtocolError> protocolError(new ProtocolError(code, errorMessage)); 133 protocolError->m_callId = callId; 134 protocolError->m_hasCallId = true; 135 if (errors && errors->hasErrors()) 136 protocolError->m_data = errors->errors(); 137 return protocolError; 138 } 139 140 static std::unique_ptr<ProtocolError> createErrorNotification(DispatchResponse::ErrorCode code, const String& errorMessage) 141 { 142 return std::unique_ptr<ProtocolError>(new ProtocolError(code, errorMessage)); 143 } 144 145 String serializeToJSON() override 146 { 147 return serialize()->serializeToJSON(); 148 } 149 150 std::vector<uint8_t> serializeToBinary() override 151 { 152 return serialize()->serializeToBinary(); 153 } 154 155 ~ProtocolError() override {} 156 157private: 158 ProtocolError(DispatchResponse::ErrorCode code, const String& errorMessage) 159 : m_code(code) 160 , m_errorMessage(errorMessage) 161 { 162 } 163 164 std::unique_ptr<DictionaryValue> serialize() { 165 std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create(); 166 error->setInteger("code", m_code); 167 error->setString("message", m_errorMessage); 168 if (m_data.length()) 169 error->setString("data", m_data); 170 std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create(); 171 message->setObject("error", std::move(error)); 172 if (m_hasCallId) 173 message->setInteger("id", m_callId); 174 return message; 175 } 176 177 DispatchResponse::ErrorCode m_code; 178 String m_errorMessage; 179 String m_data; 180 int m_callId = 0; 181 bool m_hasCallId = false; 182}; 183 184} // namespace 185 186static void reportProtocolErrorTo(FrontendChannel* frontendChannel, int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors) 187{ 188 if (frontendChannel) 189 frontendChannel->sendProtocolResponse(callId, ProtocolError::createErrorResponse(callId, code, errorMessage, errors)); 190} 191 192static void reportProtocolErrorTo(FrontendChannel* frontendChannel, DispatchResponse::ErrorCode code, const String& errorMessage) 193{ 194 if (frontendChannel) 195 frontendChannel->sendProtocolNotification(ProtocolError::createErrorNotification(code, errorMessage)); 196} 197 198void DispatcherBase::reportProtocolError(int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors) 199{ 200 reportProtocolErrorTo(m_frontendChannel, callId, code, errorMessage, errors); 201} 202 203void DispatcherBase::clearFrontend() 204{ 205 m_frontendChannel = nullptr; 206 for (auto& weak : m_weakPtrs) 207 weak->dispose(); 208 m_weakPtrs.clear(); 209} 210 211std::unique_ptr<DispatcherBase::WeakPtr> DispatcherBase::weakPtr() 212{ 213 std::unique_ptr<DispatcherBase::WeakPtr> weak(new DispatcherBase::WeakPtr(this)); 214 m_weakPtrs.insert(weak.get()); 215 return weak; 216} 217 218UberDispatcher::UberDispatcher(FrontendChannel* frontendChannel) 219 : m_frontendChannel(frontendChannel) { } 220 221void UberDispatcher::registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase> dispatcher) 222{ 223 m_dispatchers[name] = std::move(dispatcher); 224} 225 226void UberDispatcher::setupRedirects(const std::unordered_map<String, String>& redirects) 227{ 228 for (const auto& pair : redirects) 229 m_redirects[pair.first] = pair.second; 230} 231 232bool UberDispatcher::parseCommand(Value* parsedMessage, int* outCallId, String* outMethod) { 233 if (!parsedMessage) { 234 reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kParseError, "Message must be a valid JSON"); 235 return false; 236 } 237 protocol::DictionaryValue* messageObject = DictionaryValue::cast(parsedMessage); 238 if (!messageObject) { 239 reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must be an object"); 240 return false; 241 } 242 243 int callId = 0; 244 protocol::Value* callIdValue = messageObject->get("id"); 245 bool success = callIdValue && callIdValue->asInteger(&callId); 246 if (!success) { 247 reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must have integer 'id' property"); 248 return false; 249 } 250 if (outCallId) 251 *outCallId = callId; 252 253 protocol::Value* methodValue = messageObject->get("method"); 254 String method; 255 success = methodValue && methodValue->asString(&method); 256 if (!success) { 257 reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kInvalidRequest, "Message must have string 'method' property", nullptr); 258 return false; 259 } 260 if (outMethod) 261 *outMethod = method; 262 return true; 263} 264 265protocol::DispatcherBase* UberDispatcher::findDispatcher(const String& method) { 266 size_t dotIndex = StringUtil::find(method, "."); 267 if (dotIndex == StringUtil::kNotFound) 268 return nullptr; 269 String domain = StringUtil::substring(method, 0, dotIndex); 270 auto it = m_dispatchers.find(domain); 271 if (it == m_dispatchers.end()) 272 return nullptr; 273 if (!it->second->canDispatch(method)) 274 return nullptr; 275 return it->second.get(); 276} 277 278bool UberDispatcher::canDispatch(const String& in_method) 279{ 280 String method = in_method; 281 auto redirectIt = m_redirects.find(method); 282 if (redirectIt != m_redirects.end()) 283 method = redirectIt->second; 284 return !!findDispatcher(method); 285} 286 287void UberDispatcher::dispatch(int callId, const String& in_method, std::unique_ptr<Value> parsedMessage, const ProtocolMessage& rawMessage) 288{ 289 String method = in_method; 290 auto redirectIt = m_redirects.find(method); 291 if (redirectIt != m_redirects.end()) 292 method = redirectIt->second; 293 protocol::DispatcherBase* dispatcher = findDispatcher(method); 294 if (!dispatcher) { 295 reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr); 296 return; 297 } 298 std::unique_ptr<protocol::DictionaryValue> messageObject = DictionaryValue::cast(std::move(parsedMessage)); 299 dispatcher->dispatch(callId, method, rawMessage, std::move(messageObject)); 300} 301 302UberDispatcher::~UberDispatcher() = default; 303 304// static 305std::unique_ptr<InternalResponse> InternalResponse::createResponse(int callId, std::unique_ptr<Serializable> params) 306{ 307 return std::unique_ptr<InternalResponse>(new InternalResponse(callId, String(), std::move(params))); 308} 309 310// static 311std::unique_ptr<InternalResponse> InternalResponse::createNotification(const String& notification, std::unique_ptr<Serializable> params) 312{ 313 return std::unique_ptr<InternalResponse>(new InternalResponse(0, notification, std::move(params))); 314} 315 316String InternalResponse::serializeToJSON() 317{ 318 std::unique_ptr<DictionaryValue> result = DictionaryValue::create(); 319 std::unique_ptr<Serializable> params(m_params ? std::move(m_params) : DictionaryValue::create()); 320 if (m_notification.length()) { 321 result->setString("method", m_notification); 322 result->setValue("params", SerializedValue::fromJSON(params->serializeToJSON())); 323 } else { 324 result->setInteger("id", m_callId); 325 result->setValue("result", SerializedValue::fromJSON(params->serializeToJSON())); 326 } 327 return result->serializeToJSON(); 328} 329 330std::vector<uint8_t> InternalResponse::serializeToBinary() 331{ 332 std::unique_ptr<DictionaryValue> result = DictionaryValue::create(); 333 std::unique_ptr<Serializable> params(m_params ? std::move(m_params) : DictionaryValue::create()); 334 if (m_notification.length()) { 335 result->setString("method", m_notification); 336 result->setValue("params", SerializedValue::fromBinary(params->serializeToBinary())); 337 } else { 338 result->setInteger("id", m_callId); 339 result->setValue("result", SerializedValue::fromBinary(params->serializeToBinary())); 340 } 341 return result->serializeToBinary(); 342} 343 344InternalResponse::InternalResponse(int callId, const String& notification, std::unique_ptr<Serializable> params) 345 : m_callId(callId) 346 , m_notification(notification) 347 , m_params(params ? std::move(params) : nullptr) 348{ 349} 350 351{% for namespace in config.protocol.namespace %} 352} // namespace {{namespace}} 353{% endfor %} 354