dom/network/src/TCPSocketParent.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "TCPSocketParent.h"
michael@0 6 #include "jsapi.h"
michael@0 7 #include "jsfriendapi.h"
michael@0 8 #include "nsJSUtils.h"
michael@0 9 #include "nsIDOMTCPSocket.h"
michael@0 10 #include "nsCxPusher.h"
michael@0 11 #include "mozilla/unused.h"
michael@0 12 #include "mozilla/AppProcessChecker.h"
michael@0 13 #include "mozilla/net/NeckoCommon.h"
michael@0 14 #include "mozilla/net/PNeckoParent.h"
michael@0 15 #include "mozilla/dom/ContentParent.h"
michael@0 16 #include "mozilla/dom/TabParent.h"
michael@0 17 #include "nsIScriptSecurityManager.h"
michael@0 18
michael@0 19 namespace IPC {
michael@0 20
michael@0 21 //Defined in TCPSocketChild.cpp
michael@0 22 extern bool
michael@0 23 DeserializeArrayBuffer(JS::Handle<JSObject*> aObj,
michael@0 24 const InfallibleTArray<uint8_t>& aBuffer,
michael@0 25 JS::MutableHandle<JS::Value> aVal);
michael@0 26
michael@0 27 }
michael@0 28
michael@0 29 namespace mozilla {
michael@0 30 namespace dom {
michael@0 31
michael@0 32 static void
michael@0 33 FireInteralError(mozilla::net::PTCPSocketParent* aActor, uint32_t aLineNo)
michael@0 34 {
michael@0 35 mozilla::unused <<
michael@0 36 aActor->SendCallback(NS_LITERAL_STRING("onerror"),
michael@0 37 TCPError(NS_LITERAL_STRING("InvalidStateError")),
michael@0 38 NS_LITERAL_STRING("connecting"));
michael@0 39 }
michael@0 40
michael@0 41 NS_IMPL_CYCLE_COLLECTION(TCPSocketParentBase, mSocket, mIntermediary)
michael@0 42 NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketParentBase)
michael@0 43 NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketParentBase)
michael@0 44
michael@0 45 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketParentBase)
michael@0 46 NS_INTERFACE_MAP_ENTRY(nsITCPSocketParent)
michael@0 47 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 48 NS_INTERFACE_MAP_END
michael@0 49
michael@0 50 TCPSocketParentBase::TCPSocketParentBase()
michael@0 51 : mIPCOpen(false)
michael@0 52 {
michael@0 53 }
michael@0 54
michael@0 55 TCPSocketParentBase::~TCPSocketParentBase()
michael@0 56 {
michael@0 57 }
michael@0 58
michael@0 59 void
michael@0 60 TCPSocketParentBase::ReleaseIPDLReference()
michael@0 61 {
michael@0 62 MOZ_ASSERT(mIPCOpen);
michael@0 63 mIPCOpen = false;
michael@0 64 this->Release();
michael@0 65 }
michael@0 66
michael@0 67 void
michael@0 68 TCPSocketParentBase::AddIPDLReference()
michael@0 69 {
michael@0 70 MOZ_ASSERT(!mIPCOpen);
michael@0 71 mIPCOpen = true;
michael@0 72 this->AddRef();
michael@0 73 }
michael@0 74
michael@0 75 NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketParent::Release(void)
michael@0 76 {
michael@0 77 nsrefcnt refcnt = TCPSocketParentBase::Release();
michael@0 78 if (refcnt == 1 && mIPCOpen) {
michael@0 79 mozilla::unused << PTCPSocketParent::SendRequestDelete();
michael@0 80 return 1;
michael@0 81 }
michael@0 82 return refcnt;
michael@0 83 }
michael@0 84
michael@0 85 bool
michael@0 86 TCPSocketParent::RecvOpen(const nsString& aHost, const uint16_t& aPort, const bool& aUseSSL,
michael@0 87 const nsString& aBinaryType)
michael@0 88 {
michael@0 89 // We don't have browser actors in xpcshell, and hence can't run automated
michael@0 90 // tests without this loophole.
michael@0 91 if (net::UsingNeckoIPCSecurity() &&
michael@0 92 !AssertAppProcessPermission(Manager()->Manager(), "tcp-socket")) {
michael@0 93 FireInteralError(this, __LINE__);
michael@0 94 return true;
michael@0 95 }
michael@0 96
michael@0 97 // Obtain App ID
michael@0 98 uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
michael@0 99 const PContentParent *content = Manager()->Manager();
michael@0 100 const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
michael@0 101 if (browsers.Length() > 0) {
michael@0 102 TabParent *tab = static_cast<TabParent*>(browsers[0]);
michael@0 103 appId = tab->OwnAppId();
michael@0 104 }
michael@0 105
michael@0 106 nsresult rv;
michael@0 107 mIntermediary = do_CreateInstance("@mozilla.org/tcp-socket-intermediary;1", &rv);
michael@0 108 if (NS_FAILED(rv)) {
michael@0 109 FireInteralError(this, __LINE__);
michael@0 110 return true;
michael@0 111 }
michael@0 112
michael@0 113 rv = mIntermediary->Open(this, aHost, aPort, aUseSSL, aBinaryType, appId,
michael@0 114 getter_AddRefs(mSocket));
michael@0 115 if (NS_FAILED(rv) || !mSocket) {
michael@0 116 FireInteralError(this, __LINE__);
michael@0 117 return true;
michael@0 118 }
michael@0 119
michael@0 120 return true;
michael@0 121 }
michael@0 122
michael@0 123 NS_IMETHODIMP
michael@0 124 TCPSocketParent::InitJS(JS::Handle<JS::Value> aIntermediary, JSContext* aCx)
michael@0 125 {
michael@0 126 MOZ_ASSERT(aIntermediary.isObject());
michael@0 127 mIntermediaryObj = &aIntermediary.toObject();
michael@0 128 return NS_OK;
michael@0 129 }
michael@0 130
michael@0 131 bool
michael@0 132 TCPSocketParent::RecvStartTLS()
michael@0 133 {
michael@0 134 NS_ENSURE_TRUE(mSocket, true);
michael@0 135 nsresult rv = mSocket->UpgradeToSecure();
michael@0 136 NS_ENSURE_SUCCESS(rv, true);
michael@0 137 return true;
michael@0 138 }
michael@0 139
michael@0 140 bool
michael@0 141 TCPSocketParent::RecvSuspend()
michael@0 142 {
michael@0 143 NS_ENSURE_TRUE(mSocket, true);
michael@0 144 nsresult rv = mSocket->Suspend();
michael@0 145 NS_ENSURE_SUCCESS(rv, true);
michael@0 146 return true;
michael@0 147 }
michael@0 148
michael@0 149 bool
michael@0 150 TCPSocketParent::RecvResume()
michael@0 151 {
michael@0 152 NS_ENSURE_TRUE(mSocket, true);
michael@0 153 nsresult rv = mSocket->Resume();
michael@0 154 NS_ENSURE_SUCCESS(rv, true);
michael@0 155 return true;
michael@0 156 }
michael@0 157
michael@0 158 bool
michael@0 159 TCPSocketParent::RecvData(const SendableData& aData,
michael@0 160 const uint32_t& aTrackingNumber)
michael@0 161 {
michael@0 162 NS_ENSURE_TRUE(mIntermediary, true);
michael@0 163
michael@0 164 nsresult rv;
michael@0 165 switch (aData.type()) {
michael@0 166 case SendableData::TArrayOfuint8_t: {
michael@0 167 AutoSafeJSContext cx;
michael@0 168 JSAutoRequest ar(cx);
michael@0 169 JS::Rooted<JS::Value> val(cx);
michael@0 170 JS::Rooted<JSObject*> obj(cx, mIntermediaryObj);
michael@0 171 IPC::DeserializeArrayBuffer(obj, aData.get_ArrayOfuint8_t(), &val);
michael@0 172 rv = mIntermediary->OnRecvSendArrayBuffer(val, aTrackingNumber);
michael@0 173 NS_ENSURE_SUCCESS(rv, true);
michael@0 174 break;
michael@0 175 }
michael@0 176
michael@0 177 case SendableData::TnsString:
michael@0 178 rv = mIntermediary->OnRecvSendString(aData.get_nsString(), aTrackingNumber);
michael@0 179 NS_ENSURE_SUCCESS(rv, true);
michael@0 180 break;
michael@0 181
michael@0 182 default:
michael@0 183 MOZ_CRASH("unexpected SendableData type");
michael@0 184 }
michael@0 185 return true;
michael@0 186 }
michael@0 187
michael@0 188 bool
michael@0 189 TCPSocketParent::RecvClose()
michael@0 190 {
michael@0 191 NS_ENSURE_TRUE(mSocket, true);
michael@0 192 nsresult rv = mSocket->Close();
michael@0 193 NS_ENSURE_SUCCESS(rv, true);
michael@0 194 return true;
michael@0 195 }
michael@0 196
michael@0 197 NS_IMETHODIMP
michael@0 198 TCPSocketParent::SendEvent(const nsAString& aType, JS::Handle<JS::Value> aDataVal,
michael@0 199 const nsAString& aReadyState, JSContext* aCx)
michael@0 200 {
michael@0 201 if (!mIPCOpen) {
michael@0 202 NS_WARNING("Dropping callback due to no IPC connection");
michael@0 203 return NS_OK;
michael@0 204 }
michael@0 205
michael@0 206 CallbackData data;
michael@0 207 if (aDataVal.isString()) {
michael@0 208 JSString* jsstr = aDataVal.toString();
michael@0 209 nsDependentJSString str;
michael@0 210 if (!str.init(aCx, jsstr)) {
michael@0 211 FireInteralError(this, __LINE__);
michael@0 212 return NS_ERROR_OUT_OF_MEMORY;
michael@0 213 }
michael@0 214 data = SendableData(str);
michael@0 215
michael@0 216 } else if (aDataVal.isUndefined() || aDataVal.isNull()) {
michael@0 217 data = mozilla::void_t();
michael@0 218
michael@0 219 } else if (aDataVal.isObject()) {
michael@0 220 JS::Rooted<JSObject *> obj(aCx, &aDataVal.toObject());
michael@0 221 if (JS_IsArrayBufferObject(obj)) {
michael@0 222 uint32_t nbytes = JS_GetArrayBufferByteLength(obj);
michael@0 223 uint8_t* buffer = JS_GetArrayBufferData(obj);
michael@0 224 if (!buffer) {
michael@0 225 FireInteralError(this, __LINE__);
michael@0 226 return NS_ERROR_OUT_OF_MEMORY;
michael@0 227 }
michael@0 228 FallibleTArray<uint8_t> fallibleArr;
michael@0 229 if (!fallibleArr.InsertElementsAt(0, buffer, nbytes)) {
michael@0 230 FireInteralError(this, __LINE__);
michael@0 231 return NS_ERROR_OUT_OF_MEMORY;
michael@0 232 }
michael@0 233 InfallibleTArray<uint8_t> arr;
michael@0 234 arr.SwapElements(fallibleArr);
michael@0 235 data = SendableData(arr);
michael@0 236
michael@0 237 } else {
michael@0 238 nsDependentJSString name;
michael@0 239
michael@0 240 JS::Rooted<JS::Value> val(aCx);
michael@0 241 if (!JS_GetProperty(aCx, obj, "name", &val)) {
michael@0 242 NS_ERROR("No name property on supposed error object");
michael@0 243 } else if (JSVAL_IS_STRING(val)) {
michael@0 244 if (!name.init(aCx, JSVAL_TO_STRING(val))) {
michael@0 245 NS_WARNING("couldn't initialize string");
michael@0 246 }
michael@0 247 }
michael@0 248
michael@0 249 data = TCPError(name);
michael@0 250 }
michael@0 251 } else {
michael@0 252 NS_ERROR("Unexpected JS value encountered");
michael@0 253 FireInteralError(this, __LINE__);
michael@0 254 return NS_ERROR_FAILURE;
michael@0 255 }
michael@0 256 mozilla::unused <<
michael@0 257 PTCPSocketParent::SendCallback(nsString(aType), data,
michael@0 258 nsString(aReadyState));
michael@0 259 return NS_OK;
michael@0 260 }
michael@0 261
michael@0 262 NS_IMETHODIMP
michael@0 263 TCPSocketParent::SetSocketAndIntermediary(nsIDOMTCPSocket *socket,
michael@0 264 nsITCPSocketIntermediary *intermediary,
michael@0 265 JSContext* cx)
michael@0 266 {
michael@0 267 mSocket = socket;
michael@0 268 mIntermediary = intermediary;
michael@0 269 return NS_OK;
michael@0 270 }
michael@0 271
michael@0 272 NS_IMETHODIMP
michael@0 273 TCPSocketParent::SendUpdateBufferedAmount(uint32_t aBufferedAmount,
michael@0 274 uint32_t aTrackingNumber)
michael@0 275 {
michael@0 276 mozilla::unused << PTCPSocketParent::SendUpdateBufferedAmount(aBufferedAmount,
michael@0 277 aTrackingNumber);
michael@0 278 return NS_OK;
michael@0 279 }
michael@0 280
michael@0 281 void
michael@0 282 TCPSocketParent::ActorDestroy(ActorDestroyReason why)
michael@0 283 {
michael@0 284 if (mSocket) {
michael@0 285 mSocket->Close();
michael@0 286 }
michael@0 287 mSocket = nullptr;
michael@0 288 mIntermediaryObj = nullptr;
michael@0 289 mIntermediary = nullptr;
michael@0 290 }
michael@0 291
michael@0 292 bool
michael@0 293 TCPSocketParent::RecvRequestDelete()
michael@0 294 {
michael@0 295 mozilla::unused << Send__delete__(this);
michael@0 296 return true;
michael@0 297 }
michael@0 298
michael@0 299 } // namespace dom
michael@0 300 } // namespace mozilla

mercurial