Bug 950660: Part 2 - Change TCPSocket interface to TCPSocketChild and unbitrot r=jdm
authorRandell Jesup <rjesup@jesup.org>
Sun, 20 Sep 2015 23:05:20 -0400
changeset 296090 af45bcfab412d2db786648f281d1e85faf1c09f1
parent 296089 3f9843c4493986cadab5b8435c233a8e43d9e9bb
child 296091 dfaa6b689bc00d216add359d8ca8a8e40c65a109
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 2 - Change TCPSocket interface to TCPSocketChild and unbitrot r=jdm
dom/network/PTCPSocket.ipdl
dom/network/TCPSocket.cpp
dom/network/TCPSocket.h
dom/network/TCPSocketChild.cpp
dom/network/TCPSocketChild.h
dom/network/TCPSocketParent.cpp
dom/network/TCPSocketParent.h
--- a/dom/network/PTCPSocket.ipdl
+++ b/dom/network/PTCPSocket.ipdl
@@ -40,17 +40,17 @@ parent:
   // 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);
+           bool useSSL, bool aUseArrayBuffers);
 
   // 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();
 
--- a/dom/network/TCPSocket.cpp
+++ b/dom/network/TCPSocket.cpp
@@ -162,22 +162,24 @@ TCPSocket::TCPSocket(nsIGlobalObject* aG
   , mWaitingForStartTLS(false)
 #ifdef MOZ_WIDGET_GONK
   , mTxBytes(0)
   , mRxBytes(0)
   , mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
   , mInBrowser(false)
 #endif
 {
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal);
-  if (window && window->IsOuterWindow()) {
-    window = window->GetCurrentInnerWindow();
-  }
-  if (window) {
-    mInnerWindowID = window->WindowID();
+  if (aGlobal) {
+    nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal);
+    if (window && window->IsOuterWindow()) {
+      window = window->GetCurrentInnerWindow();
+    }
+    if (window) {
+      mInnerWindowID = window->WindowID();
+    }
   }
 }
 
 TCPSocket::~TCPSocket()
 {
 }
 
 nsresult
@@ -230,53 +232,63 @@ TCPSocket::CreateStream()
                                     BUFFER_SIZE,
                                     false, /* close source */
                                     false); /* close sink */
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 nsresult
+TCPSocket::InitWithUnconnectedTransport(nsISocketTransport* aTransport)
+{
+  mReadyState = TCPReadyState::Connecting;
+  mTransport = aTransport;
+
+  MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Content);
+
+  nsCOMPtr<nsIThread> mainThread;
+  NS_GetMainThread(getter_AddRefs(mainThread));
+  mTransport->SetEventSink(this, mainThread);
+
+  nsresult rv = CreateStream();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+nsresult
 TCPSocket::Init()
 {
   nsCOMPtr<nsIObserverService> obs = do_GetService("@mozilla.org/observer-service;1");
   if (obs) {
     obs->AddObserver(this, "inner-window-destroyed", true);
   }
 
-  mReadyState = TCPReadyState::Connecting;
-
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    mReadyState = TCPReadyState::Connecting;
     mSocketBridgeChild = new TCPSocketChild(mHost, mPort);
     mSocketBridgeChild->SendOpen(this, mSsl, mUseArrayBuffers);
     return NS_OK;
   }
 
   nsCOMPtr<nsISocketTransportService> sts =
     do_GetService("@mozilla.org/network/socket-transport-service;1");
 
   const char* socketTypes[1];
   if (mSsl) {
     socketTypes[0] = "ssl";
   } else {
     socketTypes[0] = "starttls";
   }
