Supports DevTools socket access authentication based on Android permissions.

BUG=399567

Review URL: https://codereview.chromium.org/382143005

Cr-Commit-Position: refs/heads/master@{#288273}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288273 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/socket/unix_domain_client_socket_posix_unittest.cc b/net/socket/unix_domain_client_socket_posix_unittest.cc
index d791122..d22aaf6 100644
--- a/net/socket/unix_domain_client_socket_posix_unittest.cc
+++ b/net/socket/unix_domain_client_socket_posix_unittest.cc
@@ -21,10 +21,14 @@
 
 const char kSocketFilename[] = "socket_for_testing";
 
-bool UserCanConnectCallback(bool allow_user, uid_t uid, gid_t gid) {
+bool UserCanConnectCallback(
+    bool allow_user, const UnixDomainServerSocket::Credentials& credentials) {
   // Here peers are running in same process.
-  EXPECT_EQ(getuid(), uid);
-  EXPECT_EQ(getgid(), gid);
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  EXPECT_EQ(getpid(), credentials.process_id);
+#endif
+  EXPECT_EQ(getuid(), credentials.user_id);
+  EXPECT_EQ(getgid(), credentials.group_id);
   return allow_user;
 }
 
diff --git a/net/socket/unix_domain_listen_socket_posix.cc b/net/socket/unix_domain_listen_socket_posix.cc
index 7bab4ff..dc7c19c9 100644
--- a/net/socket/unix_domain_listen_socket_posix.cc
+++ b/net/socket/unix_domain_listen_socket_posix.cc
@@ -113,10 +113,9 @@
   SocketDescriptor conn = StreamListenSocket::AcceptSocket();
   if (conn == kInvalidSocket)
     return;
-  uid_t user_id;
-  gid_t group_id;
-  if (!UnixDomainServerSocket::GetPeerIds(conn, &user_id, &group_id) ||
-      !auth_callback_.Run(user_id, group_id)) {
+  UnixDomainServerSocket::Credentials credentials;
+  if (!UnixDomainServerSocket::GetPeerCredentials(conn, &credentials) ||
+      !auth_callback_.Run(credentials)) {
     if (IGNORE_EINTR(close(conn)) < 0)
       LOG(ERROR) << "close() error";
     return;
diff --git a/net/socket/unix_domain_listen_socket_posix_unittest.cc b/net/socket/unix_domain_listen_socket_posix_unittest.cc
index 5fe50173..6fcbfd5 100644
--- a/net/socket/unix_domain_listen_socket_posix_unittest.cc
+++ b/net/socket/unix_domain_listen_socket_posix_unittest.cc
@@ -138,7 +138,7 @@
 
 bool UserCanConnectCallback(
     bool allow_user, const scoped_refptr<EventManager>& event_manager,
-    uid_t, gid_t) {
+    const UnixDomainServerSocket::Credentials&) {
   event_manager->Notify(
       allow_user ? EVENT_AUTH_GRANTED : EVENT_AUTH_DENIED);
   return allow_user;
diff --git a/net/socket/unix_domain_server_socket_posix.cc b/net/socket/unix_domain_server_socket_posix.cc
index 8f2f2d6..a81f1ce03 100644
--- a/net/socket/unix_domain_server_socket_posix.cc
+++ b/net/socket/unix_domain_server_socket_posix.cc
@@ -28,19 +28,20 @@
 }
 
 // static
-bool UnixDomainServerSocket::GetPeerIds(SocketDescriptor socket,
-                                        uid_t* user_id,
-                                        gid_t* group_id) {
+bool UnixDomainServerSocket::GetPeerCredentials(SocketDescriptor socket,
+                                                Credentials* credentials) {
 #if defined(OS_LINUX) || defined(OS_ANDROID)
   struct ucred user_cred;
   socklen_t len = sizeof(user_cred);
   if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &user_cred, &len) < 0)
     return false;
-  *user_id = user_cred.uid;
-  *group_id = user_cred.gid;
+  credentials->process_id = user_cred.pid;
+  credentials->user_id = user_cred.uid;
+  credentials->group_id = user_cred.gid;
   return true;
 #else
-  return getpeereid(socket, user_id, group_id) == 0;
+  return getpeereid(
+      socket, &credentials->user_id, &credentials->group_id) == 0;
 #endif
 }
 
@@ -130,10 +131,9 @@
     scoped_ptr<StreamSocket>* socket) {
   DCHECK(accept_socket_);
 
-  uid_t user_id;
-  gid_t group_id;
-  if (!GetPeerIds(accept_socket_->socket_fd(), &user_id, &group_id) ||
-      !auth_callback_.Run(user_id, group_id)) {
+  Credentials credentials;
+  if (!GetPeerCredentials(accept_socket_->socket_fd(), &credentials) ||
+      !auth_callback_.Run(credentials)) {
     accept_socket_.reset();
     return false;
   }
diff --git a/net/socket/unix_domain_server_socket_posix.h b/net/socket/unix_domain_server_socket_posix.h
index 06fb8d3..85c743d2 100644
--- a/net/socket/unix_domain_server_socket_posix.h
+++ b/net/socket/unix_domain_server_socket_posix.h
@@ -25,20 +25,30 @@
 // Linux and Android.
 class NET_EXPORT UnixDomainServerSocket : public ServerSocket {
  public:
+  // Credentials of a peer process connected to the socket.
+  struct NET_EXPORT Credentials {
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+    // Linux/Android API provides more information about the connected peer
+    // than Windows/OS X. It's useful for permission-based authorization on
+    // Android.
+    pid_t process_id;
+#endif
+    uid_t user_id;
+    gid_t group_id;
+  };
+
   // Callback that returns whether the already connected client, identified by
-  // its process |user_id| and |group_id|, is allowed to keep the connection
-  // open. Note that the socket is closed immediately in case the callback
-  // returns false.
-  typedef base::Callback<bool (uid_t user_id, gid_t group_id)> AuthCallback;
+  // its credentials, is allowed to keep the connection open. Note that
+  // the socket is closed immediately in case the callback returns false.
+  typedef base::Callback<bool (const Credentials&)> AuthCallback;
 
   UnixDomainServerSocket(const AuthCallback& auth_callack,
                          bool use_abstract_namespace);
   virtual ~UnixDomainServerSocket();
 
-  // Gets UID and GID of peer to check permissions.
-  static bool GetPeerIds(SocketDescriptor socket_fd,
-                         uid_t* user_id,
-                         gid_t* group_id);
+  // Gets credentials of peer to check permissions.
+  static bool GetPeerCredentials(SocketDescriptor socket_fd,
+                                 Credentials* credentials);
 
   // ServerSocket implementation.
   virtual int Listen(const IPEndPoint& address, int backlog) OVERRIDE;
diff --git a/net/socket/unix_domain_server_socket_posix_unittest.cc b/net/socket/unix_domain_server_socket_posix_unittest.cc
index 07209f6..d8a5281 100644
--- a/net/socket/unix_domain_server_socket_posix_unittest.cc
+++ b/net/socket/unix_domain_server_socket_posix_unittest.cc
@@ -24,10 +24,14 @@
 const char kSocketFilename[] = "socket_for_testing";
 const char kInvalidSocketPath[] = "/invalid/path";
 
-bool UserCanConnectCallback(bool allow_user, uid_t uid, gid_t gid) {
+bool UserCanConnectCallback(bool allow_user,
+    const UnixDomainServerSocket::Credentials& credentials) {
   // Here peers are running in same process.
-  EXPECT_EQ(getuid(), uid);
-  EXPECT_EQ(getgid(), gid);
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  EXPECT_EQ(getpid(), credentials.process_id);
+#endif
+  EXPECT_EQ(getuid(), credentials.user_id);
+  EXPECT_EQ(getgid(), credentials.group_id);
   return allow_user;
 }