Bug 1515582. Remove the separate XBL scope setup. r=bholley

With these changes, XBL just runs in the window scope of whatever document it's
attached to.  Since (outside of tests and "remote XUL") we no longer attach XBL
to web documents, this is fine.  And "remote XUL" already ran without the XBL
scope.

Native anonymous content, which used to be placed in the XBL scope to hide it
from the page, is now placed in the unprivileged junk scope, so it stays hidden
from the page.

dom/xbl/test/test_bug944407.xul is being removed because we are changing the
behavior it's trying to test for.  Since we now always put the XBL in the same
scope as the page, script is enabled for the XBL if and only if it's enabled for
the page.

dom/base/test/test_bug419527.xhtml, dom/events/test/test_bug391568.xhtml,
dom/xbl/test/test_bug1086996.xhtml are being switched to a chrome test because
otherwise the XBL can't see the getAnonymousNodes method.

All the XBL bits are being removed from test_interfaces because we no longer
have a separate XBL scope to test the behavior of.

js/xpconnect/tests/mochitest/test_nac.xhtml is being removed because XBL no
longer has access to NAC unless the page it's attached to does too, so the test
doesn't really make sense.

layout/xul/test/test_bug1197913.xul is being switched to a chrome test because
its XUL elements use bindings that rely on APIs that are not exposed to normal
web content.

layout/reftests/bugs/495385-2f.xhtml is being removed because I can't think of
a sane way to test that in the new world, short of running the reftest as
chrome.  And it doesn't seem worthwhile to look for a way to do that.

dom/xbl/test/test_bug1098628_throw_from_construct.xhtml now needs to
expectUncaughtException(), because the exception is now being thrown in Window
scope.

