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/inspector_protocol/Collections.h" | |
10 #include "platform/inspector_protocol/FrontendChannel.h" | |
11 #include "platform/inspector_protocol/Parser.h" | |
12 | |
13 namespace blink { | |
14 namespace protocol { | |
15 | |
16 using protocol::Maybe; | |
17 | |
18 class DispatcherImpl; | |
19 | |
20 class DispatcherImplWeakPtr { | |
21 public: | |
22 DispatcherImplWeakPtr(DispatcherImpl* dispatcher) : m_dispatcher(dispatcher)
{ } | |
23 ~DispatcherImplWeakPtr(); | |
24 DispatcherImpl* get() { return m_dispatcher; } | |
25 void dispose() { m_dispatcher = nullptr; } | |
26 private: | |
27 DispatcherImpl* m_dispatcher; | |
28 }; | |
29 | |
30 class DispatcherImpl : public Dispatcher { | |
31 public: | |
32 DispatcherImpl(FrontendChannel* frontendChannel) | |
33 : m_frontendChannel(frontendChannel) | |
34 {% for domain in api.domains %} | |
35 , m_{{domain.domain | lower}}Agent(0) | |
36 {% endfor %} | |
37 { | |
38 {% for domain in api.domains %} | |
39 {% for command in domain.commands %} | |
40 {% if "redirect" in command %}{% continue %}{% endif %} | |
41 {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{%
continue %}{% endif %} | |
42 m_dispatchMap.set("{{domain.domain}}.{{command.name}}", &DispatcherImpl:
:{{domain.domain}}_{{command.name}}); | |
43 {% endfor %} | |
44 {% endfor %} | |
45 | |
46 // Initialize common errors. | |
47 m_commonErrors.resize(LastEntry); | |
48 m_commonErrors[ParseError] = -32700; | |
49 m_commonErrors[InvalidRequest] = -32600; | |
50 m_commonErrors[MethodNotFound] = -32601; | |
51 m_commonErrors[InvalidParams] = -32602; | |
52 m_commonErrors[InternalError] = -32603; | |
53 m_commonErrors[ServerError] = -32000; | |
54 } | |
55 | |
56 ~DispatcherImpl() { clearFrontend(); } | |
57 | |
58 virtual void clearFrontend() | |
59 { | |
60 m_frontendChannel = nullptr; | |
61 for (auto& weak : m_weakPtrs) | |
62 weak.first->dispose(); | |
63 m_weakPtrs.clear(); | |
64 } | |
65 | |
66 std::unique_ptr<DispatcherImplWeakPtr> weakPtr() | |
67 { | |
68 std::unique_ptr<DispatcherImplWeakPtr> weak(new DispatcherImplWeakPtr(th
is)); | |
69 m_weakPtrs.add(weak.get()); | |
70 return weak; | |
71 } | |
72 | |
73 virtual void dispatch(const String16& message); | |
74 virtual void reportProtocolError(int callId, CommonErrorCode, const String16
& errorMessage, ErrorSupport* errors) const; | |
75 using Dispatcher::reportProtocolError; | |
76 | |
77 void sendResponse(int callId, const ErrorString& invocationError, ErrorSuppo
rt* errors, std::unique_ptr<protocol::DictionaryValue> result); | |
78 | |
79 {% for domain in api.domains %} | |
80 virtual void registerAgent(blink::protocol::{{domain.domain}}::Backend* agen
t) { DCHECK(!m_{{domain.domain | lower}}Agent); m_{{domain.domain | lower}}Agent
= agent; } | |
81 {% endfor %} | |
82 | |
83 private: | |
84 friend class DispatcherCallbackBase; | |
85 friend class DispatcherImplWeakPtr; | |
86 using CallHandler = void (DispatcherImpl::*)(int callId, std::unique_ptr<Dic
tionaryValue> messageObject, ErrorSupport* errors); | |
87 using DispatchMap = protocol::HashMap<String16, CallHandler>; | |
88 | |
89 {% for domain in api.domains %} | |
90 {% for command in domain.commands %} | |
91 {% if "redirect" in command %}{% continue %}{% endif %} | |
92 {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{%
continue %}{% endif %} | |
93 void {{domain.domain}}_{{command.name}}(int callId, std::unique_ptr<Dictiona
ryValue> requestMessageObject, ErrorSupport*); | |
94 {% endfor %} | |
95 {% endfor %} | |
96 | |
97 FrontendChannel* m_frontendChannel; | |
98 | |
99 {% for domain in api.domains %} | |
100 {{domain.domain}}::Backend* m_{{domain.domain | lower}}Agent; | |
101 {% endfor %} | |
102 | |
103 void sendResponse(int callId, ErrorString invocationError, std::unique_ptr<p
rotocol::DictionaryValue> result) | |
104 { | |
105 sendResponse(callId, invocationError, nullptr, std::move(result)); | |
106 } | |
107 | |
108 void sendResponse(int callId, ErrorString invocationError) | |
109 { | |
110 sendResponse(callId, invocationError, nullptr, DictionaryValue::create()
); | |
111 } | |
112 | |
113 static const char kInvalidRequest[]; | |
114 | |
115 DispatchMap m_dispatchMap; | |
116 protocol::Vector<int> m_commonErrors; | |
117 protocol::HashSet<DispatcherImplWeakPtr*> m_weakPtrs; | |
118 }; | |
119 | |
120 class PLATFORM_EXPORT DispatcherCallbackBase : public protocol::BackendCallback
{ | |
121 public: | |
122 DispatcherCallbackBase(std::unique_ptr<DispatcherImplWeakPtr> backendImpl, i
nt callId) | |
123 : m_backendImpl(std::move(backendImpl)), m_callId(callId) { } | |
124 virtual ~DispatcherCallbackBase() { } | |
125 void dispose() { m_backendImpl = nullptr; } | |
126 | |
127 protected: | |
128 void sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage,
const ErrorString& invocationError) | |
129 { | |
130 if (!m_backendImpl->get()) | |
131 return; | |
132 m_backendImpl->get()->sendResponse(m_callId, invocationError, nullptr, s
td::move(partialMessage)); | |
133 m_backendImpl = nullptr; | |
134 } | |
135 | |
136 private: | |
137 std::unique_ptr<DispatcherImplWeakPtr> m_backendImpl; | |
138 int m_callId; | |
139 }; | |
140 | |
141 DispatcherImplWeakPtr::~DispatcherImplWeakPtr() | |
142 { | |
143 if (m_dispatcher) | |
144 m_dispatcher->m_weakPtrs.remove(this); | |
145 } | |
146 | |
147 const char DispatcherImpl::kInvalidRequest[] = "Invalid request"; | |
148 | |
149 {% for domain in api.domains %} | |
150 {% for command in domain.commands %} | |
151 {% if "redirect" in command %}{% continue %}{% endif %} | |
152 {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{%
continue %}{% endif %} | |
153 | |
154 {% if "async" in command %} | |
155 | |
156 class PLATFORM_EXPORT {{domain.domain}}{{command.name | to_title_case}}Callback
: public {{domain.domain}}::Backend::{{command.name | to_title_case}}Callback, p
ublic DispatcherCallbackBase { | |
157 public: | |
158 {{domain.domain}}{{command.name | to_title_case}}Callback(std::unique_ptr<Di
spatcherImplWeakPtr> backendImpl, int callId) | |
159 : DispatcherCallbackBase(std::move(backendImpl), callId) { } | |
160 | |
161 void sendSuccess( | |
162 {%- for parameter in command.returns -%} | |
163 {%- if "optional" in parameter -%} | |
164 const Maybe<{{resolve_type(parameter).raw_type}}>& {{parameter.name}} | |
165 {%- else -%} | |
166 {{resolve_type(parameter).pass_type}} {{parameter.name}} | |
167 {%- endif -%} | |
168 {%- if not loop.last -%}, {% endif -%} | |
169 {%- endfor -%}) override | |
170 { | |
171 std::unique_ptr<protocol::DictionaryValue> resultObject = DictionaryValu
e::create(); | |
172 {% for parameter in command.returns %} | |
173 {% if "optional" in parameter %} | |
174 if ({{parameter.name}}.isJust()) | |
175 resultObject->setValue("{{parameter.name}}", toValue({{parameter.nam
e}}.fromJust())); | |
176 {% else %} | |
177 resultObject->setValue("{{parameter.name}}", toValue({{resolve_type(para
meter).to_raw_type % parameter.name}})); | |
178 {% endif %} | |
179 {% endfor %} | |
180 sendIfActive(std::move(resultObject), ErrorString()); | |
181 } | |
182 | |
183 void sendFailure(const ErrorString& error) override | |
184 { | |
185 DCHECK(error.length()); | |
186 sendIfActive(nullptr, error); | |
187 } | |
188 }; | |
189 {% endif %} | |
190 | |
191 void DispatcherImpl::{{domain.domain}}_{{command.name}}(int callId, std::unique_
ptr<DictionaryValue> requestMessageObject, ErrorSupport* errors) | |
192 { | |
193 if (!m_{{domain.domain | lower}}Agent) | |
194 errors->addError("{{domain.domain}} handler is not available."); | |
195 | |
196 if (errors->hasErrors()) { | |
197 reportProtocolError(callId, InvalidParams, kInvalidRequest, errors); | |
198 return; | |
199 } | |
200 {% if "parameters" in command %} | |
201 | |
202 // Prepare input parameters. | |
203 protocol::DictionaryValue* object = DictionaryValue::cast(requestMessageObje
ct->get("params")); | |
204 errors->push(); | |
205 {% for property in command.parameters %} | |
206 protocol::Value* {{property.name}}Value = object ? object->get("{{property.n
ame}}") : nullptr; | |
207 {% if property.optional %} | |
208 Maybe<{{resolve_type(property).raw_type}}> in_{{property.name}}; | |
209 if ({{property.name}}Value) { | |
210 errors->setName("{{property.name}}"); | |
211 in_{{property.name}} = FromValue<{{resolve_type(property).raw_type}}>::p
arse({{property.name}}Value, errors); | |
212 } | |
213 {% else %} | |
214 errors->setName("{{property.name}}"); | |
215 {{resolve_type(property).type}} in_{{property.name}} = FromValue<{{resolve_t
ype(property).raw_type}}>::parse({{property.name}}Value, errors); | |
216 {% endif %} | |
217 {% endfor %} | |
218 errors->pop(); | |
219 if (errors->hasErrors()) { | |
220 reportProtocolError(callId, InvalidParams, kInvalidRequest, errors); | |
221 return; | |
222 } | |
223 {% endif %} | |
224 | |
225 {% if "async" in command %} | |
226 std::unique_ptr<{{domain.domain}}{{command.name | to_title_case}}Callback> c
allback(new {{domain.domain}}{{command.name | to_title_case}}Callback(weakPtr(),
callId)); | |
227 {% elif "returns" in command %} | |
228 // Declare output parameters. | |
229 std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create(
); | |
230 {% for property in command.returns %} | |
231 {% if "optional" in property %} | |
232 Maybe<{{resolve_type(property).raw_type}}> out_{{property.name}}; | |
233 {% else %} | |
234 {{resolve_type(property).type}} out_{{property.name}}; | |
235 {% endif %} | |
236 {% endfor %} | |
237 {% endif %} | |
238 | |
239 std::unique_ptr<DispatcherImplWeakPtr> weak = weakPtr(); | |
240 ErrorString error; | |
241 m_{{domain.domain | lower}}Agent->{{command.name}}(&error | |
242 {%- for property in command.parameters -%} | |
243 {%- if "optional" in property -%} | |
244 , in_{{property.name}} | |
245 {%- else -%} | |
246 , {{resolve_type(property).to_pass_type % ("in_" + property.name)}} | |
247 {%- endif -%} | |
248 {%- endfor %} | |
249 {%- if "async" in command -%} | |
250 , std::move(callback) | |
251 {%- elif "returns" in command %} | |
252 {%- for property in command.returns -%} | |
253 , &out_{{property.name}} | |
254 {%- endfor %} | |
255 {% endif %}); | |
256 {% if "returns" in command and not("async" in command) %} | |
257 if (!error.length()) { | |
258 {% for parameter in command.returns %} | |
259 {% if "optional" in parameter %} | |
260 if (out_{{parameter.name}}.isJust()) | |
261 result->setValue("{{parameter.name}}", toValue(out_{{parameter.name}
}.fromJust())); | |
262 {% else %} | |
263 result->setValue("{{parameter.name}}", toValue({{resolve_type(parameter)
.to_raw_type % ("out_" + parameter.name)}})); | |
264 {% endif %} | |
265 {% endfor %} | |
266 } | |
267 if (weak->get()) | |
268 weak->get()->sendResponse(callId, error, std::move(result)); | |
269 {% elif not("async" in command) %} | |
270 if (weak->get()) | |
271 weak->get()->sendResponse(callId, error); | |
272 {% endif %} | |
273 } | |
274 {% endfor %} | |
275 {% endfor %} | |
276 | |
277 std::unique_ptr<Dispatcher> Dispatcher::create(FrontendChannel* frontendChannel) | |
278 { | |
279 return wrapUnique(new DispatcherImpl(frontendChannel)); | |
280 } | |
281 | |
282 void DispatcherImpl::dispatch(const String16& message) | |
283 { | |
284 int callId = 0; | |
285 std::unique_ptr<protocol::Value> parsedMessage = parseJSON(message); | |
286 DCHECK(parsedMessage); | |
287 std::unique_ptr<protocol::DictionaryValue> messageObject = DictionaryValue::
cast(std::move(parsedMessage)); | |
288 DCHECK(messageObject); | |
289 | |
290 protocol::Value* callIdValue = messageObject->get("id"); | |
291 bool success = callIdValue->asNumber(&callId); | |
292 DCHECK(success); | |
293 | |
294 protocol::Value* methodValue = messageObject->get("method"); | |
295 String16 method; | |
296 success = methodValue && methodValue->asString(&method); | |
297 DCHECK(success); | |
298 | |
299 protocol::HashMap<String16, CallHandler>::iterator it = m_dispatchMap.find(m
ethod); | |
300 if (it == m_dispatchMap.end()) { | |
301 reportProtocolError(callId, MethodNotFound, "'" + method + "' wasn't fou
nd"); | |
302 return; | |
303 } | |
304 | |
305 protocol::ErrorSupport errors; | |
306 ((*this).*(*it->second))(callId, std::move(messageObject), &errors); | |
307 } | |
308 | |
309 void DispatcherImpl::sendResponse(int callId, const ErrorString& invocationError
, ErrorSupport* errors, std::unique_ptr<protocol::DictionaryValue> result) | |
310 { | |
311 if (invocationError.length() || (errors && errors->hasErrors())) { | |
312 reportProtocolError(callId, ServerError, invocationError, errors); | |
313 return; | |
314 } | |
315 | |
316 std::unique_ptr<protocol::DictionaryValue> responseMessage = DictionaryValue
::create(); | |
317 responseMessage->setNumber("id", callId); | |
318 responseMessage->setObject("result", std::move(result)); | |
319 if (m_frontendChannel) | |
320 m_frontendChannel->sendProtocolResponse(callId, responseMessage->toJSONS
tring()); | |
321 } | |
322 | |
323 void Dispatcher::reportProtocolError(int callId, CommonErrorCode code, const Str
ing16& errorMessage) const | |
324 { | |
325 ErrorSupport errors; | |
326 reportProtocolError(callId, code, errorMessage, &errors); | |
327 } | |
328 | |
329 void DispatcherImpl::reportProtocolError(int callId, CommonErrorCode code, const
String16& errorMessage, ErrorSupport* errors) const | |
330 { | |
331 DCHECK(code >=0); | |
332 DCHECK((unsigned)code < m_commonErrors.size()); | |
333 DCHECK(m_commonErrors[code]); | |
334 std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create()
; | |
335 error->setNumber("code", m_commonErrors[code]); | |
336 error->setString("message", errorMessage); | |
337 DCHECK(error); | |
338 if (errors && errors->hasErrors()) | |
339 error->setString("data", errors->errors()); | |
340 std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create
(); | |
341 message->setObject("error", std::move(error)); | |
342 message->setNumber("id", callId); | |
343 if (m_frontendChannel) | |
344 m_frontendChannel->sendProtocolResponse(callId, message->toJSONString())
; | |
345 } | |
346 | |
347 bool Dispatcher::getCommandName(const String16& message, String16* result) | |
348 { | |
349 std::unique_ptr<protocol::Value> value = parseJSON(message); | |
350 if (!value) | |
351 return false; | |
352 | |
353 protocol::DictionaryValue* object = DictionaryValue::cast(value.get()); | |
354 if (!object) | |
355 return false; | |
356 | |
357 if (!object->getString("method", result)) | |
358 return false; | |
359 | |
360 return true; | |
361 } | |
362 | |
363 } // namespace protocol | |
364 } // namespace blink | |
OLD | NEW |