OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 //#include "DispatcherBase.h" | |
6 //#include "Parser.h" | |
7 | |
8 {% for namespace in config.protocol.namespace %} | |
9 namespace {{namespace}} { | |
10 {% endfor %} | |
11 | |
12 // static | |
13 const char DispatcherBase::kInvalidRequest[] = "Invalid request"; | |
14 | |
15 DispatcherBase::WeakPtr::WeakPtr(DispatcherBase* dispatcher) : m_dispatcher(disp
atcher) { } | |
16 | |
17 DispatcherBase::WeakPtr::~WeakPtr() | |
18 { | |
19 if (m_dispatcher) | |
20 m_dispatcher->m_weakPtrs.erase(this); | |
21 } | |
22 | |
23 DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> back
endImpl, int callId) | |
24 : m_backendImpl(std::move(backendImpl)) | |
25 , m_callId(callId) { } | |
26 | |
27 DispatcherBase::Callback::~Callback() = default; | |
28 | |
29 void DispatcherBase::Callback::dispose() | |
30 { | |
31 m_backendImpl = nullptr; | |
32 } | |
33 | |
34 void DispatcherBase::Callback::sendIfActive(std::unique_ptr<protocol::Dictionary
Value> partialMessage, const ErrorString& invocationError) | |
35 { | |
36 if (!m_backendImpl || !m_backendImpl->get()) | |
37 return; | |
38 m_backendImpl->get()->sendResponse(m_callId, invocationError, nullptr, std::
move(partialMessage)); | |
39 m_backendImpl = nullptr; | |
40 } | |
41 | |
42 DispatcherBase::DispatcherBase(FrontendChannel* frontendChannel) | |
43 : m_frontendChannel(frontendChannel) { } | |
44 | |
45 DispatcherBase::~DispatcherBase() | |
46 { | |
47 clearFrontend(); | |
48 } | |
49 | |
50 // static | |
51 bool DispatcherBase::getCommandName(const String& message, String* result) | |
52 { | |
53 std::unique_ptr<protocol::Value> value = parseJSON(message); | |
54 if (!value) | |
55 return false; | |
56 | |
57 protocol::DictionaryValue* object = DictionaryValue::cast(value.get()); | |
58 if (!object) | |
59 return false; | |
60 | |
61 if (!object->getString("method", result)) | |
62 return false; | |
63 | |
64 return true; | |
65 } | |
66 | |
67 void DispatcherBase::sendResponse(int callId, const ErrorString& invocationError
, ErrorSupport* errors, std::unique_ptr<protocol::DictionaryValue> result) | |
68 { | |
69 if (invocationError.length() || (errors && errors->hasErrors())) { | |
70 reportProtocolError(callId, ServerError, invocationError, errors); | |
71 return; | |
72 } | |
73 | |
74 std::unique_ptr<protocol::DictionaryValue> responseMessage = DictionaryValue
::create(); | |
75 responseMessage->setInteger("id", callId); | |
76 responseMessage->setObject("result", std::move(result)); | |
77 if (m_frontendChannel) | |
78 m_frontendChannel->sendProtocolResponse(callId, responseMessage->toJSONS
tring()); | |
79 } | |
80 | |
81 void DispatcherBase::sendResponse(int callId, const ErrorString& invocationError
, std::unique_ptr<protocol::DictionaryValue> result) | |
82 { | |
83 sendResponse(callId, invocationError, nullptr, std::move(result)); | |
84 } | |
85 | |
86 void DispatcherBase::sendResponse(int callId, const ErrorString& invocationError
) | |
87 { | |
88 sendResponse(callId, invocationError, nullptr, DictionaryValue::create()); | |
89 } | |
90 | |
91 static void reportProtocolErrorTo(FrontendChannel* frontendChannel, int callId,
DispatcherBase::CommonErrorCode code, const String& errorMessage, ErrorSupport*
errors) | |
92 { | |
93 if (!frontendChannel) | |
94 return; | |
95 std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create()
; | |
96 error->setInteger("code", code); | |
97 error->setString("message", errorMessage); | |
98 DCHECK(error); | |
99 if (errors && errors->hasErrors()) | |
100 error->setString("data", errors->errors()); | |
101 std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create
(); | |
102 message->setObject("error", std::move(error)); | |
103 message->setInteger("id", callId); | |
104 frontendChannel->sendProtocolResponse(callId, message->toJSONString()); | |
105 } | |
106 | |
107 void DispatcherBase::reportProtocolError(int callId, CommonErrorCode code, const
String& errorMessage, ErrorSupport* errors) | |
108 { | |
109 reportProtocolErrorTo(m_frontendChannel, callId, code, errorMessage, errors)
; | |
110 } | |
111 | |
112 void DispatcherBase::clearFrontend() | |
113 { | |
114 m_frontendChannel = nullptr; | |
115 for (auto& weak : m_weakPtrs) | |
116 weak->dispose(); | |
117 m_weakPtrs.clear(); | |
118 } | |
119 | |
120 std::unique_ptr<DispatcherBase::WeakPtr> DispatcherBase::weakPtr() | |
121 { | |
122 std::unique_ptr<DispatcherBase::WeakPtr> weak(new DispatcherBase::WeakPtr(th
is)); | |
123 m_weakPtrs.insert(weak.get()); | |
124 return weak; | |
125 } | |
126 | |
127 UberDispatcher::UberDispatcher(FrontendChannel* frontendChannel) | |
128 : m_frontendChannel(frontendChannel) { } | |
129 | |
130 void UberDispatcher::registerBackend(const String& name, std::unique_ptr<protoco
l::DispatcherBase> dispatcher) | |
131 { | |
132 m_dispatchers[name] = std::move(dispatcher); | |
133 } | |
134 | |
135 void UberDispatcher::dispatch(std::unique_ptr<Value> parsedMessage) | |
136 { | |
137 if (!parsedMessage) | |
138 return; | |
139 std::unique_ptr<protocol::DictionaryValue> messageObject = DictionaryValue::
cast(std::move(parsedMessage)); | |
140 if (!messageObject) | |
141 return; | |
142 | |
143 int callId = 0; | |
144 protocol::Value* callIdValue = messageObject->get("id"); | |
145 bool success = callIdValue && callIdValue->asInteger(&callId); | |
146 if (!success) | |
147 return; | |
148 | |
149 protocol::Value* methodValue = messageObject->get("method"); | |
150 String method; | |
151 success = methodValue && methodValue->asString(&method); | |
152 if (!success) | |
153 return; | |
154 | |
155 size_t dotIndex = method.find("."); | |
156 if (dotIndex == StringUtil::kNotFound) { | |
157 reportProtocolErrorTo(m_frontendChannel, callId, DispatcherBase::MethodN
otFound, "'" + method + "' wasn't found", nullptr); | |
158 return; | |
159 } | |
160 String domain = StringUtil::substring(method, 0, dotIndex); | |
161 auto it = m_dispatchers.find(domain); | |
162 if (it == m_dispatchers.end()) { | |
163 reportProtocolErrorTo(m_frontendChannel, callId, DispatcherBase::MethodN
otFound, "'" + method + "' wasn't found", nullptr); | |
164 return; | |
165 } | |
166 it->second->dispatch(callId, method, std::move(messageObject)); | |
167 } | |
168 | |
169 UberDispatcher::~UberDispatcher() = default; | |
170 | |
171 {% for namespace in config.protocol.namespace %} | |
172 } // namespace {{namespace}} | |
173 {% endfor %} | |
OLD | NEW |