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.
4
5#include "chrome/browser/devtools/devtools_protocol.h"
6
7#include "base/json/json_reader.h"
8#include "base/json/json_writer.h"
9#include "base/strings/stringprintf.h"
10
11namespace {
12
13const char kErrorCodeParam[] = "code";
14const char kErrorParam[] = "error";
15const char kErrorMessageParam[] = "message";
16const char kIdParam[] = "id";
17const char kMethodParam[] = "method";
18const char kParamsParam[] = "params";
19const char kResultParam[] = "result";
20
21// JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object
22enum Error {
23  kErrorInvalidParams = -32602
24};
25
26}  // namespace
27
28DevToolsProtocol::Message::~Message() {
29}
30
31DevToolsProtocol::Message::Message(const std::string& method,
32                                   base::DictionaryValue* params)
33    : method_(method),
34      params_(params ? params->DeepCopy() : NULL) {
35}
36
37DevToolsProtocol::Command::Command(int id,
38                                   const std::string& method,
39                                   base::DictionaryValue* params)
40    : Message(method, params),
41      id_(id) {
42}
43
44DevToolsProtocol::Command::~Command() {
45}
46
47std::string DevToolsProtocol::Command::Serialize() {
48  base::DictionaryValue command;
49  command.SetInteger(kIdParam, id_);
50  command.SetString(kMethodParam, method_);
51  if (params_)
52    command.Set(kParamsParam, params_->DeepCopy());
53
54  std::string json_command;
55  base::JSONWriter::Write(&command, &json_command);
56  return json_command;
57}
58
59scoped_ptr<DevToolsProtocol::Response>
60DevToolsProtocol::Command::SuccessResponse(base::DictionaryValue* result) {
61  return scoped_ptr<DevToolsProtocol::Response>(
62      new DevToolsProtocol::Response(id_, result));
63}
64
65scoped_ptr<DevToolsProtocol::Response>
66DevToolsProtocol::Command::InvalidParamResponse(const std::string& param) {
67  std::string message =
68      base::StringPrintf("Missing or invalid '%s' parameter", param.c_str());
69  return scoped_ptr<DevToolsProtocol::Response>(
70      new DevToolsProtocol::Response(id_, kErrorInvalidParams, message));
71}
72
73DevToolsProtocol::Notification::~Notification() {
74}
75
76DevToolsProtocol::Notification::Notification(const std::string& method,
77                                             base::DictionaryValue* params)
78    : Message(method, params) {
79}
80
81DevToolsProtocol::Response::~Response() {
82}
83
84DevToolsProtocol::Response::Response(int id,
85                                     int error_code,
86                                     const std::string error_message)
87    : id_(id),
88      error_code_(error_code),
89      error_message_(error_message) {
90}
91
92DevToolsProtocol::Response::Response(int id, base::DictionaryValue* result)
93    : id_(id),
94      error_code_(0),
95      result_(result) {
96}
97
98base::DictionaryValue* DevToolsProtocol::Response::Serialize() {
99  base::DictionaryValue* response = new base::DictionaryValue();
100
101  response->SetInteger(kIdParam, id_);
102
103  if (error_code_) {
104    base::DictionaryValue* error_object = new base::DictionaryValue();
105    response->Set(kErrorParam, error_object);
106    error_object->SetInteger(kErrorCodeParam, error_code_);
107    if (!error_message_.empty())
108      error_object->SetString(kErrorMessageParam, error_message_);
109  } else {
110    if (result_)
111      response->Set(kResultParam, result_->DeepCopy());
112    else
113      response->Set(kResultParam, new base::DictionaryValue());
114  }
115
116  return response;
117}
118
119// static
120DevToolsProtocol::Command* DevToolsProtocol::ParseCommand(
121    base::DictionaryValue* command_dict) {
122  if (!command_dict)
123    return NULL;
124
125  int id;
126  if (!command_dict->GetInteger(kIdParam, &id) || id < 0)
127    return NULL;
128
129  std::string method;
130  if (!command_dict->GetString(kMethodParam, &method))
131    return NULL;
132
133  base::DictionaryValue* params = NULL;
134  command_dict->GetDictionary(kParamsParam, &params);
135  return new Command(id, method, params);
136}
137
138// static
139DevToolsProtocol::Notification* DevToolsProtocol::ParseNotification(
140    const std::string& json) {
141  scoped_ptr<base::Value> value(base::JSONReader::Read(json));
142  if (!value || !value->IsType(base::Value::TYPE_DICTIONARY))
143    return NULL;
144
145  scoped_ptr<base::DictionaryValue> dict(
146      static_cast<base::DictionaryValue*>(value.release()));
147
148  std::string method;
149  if (!dict->GetString(kMethodParam, &method))
150    return NULL;
151
152  base::DictionaryValue* params = NULL;
153  dict->GetDictionary(kParamsParam, &params);
154  return new Notification(method, params);
155}
156
157DevToolsProtocol::Response* DevToolsProtocol::ParseResponse(
158    const std::string& json) {
159  scoped_ptr<base::Value> value(base::JSONReader::Read(json));
160  if (!value || !value->IsType(base::Value::TYPE_DICTIONARY))
161    return NULL;
162
163  scoped_ptr<base::DictionaryValue> dict(
164      static_cast<base::DictionaryValue*>(value.release()));
165
166  int id;
167  if (!dict->GetInteger(kIdParam, &id))
168    return NULL;
169
170  int error_code = 0;
171  base::DictionaryValue* error_dict = NULL;
172  if (dict->GetDictionary(kErrorParam, &error_dict))
173    error_dict->GetInteger(kErrorCodeParam, &error_code);
174  return new Response(id, error_code, std::string());
175}
176