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 |