+  nsCOMPtr<nsISocketTransport> transport;
   nsresult rv = sts->CreateTransport(socketTypes, 1, NS_ConvertUTF16toUTF8(mHost), mPort,
-                                     nullptr, getter_AddRefs(mTransport));
+                                     nullptr, getter_AddRefs(transport));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIThread> mainThread;
-  NS_GetMainThread(getter_AddRefs(mainThread));
-
-  mTransport->SetEventSink(this, mainThread);
-
-  rv = CreateStream();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  return InitWithUnconnectedTransport(transport);
 }
 
 void
 TCPSocket::InitWithSocketChild(TCPSocketChild* aSocketBridge)
 {
   mSocketBridgeChild = aSocketBridge;
   mReadyState = TCPReadyState::Open;
   mSocketBridgeChild->SetSocket(this);
@@ -481,16 +493,50 @@ TCPSocket::FireEvent(const nsAString& aT
   if (NS_WARN_IF(!api.Init(GetOwner()))) {
     return;
   }
   JS::Rooted<JS::Value> val(api.cx());
   FireDataEvent(api.cx(), aType, val);
 }
 
 void
+TCPSocket::FireDataEvent(const nsAString& aType,
+                         const InfallibleTArray<uint8_t>& buffer)
+{
+  AutoJSAPI api;
+  if (NS_WARN_IF(!api.Init(GetOwner()))) {
+    return NS_ERROR_FAILURE;
+  }
+  JSContext* cx = api.cx();
+  JS::Rooted<JS::Value> val(cx);
+
+  bool ok = IPC::DeserializeArrayBuffer(cx, buffer, &val);
+  if (ok) {
+    FireDataEvent(aType, val);
+  }
+}
+
+void
+TCPSocket::FireDataEvent(const nsAString& aType,
+                         const nsACString& aString)
+{
+  AutoJSAPI api;
+  if (NS_WARN_IF(!api.Init(GetOwner()))) {
+    return NS_ERROR_FAILURE;
+  }
+  JSContext* cx = api.cx();
+  JS::Rooted<JS::Value> val(cx);
+
+  bool ok = ToJSValue(cx, NS_ConvertASCIItoUTF16(aString), &val);
+  if (ok) {
+    FireDataEvent(aType, val);
+  }
+}
+
+void
 TCPSocket::FireDataEvent(JSContext* aCx, const nsAString& aType, JS::Handle<JS::Value> aData)
 {
   MOZ_ASSERT(!mSocketBridgeParent);
 
   RootedDictionary<TCPSocketEventInit> init(aCx);
   init.mBubbles = false;
   init.mCancelable = false;
   init.mData = aData;
--- a/dom/network/TCPSocket.h
+++ b/dom/network/TCPSocket.h
@@ -159,18 +159,24 @@ public:
   void UpdateBufferedAmount(uint32_t aAmount, uint32_t aTrackingNumber);
   // Set this child socket's ready state, based on the state in the parent process.
   void UpdateReadyState(uint32_t aReadyState);
   // Dispatch an "error" event at this object.
   void FireErrorEvent(const nsAString& aName, const nsAString& aMessage);
   // Dispatch an event of the given type at this object.
   void FireEvent(const nsAString& aType);
   // Dispatch a "data" event at this object.
+  void FireDataEvent(const nsAString& aType, const InfallibleTArray<uint8_t>& buffer);
+  void FireDataEvent(const nsAString& aType, const nsAString& aString);
   void FireDataEvent(JSContext* aCx, const nsAString& aType, JS::Handle<JS::Value> aData);
 
+  // Initialize this socket from a low-level connection that hasn't connected yet
+  // (called from RecvOpenBind() in TCPSocketParent).
+  nsresult InitWithUnconnectedTransport(nsISocketTransport* aTransport);
+
 private:
   ~TCPSocket();
 
   // Initialize this socket with an existing IPC actor.
   void InitWithSocketChild(TCPSocketChild* aBridge);
   // Initialize this socket from an existing low-level connection.
   nsresult InitWithTransport(nsISocketTransport* aTransport);
   // Initialize the input/output streams for this socket object.
--- a/dom/network/TCPSocketChild.cpp
+++ b/dom/network/TCPSocketChild.cpp
@@ -97,31 +97,30 @@ TCPSocketChild::SendOpen(TCPSocket* aSoc
 {
   mSocket = aSocket;
 
   AddIPDLReference();
   gNeckoChild->SendPTCPSocketConstructor(this, mHost, mPort);
   PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
 }
 
-NS_IMETHODIMP
-TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketInternal* aSocket,
+void
+TCPSocketChild::SendWindowlessOpenBind(TCPSocket* 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;
+                                aUseSSL, true);
 }
 
 void
 TCPSocketChildBase::ReleaseIPDLReference()
 {
   MOZ_ASSERT(mIPCOpen);
   mIPCOpen = false;
   this->Release();
@@ -160,45 +159,22 @@ 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) {
-      bool ok = IPC::DeserializeArrayBuffer(cx, data.get_ArrayOfuint8_t(), &val);
-      NS_ENSURE_TRUE(ok, true);
-
+      mSocket->FireDataEvent(cx, aType, data.get_ArrayOfuint8_t());
     } else if (data.type() == SendableData::TnsCString) {
-      bool ok = ToJSValue(cx, NS_ConvertASCIItoUTF16(data.get_nsCString()), &val);
-      NS_ENSURE_TRUE(ok, true);
-
+      mSocket->FireDataEvent(aType, data.get_nsCString());
     } else {
       MOZ_CRASH("Invalid callback data type!");
     }
-    mSocket->FireDataEvent(cx, aType, val);
-
   } else {
     MOZ_CRASH("Invalid callback type!");
   }
   return true;
 }
 
 void
 TCPSocketChild::SendSend(const nsACString& aData, uint32_t aTrackingNumber)
