1 // Copyright 2014 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_handler.h"
8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h"
10 #include "content/browser/devtools/devtools_manager.h"
11 #include "content/public/browser/devtools_manager_delegate.h"
17 const char kIdParam
[] = "id";
18 const char kMethodParam
[] = "method";
19 const char kParamsParam
[] = "params";
21 // JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object
22 const int kStatusParseError
= -32700;
23 const int kStatusInvalidRequest
= -32600;
24 const int kStatusNoSuchMethod
= -32601;
26 scoped_ptr
<base::DictionaryValue
> TakeDictionary(base::DictionaryValue
* dict
,
27 const std::string
& key
) {
28 scoped_ptr
<base::Value
> value
;
29 dict
->Remove(key
, &value
);
30 base::DictionaryValue
* result
= nullptr;
32 value
.release()->GetAsDictionary(&result
);
33 return make_scoped_ptr(result
);
38 DevToolsProtocolHandler::DevToolsProtocolHandler(
39 DevToolsAgentHost
* agent_host
, const Notifier
& notifier
)
40 : agent_host_(agent_host
),
42 dispatcher_(notifier
) {
45 DevToolsProtocolHandler::~DevToolsProtocolHandler() {
48 void DevToolsProtocolHandler::HandleMessage(const std::string
& message
) {
49 scoped_ptr
<base::DictionaryValue
> command
= ParseCommand(message
);
52 if (PassCommandToDelegate(command
.get()))
54 HandleCommand(command
.Pass());
57 bool DevToolsProtocolHandler::HandleOptionalMessage(
58 const std::string
& message
, int* call_id
) {
59 scoped_ptr
<base::DictionaryValue
> command
= ParseCommand(message
);
62 if (PassCommandToDelegate(command
.get()))
64 return HandleOptionalCommand(command
.Pass(), call_id
);
67 bool DevToolsProtocolHandler::PassCommandToDelegate(
68 base::DictionaryValue
* command
) {
69 DevToolsManagerDelegate
* delegate
=
70 DevToolsManager::GetInstance()->delegate();
74 scoped_ptr
<base::DictionaryValue
> response(
75 delegate
->HandleCommand(agent_host_
, command
));
77 std::string json_response
;
78 base::JSONWriter::Write(*response
, &json_response
);
79 client_
.SendRawMessage(json_response
);
86 scoped_ptr
<base::DictionaryValue
>
87 DevToolsProtocolHandler::ParseCommand(const std::string
& message
) {
88 scoped_ptr
<base::Value
> value
= base::JSONReader::Read(message
);
89 if (!value
|| !value
->IsType(base::Value::TYPE_DICTIONARY
)) {
90 client_
.SendError(DevToolsProtocolClient::kNoId
,
91 Response(kStatusParseError
,
92 "Message must be in JSON format"));
96 scoped_ptr
<base::DictionaryValue
> command
=
97 make_scoped_ptr(static_cast<base::DictionaryValue
*>(value
.release()));
98 int id
= DevToolsProtocolClient::kNoId
;
99 bool ok
= command
->GetInteger(kIdParam
, &id
) && id
>= 0;
101 client_
.SendError(id
, Response(kStatusInvalidRequest
,
102 "The type of 'id' property must be number"));
107 ok
= command
->GetString(kMethodParam
, &method
);
109 client_
.SendError(id
,
110 Response(kStatusInvalidRequest
,
111 "The type of 'method' property must be string"));
118 void DevToolsProtocolHandler::HandleCommand(
119 scoped_ptr
<base::DictionaryValue
> command
) {
120 int id
= DevToolsProtocolClient::kNoId
;
122 command
->GetInteger(kIdParam
, &id
);
123 command
->GetString(kMethodParam
, &method
);
124 DevToolsProtocolDispatcher::CommandHandler
command_handler(
125 dispatcher_
.FindCommandHandler(method
));
126 if (command_handler
.is_null()) {
127 client_
.SendError(id
, Response(kStatusNoSuchMethod
, "No such method"));
132 command_handler
.Run(id
, TakeDictionary(command
.get(), kParamsParam
));
136 bool DevToolsProtocolHandler::HandleOptionalCommand(
137 scoped_ptr
<base::DictionaryValue
> command
, int* call_id
) {
138 *call_id
= DevToolsProtocolClient::kNoId
;
140 command
->GetInteger(kIdParam
, call_id
);
141 command
->GetString(kMethodParam
, &method
);
142 DevToolsProtocolDispatcher::CommandHandler
command_handler(
143 dispatcher_
.FindCommandHandler(method
));
144 if (!command_handler
.is_null()) {
145 return command_handler
.Run(
146 *call_id
, TakeDictionary(command
.get(), kParamsParam
));
151 } // namespace content