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" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 const int kMinVersionPortForwarding = 28; | 52 const int kMinVersionPortForwarding = 28; |
53 | 53 |
54 class SocketTunnel : public base::NonThreadSafe { | 54 class SocketTunnel : public base::NonThreadSafe { |
55 public: | 55 public: |
56 typedef base::Callback<void(int)> CounterCallback; | 56 typedef base::Callback<void(int)> CounterCallback; |
57 | 57 |
58 static void StartTunnel(const std::string& host, | 58 static void StartTunnel(const std::string& host, |
59 int port, | 59 int port, |
60 const CounterCallback& callback, | 60 const CounterCallback& callback, |
61 int result, | 61 int result, |
62 scoped_ptr<net::StreamSocket> socket) { | 62 net::StreamSocket* socket) { |
63 if (result < 0) | 63 if (result < 0) |
64 return; | 64 return; |
65 SocketTunnel* tunnel = new SocketTunnel(callback); | 65 SocketTunnel* tunnel = new SocketTunnel(callback); |
66 tunnel->Start(socket.Pass(), host, port); | 66 tunnel->Start(socket, host, port); |
67 } | 67 } |
68 | 68 |
69 private: | 69 private: |
70 explicit SocketTunnel(const CounterCallback& callback) | 70 explicit SocketTunnel(const CounterCallback& callback) |
71 : pending_writes_(0), | 71 : pending_writes_(0), |
72 pending_destruction_(false), | 72 pending_destruction_(false), |
73 callback_(callback), | 73 callback_(callback), |
74 about_to_destroy_(false) { | 74 about_to_destroy_(false) { |
75 callback_.Run(1); | 75 callback_.Run(1); |
76 } | 76 } |
77 | 77 |
78 void Start(scoped_ptr<net::StreamSocket> socket, | 78 void Start(net::StreamSocket* socket, const std::string& host, int port) { |
79 const std::string& host, int port) { | 79 remote_socket_.reset(socket); |
80 remote_socket_.swap(socket); | |
81 | 80 |
82 host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL); | 81 host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL); |
83 net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); | 82 net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); |
84 int result = host_resolver_->Resolve( | 83 int result = host_resolver_->Resolve( |
85 request_info, | 84 request_info, |
86 net::DEFAULT_PRIORITY, | 85 net::DEFAULT_PRIORITY, |
87 &address_list_, | 86 &address_list_, |
88 base::Bind(&SocketTunnel::OnResolved, base::Unretained(this)), | 87 base::Bind(&SocketTunnel::OnResolved, base::Unretained(this)), |
89 NULL, | 88 NULL, |
90 net::BoundNetLog()); | 89 net::BoundNetLog()); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 best_browser = browser; | 247 best_browser = browser; |
249 newest_version = current_version; | 248 newest_version = current_version; |
250 } | 249 } |
251 } | 250 } |
252 return best_browser; | 251 return best_browser; |
253 } | 252 } |
254 | 253 |
255 } // namespace | 254 } // namespace |
256 | 255 |
257 class PortForwardingController::Connection | 256 class PortForwardingController::Connection |
258 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate { | 257 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate, |
| 258 public base::RefCountedThreadSafe< |
| 259 Connection, |
| 260 content::BrowserThread::DeleteOnUIThread> { |
259 public: | 261 public: |
260 Connection(Registry* registry, | 262 Connection(Registry* registry, |
261 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, | 263 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, |
262 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, | 264 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, |
263 const ForwardingMap& forwarding_map); | 265 const ForwardingMap& forwarding_map); |
264 virtual ~Connection(); | |
265 | 266 |
266 const PortStatusMap& GetPortStatusMap(); | 267 const PortStatusMap& GetPortStatusMap(); |
267 | 268 |
268 void UpdateForwardingMap(const ForwardingMap& new_forwarding_map); | 269 void UpdateForwardingMap(const ForwardingMap& new_forwarding_map); |
269 | 270 |
270 void Shutdown(); | 271 void Shutdown(); |
271 | 272 |
272 private: | 273 private: |
273 friend struct content::BrowserThread::DeleteOnThread< | 274 friend struct content::BrowserThread::DeleteOnThread< |
274 content::BrowserThread::UI>; | 275 content::BrowserThread::UI>; |
275 friend class base::DeleteHelper<Connection>; | 276 friend class base::DeleteHelper<Connection>; |
276 | 277 |
| 278 virtual ~Connection(); |
277 | 279 |
278 typedef std::map<int, std::string> ForwardingMap; | 280 typedef std::map<int, std::string> ForwardingMap; |
279 | 281 |
280 typedef base::Callback<void(PortStatus)> CommandCallback; | 282 typedef base::Callback<void(PortStatus)> CommandCallback; |
281 typedef std::map<int, CommandCallback> CommandCallbackMap; | 283 typedef std::map<int, CommandCallback> CommandCallbackMap; |
282 | 284 |
283 void SerializeChanges(const std::string& method, | 285 void SerializeChanges(const std::string& method, |
284 const ForwardingMap& old_map, | 286 const ForwardingMap& old_map, |
285 const ForwardingMap& new_map); | 287 const ForwardingMap& new_map); |
286 | 288 |
287 void SendCommand(const std::string& method, int port); | 289 void SendCommand(const std::string& method, int port); |
288 bool ProcessResponse(const std::string& json); | 290 bool ProcessResponse(const std::string& json); |
289 | 291 |
290 void ProcessBindResponse(int port, PortStatus status); | 292 void ProcessBindResponse(int port, PortStatus status); |
291 void ProcessUnbindResponse(int port, PortStatus status); | 293 void ProcessUnbindResponse(int port, PortStatus status); |
292 | 294 |
293 static void UpdateSocketCountOnHandlerThread( | 295 void UpdateSocketCountOnHandlerThread(int port, int increment); |
294 base::WeakPtr<Connection> weak_connection, int port, int increment); | |
295 void UpdateSocketCount(int port, int increment); | 296 void UpdateSocketCount(int port, int increment); |
296 | 297 |
297 // DevToolsAndroidBridge::AndroidWebSocket::Delegate implementation: | 298 // DevToolsAndroidBridge::AndroidWebSocket::Delegate implementation: |
298 virtual void OnSocketOpened() OVERRIDE; | 299 virtual void OnSocketOpened() OVERRIDE; |
299 virtual void OnFrameRead(const std::string& message) OVERRIDE; | 300 virtual void OnFrameRead(const std::string& message) OVERRIDE; |
300 virtual void OnSocketClosed() OVERRIDE; | 301 virtual void OnSocketClosed(bool closed_by_device) OVERRIDE; |
301 | 302 |
302 PortForwardingController::Registry* registry_; | 303 PortForwardingController::Registry* registry_; |
303 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device_; | 304 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device_; |
304 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser_; | 305 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser_; |
305 scoped_ptr<DevToolsAndroidBridge::AndroidWebSocket> web_socket_; | 306 scoped_refptr<DevToolsAndroidBridge::AndroidWebSocket> web_socket_; |
306 int command_id_; | 307 int command_id_; |
307 bool connected_; | 308 bool connected_; |
308 ForwardingMap forwarding_map_; | 309 ForwardingMap forwarding_map_; |
309 CommandCallbackMap pending_responses_; | 310 CommandCallbackMap pending_responses_; |
310 PortStatusMap port_status_; | 311 PortStatusMap port_status_; |
311 base::WeakPtrFactory<Connection> weak_factory_; | |
312 | 312 |
313 DISALLOW_COPY_AND_ASSIGN(Connection); | 313 DISALLOW_COPY_AND_ASSIGN(Connection); |
314 }; | 314 }; |
315 | 315 |
316 PortForwardingController::Connection::Connection( | 316 PortForwardingController::Connection::Connection( |
317 Registry* registry, | 317 Registry* registry, |
318 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, | 318 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, |
319 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, | 319 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, |
320 const ForwardingMap& forwarding_map) | 320 const ForwardingMap& forwarding_map) |
321 : registry_(registry), | 321 : registry_(registry), |
322 device_(device), | 322 device_(device), |
323 browser_(browser), | 323 browser_(browser), |
324 command_id_(0), | 324 command_id_(0), |
325 connected_(false), | 325 connected_(false), |
326 forwarding_map_(forwarding_map), | 326 forwarding_map_(forwarding_map) { |
327 weak_factory_(this) { | |
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
329 (*registry_)[device_->serial()] = this; | 328 (*registry_)[device_->serial()] = this; |
330 web_socket_.reset( | 329 web_socket_ = browser->CreateWebSocket(kDevToolsRemoteBrowserTarget, this); |
331 browser->CreateWebSocket(kDevToolsRemoteBrowserTarget, this)); | 330 web_socket_->Connect(); |
| 331 AddRef(); // Balanced in OnSocketClosed(); |
| 332 } |
| 333 |
| 334 void PortForwardingController::Connection::Shutdown() { |
| 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 336 registry_ = NULL; |
| 337 // This will have no effect if the socket is not connected yet. |
| 338 web_socket_->Disconnect(); |
332 } | 339 } |
333 | 340 |
334 PortForwardingController::Connection::~Connection() { | 341 PortForwardingController::Connection::~Connection() { |
335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
336 DCHECK(registry_->find(device_->serial()) != registry_->end()); | 343 if (registry_) { |
337 registry_->erase(device_->serial()); | 344 DCHECK(registry_->find(device_->serial()) != registry_->end()); |
| 345 registry_->erase(device_->serial()); |
| 346 } |
338 } | 347 } |
339 | 348 |
340 void PortForwardingController::Connection::UpdateForwardingMap( | 349 void PortForwardingController::Connection::UpdateForwardingMap( |
341 const ForwardingMap& new_forwarding_map) { | 350 const ForwardingMap& new_forwarding_map) { |
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
343 if (connected_) { | 352 if (connected_) { |
344 SerializeChanges(kTetheringUnbind, new_forwarding_map, forwarding_map_); | 353 SerializeChanges(kTetheringUnbind, new_forwarding_map, forwarding_map_); |
345 SerializeChanges(kTetheringBind, forwarding_map_, new_forwarding_map); | 354 SerializeChanges(kTetheringBind, forwarding_map_, new_forwarding_map); |
346 } | 355 } |
347 forwarding_map_ = new_forwarding_map; | 356 forwarding_map_ = new_forwarding_map; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 int port, PortStatus status) { | 433 int port, PortStatus status) { |
425 PortStatusMap::iterator it = port_status_.find(port); | 434 PortStatusMap::iterator it = port_status_.find(port); |
426 if (it == port_status_.end()) | 435 if (it == port_status_.end()) |
427 return; | 436 return; |
428 if (status == kStatusError) | 437 if (status == kStatusError) |
429 it->second = status; | 438 it->second = status; |
430 else | 439 else |
431 port_status_.erase(it); | 440 port_status_.erase(it); |
432 } | 441 } |
433 | 442 |
434 // static | |
435 void PortForwardingController::Connection::UpdateSocketCountOnHandlerThread( | 443 void PortForwardingController::Connection::UpdateSocketCountOnHandlerThread( |
436 base::WeakPtr<Connection> weak_connection, int port, int increment) { | 444 int port, int increment) { |
437 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 445 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
438 base::Bind(&Connection::UpdateSocketCount, | 446 base::Bind(&Connection::UpdateSocketCount, this, port, increment)); |
439 weak_connection, port, increment)); | |
440 } | 447 } |
441 | 448 |
442 void PortForwardingController::Connection::UpdateSocketCount( | 449 void PortForwardingController::Connection::UpdateSocketCount( |
443 int port, int increment) { | 450 int port, int increment) { |
444 #if defined(DEBUG_DEVTOOLS) | 451 #if defined(DEBUG_DEVTOOLS) |
445 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 452 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
446 PortStatusMap::iterator it = port_status_.find(port); | 453 PortStatusMap::iterator it = port_status_.find(port); |
447 if (it == port_status_.end()) | 454 if (it == port_status_.end()) |
448 return; | 455 return; |
449 if (it->second < 0 || (it->second == 0 && increment < 0)) | 456 if (it->second < 0 || (it->second == 0 && increment < 0)) |
450 return; | 457 return; |
451 it->second += increment; | 458 it->second += increment; |
452 #endif // defined(DEBUG_DEVTOOLS) | 459 #endif // defined(DEBUG_DEVTOOLS) |
453 } | 460 } |
454 | 461 |
455 const PortForwardingController::PortStatusMap& | 462 const PortForwardingController::PortStatusMap& |
456 PortForwardingController::Connection::GetPortStatusMap() { | 463 PortForwardingController::Connection::GetPortStatusMap() { |
457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
458 return port_status_; | 465 return port_status_; |
459 } | 466 } |
460 | 467 |
461 void PortForwardingController::Connection::OnSocketOpened() { | 468 void PortForwardingController::Connection::OnSocketOpened() { |
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 470 if (!registry_) { |
| 471 // Socket was created after Shutdown was called. Disconnect immediately. |
| 472 web_socket_->Disconnect(); |
| 473 return; |
| 474 } |
463 connected_ = true; | 475 connected_ = true; |
464 SerializeChanges(kTetheringBind, ForwardingMap(), forwarding_map_); | 476 SerializeChanges(kTetheringBind, ForwardingMap(), forwarding_map_); |
465 } | 477 } |
466 | 478 |
467 void PortForwardingController::Connection::OnSocketClosed() { | 479 void PortForwardingController::Connection::OnSocketClosed( |
468 delete this; | 480 bool closed_by_device) { |
| 481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 482 Release(); // Balanced in the constructor. |
469 } | 483 } |
470 | 484 |
471 void PortForwardingController::Connection::OnFrameRead( | 485 void PortForwardingController::Connection::OnFrameRead( |
472 const std::string& message) { | 486 const std::string& message) { |
473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 487 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
474 if (ProcessResponse(message)) | 488 if (ProcessResponse(message)) |
475 return; | 489 return; |
476 | 490 |
477 scoped_ptr<DevToolsProtocol::Notification> notification( | 491 scoped_ptr<DevToolsProtocol::Notification> notification( |
478 DevToolsProtocol::ParseNotification(message)); | 492 DevToolsProtocol::ParseNotification(message)); |
(...skipping 19 matching lines...) Expand all Loading... |
498 | 512 |
499 std::string location = it->second; | 513 std::string location = it->second; |
500 std::vector<std::string> tokens; | 514 std::vector<std::string> tokens; |
501 Tokenize(location, ":", &tokens); | 515 Tokenize(location, ":", &tokens); |
502 int destination_port = 0; | 516 int destination_port = 0; |
503 if (tokens.size() != 2 || !base::StringToInt(tokens[1], &destination_port)) | 517 if (tokens.size() != 2 || !base::StringToInt(tokens[1], &destination_port)) |
504 return; | 518 return; |
505 std::string destination_host = tokens[0]; | 519 std::string destination_host = tokens[0]; |
506 | 520 |
507 SocketTunnel::CounterCallback callback = | 521 SocketTunnel::CounterCallback callback = |
508 base::Bind(&Connection::UpdateSocketCountOnHandlerThread, | 522 base::Bind(&Connection::UpdateSocketCountOnHandlerThread, this, port); |
509 weak_factory_.GetWeakPtr(), port); | |
510 | 523 |
511 device_->OpenSocket( | 524 device_->OpenSocket( |
512 connection_id.c_str(), | 525 connection_id.c_str(), |
513 base::Bind(&SocketTunnel::StartTunnel, | 526 base::Bind(&SocketTunnel::StartTunnel, |
514 destination_host, | 527 destination_host, |
515 destination_port, | 528 destination_port, |
516 callback)); | 529 callback)); |
517 } | 530 } |
518 | 531 |
519 PortForwardingController::PortForwardingController(Profile* profile) | 532 PortForwardingController::PortForwardingController(Profile* profile) |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 dict->GetString(it.key(), &location)) | 599 dict->GetString(it.key(), &location)) |
587 forwarding_map_[port_num] = location; | 600 forwarding_map_[port_num] = location; |
588 } | 601 } |
589 } | 602 } |
590 | 603 |
591 if (!forwarding_map_.empty()) { | 604 if (!forwarding_map_.empty()) { |
592 StartListening(); | 605 StartListening(); |
593 UpdateConnections(); | 606 UpdateConnections(); |
594 } else { | 607 } else { |
595 StopListening(); | 608 StopListening(); |
596 STLDeleteValues(®istry_); | 609 ShutdownConnections(); |
597 NotifyListeners(DevicesStatus()); | 610 NotifyListeners(DevicesStatus()); |
598 } | 611 } |
599 } | 612 } |
600 | 613 |
601 void PortForwardingController::StartListening() { | 614 void PortForwardingController::StartListening() { |
602 if (listening_) | 615 if (listening_) |
603 return; | 616 return; |
604 listening_ = true; | 617 listening_ = true; |
605 DevToolsAndroidBridge* android_bridge = | 618 DevToolsAndroidBridge* android_bridge = |
606 DevToolsAndroidBridge::Factory::GetForProfile(profile_); | 619 DevToolsAndroidBridge::Factory::GetForProfile(profile_); |
(...skipping 10 matching lines...) Expand all Loading... |
617 DevToolsAndroidBridge::Factory::GetForProfile(profile_); | 630 DevToolsAndroidBridge::Factory::GetForProfile(profile_); |
618 if (android_bridge) | 631 if (android_bridge) |
619 android_bridge->RemoveDeviceListListener(this); | 632 android_bridge->RemoveDeviceListListener(this); |
620 } | 633 } |
621 | 634 |
622 void PortForwardingController::UpdateConnections() { | 635 void PortForwardingController::UpdateConnections() { |
623 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) | 636 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) |
624 it->second->UpdateForwardingMap(forwarding_map_); | 637 it->second->UpdateForwardingMap(forwarding_map_); |
625 } | 638 } |
626 | 639 |
| 640 void PortForwardingController::ShutdownConnections() { |
| 641 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) |
| 642 it->second->Shutdown(); |
| 643 registry_.clear(); |
| 644 } |
| 645 |
627 void PortForwardingController::NotifyListeners( | 646 void PortForwardingController::NotifyListeners( |
628 const DevicesStatus& status) const { | 647 const DevicesStatus& status) const { |
629 Listeners copy(listeners_); // Iterate over copy. | 648 Listeners copy(listeners_); // Iterate over copy. |
630 for (Listeners::const_iterator it = copy.begin(); it != copy.end(); ++it) | 649 for (Listeners::const_iterator it = copy.begin(); it != copy.end(); ++it) |
631 (*it)->PortStatusChanged(status); | 650 (*it)->PortStatusChanged(status); |
632 } | 651 } |
633 | 652 |
634 // static | 653 // static |
635 PortForwardingController::Factory* | 654 PortForwardingController::Factory* |
636 PortForwardingController::Factory::GetInstance() { | 655 PortForwardingController::Factory::GetInstance() { |
(...skipping 12 matching lines...) Expand all Loading... |
649 "PortForwardingController", | 668 "PortForwardingController", |
650 BrowserContextDependencyManager::GetInstance()) {} | 669 BrowserContextDependencyManager::GetInstance()) {} |
651 | 670 |
652 PortForwardingController::Factory::~Factory() {} | 671 PortForwardingController::Factory::~Factory() {} |
653 | 672 |
654 KeyedService* PortForwardingController::Factory::BuildServiceInstanceFor( | 673 KeyedService* PortForwardingController::Factory::BuildServiceInstanceFor( |
655 content::BrowserContext* context) const { | 674 content::BrowserContext* context) const { |
656 Profile* profile = Profile::FromBrowserContext(context); | 675 Profile* profile = Profile::FromBrowserContext(context); |
657 return new PortForwardingController(profile); | 676 return new PortForwardingController(profile); |
658 } | 677 } |
OLD | NEW |