dom/network/src/TCPSocketChild.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include <algorithm>
     6 #include "TCPSocketChild.h"
     7 #include "mozilla/unused.h"
     8 #include "mozilla/net/NeckoChild.h"
     9 #include "mozilla/dom/PBrowserChild.h"
    10 #include "mozilla/dom/TabChild.h"
    11 #include "nsIDOMTCPSocket.h"
    12 #include "nsJSUtils.h"
    13 #include "nsContentUtils.h"
    14 #include "jsapi.h"
    15 #include "jsfriendapi.h"
    16 #include "jswrapper.h"
    18 using mozilla::net::gNeckoChild;
    20 namespace IPC {
    22 bool
    23 DeserializeArrayBuffer(JS::Handle<JSObject*> aObj,
    24                        const InfallibleTArray<uint8_t>& aBuffer,
    25                        JS::MutableHandle<JS::Value> aVal)
    26 {
    27   mozilla::AutoSafeJSContext cx;
    28   JSAutoCompartment ac(cx, aObj);
    30   JS::Rooted<JSObject*> obj(cx, JS_NewArrayBuffer(cx, aBuffer.Length()));
    31   if (!obj)
    32     return false;
    33   uint8_t* data = JS_GetArrayBufferData(obj);
    34   if (!data)
    35     return false;
    36   memcpy(data, aBuffer.Elements(), aBuffer.Length());
    37   aVal.set(OBJECT_TO_JSVAL(obj));
    38   return true;
    39 }
    41 } // namespace IPC
    43 namespace mozilla {
    44 namespace dom {
    46 NS_IMPL_CYCLE_COLLECTION(TCPSocketChildBase, mSocket)
    47 NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketChildBase)
    48 NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketChildBase)
    50 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketChildBase)
    51   NS_INTERFACE_MAP_ENTRY(nsITCPSocketChild)
    52   NS_INTERFACE_MAP_ENTRY(nsISupports)
    53 NS_INTERFACE_MAP_END
    55 TCPSocketChildBase::TCPSocketChildBase()
    56 : mIPCOpen(false)
    57 {
    58 }
    60 TCPSocketChildBase::~TCPSocketChildBase()
    61 {
    62 }
    64 NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketChild::Release(void)
    65 {
    66   nsrefcnt refcnt = TCPSocketChildBase::Release();
    67   if (refcnt == 1 && mIPCOpen) {
    68     PTCPSocketChild::SendRequestDelete();
    69     return 1;
    70   }
    71   return refcnt;
    72 }
    74 TCPSocketChild::TCPSocketChild()
    75 : mWindowObj(nullptr)
    76 {
    77 }
    79 NS_IMETHODIMP
    80 TCPSocketChild::SendOpen(nsITCPSocketInternal* aSocket,
    81                          const nsAString& aHost, uint16_t aPort,
    82                          bool aUseSSL, const nsAString& aBinaryType,
    83                          nsIDOMWindow* aWindow, JS::Handle<JS::Value> aWindowObj,
    84                          JSContext* aCx)
    85 {
    86   mSocket = aSocket;
    88   MOZ_ASSERT(aWindowObj.isObject());
    89   mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
    90   if (!mWindowObj) {
    91     return NS_ERROR_FAILURE;
    92   }
    93   AddIPDLReference();
    94   gNeckoChild->SendPTCPSocketConstructor(this);
    95   PTCPSocketChild::SendOpen(nsString(aHost), aPort,
    96                             aUseSSL, nsString(aBinaryType));
    97   return NS_OK;
    98 }
   100 void
   101 TCPSocketChildBase::ReleaseIPDLReference()
   102 {
   103   MOZ_ASSERT(mIPCOpen);
   104   mIPCOpen = false;
   105   this->Release();
   106 }
   108 void
   109 TCPSocketChildBase::AddIPDLReference()
   110 {
   111   MOZ_ASSERT(!mIPCOpen);
   112   mIPCOpen = true;
   113   this->AddRef();
   114 }
   116 TCPSocketChild::~TCPSocketChild()
   117 {
   118 }
   120 bool
   121 TCPSocketChild::RecvUpdateBufferedAmount(const uint32_t& aBuffered,
   122                                          const uint32_t& aTrackingNumber)
   123 {
   124   if (NS_FAILED(mSocket->UpdateBufferedAmount(aBuffered, aTrackingNumber))) {
   125     NS_ERROR("Shouldn't fail!");
   126   }
   127   return true;
   128 }
   130 bool
   131 TCPSocketChild::RecvCallback(const nsString& aType,
   132                              const CallbackData& aData,
   133                              const nsString& aReadyState)
   134 {
   135   if (NS_FAILED(mSocket->UpdateReadyState(aReadyState)))
   136     NS_ERROR("Shouldn't fail!");
   138   nsresult rv = NS_ERROR_FAILURE;
   139   if (aData.type() == CallbackData::Tvoid_t) {
   140     rv = mSocket->CallListenerVoid(aType);
   142   } else if (aData.type() == CallbackData::TTCPError) {
   143     const TCPError& err(aData.get_TCPError());
   144     rv = mSocket->CallListenerError(aType, err.name());
   146   } else if (aData.type() == CallbackData::TSendableData) {
   147     const SendableData& data = aData.get_SendableData();
   149     if (data.type() == SendableData::TArrayOfuint8_t) {
   150       JSContext* cx = nsContentUtils::GetSafeJSContext();
   151       JSAutoRequest ar(cx);
   152       JS::Rooted<JS::Value> val(cx);
   153       JS::Rooted<JSObject*> window(cx, mWindowObj);
   154       bool ok = IPC::DeserializeArrayBuffer(window, data.get_ArrayOfuint8_t(), &val);
   155       NS_ENSURE_TRUE(ok, true);
   156       rv = mSocket->CallListenerArrayBuffer(aType, val);
   158     } else if (data.type() == SendableData::TnsString) {
   159       rv = mSocket->CallListenerData(aType, data.get_nsString());
   161     } else {
   162       MOZ_CRASH("Invalid callback data type!");
   163     }
   165   } else {
   166     MOZ_CRASH("Invalid callback type!");
   167   }
   168   NS_ENSURE_SUCCESS(rv, true);
   169   return true;
   170 }
   172 NS_IMETHODIMP
   173 TCPSocketChild::SendStartTLS()
   174 {
   175   PTCPSocketChild::SendStartTLS();
   176   return NS_OK;
   177 }
   179 NS_IMETHODIMP
   180 TCPSocketChild::SendSuspend()
   181 {
   182   PTCPSocketChild::SendSuspend();
   183   return NS_OK;
   184 }
   186 NS_IMETHODIMP
   187 TCPSocketChild::SendResume()
   188 {
   189   PTCPSocketChild::SendResume();
   190   return NS_OK;
   191 }
   193 NS_IMETHODIMP
   194 TCPSocketChild::SendClose()
   195 {
   196   PTCPSocketChild::SendClose();
   197   return NS_OK;
   198 }
   200 NS_IMETHODIMP
   201 TCPSocketChild::SendSend(JS::Handle<JS::Value> aData,
   202                          uint32_t aByteOffset,
   203                          uint32_t aByteLength,
   204                          uint32_t aTrackingNumber,
   205                          JSContext* aCx)
   206 {
   207   if (aData.isString()) {
   208     JSString* jsstr = aData.toString();
   209     nsDependentJSString str;
   210     bool ok = str.init(aCx, jsstr);
   211     NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
   212     SendData(str, aTrackingNumber);
   213   } else {
   214     NS_ENSURE_TRUE(aData.isObject(), NS_ERROR_FAILURE);
   215     JS::Rooted<JSObject*> obj(aCx, &aData.toObject());
   216     NS_ENSURE_TRUE(JS_IsArrayBufferObject(obj), NS_ERROR_FAILURE);
   217     uint32_t buflen = JS_GetArrayBufferByteLength(obj);
   218     aByteOffset = std::min(buflen, aByteOffset);
   219     uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength);
   220     uint8_t* data = JS_GetArrayBufferData(obj);
   221     if (!data) {
   222       return NS_ERROR_OUT_OF_MEMORY;
   223     }
   224     FallibleTArray<uint8_t> fallibleArr;
   225     if (!fallibleArr.InsertElementsAt(0, data + aByteOffset, nbytes)) {
   226       return NS_ERROR_OUT_OF_MEMORY;
   227     }
   228     InfallibleTArray<uint8_t> arr;
   229     arr.SwapElements(fallibleArr);
   230     SendData(arr, aTrackingNumber);
   231   }
   232   return NS_OK;
   233 }
   235 NS_IMETHODIMP
   236 TCPSocketChild::SetSocketAndWindow(nsITCPSocketInternal *aSocket,
   237                                    JS::Handle<JS::Value> aWindowObj,
   238                                    JSContext* aCx)
   239 {
   240   mSocket = aSocket;
   241   MOZ_ASSERT(aWindowObj.isObject());
   242   mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
   243   if (!mWindowObj) {
   244     return NS_ERROR_FAILURE;
   245   }
   246   return NS_OK;
   247 }
   249 bool
   250 TCPSocketChild::RecvRequestDelete()
   251 {
   252   mozilla::unused << Send__delete__(this);
   253   return true;
   254 }
   256 } // namespace dom
   257 } // namespace mozilla

mercurial