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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 const int kMinVersionPortForwarding = 28; | 49 const int kMinVersionPortForwarding = 28; |
50 | 50 |
51 class SocketTunnel : public base::NonThreadSafe { | 51 class SocketTunnel : public base::NonThreadSafe { |
52 public: | 52 public: |
53 typedef base::Callback<void(int)> CounterCallback; | 53 typedef base::Callback<void(int)> CounterCallback; |
54 | 54 |
55 static void StartTunnel(const std::string& host, | 55 static void StartTunnel(const std::string& host, |
56 int port, | 56 int port, |
57 const CounterCallback& callback, | 57 const CounterCallback& callback, |
58 int result, | 58 int result, |
59 net::StreamSocket* socket) { | 59 scoped_ptr<net::StreamSocket> socket) { |
60 if (result < 0) | 60 if (result < 0) |
61 return; | 61 return; |
62 SocketTunnel* tunnel = new SocketTunnel(callback); | 62 SocketTunnel* tunnel = new SocketTunnel(callback); |
63 tunnel->Start(socket, host, port); | 63 tunnel->Start(socket.Pass(), host, port); |
64 } | 64 } |
65 | 65 |
66 private: | 66 private: |
67 explicit SocketTunnel(const CounterCallback& callback) | 67 explicit SocketTunnel(const CounterCallback& callback) |
68 : pending_writes_(0), | 68 : pending_writes_(0), |
69 pending_destruction_(false), | 69 pending_destruction_(false), |
70 callback_(callback), | 70 callback_(callback), |
71 about_to_destroy_(false) { | 71 about_to_destroy_(false) { |
72 callback_.Run(1); | 72 callback_.Run(1); |
73 } | 73 } |
74 | 74 |
75 void Start(net::StreamSocket* socket, const std::string& host, int port) { | 75 void Start(scoped_ptr<net::StreamSocket> socket, |
76 remote_socket_.reset(socket); | 76 const std::string& host, int port) { |
77 remote_socket_.swap(socket); | |
77 | 78 |
78 host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL); | 79 host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL); |
79 net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); | 80 net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); |
80 int result = host_resolver_->Resolve( | 81 int result = host_resolver_->Resolve( |
81 request_info, | 82 request_info, |
82 net::DEFAULT_PRIORITY, | 83 net::DEFAULT_PRIORITY, |
83 &address_list_, | 84 &address_list_, |
84 base::Bind(&SocketTunnel::OnResolved, base::Unretained(this)), | 85 base::Bind(&SocketTunnel::OnResolved, base::Unretained(this)), |
85 NULL, | 86 NULL, |
86 net::BoundNetLog()); | 87 net::BoundNetLog()); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 best_browser = browser; | 245 best_browser = browser; |
245 newest_version = current_version; | 246 newest_version = current_version; |
246 } | 247 } |
247 } | 248 } |
248 return best_browser; | 249 return best_browser; |
249 } | 250 } |
250 | 251 |
251 } // namespace | 252 } // namespace |
252 | 253 |
253 class PortForwardingController::Connection | 254 class PortForwardingController::Connection |
254 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate, | 255 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate { |
255 public base::RefCountedThreadSafe< | |
256 Connection, | |
257 content::BrowserThread::DeleteOnUIThread> { | |
258 public: | 256 public: |
259 Connection(Registry* registry, | 257 Connection(Registry* registry, |
260 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, | 258 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, |
261 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, | 259 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, |
262 const ForwardingMap& forwarding_map); | 260 const ForwardingMap& forwarding_map); |
261 virtual ~Connection(); | |
263 | 262 |
264 const PortStatusMap& GetPortStatusMap(); | 263 const PortStatusMap& GetPortStatusMap(); |
265 | 264 |
266 void UpdateForwardingMap(const ForwardingMap& new_forwarding_map); | 265 void UpdateForwardingMap(const ForwardingMap& new_forwarding_map); |
267 | 266 |
268 void Shutdown(); | |
269 | |
270 private: | 267 private: |
271 friend struct content::BrowserThread::DeleteOnThread< | 268 friend struct content::BrowserThread::DeleteOnThread< |
272 content::BrowserThread::UI>; | 269 content::BrowserThread::UI>; |
273 friend class base::DeleteHelper<Connection>; | 270 friend class base::DeleteHelper<Connection>; |
274 | 271 |
275 virtual ~Connection(); | |
276 | 272 |
277 typedef std::map<int, std::string> ForwardingMap; | 273 typedef std::map<int, std::string> ForwardingMap; |
278 | 274 |
279 typedef base::Callback<void(PortStatus)> CommandCallback; | 275 typedef base::Callback<void(PortStatus)> CommandCallback; |
280 typedef std::map<int, CommandCallback> CommandCallbackMap; | 276 typedef std::map<int, CommandCallback> CommandCallbackMap; |
281 | 277 |
282 void SerializeChanges(const std::string& method, | 278 void SerializeChanges(const std::string& method, |
283 const ForwardingMap& old_map, | 279 const ForwardingMap& old_map, |
284 const ForwardingMap& new_map); | 280 const ForwardingMap& new_map); |
285 | 281 |
286 void SendCommand(const std::string& method, int port); | 282 void SendCommand(const std::string& method, int port); |
287 bool ProcessResponse(const std::string& json); | 283 bool ProcessResponse(const std::string& json); |
288 | 284 |
289 void ProcessBindResponse(int port, PortStatus status); | 285 void ProcessBindResponse(int port, PortStatus status); |
290 void ProcessUnbindResponse(int port, PortStatus status); | 286 void ProcessUnbindResponse(int port, PortStatus status); |
291 | 287 |
292 void UpdateSocketCountOnHandlerThread(int port, int increment); | 288 static void UpdateSocketCountOnHandlerThread( |
289 base::WeakPtr<Connection> weak_connection, int port, int increment); | |
293 void UpdateSocketCount(int port, int increment); | 290 void UpdateSocketCount(int port, int increment); |
294 | 291 |
295 // DevToolsAndroidBridge::AndroidWebSocket::Delegate implementation: | 292 // DevToolsAndroidBridge::AndroidWebSocket::Delegate implementation: |
296 virtual void OnSocketOpened() OVERRIDE; | 293 virtual void OnSocketOpened() OVERRIDE; |
297 virtual void OnFrameRead(const std::string& message) OVERRIDE; | 294 virtual void OnFrameRead(const std::string& message) OVERRIDE; |
298 virtual void OnSocketClosed(bool closed_by_device) OVERRIDE; | 295 virtual void OnSocketClosed() OVERRIDE; |
299 | 296 |
300 PortForwardingController::Registry* registry_; | 297 PortForwardingController::Registry* registry_; |
301 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device_; | 298 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device_; |
302 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser_; | 299 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser_; |
303 scoped_refptr<DevToolsAndroidBridge::AndroidWebSocket> web_socket_; | 300 scoped_ptr<DevToolsAndroidBridge::AndroidWebSocket> web_socket_; |
304 int command_id_; | 301 int command_id_; |
305 bool connected_; | 302 bool connected_; |
306 ForwardingMap forwarding_map_; | 303 ForwardingMap forwarding_map_; |
307 CommandCallbackMap pending_responses_; | 304 CommandCallbackMap pending_responses_; |
308 PortStatusMap port_status_; | 305 PortStatusMap port_status_; |
306 base::WeakPtrFactory<Connection> weak_factory_; | |
309 | 307 |
310 DISALLOW_COPY_AND_ASSIGN(Connection); | 308 DISALLOW_COPY_AND_ASSIGN(Connection); |
311 }; | 309 }; |
312 | 310 |
313 PortForwardingController::Connection::Connection( | 311 PortForwardingController::Connection::Connection( |
314 Registry* registry, | 312 Registry* registry, |
315 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, | 313 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> device, |
316 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, | 314 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, |
317 const ForwardingMap& forwarding_map) | 315 const ForwardingMap& forwarding_map) |
318 : registry_(registry), | 316 : registry_(registry), |
319 device_(device), | 317 device_(device), |
320 browser_(browser), | 318 browser_(browser), |
321 command_id_(0), | 319 command_id_(0), |
322 connected_(false), | 320 connected_(false), |
323 forwarding_map_(forwarding_map) { | 321 forwarding_map_(forwarding_map), |
322 weak_factory_(this) { | |
324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
325 (*registry_)[device_->serial()] = this; | 324 (*registry_)[device_->serial()] = this; |
326 web_socket_ = browser->CreateWebSocket(kDevToolsRemoteBrowserTarget, this); | 325 web_socket_.reset( |
327 web_socket_->Connect(); | 326 browser->CreateWebSocket(kDevToolsRemoteBrowserTarget, this)); |
328 AddRef(); // Balanced in OnSocketClosed(); | |
329 } | |
330 | |
331 void PortForwardingController::Connection::Shutdown() { | |
332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
333 registry_ = NULL; | |
334 // This will have no effect if the socket is not connected yet. | |
335 web_socket_->Disconnect(); | |
336 } | 327 } |
337 | 328 |
338 PortForwardingController::Connection::~Connection() { | 329 PortForwardingController::Connection::~Connection() { |
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
340 if (registry_) { | 331 DCHECK(registry_->find(device_->serial()) != registry_->end()); |
341 DCHECK(registry_->find(device_->serial()) != registry_->end()); | 332 registry_->erase(device_->serial()); |
342 registry_->erase(device_->serial()); | |
343 } | |
344 } | 333 } |
345 | 334 |
346 void PortForwardingController::Connection::UpdateForwardingMap( | 335 void PortForwardingController::Connection::UpdateForwardingMap( |
347 const ForwardingMap& new_forwarding_map) { | 336 const ForwardingMap& new_forwarding_map) { |
348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
349 if (connected_) { | 338 if (connected_) { |
350 SerializeChanges(tethering::unbind::kName, | 339 SerializeChanges(tethering::unbind::kName, |
351 new_forwarding_map, forwarding_map_); | 340 new_forwarding_map, forwarding_map_); |
352 SerializeChanges(tethering::bind::kName, | 341 SerializeChanges(tethering::bind::kName, |
353 forwarding_map_, new_forwarding_map); | 342 forwarding_map_, new_forwarding_map); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 int port, PortStatus status) { | 424 int port, PortStatus status) { |
436 PortStatusMap::iterator it = port_status_.find(port); | 425 PortStatusMap::iterator it = port_status_.find(port); |
437 if (it == port_status_.end()) | 426 if (it == port_status_.end()) |
438 return; | 427 return; |
439 if (status == kStatusError) | 428 if (status == kStatusError) |
440 it->second = status; | 429 it->second = status; |
441 else | 430 else |
442 port_status_.erase(it); | 431 port_status_.erase(it); |
443 } | 432 } |
444 | 433 |
434 // static | |
445 void PortForwardingController::Connection::UpdateSocketCountOnHandlerThread( | 435 void PortForwardingController::Connection::UpdateSocketCountOnHandlerThread( |
446 int port, int increment) { | 436 base::WeakPtr<Connection> weak_connection, int port, int increment) { |
447 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 437 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
448 base::Bind(&Connection::UpdateSocketCount, this, port, increment)); | 438 base::Bind(&Connection::UpdateSocketCount, |
439 weak_connection, port, increment)); | |
449 } | 440 } |
450 | 441 |
451 void PortForwardingController::Connection::UpdateSocketCount( | 442 void PortForwardingController::Connection::UpdateSocketCount( |
452 int port, int increment) { | 443 int port, int increment) { |
453 #if defined(DEBUG_DEVTOOLS) | 444 #if defined(DEBUG_DEVTOOLS) |
454 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 445 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
455 PortStatusMap::iterator it = port_status_.find(port); | 446 PortStatusMap::iterator it = port_status_.find(port); |
456 if (it == port_status_.end()) | 447 if (it == port_status_.end()) |
457 return; | 448 return; |
458 if (it->second < 0 || (it->second == 0 && increment < 0)) | 449 if (it->second < 0 || (it->second == 0 && increment < 0)) |
459 return; | 450 return; |
460 it->second += increment; | 451 it->second += increment; |
461 #endif // defined(DEBUG_DEVTOOLS) | 452 #endif // defined(DEBUG_DEVTOOLS) |
462 } | 453 } |
463 | 454 |
464 const PortForwardingController::PortStatusMap& | 455 const PortForwardingController::PortStatusMap& |
465 PortForwardingController::Connection::GetPortStatusMap() { | 456 PortForwardingController::Connection::GetPortStatusMap() { |
466 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
467 return port_status_; | 458 return port_status_; |
468 } | 459 } |
469 | 460 |
470 void PortForwardingController::Connection::OnSocketOpened() { | 461 void PortForwardingController::Connection::OnSocketOpened() { |
471 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
472 if (!registry_) { | |
473 // Socket was created after Shutdown was called. Disconnect immediately. | |
474 web_socket_->Disconnect(); | |
475 return; | |
476 } | |
477 connected_ = true; | 463 connected_ = true; |
478 SerializeChanges(tethering::bind::kName, ForwardingMap(), forwarding_map_); | 464 SerializeChanges(tethering::bind::kName, ForwardingMap(), forwarding_map_); |
479 } | 465 } |
480 | 466 |
481 void PortForwardingController::Connection::OnSocketClosed( | 467 void PortForwardingController::Connection::OnSocketClosed() { |
482 bool closed_by_device) { | 468 delete this; |
483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
484 Release(); // Balanced in the constructor. | |
485 } | 469 } |
486 | 470 |
487 void PortForwardingController::Connection::OnFrameRead( | 471 void PortForwardingController::Connection::OnFrameRead( |
488 const std::string& message) { | 472 const std::string& message) { |
489 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
490 if (ProcessResponse(message)) | 474 if (ProcessResponse(message)) |
491 return; | 475 return; |
492 | 476 |
493 scoped_ptr<DevToolsProtocol::Notification> notification( | 477 scoped_ptr<DevToolsProtocol::Notification> notification( |
494 DevToolsProtocol::ParseNotification(message)); | 478 DevToolsProtocol::ParseNotification(message)); |
(...skipping 20 matching lines...) Expand all Loading... | |
515 | 499 |
516 std::string location = it->second; | 500 std::string location = it->second; |
517 std::vector<std::string> tokens; | 501 std::vector<std::string> tokens; |
518 Tokenize(location, ":", &tokens); | 502 Tokenize(location, ":", &tokens); |
519 int destination_port = 0; | 503 int destination_port = 0; |
520 if (tokens.size() != 2 || !base::StringToInt(tokens[1], &destination_port)) | 504 if (tokens.size() != 2 || !base::StringToInt(tokens[1], &destination_port)) |
521 return; | 505 return; |
522 std::string destination_host = tokens[0]; | 506 std::string destination_host = tokens[0]; |
523 | 507 |
524 SocketTunnel::CounterCallback callback = | 508 SocketTunnel::CounterCallback callback = |
525 base::Bind(&Connection::UpdateSocketCountOnHandlerThread, this, port); | 509 base::Bind(&Connection::UpdateSocketCountOnHandlerThread, |
510 weak_factory_.GetWeakPtr(), port); | |
526 | 511 |
527 device_->OpenSocket( | 512 device_->OpenSocket( |
528 connection_id.c_str(), | 513 connection_id.c_str(), |
529 base::Bind(&SocketTunnel::StartTunnel, | 514 base::Bind(&SocketTunnel::StartTunnel, |
530 destination_host, | 515 destination_host, |
531 destination_port, | 516 destination_port, |
532 callback)); | 517 callback)); |
533 } | 518 } |
534 | 519 |
535 PortForwardingController::PortForwardingController(Profile* profile) | 520 PortForwardingController::PortForwardingController(Profile* profile) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
584 std::string location; | 569 std::string location; |
585 if (base::StringToInt(it.key(), &port_num) && | 570 if (base::StringToInt(it.key(), &port_num) && |
586 dict->GetString(it.key(), &location)) | 571 dict->GetString(it.key(), &location)) |
587 forwarding_map_[port_num] = location; | 572 forwarding_map_[port_num] = location; |
588 } | 573 } |
589 } | 574 } |
590 | 575 |
591 if (!forwarding_map_.empty()) { | 576 if (!forwarding_map_.empty()) { |
592 UpdateConnections(); | 577 UpdateConnections(); |
593 } else { | 578 } else { |
594 ShutdownConnections(); | 579 while (!registry_.empty()) { |
dgozman
2014/09/26 09:58:40
Let's make a copy vector of registry, and delete e
| |
580 delete registry_.begin()->second; | |
581 } | |
595 } | 582 } |
596 } | 583 } |
597 | 584 |
598 void PortForwardingController::UpdateConnections() { | 585 void PortForwardingController::UpdateConnections() { |
599 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) | 586 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) |
600 it->second->UpdateForwardingMap(forwarding_map_); | 587 it->second->UpdateForwardingMap(forwarding_map_); |
601 } | 588 } |
602 | |
603 void PortForwardingController::ShutdownConnections() { | |
604 for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it) | |
605 it->second->Shutdown(); | |
606 registry_.clear(); | |
607 } | |
OLD | NEW |