dom/xbl/test/test_bug1359859.xhtml needs to expectUncaughtException() as needed
and not use XPCNativeWrapper (which it doesn't need to anyway now).

dom/xbl/test/test_bug389322.xhtml, dom/xbl/test/test_bug400705.xhtml,
dom/xbl/test/test_bug401907.xhtml, dom/xbl/test/test_bug403162.xhtml,
dom/xbl/test/test_bug526178.xhtml, dom/xbl/test/test_bug639338.xhtml don't need
to use XPCNativeWrapper anymore.

dom/xbl/test/test_bug821850.html is being removed because it exists only to test XBL scopes.

dom/xbl/test/file_bug950909.xml is being changed to work without a separate XBL
scope (though whether the test still makes sense at that point is a bit questionable).

Differential Revision: https://phabricator.services.mozilla.com/D19260

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2019-02-11 21:51:47 +00:00
parent f9b1e042ff
commit bc348929b6
46 changed files with 93 additions and 850 deletions

View File

@ -4759,22 +4759,11 @@ inline mozilla::dom::Document* nsINode::GetOwnerDocument() const {
inline nsINode* nsINode::OwnerDocAsNode() const { return OwnerDoc(); }
// ShouldUseXBLScope is defined here as a template so that we can get the faster
// version of IsInAnonymousSubtree if we're statically known to be an
// nsIContent. we could try defining ShouldUseXBLScope separately on nsINode
// and nsIContent, but then we couldn't put its nsINode implementation here
// (because this header does not include nsIContent) and we can't put it in
// nsIContent.h, because the definition of nsIContent::IsInAnonymousSubtree is
// in nsIContentInlines.h. And then we get include hell from people trying to
// call nsINode::GetParentObject but not including nsIContentInlines.h and with
// no really good way to include it.
template <typename T>
inline bool ShouldUseXBLScope(const T* aNode) {
return aNode->IsInAnonymousSubtree();
inline bool ShouldUseNACScope(const nsINode* aNode) {
return aNode->IsInNativeAnonymousSubtree();
}
template <typename T>
inline bool ShouldUseUAWidgetScope(const T* aNode) {
inline bool ShouldUseUAWidgetScope(const nsINode* aNode) {
return aNode->IsInUAWidget();
}
@ -4782,8 +4771,8 @@ inline mozilla::dom::ParentObject nsINode::GetParentObject() const {
mozilla::dom::ParentObject p(OwnerDoc());
// Note that mReflectionScope is a no-op for chrome, and other places
// where we don't check this value.
if (ShouldUseXBLScope(this)) {
p.mReflectionScope = mozilla::dom::ReflectionScope::XBL;
if (ShouldUseNACScope(this)) {
p.mReflectionScope = mozilla::dom::ReflectionScope::NAC;
} else if (ShouldUseUAWidgetScope(this)) {
p.mReflectionScope = mozilla::dom::ReflectionScope::UAWidget;
}

View File

@ -1994,9 +1994,6 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
if (aDocument != oldDoc) {
JS::SetRealmPrincipals(realm,
nsJSPrincipals::get(aDocument->NodePrincipal()));
// Make sure we clear out the old content XBL scope, so the new one will
// get created with a principal that subsumes our new principal.
xpc::ClearContentXBLScope(newInnerGlobal);
}
} else {
if (aState) {

View File

@ -1194,7 +1194,7 @@ static void CheckForOutdatedParent(nsINode* aParent, nsINode* aNode,
}
static nsresult UpdateGlobalsInSubtree(nsIContent* aRoot) {
MOZ_ASSERT(ShouldUseXBLScope(aRoot));
MOZ_ASSERT(ShouldUseNACScope(aRoot));
// Start off with no global so we don't fire any error events on failure.
AutoJSAPI jsapi;
jsapi.Init();
@ -1272,12 +1272,13 @@ nsresult nsINode::InsertChildBefore(nsIContent* aKid,
nsIContent* parent = IsContent() ? AsContent() : nullptr;
bool wasInXBLScope = ShouldUseXBLScope(aKid);
// XXXbz Do we even need this code anymore?
bool wasInNACScope = ShouldUseNACScope(aKid);
nsresult rv = aKid->BindToTree(doc, parent,
parent ? parent->GetBindingParent() : nullptr);
if (NS_SUCCEEDED(rv) && !wasInXBLScope && ShouldUseXBLScope(aKid)) {
MOZ_ASSERT(ShouldUseXBLScope(this),
"Why does the kid need to use an XBL scope?");
if (NS_SUCCEEDED(rv) && !wasInNACScope && ShouldUseNACScope(aKid)) {
MOZ_ASSERT(ShouldUseNACScope(this),
"Why does the kid need to use an the anonymous content scope?");
rv = UpdateGlobalsInSubtree(aKid);
}
if (NS_FAILED(rv)) {
@ -2657,9 +2658,10 @@ JSObject* nsINode::WrapObject(JSContext* aCx,
}
JS::Rooted<JSObject*> obj(aCx, WrapNode(aCx, aGivenProto));
MOZ_ASSERT_IF(obj && ChromeOnlyAccess(),
xpc::IsInContentXBLScope(obj) ||
!xpc::UseContentXBLScope(JS::GetObjectRealmOrNull(obj)));
MOZ_ASSERT_IF(
obj && ChromeOnlyAccess(),
JS::GetNonCCWObjectGlobal(obj) == xpc::UnprivilegedJunkScope() ||
xpc::IsInUAWidgetScope(obj) || xpc::AccessCheck::isChrome(obj));
return obj;
}

View File

@ -19,6 +19,7 @@ support-files =
[test_anonymousContent_xul_window.xul]
[test_blockParsing.html]
[test_blocking_image.html]
[test_bug419527.xhtml]
[test_bug715041.xul]
[test_bug715041_removal.xul]
[test_bug945152.html]

View File

@ -370,7 +370,6 @@ support-files = test_bug402150.html^headers^
[test_bug418214.html]
[test_bug418986-1.html]
[test_bug419132.html]
[test_bug419527.xhtml]
[test_bug420609.xhtml]
[test_bug420700.html]
[test_bug421602.html]

View File

@ -5,8 +5,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=419527
-->
<head>
<title>Test for Bug 419527</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="rangebinding">
@ -14,14 +14,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=419527
</content>
<implementation>
<constructor>
var win = XPCNativeWrapper.unwrap(window);
var win = window;
var span = document.getAnonymousNodes(this)[0];
win.ok(span.localName == "span", "Wrong anon node!");
var range = document.createRange();
range.selectNode(span.firstChild);
win.ok(range.startContainer == span, "Wrong start container!");
win.ok(range.endContainer == span, "Wrong end container!");
var newSubTree = XPCNativeWrapper(win.newSubTree);
var newSubTree = win.newSubTree;
newSubTree.appendChild(this);
range.setStart(newSubTree.firstChild, 0);
win.ok(range.startContainer == newSubTree.firstChild,

View File

@ -420,7 +420,7 @@ inline nsWrapperCache* GetWrapperCache(const SmartPtr<T>& aObject) {
return GetWrapperCache(aObject.get());
}
enum class ReflectionScope { Content, XBL, UAWidget };
enum class ReflectionScope { Content, NAC, UAWidget };
struct MOZ_STACK_CLASS ParentObject {
template <class T>

View File

@ -1621,18 +1621,8 @@ static inline JSObject* FindAssociatedGlobal(
obj = JS::GetNonCCWObjectGlobal(obj);
switch (scope) {
case mozilla::dom::ReflectionScope::XBL: {
// If scope is set to XBLScope, it means that the canonical reflector for
// this native object should live in the content XBL scope. Note that we
// never put anonymous content inside an add-on scope.
if (xpc::IsInContentXBLScope(obj)) {
return obj;
}
JS::Rooted<JSObject*> rootedObj(cx, obj);
JSObject* xblScope = xpc::GetXBLScope(cx, rootedObj);
MOZ_ASSERT_IF(xblScope, JS_IsGlobalObject(xblScope));
JS::AssertObjectIsNotGray(xblScope);
return xblScope;
case mozilla::dom::ReflectionScope::NAC: {
return xpc::NACScope(obj);
}
case mozilla::dom::ReflectionScope::UAWidget: {

View File

@ -12,6 +12,7 @@ support-files =
test_bug336682.js
[test_bug336682_2.xul]
[test_bug391568.xhtml]
[test_bug415498.xul]
[test_bug418986-3.xul]
[test_bug524674.xul]

View File

@ -36,7 +36,6 @@ support-files =
support-files = test_bug336682.js
[test_bug367781.html]
[test_bug379120.html]
[test_bug391568.xhtml]
[test_bug402089.html]
[test_bug405632.html]
[test_bug409604.html]

View File

@ -5,8 +5,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391568
-->
<head>
<title>Test for Bug 391568</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script>
var constructorFired = 0;
</script>
@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391568
<xbl:implementation>
<xbl:constructor>
var win = XPCNativeWrapper.unwrap(window);
var win = window;
++win.constructorFired;
document.getAnonymousNodes(this)[0].addEventListener(
"DOMCharacterDataModified",

View File

@ -1,20 +0,0 @@
<?xml version="1.0"?>
<bindings id="xbltestBindings" xmlns="http://www.mozilla.org/xbl">
<binding id="xbltest">
<content>PASS</content>
<implementation>
<constructor>
var win = XPCNativeWrapper.unwrap(window);
var SpecialPowers = win.SpecialPowers;
var is = win.is;
var todo_is = win.todo_is;
var ok = win.ok;
var legacyMozPrefixedInterfaces = win.legacyMozPrefixedInterfaces;
var createInterfaceMap = win.createInterfaceMap;
eval(win.runTest.toString());
runTest(true);
win.SimpleTest.finish();
</constructor>
</implementation>
</binding>
</bindings>

View File

@ -6,7 +6,6 @@ support-files =
file_clonewrapper.html
file_domWindowUtils_scrollbarSize.html
file_frameElementWrapping.html
file_interfaces.xml
file_moving_nodeList.html
file_moving_xhr.html
file_resource_timing_nocors.html

View File

@ -20,7 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=766694
ok(!self.isSecureContext, "The test should not be running in a secure context");
</script>
<script type="text/javascript" src="test_interfaces.js"></script>
<span id="span" style="-moz-binding: url(file_interfaces.xml)"></span>
</pre>
</body>
</html>

View File

@ -15,7 +15,6 @@
// {name: "ExperimentalThing", release: false},
// {name: "ReallyExperimentalThing", nightly: true},
// {name: "DesktopOnlyThing", desktop: true},
// {name: "FancyControl", xbl: true},
// {name: "DisabledEverywhere", disabled: true},
// ];
//
@ -175,8 +174,6 @@ var interfaceNamesInGlobalScope =
{name: "Blob", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BlobEvent", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BoxObject", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "BroadcastChannel", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -201,16 +198,12 @@ var interfaceNamesInGlobalScope =
{name: "ChannelSplitterNode", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "CharacterData", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "ChromeNodeList", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Clipboard"},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "ClipboardEvent", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "CloseEvent", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "CommandEvent", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Comment", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -892,9 +885,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "SharedWorker", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "SimpleGestureEvent", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "SimpleTest", insecureContext: true, xbl: false},
{name: "SimpleTest", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "SourceBuffer", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -910,7 +901,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "SpeechSynthesisVoice", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "SpecialPowers", insecureContext: true, xbl: false},
{name: "SpecialPowers", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "StereoPannerNode", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -1153,12 +1144,6 @@ var interfaceNamesInGlobalScope =
{name: "TrackEvent", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TransitionEvent", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TreeColumn", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TreeColumns", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TreeContentView", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "TreeWalker", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -1267,27 +1252,11 @@ var interfaceNamesInGlobalScope =
{name: "XPathResult", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XSLTProcessor", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULCommandEvent", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULDocument", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULFrameElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULMenuElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULPopupElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULTextElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULTreeElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
];
// IMPORTANT: Do not change the list above without review from a DOM peer!
function createInterfaceMap(isXBLScope) {
function createInterfaceMap() {
var interfaceMap = {};
function addInterfaces(interfaces)
@ -1299,7 +1268,6 @@ function createInterfaceMap(isXBLScope) {
ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
if ((entry.nightly === !isNightly) ||
(entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
(entry.xbl === !isXBLScope) ||
(entry.desktop === !isDesktop) ||
(entry.windows === !isWindows) ||
(entry.mac === !isMac) ||
@ -1330,8 +1298,8 @@ function createInterfaceMap(isXBLScope) {
return interfaceMap;
}
function runTest(isXBLScope) {
var interfaceMap = createInterfaceMap(isXBLScope);
function runTest() {
var interfaceMap = createInterfaceMap();
for (var name of Object.getOwnPropertyNames(window)) {
// An interface name should start with an upper case character.
// However, we have a couple of legacy interfaces that start with 'moz', so
@ -1341,19 +1309,19 @@ function runTest(isXBLScope) {
}
ok(interfaceMap[name],
"If this is failing: DANGER, are you sure you want to expose the new interface " + name +
" to all webpages as a property on the window (XBL: " + isXBLScope + ")? Do not make a change to this file without a " +
" to all webpages as a property on the window? Do not make a change to this file without a " +
" review from a DOM peer for that specific change!!! (or a JS peer for changes to ecmaGlobals)");
ok(name in window,
`${name} is exposed as an own property on the window but tests false for "in" in the ${isXBLScope ? "XBL" : "global"} scope`);
`${name} is exposed as an own property on the window but tests false for "in" in the global scope`);
ok(Object.getOwnPropertyDescriptor(window, name),
`${name} is exposed as an own property on the window but has no property descriptor in the ${isXBLScope ? "XBL" : "global"} scope`);
`${name} is exposed as an own property on the window but has no property descriptor in the global scope`);
delete interfaceMap[name];
}
for (var name of Object.keys(interfaceMap)) {
ok(name in window === interfaceMap[name],
name + " should " + (interfaceMap[name] ? "" : " NOT") + " be defined on the " + (isXBLScope ? "XBL" : "global") +" scope");
name + " should " + (interfaceMap[name] ? "" : " NOT") + " be defined on the global scope");
if (!interfaceMap[name]) {
delete interfaceMap[name];
}
@ -1362,5 +1330,4 @@ function runTest(isXBLScope) {
"The following interface(s) are not enumerated: " + Object.keys(interfaceMap).join(", "));
}
runTest(false);
SimpleTest.waitForExplicitFinish();
runTest();

View File

@ -20,7 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=766694
ok(self.isSecureContext, "The test should be running in a secure context");
</script>
<script type="text/javascript" src="test_interfaces.js"></script>
<span id="span" style="-moz-binding: url(file_interfaces.xml)"></span>
</pre>
</body>
</html>

View File

@ -218,16 +218,8 @@ void nsXBLBinding::SetBoundElement(Element* aElement) {
return;
}
// Compute whether we're using an XBL scope.
//
// We disable XBL scopes for remote XUL, where we care about compat more
// than security. So we need to know whether we're using an XBL scope so that
// we can decide what to do about untrusted events when "allowuntrusted"
// is not given in the handler declaration.
nsCOMPtr<nsIGlobalObject> go = mBoundElement->OwnerDoc()->GetScopeObject();
NS_ENSURE_TRUE_VOID(go && go->GetGlobalJSObject());
mUsingContentXBLScope = xpc::UseContentXBLScope(
JS::GetObjectRealmOrNull(go->GetGlobalJSObject()));
// mUsingContentXBLScope can go away. See bug 1527116.
mUsingContentXBLScope = false;
}
bool nsXBLBinding::HasStyleSheets() const {

View File

@ -1,6 +1,5 @@
[DEFAULT]
support-files =
file_bug944407.xml
file_bug950909.xml
file_fieldScopeChain.xml
@ -11,6 +10,6 @@ skip-if = (verify && debug && (os == 'linux' || os == 'mac'))
[test_bug721452.xul]
[test_bug723676.xul]
[test_bug772966.xul]
[test_bug944407.xul]
[test_bug950909.xul]
[test_bug1086996.xhtml]
[test_fieldScopeChain.html]

View File

@ -4,7 +4,7 @@
<content>PASS</content>
<implementation>
<constructor>
var win = XPCNativeWrapper.unwrap(window);
var win = window;
win.document.bindingConstructorRan = true;
win.ok(true, "binding URI with no fragment applied");
win.SimpleTest.finish();

View File

@ -1,300 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=821850
-->
<head>
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="testBinding">
<implementation>
<constructor>
// Store a property as an expando on the bound element.
this._prop = "propVal";
// Wait for both constructors to fire.
window.constructorCount = (window.constructorCount + 1) || 1;
if (window.constructorCount != 3)
return;
// Grab some basic infrastructure off the content window.
var win = XPCNativeWrapper.unwrap(window);
SpecialPowers = win.SpecialPowers;
Cu = SpecialPowers.Cu;
Ci = SpecialPowers.Ci;
is = win.is;
ok = win.ok;
SimpleTest = win.SimpleTest;
// Stick some expandos on the content window.
window.xrayExpando = 3;
win.primitiveExpando = 11;
win.stringExpando = "stringExpando";
win.objectExpando = { foo: 12 };
win.globalExpando = SpecialPowers.unwrap(Cu.getGlobalForObject({}));
win.functionExpando = function() { return "called" };
win.functionExpando.prop = 2;
// Make sure we're Xraying.
ok(Cu.isXrayWrapper(window), "Window is Xrayed");
ok(Cu.isXrayWrapper(document), "Document is Xrayed");
var bound = document.getElementById('bound');
var bound2 = document.getElementById('bound2');
var bound3 = document.getElementById('bound3');
ok(bound, "bound is non-null");
is(bound.method('baz'), "method:baz", "Xray methods work");
is(bound.prop, "propVal", "Property Xrays work");
is(bound.primitiveField, undefined, "Xrays don't show fields");
is(bound.wrappedJSObject.primitiveField, 2, "Waiving Xrays show fields");
// Check exposure behavior.
is(typeof bound.unexposedMethod, 'function',
"Unexposed method should be visible to XBL");
is(typeof bound.wrappedJSObject.unexposedMethod, 'undefined',
"Unexposed method should not be defined in content");
is(typeof bound.unexposedProperty, 'number',
"Unexposed property should be visible to XBL");
is(typeof bound.wrappedJSObject.unexposedProperty, 'undefined',
"Unexposed property should not be defined in content");
// Check that here HTMLImageElement.QueryInterface works
var img = document.querySelector("img");
ok("QueryInterface" in SpecialPowers.wrap(img),
"Should have a img.QueryInterface here");
is(SpecialPowers.unwrap(SpecialPowers.wrap(img).QueryInterface(Ci.nsIImageLoadingContent)),
img, "Should be able to QI the image");
// Make sure standard constructors work right in the presence of
// sandboxPrototype and Xray-resolved constructors.
is(window.Function, XPCNativeWrapper(window.wrappedJSObject.Function),
"window.Function comes from the window, not the global");
ok(Function != window.Function, "Function constructors are distinct");
is(Object.getPrototypeOf(Function.prototype), Object.getPrototypeOf({foo: 42}),
"Function constructor is local");
ok(Object.getPrototypeOf(bound.wrappedJSObject) == Object.getPrototypeOf(bound2.wrappedJSObject),
"Div and div should have the same content-side prototype");
ok(Object.getPrototypeOf(bound.wrappedJSObject) != Object.getPrototypeOf(bound3.wrappedJSObject),
"Div and span should have different content-side prototypes");
ok(bound.wrappedJSObject.method == bound3.wrappedJSObject.method,
"Methods should be shared");
// This gets invoked by an event handler.
window.finish = function() {
// Content messed with stuff. Make sure we still see the right thing.
is(bound.method('bay'), "method:bay", "Xray methods work");
is(bound.wrappedJSObject.method('bay'), "hah", "Xray waived methods work");
is(bound.prop, "set:someOtherVal", "Xray props work");
is(bound.wrappedJSObject.prop, "redefined", "Xray waived props work");
is(bound.wrappedJSObject.primitiveField, 321, "Can't do anything about redefined fields");
SimpleTest.finish();
}
// Hand things off to content. Content will call us back.
win.go();
</constructor>
<field name="primitiveField">2</field>
<method name="unexposedMethod"><body></body></method>
<property name="unexposedProperty" onget="return 2;" readonly="true"></property>
<method name="method" exposeToUntrustedContent="true">
<parameter name="arg" />
<body>
return "method:" + arg;
</body>
</method>
<method name="passMeAJSObject" exposeToUntrustedContent="true">
<parameter name="arg" />
<body>
is(typeof arg.prop, 'undefined', "No properties");
is(arg.wrappedJSObject.prop, 2, "Underlying object has properties");
is(Object.getOwnPropertyNames(arg).length, 0, "Should have no own properties");
is(Object.getOwnPropertyNames(arg.wrappedJSObject).length, 1, "Underlying object has properties");
arg.foo = 2;
is(arg.foo, 2, "Should place expandos");
is(typeof arg.wrappedJSObject.foo, 'undefined', "Expandos should be invisible to content");
</body>
</method>
<property name="prop" exposeToUntrustedContent="true">
<getter>return this._prop;</getter>
<setter>this._prop = "set:" + val;</setter>
</property>
</implementation>
<handlers>
<handler event="testevent" action="ok(true, 'called event handler'); finish();" allowuntrusted="true"/>
<handler event="testtrusted" action="ok(true, 'called trusted handler'); window.wrappedJSObject.triggeredTrustedHandler = true;"/>
<handler event="keyup" action="ok(true, 'called untrusted key handler'); window.wrappedJSObject.triggeredUntrustedKeyHandler = true;" allowuntrusted="true"/>
<handler event="keydown" action="ok(true, 'called trusted key handler'); window.wrappedJSObject.triggeredTrustedKeyHandler = true;"/>
</handlers>
</binding>
</bindings>
<script type="application/javascript">
<![CDATA[
ok = parent.ok;
is = parent.is;
SimpleTest = parent.SimpleTest;
SpecialPowers = parent.SpecialPowers;
// Test the Xray waiving behavior when accessing fields. We should be able to
// see sequential JS-implemented properties, but should regain Xrays when we
// hit a native property.
window.contentVal = { foo: 10, rabbit: { hole: { bar: 100, win: window} } };
ok(true, "Set contentVal");
// Check that we're not exposing QueryInterface to non-XBL code
ok(!("QueryInterface" in document),
"Should not have a document.QueryInterface here");
function go() {
"use strict";
// Test what we can and cannot access in the XBL scope.
is(typeof window.xrayExpando, "undefined", "Xray expandos are private to the caller");
is(window.primitiveExpando, 11, "Can see waived expandos");
is(window.stringExpando, "stringExpando", "Can see waived expandos");
is(typeof window.objectExpando, "object", "object expando exists");
checkThrows(() => window.objectExpando.foo);
is(SpecialPowers.wrap(window.objectExpando).foo, 12, "SpecialPowers sees the right thing");
is(typeof window.globalExpando, "object", "Can see global object");
checkThrows(() => window.globalExpando.win);
is(window.functionExpando(), "called", "XBL functions are callable");
checkThrows(() => window.functionExpando.prop);
// Inspect the bound element.
var bound = document.getElementById('bound');
is(bound.primitiveField, 2, "Can see primitive fields");
is(bound.method("foo"), "method:foo", "Can invoke XBL method from content");
is(bound.prop, "propVal", "Can access properties from content");
bound.prop = "someOtherVal";
is(bound.prop, "set:someOtherVal", "Can set properties from content");
// Make sure that XBL scopes get opaque wrappers.
//
// Note: Now that we have object Xrays, we have to pass in a more obscure
// ES type that we don't Xray to test this.
var proto = bound.__proto__;
var nonXrayableObject = new WeakMap();
nonXrayableObject.prop = 2;
proto.passMeAJSObject(nonXrayableObject);
//
// Try sticking a bunch of stuff on the prototype object.
//
proto.someExpando = 201;
is(bound.someExpando, 201, "Can stick non-XBL properties on the proto");
// Previously, this code checked that content couldn't tamper with its XBL
// prototype. But we decided to allow this to reduce regression risk, so for
// now just check that this works.
function checkMayTamper(obj, propName, desc) {
var accessor = !('value' in Object.getOwnPropertyDescriptor(obj, propName));
if (!accessor)
checkAllowed(function() { obj[propName] = function() {} }, desc + ": assign");
checkAllowed(function() { Object.defineProperty(obj, propName, {configurable: true, value: 3}) }, desc + ": define with value");
checkAllowed(function() { Object.defineProperty(obj, propName, {configurable: true, writable: true}) }, desc + ": make writable");
checkAllowed(function() { Object.defineProperty(obj, propName, {configurable: true}) }, desc + ": make configurable");
checkAllowed(function() { Object.defineProperty(obj, propName, {configurable: true, get: function() {}}) }, desc + ": define with getter");
checkAllowed(function() { Object.defineProperty(obj, propName, {configurable: true, set: function() {}}) }, desc + ": define with setter");
// Windows are implemented as proxies, and Proxy::delete_ doesn't currently
// pass strict around. Work around it in the window.binding case by just
// checking if delete returns false.
// manually.
checkAllowed(function() { delete obj[propName]; }, desc + ": delete");
if (!accessor)
checkAllowed(function() { obj[propName] = function() {} }, desc + ": assign (again)");
}
// Make sure content can do whatever it wants with the prototype.
checkMayTamper(proto, 'method', "XBL Proto Method");
checkMayTamper(proto, 'prop', "XBL Proto Prop");
checkMayTamper(proto, 'primitiveField', "XBL Field Accessor");
// Tamper with the derived object. This doesn't affect the XBL scope thanks
// to Xrays.
bound.method = function() { return "heh"; };
Object.defineProperty(bound, 'method', {value: function() { return "hah" }});
Object.defineProperty(bound, 'prop', {value: "redefined"});
bound.primitiveField = 321;
// Untrusted events should not trigger event handlers without
// exposeToUntrustedContent=true.
window.triggeredTrustedHandler = false;
var untrustedEvent = new CustomEvent('testtrusted');
is(untrustedEvent.type, 'testtrusted', "Constructor should see type");
bound.dispatchEvent(untrustedEvent);
ok(!window.triggeredTrustedHandler, "untrusted events should not trigger trusted handler");
var trustedEvent = new CustomEvent('testtrusted');
is(trustedEvent.type, 'testtrusted', "Wrapped constructor should see type");
SpecialPowers.wrap(bound).dispatchEvent(trustedEvent); // Dispatch over SpecialPowers to make the event trusted.
ok(window.triggeredTrustedHandler, "trusted events should trigger trusted handler");
//
// We check key events as well, since they're implemented differently.
//
// NB: We don't check isTrusted on the events we create here, because
// according to smaug, old-style event initialization doesn't mark the
// event as trusted until it's dispatched.
//
window.triggeredUntrustedKeyHandler = false;
window.triggeredTrustedKeyHandler = false;
// Untrusted event, permissive handler.
var untrustedKeyEvent = document.createEvent('KeyboardEvent');
untrustedKeyEvent.initEvent('keyup', true, true);
bound.dispatchEvent(untrustedKeyEvent);
ok(window.triggeredUntrustedKeyHandler, "untrusted key events should trigger untrusted handler");
// Untrusted event, strict handler.
var fakeTrustedKeyEvent = document.createEvent('KeyboardEvent');
fakeTrustedKeyEvent.initEvent('keydown', true, true);
bound.dispatchEvent(fakeTrustedKeyEvent);
ok(!window.triggeredTrustedKeyHandler, "untrusted key events should not trigger trusted handler");
// Trusted event, strict handler. Dispatch using SpecialPowers to make the event trusted.
var trustedKeyEvent = document.createEvent('KeyboardEvent');
trustedKeyEvent.initEvent('keydown', true, true);
SpecialPowers.wrap(bound).dispatchEvent(trustedKeyEvent);
ok(window.triggeredTrustedKeyHandler, "trusted key events should trigger trusted handler");
// Hand control back to the XBL scope by dispatching an event on the bound element.
bound.dispatchEvent(new CustomEvent('testevent'));
}
function checkThrows(fn) {
try { fn(); ok(false, "Should have thrown"); }
catch (e) { ok(!!/denied|insecure/.exec(e), "Should have thrown security exception: " + e); }
}
function checkAllowed(fn, desc) {
try { fn(); ok(true, desc + ": Didn't throw"); }
catch (e) { ok(false, desc + ": Threw: " + e); }
}
function setup() {
// When the bindings are applied, the constructor will be invoked and the
// test will continue.
document.getElementById('bound').style.MozBinding = 'url(#testBinding)';
document.getElementById('bound2').style.MozBinding = 'url(#testBinding)';
document.getElementById('bound3').style.MozBinding = 'url(#testBinding)';
}
]]>
</script>
</head>
<body onload="setup()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821850">Mozilla Bug 821850</a>
<p id="display"></p>
<div id="content">
<div id="bound">Bound element</div>
<div id="bound2">Bound element</div>
<span id="bound3">Bound element</span>
<img/>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -1,8 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<div id="deny" style="-moz-binding: url(file_bug944407.xml#testAllowScript)"></div>
<div id="allow" style="-moz-binding: url(chrome://mochitests/content/chrome/dom/xbl/test/file_bug944407.xml#testAllowScript)"</div>
<script>/* Flush layout with a script tab - see bug 944407 comment 37. */</script>
</body>
</html>

View File

@ -1,75 +0,0 @@
<?xml version="1.0"?>
<bindings id="testBindings" xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="testAllowScript" bindToUntrustedContent="true">
<implementation>
<property name="someProp" onget="return 2;" readonly="true"></property>
<method name="someMethod"><body> return 3; </body></method>
<method name="startTest">
<body>
<![CDATA[
// Make sure we only get constructed when we're loaded from a domain
// with script enabled.
is(this.id, 'allow', "XBL should only be bound when the origin of the binding allows scripts");
var t = this;
doFinish = function() {
// Take a moment to make sure that other constructors don't run when they shouldn't.
if (t.id == 'allow')
setTimeout(SpecialPowers.wrap(window.parent).finish, 100);
}
onTestEvent = function(target) {
ok(true, 'called event handler');
// Try calling event handlers on anonymous content.
var e = new MouseEvent('click');
document.getAnonymousNodes(target)[1].dispatchEvent(e);
ok(window.calledEventHandlerOnAC, "Should invoke event handler on AC");
// Now, dispatch a key event to test key handlers and move the test along.
var k = document.createEvent('KeyboardEvent');
k.initEvent('keyup', true, true);
target.dispatchEvent(k);
}
// Check the implementation.
is(this.someProp, 2, "Properties work");
is(this.someMethod(), 3, "Methods work");
// Kick over to the event handlers. This tests XBL event handlers,
// XBL key handlers, and event handlers on anonymous content.
this.dispatchEvent(new CustomEvent('testEvent'));
]]>
</body>
</method>
<constructor>
<![CDATA[
win = XPCNativeWrapper.unwrap(window);
SpecialPowers = win.SpecialPowers;
ok = win.ok = SpecialPowers.wrap(window.parent).ok;
is = win.is = SpecialPowers.wrap(window.parent).is;
info = win.info = SpecialPowers.wrap(window.parent).info;
info("Invoked constructor for " + this.id);
var t = this;
window.addEventListener('load', function() {
// Wait two refresh-driver ticks to make sure that the constructor runs
// for both |allow| and |deny| if it's ever going to.
//
// See bug 944407 comment 37.
info("Invoked load listener for " + t.id);
window.requestAnimationFrame(function() { window.requestAnimationFrame(t.startTest.bind(t)); });
}, {once: true});
]]>
</constructor>
</implementation>
<handlers>
<handler event="testEvent" action="onTestEvent(this)" allowuntrusted="true"/>
<handler event="keyup" action="ok(true, 'called key handler'); doFinish();" allowuntrusted="true"/>
</handlers>
<content>Anonymous Content<html:div onclick="window.calledEventHandlerOnAC = true;"></html:div><html:b style="display:none"><children/></html:b></content>
</binding>
</bindings>

View File

@ -4,12 +4,9 @@
<implementation implements="nsIObserver">
<constructor>
<![CDATA[
// This binding gets applied to a content object, and thus is actually
// running in a content XBL scope.
var win = XPCNativeWrapper.unwrap(window);
var win = window;
var SpecialPowers = win.SpecialPowers;
var ok = SpecialPowers.unwrap(SpecialPowers.wrap(window).parent.ok);
ok(win != window, "Should be running in an XBL scope with Xrays");
// Generate an XPCWrappedJS for the reflector. We need to do this
// explicitly with a testing helper, because we're converging on

View File

@ -12,10 +12,7 @@ support-files =
file_bug481558css.sjs
file_bug591198_inner.html
file_bug591198_xbl.xml
file_bug821850.xhtml
file_bug844783.xhtml
file_bug944407.html
file_bug944407.xml
file_bug950909.html
[test_bug310107.html]
@ -36,9 +33,7 @@ support-files =
[test_bug591198.html]
[test_bug639338.xhtml]
[test_bug790265.xhtml]
[test_bug821850.html]
[test_bug844783.html]
[test_bug872273.xhtml]
[test_bug1086996.xhtml]
[test_bug1098628_throw_from_construct.xhtml]
[test_bug1359859.xhtml]

View File

@ -8,7 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1086996
<binding id="handlerBinding">
<implementation>
<constructor>
<![CDATA[XPCNativeWrapper.unwrap(window).constructedHandlerBinding();]]>
<![CDATA[window.constructedHandlerBinding();]]>
</constructor>
</implementation>
<handlers>
@ -29,8 +29,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1086996
</binding>
</bindings>
<title>Test for Bug 1086996</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1086996">Mozilla Bug 1086996</a>

View File

@ -21,6 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1098628
<binding id="test">
<implementation>
<constructor><![CDATA[
SimpleTest.expectUncaughtException();
throw "flimfniffle";
]]></constructor>
</implementation>

View File

@ -9,11 +9,15 @@
<binding id="testBinding">
<implementation>
<constructor>
XPCNativeWrapper.unwrap(window).running();
window.running();
this.constructed = true;
SimpleTest.expectUncaughtException();
throw new Error("Constructor threw");
</constructor>
<field name="throwingField">throw new Error("field threw")</field>
<field name="throwingField">
SimpleTest.expectUncaughtException();
throw new Error("field threw")
</field>
<field name="normalField">"hello"</field>
</implementation>
</binding>

View File

@ -17,7 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=389322
var success = true;
}
catch (e) { success = false; }
XPCNativeWrapper.unwrap(window).report("XBL fields", success)
window.report("XBL fields", success)
return ""
}())
]]></field>
@ -28,7 +28,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=389322
var success = true;
}
catch (e) { success = false; }
XPCNativeWrapper.unwrap(window).report("XBL property getters", success)
window.report("XBL property getters", success)
return 1
]]></getter>
<setter><![CDATA[
@ -37,7 +37,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=389322
var success = true
}
catch (e) { success = false }
XPCNativeWrapper.unwrap(window).report("XBL property setters", success)
window.report("XBL property setters", success)
return val
]]></setter>
</property>
@ -49,7 +49,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=389322
}
catch (e) { success = false; }
XPCNativeWrapper.unwrap(window).report("XBL methods", success)
window.report("XBL methods", success)
]]></body>
</method>
<constructor><![CDATA[
@ -61,7 +61,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=389322
var success = true
}
catch (e) { success = false }
var win = XPCNativeWrapper.unwrap(window);
var win = window;
win.report("XBL constructors", success)
var ev = document.createEvent("Events")

View File

@ -9,8 +9,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=400705
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="test">
<implementation>
<field name="a">XPCNativeWrapper.unwrap(window).countera++</field>
<field name="b">XPCNativeWrapper.unwrap(window).counterb++</field>
<field name="a">window.countera++</field>
<field name="b">window.counterb++</field>
</implementation>
</binding>
</bindings>

View File

@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=401907
<binding id="binding">
<implementation>
<constructor>
var win = XPCNativeWrapper.unwrap(window);
var win = window;
win.ok(true, "First binding with ID 'binding' should be used!");
win.testRun = true;
if (win.needsFinish) {
@ -23,7 +23,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=401907
<binding id="binding">
<implementation>
<constructor>
var win = XPCNativeWrapper.unwrap(window);
var win = window;
win.ok(false, "First binding with ID 'binding' should be used!");
win.testRun = true;
if (win.needsFinish) {

View File

@ -9,7 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=403162
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="test">
<handlers>
<handler event="foo" action="XPCNativeWrapper.unwrap(window).triggerCount++" allowuntrusted="true"/>
<handler event="foo" action="window.triggerCount++" allowuntrusted="true"/>
</handlers>
</binding>
</bindings>

View File

@ -16,7 +16,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=526178
<binding id="binding">
<implementation>
<constructor>
var win = XPCNativeWrapper.unwrap(window);
var win = window;
win.logString += this.localName;
win.bindingDone();
</constructor>

View File

@ -9,9 +9,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=403162
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="test">
<handlers>
<handler event="DOMMouseScroll" action="XPCNativeWrapper.unwrap(window).triggerCount++" allowuntrusted="true"/>
<handler event="DOMMouseScroll" modifiers="shift" action="XPCNativeWrapper.unwrap(window).shiftCount++" allowuntrusted="true"/>
<handler event="DOMMouseScroll" modifiers="control" action="XPCNativeWrapper.unwrap(window).controlCount++" allowuntrusted="true"/>
<handler event="DOMMouseScroll" action="window.triggerCount++" allowuntrusted="true"/>
<handler event="DOMMouseScroll" modifiers="shift" action="window.shiftCount++" allowuntrusted="true"/>
<handler event="DOMMouseScroll" modifiers="control" action="window.controlCount++" allowuntrusted="true"/>
</handlers>
</binding>
</bindings>

View File

@ -1,37 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=821850
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 821850</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for XBL scope behavior. **/
SimpleTest.waitForExplicitFinish();
// Embed the real test. It will take care of everything else.
//
// NB: This two-layer setup used to exist because XBL scopes were behind a
// pref, and we wanted to make sure that we properly set the pref before
// loading the real test. This stuff is no longer behind a pref, but we just
// leave the structure as-is for expediency.
function setup() {
$('ifr').setAttribute('src', 'file_bug821850.xhtml');
}
</script>
</head>
<body onload="setup();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821850">Mozilla Bug 821850</a>
<p id="display"></p>
<div id="content">
<iframe id="ifr"></iframe>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -1,43 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=944407
-->
<window title="Mozilla Bug 944407"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=944407"
target="_blank">Mozilla Bug 944407</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for XBL bindings with script disabled. **/
SimpleTest.waitForExplicitFinish();
const {Services} = ChromeUtils.import('resource://gre/modules/Services.jsm');
function go() {
// Disable javascript, and load the frame.
function loadFrame() {
ok(!Services.prefs.getBoolPref('javascript.enabled'), "Javascript should be disabled");
$('ifr').setAttribute('src', 'http://mochi.test:8888/tests/dom/xbl/test/file_bug944407.html');
}
SpecialPowers.pushPrefEnv({ set: [['javascript.enabled', false]] }, loadFrame);
}
function finish() {
SimpleTest.finish();
}
addLoadEvent(go);
]]>
</script>
<iframe id='ifr' />
</window>

View File

@ -637,6 +637,17 @@ JSObject* UnprivilegedJunkScope() {
return XPCJSRuntime::Get()->UnprivilegedJunkScope();
}
JSObject* NACScope(JSObject* global) {
// If we're a chrome global, just use ourselves.
if (AccessCheck::isChrome(global)) {
return global;
}
JSObject* scope = UnprivilegedJunkScope();
JS::ExposeObjectToActiveJS(scope);
return scope;
}
JSObject* PrivilegedJunkScope() { return XPCJSRuntime::Get()->LoaderGlobal(); }
JSObject* CompilationScope() { return XPCJSRuntime::Get()->LoaderGlobal(); }

View File

@ -79,15 +79,11 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JS::Compartment* aCompartment,
// Determine whether we would allow an XBL scope in this situation.
// In addition to being pref-controlled, we also disable XBL scopes for
// remote XUL domains, _except_ if we have an additional pref override set.
//
// Note that we can't quite remove this yet, even though we never actually
// use XBL scopes, because some code (including the security manager) uses
// this boolean to make decisions that we rely on in our test infrastructure.
mAllowContentXBLScope = !RemoteXULForbidsXBLScope(aFirstGlobal);
// Determine whether to use an XBL scope.
mUseContentXBLScope = mAllowContentXBLScope;
if (mUseContentXBLScope) {
const js::Class* clasp = js::GetObjectClass(aFirstGlobal);
mUseContentXBLScope =
!AccessCheck::isChrome(mCompartment) && !strcmp(clasp->name, "Window");
}
}
// static
@ -206,58 +202,10 @@ JSObject* XPCWrappedNativeScope::EnsureContentXBLScope(JSContext* cx) {
MOZ_ASSERT(strcmp(js::GetObjectClass(global)->name,
"nsXBLPrototypeScript compilation scope"));
// If this scope doesn't need an XBL scope, just return the global.
if (!mUseContentXBLScope) {
return global;
}
// Given the status of in-content XBL, release assert we have a single realm
// for now so we don't have to worry about the multiple-realms case.
// See bug 1515582.
js::AssertCompartmentHasSingleRealm(Compartment());
// If we already have a special XBL scope object, we know what to use.
if (mContentXBLScope) {
return mContentXBLScope;
}
// Set up the sandbox options. Note that we use the DOM global as the
// sandboxPrototype so that the XBL scope can access all the DOM objects
// it's accustomed to accessing.
//
// In general wantXrays shouldn't matter much here, but there are weird
// cases when adopting bound content between same-origin globals where a
// <destructor> in one content XBL scope sees anonymous content in another
// content XBL scope. When that happens, we hit LookupBindingMember for an
// anonymous element that lives in a content XBL scope, which isn't a tested
// or audited codepath. So let's avoid hitting that case by opting out of
// same-origin Xrays.
SandboxOptions options;
options.wantXrays = false;
options.wantComponents = false;
options.proto = global;
options.sameZoneAs = global;
options.isContentXBLScope = true;
// Use an ExpandedPrincipal to create asymmetric security.
nsIPrincipal* principal = xpc::GetObjectPrincipal(global);
MOZ_ASSERT(!nsContentUtils::IsExpandedPrincipal(principal));
nsTArray<nsCOMPtr<nsIPrincipal>> principalAsArray(1);
principalAsArray.AppendElement(principal);
RefPtr<ExpandedPrincipal> ep = ExpandedPrincipal::Create(
principalAsArray, principal->OriginAttributesRef());
// Create the sandbox.
RootedValue v(cx);
nsresult rv = CreateSandboxObject(
cx, &v, static_cast<nsIExpandedPrincipal*>(ep), options);
NS_ENSURE_SUCCESS(rv, nullptr);
mContentXBLScope = &v.toObject();
MOZ_ASSERT(xpc::IsInContentXBLScope(js::UncheckedUnwrap(mContentXBLScope)));
// Good to go!
return mContentXBLScope;
// We can probably remove EnsureContentXBLScope and clean up all its callers,
// but a bunch (all?) of those callers will just go away when we remove XBL
// support, so it's simpler to just leave it here as a no-op.
return global;
}
bool XPCWrappedNativeScope::AllowContentXBLScope(Realm* aRealm) {
@ -309,16 +257,6 @@ bool AllowContentXBLScope(JS::Realm* realm) {
return scope && scope->AllowContentXBLScope(realm);
}
bool UseContentXBLScope(JS::Realm* realm) {
JS::Compartment* comp = GetCompartmentForRealm(realm);
XPCWrappedNativeScope* scope = CompartmentPrivate::Get(comp)->scope;
return scope && scope->UseContentXBLScope();
}
void ClearContentXBLScope(JSObject* global) {
CompartmentPrivate::Get(global)->scope->ClearContentXBLScope();
}
} /* namespace xpc */
XPCWrappedNativeScope::~XPCWrappedNativeScope() {
@ -414,23 +352,11 @@ void XPCWrappedNativeScope::UpdateWeakPointersAfterGC() {
// Update our pointer to the compartment in case we finalized all globals.
if (js::gc::AllRealmsNeedSweep(mCompartment)) {
mCompartment = nullptr;
JSContext* cx = dom::danger::GetJSContext();
mContentXBLScope.finalize(cx);
GetWrappedNativeMap()->Clear();
mWrappedNativeProtoMap->Clear();
return;
}
#ifdef DEBUG
// These are traced, so no updates are necessary.
if (mContentXBLScope) {
JSObject* prev = mContentXBLScope.unbarrieredGet();
mContentXBLScope.updateWeakPointerAfterGC();
MOZ_ASSERT(prev == mContentXBLScope.unbarrieredGet());
MOZ_ASSERT_IF(prev, js::GetObjectCompartment(prev) == mCompartment);
}
#endif
// Sweep mWrappedNativeMap for dying flat JS objects. Moving has already
// been handled by XPCWrappedNative::FlatJSObjectMoved.
for (auto iter = GetWrappedNativeMap()->Iter(); !iter.Done(); iter.Next()) {

View File

@ -842,9 +842,6 @@ class XPCWrappedNativeScope final {
static void TraceWrappedNativesInAllScopes(JSTracer* trc);
void TraceInside(JSTracer* trc) {
if (mContentXBLScope) {
mContentXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope");
}
if (mXrayExpandos.initialized()) {
mXrayExpandos.trace(trc);
}
@ -915,8 +912,6 @@ class XPCWrappedNativeScope final {
return xpc::IsContentXBLCompartment(Compartment());
}
bool AllowContentXBLScope(JS::Realm* aRealm);
bool UseContentXBLScope() { return mUseContentXBLScope; }
void ClearContentXBLScope() { mContentXBLScope = nullptr; }
// ID Object prototype caches.
JS::ObjectPtr mIDProto;
@ -938,26 +933,12 @@ class XPCWrappedNativeScope final {
XPCWrappedNativeScope* mNext;
JS::Compartment* mCompartment;
// XBL Scope. This is is a lazily-created sandbox for non-system scopes.
// EnsureContentXBLScope() decides whether it needs to be created or not.
// This reference is wrapped into the compartment of mGlobalJSObject.
JS::ObjectPtr mContentXBLScope;
JS::WeakMapPtr<JSObject*, JSObject*> mXrayExpandos;
// For remote XUL domains, we run all XBL in the content scope for compat
// reasons (though we sometimes pref this off for automation). We separately
// track the result of this decision (mAllowContentXBLScope), from the
// decision of whether to actually _use_ an XBL scope (mUseContentXBLScope),
// which depends on the type of global and whether the compartment is system
// principal or not.
//
// This distinction is useful primarily because, if true, we know that we
// have no way of distinguishing XBL script from content script for the
// given scope. In these (unsupported) situations, we just always claim to
// be XBL.
// reasons (though we sometimes pref this off for automation). We
// track the result of this decision (mAllowContentXBLScope) for now.
bool mAllowContentXBLScope;
bool mUseContentXBLScope;
};
/***************************************************************************/

View File

@ -129,15 +129,9 @@ inline JSObject* GetXBLScopeOrGlobal(JSContext* cx, JSObject* obj) {
// in this compartment. See the comment around mAllowContentXBLScope.
bool AllowContentXBLScope(JS::Realm* realm);
// Returns whether we will use an XBL scope for this realm. This is
// semantically equivalent to comparing global != GetXBLScope(global), but it
// does not have the side-effect of eagerly creating the XBL scope if it does
// not already exist.
bool UseContentXBLScope(JS::Realm* realm);
// Clear out the content XBL scope (if any) on the given global. This will
// force creation of a new one if one is needed again.
void ClearContentXBLScope(JSObject* global);
// Get the scope for creating reflectors for native anonymous content
// whose normal global would be the given global.
JSObject* NACScope(JSObject* global);
bool IsSandboxPrototypeProxy(JSObject* obj);

View File

@ -104,7 +104,6 @@ skip-if = (debug == false)
[test_getweakmapkeys.html]
[test_paris_weakmap_keys.html]
skip-if = (debug == false)
[test_nac.xhtml]
[test_nukeContentWindow.html]
[test_sameOriginPolicy.html]
[test_sandbox_fetch.html]

View File

@ -1,64 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=914618
-->
<head>
<title>Test for Bug 914618</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="testBinding" chromeOnlyContent="true">
<!-- The root of the anonymous subtree is special, and is not allowed to
be adopted, among other things. Work with a child of the root. -->
<content><html:div><html:span id="nac">hidden text</html:span></html:div></content>
<implementation>
<constructor>
var win = XPCNativeWrapper.unwrap(window);
var nac = document.getAnonymousNodes(this)[0].firstChild;
win.is(nac.textContent, "hidden text", "XBL can see NAC");
win.playWithNAC(nac);
</constructor>
</implementation>
</binding>
</bindings>
<script type="application/javascript">
<![CDATA[
/** Test for Bug 914618 **/
SimpleTest.waitForExplicitFinish();
function checkThrows(fn) {
try {
fn();
ok(false, "Should have thrown");
} catch (e) {
ok(/denied|insecure|/.test(e), "Should have thrown security error");
}
}
function playWithNAC(nac) {
checkThrows(function() { nac.toString(); });
checkThrows(function() { nac.textContent; });
var iwin = document.getElementById('ifr').contentWindow;
iwin.nac = window.nac = nac;
checkThrows(new iwin.Function('nac.toString();'));
checkThrows(new iwin.Function('nac.textContent;'));
SimpleTest.finish();
}
]]>
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=914618">Mozilla Bug 914618</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<div id="bindingSink" style="-moz-binding: url(#testBinding);"></div>
<iframe id="ifr"></iframe>
<pre id="test">
</pre>
</body>
</html>

View File

@ -1,50 +0,0 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- Test that suppression works (or is turned off) for XBL content -->
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="before">
<content>Hello<children/></content>
</binding>
<binding id="after">
<content><children/>Kitty</content>
</binding>
<binding id="empty1">
<content><div xmlns="http://www.w3.org/1999/xhtml">Hello</div><children/></content>
</binding>
<binding id="empty2">
<content><children/><div xmlns="http://www.w3.org/1999/xhtml">Kitty</div></content>
<implementation>
<constructor>
// We used to do this in an onload handler, but getAnonymousNodes is no
// longer accessible to content, and we can't use SpecialPowers in
// reftests. So we enable XBL scopes and take advantage of the fact that XBL
// scopes can access these functions. We apply this binding
// programatically to make absolutely sure this constructor runs after all the
// other bindings have been set up.
document.body.offsetHeight;
document.getAnonymousNodes(document.getElementById("d3"))[0].style.display = 'inline';
document.getAnonymousNodes(document.getElementById("d4"))[2].style.display = 'inline';
</constructor>
</implementation>
</binding>
</bindings>
<style>
body > div { border:1px solid black; margin:1em;
font-family:sans-serif; letter-spacing:2px; }
#d1 { -moz-binding:url(#before); }
#d2 { -moz-binding:url(#after); }
#d3 { -moz-binding:url(#empty1); }
</style>
<script>
function loaded() {
document.getElementById('d4').style.MozBinding = "url(#empty2)";
}
</script>
</head>
<body onload="loaded()">
<div id="d1"> <span>Kitty</span></div>
<div id="d2"><span>Hello</span> </div>
<div id="d3"> <span>Kitty</span></div>
<div id="d4"><span>Hello</span> </div>
</body>
</html>

View File

@ -1385,7 +1385,6 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2b.html 495385-2-
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2c.html 495385-2-ref.html # Bug 1392106
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2d.html 495385-2-ref.html # Bug 1392106
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2e.html 495385-2-ref.html # Bug 1392106
pref(dom.use_xbl_scopes_for_remote_xul,true) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2f.xhtml 495385-2-ref.html # Bug 1392106
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2g.html 495385-2-ref.html # Bug 1392106
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2h.html 495385-2-ref.html # Bug 1392106
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2i.html 495385-2-ref.html # Bug 1392106

View File

@ -27,6 +27,7 @@ skip-if = (verify && debug && (os == 'linux'))
[test_bug703150.xul]
[test_bug987230.xul]
skip-if = os == 'linux' # No native mousedown event on Linux
[test_bug1197913.xul]
[test_popupReflowPos.xul]
[test_popupSizeTo.xul]
[test_popupZoom.xul]

View File

@ -6,7 +6,6 @@ support-files =
[test_bug511075.html]
skip-if = toolkit == 'android' #bug 798806
[test_bug563416.html]
[test_bug1197913.xul]
skip-if = toolkit == 'android'
[test_resizer_incontent.xul]
[test_splitter.xul]

View File

@ -7,8 +7,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1197913
<window title="Mozilla Bug 1197913"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="SimpleTest.waitForFocus(nextTest, window)">
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<!-- test results are displayed in the html:body -->