1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TCPSocketChild.h"
#include <algorithm>
#include "TCPSocket.h"
#include "js/ArrayBuffer.h" // JS::NewArrayBufferWithContents
#include "js/RootingAPI.h" // JS::MutableHandle
#include "js/Utility.h" // js::ArrayBufferContentsArena, JS::FreePolicy, js_pod_arena_malloc
#include "js/Value.h" // JS::Value
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/net/NeckoChild.h"
#include "nsContentUtils.h"
#include "nsITCPSocketCallback.h"
using mozilla::net::gNeckoChild;
namespace IPC {
bool DeserializeArrayBuffer(JSContext* cx, const nsTArray<uint8_t>& aBuffer,
JS::MutableHandle<JS::Value> aVal) {
mozilla::UniquePtr<uint8_t[], JS::FreePolicy> data(
js_pod_arena_malloc<uint8_t>(js::ArrayBufferContentsArena,
aBuffer.Length()));
if (!data) return false;
memcpy(data.get(), aBuffer.Elements(), aBuffer.Length());
JSObject* obj =
JS::NewArrayBufferWithContents(cx, aBuffer.Length(), std::move(data));
if (!obj) return false;
aVal.setObject(*obj);
return true;
}
} // namespace IPC
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(TCPSocketChildBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TCPSocketChildBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSocket)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TCPSocketChildBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSocket)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TCPSocketChildBase)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketChildBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketChildBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketChildBase)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
TCPSocketChildBase::TCPSocketChildBase() : mIPCOpen(false) {
mozilla::HoldJSObjects(this);
}
TCPSocketChildBase::~TCPSocketChildBase() { mozilla::DropJSObjects(this); }
NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketChild::Release(void) {
nsrefcnt refcnt = TCPSocketChildBase::Release();
if (refcnt == 1 && mIPCOpen) {
PTCPSocketChild::SendRequestDelete();
return 1;
}
return refcnt;
}
TCPSocketChild::TCPSocketChild(const nsAString& aHost, const uint16_t& aPort,
nsISerialEventTarget* aTarget)
: mHost(aHost), mPort(aPort), mIPCEventTarget(aTarget) {}
void TCPSocketChild::SendOpen(nsITCPSocketCallback* aSocket, bool aUseSSL,
bool aUseArrayBuffers) {
mSocket = aSocket;
AddIPDLReference();
gNeckoChild->SendPTCPSocketConstructor(this, mHost, mPort);
PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
}
void TCPSocketChildBase::ReleaseIPDLReference() {
MOZ_ASSERT(mIPCOpen);
mIPCOpen = false;
mSocket = nullptr;
this->Release();
}
void TCPSocketChildBase::AddIPDLReference() {
MOZ_ASSERT(!mIPCOpen);
mIPCOpen = true;
this->AddRef();
}
TCPSocketChild::~TCPSocketChild() = default;
mozilla::ipc::IPCResult TCPSocketChild::RecvUpdateBufferedAmount(
const uint32_t& aBuffered, const uint32_t& aTrackingNumber) {
mSocket->UpdateBufferedAmount(aBuffered, aTrackingNumber);
return IPC_OK();
}
mozilla::ipc::IPCResult TCPSocketChild::RecvCallback(
const nsString& aType, const CallbackData& aData,
const uint32_t& aReadyState) {
mSocket->UpdateReadyState(aReadyState);
if (aData.type() == CallbackData::Tvoid_t) {
mSocket->FireEvent(aType);
} else if (aData.type() == CallbackData::TTCPError) {
const TCPError& err(aData.get_TCPError());
mSocket->FireErrorEvent(err.name(), err.message(), err.errorCode());
} else if (aData.type() == CallbackData::TSendableData) {
const SendableData& data = aData.get_SendableData();
if (data.type() == SendableData::TArrayOfuint8_t) {
mSocket->FireDataArrayEvent(aType, data.get_ArrayOfuint8_t());
} else if (data.type() == SendableData::TnsCString) {
mSocket->FireDataStringEvent(aType, data.get_nsCString());
} else {
MOZ_CRASH("Invalid callback data type!");
}
} else {
MOZ_CRASH("Invalid callback type!");
}
return IPC_OK();
}
void TCPSocketChild::SendSend(const nsACString& aData) {
SendData(nsCString(aData));
}
void TCPSocketChild::SendSend(nsTArray<uint8_t>&& aData) {
SendData(SendableData{std::move(aData)});
}
void TCPSocketChild::SetSocket(TCPSocket* aSocket) { mSocket = aSocket; }
void TCPSocketChild::GetHost(nsAString& aHost) { aHost = mHost; }
void TCPSocketChild::GetPort(uint16_t* aPort) const { *aPort = mPort; }
mozilla::ipc::IPCResult TCPSocketChild::RecvRequestDelete() {
(void)Send__delete__(this);
return IPC_OK();
}
} // namespace mozilla::dom
|