1// Copyright (c) 2011 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/debugger/devtools_remote_service.h"
6
7#include <string>
8
9#include "base/json/json_reader.h"
10#include "base/json/json_writer.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/values.h"
13#include "chrome/browser/debugger/devtools_manager.h"
14#include "chrome/browser/debugger/devtools_protocol_handler.h"
15#include "chrome/browser/debugger/devtools_remote_message.h"
16#include "chrome/browser/debugger/inspectable_tab_proxy.h"
17#include "chrome/common/devtools_messages.h"
18#include "content/browser/tab_contents/navigation_controller.h"
19#include "content/browser/tab_contents/navigation_entry.h"
20
21const char DevToolsRemoteServiceCommand::kPing[] = "ping";
22const char DevToolsRemoteServiceCommand::kVersion[] = "version";
23const char DevToolsRemoteServiceCommand::kListTabs[] = "list_tabs";
24
25const char DevToolsRemoteService::kToolName[] = "DevToolsService";
26
27namespace {
28const char kCommandKey[] = "command";
29const char kDataKey[] = "data";
30const char kResultKey[] = "result";
31}  // namespace
32
33DevToolsRemoteService::DevToolsRemoteService(DevToolsProtocolHandler* delegate)
34    : delegate_(delegate) {}
35
36DevToolsRemoteService::~DevToolsRemoteService() {}
37
38void DevToolsRemoteService::HandleMessage(
39    const DevToolsRemoteMessage& message) {
40  scoped_ptr<Value> request(base::JSONReader::Read(message.content(), false));
41  if (request.get() == NULL) {
42    // Bad JSON
43    NOTREACHED();
44    return;
45  }
46  DictionaryValue* json;
47  if (request->IsType(Value::TYPE_DICTIONARY)) {
48    json = static_cast<DictionaryValue*>(request.get());
49    if (!json->HasKey(kCommandKey)) {
50      NOTREACHED();  // Broken protocol - no "command" specified
51      return;
52    }
53  } else {
54    NOTREACHED();  // Broken protocol - not a JS object
55    return;
56  }
57  ProcessJson(json, message);
58}
59
60void DevToolsRemoteService::ProcessJson(DictionaryValue* json,
61                                        const DevToolsRemoteMessage& message) {
62  static const std::string kOkResponse = "ok";  // "Ping" response
63  static const std::string kVersion = "0.1";  // Current protocol version
64  std::string command;
65  DictionaryValue response;
66
67  json->GetString(kCommandKey, &command);
68  response.SetString(kCommandKey, command);
69
70  if (command == DevToolsRemoteServiceCommand::kPing) {
71    response.SetInteger(kResultKey, Result::kOk);
72    response.SetString(kDataKey, kOkResponse);
73  } else if (command == DevToolsRemoteServiceCommand::kVersion) {
74    response.SetInteger(kResultKey, Result::kOk);
75    response.SetString(kDataKey, kVersion);
76  } else if (command == DevToolsRemoteServiceCommand::kListTabs) {
77    ListValue* data = new ListValue();
78    const InspectableTabProxy::ControllersMap& navcon_map =
79        delegate_->inspectable_tab_proxy()->controllers_map();
80    for (InspectableTabProxy::ControllersMap::const_iterator it =
81        navcon_map.begin(), end = navcon_map.end(); it != end; ++it) {
82      NavigationEntry* entry = it->second->GetActiveEntry();
83      if (entry == NULL) {
84        continue;
85      }
86      if (entry->url().is_valid()) {
87        ListValue* tab = new ListValue();
88        tab->Append(Value::CreateIntegerValue(
89            static_cast<int32>(it->second->session_id().id())));
90        tab->Append(Value::CreateStringValue(entry->url().spec()));
91        data->Append(tab);
92      }
93    }
94    response.SetInteger(kResultKey, Result::kOk);
95    response.Set(kDataKey, data);
96  } else {
97    // Unknown protocol command.
98    NOTREACHED();
99    response.SetInteger(kResultKey, Result::kUnknownCommand);
100  }
101  std::string response_json;
102  base::JSONWriter::Write(&response, false, &response_json);
103  scoped_ptr<DevToolsRemoteMessage> response_message(
104      DevToolsRemoteMessageBuilder::instance().Create(message.tool(),
105                                                      message.destination(),
106                                                      response_json));
107  delegate_->Send(*response_message.get());
108}
109