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

Side by Side Diff: content/browser/devtools/tethering_handler.cc

Issue 658163003: [DevTools] Added browser protocol to handler generator (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@singleUse
Patch Set: Created 6 years, 1 month 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 (c) 2012 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 "content/browser/devtools/tethering_handler.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/stl_util.h"
10 #include "base/values.h"
11 #include "content/browser/devtools/devtools_http_handler_impl.h"
12 #include "content/browser/devtools/devtools_protocol_constants.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/devtools_http_handler_delegate.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/ip_endpoint.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/net_log.h"
19 #include "net/socket/stream_listen_socket.h"
20 #include "net/socket/stream_socket.h"
21 #include "net/socket/tcp_server_socket.h"
22
23 namespace content {
24
25 namespace {
26
27 const char kLocalhost[] = "127.0.0.1";
28
29 const int kListenBacklog = 5;
30 const int kBufferSize = 16 * 1024;
31
32 const int kMinTetheringPort = 1024;
33 const int kMaxTetheringPort = 32767;
34
35 class SocketPump : public net::StreamListenSocket::Delegate {
36 public:
37 SocketPump(DevToolsHttpHandlerDelegate* delegate,
38 net::StreamSocket* client_socket)
39 : client_socket_(client_socket),
40 delegate_(delegate),
41 wire_buffer_size_(0),
42 pending_destruction_(false) {
43 }
44
45 std::string Init() {
46 std::string channel_name;
47 server_socket_ = delegate_->CreateSocketForTethering(this, &channel_name);
48 if (!server_socket_.get() || channel_name.empty())
49 SelfDestruct();
50 return channel_name;
51 }
52
53 ~SocketPump() override {}
54
55 private:
56 void DidAccept(net::StreamListenSocket* server,
57 scoped_ptr<net::StreamListenSocket> socket) override {
58 if (accepted_socket_.get())
59 return;
60
61 buffer_ = new net::IOBuffer(kBufferSize);
62 wire_buffer_ = new net::GrowableIOBuffer();
63 wire_buffer_->SetCapacity(kBufferSize);
64
65 accepted_socket_ = socket.Pass();
66 int result = client_socket_->Read(
67 buffer_.get(),
68 kBufferSize,
69 base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
70 if (result != net::ERR_IO_PENDING)
71 OnClientRead(result);
72 }
73
74 void DidRead(net::StreamListenSocket* socket,
75 const char* data,
76 int len) override {
77 int old_size = wire_buffer_size_;
78 wire_buffer_size_ += len;
79 while (wire_buffer_->capacity() < wire_buffer_size_)
80 wire_buffer_->SetCapacity(wire_buffer_->capacity() * 2);
81 memcpy(wire_buffer_->StartOfBuffer() + old_size, data, len);
82 if (old_size != wire_buffer_->offset())
83 return;
84 OnClientWrite(0);
85 }
86
87 void DidClose(net::StreamListenSocket* socket) override { SelfDestruct(); }
88
89 void OnClientRead(int result) {
90 if (result <= 0) {
91 SelfDestruct();
92 return;
93 }
94
95 accepted_socket_->Send(buffer_->data(), result);
96 result = client_socket_->Read(
97 buffer_.get(),
98 kBufferSize,
99 base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
100 if (result != net::ERR_IO_PENDING)
101 OnClientRead(result);
102 }
103
104 void OnClientWrite(int result) {
105 if (result < 0) {
106 SelfDestruct();
107 return;
108 }
109
110 wire_buffer_->set_offset(wire_buffer_->offset() + result);
111
112 int remaining = wire_buffer_size_ - wire_buffer_->offset();
113 if (remaining == 0) {
114 if (pending_destruction_)
115 SelfDestruct();
116 return;
117 }
118
119
120 if (remaining > kBufferSize)
121 remaining = kBufferSize;
122
123 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(remaining);
124 memcpy(buffer->data(), wire_buffer_->data(), remaining);
125 result = client_socket_->Write(
126 buffer.get(),
127 remaining,
128 base::Bind(&SocketPump::OnClientWrite, base::Unretained(this)));
129
130 // Shrink buffer
131 int offset = wire_buffer_->offset();
132 if (offset > kBufferSize) {
133 memcpy(wire_buffer_->StartOfBuffer(), wire_buffer_->data(),
134 wire_buffer_size_ - offset);
135 wire_buffer_size_ -= offset;
136 wire_buffer_->set_offset(0);
137 }
138
139 if (result != net::ERR_IO_PENDING)
140 OnClientWrite(result);
141 return;
142 }
143
144 void SelfDestruct() {
145 if (wire_buffer_.get() && wire_buffer_->offset() != wire_buffer_size_) {
146 pending_destruction_ = true;
147 return;
148 }
149 delete this;
150 }
151
152 private:
153 scoped_ptr<net::StreamSocket> client_socket_;
154 scoped_ptr<net::StreamListenSocket> server_socket_;
155 scoped_ptr<net::StreamListenSocket> accepted_socket_;
156 scoped_refptr<net::IOBuffer> buffer_;
157 scoped_refptr<net::GrowableIOBuffer> wire_buffer_;
158 DevToolsHttpHandlerDelegate* delegate_;
159 int wire_buffer_size_;
160 bool pending_destruction_;
161 };
162
163 static int GetPort(scoped_refptr<DevToolsProtocol::Command> command,
164 const std::string& paramName) {
165 base::DictionaryValue* params = command->params();
166 int port = 0;
167 if (!params ||
168 !params->GetInteger(paramName, &port) ||
169 port < kMinTetheringPort || port > kMaxTetheringPort)
170 return 0;
171 return port;
172 }
173
174 class BoundSocket {
175 public:
176 typedef base::Callback<void(int, const std::string&)> AcceptedCallback;
177
178 BoundSocket(AcceptedCallback accepted_callback,
179 DevToolsHttpHandlerDelegate* delegate)
180 : accepted_callback_(accepted_callback),
181 delegate_(delegate),
182 socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
183 port_(0) {
184 }
185
186 virtual ~BoundSocket() {
187 }
188
189 bool Listen(int port) {
190 port_ = port;
191 net::IPAddressNumber ip_number;
192 if (!net::ParseIPLiteralToNumber(kLocalhost, &ip_number))
193 return false;
194
195 net::IPEndPoint end_point(ip_number, port);
196 int result = socket_->Listen(end_point, kListenBacklog);
197 if (result < 0)
198 return false;
199
200 net::IPEndPoint local_address;
201 result = socket_->GetLocalAddress(&local_address);
202 if (result < 0)
203 return false;
204
205 DoAccept();
206 return true;
207 }
208
209 private:
210 typedef std::map<net::IPEndPoint, net::StreamSocket*> AcceptedSocketsMap;
211
212 void DoAccept() {
213 while (true) {
214 int result = socket_->Accept(
215 &accept_socket_,
216 base::Bind(&BoundSocket::OnAccepted, base::Unretained(this)));
217 if (result == net::ERR_IO_PENDING)
218 break;
219 else
220 HandleAcceptResult(result);
221 }
222 }
223
224 void OnAccepted(int result) {
225 HandleAcceptResult(result);
226 if (result == net::OK)
227 DoAccept();
228 }
229
230 void HandleAcceptResult(int result) {
231 if (result != net::OK)
232 return;
233
234 SocketPump* pump = new SocketPump(delegate_, accept_socket_.release());
235 std::string name = pump->Init();
236 if (!name.empty())
237 accepted_callback_.Run(port_, name);
238 }
239
240 AcceptedCallback accepted_callback_;
241 DevToolsHttpHandlerDelegate* delegate_;
242 scoped_ptr<net::ServerSocket> socket_;
243 scoped_ptr<net::StreamSocket> accept_socket_;
244 int port_;
245 };
246
247 } // namespace
248
249 // TetheringHandler::TetheringImpl -------------------------------------------
250
251 class TetheringHandler::TetheringImpl {
252 public:
253 TetheringImpl(
254 base::WeakPtr<TetheringHandler> handler,
255 DevToolsHttpHandlerDelegate* delegate);
256 ~TetheringImpl();
257
258 void Bind(scoped_refptr<DevToolsProtocol::Command> command, int port);
259 void Unbind(scoped_refptr<DevToolsProtocol::Command> command, int port);
260 void Accepted(int port, const std::string& name);
261
262 private:
263 void SendInternalError(scoped_refptr<DevToolsProtocol::Command> command,
264 const std::string& message);
265
266 base::WeakPtr<TetheringHandler> handler_;
267 DevToolsHttpHandlerDelegate* delegate_;
268
269 typedef std::map<int, BoundSocket*> BoundSockets;
270 BoundSockets bound_sockets_;
271 };
272
273 TetheringHandler::TetheringImpl::TetheringImpl(
274 base::WeakPtr<TetheringHandler> handler,
275 DevToolsHttpHandlerDelegate* delegate)
276 : handler_(handler),
277 delegate_(delegate) {
278 }
279
280 TetheringHandler::TetheringImpl::~TetheringImpl() {
281 STLDeleteContainerPairSecondPointers(bound_sockets_.begin(),
282 bound_sockets_.end());
283 }
284
285 void TetheringHandler::TetheringImpl::Bind(
286 scoped_refptr<DevToolsProtocol::Command> command, int port) {
287 if (bound_sockets_.find(port) != bound_sockets_.end()) {
288 SendInternalError(command, "Port already bound");
289 return;
290 }
291
292 BoundSocket::AcceptedCallback callback = base::Bind(
293 &TetheringHandler::TetheringImpl::Accepted, base::Unretained(this));
294 scoped_ptr<BoundSocket> bound_socket(new BoundSocket(callback, delegate_));
295 if (!bound_socket->Listen(port)) {
296 SendInternalError(command, "Could not bind port");
297 return;
298 }
299
300 bound_sockets_[port] = bound_socket.release();
301 BrowserThread::PostTask(
302 BrowserThread::UI,
303 FROM_HERE,
304 base::Bind(&TetheringHandler::SendBindSuccess, handler_, command));
305 }
306
307 void TetheringHandler::TetheringImpl::Unbind(
308 scoped_refptr<DevToolsProtocol::Command> command, int port) {
309
310 BoundSockets::iterator it = bound_sockets_.find(port);
311 if (it == bound_sockets_.end()) {
312 SendInternalError(command, "Port is not bound");
313 return;
314 }
315
316 delete it->second;
317 bound_sockets_.erase(it);
318 BrowserThread::PostTask(
319 BrowserThread::UI,
320 FROM_HERE,
321 base::Bind(&TetheringHandler::SendUnbindSuccess, handler_, command));
322 }
323
324 void TetheringHandler::TetheringImpl::Accepted(
325 int port, const std::string& name) {
326 BrowserThread::PostTask(
327 BrowserThread::UI,
328 FROM_HERE,
329 base::Bind(&TetheringHandler::Accepted, handler_, port, name));
330 }
331
332 void TetheringHandler::TetheringImpl::SendInternalError(
333 scoped_refptr<DevToolsProtocol::Command> command,
334 const std::string& message) {
335 BrowserThread::PostTask(
336 BrowserThread::UI,
337 FROM_HERE,
338 base::Bind(&TetheringHandler::SendInternalError, handler_,
339 command, message));
340 }
341
342
343 // TetheringHandler ----------------------------------------------------------
344
345 // static
346 TetheringHandler::TetheringImpl* TetheringHandler::impl_ = nullptr;
347
348 TetheringHandler::TetheringHandler(
349 DevToolsHttpHandlerDelegate* delegate,
350 scoped_refptr<base::MessageLoopProxy> message_loop_proxy)
351 : delegate_(delegate),
352 message_loop_proxy_(message_loop_proxy),
353 is_active_(false),
354 weak_factory_(this) {
355 RegisterCommandHandler(devtools::Tethering::bind::kName,
356 base::Bind(&TetheringHandler::OnBind,
357 base::Unretained(this)));
358 RegisterCommandHandler(devtools::Tethering::unbind::kName,
359 base::Bind(&TetheringHandler::OnUnbind,
360 base::Unretained(this)));
361 }
362
363 TetheringHandler::~TetheringHandler() {
364 if (is_active_) {
365 message_loop_proxy_->DeleteSoon(FROM_HERE, impl_);
366 impl_ = nullptr;
367 }
368 }
369
370 void TetheringHandler::Accepted(int port, const std::string& name) {
371 base::DictionaryValue* params = new base::DictionaryValue();
372 params->SetInteger(devtools::Tethering::accepted::kParamPort, port);
373 params->SetString(devtools::Tethering::accepted::kParamConnectionId, name);
374 SendNotification(devtools::Tethering::accepted::kName, params);
375 }
376
377 bool TetheringHandler::Activate() {
378 if (is_active_)
379 return true;
380 if (impl_)
381 return false;
382 is_active_ = true;
383 impl_ = new TetheringImpl(weak_factory_.GetWeakPtr(), delegate_);
384 return true;
385 }
386
387 scoped_refptr<DevToolsProtocol::Response>
388 TetheringHandler::OnBind(scoped_refptr<DevToolsProtocol::Command> command) {
389 const std::string& portParamName = devtools::Tethering::bind::kParamPort;
390 int port = GetPort(command, portParamName);
391 if (port == 0)
392 return command->InvalidParamResponse(portParamName);
393
394 if (!Activate()) {
395 return command->ServerErrorResponse(
396 "Tethering is used by another connection");
397 }
398 DCHECK(impl_);
399 message_loop_proxy_->PostTask(
400 FROM_HERE,
401 base::Bind(&TetheringImpl::Bind, base::Unretained(impl_),
402 command, port));
403 return command->AsyncResponsePromise();
404 }
405
406 scoped_refptr<DevToolsProtocol::Response>
407 TetheringHandler::OnUnbind(scoped_refptr<DevToolsProtocol::Command> command) {
408 const std::string& portParamName = devtools::Tethering::unbind::kParamPort;
409 int port = GetPort(command, portParamName);
410 if (port == 0)
411 return command->InvalidParamResponse(portParamName);
412
413 if (!Activate()) {
414 return command->ServerErrorResponse(
415 "Tethering is used by another connection");
416 }
417 DCHECK(impl_);
418 message_loop_proxy_->PostTask(
419 FROM_HERE,
420 base::Bind(&TetheringImpl::Unbind, base::Unretained(impl_),
421 command, port));
422 return command->AsyncResponsePromise();
423 }
424
425 void TetheringHandler::SendBindSuccess(
426 scoped_refptr<DevToolsProtocol::Command> command) {
427 SendAsyncResponse(command->SuccessResponse(nullptr));
428 }
429
430 void TetheringHandler::SendUnbindSuccess(
431 scoped_refptr<DevToolsProtocol::Command> command) {
432 SendAsyncResponse(command->SuccessResponse(nullptr));
433 }
434
435 void TetheringHandler::SendInternalError(
436 scoped_refptr<DevToolsProtocol::Command> command,
437 const std::string& message) {
438 SendAsyncResponse(command->InternalErrorResponse(message));
439 }
440
441 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698