mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1065811 - Track Xray waivers with CPOWs. r=billm
This commit is contained in:
parent
8b65a1f10b
commit
8e8a7d28c3
@ -223,7 +223,7 @@
|
||||
// (the privileged junk scope, but we don't have a good way to test for that
|
||||
// specifically).
|
||||
is(unprivilegedObject.expando, undefined, "parent->child references should get Xrays");
|
||||
todo_is(unprivilegedObject.wrappedJSObject.expando, 42, "parent->child references should get waivable Xrays - see bug 1065811");
|
||||
is(unprivilegedObject.wrappedJSObject.expando, 42, "parent->child references should get waivable Xrays");
|
||||
|
||||
// Send an object to the child to let it verify invariants in the other direction.
|
||||
function passMe() { return 42; };
|
||||
|
@ -53,7 +53,8 @@ void
|
||||
JavaScriptChild::updateWeakPointers()
|
||||
{
|
||||
objects_.sweep();
|
||||
objectIds_.sweep();
|
||||
unwaivedObjectIds_.sweep();
|
||||
waivedObjectIds_.sweep();
|
||||
}
|
||||
|
||||
JSObject *
|
||||
|
@ -96,7 +96,7 @@ class Logging
|
||||
|
||||
if (local == incoming) {
|
||||
JS::RootedObject obj(cx);
|
||||
obj = shared->findObjectById(id);
|
||||
obj = shared->objects_.find(id);
|
||||
if (obj) {
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
objDesc = js_ObjectClassName(cx, obj);
|
||||
|
@ -53,7 +53,8 @@ JavaScriptParent::trace(JSTracer *trc)
|
||||
{
|
||||
if (active()) {
|
||||
objects_.trace(trc);
|
||||
objectIds_.trace(trc);
|
||||
unwaivedObjectIds_.trace(trc);
|
||||
waivedObjectIds_.trace(trc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "WrapperFactory.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace js;
|
||||
@ -186,7 +187,9 @@ JavaScriptShared::init()
|
||||
return false;
|
||||
if (!cpows_.init())
|
||||
return false;
|
||||
if (!objectIds_.init())
|
||||
if (!unwaivedObjectIds_.init())
|
||||
return false;
|
||||
if (!waivedObjectIds_.init())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -383,7 +386,7 @@ JavaScriptShared::ConvertID(const JSIID &from, nsID *to)
|
||||
JSObject *
|
||||
JavaScriptShared::findObjectById(JSContext *cx, const ObjectId &objId)
|
||||
{
|
||||
RootedObject obj(cx, findObjectById(objId));
|
||||
RootedObject obj(cx, objects_.find(objId));
|
||||
if (!obj) {
|
||||
JS_ReportError(cx, "operation not possible on dead CPOW");
|
||||
return nullptr;
|
||||
@ -394,8 +397,13 @@ JavaScriptShared::findObjectById(JSContext *cx, const ObjectId &objId)
|
||||
// can access objects in other compartments using cross-compartment
|
||||
// wrappers.
|
||||
JSAutoCompartment ac(cx, scopeForTargetObjects());
|
||||
if (!JS_WrapObject(cx, &obj))
|
||||
return nullptr;
|
||||
if (objId.hasXrayWaiver()) {
|
||||
if (!xpc::WrapperFactory::WaiveXrayAndWrap(cx, &obj))
|
||||
return nullptr;
|
||||
} else {
|
||||
if (!JS_WrapObject(cx, &obj))
|
||||
return nullptr;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@ class ObjectId {
|
||||
static const size_t FLAG_BITS = 1;
|
||||
static const uint64_t SERIAL_NUMBER_MAX = (uint64_t(1) << SERIAL_NUMBER_BITS) - 1;
|
||||
|
||||
explicit ObjectId(uint64_t serialNumber, bool isCallable)
|
||||
: serialNumber_(serialNumber), isCallable_(isCallable)
|
||||
explicit ObjectId(uint64_t serialNumber, bool hasXrayWaiver)
|
||||
: serialNumber_(serialNumber), hasXrayWaiver_(hasXrayWaiver)
|
||||
{
|
||||
if (MOZ_UNLIKELY(serialNumber == 0 || serialNumber > SERIAL_NUMBER_MAX))
|
||||
MOZ_CRASH("Bad CPOW Id");
|
||||
@ -33,17 +33,17 @@ class ObjectId {
|
||||
|
||||
bool operator==(const ObjectId &other) const {
|
||||
bool equal = serialNumber() == other.serialNumber();
|
||||
MOZ_ASSERT_IF(equal, isCallable() == other.isCallable());
|
||||
MOZ_ASSERT_IF(equal, hasXrayWaiver() == other.hasXrayWaiver());
|
||||
return equal;
|
||||
}
|
||||
|
||||
bool isNull() { return !serialNumber_; }
|
||||
|
||||
uint64_t serialNumber() const { return serialNumber_; }
|
||||
bool isCallable() const { return isCallable_; }
|
||||
bool hasXrayWaiver() const { return hasXrayWaiver_; }
|
||||
uint64_t serialize() const {
|
||||
MOZ_ASSERT(serialNumber(), "Don't send a null ObjectId over IPC");
|
||||
return uint64_t((serialNumber() << FLAG_BITS) | ((isCallable() ? 1 : 0) << 0));
|
||||
return uint64_t((serialNumber() << FLAG_BITS) | ((hasXrayWaiver() ? 1 : 0) << 0));
|
||||
}
|
||||
|
||||
static ObjectId nullId() { return ObjectId(); }
|
||||
@ -52,10 +52,10 @@ class ObjectId {
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectId() : serialNumber_(0), isCallable_(false) {}
|
||||
ObjectId() : serialNumber_(0), hasXrayWaiver_(false) {}
|
||||
|
||||
uint64_t serialNumber_ : SERIAL_NUMBER_BITS;
|
||||
bool isCallable_ : 1;
|
||||
bool hasXrayWaiver_ : 1;
|
||||
};
|
||||
|
||||
class JavaScriptShared;
|
||||
@ -174,9 +174,6 @@ class JavaScriptShared
|
||||
JSObject *findCPOWById(const ObjectId &objId) {
|
||||
return cpows_.find(objId);
|
||||
}
|
||||
JSObject *findObjectById(const ObjectId &objId) {
|
||||
return objects_.find(objId);
|
||||
}
|
||||
JSObject *findObjectById(JSContext *cx, const ObjectId &objId);
|
||||
|
||||
static bool LoggingEnabled() { return sLoggingEnabled; }
|
||||
@ -196,7 +193,27 @@ class JavaScriptShared
|
||||
IdToObjectMap cpows_;
|
||||
|
||||
uint64_t nextSerialNumber_;
|
||||
ObjectToIdMap objectIds_;
|
||||
|
||||
// CPOW references can be weak, and any object we store in a map may be
|
||||
// GCed (at which point the CPOW will report itself "dead" to the owner).
|
||||
// This means that we don't want to store any js::Wrappers in the CPOW map,
|
||||
// because CPOW will die if the wrapper is GCed, even if the underlying
|
||||
// object is still alive.
|
||||
//
|
||||
// This presents a tricky situation for Xray waivers, since they're normally
|
||||
// represented as a special same-compartment wrapper. We have to strip them
|
||||
// off before putting them in the id-to-object and object-to-id maps, so we
|
||||
// need a way of distinguishing them at lookup-time.
|
||||
//
|
||||
// For the id-to-object map, we encode waiver-or-not information into the id
|
||||
// itself, which lets us do the right thing when accessing the object.
|
||||
//
|
||||
// For the object-to-id map, we just keep two maps, one for each type.
|
||||
ObjectToIdMap unwaivedObjectIds_;
|
||||
ObjectToIdMap waivedObjectIds_;
|
||||
ObjectToIdMap &objectIdMap(bool waiver) {
|
||||
return waiver ? waivedObjectIds_ : unwaivedObjectIds_;
|
||||
}
|
||||
|
||||
static bool sLoggingInitialized;
|
||||
static bool sLoggingEnabled;
|
||||
|
@ -679,9 +679,9 @@ WrapperAnswer::AnswerIsConstructor(const ObjectId &objId, bool *result)
|
||||
bool
|
||||
WrapperAnswer::RecvDropObject(const ObjectId &objId)
|
||||
{
|
||||
JSObject *obj = findObjectById(objId);
|
||||
JSObject *obj = objects_.find(objId);
|
||||
if (obj) {
|
||||
objectIds_.remove(obj);
|
||||
objectIdMap(objId.hasXrayWaiver()).remove(obj);
|
||||
objects_.remove(objId);
|
||||
}
|
||||
return true;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "WrapperFactory.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace JS;
|
||||
@ -870,14 +871,17 @@ WrapperOwner::toObjectVariant(JSContext *cx, JSObject *objArg, ObjectVariant *ob
|
||||
// wrappers, then the wrapper might be GCed while the target remained alive.
|
||||
// Whenever operating on an object that comes from the table, we wrap it
|
||||
// in findObjectById.
|
||||
obj = js::UncheckedUnwrap(obj, false);
|
||||
unsigned wrapperFlags = 0;
|
||||
obj = js::UncheckedUnwrap(obj, false, &wrapperFlags);
|
||||
if (obj && IsCPOW(obj) && OwnerOf(obj) == this) {
|
||||
*objVarp = LocalObject(idOf(obj).serialize());
|
||||
return true;
|
||||
}
|
||||
bool waiveXray = wrapperFlags & xpc::WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG;
|
||||
|
||||
ObjectId id = objectIds_.find(obj);
|
||||
ObjectId id = objectIdMap(waiveXray).find(obj);
|
||||
if (!id.isNull()) {
|
||||
MOZ_ASSERT(id.hasXrayWaiver() == waiveXray);
|
||||
*objVarp = RemoteObject(id.serialize());
|
||||
return true;
|
||||
}
|
||||
@ -887,10 +891,10 @@ WrapperOwner::toObjectVariant(JSContext *cx, JSObject *objArg, ObjectVariant *ob
|
||||
if (mozilla::dom::IsDOMObject(obj))
|
||||
mozilla::dom::TryPreserveWrapper(obj);
|
||||
|
||||
id = ObjectId(nextSerialNumber_++, JS::IsCallable(obj));
|
||||
id = ObjectId(nextSerialNumber_++, waiveXray);
|
||||
if (!objects_.add(id, obj))
|
||||
return false;
|
||||
if (!objectIds_.add(cx, obj, id))
|
||||
if (!objectIdMap(waiveXray).add(cx, obj, id))
|
||||
return false;
|
||||
|
||||
*objVarp = RemoteObject(id.serialize());
|
||||
|
Loading…
Reference in New Issue
Block a user