Bug 763897 - Incorrect behaviour of mozMatchesSelector.call through xray; r=bholley

This commit is contained in:
Gabor Krizsanits 2012-08-27 15:15:20 +02:00
parent 9a223560e1
commit 5138045eff
7 changed files with 142 additions and 18 deletions

View File

@ -65,7 +65,8 @@ const char* XPCJSRuntime::mStrings[] = {
"__scriptOnly__", // IDX_SCRIPTONLY
"baseURIObject", // IDX_BASEURIOBJECT
"nodePrincipal", // IDX_NODEPRINCIPAL
"documentURIObject" // IDX_DOCUMENTURIOBJECT
"documentURIObject", // IDX_DOCUMENTURIOBJECT
"mozMatchesSelector" // IDX_MOZMATCHESSELECTOR
};
/***************************************************************************/

View File

@ -730,6 +730,7 @@ public:
IDX_BASEURIOBJECT ,
IDX_NODEPRINCIPAL ,
IDX_DOCUMENTURIOBJECT ,
IDX_MOZMATCHESSELECTOR ,
IDX_TOTAL_COUNT // just a count of the above
};

View File

@ -52,6 +52,7 @@ MOCHITEST_CHROME_FILES = \
test_expandosharing.xul \
file_expandosharing.jsm \
test_getweakmapkeys.xul \
test_mozMatchesSelector.xul \
test_nodelists.xul \
test_precisegc.xul \
test_sandboxImport.xul \

View File

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=533596
-->
<window title="Mozilla Bug 533596"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<iframe src="http://example.org/tests/js/xpconnect/tests/mochitest/file_mozMatchesSelector.html"
onload="runTest(this)">
</iframe>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
function runTest(ifr)
{
var doc = ifr.contentDocument;
var docElem = doc.documentElement;
var res = doc.createElement('div').mozMatchesSelector('div');
is(res, true, "mozMatchesSelector call through xray, regular case");
res = docElem.mozMatchesSelector.call(
doc.createElement('div'), 'div');
is(res, true, "mozMatchesSelector call through xray, with .call");
var sb = new Components.utils.Sandbox(ifr.contentWindow);
sb.doc = doc;
var str = "doc.documentElement.mozMatchesSelector.call(doc.createElement( 'div' ),'div')";
res = Components.utils.evalInSandbox(str, sb);
is(res, true, "mozMatchesSelector call through xray (same origin), with .call");
docElem.mozMatchesSelector = function(){return false};
res = docElem.mozMatchesSelector.call(doc.createElement( 'div' ),'div');
is(res, false, "shadowing mozMatchesSelector with an expando on the xray wrapper");
SimpleTest.finish();
}
]]></script>
</window>

View File

@ -73,6 +73,7 @@ MOCHITEST_FILES = bug500931_helper.html \
file_documentdomain.html \
test_lookupMethod.html \
file_bug738244.html \
file_mozMatchesSelector.html \
$(NULL)
MOCHITEST_CHROME_FILES = \

View File

@ -0,0 +1 @@
<html><body></body></html>

View File

@ -18,6 +18,7 @@
#include "xpcprivate.h"
#include "jsapi.h"
#include "nsJSUtils.h"
#include "mozilla/dom/BindingUtils.h"
@ -634,14 +635,96 @@ XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, JSObject
return true;
}
template <typename T>
static bool
Is(JSObject *wrapper)
{
JSObject *holder = GetHolder(wrapper);
XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
nsCOMPtr<T> native = do_QueryWrappedNative(wn);
return !!native;
}
// Helper function to work around some limitations of the current XPC
// calling mechanism. See: bug 763897.
// The idea is that we unwrap the 'this' object, and find the wrapped
// native that belongs to it. Then we simply make the call directly
// on it after a Query Interface.
static JSBool
mozMatchesSelectorStub(JSContext *cx, unsigned argc, jsval *vp)
{
if (argc < 1)
JS_ReportError(cx, "Not enough arguments");
JSObject *wrapper = JS_THIS_OBJECT(cx, vp);
JSString *selector = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
nsDependentJSString selectorStr;
NS_ENSURE_TRUE(selectorStr.init(cx, selector), false);
nsCOMPtr<nsIDOMElement> element;
if (IsWrapper(wrapper) && WrapperFactory::IsXrayWrapper(wrapper)) {
// If it's xray wrapped we can get the wn directly.
JSObject *holder = GetHolder(wrapper);
XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
element = do_QueryWrappedNative(wn);
} else {
// Else we can use the XPC utility function for unwrapping it.
nsCOMPtr<nsIXPConnectWrappedNative> iwn;
nsIXPConnect *xpc = nsXPConnect::GetXPConnect();
nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, wrapper,
getter_AddRefs(iwn));
if (NS_FAILED(rv) || !iwn) {
JS_ReportError(cx, "Unexpected object");
return false;
}
element = do_QueryWrappedNative(iwn);
}
if (!element) {
JS_ReportError(cx, "Unexpected object");
return false;
}
bool ret;
nsresult rv = element->MozMatchesSelector(selectorStr, &ret);
if (NS_FAILED(rv)) {
XPCThrower::Throw(rv, cx);
return false;
}
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(ret));
return true;
}
bool
XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, JSObject *wrapper,
JSObject *holder, jsid id, bool set,
JSPropertyDescriptor *desc)
{
MOZ_ASSERT(js::GetObjectJSClass(holder) == &HolderClass);
XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
if (!set &&
id == rt->GetStringID(XPCJSRuntime::IDX_MOZMATCHESSELECTOR) &&
Is<nsIDOMElement>(wrapper))
{
// XPC calling mechanism cannot handle call/bind properly in some cases
// especially through xray wrappers. This is a temoorary work around for
// this problem for mozMatchesSelector. See: bug 763897.
desc->obj = wrapper;
desc->attrs = JSPROP_ENUMERATE;
JSFunction *fun = JS_NewFunction(cx, mozMatchesSelectorStub,
1, 0, JS_GetPrototype(wrapper),
"mozMatchesSelector");
NS_ENSURE_TRUE(fun, false);
desc->value = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun));
desc->getter = NULL;
desc->setter = NULL;
desc->shortid = 0;
return true;
}
desc->obj = NULL;
MOZ_ASSERT(js::GetObjectJSClass(holder) == &HolderClass);
JSObject *wnObject = GetWrappedNativeObjectFromHolder(holder);
XPCWrappedNative *wn = GetWrappedNative(wnObject);
@ -735,16 +818,6 @@ wrappedJSObject_getter(JSContext *cx, JSHandleObject wrapper, JSHandleId id, JSM
return WrapperFactory::WaiveXrayAndWrap(cx, vp.address());
}
template <typename T>
static bool
Is(JSObject *wrapper)
{
JSObject *holder = GetHolder(wrapper);
XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
nsCOMPtr<T> native = do_QueryWrappedNative(wn);
return !!native;
}
static JSBool
WrapURI(JSContext *cx, nsIURI *uri, jsval *vp)
{
@ -933,13 +1006,9 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, js::Wrapper &jsWra
return false;
}
if (!pobj) {
return true;
}
#ifdef DEBUG
NS_ASSERTION(JS_HasPropertyById(cx, holder, id, &hasProp) &&
hasProp, "id got defined somewhere else?");
NS_ASSERTION(!pobj || (JS_HasPropertyById(cx, holder, id, &hasProp) &&
hasProp), "id got defined somewhere else?");
#endif
}