Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4470)

Unified Diff: chrome/browser/devtools/tethering_adb_filter.cc

Issue 23490021: Rename chrome/browser/devtools/tethering_adb_filter.* to port_forwarding_controller.* (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/devtools/tethering_adb_filter.cc
diff --git a/chrome/browser/devtools/tethering_adb_filter.cc b/chrome/browser/devtools/tethering_adb_filter.cc
deleted file mode 100644
index 9a06bfe6a00a5213b8069dad7e9885253788f826..0000000000000000000000000000000000000000
--- a/chrome/browser/devtools/tethering_adb_filter.cc
+++ /dev/null
@@ -1,594 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/devtools/tethering_adb_filter.h"
-
-#include <algorithm>
-#include <map>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "chrome/browser/devtools/adb_client_socket.h"
-#include "chrome/browser/devtools/adb_web_socket.h"
-#include "chrome/browser/devtools/devtools_protocol.h"
-#include "chrome/common/pref_names.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/address_list.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/dns/host_resolver.h"
-#include "net/socket/tcp_client_socket.h"
-
-using content::BrowserThread;
-
-namespace {
-
-const int kBufferSize = 16 * 1024;
-
-enum {
- kStatusError = -3,
- kStatusDisconnecting = -2,
- kStatusConnecting = -1,
- kStatusOK = 0,
- // Positive values are used to count open connections.
-};
-
-static const char kPortAttribute[] = "port";
-static const char kConnectionIdAttribute[] = "connectionId";
-static const char kTetheringAccepted[] = "Tethering.accepted";
-static const char kTetheringBind[] = "Tethering.bind";
-static const char kTetheringUnbind[] = "Tethering.unbind";
-
-static const char kChromeProductName[] = "Chrome";
-static const char kDevToolsRemoteBrowserTarget[] = "/devtools/browser";
-const int kMinVersionPortForwarding = 28;
-
-class SocketTunnel {
- public:
- typedef base::Callback<void(int)> CounterCallback;
-
- SocketTunnel(const std::string& location, const CounterCallback& callback)
- : location_(location),
- pending_writes_(0),
- pending_destruction_(false),
- callback_(callback),
- about_to_destroy_(false) {
- callback_.Run(1);
- }
-
- void Start(int result, net::StreamSocket* socket) {
- if (result < 0) {
- SelfDestruct();
- return;
- }
- remote_socket_.reset(socket);
-
- std::vector<std::string> tokens;
- Tokenize(location_, ":", &tokens);
- int port = 0;
- if (tokens.size() != 2 || !base::StringToInt(tokens[1], &port)) {
- SelfDestruct();
- return;
- }
-
- host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL);
- net::HostResolver::RequestInfo request_info(
- net::HostPortPair(tokens[0], port));
- result = host_resolver_->Resolve(
- request_info,
- net::DEFAULT_PRIORITY,
- &address_list_,
- base::Bind(&SocketTunnel::OnResolved, base::Unretained(this)),
- NULL,
- net::BoundNetLog());
- if (result != net::ERR_IO_PENDING)
- OnResolved(result);
- }
-
- private:
- void OnResolved(int result) {
- if (result < 0) {
- SelfDestruct();
- return;
- }
-
- host_socket_.reset(new net::TCPClientSocket(address_list_, NULL,
- net::NetLog::Source()));
- result = host_socket_->Connect(base::Bind(&SocketTunnel::OnConnected,
- base::Unretained(this)));
- if (result != net::ERR_IO_PENDING)
- OnConnected(result);
- }
-
- ~SocketTunnel() {
- about_to_destroy_ = true;
- if (host_socket_)
- host_socket_->Disconnect();
- if (remote_socket_)
- remote_socket_->Disconnect();
- callback_.Run(-1);
- }
-
- void OnConnected(int result) {
- if (result < 0) {
- SelfDestruct();
- return;
- }
-
- Pump(host_socket_.get(), remote_socket_.get());
- Pump(remote_socket_.get(), host_socket_.get());
- }
-
- void Pump(net::StreamSocket* from, net::StreamSocket* to) {
- scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
- int result = from->Read(
- buffer.get(),
- kBufferSize,
- base::Bind(
- &SocketTunnel::OnRead, base::Unretained(this), from, to, buffer));
- if (result != net::ERR_IO_PENDING)
- OnRead(from, to, buffer, result);
- }
-
- void OnRead(net::StreamSocket* from,
- net::StreamSocket* to,
- scoped_refptr<net::IOBuffer> buffer,
- int result) {
- if (result <= 0) {
- SelfDestruct();
- return;
- }
-
- int total = result;
- scoped_refptr<net::DrainableIOBuffer> drainable =
- new net::DrainableIOBuffer(buffer.get(), total);
-
- ++pending_writes_;
- result = to->Write(drainable.get(),
- total,
- base::Bind(&SocketTunnel::OnWritten,
- base::Unretained(this),
- drainable,
- from,
- to));
- if (result != net::ERR_IO_PENDING)
- OnWritten(drainable, from, to, result);
- }
-
- void OnWritten(scoped_refptr<net::DrainableIOBuffer> drainable,
- net::StreamSocket* from,
- net::StreamSocket* to,
- int result) {
- --pending_writes_;
- if (result < 0) {
- SelfDestruct();
- return;
- }
-
- drainable->DidConsume(result);
- if (drainable->BytesRemaining() > 0) {
- ++pending_writes_;
- result = to->Write(drainable.get(),
- drainable->BytesRemaining(),
- base::Bind(&SocketTunnel::OnWritten,
- base::Unretained(this),
- drainable,
- from,
- to));
- if (result != net::ERR_IO_PENDING)
- OnWritten(drainable, from, to, result);
- return;
- }
-
- if (pending_destruction_) {
- SelfDestruct();
- return;
- }
- Pump(from, to);
- }
-
- void SelfDestruct() {
- // In case one of the connections closes, we could get here
- // from another one due to Disconnect firing back on all
- // read callbacks.
- if (about_to_destroy_)
- return;
- if (pending_writes_ > 0) {
- pending_destruction_ = true;
- return;
- }
- delete this;
- }
-
- std::string location_;
- scoped_ptr<net::StreamSocket> remote_socket_;
- scoped_ptr<net::StreamSocket> host_socket_;
- scoped_ptr<net::HostResolver> host_resolver_;
- net::AddressList address_list_;
- int pending_writes_;
- bool pending_destruction_;
- CounterCallback callback_;
- bool about_to_destroy_;
-};
-
-typedef std::vector<int> ParsedVersion;
-
-static ParsedVersion ParseVersion(const std::string& version) {
- ParsedVersion result;
- std::vector<std::string> parts;
- Tokenize(version, ".", &parts);
- for (size_t i = 0; i != parts.size(); ++i) {
- int value = 0;
- base::StringToInt(parts[i], &value);
- result.push_back(value);
- }
- return result;
-}
-
-static bool IsVersionLower(const ParsedVersion& left,
- const ParsedVersion& right) {
- return std::lexicographical_compare(
- left.begin(), left.end(), right.begin(), right.end());
-}
-
-static bool IsPortForwardingSupported(const ParsedVersion& version) {
- return !version.empty() && version[0] >= kMinVersionPortForwarding;
-}
-
-static std::string FindBestSocketForTethering(
- const DevToolsAdbBridge::RemoteBrowsers browsers) {
- std::string socket;
- ParsedVersion newest_version;
- for (DevToolsAdbBridge::RemoteBrowsers::const_iterator it = browsers.begin();
- it != browsers.end(); ++it) {
- scoped_refptr<DevToolsAdbBridge::RemoteBrowser> browser = *it;
- ParsedVersion current_version = ParseVersion(browser->version());
- if (browser->product() == kChromeProductName &&
- IsPortForwardingSupported(current_version) &&
- IsVersionLower(newest_version, current_version)) {
- socket = browser->socket();
- newest_version = current_version;
- }
- }
- return socket;
-}
-
-} // namespace
-
-TetheringAdbFilter::TetheringAdbFilter(
- scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
- base::MessageLoop* adb_message_loop,
- PrefService* pref_service,
- scoped_refptr<AdbWebSocket> web_socket)
- : device_(device),
- adb_message_loop_(adb_message_loop),
- web_socket_(web_socket),
- command_id_(0) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- pref_change_registrar_.Init(pref_service);
-
- OnPrefsChange();
-
- base::Closure pref_callback = base::Bind(
- &TetheringAdbFilter::OnPrefsChange, base::Unretained(this));
- pref_change_registrar_.Add(
- prefs::kDevToolsPortForwardingEnabled, pref_callback);
- pref_change_registrar_.Add(
- prefs::kDevToolsPortForwardingConfig, pref_callback);
-}
-
-TetheringAdbFilter::~TetheringAdbFilter() {
-}
-
-void TetheringAdbFilter::OnPrefsChange() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- ForwardingMap new_forwarding_map;
-
- PrefService* pref_service = pref_change_registrar_.prefs();
- bool enabled =
- pref_service->GetBoolean(prefs::kDevToolsPortForwardingEnabled);
- if (enabled) {
- const DictionaryValue* dict =
- pref_service->GetDictionary(prefs::kDevToolsPortForwardingConfig);
- for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
- int port_num;
- std::string location;
- if (base::StringToInt(it.key(), &port_num) &&
- dict->GetString(it.key(), &location))
- new_forwarding_map[port_num] = location;
- }
- }
-
- adb_message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&TetheringAdbFilter::ChangeForwardingMap,
- this, new_forwarding_map));
-}
-
-void TetheringAdbFilter::ChangeForwardingMap(ForwardingMap new_forwarding_map) {
- DCHECK_EQ(base::MessageLoop::current(), adb_message_loop_);
-
- SerializeChanges(kTetheringUnbind, new_forwarding_map, forwarding_map_);
- SerializeChanges(kTetheringBind, forwarding_map_, new_forwarding_map);
- forwarding_map_ = new_forwarding_map;
-}
-
-void TetheringAdbFilter::SerializeChanges(const std::string& method,
- const ForwardingMap& old_map,
- const ForwardingMap& new_map) {
- for (ForwardingMap::const_iterator new_it(new_map.begin());
- new_it != new_map.end(); ++new_it) {
- int port = new_it->first;
- const std::string& location = new_it->second;
- ForwardingMap::const_iterator old_it = old_map.find(port);
- if (old_it != old_map.end() && old_it->second == location)
- continue; // The port points to the same location in both configs, skip.
-
- SendCommand(method, port);
- }
-}
-
-void TetheringAdbFilter::SendCommand(const std::string& method, int port) {
- base::DictionaryValue params;
- params.SetInteger(kPortAttribute, port);
- DevToolsProtocol::Command command(++command_id_, method, &params);
-
- if (method == kTetheringBind) {
- pending_responses_[command.id()] =
- base::Bind(&TetheringAdbFilter::ProcessBindResponse,
- base::Unretained(this), port);
-#if defined(DEBUG_DEVTOOLS)
- port_status_[port] = kStatusConnecting;
- UpdatePortStatusMap();
-#endif // defined(DEBUG_DEVTOOLS)
- } else {
- DCHECK_EQ(kTetheringUnbind, method);
-
- PortStatusMap::iterator it = port_status_.find(port);
- if (it != port_status_.end() && it->second == kStatusError) {
- // The bind command failed on this port, do not attempt unbind.
- port_status_.erase(it);
- UpdatePortStatusMap();
- return;
- }
-
- pending_responses_[command.id()] =
- base::Bind(&TetheringAdbFilter::ProcessUnbindResponse,
- base::Unretained(this), port);
-#if defined(DEBUG_DEVTOOLS)
- port_status_[port] = kStatusDisconnecting;
- UpdatePortStatusMap();
-#endif // defined(DEBUG_DEVTOOLS)
- }
-
- web_socket_->SendFrameOnHandlerThread(command.Serialize());
-}
-
-bool TetheringAdbFilter::ProcessResponse(const std::string& message) {
- scoped_ptr<DevToolsProtocol::Response> response(
- DevToolsProtocol::ParseResponse(message));
- if (!response)
- return false;
-
- CommandCallbackMap::iterator it = pending_responses_.find(response->id());
- if (it == pending_responses_.end())
- return false;
-
- it->second.Run(response->error_code() ? kStatusError : kStatusOK);
- pending_responses_.erase(it);
- return true;
-}
-
-void TetheringAdbFilter::ProcessBindResponse(int port, PortStatus status) {
- port_status_[port] = status;
- UpdatePortStatusMap();
-}
-
-void TetheringAdbFilter::ProcessUnbindResponse(int port, PortStatus status) {
- PortStatusMap::iterator it = port_status_.find(port);
- if (it == port_status_.end())
- return;
- if (status == kStatusError)
- it->second = status;
- else
- port_status_.erase(it);
- UpdatePortStatusMap();
-}
-
-void TetheringAdbFilter::UpdateSocketCount(int port, int increment) {
-#if defined(DEBUG_DEVTOOLS)
- PortStatusMap::iterator it = port_status_.find(port);
- if (it == port_status_.end())
- return;
- if (it->second < 0 || (it->second == 0 && increment < 0))
- return;
- it->second += increment;
- UpdatePortStatusMap();
-#endif // defined(DEBUG_DEVTOOLS)
-}
-
-void TetheringAdbFilter::UpdatePortStatusMap() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TetheringAdbFilter::UpdatePortStatusMapOnUIThread,
- this, port_status_));
-}
-
-void TetheringAdbFilter::UpdatePortStatusMapOnUIThread(
- const PortStatusMap& status_map) {
- port_status_on_ui_thread_ = status_map;
-}
-
-const TetheringAdbFilter::PortStatusMap&
-TetheringAdbFilter::GetPortStatusMap() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return port_status_on_ui_thread_;
-}
-
-bool TetheringAdbFilter::ProcessIncomingMessage(const std::string& message) {
- DCHECK_EQ(base::MessageLoop::current(), adb_message_loop_);
-
- if (ProcessResponse(message))
- return true;
-
- scoped_ptr<DevToolsProtocol::Notification> notification(
- DevToolsProtocol::ParseNotification(message));
- if (!notification)
- return false;
-
- if (notification->method() != kTetheringAccepted)
- return false;
-
- DictionaryValue* params = notification->params();
- if (!params)
- return false;
-
- int port;
- std::string connection_id;
- if (!params->GetInteger(kPortAttribute, &port) ||
- !params->GetString(kConnectionIdAttribute, &connection_id))
- return false;
-
- std::map<int, std::string>::iterator it = forwarding_map_.find(port);
- if (it == forwarding_map_.end())
- return false;
-
- std::string location = it->second;
-
- SocketTunnel* tunnel = new SocketTunnel(location,
- base::Bind(&TetheringAdbFilter::UpdateSocketCount, this, port));
-
- device_->OpenSocket(connection_id.c_str(),
- base::Bind(&SocketTunnel::Start, base::Unretained(tunnel)));
- return true;
-}
-
-class PortForwardingController::Connection : public AdbWebSocket::Delegate {
- public:
- Connection(
- Registry* registry,
- scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
- const std::string& socket,
- scoped_refptr<DevToolsAdbBridge> bridge,
- PrefService* pref_service);
-
- void Shutdown();
-
- TetheringAdbFilter::PortStatusMap port_status();
-
- private:
- virtual ~Connection();
-
- virtual void OnSocketOpened() OVERRIDE;
- virtual void OnFrameRead(const std::string& message) OVERRIDE;
- virtual void OnSocketClosed(bool closed_by_device) OVERRIDE;
- virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE;
-
- Registry* registry_;
- scoped_refptr<DevToolsAdbBridge::AndroidDevice> device_;
- scoped_refptr<DevToolsAdbBridge> bridge_;
- PrefService* pref_service_;
-
- scoped_refptr<TetheringAdbFilter> tethering_adb_filter_;
- scoped_refptr<AdbWebSocket> web_socket_;
-};
-
-PortForwardingController::Connection::Connection(
- Registry* registry,
- scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
- const std::string& socket,
- scoped_refptr<DevToolsAdbBridge> bridge,
- PrefService* pref_service)
- : registry_(registry),
- device_(device),
- bridge_(bridge),
- pref_service_(pref_service) {
- (*registry_)[device_->serial()] = this;
- web_socket_ = new AdbWebSocket(
- device, socket, kDevToolsRemoteBrowserTarget,
- bridge->GetAdbMessageLoop(), this);
-}
-
-void PortForwardingController::Connection::Shutdown() {
- registry_ = NULL;
- // This will have no effect if the socket is not connected yet.
- web_socket_->Disconnect();
-}
-
-TetheringAdbFilter::PortStatusMap
-PortForwardingController::Connection::port_status() {
- if (tethering_adb_filter_)
- return tethering_adb_filter_->GetPortStatusMap();
- else
- return TetheringAdbFilter::PortStatusMap();
-}
-
-PortForwardingController::Connection::~Connection() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (registry_) {
- DCHECK(registry_->find(device_->serial()) != registry_->end());
- registry_->erase(device_->serial());
- }
-}
-
-void PortForwardingController::Connection::OnSocketOpened() {
- if (!registry_) {
- // Socket was created after Shutdown was called. Disconnect immediately.
- web_socket_->Disconnect();
- return;
- }
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- tethering_adb_filter_ = new TetheringAdbFilter(
- device_, bridge_->GetAdbMessageLoop(), pref_service_, web_socket_);
-}
-
-void PortForwardingController::Connection::OnFrameRead(
- const std::string& message) {
-}
-
-void PortForwardingController::Connection::OnSocketClosed(
- bool closed_by_device) {
- delete this;
-}
-
-bool PortForwardingController::Connection::ProcessIncomingMessage(
- const std::string& message) {
- return tethering_adb_filter_->ProcessIncomingMessage(message);
-}
-
-
-PortForwardingController::PortForwardingController(
- scoped_refptr<DevToolsAdbBridge> bridge,
- PrefService* pref_service)
- : bridge_(bridge),
- pref_service_(pref_service) {
-}
-
-PortForwardingController::~PortForwardingController() {
- for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it)
- it->second->Shutdown();
-}
-
-void PortForwardingController::UpdateDeviceList(
- const DevToolsAdbBridge::RemoteDevices& devices) {
- for (DevToolsAdbBridge::RemoteDevices::const_iterator it = devices.begin();
- it != devices.end(); ++it) {
- Registry::iterator rit = registry_.find((*it)->serial());
- if (rit == registry_.end()) {
- std::string socket = FindBestSocketForTethering((*it)->browsers());
- if (!socket.empty() || (*it)->serial().empty()) {
- // Will delete itself when disconnected.
- new Connection(
- &registry_, (*it)->device(), socket, bridge_, pref_service_);
- }
- } else {
- (*it)->set_port_status((*rit).second->port_status());
- }
- }
-}

Powered by Google App Engine
This is Rietveld 408576698