зеркало из https://github.com/mozilla/pjs.git
bug 580128 - Clean up our passing from JS-into-C++ story. r=peterv/mrbkap
This commit is contained in:
Родитель
8fa4142573
Коммит
84dc68b734
|
@ -45,6 +45,8 @@
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
#include "XrayWrapper.h"
|
#include "XrayWrapper.h"
|
||||||
|
#include "AccessCheck.h"
|
||||||
|
#include "WrapperFactory.h"
|
||||||
|
|
||||||
namespace XPCWrapper {
|
namespace XPCWrapper {
|
||||||
|
|
||||||
|
@ -64,10 +66,8 @@ JSObject *
|
||||||
Unwrap(JSContext *cx, JSObject *wrapper)
|
Unwrap(JSContext *cx, JSObject *wrapper)
|
||||||
{
|
{
|
||||||
if (wrapper->isProxy()) {
|
if (wrapper->isProxy()) {
|
||||||
if (wrapper->getProxyHandler() != &JSCrossCompartmentWrapper::singleton) {
|
if (xpc::WrapperFactory::IsScriptAccessOnly(cx, wrapper))
|
||||||
// XXX Security check!
|
return nsnull;
|
||||||
}
|
|
||||||
|
|
||||||
return wrapper->unwrap();
|
return wrapper->unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -314,7 +314,7 @@ MaybePreserveWrapper(JSContext *cx, XPCWrappedNative *wn, uintN flags)
|
||||||
inline JSBool
|
inline JSBool
|
||||||
IsSecurityWrapper(JSObject *wrapper)
|
IsSecurityWrapper(JSObject *wrapper)
|
||||||
{
|
{
|
||||||
return !!wrapper->getClass()->ext.wrappedObject;
|
return wrapper->isWrapper() || !!wrapper->getClass()->ext.wrappedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -67,7 +67,8 @@ const char* XPCJSRuntime::mStrings[] = {
|
||||||
"item", // IDX_ITEM
|
"item", // IDX_ITEM
|
||||||
"__proto__", // IDX_PROTO
|
"__proto__", // IDX_PROTO
|
||||||
"__iterator__", // IDX_ITERATOR
|
"__iterator__", // IDX_ITERATOR
|
||||||
"__exposedProps__" // IDX_EXPOSEDPROPS
|
"__exposedProps__", // IDX_EXPOSEDPROPS
|
||||||
|
"__scriptOnly__" // IDX_SCRIPTONLY
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
|
@ -661,6 +661,7 @@ public:
|
||||||
IDX_PROTO ,
|
IDX_PROTO ,
|
||||||
IDX_ITERATOR ,
|
IDX_ITERATOR ,
|
||||||
IDX_EXPOSEDPROPS ,
|
IDX_EXPOSEDPROPS ,
|
||||||
|
IDX_SCRIPTONLY ,
|
||||||
IDX_TOTAL_COUNT // just a count of the above
|
IDX_TOTAL_COUNT // just a count of the above
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ _TEST_FILES = bug500931_helper.html \
|
||||||
test_bug503926.html \
|
test_bug503926.html \
|
||||||
test_bug504877.html \
|
test_bug504877.html \
|
||||||
test_bug505915.html \
|
test_bug505915.html \
|
||||||
|
file_bug505915.html \
|
||||||
test_bug517163.html \
|
test_bug517163.html \
|
||||||
test_bug553407.html \
|
test_bug553407.html \
|
||||||
test_bug560351.html \
|
test_bug560351.html \
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Inner frame for testing bug 505915.
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=505915
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<body onload="parent.postMessage('', '*');">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -16,9 +16,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=505915
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script type="application/javascript">
|
<script type="application/javascript;version=1.7">
|
||||||
|
|
||||||
/** Test for Bug 505915 **/
|
/** Test for Bug 505915 **/
|
||||||
|
window.addEventListener("message", function () { gen.next() }, false);
|
||||||
|
|
||||||
function go() {
|
function go() {
|
||||||
var ifr = $('ifr');
|
var ifr = $('ifr');
|
||||||
|
@ -48,7 +49,50 @@ function go() {
|
||||||
"threw a security exception instead of an invalid child exception");
|
"threw a security exception instead of an invalid child exception");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Location is always wrapped, so test it separately.
|
||||||
|
|
||||||
|
ifr.onload = null;
|
||||||
|
var path = "/tests/js/src/xpconnect/tests/mochitest/file_bug505915.html";
|
||||||
|
|
||||||
|
ifr.contentWindow.location = "http://mochi.test:8888/" + path;
|
||||||
|
yield;
|
||||||
|
try {
|
||||||
|
document.documentElement.appendChild(ifr.contentWindow.location);
|
||||||
|
ok(false, "weird behavior");
|
||||||
|
} catch (e) {
|
||||||
|
ok(!/NS_ERROR_XPC_SECURITY_MANAGER_VETO/.test(e),
|
||||||
|
"didn't throw a security exception");
|
||||||
|
}
|
||||||
|
oldLocation = ifr.contentWindow.location;
|
||||||
|
ifr.contentWindow.location = "http://example.org/" + path;
|
||||||
|
yield;
|
||||||
|
try {
|
||||||
|
document.documentElement.appendChild(oldLocation);
|
||||||
|
ok(false, "weird behavior");
|
||||||
|
} catch (e) {
|
||||||
|
ok(/NS_ERROR_XPC_SECURITY_MANAGER_VETO/.test(e),
|
||||||
|
"threw a security exception instead of an invalid child exception");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
document.documentElement.appendChild(ifr.contentWindow.location);
|
||||||
|
ok(false, "weird behavior");
|
||||||
|
} catch (e) {
|
||||||
|
ok(/NS_ERROR_XPC_SECURITY_MANAGER_VETO/.test(e),
|
||||||
|
"threw a security exception instead of an invalid child exception");
|
||||||
|
}
|
||||||
|
oldLocation = ifr.contentWindow.location;
|
||||||
|
ifr.contentWindow.location = "http://mochi.test:8888/" + path;
|
||||||
|
yield;
|
||||||
|
try {
|
||||||
|
document.documentElement.appendChild(oldLocation);
|
||||||
|
ok(false, "weird behavior");
|
||||||
|
} catch (e) {
|
||||||
|
ok(!/NS_ERROR_XPC_SECURITY_MANAGER_VETO/.test(e),
|
||||||
|
"didn't throw a security exception");
|
||||||
|
}
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
|
yield;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
@ -56,7 +100,7 @@ SimpleTest.waitForExplicitFinish();
|
||||||
</script>
|
</script>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<iframe id="ifr" onload="go()" src="http://example.org/"></iframe>
|
<iframe id="ifr" onload="gen = go(); gen.next();" src="http://example.org/"></iframe>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -64,19 +64,15 @@ AccessCheck::isSameOrigin(JSCompartment *a, JSCompartment *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AccessCheck::isLocationObjectSameOrigin(JSContext *cx, JSObject *obj)
|
AccessCheck::isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper)
|
||||||
{
|
{
|
||||||
JSCompartment *compartment = obj->compartment();
|
JSObject *obj = wrapper->unwrap()->getParent();
|
||||||
|
|
||||||
obj = obj->unwrap()->getParent();
|
|
||||||
if (!obj->getClass()->ext.innerObject) {
|
if (!obj->getClass()->ext.innerObject) {
|
||||||
obj = obj->unwrap();
|
obj = obj->unwrap();
|
||||||
JS_ASSERT(obj->getClass()->ext.innerObject);
|
JS_ASSERT(obj->getClass()->ext.innerObject);
|
||||||
}
|
}
|
||||||
OBJ_TO_INNER_OBJECT(cx, obj);
|
OBJ_TO_INNER_OBJECT(cx, obj);
|
||||||
if (!obj)
|
return obj && isSameOrigin(wrapper->compartment(), obj->compartment());
|
||||||
return false;
|
|
||||||
return isSameOrigin(compartment, obj->compartment());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -52,7 +52,7 @@ class AccessCheck {
|
||||||
static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id,
|
static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id,
|
||||||
JSWrapper::Action act);
|
JSWrapper::Action act);
|
||||||
static bool isSystemOnlyAccessPermitted(JSContext *cx);
|
static bool isSystemOnlyAccessPermitted(JSContext *cx);
|
||||||
static bool isLocationObjectSameOrigin(JSContext *cx, JSObject *obj);
|
static bool isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper);
|
||||||
|
|
||||||
static bool needsSystemOnlyWrapper(JSObject *obj);
|
static bool needsSystemOnlyWrapper(JSObject *obj);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "AccessCheck.h"
|
#include "AccessCheck.h"
|
||||||
#include "CrossOriginWrapper.h"
|
#include "CrossOriginWrapper.h"
|
||||||
#include "XrayWrapper.h"
|
#include "XrayWrapper.h"
|
||||||
|
#include "WrapperFactory.h"
|
||||||
|
|
||||||
#include "XPCWrapper.h"
|
#include "XPCWrapper.h"
|
||||||
|
|
||||||
|
@ -160,8 +161,8 @@ FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id,
|
||||||
|
|
||||||
template<> SOW SOW::singleton(0);
|
template<> SOW SOW::singleton(0);
|
||||||
template<> COW COW::singleton(0);
|
template<> COW COW::singleton(0);
|
||||||
template<> XOW XOW::singleton(0);
|
template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
|
||||||
template<> NNXOW NNXOW::singleton(0);
|
template<> NNXOW NNXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
|
||||||
template<> LW LW::singleton(0);
|
template<> LW LW::singleton(0);
|
||||||
template<> XLW XLW::singleton(0);
|
template<> XLW XLW::singleton(0);
|
||||||
|
|
||||||
|
|
|
@ -241,4 +241,32 @@ WrapperFactory::WrapLocationObject(JSContext *cx, JSObject *obj)
|
||||||
return wrapperObj;
|
return wrapperObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperFactory::IsScriptAccessOnly(JSContext *cx, JSObject *wrapper)
|
||||||
|
{
|
||||||
|
JS_ASSERT(wrapper->isWrapper());
|
||||||
|
|
||||||
|
uintN flags;
|
||||||
|
JSObject *obj = wrapper->unwrap(&flags);
|
||||||
|
|
||||||
|
// If the wrapper indicates script-only access, we are done.
|
||||||
|
if (flags & SCRIPT_ACCESS_ONLY_FLAG)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// In addition, chrome objects can explicitly opt-in by setting .scriptOnly to true.
|
||||||
|
if (wrapper->getProxyHandler() == &FilteringWrapper<JSCrossCompartmentWrapper,
|
||||||
|
CrossOriginAccessiblePropertiesOnly>::singleton) {
|
||||||
|
jsid scriptOnlyId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_SCRIPTONLY);
|
||||||
|
jsval scriptOnly;
|
||||||
|
if (JS_LookupPropertyById(cx, obj, scriptOnlyId, &scriptOnly) &&
|
||||||
|
scriptOnly == JSVAL_TRUE)
|
||||||
|
return true; // script-only
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow non-script access to same-origin location objects and any other
|
||||||
|
// objects.
|
||||||
|
return IsLocationObject(obj) &&
|
||||||
|
!xpc::AccessCheck::isLocationObjectSameOrigin(cx, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,8 @@ namespace xpc {
|
||||||
class WrapperFactory {
|
class WrapperFactory {
|
||||||
public:
|
public:
|
||||||
enum { WAIVE_XRAY_WRAPPER_FLAG = (1<<0),
|
enum { WAIVE_XRAY_WRAPPER_FLAG = (1<<0),
|
||||||
IS_XRAY_WRAPPER_FLAG = (1<<1) };
|
IS_XRAY_WRAPPER_FLAG = (1<<1),
|
||||||
|
SCRIPT_ACCESS_ONLY_FLAG = (1<<2) };
|
||||||
|
|
||||||
// Return true if any of any of the nested wrappers have the flag set.
|
// Return true if any of any of the nested wrappers have the flag set.
|
||||||
static bool HasWrapperFlag(JSObject *wrapper, uintN flag) {
|
static bool HasWrapperFlag(JSObject *wrapper, uintN flag) {
|
||||||
|
@ -58,6 +59,8 @@ class WrapperFactory {
|
||||||
return HasWrapperFlag(wrapper, IS_XRAY_WRAPPER_FLAG);
|
return HasWrapperFlag(wrapper, IS_XRAY_WRAPPER_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsScriptAccessOnly(JSContext *cx, JSObject *wrapper);
|
||||||
|
|
||||||
// Prepare a given object for wrapping in a new compartment.
|
// Prepare a given object for wrapping in a new compartment.
|
||||||
static JSObject *PrepareForWrapping(JSContext *cx,
|
static JSObject *PrepareForWrapping(JSContext *cx,
|
||||||
JSObject *scope,
|
JSObject *scope,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче