dom/network/src/TCPSocketChild.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/network/src/TCPSocketChild.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,257 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include <algorithm>
     1.9 +#include "TCPSocketChild.h"
    1.10 +#include "mozilla/unused.h"
    1.11 +#include "mozilla/net/NeckoChild.h"
    1.12 +#include "mozilla/dom/PBrowserChild.h"
    1.13 +#include "mozilla/dom/TabChild.h"
    1.14 +#include "nsIDOMTCPSocket.h"
    1.15 +#include "nsJSUtils.h"
    1.16 +#include "nsContentUtils.h"
    1.17 +#include "jsapi.h"
    1.18 +#include "jsfriendapi.h"
    1.19 +#include "jswrapper.h"
    1.20 +
    1.21 +using mozilla::net::gNeckoChild;
    1.22 +
    1.23 +namespace IPC {
    1.24 +
    1.25 +bool
    1.26 +DeserializeArrayBuffer(JS::Handle<JSObject*> aObj,
    1.27 +                       const InfallibleTArray<uint8_t>& aBuffer,
    1.28 +                       JS::MutableHandle<JS::Value> aVal)
    1.29 +{
    1.30 +  mozilla::AutoSafeJSContext cx;
    1.31 +  JSAutoCompartment ac(cx, aObj);
    1.32 +
    1.33 +  JS::Rooted<JSObject*> obj(cx, JS_NewArrayBuffer(cx, aBuffer.Length()));
    1.34 +  if (!obj)
    1.35 +    return false;
    1.36 +  uint8_t* data = JS_GetArrayBufferData(obj);
    1.37 +  if (!data)
    1.38 +    return false;
    1.39 +  memcpy(data, aBuffer.Elements(), aBuffer.Length());
    1.40 +  aVal.set(OBJECT_TO_JSVAL(obj));
    1.41 +  return true;
    1.42 +}
    1.43 +
    1.44 +} // namespace IPC
    1.45 +
    1.46 +namespace mozilla {
    1.47 +namespace dom {
    1.48 +
    1.49 +NS_IMPL_CYCLE_COLLECTION(TCPSocketChildBase, mSocket)
    1.50 +NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketChildBase)
    1.51 +NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketChildBase)
    1.52 +
    1.53 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketChildBase)
    1.54 +  NS_INTERFACE_MAP_ENTRY(nsITCPSocketChild)
    1.55 +  NS_INTERFACE_MAP_ENTRY(nsISupports)
    1.56 +NS_INTERFACE_MAP_END
    1.57 +
    1.58 +TCPSocketChildBase::TCPSocketChildBase()
    1.59 +: mIPCOpen(false)
    1.60 +{
    1.61 +}
    1.62 +
    1.63 +TCPSocketChildBase::~TCPSocketChildBase()
    1.64 +{
    1.65 +}
    1.66 +
    1.67 +NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketChild::Release(void)
    1.68 +{
    1.69 +  nsrefcnt refcnt = TCPSocketChildBase::Release();
    1.70 +  if (refcnt == 1 && mIPCOpen) {
    1.71 +    PTCPSocketChild::SendRequestDelete();
    1.72 +    return 1;
    1.73 +  }
    1.74 +  return refcnt;
    1.75 +}
    1.76 +
    1.77 +TCPSocketChild::TCPSocketChild()
    1.78 +: mWindowObj(nullptr)
    1.79 +{
    1.80 +}
    1.81 +
    1.82 +NS_IMETHODIMP
    1.83 +TCPSocketChild::SendOpen(nsITCPSocketInternal* aSocket,
    1.84 +                         const nsAString& aHost, uint16_t aPort,
    1.85 +                         bool aUseSSL, const nsAString& aBinaryType,
    1.86 +                         nsIDOMWindow* aWindow, JS::Handle<JS::Value> aWindowObj,
    1.87 +                         JSContext* aCx)
    1.88 +{
    1.89 +  mSocket = aSocket;
    1.90 +
    1.91 +  MOZ_ASSERT(aWindowObj.isObject());
    1.92 +  mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
    1.93 +  if (!mWindowObj) {
    1.94 +    return NS_ERROR_FAILURE;
    1.95 +  }
    1.96 +  AddIPDLReference();
    1.97 +  gNeckoChild->SendPTCPSocketConstructor(this);
    1.98 +  PTCPSocketChild::SendOpen(nsString(aHost), aPort,
    1.99 +                            aUseSSL, nsString(aBinaryType));
   1.100 +  return NS_OK;
   1.101 +}
   1.102 +
   1.103 +void
   1.104 +TCPSocketChildBase::ReleaseIPDLReference()
   1.105 +{
   1.106 +  MOZ_ASSERT(mIPCOpen);
   1.107 +  mIPCOpen = false;
   1.108 +  this->Release();
   1.109 +}
   1.110 +
   1.111 +void
   1.112 +TCPSocketChildBase::AddIPDLReference()
   1.113 +{
   1.114 +  MOZ_ASSERT(!mIPCOpen);
   1.115 +  mIPCOpen = true;
   1.116 +  this->AddRef();
   1.117 +}
   1.118 +
   1.119 +TCPSocketChild::~TCPSocketChild()
   1.120 +{
   1.121 +}
   1.122 +
   1.123 +bool
   1.124 +TCPSocketChild::RecvUpdateBufferedAmount(const uint32_t& aBuffered,
   1.125 +                                         const uint32_t& aTrackingNumber)
   1.126 +{
   1.127 +  if (NS_FAILED(mSocket->UpdateBufferedAmount(aBuffered, aTrackingNumber))) {
   1.128 +    NS_ERROR("Shouldn't fail!");
   1.129 +  }
   1.130 +  return true;
   1.131 +}
   1.132 +
   1.133 +bool
   1.134 +TCPSocketChild::RecvCallback(const nsString& aType,
   1.135 +                             const CallbackData& aData,
   1.136 +                             const nsString& aReadyState)
   1.137 +{
   1.138 +  if (NS_FAILED(mSocket->UpdateReadyState(aReadyState)))
   1.139 +    NS_ERROR("Shouldn't fail!");
   1.140 +
   1.141 +  nsresult rv = NS_ERROR_FAILURE;
   1.142 +  if (aData.type() == CallbackData::Tvoid_t) {
   1.143 +    rv = mSocket->CallListenerVoid(aType);
   1.144 +
   1.145 +  } else if (aData.type() == CallbackData::TTCPError) {
   1.146 +    const TCPError& err(aData.get_TCPError());
   1.147 +    rv = mSocket->CallListenerError(aType, err.name());
   1.148 +
   1.149 +  } else if (aData.type() == CallbackData::TSendableData) {
   1.150 +    const SendableData& data = aData.get_SendableData();
   1.151 +
   1.152 +    if (data.type() == SendableData::TArrayOfuint8_t) {
   1.153 +      JSContext* cx = nsContentUtils::GetSafeJSContext();
   1.154 +      JSAutoRequest ar(cx);
   1.155 +      JS::Rooted<JS::Value> val(cx);
   1.156 +      JS::Rooted<JSObject*> window(cx, mWindowObj);
   1.157 +      bool ok = IPC::DeserializeArrayBuffer(window, data.get_ArrayOfuint8_t(), &val);
   1.158 +      NS_ENSURE_TRUE(ok, true);
   1.159 +      rv = mSocket->CallListenerArrayBuffer(aType, val);
   1.160 +
   1.161 +    } else if (data.type() == SendableData::TnsString) {
   1.162 +      rv = mSocket->CallListenerData(aType, data.get_nsString());
   1.163 +
   1.164 +    } else {
   1.165 +      MOZ_CRASH("Invalid callback data type!");
   1.166 +    }
   1.167 +
   1.168 +  } else {
   1.169 +    MOZ_CRASH("Invalid callback type!");
   1.170 +  }
   1.171 +  NS_ENSURE_SUCCESS(rv, true);
   1.172 +  return true;
   1.173 +}
   1.174 +
   1.175 +NS_IMETHODIMP
   1.176 +TCPSocketChild::SendStartTLS()
   1.177 +{
   1.178 +  PTCPSocketChild::SendStartTLS();
   1.179 +  return NS_OK;
   1.180 +}
   1.181 +
   1.182 +NS_IMETHODIMP
   1.183 +TCPSocketChild::SendSuspend()
   1.184 +{
   1.185 +  PTCPSocketChild::SendSuspend();
   1.186 +  return NS_OK;
   1.187 +}
   1.188 +
   1.189 +NS_IMETHODIMP
   1.190 +TCPSocketChild::SendResume()
   1.191 +{
   1.192 +  PTCPSocketChild::SendResume();
   1.193 +  return NS_OK;
   1.194 +}
   1.195 +
   1.196 +NS_IMETHODIMP
   1.197 +TCPSocketChild::SendClose()
   1.198 +{
   1.199 +  PTCPSocketChild::SendClose();
   1.200 +  return NS_OK;
   1.201 +}
   1.202 +
   1.203 +NS_IMETHODIMP
   1.204 +TCPSocketChild::SendSend(JS::Handle<JS::Value> aData,
   1.205 +                         uint32_t aByteOffset,
   1.206 +                         uint32_t aByteLength,
   1.207 +                         uint32_t aTrackingNumber,
   1.208 +                         JSContext* aCx)
   1.209 +{
   1.210 +  if (aData.isString()) {
   1.211 +    JSString* jsstr = aData.toString();
   1.212 +    nsDependentJSString str;
   1.213 +    bool ok = str.init(aCx, jsstr);
   1.214 +    NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
   1.215 +    SendData(str, aTrackingNumber);
   1.216 +  } else {
   1.217 +    NS_ENSURE_TRUE(aData.isObject(), NS_ERROR_FAILURE);
   1.218 +    JS::Rooted<JSObject*> obj(aCx, &aData.toObject());
   1.219 +    NS_ENSURE_TRUE(JS_IsArrayBufferObject(obj), NS_ERROR_FAILURE);
   1.220 +    uint32_t buflen = JS_GetArrayBufferByteLength(obj);
   1.221 +    aByteOffset = std::min(buflen, aByteOffset);
   1.222 +    uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength);
   1.223 +    uint8_t* data = JS_GetArrayBufferData(obj);
   1.224 +    if (!data) {
   1.225 +      return NS_ERROR_OUT_OF_MEMORY;
   1.226 +    }
   1.227 +    FallibleTArray<uint8_t> fallibleArr;
   1.228 +    if (!fallibleArr.InsertElementsAt(0, data + aByteOffset, nbytes)) {
   1.229 +      return NS_ERROR_OUT_OF_MEMORY;
   1.230 +    }
   1.231 +    InfallibleTArray<uint8_t> arr;
   1.232 +    arr.SwapElements(fallibleArr);
   1.233 +    SendData(arr, aTrackingNumber);
   1.234 +  }
   1.235 +  return NS_OK;
   1.236 +}
   1.237 +
   1.238 +NS_IMETHODIMP
   1.239 +TCPSocketChild::SetSocketAndWindow(nsITCPSocketInternal *aSocket,
   1.240 +                                   JS::Handle<JS::Value> aWindowObj,
   1.241 +                                   JSContext* aCx)
   1.242 +{
   1.243 +  mSocket = aSocket;
   1.244 +  MOZ_ASSERT(aWindowObj.isObject());
   1.245 +  mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
   1.246 +  if (!mWindowObj) {
   1.247 +    return NS_ERROR_FAILURE;
   1.248 +  }
   1.249 +  return NS_OK;
   1.250 +}
   1.251 +
   1.252 +bool
   1.253 +TCPSocketChild::RecvRequestDelete()
   1.254 +{
   1.255 +  mozilla::unused << Send__delete__(this);
   1.256 +  return true;
   1.257 +}
   1.258 +
   1.259 +} // namespace dom
   1.260 +} // namespace mozilla

mercurial