js/ipc/JavaScriptParent.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=4 sw=4 et tw=80:
michael@0 3 *
michael@0 4 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #include "JavaScriptParent.h"
michael@0 9 #include "mozilla/dom/ContentParent.h"
michael@0 10 #include "nsJSUtils.h"
michael@0 11 #include "jsfriendapi.h"
michael@0 12 #include "jsproxy.h"
michael@0 13 #include "jswrapper.h"
michael@0 14 #include "HeapAPI.h"
michael@0 15 #include "xpcprivate.h"
michael@0 16 #include "mozilla/Casting.h"
michael@0 17
michael@0 18 using namespace js;
michael@0 19 using namespace JS;
michael@0 20 using namespace mozilla;
michael@0 21 using namespace mozilla::jsipc;
michael@0 22 using namespace mozilla::dom;
michael@0 23
michael@0 24 JavaScriptParent::JavaScriptParent()
michael@0 25 : refcount_(1),
michael@0 26 inactive_(false)
michael@0 27 {
michael@0 28 }
michael@0 29
michael@0 30 static inline JavaScriptParent *
michael@0 31 ParentOf(JSObject *obj)
michael@0 32 {
michael@0 33 MOZ_ASSERT(JavaScriptParent::IsCPOW(obj));
michael@0 34 return reinterpret_cast<JavaScriptParent *>(GetProxyExtra(obj, 0).toPrivate());
michael@0 35 }
michael@0 36
michael@0 37 ObjectId
michael@0 38 JavaScriptParent::idOf(JSObject *obj)
michael@0 39 {
michael@0 40 MOZ_ASSERT(JavaScriptParent::IsCPOW(obj));
michael@0 41
michael@0 42 Value v = GetProxyExtra(obj, 1);
michael@0 43 MOZ_ASSERT(v.isDouble());
michael@0 44
michael@0 45 ObjectId objId = BitwiseCast<uint64_t>(v.toDouble());
michael@0 46 MOZ_ASSERT(findObject(objId) == obj);
michael@0 47 MOZ_ASSERT(objId);
michael@0 48
michael@0 49 return objId;
michael@0 50 }
michael@0 51
michael@0 52 int sCPOWProxyHandler;
michael@0 53
michael@0 54 class CPOWProxyHandler : public BaseProxyHandler
michael@0 55 {
michael@0 56 public:
michael@0 57 CPOWProxyHandler()
michael@0 58 : BaseProxyHandler(&sCPOWProxyHandler) {}
michael@0 59 virtual ~CPOWProxyHandler() {}
michael@0 60
michael@0 61 virtual bool finalizeInBackground(Value priv) MOZ_OVERRIDE {
michael@0 62 return false;
michael@0 63 }
michael@0 64
michael@0 65 virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
michael@0 66 virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 67 MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
michael@0 68 virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 69 MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
michael@0 70 virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 71 MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
michael@0 72 virtual bool getOwnPropertyNames(JSContext *cx, HandleObject proxy,
michael@0 73 AutoIdVector &props) MOZ_OVERRIDE;
michael@0 74 virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
michael@0 75 virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
michael@0 76
michael@0 77 virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
michael@0 78 virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
michael@0 79 virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
michael@0 80 HandleId id, MutableHandleValue vp) MOZ_OVERRIDE;
michael@0 81 virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
michael@0 82 JS::HandleId id, bool strict, JS::MutableHandleValue vp) MOZ_OVERRIDE;
michael@0 83 virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
michael@0 84
michael@0 85 virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
michael@0 86 virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
michael@0 87 virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
michael@0 88 virtual const char* className(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
michael@0 89 virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE;
michael@0 90
michael@0 91 static CPOWProxyHandler singleton;
michael@0 92 };
michael@0 93
michael@0 94 CPOWProxyHandler CPOWProxyHandler::singleton;
michael@0 95
michael@0 96 #define FORWARD(call, args) \
michael@0 97 JavaScriptParent *parent = ParentOf(proxy); \
michael@0 98 if (!parent->active()) { \
michael@0 99 JS_ReportError(cx, "cannot use a CPOW whose process is gone"); \
michael@0 100 return false; \
michael@0 101 } \
michael@0 102 return parent->call args;
michael@0 103
michael@0 104 bool
michael@0 105 CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
michael@0 106 {
michael@0 107 FORWARD(preventExtensions, (cx, proxy));
michael@0 108 }
michael@0 109
michael@0 110 bool
michael@0 111 JavaScriptParent::preventExtensions(JSContext *cx, HandleObject proxy)
michael@0 112 {
michael@0 113 ObjectId objId = idOf(proxy);
michael@0 114
michael@0 115 ReturnStatus status;
michael@0 116 if (!CallPreventExtensions(objId, &status))
michael@0 117 return ipcfail(cx);
michael@0 118
michael@0 119 return ok(cx, status);
michael@0 120 }
michael@0 121
michael@0 122 bool
michael@0 123 CPOWProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 124 MutableHandle<JSPropertyDescriptor> desc)
michael@0 125 {
michael@0 126 FORWARD(getPropertyDescriptor, (cx, proxy, id, desc));
michael@0 127 }
michael@0 128
michael@0 129 bool
michael@0 130 JavaScriptParent::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 131 MutableHandle<JSPropertyDescriptor> desc)
michael@0 132 {
michael@0 133 ObjectId objId = idOf(proxy);
michael@0 134
michael@0 135 nsString idstr;
michael@0 136 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 137 return false;
michael@0 138
michael@0 139 ReturnStatus status;
michael@0 140 PPropertyDescriptor result;
michael@0 141 if (!CallGetPropertyDescriptor(objId, idstr, &status, &result))
michael@0 142 return ipcfail(cx);
michael@0 143 if (!ok(cx, status))
michael@0 144 return false;
michael@0 145
michael@0 146 return toDescriptor(cx, result, desc);
michael@0 147 }
michael@0 148
michael@0 149 bool
michael@0 150 CPOWProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
michael@0 151 HandleId id, MutableHandle<JSPropertyDescriptor> desc)
michael@0 152 {
michael@0 153 FORWARD(getOwnPropertyDescriptor, (cx, proxy, id, desc));
michael@0 154 }
michael@0 155
michael@0 156 bool
michael@0 157 JavaScriptParent::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 158 MutableHandle<JSPropertyDescriptor> desc)
michael@0 159 {
michael@0 160 ObjectId objId = idOf(proxy);
michael@0 161
michael@0 162 nsString idstr;
michael@0 163 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 164 return false;
michael@0 165
michael@0 166 ReturnStatus status;
michael@0 167 PPropertyDescriptor result;
michael@0 168 if (!CallGetOwnPropertyDescriptor(objId, idstr, &status, &result))
michael@0 169 return ipcfail(cx);
michael@0 170 if (!ok(cx, status))
michael@0 171 return false;
michael@0 172
michael@0 173 return toDescriptor(cx, result, desc);
michael@0 174 }
michael@0 175
michael@0 176 bool
michael@0 177 CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 178 MutableHandle<JSPropertyDescriptor> desc)
michael@0 179 {
michael@0 180 FORWARD(defineProperty, (cx, proxy, id, desc));
michael@0 181 }
michael@0 182
michael@0 183 bool
michael@0 184 JavaScriptParent::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
michael@0 185 MutableHandle<JSPropertyDescriptor> desc)
michael@0 186 {
michael@0 187 ObjectId objId = idOf(proxy);
michael@0 188
michael@0 189 nsString idstr;
michael@0 190 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 191 return false;
michael@0 192
michael@0 193 PPropertyDescriptor descriptor;
michael@0 194 if (!fromDescriptor(cx, desc, &descriptor))
michael@0 195 return false;
michael@0 196
michael@0 197 ReturnStatus status;
michael@0 198 if (!CallDefineProperty(objId, idstr, descriptor, &status))
michael@0 199 return ipcfail(cx);
michael@0 200
michael@0 201 return ok(cx, status);
michael@0 202 }
michael@0 203
michael@0 204 bool
michael@0 205 CPOWProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
michael@0 206 {
michael@0 207 FORWARD(getOwnPropertyNames, (cx, proxy, props));
michael@0 208 }
michael@0 209
michael@0 210 bool
michael@0 211 JavaScriptParent::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
michael@0 212 {
michael@0 213 return getPropertyNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props);
michael@0 214 }
michael@0 215
michael@0 216 bool
michael@0 217 CPOWProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
michael@0 218 {
michael@0 219 FORWARD(delete_, (cx, proxy, id, bp));
michael@0 220 }
michael@0 221
michael@0 222 bool
michael@0 223 JavaScriptParent::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
michael@0 224 {
michael@0 225 ObjectId objId = idOf(proxy);
michael@0 226
michael@0 227 nsString idstr;
michael@0 228 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 229 return false;
michael@0 230
michael@0 231 ReturnStatus status;
michael@0 232 if (!CallDelete(objId, idstr, &status, bp))
michael@0 233 return ipcfail(cx);
michael@0 234
michael@0 235 return ok(cx, status);
michael@0 236 }
michael@0 237
michael@0 238 bool
michael@0 239 CPOWProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
michael@0 240 {
michael@0 241 FORWARD(enumerate, (cx, proxy, props));
michael@0 242 }
michael@0 243
michael@0 244 bool
michael@0 245 JavaScriptParent::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
michael@0 246 {
michael@0 247 return getPropertyNames(cx, proxy, 0, props);
michael@0 248 }
michael@0 249
michael@0 250 bool
michael@0 251 CPOWProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
michael@0 252 {
michael@0 253 FORWARD(has, (cx, proxy, id, bp));
michael@0 254 }
michael@0 255
michael@0 256 bool
michael@0 257 JavaScriptParent::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
michael@0 258 {
michael@0 259 ObjectId objId = idOf(proxy);
michael@0 260
michael@0 261 nsString idstr;
michael@0 262 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 263 return false;
michael@0 264
michael@0 265 ReturnStatus status;
michael@0 266 if (!CallHas(objId, idstr, &status, bp))
michael@0 267 return ipcfail(cx);
michael@0 268
michael@0 269 return ok(cx, status);
michael@0 270 }
michael@0 271
michael@0 272 bool
michael@0 273 CPOWProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
michael@0 274 {
michael@0 275 FORWARD(hasOwn, (cx, proxy, id, bp));
michael@0 276 }
michael@0 277
michael@0 278 bool
michael@0 279 JavaScriptParent::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
michael@0 280 {
michael@0 281 ObjectId objId = idOf(proxy);
michael@0 282
michael@0 283 nsString idstr;
michael@0 284 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 285 return false;
michael@0 286
michael@0 287 ReturnStatus status;
michael@0 288 if (!CallHasOwn(objId, idstr, &status, bp))
michael@0 289 return ipcfail(cx);
michael@0 290
michael@0 291 return !!ok(cx, status);
michael@0 292 }
michael@0 293
michael@0 294 bool
michael@0 295 CPOWProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
michael@0 296 HandleId id, MutableHandleValue vp)
michael@0 297 {
michael@0 298 FORWARD(get, (cx, proxy, receiver, id, vp));
michael@0 299 }
michael@0 300
michael@0 301 bool
michael@0 302 JavaScriptParent::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
michael@0 303 HandleId id, MutableHandleValue vp)
michael@0 304 {
michael@0 305 ObjectId objId = idOf(proxy);
michael@0 306 ObjectId receiverId = idOf(receiver);
michael@0 307
michael@0 308 nsString idstr;
michael@0 309 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 310 return false;
michael@0 311
michael@0 312 JSVariant val;
michael@0 313 ReturnStatus status;
michael@0 314 if (!CallGet(objId, receiverId, idstr, &status, &val))
michael@0 315 return ipcfail(cx);
michael@0 316
michael@0 317 if (!ok(cx, status))
michael@0 318 return false;
michael@0 319
michael@0 320 return toValue(cx, val, vp);
michael@0 321 }
michael@0 322
michael@0 323 bool
michael@0 324 CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
michael@0 325 JS::HandleId id, bool strict, JS::MutableHandleValue vp)
michael@0 326 {
michael@0 327 FORWARD(set, (cx, proxy, receiver, id, strict, vp));
michael@0 328 }
michael@0 329
michael@0 330 bool
michael@0 331 JavaScriptParent::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
michael@0 332 JS::HandleId id, bool strict, JS::MutableHandleValue vp)
michael@0 333 {
michael@0 334 ObjectId objId = idOf(proxy);
michael@0 335 ObjectId receiverId = idOf(receiver);
michael@0 336
michael@0 337 nsString idstr;
michael@0 338 if (!convertIdToGeckoString(cx, id, &idstr))
michael@0 339 return false;
michael@0 340
michael@0 341 JSVariant val;
michael@0 342 if (!toVariant(cx, vp, &val))
michael@0 343 return false;
michael@0 344
michael@0 345 ReturnStatus status;
michael@0 346 JSVariant result;
michael@0 347 if (!CallSet(objId, receiverId, idstr, strict, val, &status, &result))
michael@0 348 return ipcfail(cx);
michael@0 349
michael@0 350 if (!ok(cx, status))
michael@0 351 return false;
michael@0 352
michael@0 353 return toValue(cx, result, vp);
michael@0 354 }
michael@0 355
michael@0 356 bool
michael@0 357 CPOWProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
michael@0 358 {
michael@0 359 FORWARD(keys, (cx, proxy, props));
michael@0 360 }
michael@0 361
michael@0 362 bool
michael@0 363 JavaScriptParent::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
michael@0 364 {
michael@0 365 return getPropertyNames(cx, proxy, JSITER_OWNONLY, props);
michael@0 366 }
michael@0 367
michael@0 368 bool
michael@0 369 CPOWProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
michael@0 370 {
michael@0 371 FORWARD(isExtensible, (cx, proxy, extensible));
michael@0 372 }
michael@0 373
michael@0 374 bool
michael@0 375 JavaScriptParent::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
michael@0 376 {
michael@0 377 ObjectId objId = idOf(proxy);
michael@0 378
michael@0 379 ReturnStatus status;
michael@0 380 if (!CallIsExtensible(objId, &status, extensible))
michael@0 381 return ipcfail(cx);
michael@0 382
michael@0 383 return ok(cx, status);
michael@0 384 }
michael@0 385
michael@0 386 bool
michael@0 387 CPOWProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
michael@0 388 {
michael@0 389 FORWARD(call, (cx, proxy, args));
michael@0 390 }
michael@0 391
michael@0 392 bool
michael@0 393 JavaScriptParent::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
michael@0 394 {
michael@0 395 ObjectId objId = idOf(proxy);
michael@0 396
michael@0 397 InfallibleTArray<JSParam> vals;
michael@0 398 AutoValueVector outobjects(cx);
michael@0 399
michael@0 400 RootedValue v(cx);
michael@0 401 for (size_t i = 0; i < args.length() + 2; i++) {
michael@0 402 v = args.base()[i];
michael@0 403 if (v.isObject()) {
michael@0 404 RootedObject obj(cx, &v.toObject());
michael@0 405 if (xpc::IsOutObject(cx, obj)) {
michael@0 406 // Make sure it is not an in-out object.
michael@0 407 bool found;
michael@0 408 if (!JS_HasProperty(cx, obj, "value", &found))
michael@0 409 return false;
michael@0 410 if (found) {
michael@0 411 JS_ReportError(cx, "in-out objects cannot be sent via CPOWs yet");
michael@0 412 return false;
michael@0 413 }
michael@0 414
michael@0 415 vals.AppendElement(JSParam(void_t()));
michael@0 416 if (!outobjects.append(ObjectValue(*obj)))
michael@0 417 return false;
michael@0 418 continue;
michael@0 419 }
michael@0 420 }
michael@0 421 JSVariant val;
michael@0 422 if (!toVariant(cx, v, &val))
michael@0 423 return false;
michael@0 424 vals.AppendElement(JSParam(val));
michael@0 425 }
michael@0 426
michael@0 427 JSVariant result;
michael@0 428 ReturnStatus status;
michael@0 429 InfallibleTArray<JSParam> outparams;
michael@0 430 if (!CallCall(objId, vals, &status, &result, &outparams))
michael@0 431 return ipcfail(cx);
michael@0 432 if (!ok(cx, status))
michael@0 433 return false;
michael@0 434
michael@0 435 if (outparams.Length() != outobjects.length())
michael@0 436 return ipcfail(cx);
michael@0 437
michael@0 438 RootedObject obj(cx);
michael@0 439 for (size_t i = 0; i < outparams.Length(); i++) {
michael@0 440 // Don't bother doing anything for outparams that weren't set.
michael@0 441 if (outparams[i].type() == JSParam::Tvoid_t)
michael@0 442 continue;
michael@0 443
michael@0 444 // Take the value the child process returned, and set it on the XPC
michael@0 445 // object.
michael@0 446 if (!toValue(cx, outparams[i], &v))
michael@0 447 return false;
michael@0 448
michael@0 449 obj = &outobjects[i].toObject();
michael@0 450 if (!JS_SetProperty(cx, obj, "value", v))
michael@0 451 return false;
michael@0 452 }
michael@0 453
michael@0 454 if (!toValue(cx, result, args.rval()))
michael@0 455 return false;
michael@0 456
michael@0 457 return true;
michael@0 458 }
michael@0 459
michael@0 460
michael@0 461 bool
michael@0 462 CPOWProxyHandler::objectClassIs(HandleObject proxy, js::ESClassValue classValue, JSContext *cx)
michael@0 463 {
michael@0 464 FORWARD(objectClassIs, (cx, proxy, classValue));
michael@0 465 }
michael@0 466
michael@0 467 bool
michael@0 468 JavaScriptParent::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue classValue)
michael@0 469 {
michael@0 470 ObjectId objId = idOf(proxy);
michael@0 471
michael@0 472 // This function is assumed infallible, so we just return false if the IPC
michael@0 473 // channel fails.
michael@0 474 bool result;
michael@0 475 if (!CallObjectClassIs(objId, classValue, &result))
michael@0 476 return false;
michael@0 477
michael@0 478 return result;
michael@0 479 }
michael@0 480
michael@0 481 const char *
michael@0 482 CPOWProxyHandler::className(JSContext *cx, HandleObject proxy)
michael@0 483 {
michael@0 484 JavaScriptParent *parent = ParentOf(proxy);
michael@0 485 if (!parent->active())
michael@0 486 return "<dead CPOW>";
michael@0 487 return parent->className(cx, proxy);
michael@0 488 }
michael@0 489
michael@0 490 const char *
michael@0 491 JavaScriptParent::className(JSContext *cx, HandleObject proxy)
michael@0 492 {
michael@0 493 ObjectId objId = idOf(proxy);
michael@0 494
michael@0 495 nsString name;
michael@0 496 if (!CallClassName(objId, &name))
michael@0 497 return "<error>";
michael@0 498
michael@0 499 return ToNewCString(name);
michael@0 500 }
michael@0 501
michael@0 502 void
michael@0 503 CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy)
michael@0 504 {
michael@0 505 ParentOf(proxy)->drop(proxy);
michael@0 506 }
michael@0 507
michael@0 508 void
michael@0 509 JavaScriptParent::drop(JSObject *obj)
michael@0 510 {
michael@0 511 ObjectId objId = idOf(obj);
michael@0 512
michael@0 513 objects_.remove(objId);
michael@0 514 if (!inactive_ && !SendDropObject(objId))
michael@0 515 (void)0;
michael@0 516 decref();
michael@0 517 }
michael@0 518
michael@0 519 bool
michael@0 520 JavaScriptParent::init()
michael@0 521 {
michael@0 522 if (!JavaScriptShared::init())
michael@0 523 return false;
michael@0 524
michael@0 525 return true;
michael@0 526 }
michael@0 527
michael@0 528 bool
michael@0 529 JavaScriptParent::makeId(JSContext *cx, JSObject *obj, ObjectId *idp)
michael@0 530 {
michael@0 531 obj = js::CheckedUnwrap(obj, false);
michael@0 532 if (!obj || !IsProxy(obj) || GetProxyHandler(obj) != &CPOWProxyHandler::singleton) {
michael@0 533 JS_ReportError(cx, "cannot ipc non-cpow object");
michael@0 534 return false;
michael@0 535 }
michael@0 536
michael@0 537 *idp = idOf(obj);
michael@0 538 return true;
michael@0 539 }
michael@0 540
michael@0 541 bool
michael@0 542 JavaScriptParent::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t flags, AutoIdVector &props)
michael@0 543 {
michael@0 544 ObjectId objId = idOf(proxy);
michael@0 545
michael@0 546 ReturnStatus status;
michael@0 547 InfallibleTArray<nsString> names;
michael@0 548 if (!CallGetPropertyNames(objId, flags, &status, &names))
michael@0 549 return ipcfail(cx);
michael@0 550 if (!ok(cx, status))
michael@0 551 return false;
michael@0 552
michael@0 553 for (size_t i = 0; i < names.Length(); i++) {
michael@0 554 RootedId name(cx);
michael@0 555 if (!convertGeckoStringToId(cx, names[i], &name))
michael@0 556 return false;
michael@0 557 if (!props.append(name))
michael@0 558 return false;
michael@0 559 }
michael@0 560
michael@0 561 return true;
michael@0 562 }
michael@0 563
michael@0 564 JSObject *
michael@0 565 JavaScriptParent::unwrap(JSContext *cx, ObjectId objId)
michael@0 566 {
michael@0 567 RootedObject obj(cx, findObject(objId));
michael@0 568 if (obj) {
michael@0 569 if (!JS_WrapObject(cx, &obj))
michael@0 570 return nullptr;
michael@0 571 return obj;
michael@0 572 }
michael@0 573
michael@0 574 if (objId > MAX_CPOW_IDS) {
michael@0 575 JS_ReportError(cx, "unusable CPOW id");
michael@0 576 return nullptr;
michael@0 577 }
michael@0 578
michael@0 579 bool callable = !!(objId & OBJECT_IS_CALLABLE);
michael@0 580
michael@0 581 RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
michael@0 582
michael@0 583 RootedValue v(cx, UndefinedValue());
michael@0 584 ProxyOptions options;
michael@0 585 options.selectDefaultClass(callable);
michael@0 586 obj = NewProxyObject(cx,
michael@0 587 &CPOWProxyHandler::singleton,
michael@0 588 v,
michael@0 589 nullptr,
michael@0 590 global,
michael@0 591 options);
michael@0 592 if (!obj)
michael@0 593 return nullptr;
michael@0 594
michael@0 595 if (!objects_.add(objId, obj))
michael@0 596 return nullptr;
michael@0 597
michael@0 598 // Incref once we know the decref will be called.
michael@0 599 incref();
michael@0 600
michael@0 601 SetProxyExtra(obj, 0, PrivateValue(this));
michael@0 602 SetProxyExtra(obj, 1, DoubleValue(BitwiseCast<double>(objId)));
michael@0 603 return obj;
michael@0 604 }
michael@0 605
michael@0 606 bool
michael@0 607 JavaScriptParent::ipcfail(JSContext *cx)
michael@0 608 {
michael@0 609 JS_ReportError(cx, "child process crashed or timedout");
michael@0 610 return false;
michael@0 611 }
michael@0 612
michael@0 613 bool
michael@0 614 JavaScriptParent::ok(JSContext *cx, const ReturnStatus &status)
michael@0 615 {
michael@0 616 if (status.type() == ReturnStatus::TReturnSuccess)
michael@0 617 return true;
michael@0 618
michael@0 619 if (status.type() == ReturnStatus::TReturnStopIteration)
michael@0 620 return JS_ThrowStopIteration(cx);
michael@0 621
michael@0 622 RootedValue exn(cx);
michael@0 623 if (!toValue(cx, status.get_ReturnException().exn(), &exn))
michael@0 624 return false;
michael@0 625
michael@0 626 JS_SetPendingException(cx, exn);
michael@0 627 return false;
michael@0 628 }
michael@0 629
michael@0 630 void
michael@0 631 JavaScriptParent::decref()
michael@0 632 {
michael@0 633 refcount_--;
michael@0 634 if (!refcount_)
michael@0 635 delete this;
michael@0 636 }
michael@0 637
michael@0 638 void
michael@0 639 JavaScriptParent::incref()
michael@0 640 {
michael@0 641 refcount_++;
michael@0 642 }
michael@0 643
michael@0 644 void
michael@0 645 JavaScriptParent::ActorDestroy(ActorDestroyReason why)
michael@0 646 {
michael@0 647 inactive_ = true;
michael@0 648 }
michael@0 649
michael@0 650 /* static */ bool
michael@0 651 JavaScriptParent::IsCPOW(JSObject *obj)
michael@0 652 {
michael@0 653 return IsProxy(obj) && GetProxyHandler(obj) == &CPOWProxyHandler::singleton;
michael@0 654 }
michael@0 655
michael@0 656 /* static */ nsresult
michael@0 657 JavaScriptParent::InstanceOf(JSObject *proxy, const nsID *id, bool *bp)
michael@0 658 {
michael@0 659 JavaScriptParent *parent = ParentOf(proxy);
michael@0 660 if (!parent->active())
michael@0 661 return NS_ERROR_UNEXPECTED;
michael@0 662 return parent->instanceOf(proxy, id, bp);
michael@0 663 }
michael@0 664
michael@0 665 nsresult
michael@0 666 JavaScriptParent::instanceOf(JSObject *obj, const nsID *id, bool *bp)
michael@0 667 {
michael@0 668 ObjectId objId = idOf(obj);
michael@0 669
michael@0 670 JSIID iid;
michael@0 671 ConvertID(*id, &iid);
michael@0 672
michael@0 673 ReturnStatus status;
michael@0 674 if (!CallInstanceOf(objId, iid, &status, bp))
michael@0 675 return NS_ERROR_UNEXPECTED;
michael@0 676
michael@0 677 if (status.type() != ReturnStatus::TReturnSuccess)
michael@0 678 return NS_ERROR_UNEXPECTED;
michael@0 679
michael@0 680 return NS_OK;
michael@0 681 }
michael@0 682
michael@0 683 /* static */ bool
michael@0 684 JavaScriptParent::DOMInstanceOf(JSContext *cx, JSObject *proxy, int prototypeID, int depth, bool *bp)
michael@0 685 {
michael@0 686 FORWARD(domInstanceOf, (cx, proxy, prototypeID, depth, bp));
michael@0 687 }
michael@0 688
michael@0 689 bool
michael@0 690 JavaScriptParent::domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp)
michael@0 691 {
michael@0 692 ObjectId objId = idOf(obj);
michael@0 693
michael@0 694 ReturnStatus status;
michael@0 695 if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
michael@0 696 return ipcfail(cx);
michael@0 697
michael@0 698 return ok(cx, status);
michael@0 699 }
michael@0 700
michael@0 701 mozilla::ipc::IProtocol*
michael@0 702 JavaScriptParent::CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx)
michael@0 703 {
michael@0 704 ContentParent *contentParent = aCtx->GetContentParent();
michael@0 705 nsAutoPtr<PJavaScriptParent> actor(contentParent->AllocPJavaScriptParent());
michael@0 706 if (!actor || !contentParent->RecvPJavaScriptConstructor(actor)) {
michael@0 707 return nullptr;
michael@0 708 }
michael@0 709 return actor.forget();
michael@0 710 }

mercurial