| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/device/port_forwarding_controller.h" | 5 #include "chrome/browser/devtools/device/port_forwarding_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/memory/singleton.h" | 12 #include "base/memory/singleton.h" |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/prefs/pref_service.h" | 14 #include "base/prefs/pref_service.h" |
| 15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 18 #include "base/threading/non_thread_safe.h" | 18 #include "base/threading/non_thread_safe.h" |
| 19 #include "chrome/browser/devtools/devtools_protocol.h" | 19 #include "chrome/browser/devtools/devtools_protocol.h" |
| 20 #include "chrome/browser/devtools/devtools_protocol_constants.h" |
| 20 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 21 #include "chrome/common/pref_names.h" | 22 #include "chrome/common/pref_names.h" |
| 22 #include "components/keyed_service/content/browser_context_dependency_manager.h" | 23 #include "components/keyed_service/content/browser_context_dependency_manager.h" |
| 23 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
| 24 #include "net/base/address_list.h" | 25 #include "net/base/address_list.h" |
| 25 #include "net/base/io_buffer.h" | 26 #include "net/base/io_buffer.h" |
| 26 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
| 27 #include "net/base/net_util.h" | 28 #include "net/base/net_util.h" |
| 28 #include "net/dns/host_resolver.h" | 29 #include "net/dns/host_resolver.h" |
| 29 #include "net/socket/tcp_client_socket.h" | 30 #include "net/socket/tcp_client_socket.h" |
| 30 | 31 |
| 31 using content::BrowserThread; | 32 using content::BrowserThread; |
| 32 | 33 |
| 33 namespace { | 34 namespace { |
| 34 | 35 |
| 35 const int kBufferSize = 16 * 1024; | 36 const int kBufferSize = 16 * 1024; |
| 36 | 37 |
| 37 enum { | 38 enum { |
| 38 kStatusError = -3, | 39 kStatusError = -3, |
| 39 kStatusDisconnecting = -2, | 40 kStatusDisconnecting = -2, |
| 40 kStatusConnecting = -1, | 41 kStatusConnecting = -1, |
| 41 kStatusOK = 0, | 42 kStatusOK = 0, |
| 42 // Positive values are used to count open connections. | 43 // Positive values are used to count open connections. |
| 43 }; | 44 }; |
| 44 | 45 |
| 45 static const char kPortAttribute[] = "port"; | 46 namespace tethering = ::chrome::devtools::Tethering; |
| 46 static const char kConnectionIdAttribute[] = "connectionId"; | |
| 47 static const char kTetheringAccepted[] = "Tethering.accepted"; | |
| 48 static const char kTetheringBind[] = "Tethering.bind"; | |
| 49 static const char kTetheringUnbind[] = "Tethering.unbind"; | |
| 50 | 47 |
| 51 static const char kDevToolsRemoteBrowserTarget[] = "/devtools/browser"; | 48 static const char kDevToolsRemoteBrowserTarget[] = "/devtools/browser"; |
| 52 const int kMinVersionPortForwarding = 28; | 49 const int kMinVersionPortForwarding = 28; |
| 53 | 50 |
| 54 class SocketTunnel : public base::NonThreadSafe { | 51 class SocketTunnel : public base::NonThreadSafe { |
| 55 public: | 52 public: |
| 56 typedef base::Callback<void(int)> CounterCallback; | 53 typedef base::Callback<void(int)> CounterCallback; |
| 57 | 54 |
| 58 static void StartTunnel(const std::string& host, | 55 static void StartTunnel(const std::string& host, |
| 59 int port, | 56 int port, |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 if (registry_) { | 340 if (registry_) { |
| 344 DCHECK(registry_->find(device_->serial()) != registry_->end()); | 341 DCHECK(registry_->find(device_->serial()) != registry_->end()); |
| 345 registry_->erase(device_->serial()); | 342 registry_->erase(device_->serial()); |
| 346 } | 343 } |
| 347 } | 344 } |
| 348 | 345 |
| 349 void PortForwardingController::Connection::UpdateForwardingMap( | 346 void PortForwardingController::Connection::UpdateForwardingMap( |
| 350 const ForwardingMap& new_forwarding_map) { | 347 const ForwardingMap& new_forwarding_map) { |
| 351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 352 if (connected_) { | 349 if (connected_) { |
| 353 SerializeChanges(kTetheringUnbind, new_forwarding_map, forwarding_map_); | 350 SerializeChanges(tethering::unbind::kName, |
| 354 SerializeChanges(kTetheringBind, forwarding_map_, new_forwarding_map); | 351 new_forwarding_map, forwarding_map_); |
| 352 SerializeChanges(tethering::bind::kName, |
| 353 forwarding_map_, new_forwarding_map); |
| 355 } | 354 } |
| 356 forwarding_map_ = new_forwarding_map; | 355 forwarding_map_ = new_forwarding_map; |
| 357 } | 356 } |
| 358 | 357 |
| 359 void PortForwardingController::Connection::SerializeChanges( | 358 void PortForwardingController::Connection::SerializeChanges( |
| 360 const std::string& method, | 359 const std::string& method, |
| 361 const ForwardingMap& old_map, | 360 const ForwardingMap& old_map, |
| 362 const ForwardingMap& new_map) { | 361 const ForwardingMap& new_map) { |
| 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 364 for (ForwardingMap::const_iterator new_it(new_map.begin()); | 363 for (ForwardingMap::const_iterator new_it(new_map.begin()); |
| 365 new_it != new_map.end(); ++new_it) { | 364 new_it != new_map.end(); ++new_it) { |
| 366 int port = new_it->first; | 365 int port = new_it->first; |
| 367 const std::string& location = new_it->second; | 366 const std::string& location = new_it->second; |
| 368 ForwardingMap::const_iterator old_it = old_map.find(port); | 367 ForwardingMap::const_iterator old_it = old_map.find(port); |
| 369 if (old_it != old_map.end() && old_it->second == location) | 368 if (old_it != old_map.end() && old_it->second == location) |
| 370 continue; // The port points to the same location in both configs, skip. | 369 continue; // The port points to the same location in both configs, skip. |
| 371 | 370 |
| 372 SendCommand(method, port); | 371 SendCommand(method, port); |
| 373 } | 372 } |
| 374 } | 373 } |
| 375 | 374 |
| 376 void PortForwardingController::Connection::SendCommand( | 375 void PortForwardingController::Connection::SendCommand( |
| 377 const std::string& method, int port) { | 376 const std::string& method, int port) { |
| 378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 379 base::DictionaryValue params; | 378 base::DictionaryValue params; |
| 380 params.SetInteger(kPortAttribute, port); | 379 if (method == tethering::bind::kName) { |
| 380 params.SetInteger(tethering::bind::kParamPort, port); |
| 381 } else { |
| 382 DCHECK_EQ(tethering::unbind::kName, method); |
| 383 params.SetInteger(tethering::unbind::kParamPort, port); |
| 384 } |
| 381 DevToolsProtocol::Command command(++command_id_, method, ¶ms); | 385 DevToolsProtocol::Command command(++command_id_, method, ¶ms); |
| 382 | 386 |
| 383 if (method == kTetheringBind) { | 387 if (method == tethering::bind::kName) { |
| 384 pending_responses_[command.id()] = | 388 pending_responses_[command.id()] = |
| 385 base::Bind(&Connection::ProcessBindResponse, | 389 base::Bind(&Connection::ProcessBindResponse, |
| 386 base::Unretained(this), port); | 390 base::Unretained(this), port); |
| 387 #if defined(DEBUG_DEVTOOLS) | 391 #if defined(DEBUG_DEVTOOLS) |
| 388 port_status_[port] = kStatusConnecting; | 392 port_status_[port] = kStatusConnecting; |
| 389 #endif // defined(DEBUG_DEVTOOLS) | 393 #endif // defined(DEBUG_DEVTOOLS) |
| 390 } else { | 394 } else { |
| 391 DCHECK_EQ(kTetheringUnbind, method); | |
| 392 | |
| 393 PortStatusMap::iterator it = port_status_.find(port); | 395 PortStatusMap::iterator it = port_status_.find(port); |
| 394 if (it != port_status_.end() && it->second == kStatusError) { | 396 if (it != port_status_.end() && it->second == kStatusError) { |
| 395 // The bind command failed on this port, do not attempt unbind. | 397 // The bind command failed on this port, do not attempt unbind. |
| 396 port_status_.erase(it); | 398 port_status_.erase(it); |
| 397 return; | 399 return; |
| 398 } | 400 } |
| 399 | 401 |
| 400 pending_responses_[command.id()] = | 402 pending_responses_[command.id()] = |
| 401 base::Bind(&Connection::ProcessUnbindResponse, | 403 base::Bind(&Connection::ProcessUnbindResponse, |
| 402 base::Unretained(this), port); | 404 base::Unretained(this), port); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 } | 468 } |
| 467 | 469 |
| 468 void PortForwardingController::Connection::OnSocketOpened() { | 470 void PortForwardingController::Connection::OnSocketOpened() { |
| 469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 471 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 470 if (!registry_) { | 472 if (!registry_) { |
| 471 // Socket was created after Shutdown was called. Disconnect immediately. | 473 // Socket was created after Shutdown was called. Disconnect immediately. |
| 472 web_socket_->Disconnect(); | 474 web_socket_->Disconnect(); |
| 473 return; | 475 return; |
| 474 } | 476 } |
| 475 connected_ = true; | 477 connected_ = true; |
| 476 SerializeChanges(kTetheringBind, ForwardingMap(), forwarding_map_); | 478 SerializeChanges(tethering::bind::kName, ForwardingMap(), forwarding_map_); |
| 477 } | 479 } |
| 478 | 480 |
| 479 void PortForwardingController::Connection::OnSocketClosed( | 481 void PortForwardingController::Connection::OnSocketClosed( |
| 480 bool closed_by_device) { | 482 bool closed_by_device) { |
| 481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 482 Release(); // Balanced in the constructor. | 484 Release(); // Balanced in the constructor. |
| 483 } | 485 } |
| 484 | 486 |
| 485 void PortForwardingController::Connection::OnFrameRead( | 487 void PortForwardingController::Connection::OnFrameRead( |
| 486 const std::string& message) { | 488 const std::string& message) { |
| 487 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 489 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 488 if (ProcessResponse(message)) | 490 if (ProcessResponse(message)) |
| 489 return; | 491 return; |
| 490 | 492 |
| 491 scoped_ptr<DevToolsProtocol::Notification> notification( | 493 scoped_ptr<DevToolsProtocol::Notification> notification( |
| 492 DevToolsProtocol::ParseNotification(message)); | 494 DevToolsProtocol::ParseNotification(message)); |
| 493 if (!notification) | 495 if (!notification) |
| 494 return; | 496 return; |
| 495 | 497 |
| 496 if (notification->method() != kTetheringAccepted) | 498 if (notification->method() != tethering::accepted::kName) |
| 497 return; | 499 return; |
| 498 | 500 |
| 499 base::DictionaryValue* params = notification->params(); | 501 base::DictionaryValue* params = notification->params(); |
| 500 if (!params) | 502 if (!params) |
| 501 return; | 503 return; |
| 502 | 504 |
| 503 int port; | 505 int port; |
| 504 std::string connection_id; | 506 std::string connection_id; |
| 505 if (!params->GetInteger(kPortAttribute, &port) || | 507 if (!params->GetInteger(tethering::accepted::kParamPort, &port) || |
| 506 !params->GetString(kConnectionIdAttribute, &connection_id)) | 508 !params->GetString(tethering::accepted::kParamConnectionId, |
| 509 &connection_id)) |
| 507 return; | 510 return; |
| 508 | 511 |
| 509 std::map<int, std::string>::iterator it = forwarding_map_.find(port); | 512 std::map<int, std::string>::iterator it = forwarding_map_.find(port); |
| 510 if (it == forwarding_map_.end()) | 513 if (it == forwarding_map_.end()) |
| 511 return; | 514 return; |
| 512 | 515 |
| 513 std::string location = it->second; | 516 std::string location = it->second; |
| 514 std::vector<std::string> tokens; | 517 std::vector<std::string> tokens; |
| 515 Tokenize(location, ":", &tokens); | 518 Tokenize(location, ":", &tokens); |
| 516 int destination_port = 0; | 519 int destination_port = 0; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 void PortForwardingController::UpdateConnections() { | 598 void PortForwardingController::UpdateConnections() { |
| 596 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) | 599 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) |
| 597 it->second->UpdateForwardingMap(forwarding_map_); | 600 it->second->UpdateForwardingMap(forwarding_map_); |
| 598 } | 601 } |
| 599 | 602 |
| 600 void PortForwardingController::ShutdownConnections() { | 603 void PortForwardingController::ShutdownConnections() { |
| 601 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) | 604 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) |
| 602 it->second->Shutdown(); | 605 it->second->Shutdown(); |
| 603 registry_.clear(); | 606 registry_.clear(); |
| 604 } | 607 } |
| OLD | NEW |