зеркало из 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 "jswrapper.h"
|
||||
#include "XrayWrapper.h"
|
||||
#include "AccessCheck.h"
|
||||
#include "WrapperFactory.h"
|
||||
|
||||
namespace XPCWrapper {
|
||||
|
||||
|
@ -64,10 +66,8 @@ JSObject *
|
|||
Unwrap(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
if (wrapper->isProxy()) {
|
||||
if (wrapper->getProxyHandler() != &JSCrossCompartmentWrapper::singleton) {
|
||||
// XXX Security check!
|
||||
}
|
||||
|
||||
if (xpc::WrapperFactory::IsScriptAccessOnly(cx, wrapper))
|
||||
return nsnull;
|
||||
return wrapper->unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -314,7 +314,7 @@ MaybePreserveWrapper(JSContext *cx, XPCWrappedNative *wn, uintN flags)
|
|||
inline JSBool
|
||||
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
|
||||
"__proto__", // IDX_PROTO
|
||||
"__iterator__", // IDX_ITERATOR
|
||||
"__exposedProps__" // IDX_EXPOSEDPROPS
|
||||
"__exposedProps__", // IDX_EXPOSEDPROPS
|
||||
"__scriptOnly__" // IDX_SCRIPTONLY
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -661,6 +661,7 @@ public:
|
|||
IDX_PROTO ,
|
||||
IDX_ITERATOR ,
|
||||
IDX_EXPOSEDPROPS ,
|
||||
IDX_SCRIPTONLY ,
|
||||
IDX_TOTAL_COUNT // just a count of the above
|
||||
};
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ _TEST_FILES = bug500931_helper.html \
|
|||
test_bug503926.html \
|
||||
test_bug504877.html \
|
||||
test_bug505915.html \
|
||||
file_bug505915.html \
|
||||
test_bug517163.html \
|
||||
test_bug553407.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>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 505915 **/
|
||||
window.addEventListener("message", function () { gen.next() }, false);
|
||||
|
||||
function go() {
|
||||
var ifr = $('ifr');
|
||||
|
@ -48,7 +49,50 @@ function go() {
|
|||
"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();
|
||||
yield;
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -56,7 +100,7 @@ SimpleTest.waitForExplicitFinish();
|
|||
</script>
|
||||
</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>
|
||||
</html>
|
||||
|
|
|
@ -64,19 +64,15 @@ AccessCheck::isSameOrigin(JSCompartment *a, JSCompartment *b)
|
|||
}
|
||||
|
||||
bool
|
||||
AccessCheck::isLocationObjectSameOrigin(JSContext *cx, JSObject *obj)
|
||||
AccessCheck::isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSCompartment *compartment = obj->compartment();
|
||||
|
||||
obj = obj->unwrap()->getParent();
|
||||
JSObject *obj = wrapper->unwrap()->getParent();
|
||||
if (!obj->getClass()->ext.innerObject) {
|
||||
obj = obj->unwrap();
|
||||
JS_ASSERT(obj->getClass()->ext.innerObject);
|
||||
}
|
||||
OBJ_TO_INNER_OBJECT(cx, obj);
|
||||
if (!obj)
|
||||
return false;
|
||||
return isSameOrigin(compartment, obj->compartment());
|
||||
return obj && isSameOrigin(wrapper->compartment(), obj->compartment());
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -52,7 +52,7 @@ class AccessCheck {
|
|||
static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWrapper::Action act);
|
||||
static bool isSystemOnlyAccessPermitted(JSContext *cx);
|
||||
static bool isLocationObjectSameOrigin(JSContext *cx, JSObject *obj);
|
||||
static bool isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
static bool needsSystemOnlyWrapper(JSObject *obj);
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "AccessCheck.h"
|
||||
#include "CrossOriginWrapper.h"
|
||||
#include "XrayWrapper.h"
|
||||
#include "WrapperFactory.h"
|
||||
|
||||
#include "XPCWrapper.h"
|
||||
|
||||
|
@ -160,8 +161,8 @@ FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id,
|
|||
|
||||
template<> SOW SOW::singleton(0);
|
||||
template<> COW COW::singleton(0);
|
||||
template<> XOW XOW::singleton(0);
|
||||
template<> NNXOW NNXOW::singleton(0);
|
||||
template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
|
||||
template<> NNXOW NNXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
|
||||
template<> LW LW::singleton(0);
|
||||
template<> XLW XLW::singleton(0);
|
||||
|
||||
|
|
|
@ -241,4 +241,32 @@ WrapperFactory::WrapLocationObject(JSContext *cx, JSObject *obj)
|
|||
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 {
|
||||
public:
|
||||
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.
|
||||
static bool HasWrapperFlag(JSObject *wrapper, uintN flag) {
|
||||
|
@ -58,6 +59,8 @@ class WrapperFactory {
|
|||
return HasWrapperFlag(wrapper, IS_XRAY_WRAPPER_FLAG);
|
||||
}
|
||||
|
||||
static bool IsScriptAccessOnly(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
// Prepare a given object for wrapping in a new compartment.
|
||||
static JSObject *PrepareForWrapping(JSContext *cx,
|
||||
JSObject *scope,
|
||||
|
|
Загрузка…
Ссылка в новой задаче