1 // Copyright (c) 2013 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.
5 #include "content/browser/devtools/devtools_protocol.h"
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/strings/stringprintf.h"
15 const char kIdParam
[] = "id";
16 const char kMethodParam
[] = "method";
17 const char kParamsParam
[] = "params";
18 const char kResultParam
[] = "result";
19 const char kErrorParam
[] = "error";
20 const char kErrorCodeParam
[] = "code";
21 const char kErrorMessageParam
[] = "message";
24 // JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object
26 kErrorParseError
= -32700,
27 kErrorInvalidRequest
= -32600,
28 kErrorNoSuchMethod
= -32601,
29 kErrorInvalidParams
= -32602,
30 kErrorInternalError
= -32603,
31 kErrorServerError
= -32000
38 DevToolsProtocol::Message::~Message() {
41 DevToolsProtocol::Message::Message(const std::string
& method
,
42 base::DictionaryValue
* params
)
45 size_t pos
= method
.find(".");
46 if (pos
!= std::string::npos
&& pos
> 0)
47 domain_
= method
.substr(0, pos
);
50 DevToolsProtocol::Command::~Command() {
53 std::string
DevToolsProtocol::Command::Serialize() {
54 base::DictionaryValue command
;
55 command
.SetInteger(kIdParam
, id_
);
56 command
.SetString(kMethodParam
, method_
);
58 command
.Set(kParamsParam
, params_
->DeepCopy());
60 std::string json_command
;
61 base::JSONWriter::Write(&command
, &json_command
);
65 scoped_refptr
<DevToolsProtocol::Response
>
66 DevToolsProtocol::Command::SuccessResponse(base::DictionaryValue
* result
) {
67 return new DevToolsProtocol::Response(id_
, result
);
70 scoped_refptr
<DevToolsProtocol::Response
>
71 DevToolsProtocol::Command::InternalErrorResponse(const std::string
& message
) {
72 return new DevToolsProtocol::Response(id_
, kErrorInternalError
, message
);
75 scoped_refptr
<DevToolsProtocol::Response
>
76 DevToolsProtocol::Command::InvalidParamResponse(const std::string
& param
) {
78 base::StringPrintf("Missing or invalid '%s' parameter", param
.c_str());
79 return new DevToolsProtocol::Response(id_
, kErrorInvalidParams
, message
);
82 scoped_refptr
<DevToolsProtocol::Response
>
83 DevToolsProtocol::Command::NoSuchMethodErrorResponse() {
84 return new Response(id_
, kErrorNoSuchMethod
, "No such method");
87 scoped_refptr
<DevToolsProtocol::Response
>
88 DevToolsProtocol::Command::ServerErrorResponse(const std::string
& message
) {
89 return new Response(id_
, kErrorServerError
, message
);
92 scoped_refptr
<DevToolsProtocol::Response
>
93 DevToolsProtocol::Command::AsyncResponsePromise() {
94 scoped_refptr
<DevToolsProtocol::Response
> promise
=
95 new DevToolsProtocol::Response(0, NULL
);
96 promise
->is_async_promise_
= true;
100 DevToolsProtocol::Command::Command(int id
,
101 const std::string
& method
,
102 base::DictionaryValue
* params
)
103 : Message(method
, params
),
107 DevToolsProtocol::Response::~Response() {
110 std::string
DevToolsProtocol::Response::Serialize() {
111 base::DictionaryValue response
;
114 response
.SetInteger(kIdParam
, id_
);
117 base::DictionaryValue
* error_object
= new base::DictionaryValue();
118 response
.Set(kErrorParam
, error_object
);
119 error_object
->SetInteger(kErrorCodeParam
, error_code_
);
120 if (!error_message_
.empty())
121 error_object
->SetString(kErrorMessageParam
, error_message_
);
124 response
.Set(kResultParam
, result_
->DeepCopy());
126 response
.Set(kResultParam
, new base::DictionaryValue());
129 std::string json_response
;
130 base::JSONWriter::Write(&response
, &json_response
);
131 return json_response
;
134 DevToolsProtocol::Response::Response(int id
, base::DictionaryValue
* result
)
138 is_async_promise_(false) {
141 DevToolsProtocol::Response::Response(int id
,
143 const std::string
& error_message
)
145 error_code_(error_code
),
146 error_message_(error_message
),
147 is_async_promise_(false) {
150 DevToolsProtocol::Notification::Notification(const std::string
& method
,
151 base::DictionaryValue
* params
)
152 : Message(method
, params
) {
155 DevToolsProtocol::Notification::~Notification() {
158 std::string
DevToolsProtocol::Notification::Serialize() {
159 base::DictionaryValue notification
;
160 notification
.SetString(kMethodParam
, method_
);
162 notification
.Set(kParamsParam
, params_
->DeepCopy());
164 std::string json_notification
;
165 base::JSONWriter::Write(¬ification
, &json_notification
);
166 return json_notification
;
169 DevToolsProtocol::Handler::~Handler() {
172 scoped_refptr
<DevToolsProtocol::Response
>
173 DevToolsProtocol::Handler::HandleCommand(
174 scoped_refptr
<DevToolsProtocol::Command
> command
) {
175 CommandHandlers::iterator it
= command_handlers_
.find(command
->method());
176 if (it
== command_handlers_
.end())
178 return (it
->second
).Run(command
);
181 void DevToolsProtocol::Handler::HandleNotification(
182 scoped_refptr
<DevToolsProtocol::Notification
> notification
) {
183 NotificationHandlers::iterator it
=
184 notification_handlers_
.find(notification
->method());
185 if (it
== notification_handlers_
.end())
187 (it
->second
).Run(notification
);
190 void DevToolsProtocol::Handler::SetNotifier(const Notifier
& notifier
) {
191 notifier_
= notifier
;
194 DevToolsProtocol::Handler::Handler() {
197 void DevToolsProtocol::Handler::RegisterCommandHandler(
198 const std::string
& command
,
199 const CommandHandler
& handler
) {
200 command_handlers_
[command
] = handler
;
203 void DevToolsProtocol::Handler::RegisterNotificationHandler(
204 const std::string
& notification
,
205 const NotificationHandler
& handler
) {
206 notification_handlers_
[notification
] = handler
;
209 void DevToolsProtocol::Handler::SendNotification(
210 const std::string
& method
,
211 base::DictionaryValue
* params
) {
212 scoped_refptr
<DevToolsProtocol::Notification
> notification
=
213 new DevToolsProtocol::Notification(method
, params
);
214 SendRawMessage(notification
->Serialize());
217 void DevToolsProtocol::Handler::SendAsyncResponse(
218 scoped_refptr
<DevToolsProtocol::Response
> response
) {
219 SendRawMessage(response
->Serialize());
222 void DevToolsProtocol::Handler::SendRawMessage(const std::string
& message
) {
223 if (!notifier_
.is_null())
224 notifier_
.Run(message
);
227 static bool ParseMethod(base::DictionaryValue
* command
,
228 std::string
* method
) {
229 if (!command
->GetString(kMethodParam
, method
))
231 size_t pos
= method
->find(".");
232 if (pos
== std::string::npos
|| pos
== 0)
238 scoped_refptr
<DevToolsProtocol::Command
> DevToolsProtocol::ParseCommand(
239 const std::string
& json
,
240 std::string
* error_response
) {
241 scoped_ptr
<base::DictionaryValue
> command_dict(
242 ParseMessage(json
, error_response
));
243 return ParseCommand(command_dict
.get(), error_response
);
247 scoped_refptr
<DevToolsProtocol::Command
> DevToolsProtocol::ParseCommand(
248 base::DictionaryValue
* command_dict
,
249 std::string
* error_response
) {
255 bool ok
= command_dict
->GetInteger(kIdParam
, &id
) && id
>= 0;
256 ok
= ok
&& ParseMethod(command_dict
, &method
);
258 scoped_refptr
<Response
> response
=
259 new Response(kNoId
, kErrorInvalidRequest
, "No such method");
260 *error_response
= response
->Serialize();
264 base::DictionaryValue
* params
= NULL
;
265 command_dict
->GetDictionary(kParamsParam
, ¶ms
);
266 return new Command(id
, method
, params
? params
->DeepCopy() : NULL
);
270 scoped_refptr
<DevToolsProtocol::Command
>
271 DevToolsProtocol::CreateCommand(
273 const std::string
& method
,
274 base::DictionaryValue
* params
) {
275 return new Command(id
, method
, params
);
279 scoped_refptr
<DevToolsProtocol::Response
>
280 DevToolsProtocol::ParseResponse(
281 base::DictionaryValue
* response_dict
) {
283 if (!response_dict
->GetInteger(kIdParam
, &id
))
286 const base::DictionaryValue
* error_dict
;
287 if (response_dict
->GetDictionary(kErrorParam
, &error_dict
)) {
288 int error_code
= kErrorInternalError
;
289 response_dict
->GetInteger(kErrorCodeParam
, &error_code
);
290 std::string error_message
;
291 response_dict
->GetString(kErrorMessageParam
, &error_message
);
292 return new Response(id
, error_code
, error_message
);
295 const base::DictionaryValue
* result
= NULL
;
296 response_dict
->GetDictionary(kResultParam
, &result
);
297 return new Response(id
, result
? result
->DeepCopy() : NULL
);
301 scoped_refptr
<DevToolsProtocol::Notification
>
302 DevToolsProtocol::ParseNotification(const std::string
& json
) {
303 scoped_ptr
<base::DictionaryValue
> dict(ParseMessage(json
, NULL
));
308 bool ok
= ParseMethod(dict
.get(), &method
);
312 base::DictionaryValue
* params
= NULL
;
313 dict
->GetDictionary(kParamsParam
, ¶ms
);
314 return new Notification(method
, params
? params
->DeepCopy() : NULL
);
318 scoped_refptr
<DevToolsProtocol::Notification
>
319 DevToolsProtocol::CreateNotification(
320 const std::string
& method
,
321 base::DictionaryValue
* params
) {
322 return new Notification(method
, params
);
326 base::DictionaryValue
* DevToolsProtocol::ParseMessage(
327 const std::string
& json
,
328 std::string
* error_response
) {
329 int parse_error_code
;
330 std::string error_message
;
331 scoped_ptr
<base::Value
> message(
332 base::JSONReader::ReadAndReturnError(
333 json
, 0, &parse_error_code
, &error_message
));
335 if (!message
|| !message
->IsType(base::Value::TYPE_DICTIONARY
)) {
336 scoped_refptr
<Response
> response
=
337 new Response(0, kErrorParseError
, error_message
);
339 *error_response
= response
->Serialize();
343 return static_cast<base::DictionaryValue
*>(message
.release());
346 } // namespace content