1 // Copyright (c) 2009 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_protocol_handler.h"
6
7 #include "base/logging.h"
8 #include "chrome/browser/debugger/inspectable_tab_proxy.h"
9 #include "chrome/browser/debugger/debugger_remote_service.h"
10 #include "chrome/browser/debugger/devtools_remote_message.h"
11 #include "chrome/browser/debugger/devtools_remote_listen_socket.h"
12 #include "chrome/browser/debugger/devtools_remote_service.h"
13 #include "chrome/browser/debugger/extension_ports_remote_service.h"
14 #include "content/browser/browser_thread.h"
15
16 // static
Start(int port)17 scoped_refptr<DevToolsProtocolHandler> DevToolsProtocolHandler::Start(
18 int port) {
19 scoped_refptr<DevToolsProtocolHandler> proto_handler =
20 new DevToolsProtocolHandler(port);
21 proto_handler->RegisterDestination(
22 new DevToolsRemoteService(proto_handler),
23 DevToolsRemoteService::kToolName);
24 proto_handler->RegisterDestination(
25 new DebuggerRemoteService(proto_handler),
26 DebuggerRemoteService::kToolName);
27 proto_handler->RegisterDestination(
28 new ExtensionPortsRemoteService(proto_handler),
29 ExtensionPortsRemoteService::kToolName);
30 proto_handler->Start();
31 return proto_handler;
32 }
33
DevToolsProtocolHandler(int port)34 DevToolsProtocolHandler::DevToolsProtocolHandler(int port)
35 : port_(port),
36 connection_(NULL),
37 server_(NULL) {
38 inspectable_tab_proxy_.reset(new InspectableTabProxy);
39 }
40
~DevToolsProtocolHandler()41 DevToolsProtocolHandler::~DevToolsProtocolHandler() {
42 // Stop() must be called prior to this being called
43 DCHECK(server_.get() == NULL);
44 DCHECK(connection_.get() == NULL);
45 }
46
Start()47 void DevToolsProtocolHandler::Start() {
48 BrowserThread::PostTask(
49 BrowserThread::IO, FROM_HERE,
50 NewRunnableMethod(this, &DevToolsProtocolHandler::Init));
51 }
52
Init()53 void DevToolsProtocolHandler::Init() {
54 server_ = DevToolsRemoteListenSocket::Listen(
55 "127.0.0.1", port_, this);
56 }
57
Stop()58 void DevToolsProtocolHandler::Stop() {
59 BrowserThread::PostTask(
60 BrowserThread::IO, FROM_HERE,
61 NewRunnableMethod(this, &DevToolsProtocolHandler::Teardown));
62 tool_to_listener_map_.clear(); // Releases all scoped_refptr's to listeners
63 }
64
65 // Run in I/O thread
Teardown()66 void DevToolsProtocolHandler::Teardown() {
67 connection_ = NULL;
68 server_ = NULL;
69 }
70
RegisterDestination(DevToolsRemoteListener * listener,const std::string & tool_name)71 void DevToolsProtocolHandler::RegisterDestination(
72 DevToolsRemoteListener* listener,
73 const std::string& tool_name) {
74 DCHECK(tool_to_listener_map_.find(tool_name) == tool_to_listener_map_.end());
75 tool_to_listener_map_.insert(std::make_pair(tool_name, listener));
76 }
77
UnregisterDestination(DevToolsRemoteListener * listener,const std::string & tool_name)78 void DevToolsProtocolHandler::UnregisterDestination(
79 DevToolsRemoteListener* listener,
80 const std::string& tool_name) {
81 DCHECK(tool_to_listener_map_.find(tool_name) != tool_to_listener_map_.end());
82 DCHECK(tool_to_listener_map_.find(tool_name)->second == listener);
83 tool_to_listener_map_.erase(tool_name);
84 }
85
HandleMessage(const DevToolsRemoteMessage & message)86 void DevToolsProtocolHandler::HandleMessage(
87 const DevToolsRemoteMessage& message) {
88 std::string tool = message.GetHeaderWithEmptyDefault(
89 DevToolsRemoteMessageHeaders::kTool);
90 ToolToListenerMap::const_iterator it = tool_to_listener_map_.find(tool);
91 if (it == tool_to_listener_map_.end()) {
92 NOTREACHED(); // an unsupported tool, bail out
93 return;
94 }
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
96 BrowserThread::PostTask(
97 BrowserThread::UI, FROM_HERE,
98 NewRunnableMethod(
99 it->second.get(), &DevToolsRemoteListener::HandleMessage, message));
100 }
101
Send(const DevToolsRemoteMessage & message)102 void DevToolsProtocolHandler::Send(const DevToolsRemoteMessage& message) {
103 if (connection_ != NULL) {
104 connection_->Send(message.ToString());
105 }
106 }
107
OnAcceptConnection(ListenSocket * connection)108 void DevToolsProtocolHandler::OnAcceptConnection(ListenSocket *connection) {
109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
110 connection_ = connection;
111 }
112
OnConnectionLost()113 void DevToolsProtocolHandler::OnConnectionLost() {
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
115 connection_ = NULL;
116 for (ToolToListenerMap::const_iterator it = tool_to_listener_map_.begin(),
117 end = tool_to_listener_map_.end();
118 it != end;
119 ++it) {
120 BrowserThread::PostTask(
121 BrowserThread::UI, FROM_HERE,
122 NewRunnableMethod(
123 it->second.get(), &DevToolsRemoteListener::OnConnectionLost));
124 }
125 }
126