Cherry-pick "Fix a fd leak in NPChannelBase on Posix"

Bug 11384229

Patch taken from crrev.com/61893005 PS1

Original description:

Fix a fd leak in NPChannelBase on Posix

NPChannelBase::GetChannel is leaking file descriptor when requesting
a channel_handle which has the same key of a previous request but
conveys a different fd, causing a "leak" of opened file descriptors
in the renderer.
This is not a huge deal for Chrome, in which the renderer processes
are typically short lived (fd cleanup is performed by the OS on
their termination), but can be a problem for WebView.
A known NPChannel client which is exhibiting the fd leak issue is
the JavaBridgeDispatcher.

BUG=b/11384229

Change-Id: If7b9b8b9c4e7d64cb18cd96729d9b881bb7b1327
diff --git a/content/child/npapi/np_channel_base.cc b/content/child/npapi/np_channel_base.cc
index c8e32f3..6d12d7c 100644
--- a/content/child/npapi/np_channel_base.cc
+++ b/content/child/npapi/np_channel_base.cc
@@ -14,6 +14,7 @@
 #include "ipc/ipc_sync_message.h"
 
 #if defined(OS_POSIX)
+#include "base/file_util.h"
 #include "ipc/ipc_channel_posix.h"
 #endif
 
@@ -49,6 +50,14 @@
     const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode,
     ChannelFactory factory, base::MessageLoopProxy* ipc_message_loop,
     bool create_pipe_now, base::WaitableEvent* shutdown_event) {
+#if defined(OS_POSIX)
+  // On POSIX the channel_handle conveys an FD (socket) which is duped by the
+  // kernel during the IPC message exchange (via the SCM_RIGHTS mechanism).
+  // Ensure we do not leak this FD.
+  int fd = channel_handle.socket.auto_close ? channel_handle.socket.fd : -1;
+  file_util::ScopedFD auto_close_fd(&fd);
+#endif
+
   scoped_refptr<NPChannelBase> channel;
   std::string channel_key = channel_handle.name;
   ChannelMap::const_iterator iter = GetChannelMap()->find(channel_key);
@@ -62,6 +71,9 @@
 
   if (!channel->channel_valid()) {
     channel->channel_handle_ = channel_handle;
+#if defined(OS_POSIX)
+    ignore_result(auto_close_fd.release());
+#endif
     if (mode & IPC::Channel::MODE_SERVER_FLAG) {
       channel->channel_handle_.name =
           IPC::Channel::GenerateVerifiedChannelID(channel_key);