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