@@ -222,19 +198,19 @@ 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)
+TCPSocketChild::SendSendArray(nsTArray<uint8_t>& aArray, uint32_t aTrackingNumber)
 {
-  SendData(*aArr, aTrackingNumber);
+  SendData(aArray, aTrackingNumber);
   return NS_OK;
 }
 
 void
 TCPSocketChild::SetSocket(TCPSocket* aSocket)
 {
   mSocket = aSocket;
 }
--- a/dom/network/TCPSocketChild.h
+++ b/dom/network/TCPSocketChild.h
@@ -7,16 +7,23 @@
 #ifndef mozilla_dom_TCPSocketChild_h
 #define mozilla_dom_TCPSocketChild_h
 
 #include "mozilla/net/PTCPSocketChild.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "js/TypeDecls.h"
 
+namespace IPC {
+bool
+DeserializeArrayBuffer(JSContext* cx,
+                       const InfallibleTArray<uint8_t>& aBuffer,
+                       JS::MutableHandle<JS::Value> aVal);
+}
+
 namespace mozilla {
 namespace dom {
 
 class TCPSocket;
 
 class TCPSocketChildBase : public nsISupports {
 public:
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TCPSocketChildBase)
@@ -38,21 +45,29 @@ class TCPSocketChild : public mozilla::n
 {
 public:
   NS_IMETHOD_(MozExternalRefCountType) Release() override;
 
   TCPSocketChild(const nsAString& aHost, const uint16_t& aPort);
   ~TCPSocketChild();
 
   void SendOpen(TCPSocket* aSocket, bool aUseSSL, bool aUseArrayBuffers);
+  void SendWindowlessOpenBind(TCPSocket* aSocket,
+                              const nsACString& aRemoteHost, uint16_t aRemotePort,
+                              const nsACString& aLocalHost, uint16_t aLocalPort,
+                              bool aUseSSL);
+  NS_IMETHOD SendSendArray(nsTArray<uint8_t>& aArray,
+                           uint32_t aTrackingNumber);
   void SendSend(const nsACString& aData, uint32_t aTrackingNumber);
   nsresult SendSend(const ArrayBuffer& aData,
                     uint32_t aByteOffset,
                     uint32_t aByteLength,
                     uint32_t aTrackingNumber);
+  void SendSendArray(nsTArray<uint8_t>* arr,
+                     uint32_t trackingNumber);
   void SetSocket(TCPSocket* aSocket);
 
   void GetHost(nsAString& aHost);
   void GetPort(uint16_t* aPort);
 
   virtual bool RecvCallback(const nsString& aType,
                             const CallbackData& aData,
                             const uint32_t& aReadyState) override;
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -173,17 +173,17 @@ TCPSocketParent::RecvOpen(const nsString
 }
 
 bool
 TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost,
                               const uint16_t& aRemotePort,
                               const nsCString& aLocalAddr,
                               const uint16_t& aLocalPort,
                               const bool&     aUseSSL,
-                              const nsCString& aBinaryType)
+                              const bool&     aUseArrayBuffers)
 {
   if (net::UsingNeckoIPCSecurity() &&
       !AssertAppProcessPermission(Manager()->Manager(), "tcp-socket")) {
     FireInteralError(this, __LINE__);
     return true;
   }
 
   nsresult rv;
@@ -218,28 +218,30 @@ TCPSocketParent::RecvOpenBind(const nsCS
   rv = socketTransport->Bind(&addr);
   if (NS_FAILED(rv)) {
     FireInteralError(this, __LINE__);
     return true;
   }
 
   // Obtain App ID
   uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
+  bool     inBrowser = false;
   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();
+    inBrowser = tab->IsBrowserElement();
   }
 
-  mSocket = new TCPSocket(nullptr, aRemoteHost, aRemotePort, aUseSSL,
-                          aBinaryType.EqualsLiteral("arraybuffer"));
+  mSocket = new TCPSocket(nullptr, NS_ConvertUTF8toUTF16(aRemoteHost), aRemotePort, aUseSSL, aUseArrayBuffers);
   mSocket->SetAppIdAndBrowser(appId, inBrowser);
   mSocket->SetSocketBridgeParent(this);
-  NS_ENSURE_SUCCESS(mSocket->InitWithTransport(socketTransport), true);
+  rv = mSocket->InitWithUnconnectedTransport(socketTransport);
+  NS_ENSURE_SUCCESS(rv, true);
   return true;
 }
 
 bool
 TCPSocketParent::RecvStartTLS()
 {
   NS_ENSURE_TRUE(mSocket, true);
   ErrorResult rv;
--- a/dom/network/TCPSocketParent.h
+++ b/dom/network/TCPSocketParent.h
@@ -52,17 +52,17 @@ public:
   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;
+                            const bool& aUseArrayBuffers) 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;