OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/devtools/tethering_adb_filter.h" | 5 #include "chrome/browser/devtools/tethering_adb_filter.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
24 #include "net/dns/host_resolver.h" | 24 #include "net/dns/host_resolver.h" |
25 #include "net/socket/tcp_client_socket.h" | 25 #include "net/socket/tcp_client_socket.h" |
26 | 26 |
27 using content::BrowserThread; | 27 using content::BrowserThread; |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 const int kBufferSize = 16 * 1024; | 31 const int kBufferSize = 16 * 1024; |
32 | 32 |
| 33 enum { |
| 34 kStatusError = -3, |
| 35 kStatusDisconnecting = -2, |
| 36 kStatusConnecting = -1, |
| 37 kStatusOK = 0, |
| 38 // Positive values are used to count open connections. |
| 39 }; |
| 40 |
33 static const char kPortAttribute[] = "port"; | 41 static const char kPortAttribute[] = "port"; |
34 static const char kConnectionIdAttribute[] = "connectionId"; | 42 static const char kConnectionIdAttribute[] = "connectionId"; |
35 static const char kTetheringAccepted[] = "Tethering.accepted"; | 43 static const char kTetheringAccepted[] = "Tethering.accepted"; |
36 static const char kTetheringBind[] = "Tethering.bind"; | 44 static const char kTetheringBind[] = "Tethering.bind"; |
37 static const char kTetheringUnbind[] = "Tethering.unbind"; | 45 static const char kTetheringUnbind[] = "Tethering.unbind"; |
38 | 46 |
39 static const char kDevToolsRemoteSocketName[] = "chrome_devtools_remote"; | 47 static const char kDevToolsRemoteSocketName[] = "chrome_devtools_remote"; |
40 static const char kDevToolsRemoteBrowserTarget[] = "/devtools/browser"; | 48 static const char kDevToolsRemoteBrowserTarget[] = "/devtools/browser"; |
41 | 49 |
42 class SocketTunnel { | 50 class SocketTunnel { |
43 public: | 51 public: |
44 explicit SocketTunnel(const std::string& location) | 52 typedef base::Callback<void(int)> CounterCallback; |
| 53 |
| 54 SocketTunnel(const std::string& location, const CounterCallback& callback) |
45 : location_(location), | 55 : location_(location), |
46 pending_writes_(0), | 56 pending_writes_(0), |
47 pending_destruction_(false) { | 57 pending_destruction_(false), |
| 58 callback_(callback) { |
| 59 callback_.Run(1); |
48 } | 60 } |
49 | 61 |
50 void Start(int result, net::StreamSocket* socket) { | 62 void Start(int result, net::StreamSocket* socket) { |
51 if (result < 0) { | 63 if (result < 0) { |
52 SelfDestruct(); | 64 SelfDestruct(); |
53 return; | 65 return; |
54 } | 66 } |
55 remote_socket_.reset(socket); | 67 remote_socket_.reset(socket); |
56 | 68 |
57 std::vector<std::string> tokens; | 69 std::vector<std::string> tokens; |
(...skipping 28 matching lines...) Expand all Loading... |
86 base::Unretained(this))); | 98 base::Unretained(this))); |
87 if (result != net::ERR_IO_PENDING) | 99 if (result != net::ERR_IO_PENDING) |
88 OnConnected(result); | 100 OnConnected(result); |
89 } | 101 } |
90 | 102 |
91 ~SocketTunnel() { | 103 ~SocketTunnel() { |
92 if (host_socket_) | 104 if (host_socket_) |
93 host_socket_->Disconnect(); | 105 host_socket_->Disconnect(); |
94 if (remote_socket_) | 106 if (remote_socket_) |
95 remote_socket_->Disconnect(); | 107 remote_socket_->Disconnect(); |
| 108 callback_.Run(-1); |
96 } | 109 } |
97 | 110 |
98 void OnConnected(int result) { | 111 void OnConnected(int result) { |
99 if (result < 0) { | 112 if (result < 0) { |
100 SelfDestruct(); | 113 SelfDestruct(); |
101 return; | 114 return; |
102 } | 115 } |
103 | 116 |
104 Pump(host_socket_.get(), remote_socket_.get()); | 117 Pump(host_socket_.get(), remote_socket_.get()); |
105 Pump(remote_socket_.get(), host_socket_.get()); | 118 Pump(remote_socket_.get(), host_socket_.get()); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 delete this; | 194 delete this; |
182 } | 195 } |
183 | 196 |
184 std::string location_; | 197 std::string location_; |
185 scoped_ptr<net::StreamSocket> remote_socket_; | 198 scoped_ptr<net::StreamSocket> remote_socket_; |
186 scoped_ptr<net::StreamSocket> host_socket_; | 199 scoped_ptr<net::StreamSocket> host_socket_; |
187 scoped_ptr<net::HostResolver> host_resolver_; | 200 scoped_ptr<net::HostResolver> host_resolver_; |
188 net::AddressList address_list_; | 201 net::AddressList address_list_; |
189 int pending_writes_; | 202 int pending_writes_; |
190 bool pending_destruction_; | 203 bool pending_destruction_; |
| 204 CounterCallback callback_; |
191 }; | 205 }; |
192 | 206 |
193 } // namespace | 207 } // namespace |
194 | 208 |
195 TetheringAdbFilter::TetheringAdbFilter( | 209 TetheringAdbFilter::TetheringAdbFilter( |
196 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device, | 210 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device, |
197 base::MessageLoop* adb_message_loop, | 211 base::MessageLoop* adb_message_loop, |
198 PrefService* pref_service, | 212 PrefService* pref_service, |
199 scoped_refptr<AdbWebSocket> web_socket) | 213 scoped_refptr<AdbWebSocket> web_socket) |
200 : device_(device), | 214 : device_(device), |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 continue; // The port points to the same location in both configs, skip. | 279 continue; // The port points to the same location in both configs, skip. |
266 | 280 |
267 SendCommand(method, port); | 281 SendCommand(method, port); |
268 } | 282 } |
269 } | 283 } |
270 | 284 |
271 void TetheringAdbFilter::SendCommand(const std::string& method, int port) { | 285 void TetheringAdbFilter::SendCommand(const std::string& method, int port) { |
272 base::DictionaryValue params; | 286 base::DictionaryValue params; |
273 params.SetInteger(kPortAttribute, port); | 287 params.SetInteger(kPortAttribute, port); |
274 DevToolsProtocol::Command command(++command_id_, method, ¶ms); | 288 DevToolsProtocol::Command command(++command_id_, method, ¶ms); |
| 289 |
| 290 if (method == kTetheringBind) { |
| 291 pending_responses_[command.id()] = |
| 292 base::Bind(&TetheringAdbFilter::ProcessBindResponse, |
| 293 weak_factory_.GetWeakPtr(), port); |
| 294 #if defined(DEBUG_DEVTOOLS) |
| 295 port_status_[port] = kStatusConnecting; |
| 296 UpdatePortStatusMap(); |
| 297 #endif // defined(DEBUG_DEVTOOLS) |
| 298 } else { |
| 299 DCHECK_EQ(kTetheringUnbind, method); |
| 300 |
| 301 PortStatusMap::iterator it = port_status_.find(port); |
| 302 if (it != port_status_.end() && it->second == kStatusError) { |
| 303 // The bind command failed on this port, do not attempt unbind. |
| 304 port_status_.erase(it); |
| 305 UpdatePortStatusMap(); |
| 306 return; |
| 307 } |
| 308 |
| 309 pending_responses_[command.id()] = |
| 310 base::Bind(&TetheringAdbFilter::ProcessUnbindResponse, |
| 311 weak_factory_.GetWeakPtr(), port); |
| 312 #if defined(DEBUG_DEVTOOLS) |
| 313 port_status_[port] = kStatusDisconnecting; |
| 314 UpdatePortStatusMap(); |
| 315 #endif // defined(DEBUG_DEVTOOLS) |
| 316 } |
| 317 |
275 web_socket_->SendFrameOnHandlerThread(command.Serialize()); | 318 web_socket_->SendFrameOnHandlerThread(command.Serialize()); |
276 } | 319 } |
277 | 320 |
| 321 bool TetheringAdbFilter::ProcessResponse(const std::string& message) { |
| 322 scoped_ptr<DevToolsProtocol::Response> response( |
| 323 DevToolsProtocol::ParseResponse(message)); |
| 324 if (!response) |
| 325 return false; |
| 326 |
| 327 CommandCallbackMap::iterator it = pending_responses_.find(response->id()); |
| 328 if (it == pending_responses_.end()) |
| 329 return false; |
| 330 |
| 331 it->second.Run(response->error_code() ? kStatusError : kStatusOK); |
| 332 pending_responses_.erase(it); |
| 333 return true; |
| 334 } |
| 335 |
| 336 void TetheringAdbFilter::ProcessBindResponse(int port, PortStatus status) { |
| 337 port_status_[port] = status; |
| 338 UpdatePortStatusMap(); |
| 339 } |
| 340 |
| 341 void TetheringAdbFilter::ProcessUnbindResponse(int port, PortStatus status) { |
| 342 PortStatusMap::iterator it = port_status_.find(port); |
| 343 if (it == port_status_.end()) |
| 344 return; |
| 345 if (status == kStatusError) |
| 346 it->second = status; |
| 347 else |
| 348 port_status_.erase(it); |
| 349 UpdatePortStatusMap(); |
| 350 } |
| 351 |
| 352 void TetheringAdbFilter::UpdateSocketCount(int port, int increment) { |
| 353 #if defined(DEBUG_DEVTOOLS) |
| 354 PortStatusMap::iterator it = port_status_.find(port); |
| 355 if (it == port_status_.end()) |
| 356 return; |
| 357 if (it->second < 0 || (it->second == 0 && increment < 0)) |
| 358 return; |
| 359 it->second += increment; |
| 360 UpdatePortStatusMap(); |
| 361 #endif // defined(DEBUG_DEVTOOLS) |
| 362 } |
| 363 |
| 364 void TetheringAdbFilter::UpdatePortStatusMap() { |
| 365 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 366 base::Bind(&TetheringAdbFilter::UpdatePortStatusMapOnUIThread, |
| 367 weak_factory_.GetWeakPtr(), port_status_)); |
| 368 } |
| 369 |
| 370 void TetheringAdbFilter::UpdatePortStatusMapOnUIThread( |
| 371 const PortStatusMap& status_map) { |
| 372 port_status_on_ui_thread_ = status_map; |
| 373 } |
| 374 |
| 375 const TetheringAdbFilter::PortStatusMap& |
| 376 TetheringAdbFilter::GetPortStatusMap() { |
| 377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 378 return port_status_on_ui_thread_; |
| 379 } |
| 380 |
278 bool TetheringAdbFilter::ProcessIncomingMessage(const std::string& message) { | 381 bool TetheringAdbFilter::ProcessIncomingMessage(const std::string& message) { |
279 DCHECK_EQ(base::MessageLoop::current(), adb_message_loop_); | 382 DCHECK_EQ(base::MessageLoop::current(), adb_message_loop_); |
280 | 383 |
281 // Only parse messages that might be Tethering.accepted event. | 384 if (ProcessResponse(message)) |
282 if (message.length() > 200 || | 385 return true; |
283 message.find(kTetheringAccepted) == std::string::npos) | |
284 return false; | |
285 | 386 |
286 scoped_ptr<DevToolsProtocol::Notification> notification( | 387 scoped_ptr<DevToolsProtocol::Notification> notification( |
287 DevToolsProtocol::ParseNotification(message)); | 388 DevToolsProtocol::ParseNotification(message)); |
288 if (!notification) | 389 if (!notification) |
289 return false; | 390 return false; |
290 | 391 |
291 if (notification->method() != kTetheringAccepted) | 392 if (notification->method() != kTetheringAccepted) |
292 return false; | 393 return false; |
293 | 394 |
294 DictionaryValue* params = notification->params(); | 395 DictionaryValue* params = notification->params(); |
295 if (!params) | 396 if (!params) |
296 return false; | 397 return false; |
297 | 398 |
298 int port; | 399 int port; |
299 std::string connection_id; | 400 std::string connection_id; |
300 if (!params->GetInteger(kPortAttribute, &port) || | 401 if (!params->GetInteger(kPortAttribute, &port) || |
301 !params->GetString(kConnectionIdAttribute, &connection_id)) | 402 !params->GetString(kConnectionIdAttribute, &connection_id)) |
302 return false; | 403 return false; |
303 | 404 |
304 std::map<int, std::string>::iterator it = forwarding_map_.find(port); | 405 std::map<int, std::string>::iterator it = forwarding_map_.find(port); |
305 if (it == forwarding_map_.end()) | 406 if (it == forwarding_map_.end()) |
306 return false; | 407 return false; |
307 | 408 |
308 std::string location = it->second; | 409 std::string location = it->second; |
309 | 410 |
310 SocketTunnel* tunnel = new SocketTunnel(location); | 411 SocketTunnel* tunnel = new SocketTunnel(location, |
| 412 base::Bind(&TetheringAdbFilter::UpdateSocketCount, |
| 413 weak_factory_.GetWeakPtr(), |
| 414 port)); |
| 415 |
311 device_->OpenSocket(connection_id.c_str(), | 416 device_->OpenSocket(connection_id.c_str(), |
312 base::Bind(&SocketTunnel::Start, base::Unretained(tunnel))); | 417 base::Bind(&SocketTunnel::Start, base::Unretained(tunnel))); |
313 return true; | 418 return true; |
314 } | 419 } |
315 | 420 |
316 class PortForwardingController::Connection : public AdbWebSocket::Delegate { | 421 class PortForwardingController::Connection : public AdbWebSocket::Delegate { |
317 public: | 422 public: |
318 Connection( | 423 Connection( |
319 Registry* registry, | 424 Registry* registry, |
320 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device, | 425 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device, |
321 base::MessageLoop* adb_message_loop, | 426 base::MessageLoop* adb_message_loop, |
322 PrefService* pref_service); | 427 PrefService* pref_service); |
323 | 428 |
324 void Shutdown(); | 429 void Shutdown(); |
325 | 430 |
| 431 TetheringAdbFilter::PortStatusMap port_status(); |
| 432 |
326 private: | 433 private: |
327 virtual ~Connection(); | 434 virtual ~Connection(); |
328 | 435 |
329 virtual void OnSocketOpened() OVERRIDE; | 436 virtual void OnSocketOpened() OVERRIDE; |
330 virtual void OnFrameRead(const std::string& message) OVERRIDE; | 437 virtual void OnFrameRead(const std::string& message) OVERRIDE; |
331 virtual void OnSocketClosed(bool closed_by_device) OVERRIDE; | 438 virtual void OnSocketClosed(bool closed_by_device) OVERRIDE; |
332 virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE; | 439 virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE; |
333 | 440 |
334 Registry* registry_; | 441 Registry* registry_; |
335 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device_; | 442 scoped_refptr<DevToolsAdbBridge::AndroidDevice> device_; |
(...skipping 18 matching lines...) Expand all Loading... |
354 device, kDevToolsRemoteSocketName, kDevToolsRemoteBrowserTarget, | 461 device, kDevToolsRemoteSocketName, kDevToolsRemoteBrowserTarget, |
355 adb_message_loop_, this); | 462 adb_message_loop_, this); |
356 } | 463 } |
357 | 464 |
358 void PortForwardingController::Connection::Shutdown() { | 465 void PortForwardingController::Connection::Shutdown() { |
359 registry_ = NULL; | 466 registry_ = NULL; |
360 // This will have no effect if the socket is not connected yet. | 467 // This will have no effect if the socket is not connected yet. |
361 web_socket_->Disconnect(); | 468 web_socket_->Disconnect(); |
362 } | 469 } |
363 | 470 |
| 471 TetheringAdbFilter::PortStatusMap |
| 472 PortForwardingController::Connection::port_status() { |
| 473 if (tethering_adb_filter_) |
| 474 return tethering_adb_filter_->GetPortStatusMap(); |
| 475 else |
| 476 return TetheringAdbFilter::PortStatusMap(); |
| 477 } |
| 478 |
364 PortForwardingController::Connection::~Connection() { | 479 PortForwardingController::Connection::~Connection() { |
365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
366 if (registry_) { | 481 if (registry_) { |
367 DCHECK(registry_->find(device_->serial()) != registry_->end()); | 482 DCHECK(registry_->find(device_->serial()) != registry_->end()); |
368 registry_->erase(device_->serial()); | 483 registry_->erase(device_->serial()); |
369 } | 484 } |
370 } | 485 } |
371 | 486 |
372 void PortForwardingController::Connection::OnSocketOpened() { | 487 void PortForwardingController::Connection::OnSocketOpened() { |
373 if (!registry_) { | 488 if (!registry_) { |
(...skipping 30 matching lines...) Expand all Loading... |
404 | 519 |
405 PortForwardingController::~PortForwardingController() { | 520 PortForwardingController::~PortForwardingController() { |
406 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) | 521 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) |
407 it->second->Shutdown(); | 522 it->second->Shutdown(); |
408 } | 523 } |
409 | 524 |
410 void PortForwardingController::UpdateDeviceList( | 525 void PortForwardingController::UpdateDeviceList( |
411 const DevToolsAdbBridge::RemoteDevices& devices) { | 526 const DevToolsAdbBridge::RemoteDevices& devices) { |
412 for (DevToolsAdbBridge::RemoteDevices::const_iterator it = devices.begin(); | 527 for (DevToolsAdbBridge::RemoteDevices::const_iterator it = devices.begin(); |
413 it != devices.end(); ++it) { | 528 it != devices.end(); ++it) { |
414 if (registry_.find((*it)->serial()) == registry_.end()) { | 529 Registry::iterator rit = registry_.find((*it)->serial()); |
| 530 if (rit == registry_.end()) { |
415 // Will delete itself when disconnected. | 531 // Will delete itself when disconnected. |
416 new Connection( | 532 new Connection( |
417 ®istry_, (*it)->device(), adb_message_loop_, pref_service_); | 533 ®istry_, (*it)->device(), adb_message_loop_, pref_service_); |
| 534 } else { |
| 535 (*it)->set_port_status((*rit).second->port_status()); |
418 } | 536 } |
419 } | 537 } |
420 } | 538 } |
OLD | NEW |