| 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 |