Backed out changeset 12313cce9281 (bug 1083449) for suspicion of causing B2G debug...
[gecko.git] / dom / network / TCPSocketChild.cpp
blob377e84129d94885316159ed25a40cdb229e77449
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)
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;
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)
60 TCPSocketChildBase::~TCPSocketChildBase()
64 NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketChild::Release(void)
66 nsrefcnt refcnt = TCPSocketChildBase::Release();
67 if (refcnt == 1 && mIPCOpen) {
68 PTCPSocketChild::SendRequestDelete();
69 return 1;
71 return refcnt;
74 TCPSocketChild::TCPSocketChild()
75 : mWindowObj(nullptr)
76 , mHost()
77 , mPort(0)
81 void TCPSocketChild::Init(const nsString& aHost, const uint16_t& aPort) {
82 mHost = aHost;
83 mPort = aPort;
86 NS_IMETHODIMP
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,
91 JSContext* aCx)
93 mSocket = aSocket;
95 MOZ_ASSERT(aWindowObj.isObject());
96 mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
97 if (!mWindowObj) {
98 return NS_ERROR_FAILURE;
100 AddIPDLReference();
101 gNeckoChild->SendPTCPSocketConstructor(this, nsString(aHost), aPort);
102 PTCPSocketChild::SendOpen(nsString(aHost), aPort,
103 aUseSSL, nsString(aBinaryType));
104 return NS_OK;
107 void
108 TCPSocketChildBase::ReleaseIPDLReference()
110 MOZ_ASSERT(mIPCOpen);
111 mIPCOpen = false;
112 this->Release();
115 void
116 TCPSocketChildBase::AddIPDLReference()
118 MOZ_ASSERT(!mIPCOpen);
119 mIPCOpen = true;
120 this->AddRef();
123 TCPSocketChild::~TCPSocketChild()
127 bool
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!");
134 return true;
137 bool
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());
168 } else {
169 MOZ_CRASH("Invalid callback data type!");
172 } else {
173 MOZ_CRASH("Invalid callback type!");
175 NS_ENSURE_SUCCESS(rv, true);
176 return true;
179 NS_IMETHODIMP
180 TCPSocketChild::SendStartTLS()
182 PTCPSocketChild::SendStartTLS();
183 return NS_OK;
186 NS_IMETHODIMP
187 TCPSocketChild::SendSuspend()
189 PTCPSocketChild::SendSuspend();
190 return NS_OK;
193 NS_IMETHODIMP
194 TCPSocketChild::SendResume()
196 PTCPSocketChild::SendResume();
197 return NS_OK;
200 NS_IMETHODIMP
201 TCPSocketChild::SendClose()
203 PTCPSocketChild::SendClose();
204 return NS_OK;
207 NS_IMETHODIMP
208 TCPSocketChild::SendSend(JS::Handle<JS::Value> aData,
209 uint32_t aByteOffset,
210 uint32_t aByteLength,
211 uint32_t aTrackingNumber,
212 JSContext* aCx)
214 if (aData.isString()) {
215 JSString* jsstr = aData.toString();
216 nsAutoJSString str;
217 bool ok = str.init(aCx, jsstr);
218 NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
219 SendData(str, aTrackingNumber);
220 } else {
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);
228 if (!data) {
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);
239 return NS_OK;
242 NS_IMETHODIMP
243 TCPSocketChild::SetSocketAndWindow(nsITCPSocketInternal *aSocket,
244 JS::Handle<JS::Value> aWindowObj,
245 JSContext* aCx)
247 mSocket = aSocket;
248 MOZ_ASSERT(aWindowObj.isObject());
249 mWindowObj = js::CheckedUnwrap(&aWindowObj.toObject());
250 if (!mWindowObj) {
251 return NS_ERROR_FAILURE;
253 return NS_OK;
256 NS_IMETHODIMP
257 TCPSocketChild::GetHost(nsAString& aHost)
259 aHost = mHost;
260 return NS_OK;
263 NS_IMETHODIMP
264 TCPSocketChild::GetPort(uint16_t* aPort)
266 *aPort = mPort;
267 return NS_OK;
270 bool
271 TCPSocketChild::RecvRequestDelete()
273 mozilla::unused << Send__delete__(this);
274 return true;
277 } // namespace dom
278 } // namespace mozilla