Bug 769273 - part2: Refactoring NukeChromeCrossCompartmentWrappersForGlobal. r=bholley

This commit is contained in:
Gabor Krizsanits 2012-07-17 17:36:15 +02:00
parent 1c23b37d56
commit 7a00ad07d8
4 changed files with 53 additions and 45 deletions

View File

@ -6860,16 +6860,17 @@ public:
NS_ENSURE_TRUE(currentInner, NS_OK); NS_ENSURE_TRUE(currentInner, NS_OK);
JSObject* obj = currentInner->FastGetGlobalJSObject(); JSObject* obj = currentInner->FastGetGlobalJSObject();
// We only want to nuke wrappers for chrome->content case // We only want to nuke wrappers for the chrome->content case
if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) { if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
JSContext* cx = JSContext* cx =
nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(); nsContentUtils::ThreadJSContextStack()->GetSafeJSContext();
JSAutoRequest ar(cx); JSAutoRequest ar(cx);
js::NukeCrossCompartmentWrappers(cx,
js::NukeChromeCrossCompartmentWrappersForGlobal(cx, obj, js::ChromeCompartmentsOnly(),
window->IsInnerWindow() ? js::DontNukeForGlobalObject : js::SingleCompartment(js::GetObjectCompartment(obj)),
js::NukeForGlobalObject); window->IsInnerWindow() ? js::DontNukeForGlobalObject :
js::NukeForGlobalObject);
} }
} }

View File

@ -821,9 +821,47 @@ typedef enum NukedGlobalHandling {
DontNukeForGlobalObject DontNukeForGlobalObject
} NukedGlobalHandling; } NukedGlobalHandling;
// These filters are designed to be ephemeral stack classes, and thus don't
// do any rooting or holding of their members.
struct CompartmentFilter {
virtual bool match(JSCompartment *c) const = 0;
};
struct AllCompartments : public CompartmentFilter {
virtual bool match(JSCompartment *c) const { return true; };
};
struct ContentCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return !IsSystemCompartment(c);
};
};
struct ChromeCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return IsSystemCompartment(c);
};
};
struct SingleCompartment : public CompartmentFilter {
JSCompartment *ours;
SingleCompartment(JSCompartment *c) : ours(c) {};
virtual bool match(JSCompartment *c) const { return c == ours; };
};
struct CompartmentsWithPrincipals : public CompartmentFilter {
JSPrincipals *principals;
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {};
virtual bool match(JSCompartment *c) const {
return JS_GetCompartmentPrincipals(c) == principals;
};
};
extern JS_FRIEND_API(JSBool) extern JS_FRIEND_API(JSBool)
NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj, NukeCrossCompartmentWrappers(JSContext* cx,
NukedGlobalHandling nukeGlobal); const CompartmentFilter& sourceFilter,
const CompartmentFilter& targetFilter,
NukedGlobalHandling nukeGlobal);
} /* namespace js */ } /* namespace js */

View File

@ -1062,20 +1062,20 @@ js::NukeCrossCompartmentWrapper(JSObject *wrapper)
* option of how to handle the global object. * option of how to handle the global object.
*/ */
JS_FRIEND_API(JSBool) JS_FRIEND_API(JSBool)
js::NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj, js::NukeCrossCompartmentWrappers(JSContext* cx,
js::NukedGlobalHandling nukeGlobal) const CompartmentFilter& sourceFilter,
const CompartmentFilter& targetFilter,
js::NukedGlobalHandling nukeGlobal)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
JSRuntime *rt = cx->runtime; JSRuntime *rt = cx->runtime;
JSObject *global = &obj->global();
// Iterate through scopes looking for system cross compartment wrappers // Iterate through scopes looking for system cross compartment wrappers
// that point to an object that shares a global with obj. // that point to an object that shares a global with obj.
for (CompartmentsIter c(rt); !c.done(); c.next()) { for (CompartmentsIter c(rt); !c.done(); c.next()) {
// Skip non-system compartments because this breaks the web. // Skip non-system compartments because this breaks the web.
if (!js::IsSystemCompartment(c)) if (!sourceFilter.match(c))
continue; continue;
// Iterate the wrappers looking for anything interesting. // Iterate the wrappers looking for anything interesting.
@ -1090,10 +1090,10 @@ js::NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj,
JSObject *wobj = &e.front().value.get().toObject(); JSObject *wobj = &e.front().value.get().toObject();
JSObject *wrapped = UnwrapObject(wobj, false); JSObject *wrapped = UnwrapObject(wobj, false);
if (nukeGlobal == DontNukeForGlobalObject && wrapped == global) if (nukeGlobal == DontNukeForGlobalObject && wrapped->isGlobal())
continue; continue;
if (&wrapped->global() == global) { if (targetFilter.match(wrapped->compartment())) {
// We found a wrapper to nuke. // We found a wrapper to nuke.
e.removeFront(); e.removeFront();
NukeCrossCompartmentWrapper(wobj); NukeCrossCompartmentWrapper(wobj);

View File

@ -340,37 +340,6 @@ RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
// API to recompute all cross-compartment wrappers whose source and target // API to recompute all cross-compartment wrappers whose source and target
// match the given filters. // match the given filters.
//
// These filters are designed to be ephemeral stack classes, and thus don't
// do any rooting or holding of their members.
struct CompartmentFilter {
virtual bool match(JSCompartment *c) const = 0;
};
struct AllCompartments : public CompartmentFilter {
virtual bool match(JSCompartment *c) const { return true; }
};
struct ContentCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return !IsSystemCompartment(c);
}
};
struct SingleCompartment : public CompartmentFilter {
JSCompartment *ours;
SingleCompartment(JSCompartment *c) : ours(c) {}
virtual bool match(JSCompartment *c) const { return c == ours; }
};
struct CompartmentsWithPrincipals : public CompartmentFilter {
JSPrincipals *principals;
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {}
virtual bool match(JSCompartment *c) const {
return JS_GetCompartmentPrincipals(c) == principals;
}
};
JS_FRIEND_API(bool) JS_FRIEND_API(bool)
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter, RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter); const CompartmentFilter &targetFilter);