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::SetNotifier(const Notifier
& notifier
) {
182 notifier_
= notifier
;
185 DevToolsProtocol::Handler::Handler() {
188 void DevToolsProtocol::Handler::RegisterCommandHandler(
189 const std::string
& command
,
190 const CommandHandler
& handler
) {
191 command_handlers_
[command
] = handler
;
194 void DevToolsProtocol::Handler::SendNotification(
195 const std::string
& method
,
196 base::DictionaryValue
* params
) {
197 scoped_refptr
<DevToolsProtocol::Notification
> notification
=
198 new DevToolsProtocol::Notification(method
, params
);
199 SendRawMessage(notification
->Serialize());
202 void DevToolsProtocol::Handler::SendAsyncResponse(
203 scoped_refptr
<DevToolsProtocol::Response
> response
) {
204 SendRawMessage(response
->Serialize());
207 void DevToolsProtocol::Handler::SendRawMessage(const std::string
& message
) {
208 if (!notifier_
.is_null())
209 notifier_
.Run(message
);
212 static bool ParseMethod(base::DictionaryValue
* command
,
213 std::string
* method
) {
214 if (!command
->GetString(kMethodParam
, method
))
216 size_t pos
= method
->find(".");
217 if (pos
== std::string::npos
|| pos
== 0)
223 scoped_refptr
<DevToolsProtocol::Command
> DevToolsProtocol::ParseCommand(
224 const std::string
& json
,
225 std::string
* error_response
) {
226 scoped_ptr
<base::DictionaryValue
> command_dict(
227 ParseMessage(json
, error_response
));
228 return ParseCommand(command_dict
.get(), error_response
);
232 scoped_refptr
<DevToolsProtocol::Command
> DevToolsProtocol::ParseCommand(
233 base::DictionaryValue
* command_dict
,
234 std::string
* error_response
) {
240 bool ok
= command_dict
->GetInteger(kIdParam
, &id
) && id
>= 0;
241 ok
= ok
&& ParseMethod(command_dict
, &method
);
243 scoped_refptr
<Response
> response
=
244 new Response(kNoId
, kErrorInvalidRequest
, "No such method");
245 *error_response
= response
->Serialize();
249 base::DictionaryValue
* params
= NULL
;
250 command_dict
->GetDictionary(kParamsParam
, ¶ms
);
251 return new Command(id
, method
, params
? params
->DeepCopy() : NULL
);
255 scoped_refptr
<DevToolsProtocol::Command
>
256 DevToolsProtocol::CreateCommand(
258 const std::string
& method
,
259 base::DictionaryValue
* params
) {
260 return new Command(id
, method
, params
);
264 scoped_refptr
<DevToolsProtocol::Response
>
265 DevToolsProtocol::ParseResponse(
266 base::DictionaryValue
* response_dict
) {
268 if (!response_dict
->GetInteger(kIdParam
, &id
))
271 const base::DictionaryValue
* error_dict
;
272 if (response_dict
->GetDictionary(kErrorParam
, &error_dict
)) {
273 int error_code
= kErrorInternalError
;
274 response_dict
->GetInteger(kErrorCodeParam
, &error_code
);
275 std::string error_message
;
276 response_dict
->GetString(kErrorMessageParam
, &error_message
);
277 return new Response(id
, error_code
, error_message
);
280 const base::DictionaryValue
* result
= NULL
;
281 response_dict
->GetDictionary(kResultParam
, &result
);
282 return new Response(id
, result
? result
->DeepCopy() : NULL
);
286 scoped_refptr
<DevToolsProtocol::Notification
>
287 DevToolsProtocol::ParseNotification(const std::string
& json
) {
288 scoped_ptr
<base::DictionaryValue
> dict(ParseMessage(json
, NULL
));
293 bool ok
= ParseMethod(dict
.get(), &method
);
297 base::DictionaryValue
* params
= NULL
;
298 dict
->GetDictionary(kParamsParam
, ¶ms
);
299 return new Notification(method
, params
? params
->DeepCopy() : NULL
);
303 scoped_refptr
<DevToolsProtocol::Notification
>
304 DevToolsProtocol::CreateNotification(
305 const std::string
& method
,
306 base::DictionaryValue
* params
) {
307 return new Notification(method
, params
);
311 base::DictionaryValue
* DevToolsProtocol::ParseMessage(
312 const std::string
& json
,
313 std::string
* error_response
) {
314 int parse_error_code
;
315 std::string error_message
;
316 scoped_ptr
<base::Value
> message(
317 base::JSONReader::ReadAndReturnError(
318 json
, 0, &parse_error_code
, &error_message
));
320 if (!message
|| !message
->IsType(base::Value::TYPE_DICTIONARY
)) {
321 scoped_refptr
<Response
> response
=
322 new Response(0, kErrorParseError
, error_message
);
324 *error_response
= response
->Serialize();
328 return static_cast<base::DictionaryValue
*>(message
.release());
331 } // namespace content