Bug 950660: Part 1: Support bind in TCPSocket from content process r=jdm
author"Chih-Kai (Patrick) Wang" <kk1fff@ckwang.info>
Mon, 05 Jan 2015 15:49:24 +0800
changeset 296089 3f9843c4493986cadab5b8435c233a8e43d9e9bb
parent 296088 e92fa2dcd9df9c4f63f50dc18fe0e32e8f0e7200
child 296090 af45bcfab412d2db786648f281d1e85faf1c09f1
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
bugs950660
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 950660: Part 1: Support bind in TCPSocket from content process r=jdm
dom/network/PTCPSocket.ipdl
dom/network/TCPSocketChild.cpp
dom/network/TCPSocketParent.cpp
dom/network/TCPSocketParent.h
--- a/dom/network/PTCPSocket.ipdl
+++ b/dom/network/PTCPSocket.ipdl
@@ -36,16 +36,22 @@ protocol PTCPSocket
   manager PNecko;
 
 parent:
   // Forward calling to child's open() method to parent, expect TCPOptions
   // is expanded to |useSSL| (from TCPOptions.useSecureTransport) and
   // |binaryType| (from TCPOption.binaryType).
   Open(nsString host, uint16_t port, bool useSSL, bool useArrayBuffers);
 
+  // Ask parent to open a socket and bind the newly-opened socket to a local
+  // address specified in |localAddr| and |localPort|.
+  OpenBind(nsCString host, uint16_t port,
+           nsCString localAddr, uint16_t localPort,
+           bool useSSL, nsCString binaryType);
+
   // When child's send() is called, this message requrests parent to send
   // data and update it's trackingNumber.
   Data(SendableData data, uint32_t trackingNumber);
 
   // Forward calling to child's upgradeToSecure() method to parent.
   StartTLS();
 
   // Forward calling to child's send() method to parent.
--- a/dom/network/TCPSocketChild.cpp
+++ b/dom/network/TCPSocketChild.cpp
@@ -97,16 +97,33 @@ TCPSocketChild::SendOpen(TCPSocket* aSoc
 {
   mSocket = aSocket;
 
   AddIPDLReference();
   gNeckoChild->SendPTCPSocketConstructor(this, mHost, mPort);
   PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
 }
 
+NS_IMETHODIMP
+TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketInternal* aSocket,
+                                       const nsACString& aRemoteHost, uint16_t aRemotePort,
+                                       const nsACString& aLocalHost, uint16_t aLocalPort,
+                                       bool aUseSSL)
+{
+  mSocket = aSocket;
+  AddIPDLReference();
+  gNeckoChild->SendPTCPSocketConstructor(this,
+                                         NS_ConvertUTF8toUTF16(aRemoteHost),
+                                         aRemotePort);
+  PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort,
+                                nsCString(aLocalHost), aLocalPort,
+                                aUseSSL, NS_LITERAL_CSTRING("arraybuffer"));
+  return NS_OK;
+}
+
 void
 TCPSocketChildBase::ReleaseIPDLReference()
 {
   MOZ_ASSERT(mIPCOpen);
   mIPCOpen = false;
   this->Release();
 }
 
