Commit a0dea2e7 authored by mnaganov@chromium.org's avatar mnaganov@chromium.org

[Android] Use a "unique" remote debugging socket name on bind failure

When socket bind failure happens on enabling remote web debugging,
retry using a socket name with PID suffix to ensure uniquiness.
This allows several channels of Chrome to have remote web debugging
enabled simultaneously. Also, this preserves backwards compatibility,
as in the case of the single Chrome instance on a device, remote
debugging socket name is unchanged.

It seems easier to add retry functionality to UnixDomainSocket,
as DevToolsHttpHandler creation is heavily asynchronous.

BUG=222338

Review URL: https://chromiumcodereview.appspot.com/16093005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203132 0039d316-1c4b-4281-b951-d872f2087c98
parent 004df8a5
...@@ -30,6 +30,7 @@ AwDevToolsDelegate::AwDevToolsDelegate(content::BrowserContext* browser_context) ...@@ -30,6 +30,7 @@ AwDevToolsDelegate::AwDevToolsDelegate(content::BrowserContext* browser_context)
devtools_http_handler_ = content::DevToolsHttpHandler::Start( devtools_http_handler_ = content::DevToolsHttpHandler::Start(
new net::UnixDomainSocketWithAbstractNamespaceFactory( new net::UnixDomainSocketWithAbstractNamespaceFactory(
base::StringPrintf(kSocketNameFormat, getpid()), base::StringPrintf(kSocketNameFormat, getpid()),
"",
base::Bind(&content::CanUserConnectToDevTools)), base::Bind(&content::CanUserConnectToDevTools)),
"", "",
this); this);
......
...@@ -34,7 +34,7 @@ namespace { ...@@ -34,7 +34,7 @@ namespace {
const char kFrontEndURL[] = const char kFrontEndURL[] =
"http://chrome-devtools-frontend.appspot.com/static/%s/devtools.html"; "http://chrome-devtools-frontend.appspot.com/static/%s/devtools.html";
const char kDefaultSocketName[] = "chrome_devtools_remote"; const char kDefaultSocketName[] = "chrome_devtools_remote";
const char kTetheringSocketName[] = "chrome_devtools_tethering_%d"; const char kTetheringSocketName[] = "chrome_devtools_tethering_%d_%d";
// Delegate implementation for the devtools http handler on android. A new // Delegate implementation for the devtools http handler on android. A new
// instance of this gets created each time devtools is enabled. // instance of this gets created each time devtools is enabled.
...@@ -92,9 +92,11 @@ class DevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate { ...@@ -92,9 +92,11 @@ class DevToolsServerDelegate : public content::DevToolsHttpHandlerDelegate {
virtual scoped_refptr<net::StreamListenSocket> CreateSocketForTethering( virtual scoped_refptr<net::StreamListenSocket> CreateSocketForTethering(
net::StreamListenSocket::Delegate* delegate, net::StreamListenSocket::Delegate* delegate,
std::string* name) OVERRIDE { std::string* name) OVERRIDE {
*name = base::StringPrintf(kTetheringSocketName, ++last_tethering_socket_); *name = base::StringPrintf(
kTetheringSocketName, getpid(), ++last_tethering_socket_);
return net::UnixDomainSocket::CreateAndListenWithAbstractNamespace( return net::UnixDomainSocket::CreateAndListenWithAbstractNamespace(
*name, *name,
"",
delegate, delegate,
base::Bind(&content::CanUserConnectToDevTools)); base::Bind(&content::CanUserConnectToDevTools));
} }
...@@ -148,6 +150,7 @@ void DevToolsServer::Start() { ...@@ -148,6 +150,7 @@ void DevToolsServer::Start() {
protocol_handler_ = content::DevToolsHttpHandler::Start( protocol_handler_ = content::DevToolsHttpHandler::Start(
new net::UnixDomainSocketWithAbstractNamespaceFactory( new net::UnixDomainSocketWithAbstractNamespaceFactory(
socket_name_, socket_name_,
base::StringPrintf("%s_%d", socket_name_.c_str(), getpid()),
base::Bind(&content::CanUserConnectToDevTools)), base::Bind(&content::CanUserConnectToDevTools)),
use_bundled_frontend_resources_ ? use_bundled_frontend_resources_ ?
"" : "" :
......
...@@ -34,7 +34,7 @@ net::StreamListenSocketFactory* CreateSocketFactory() { ...@@ -34,7 +34,7 @@ net::StreamListenSocketFactory* CreateSocketFactory() {
switches::kRemoteDebuggingSocketName); switches::kRemoteDebuggingSocketName);
} }
return new net::UnixDomainSocketWithAbstractNamespaceFactory( return new net::UnixDomainSocketWithAbstractNamespaceFactory(
socket_name, base::Bind(&content::CanUserConnectToDevTools)); socket_name, "", base::Bind(&content::CanUserConnectToDevTools));
#else #else
// See if the user specified a port on the command line (useful for // See if the user specified a port on the command line (useful for
// automation). If not, use an ephemeral port by specifying 0. // automation). If not, use an ephemeral port by specifying 0.
......
...@@ -55,10 +55,13 @@ UnixDomainSocket::AuthCallback NoAuthentication() { ...@@ -55,10 +55,13 @@ UnixDomainSocket::AuthCallback NoAuthentication() {
// static // static
UnixDomainSocket* UnixDomainSocket::CreateAndListenInternal( UnixDomainSocket* UnixDomainSocket::CreateAndListenInternal(
const std::string& path, const std::string& path,
const std::string& fallback_path,
StreamListenSocket::Delegate* del, StreamListenSocket::Delegate* del,
const AuthCallback& auth_callback, const AuthCallback& auth_callback,
bool use_abstract_namespace) { bool use_abstract_namespace) {
SocketDescriptor s = CreateAndBind(path, use_abstract_namespace); SocketDescriptor s = CreateAndBind(path, use_abstract_namespace);
if (s == kInvalidSocket && !fallback_path.empty())
s = CreateAndBind(fallback_path, use_abstract_namespace);
if (s == kInvalidSocket) if (s == kInvalidSocket)
return NULL; return NULL;
UnixDomainSocket* sock = new UnixDomainSocket(s, del, auth_callback); UnixDomainSocket* sock = new UnixDomainSocket(s, del, auth_callback);
...@@ -71,7 +74,7 @@ scoped_refptr<UnixDomainSocket> UnixDomainSocket::CreateAndListen( ...@@ -71,7 +74,7 @@ scoped_refptr<UnixDomainSocket> UnixDomainSocket::CreateAndListen(
const std::string& path, const std::string& path,
StreamListenSocket::Delegate* del, StreamListenSocket::Delegate* del,
const AuthCallback& auth_callback) { const AuthCallback& auth_callback) {
return CreateAndListenInternal(path, del, auth_callback, false); return CreateAndListenInternal(path, "", del, auth_callback, false);
} }
#if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED) #if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED)
...@@ -79,10 +82,11 @@ scoped_refptr<UnixDomainSocket> UnixDomainSocket::CreateAndListen( ...@@ -79,10 +82,11 @@ scoped_refptr<UnixDomainSocket> UnixDomainSocket::CreateAndListen(
scoped_refptr<UnixDomainSocket> scoped_refptr<UnixDomainSocket>
UnixDomainSocket::CreateAndListenWithAbstractNamespace( UnixDomainSocket::CreateAndListenWithAbstractNamespace(
const std::string& path, const std::string& path,
const std::string& fallback_path,
StreamListenSocket::Delegate* del, StreamListenSocket::Delegate* del,
const AuthCallback& auth_callback) { const AuthCallback& auth_callback) {
return make_scoped_refptr( return make_scoped_refptr(
CreateAndListenInternal(path, del, auth_callback, true)); CreateAndListenInternal(path, fallback_path, del, auth_callback, true));
} }
#endif #endif
...@@ -160,7 +164,8 @@ UnixDomainSocketFactory::~UnixDomainSocketFactory() {} ...@@ -160,7 +164,8 @@ UnixDomainSocketFactory::~UnixDomainSocketFactory() {}
scoped_refptr<StreamListenSocket> UnixDomainSocketFactory::CreateAndListen( scoped_refptr<StreamListenSocket> UnixDomainSocketFactory::CreateAndListen(
StreamListenSocket::Delegate* delegate) const { StreamListenSocket::Delegate* delegate) const {
return UnixDomainSocket::CreateAndListen(path_, delegate, auth_callback_); return UnixDomainSocket::CreateAndListen(
path_, delegate, auth_callback_);
} }
#if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED) #if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED)
...@@ -168,8 +173,10 @@ scoped_refptr<StreamListenSocket> UnixDomainSocketFactory::CreateAndListen( ...@@ -168,8 +173,10 @@ scoped_refptr<StreamListenSocket> UnixDomainSocketFactory::CreateAndListen(
UnixDomainSocketWithAbstractNamespaceFactory:: UnixDomainSocketWithAbstractNamespaceFactory::
UnixDomainSocketWithAbstractNamespaceFactory( UnixDomainSocketWithAbstractNamespaceFactory(
const std::string& path, const std::string& path,
const std::string& fallback_path,
const UnixDomainSocket::AuthCallback& auth_callback) const UnixDomainSocket::AuthCallback& auth_callback)
: UnixDomainSocketFactory(path, auth_callback) {} : UnixDomainSocketFactory(path, auth_callback),
fallback_path_(fallback_path) {}
UnixDomainSocketWithAbstractNamespaceFactory:: UnixDomainSocketWithAbstractNamespaceFactory::
~UnixDomainSocketWithAbstractNamespaceFactory() {} ~UnixDomainSocketWithAbstractNamespaceFactory() {}
...@@ -178,7 +185,7 @@ scoped_refptr<StreamListenSocket> ...@@ -178,7 +185,7 @@ scoped_refptr<StreamListenSocket>
UnixDomainSocketWithAbstractNamespaceFactory::CreateAndListen( UnixDomainSocketWithAbstractNamespaceFactory::CreateAndListen(
StreamListenSocket::Delegate* delegate) const { StreamListenSocket::Delegate* delegate) const {
return UnixDomainSocket::CreateAndListenWithAbstractNamespace( return UnixDomainSocket::CreateAndListenWithAbstractNamespace(
path_, delegate, auth_callback_); path_, fallback_path_, delegate, auth_callback_);
} }
#endif #endif
......
...@@ -45,9 +45,11 @@ class NET_EXPORT UnixDomainSocket : public StreamListenSocket { ...@@ -45,9 +45,11 @@ class NET_EXPORT UnixDomainSocket : public StreamListenSocket {
#if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED) #if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED)
// Same as above except that the created socket uses the abstract namespace // Same as above except that the created socket uses the abstract namespace
// which is a Linux-only feature. // which is a Linux-only feature. If |fallback_path| is not empty,
// make the second attempt with the provided fallback name.
static scoped_refptr<UnixDomainSocket> CreateAndListenWithAbstractNamespace( static scoped_refptr<UnixDomainSocket> CreateAndListenWithAbstractNamespace(
const std::string& path, const std::string& path,
const std::string& fallback_path,
StreamListenSocket::Delegate* del, StreamListenSocket::Delegate* del,
const AuthCallback& auth_callback); const AuthCallback& auth_callback);
#endif #endif
...@@ -60,6 +62,7 @@ class NET_EXPORT UnixDomainSocket : public StreamListenSocket { ...@@ -60,6 +62,7 @@ class NET_EXPORT UnixDomainSocket : public StreamListenSocket {
static UnixDomainSocket* CreateAndListenInternal( static UnixDomainSocket* CreateAndListenInternal(
const std::string& path, const std::string& path,
const std::string& fallback_path,
StreamListenSocket::Delegate* del, StreamListenSocket::Delegate* del,
const AuthCallback& auth_callback, const AuthCallback& auth_callback,
bool use_abstract_namespace); bool use_abstract_namespace);
...@@ -103,6 +106,7 @@ class NET_EXPORT UnixDomainSocketWithAbstractNamespaceFactory ...@@ -103,6 +106,7 @@ class NET_EXPORT UnixDomainSocketWithAbstractNamespaceFactory
public: public:
UnixDomainSocketWithAbstractNamespaceFactory( UnixDomainSocketWithAbstractNamespaceFactory(
const std::string& path, const std::string& path,
const std::string& fallback_path,
const UnixDomainSocket::AuthCallback& auth_callback); const UnixDomainSocket::AuthCallback& auth_callback);
virtual ~UnixDomainSocketWithAbstractNamespaceFactory(); virtual ~UnixDomainSocketWithAbstractNamespaceFactory();
...@@ -111,6 +115,8 @@ class NET_EXPORT UnixDomainSocketWithAbstractNamespaceFactory ...@@ -111,6 +115,8 @@ class NET_EXPORT UnixDomainSocketWithAbstractNamespaceFactory
StreamListenSocket::Delegate* delegate) const OVERRIDE; StreamListenSocket::Delegate* delegate) const OVERRIDE;
private: private:
std::string fallback_path_;
DISALLOW_COPY_AND_ASSIGN(UnixDomainSocketWithAbstractNamespaceFactory); DISALLOW_COPY_AND_ASSIGN(UnixDomainSocketWithAbstractNamespaceFactory);
}; };
#endif #endif
......
...@@ -39,6 +39,7 @@ namespace net { ...@@ -39,6 +39,7 @@ namespace net {
namespace { namespace {
const char kSocketFilename[] = "unix_domain_socket_for_testing"; const char kSocketFilename[] = "unix_domain_socket_for_testing";
const char kFallbackSocketName[] = "unix_domain_socket_for_testing_2";
const char kInvalidSocketPath[] = "/invalid/path"; const char kInvalidSocketPath[] = "/invalid/path";
const char kMsg[] = "hello"; const char kMsg[] = "hello";
...@@ -51,10 +52,14 @@ enum EventType { ...@@ -51,10 +52,14 @@ enum EventType {
EVENT_READ, EVENT_READ,
}; };
string MakeSocketPath() { string MakeSocketPath(const string& socket_file_name) {
base::FilePath temp_dir; base::FilePath temp_dir;
file_util::GetTempDir(&temp_dir); file_util::GetTempDir(&temp_dir);
return temp_dir.Append(kSocketFilename).value(); return temp_dir.Append(socket_file_name).value();
}
string MakeSocketPath() {
return MakeSocketPath(kSocketFilename);
} }
class EventManager : public base::RefCounted<EventManager> { class EventManager : public base::RefCounted<EventManager> {
...@@ -254,8 +259,28 @@ TEST_F(UnixDomainSocketTestWithInvalidPath, CreateAndListenWithInvalidPath) { ...@@ -254,8 +259,28 @@ TEST_F(UnixDomainSocketTestWithInvalidPath, CreateAndListenWithInvalidPath) {
TEST_F(UnixDomainSocketTestWithInvalidPath, TEST_F(UnixDomainSocketTestWithInvalidPath,
CreateAndListenWithAbstractNamespace) { CreateAndListenWithAbstractNamespace) {
socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace( socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace(
file_path_.value(), socket_delegate_.get(), MakeAuthCallback()); file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
EXPECT_FALSE(socket_.get() == NULL);
}
TEST_F(UnixDomainSocketTest, TestFallbackName) {
scoped_refptr<UnixDomainSocket> existing_socket =
UnixDomainSocket::CreateAndListenWithAbstractNamespace(
file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
EXPECT_FALSE(existing_socket.get() == NULL);
// First, try to bind socket with the same name with no fallback name.
socket_ =
UnixDomainSocket::CreateAndListenWithAbstractNamespace(
file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
EXPECT_TRUE(socket_.get() == NULL);
// Now with a fallback name.
socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace(
file_path_.value(),
MakeSocketPath(kFallbackSocketName),
socket_delegate_.get(),
MakeAuthCallback());
EXPECT_FALSE(socket_.get() == NULL); EXPECT_FALSE(socket_.get() == NULL);
existing_socket = NULL;
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment