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/. */
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"
15 #include "jsfriendapi.h"
16 #include "jswrapper.h"
18 using mozilla::net::gNeckoChild
;
23 DeserializeArrayBuffer(JS::Handle
<JSObject
*> aObj
,
24 const InfallibleTArray
<uint8_t>& aBuffer
,
25 JS::MutableHandle
<JS::Value
> aVal
)
27 mozilla::AutoSafeJSContext cx
;
28 JSAutoCompartment
ac(cx
, aObj
);
30 JS::Rooted
<JSObject
*> obj(cx
, JS_NewArrayBuffer(cx
, aBuffer
.Length()));
33 uint8_t* data
= JS_GetArrayBufferData(obj
);
36 memcpy(data
, aBuffer
.Elements(), aBuffer
.Length());
37 aVal
.set(OBJECT_TO_JSVAL(obj
));
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
)
55 TCPSocketChildBase::TCPSocketChildBase()
60 TCPSocketChildBase::~TCPSocketChildBase()
64 NS_IMETHODIMP_(MozExternalRefCountType
) TCPSocketChild::Release(void)
66 nsrefcnt refcnt
= TCPSocketChildBase::Release();
67 if (refcnt
== 1 && mIPCOpen
) {
68 PTCPSocketChild::SendRequestDelete();
74 TCPSocketChild::TCPSocketChild()
81 void TCPSocketChild::Init(const nsString
& aHost
, const uint16_t& aPort
) {
87 TCPSocketChild::SendOpen(nsITCPSocketInternal
* aSocket
,
88 const nsAString
& aHost
, uint16_t aPort
,
89 bool aUseSSL
, const nsAString
& aBinaryType
,
90 nsIDOMWindow
* aWindow
, JS::Handle
<JS::Value
> aWindowObj
,
95 MOZ_ASSERT(aWindowObj
.isObject());
96 mWindowObj
= js::CheckedUnwrap(&aWindowObj
.toObject());
98 return NS_ERROR_FAILURE
;
101 gNeckoChild
->SendPTCPSocketConstructor(this, nsString(aHost
), aPort
);
102 PTCPSocketChild::SendOpen(nsString(aHost
), aPort
,
103 aUseSSL
, nsString(aBinaryType
));
108 TCPSocketChildBase::ReleaseIPDLReference()
110 MOZ_ASSERT(mIPCOpen
);
116 TCPSocketChildBase::AddIPDLReference()
118 MOZ_ASSERT(!mIPCOpen
);
123 TCPSocketChild::~TCPSocketChild()
128 TCPSocketChild::RecvUpdateBufferedAmount(const uint32_t& aBuffered
,
129 const uint32_t& aTrackingNumber
)
131 if (NS_FAILED(mSocket
->UpdateBufferedAmount(aBuffered
, aTrackingNumber
))) {
132 NS_ERROR("Shouldn't fail!");
138 TCPSocketChild::RecvCallback(const nsString
& aType
,
139 const CallbackData
& aData
,
140 const nsString
& aReadyState
)
142 if (NS_FAILED(mSocket
->UpdateReadyState(aReadyState
)))
143 NS_ERROR("Shouldn't fail!");
145 nsresult rv
= NS_ERROR_FAILURE
;
146 if (aData
.type() == CallbackData::Tvoid_t
) {
147 rv
= mSocket
->CallListenerVoid(aType
);
149 } else if (aData
.type() == CallbackData::TTCPError
) {
150 const TCPError
& err(aData
.get_TCPError());
151 rv
= mSocket
->CallListenerError(aType
, err
.name());
153 } else if (aData
.type() == CallbackData::TSendableData
) {
154 const SendableData
& data
= aData
.get_SendableData();
156 if (data
.type() == SendableData::TArrayOfuint8_t
) {
157 JSContext
* cx
= nsContentUtils::GetSafeJSContext();
158 JSAutoRequest
ar(cx
);
159 JS::Rooted
<JS::Value
> val(cx
);
160 JS::Rooted
<JSObject
*> window(cx
, mWindowObj
);
161 bool ok
= IPC::DeserializeArrayBuffer(window
, data
.get_ArrayOfuint8_t(), &val
);
162 NS_ENSURE_TRUE(ok
, true);
163 rv
= mSocket
->CallListenerArrayBuffer(aType
, val
);
165 } else if (data
.type() == SendableData::TnsString
) {
166 rv
= mSocket
->CallListenerData(aType
, data
.get_nsString());
169 MOZ_CRASH("Invalid callback data type!");
173 MOZ_CRASH("Invalid callback type!");
175 NS_ENSURE_SUCCESS(rv
, true);
180 TCPSocketChild::SendStartTLS()
182 PTCPSocketChild::SendStartTLS();
187 TCPSocketChild::SendSuspend()
189 PTCPSocketChild::SendSuspend();
194 TCPSocketChild::SendResume()
196 PTCPSocketChild::SendResume();
201 TCPSocketChild::SendClose()
203 PTCPSocketChild::SendClose();
208 TCPSocketChild::SendSend(JS::Handle
<JS::Value
> aData
,
209 uint32_t aByteOffset
,
210 uint32_t aByteLength
,
211 uint32_t aTrackingNumber
,
214 if (aData
.isString()) {
215 JSString
* jsstr
= aData
.toString();
217 bool ok
= str
.init(aCx
, jsstr
);
218 NS_ENSURE_TRUE(ok
, NS_ERROR_FAILURE
);
219 SendData(str
, aTrackingNumber
);
221 NS_ENSURE_TRUE(aData
.isObject(), NS_ERROR_FAILURE
);
222 JS::Rooted
<JSObject
*> obj(aCx
, &aData
.toObject());
223 NS_ENSURE_TRUE(JS_IsArrayBufferObject(obj
), NS_ERROR_FAILURE
);
224 uint32_t buflen
= JS_GetArrayBufferByteLength(obj
);
225 aByteOffset
= std::min(buflen
, aByteOffset
);
226 uint32_t nbytes
= std::min(buflen
- aByteOffset
, aByteLength
);
227 uint8_t* data
= JS_GetArrayBufferData(obj
);
229 return NS_ERROR_OUT_OF_MEMORY
;
231 FallibleTArray
<uint8_t> fallibleArr
;
232 if (!fallibleArr
.InsertElementsAt(0, data
+ aByteOffset
, nbytes
)) {
233 return NS_ERROR_OUT_OF_MEMORY
;
235 InfallibleTArray
<uint8_t> arr
;
236 arr
.SwapElements(fallibleArr
);
237 SendData(arr
, aTrackingNumber
);
243 TCPSocketChild::SetSocketAndWindow(nsITCPSocketInternal
*aSocket
,
244 JS::Handle
<JS::Value
> aWindowObj
,
248 MOZ_ASSERT(aWindowObj
.isObject());
249 mWindowObj
= js::CheckedUnwrap(&aWindowObj
.toObject());
251 return NS_ERROR_FAILURE
;
257 TCPSocketChild::GetHost(nsAString
& aHost
)
264 TCPSocketChild::GetPort(uint16_t* aPort
)
271 TCPSocketChild::RecvRequestDelete()
273 mozilla::unused
<< Send__delete__(this);
278 } // namespace mozilla