@@ -142,16 +159,26 @@ TCPSocketChild::RecvCallback(const nsStr
 
   } else if (aData.type() == CallbackData::TTCPError) {
     const TCPError& err(aData.get_TCPError());
     mSocket->FireErrorEvent(err.name(), err.message());
 
   } else if (aData.type() == CallbackData::TSendableData) {
     const SendableData& data = aData.get_SendableData();
 
+    if (data.type() == SendableData::TArrayOfuint8_t) {
+      // See if we can pass array directly.
+      nsCOMPtr<nsITCPSocketInternalNative> nativeSocket = do_QueryInterface(mSocket);
+      if (nativeSocket) {
+        const InfallibleTArray<uint8_t>& buffer = data.get_ArrayOfuint8_t();
+        nativeSocket->CallListenerNativeArray(const_cast<uint8_t*>(buffer.Elements()),
+                                              buffer.Length());
+        return true;
+      }
+    }
     AutoJSAPI api;
     if (NS_WARN_IF(!api.Init(mSocket->GetOwner()))) {
       return true;
     }
     JSContext* cx = api.cx();
     JS::Rooted<JS::Value> val(cx);
 
     if (data.type() == SendableData::TArrayOfuint8_t) {
@@ -194,16 +221,23 @@ TCPSocketChild::SendSend(const ArrayBuff
   }
 
   InfallibleTArray<uint8_t> arr;
   arr.SwapElements(fallibleArr);
   SendData(arr, aTrackingNumber);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+TCPSocketChild::SendSendArray(nsTArray<uint8_t> *aArr, uint32_t aTrackingNumber)
+{
+  SendData(*aArr, aTrackingNumber);
+  return NS_OK;
+}
+
 void
 TCPSocketChild::SetSocket(TCPSocket* aSocket)
 {
   mSocket = aSocket;
 }
 
 void
 TCPSocketChild::GetHost(nsAString& aHost)
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -11,16 +11,18 @@
 #include "mozilla/unused.h"
 #include "mozilla/AppProcessChecker.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "mozilla/net/PNeckoParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/HoldDropJSObjects.h"
+#include "nsISocketTransportService.h"
+#include "nsISocketTransport.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 
 namespace IPC {
 
 //Defined in TCPSocketChild.cpp
 extern bool
 DeserializeArrayBuffer(JSContext* aCx,
@@ -166,16 +168,82 @@ TCPSocketParent::RecvOpen(const nsString
   mSocket = new TCPSocket(nullptr, aHost, aPort, aUseSSL, aUseArrayBuffers);
   mSocket->SetAppIdAndBrowser(appId, inBrowser);
   mSocket->SetSocketBridgeParent(this);
   NS_ENSURE_SUCCESS(mSocket->Init(), true);
   return true;
 }
 
 bool
+TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost,
+                              const uint16_t& aRemotePort,
+                              const nsCString& aLocalAddr,
+                              const uint16_t& aLocalPort,
+                              const bool&     aUseSSL,
+                              const nsCString& aBinaryType)
+{
+  if (net::UsingNeckoIPCSecurity() &&
+      !AssertAppProcessPermission(Manager()->Manager(), "tcp-socket")) {
+    FireInteralError(this, __LINE__);
+    return true;
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsISocketTransportService> sts =
+    do_GetService("@mozilla.org/network/socket-transport-service;1", &rv);
+  if (NS_FAILED(rv)) {
+    FireInteralError(this, __LINE__);
+    return true;
+  }
+
+  nsCOMPtr<nsISocketTransport> socketTransport;
+  rv = sts->CreateTransport(nullptr, 0,
+                            aRemoteHost, aRemotePort,
+                            nullptr, getter_AddRefs(socketTransport));
+  if (NS_FAILED(rv)) {
+    FireInteralError(this, __LINE__);
+    return true;
+  }
+
+  PRNetAddr prAddr;
+  if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr)) {
+    FireInteralError(this, __LINE__);
+    return true;
+  }
+  if (PR_SUCCESS != PR_StringToNetAddr(aLocalAddr.BeginReading(), &prAddr)) {
+    FireInteralError(this, __LINE__);
+    return true;
+  }
+
+  mozilla::net::NetAddr addr;
+  PRNetAddrToNetAddr(&prAddr, &addr);
+  rv = socketTransport->Bind(&addr);
+  if (NS_FAILED(rv)) {
+    FireInteralError(this, __LINE__);
+    return true;
+  }
+
+  // Obtain App ID
+  uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
+  const PContentParent *content = Manager()->Manager();
+  const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
+  if (browsers.Length() > 0) {
+    TabParent *tab = static_cast<TabParent*>(browsers[0]);
+    appId = tab->OwnAppId();
+  }
+
+  mSocket = new TCPSocket(nullptr, aRemoteHost, aRemotePort, aUseSSL,
+                          aBinaryType.EqualsLiteral("arraybuffer"));
+  mSocket->SetAppIdAndBrowser(appId, inBrowser);
+  mSocket->SetSocketBridgeParent(this);
+  NS_ENSURE_SUCCESS(mSocket->InitWithTransport(socketTransport), true);
+  return true;
+}
+
+bool
 TCPSocketParent::RecvStartTLS()
 {
   NS_ENSURE_TRUE(mSocket, true);
   ErrorResult rv;
   mSocket->UpgradeToSecure(rv);
   NS_ENSURE_FALSE(rv.Failed(), true);
   return true;
 }
--- a/dom/network/TCPSocketParent.h
+++ b/dom/network/TCPSocketParent.h
@@ -47,16 +47,23 @@ class TCPSocketParent : public mozilla::
 public:
   NS_IMETHOD_(MozExternalRefCountType) Release() override;
 
   TCPSocketParent() {}
 
   virtual bool RecvOpen(const nsString& aHost, const uint16_t& aPort,
                         const bool& useSSL, const bool& aUseArrayBuffers) override;
 
+  virtual bool RecvOpenBind(const nsCString& aRemoteHost,
+                            const uint16_t& aRemotePort,
+                            const nsCString& aLocalAddr,
+                            const uint16_t& aLocalPort,
+                            const bool&     aUseSSL,
+                            const nsCString& aBinaryType) override;
+
   virtual bool RecvStartTLS() override;
   virtual bool RecvSuspend() override;
   virtual bool RecvResume() override;
   virtual bool RecvClose() override;
   virtual bool RecvData(const SendableData& aData,
                         const uint32_t& aTrackingNumber) override;
   virtual bool RecvRequestDelete() override;
   virtual nsresult OfflineNotification(nsISupports *) override;