Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: ui/devtools/devtools_server.cc

Issue 2374513002: Add ui devtools server (Closed)
Patch Set: Address @sadrul's comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "ui/devtools/devtools_server.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/format_macros.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "net/base/net_errors.h"
15 #include "net/log/net_log.h"
16 #include "net/server/http_server_request_info.h"
17 #include "net/socket/server_socket.h"
18 #include "net/socket/tcp_server_socket.h"
19
20 namespace ui {
21 namespace devtools {
22
23 namespace {
24 constexpr int kBacklog = 1;
25 const char kChromeDeveloperToolsPrefix[] =
26 "chrome-devtools://devtools/bundled/inspector.html?ws=";
27 } // namespace
28
29 UiDevToolsServer::UiDevToolsServer()
30 : thread_(new base::Thread("UiDevToolsServerThread")) {}
31
32 UiDevToolsServer::~UiDevToolsServer() {}
33
34 void UiDevToolsServer::Start(const std::string& address_string, uint16_t port) {
35 if (thread_ && thread_->IsRunning())
36 return;
37
38 // Start IO thread upon which all the methods will run
39 base::Thread::Options options;
40 options.message_loop_type = base::MessageLoop::TYPE_IO;
41 if (thread_->StartWithOptions(options)) {
42 thread_->task_runner()->PostTask(
43 FROM_HERE, base::Bind(&UiDevToolsServer::StartServer,
44 base::Unretained(this), address_string, port));
45 }
46 }
47
48 void UiDevToolsServer::StartServer(const std::string& address_string,
49 uint16_t port) {
50 std::unique_ptr<net::ServerSocket> socket(
51 new net::TCPServerSocket(nullptr, net::NetLogSource()));
52 if (socket->ListenWithAddressAndPort(address_string, port, kBacklog) !=
53 net::OK)
54 return;
55 server_ = base::MakeUnique<net::HttpServer>(std::move(socket), this);
56 }
57
58 void UiDevToolsServer::SendOverWebSocket(int connection_id,
59 const String& message) {
60 thread_->task_runner()->PostTask(
61 FROM_HERE,
62 base::Bind(&net::HttpServer::SendOverWebSocket,
63 base::Unretained(server_.get()), connection_id, message));
64 }
65
66 void UiDevToolsServer::AttachClient(std::unique_ptr<UiDevToolsClient> client) {
67 clients_.push_back(std::move(client));
68 }
69
70 // HttpServer::Delegate Implementation
71 void UiDevToolsServer::OnConnect(int connection_id) {
72 NOTIMPLEMENTED();
73 }
74
75 void UiDevToolsServer::OnHttpRequest(int connection_id,
76 const net::HttpServerRequestInfo& info) {
77 // Display a simple html page with all the clients and the corresponding
78 // devtools links
79 // TODO(mhashmi): Remove and display all clients under chrome://inspect/#other
80 if (info.path.empty() || info.path == "/") {
81 std::string clientHTML = "<html>";
82 clientHTML +=
83 "<h3>Copy paste the corresponding links in your browser to inspect "
84 "them:</h3>";
85 for (ClientsList::size_type i = 0; i != clients_.size(); i++) {
86 net::IPEndPoint ip;
87 server_->GetLocalAddress(&ip);
88 clientHTML += base::StringPrintf(
89 "<p><strong>%s</strong> (%s%s/%" PRIuS ")</p>",
90 clients_[i]->name_.c_str(), kChromeDeveloperToolsPrefix,
91 ip.ToString().c_str(), i);
92 }
93 clientHTML += "</html>";
94 thread_->task_runner()->PostTask(
95 FROM_HERE,
96 base::Bind(&net::HttpServer::Send200, base::Unretained(server_.get()),
97 connection_id, clientHTML, "text/html"));
98 }
99 }
100
101 void UiDevToolsServer::OnWebSocketRequest(
102 int connection_id,
103 const net::HttpServerRequestInfo& info) {
104 size_t target_id;
105 if (info.path.empty() ||
106 !base::StringToSizeT(info.path.substr(1), &target_id) ||
107 target_id > clients_.size())
108 return;
109
110 UiDevToolsClient* client = clients_[target_id].get();
111 // Only one user can inspect the client at a time
112 if (client->connected())
113 return;
114 client->connection_id_ = connection_id;
115 connections_[connection_id] = client;
116 thread_->task_runner()->PostTask(
117 FROM_HERE,
118 base::Bind(&net::HttpServer::AcceptWebSocket,
119 base::Unretained(server_.get()), connection_id, info));
120 }
121
122 void UiDevToolsServer::OnWebSocketMessage(int connection_id,
123 const std::string& data) {
124 ConnectionsMap::iterator it = connections_.find(connection_id);
125 DCHECK(it != connections_.end());
126 UiDevToolsClient* client = it->second;
127 if (!client) {
128 // Client shut down, close the connection
129 connections_.erase(it);
130 thread_->task_runner()->PostTask(
131 FROM_HERE, base::Bind(&net::HttpServer::Close,
132 base::Unretained(server_.get()), connection_id));
133 return;
134 }
135
136 thread_->task_runner()->PostTask(
137 FROM_HERE,
138 base::Bind(&UiDevToolsClient::Dispatch, base::Unretained(client), data));
139 }
140
141 void UiDevToolsServer::OnClose(int connection_id) {
142 ConnectionsMap::iterator it = connections_.find(connection_id);
143 DCHECK(it != connections_.end());
144 UiDevToolsClient* client = it->second;
145 if (client)
146 client->connection_id_ = UiDevToolsClient::kNotConnected;
147 connections_.erase(it);
148 }
149
150 } // namespace devtools
151 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698