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