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_
);
122 } else if (result_
) {
123 response
.Set(kResultParam
, result_
->DeepCopy());
126 std::string json_response
;
127 base::JSONWriter::Write(&response
, &json_response
);
128 return json_response
;
131 DevToolsProtocol::Response::Response(int id
, base::DictionaryValue
* result
)
135 is_async_promise_(false) {
138 DevToolsProtocol::Response::Response(int id
,
140 const std::string
& error_message
)
142 error_code_(error_code
),
143 error_message_(error_message
),
144 is_async_promise_(false) {
147 DevToolsProtocol::Notification::Notification(const std::string
& method
,
148 base::DictionaryValue
* params
)
149 : Message(method
, params
) {
152 DevToolsProtocol::Notification::~Notification() {
155 std::string
DevToolsProtocol::Notification::Serialize() {
156 base::DictionaryValue notification
;
157 notification
.SetString(kMethodParam
, method_
);
159 notification
.Set(kParamsParam
, params_
->DeepCopy());
161 std::string json_notification
;
162 base::JSONWriter::Write(¬ification
, &json_notification
);
163 return json_notification
;
166 DevToolsProtocol::Handler::~Handler() {
169 scoped_refptr
<DevToolsProtocol::Response
>
170 DevToolsProtocol::Handler::HandleCommand(
171 scoped_refptr
<DevToolsProtocol::Command
> command
) {
172 CommandHandlers::iterator it
= command_handlers_
.find(command
->method());
173 if (it
== command_handlers_
.end())
175 return (it
->second
).Run(command
);
178 void DevToolsProtocol::Handler::SetNotifier(const Notifier
& notifier
) {
179 notifier_
= notifier
;
182 DevToolsProtocol::Handler::Handler() {
185 void DevToolsProtocol::Handler::RegisterCommandHandler(
186 const std::string
& command
,
187 const CommandHandler
& handler
) {
188 command_handlers_
[command
] = handler
;
191 void DevToolsProtocol::Handler::SendNotification(
192 const std::string
& method
,
193 base::DictionaryValue
* params
) {
194 scoped_refptr
<DevToolsProtocol::Notification
> notification
=
195 new DevToolsProtocol::Notification(method
, params
);
196 SendRawMessage(notification
->Serialize());
199 void DevToolsProtocol::Handler::SendAsyncResponse(
200 scoped_refptr
<DevToolsProtocol::Response
> response
) {
201 SendRawMessage(response
->Serialize());
204 void DevToolsProtocol::Handler::SendRawMessage(const std::string
& message
) {
205 if (!notifier_
.is_null())
206 notifier_
.Run(message
);
209 static bool ParseMethod(base::DictionaryValue
* command
,
210 std::string
* method
) {
211 if (!command
->GetString(kMethodParam
, method
))
213 size_t pos
= method
->find(".");
214 if (pos
== std::string::npos
|| pos
== 0)
220 scoped_refptr
<DevToolsProtocol::Command
> DevToolsProtocol::ParseCommand(
221 const std::string
& json
,
222 std::string
* error_response
) {
223 scoped_ptr
<base::DictionaryValue
> command_dict(
224 ParseMessage(json
, error_response
));
225 return ParseCommand(command_dict
.get(), error_response
);
229 scoped_refptr
<DevToolsProtocol::Command
> DevToolsProtocol::ParseCommand(
230 base::DictionaryValue
* command_dict
,
231 std::string
* error_response
) {
237 bool ok
= command_dict
->GetInteger(kIdParam
, &id
) && id
>= 0;
238 ok
= ok
&& ParseMethod(command_dict
, &method
);
240 scoped_refptr
<Response
> response
=
241 new Response(kNoId
, kErrorInvalidRequest
, "No such method");
242 *error_response
= response
->Serialize();
246 base::DictionaryValue
* params
= NULL
;
247 command_dict
->GetDictionary(kParamsParam
, ¶ms
);
248 return new Command(id
, method
, params
? params
->DeepCopy() : NULL
);
252 scoped_refptr
<DevToolsProtocol::Command
>
253 DevToolsProtocol::CreateCommand(
255 const std::string
& method
,
256 base::DictionaryValue
* params
) {
257 return new Command(id
, method
, params
);
261 scoped_refptr
<DevToolsProtocol::Response
>
262 DevToolsProtocol::ParseResponse(
263 base::DictionaryValue
* response_dict
) {
265 if (!response_dict
->GetInteger(kIdParam
, &id
))
268 const base::DictionaryValue
* error_dict
;
269 if (response_dict
->GetDictionary(kErrorParam
, &error_dict
)) {
270 int error_code
= kErrorInternalError
;
271 response_dict
->GetInteger(kErrorCodeParam
, &error_code
);
272 std::string error_message
;
273 response_dict
->GetString(kErrorMessageParam
, &error_message
);
274 return new Response(id
, error_code
, error_message
);
277 const base::DictionaryValue
* result
= NULL
;
278 response_dict
->GetDictionary(kResultParam
, &result
);
279 return new Response(id
, result
? result
->DeepCopy() : NULL
);
283 scoped_refptr
<DevToolsProtocol::Notification
>
284 DevToolsProtocol::ParseNotification(const std::string
& json
) {
285 scoped_ptr
<base::DictionaryValue
> dict(ParseMessage(json
, NULL
));
290 bool ok
= ParseMethod(dict
.get(), &method
);
294 base::DictionaryValue
* params
= NULL
;
295 dict
->GetDictionary(kParamsParam
, ¶ms
);
296 return new Notification(method
, params
? params
->DeepCopy() : NULL
);
300 scoped_refptr
<DevToolsProtocol::Notification
>
301 DevToolsProtocol::CreateNotification(
302 const std::string
& method
,
303 base::DictionaryValue
* params
) {
304 return new Notification(method
, params
);
308 base::DictionaryValue
* DevToolsProtocol::ParseMessage(
309 const std::string
& json
,
310 std::string
* error_response
) {
311 int parse_error_code
;
312 std::string error_message
;
313 scoped_ptr
<base::Value
> message(
314 base::JSONReader::ReadAndReturnError(
315 json
, 0, &parse_error_code
, &error_message
));
317 if (!message
|| !message
->IsType(base::Value::TYPE_DICTIONARY
)) {
318 scoped_refptr
<Response
> response
=
319 new Response(0, kErrorParseError
, error_message
);
321 *error_response
= response
->Serialize();
325 return static_cast<base::DictionaryValue
*>(message
.release());
328 } // namespace content