Implement new chrome wrappers (574539, r=mrbkap).
This commit is contained in:
@@ -149,6 +149,22 @@ NewKeyValuePair(JSContext *cx, jsid key, jsval val, jsval *rval)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IdToIteratorValue(JSContext *cx, JSObject *obj, jsid id, uintN flags, jsval *vp)
|
||||||
|
{
|
||||||
|
if (!(flags & JSITER_FOREACH)) {
|
||||||
|
*vp = ID_TO_VALUE(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the lookup on the original object instead of the prototype. */
|
||||||
|
if (!obj->getProperty(cx, id, vp))
|
||||||
|
return false;
|
||||||
|
if ((flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, *vp, vp))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
Enumerate(JSContext *cx, JSObject *obj, JSObject *pobj, jsid id,
|
Enumerate(JSContext *cx, JSObject *obj, JSObject *pobj, jsid id,
|
||||||
bool enumerable, uintN flags, HashSet<jsid>& ht,
|
bool enumerable, uintN flags, HashSet<jsid>& ht,
|
||||||
@@ -166,17 +182,10 @@ Enumerate(JSContext *cx, JSObject *obj, JSObject *pobj, jsid id,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (enumerable || (flags & JSITER_HIDDEN)) {
|
if (enumerable || (flags & JSITER_HIDDEN)) {
|
||||||
if (!vec.append(ID_TO_VALUE(id)))
|
if (!vec.append(JSVAL_VOID))
|
||||||
|
return false;
|
||||||
|
if (!IdToIteratorValue(cx, obj, id, flags, vec.end() - 1))
|
||||||
return false;
|
return false;
|
||||||
if (flags & JSITER_FOREACH) {
|
|
||||||
jsval *vp = vec.end() - 1;
|
|
||||||
|
|
||||||
/* Do the lookup on the original object instead of the prototype. */
|
|
||||||
if (!obj->getProperty(cx, id, vp))
|
|
||||||
return false;
|
|
||||||
if ((flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, *vp, vp))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -434,6 +443,16 @@ IdVectorToIterator(JSContext *cx, JSObject *obj, uintN flags, AutoValueVector &p
|
|||||||
if (!ni)
|
if (!ni)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* If this is a for-each iteration, fetch the values or key/value pairs. */
|
||||||
|
if (flags & JSITER_FOREACH) {
|
||||||
|
size_t length = props.length();
|
||||||
|
for (size_t n = 0; n < length; ++n) {
|
||||||
|
jsval *vp = &ni->begin()[n];
|
||||||
|
if (!IdToIteratorValue(cx, obj, *vp, flags, vp))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iterobj->setNativeIterator(ni);
|
iterobj->setNativeIterator(ni);
|
||||||
|
|
||||||
RegisterEnumerator(cx, iterobj, ni);
|
RegisterEnumerator(cx, iterobj, ni);
|
||||||
|
|||||||
@@ -472,14 +472,14 @@ JSCrossCompartmentWrapper::~JSCrossCompartmentWrapper()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PIERCE(cx, proxy, pre, op, post) \
|
#define PIERCE(cx, proxy, mode, pre, op, post) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
AutoCompartment call(cx, wrappedObject(proxy)); \
|
AutoCompartment call(cx, wrappedObject(proxy)); \
|
||||||
if (!call.enter() || !(pre) || !enter(cx, proxy, id) || !(op)) \
|
if (!call.enter() || !(pre) || !enter(cx, proxy, id, mode) || !(op)) \
|
||||||
return false; \
|
return false; \
|
||||||
leave(cx, proxy); \
|
leave(cx, proxy); \
|
||||||
call.leave(); \
|
call.leave(); \
|
||||||
return (post); \
|
return (post); \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
#define NOTHING (true)
|
#define NOTHING (true)
|
||||||
@@ -487,7 +487,7 @@ JSCrossCompartmentWrapper::~JSCrossCompartmentWrapper()
|
|||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
JSCrossCompartmentWrapper::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
call.destination->wrapId(cx, &id),
|
call.destination->wrapId(cx, &id),
|
||||||
JSWrapper::getPropertyDescriptor(cx, proxy, id, desc),
|
JSWrapper::getPropertyDescriptor(cx, proxy, id, desc),
|
||||||
call.origin->wrap(cx, desc));
|
call.origin->wrap(cx, desc));
|
||||||
@@ -496,7 +496,7 @@ JSCrossCompartmentWrapper::getPropertyDescriptor(JSContext *cx, JSObject *proxy,
|
|||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
JSCrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
call.destination->wrapId(cx, &id),
|
call.destination->wrapId(cx, &id),
|
||||||
JSWrapper::getOwnPropertyDescriptor(cx, proxy, id, desc),
|
JSWrapper::getOwnPropertyDescriptor(cx, proxy, id, desc),
|
||||||
call.origin->wrap(cx, desc));
|
call.origin->wrap(cx, desc));
|
||||||
@@ -506,7 +506,7 @@ bool
|
|||||||
JSCrossCompartmentWrapper::defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
JSCrossCompartmentWrapper::defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
|
||||||
{
|
{
|
||||||
AutoDescriptor desc2(cx, desc);
|
AutoDescriptor desc2(cx, desc);
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, SET,
|
||||||
call.destination->wrapId(cx, &id) && call.destination->wrap(cx, &desc2),
|
call.destination->wrapId(cx, &id) && call.destination->wrap(cx, &desc2),
|
||||||
JSWrapper::getOwnPropertyDescriptor(cx, proxy, id, &desc2),
|
JSWrapper::getOwnPropertyDescriptor(cx, proxy, id, &desc2),
|
||||||
NOTHING);
|
NOTHING);
|
||||||
@@ -515,16 +515,16 @@ JSCrossCompartmentWrapper::defineProperty(JSContext *cx, JSObject *proxy, jsid i
|
|||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoValueVector &props)
|
JSCrossCompartmentWrapper::getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoValueVector &props)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
NOTHING,
|
NOTHING,
|
||||||
JSWrapper::getOwnPropertyNames(cx, proxy, props),
|
JSWrapper::getOwnPropertyNames(cx, proxy, props),
|
||||||
filter(cx, proxy, props) && call.origin->wrap(cx, props));
|
call.origin->wrap(cx, props));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
JSCrossCompartmentWrapper::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, SET,
|
||||||
call.destination->wrapId(cx, &id),
|
call.destination->wrapId(cx, &id),
|
||||||
JSWrapper::delete_(cx, proxy, id, bp),
|
JSWrapper::delete_(cx, proxy, id, bp),
|
||||||
NOTHING);
|
NOTHING);
|
||||||
@@ -533,16 +533,16 @@ JSCrossCompartmentWrapper::delete_(JSContext *cx, JSObject *proxy, jsid id, bool
|
|||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::enumerate(JSContext *cx, JSObject *proxy, AutoValueVector &props)
|
JSCrossCompartmentWrapper::enumerate(JSContext *cx, JSObject *proxy, AutoValueVector &props)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
NOTHING,
|
NOTHING,
|
||||||
JSWrapper::enumerate(cx, proxy, props),
|
JSWrapper::enumerate(cx, proxy, props),
|
||||||
filter(cx, proxy, props) && call.origin->wrap(cx, props));
|
call.origin->wrap(cx, props));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
JSCrossCompartmentWrapper::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
call.destination->wrapId(cx, &id),
|
call.destination->wrapId(cx, &id),
|
||||||
JSWrapper::has(cx, proxy, id, bp),
|
JSWrapper::has(cx, proxy, id, bp),
|
||||||
NOTHING);
|
NOTHING);
|
||||||
@@ -551,7 +551,7 @@ JSCrossCompartmentWrapper::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp
|
|||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
JSCrossCompartmentWrapper::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
call.destination->wrapId(cx, &id),
|
call.destination->wrapId(cx, &id),
|
||||||
JSWrapper::hasOwn(cx, proxy, id, bp),
|
JSWrapper::hasOwn(cx, proxy, id, bp),
|
||||||
NOTHING);
|
NOTHING);
|
||||||
@@ -560,7 +560,7 @@ JSCrossCompartmentWrapper::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool
|
|||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
JSCrossCompartmentWrapper::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
call.destination->wrap(cx, &receiver) && call.destination->wrapId(cx, &id),
|
call.destination->wrap(cx, &receiver) && call.destination->wrapId(cx, &id),
|
||||||
JSWrapper::get(cx, proxy, receiver, id, vp),
|
JSWrapper::get(cx, proxy, receiver, id, vp),
|
||||||
call.origin->wrap(cx, vp));
|
call.origin->wrap(cx, vp));
|
||||||
@@ -570,7 +570,7 @@ bool
|
|||||||
JSCrossCompartmentWrapper::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
JSCrossCompartmentWrapper::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
|
||||||
{
|
{
|
||||||
AutoValueRooter tvr(cx, *vp);
|
AutoValueRooter tvr(cx, *vp);
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, SET,
|
||||||
call.destination->wrap(cx, &receiver) && call.destination->wrapId(cx, &id) && call.destination->wrap(cx, tvr.addr()),
|
call.destination->wrap(cx, &receiver) && call.destination->wrapId(cx, &id) && call.destination->wrap(cx, tvr.addr()),
|
||||||
JSWrapper::set(cx, proxy, receiver, id, tvr.addr()),
|
JSWrapper::set(cx, proxy, receiver, id, tvr.addr()),
|
||||||
NOTHING);
|
NOTHING);
|
||||||
@@ -579,19 +579,49 @@ JSCrossCompartmentWrapper::set(JSContext *cx, JSObject *proxy, JSObject *receive
|
|||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::enumerateOwn(JSContext *cx, JSObject *proxy, AutoValueVector &props)
|
JSCrossCompartmentWrapper::enumerateOwn(JSContext *cx, JSObject *proxy, AutoValueVector &props)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
NOTHING,
|
NOTHING,
|
||||||
JSWrapper::enumerateOwn(cx, proxy, props),
|
JSWrapper::enumerateOwn(cx, proxy, props),
|
||||||
filter(cx, proxy, props) && call.origin->wrap(cx, props));
|
call.origin->wrap(cx, props));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can reify non-escaping iterator objects instead of having to wrap them. This
|
||||||
|
* allows fast iteration over objects across a compartment boundary.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
CanReify(jsval *vp)
|
||||||
|
{
|
||||||
|
return !JSVAL_IS_PRIMITIVE(*vp) &&
|
||||||
|
JSVAL_TO_OBJECT(*vp)->getClass() == &js_IteratorClass.base &&
|
||||||
|
!!(JSVAL_TO_OBJECT(*vp)->getNativeIterator()->flags & JSITER_ENUMERATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
Reify(JSContext *cx, JSCompartment *origin, jsval *vp)
|
||||||
|
{
|
||||||
|
JSObject *iterObj = JSVAL_TO_OBJECT(*vp);
|
||||||
|
NativeIterator *ni = iterObj->getNativeIterator();
|
||||||
|
AutoValueVector props(cx);
|
||||||
|
size_t length = ni->length();
|
||||||
|
if (length > 0) {
|
||||||
|
props.resize(length);
|
||||||
|
for (size_t n = 0; n < length; ++n)
|
||||||
|
props[n] = origin->wrap(cx, &ni->begin()[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *obj = ni->obj;
|
||||||
|
return origin->wrap(cx, &obj) &&
|
||||||
|
IdVectorToIterator(cx, obj, ni->flags, props, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
|
JSCrossCompartmentWrapper::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
|
||||||
{
|
{
|
||||||
PIERCE(cx, proxy,
|
PIERCE(cx, proxy, GET,
|
||||||
NOTHING,
|
NOTHING,
|
||||||
JSWrapper::iterate(cx, proxy, flags, vp),
|
JSWrapper::iterate(cx, proxy, flags, vp),
|
||||||
filter(cx, proxy, vp) && call.origin->wrap(cx, vp));
|
CanReify(vp) ? Reify(cx, call.origin, vp) : call.origin->wrap(cx, vp));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -612,7 +642,7 @@ JSCrossCompartmentWrapper::call(JSContext *cx, JSObject *proxy, uintN argc, jsva
|
|||||||
jsval *fakevp = call.getvp();
|
jsval *fakevp = call.getvp();
|
||||||
fakevp[0] = vp[0];
|
fakevp[0] = vp[0];
|
||||||
fakevp[1] = vp[1];
|
fakevp[1] = vp[1];
|
||||||
if (!enter(cx, proxy, JSVAL_VOID) || !JSWrapper::call(cx, proxy, argc, vp))
|
if (!enter(cx, proxy, JSVAL_VOID, GET) || !JSWrapper::call(cx, proxy, argc, vp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
leave(cx, proxy);
|
leave(cx, proxy);
|
||||||
@@ -635,7 +665,7 @@ JSCrossCompartmentWrapper::construct(JSContext *cx, JSObject *proxy, JSObject *r
|
|||||||
jsval *vp = call.getvp();
|
jsval *vp = call.getvp();
|
||||||
vp[0] = OBJECT_TO_JSVAL(call.target);
|
vp[0] = OBJECT_TO_JSVAL(call.target);
|
||||||
if (!call.destination->wrap(cx, &receiver) ||
|
if (!call.destination->wrap(cx, &receiver) ||
|
||||||
!enter(cx, proxy, JSVAL_VOID) ||
|
!enter(cx, proxy, JSVAL_VOID, GET) ||
|
||||||
!JSWrapper::construct(cx, proxy, receiver, argc, argv, rval)) {
|
!JSWrapper::construct(cx, proxy, receiver, argc, argv, rval)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -653,7 +683,7 @@ JSCrossCompartmentWrapper::obj_toString(JSContext *cx, JSObject *proxy)
|
|||||||
if (!call.enter())
|
if (!call.enter())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!enter(cx, proxy, JSVAL_VOID))
|
if (!enter(cx, proxy, JSVAL_VOID, GET))
|
||||||
return NULL;
|
return NULL;
|
||||||
JSString *str = JSWrapper::obj_toString(cx, proxy);
|
JSString *str = JSWrapper::obj_toString(cx, proxy);
|
||||||
if (!str)
|
if (!str)
|
||||||
@@ -674,7 +704,7 @@ JSCrossCompartmentWrapper::fun_toString(JSContext *cx, JSObject *proxy, uintN in
|
|||||||
if (!call.enter())
|
if (!call.enter())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!enter(cx, proxy, JSVAL_VOID))
|
if (!enter(cx, proxy, JSVAL_VOID, GET))
|
||||||
return NULL;
|
return NULL;
|
||||||
JSString *str = JSWrapper::fun_toString(cx, proxy, indent);
|
JSString *str = JSWrapper::fun_toString(cx, proxy, indent);
|
||||||
if (!str)
|
if (!str)
|
||||||
@@ -689,7 +719,7 @@ JSCrossCompartmentWrapper::fun_toString(JSContext *cx, JSObject *proxy, uintN in
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSCrossCompartmentWrapper::enter(JSContext *cx, JSObject *proxy, jsval id)
|
JSCrossCompartmentWrapper::enter(JSContext *cx, JSObject *proxy, jsval id, Mode mode)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -699,16 +729,4 @@ JSCrossCompartmentWrapper::leave(JSContext *cx, JSObject *proxy)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
JSCrossCompartmentWrapper::filter(JSContext *cx, JSObject *proxy, AutoValueVector &props)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JSCrossCompartmentWrapper::filter(JSContext *cx, JSObject *proxy, jsval *vp)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSCrossCompartmentWrapper JSCrossCompartmentWrapper::singleton;
|
JSCrossCompartmentWrapper JSCrossCompartmentWrapper::singleton;
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ class JSCrossCompartmentWrapper : public JSWrapper {
|
|||||||
JS_FRIEND_API(JSCrossCompartmentWrapper());
|
JS_FRIEND_API(JSCrossCompartmentWrapper());
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef enum { GET, SET } Mode;
|
||||||
|
|
||||||
virtual JS_FRIEND_API(~JSCrossCompartmentWrapper());
|
virtual JS_FRIEND_API(~JSCrossCompartmentWrapper());
|
||||||
|
|
||||||
/* ES5 Harmony fundamental proxy traps. */
|
/* ES5 Harmony fundamental proxy traps. */
|
||||||
@@ -130,10 +132,8 @@ class JSCrossCompartmentWrapper : public JSWrapper {
|
|||||||
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, uintN indent);
|
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, uintN indent);
|
||||||
|
|
||||||
/* Policy enforcement traps. */
|
/* Policy enforcement traps. */
|
||||||
virtual bool enter(JSContext *cx, JSObject *proxy, jsid id);
|
virtual bool enter(JSContext *cx, JSObject *proxy, jsid id, Mode mode);
|
||||||
virtual void leave(JSContext *cx, JSObject *proxy);
|
virtual void leave(JSContext *cx, JSObject *proxy);
|
||||||
virtual bool filter(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
|
|
||||||
virtual bool filter(JSContext *cx, JSObject *proxy, jsval *vp);
|
|
||||||
|
|
||||||
static JSCrossCompartmentWrapper singleton;
|
static JSCrossCompartmentWrapper singleton;
|
||||||
|
|
||||||
|
|||||||
115
js/src/xpconnect/src/wrappers/AccessCheck.cpp
Normal file
115
js/src/xpconnect/src/wrappers/AccessCheck.cpp
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code, released
|
||||||
|
* June 24, 2010.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Andreas Gal <gal@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jswrapper.h"
|
||||||
|
|
||||||
|
#include "XPCWrapper.h"
|
||||||
|
|
||||||
|
#include "nsJSPrincipals.h"
|
||||||
|
|
||||||
|
#include "AccessCheck.h"
|
||||||
|
|
||||||
|
namespace xpc {
|
||||||
|
|
||||||
|
nsIPrincipal *
|
||||||
|
GetCompartmentPrincipal(JSCompartment *compartment)
|
||||||
|
{
|
||||||
|
return static_cast<nsJSPrincipals *>(compartment->principals)->nsIPrincipalPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AccessCheck::isPrivileged(JSCompartment *compartment)
|
||||||
|
{
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if(!ssm) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool privileged;
|
||||||
|
if(NS_SUCCEEDED(ssm->IsSystemPrincipal(GetCompartmentPrincipal(compartment), &privileged))
|
||||||
|
&& privileged) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) && privileged) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AccessCheck::deny(JSContext *cx, jsid id)
|
||||||
|
{
|
||||||
|
if(id == JSVAL_VOID) {
|
||||||
|
JS_ReportError(cx, "Permission denied to access object");
|
||||||
|
} else {
|
||||||
|
JSString *str = JS_ValueToString(cx, id);
|
||||||
|
JS_ReportError(cx, "Permission denied to access property '%hs'", str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AccessCheck::enter(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject, jsid id,
|
||||||
|
JSCrossCompartmentWrapper::Mode mode)
|
||||||
|
{
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if(!ssm) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
JSStackFrame *fp = NULL;
|
||||||
|
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp),
|
||||||
|
GetCompartmentPrincipal(wrappedObject->getCompartment(cx)));
|
||||||
|
if(NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("Not allowing call because we're out of memory");
|
||||||
|
JS_ReportOutOfMemory(cx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AccessCheck::leave(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject)
|
||||||
|
{
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if(ssm) {
|
||||||
|
ssm->PopContextPrincipal(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
57
js/src/xpconnect/src/wrappers/AccessCheck.h
Normal file
57
js/src/xpconnect/src/wrappers/AccessCheck.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code, released
|
||||||
|
* June 24, 2010.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Andreas Gal <gal@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jswrapper.h"
|
||||||
|
|
||||||
|
namespace xpc {
|
||||||
|
|
||||||
|
class AccessCheck {
|
||||||
|
public:
|
||||||
|
static bool subsumes(JSCompartment *subject, JSCompartment *object, bool *yesno);
|
||||||
|
static bool isPrivileged(JSCompartment *compartment);
|
||||||
|
|
||||||
|
static void deny(JSContext *cx, jsid id);
|
||||||
|
|
||||||
|
static bool enter(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject, jsid id,
|
||||||
|
JSCrossCompartmentWrapper::Mode mode);
|
||||||
|
static void leave(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
244
js/src/xpconnect/src/wrappers/ChromeWrapper.cpp
Normal file
244
js/src/xpconnect/src/wrappers/ChromeWrapper.cpp
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code, released
|
||||||
|
* June 24, 2010.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Andreas Gal <gal@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "ChromeWrapper.h"
|
||||||
|
#include "AccessCheck.h"
|
||||||
|
|
||||||
|
#include "XPCWrapper.h"
|
||||||
|
|
||||||
|
using namespace js;
|
||||||
|
|
||||||
|
namespace xpc {
|
||||||
|
|
||||||
|
ChromeWrapper ChromeWrapper::singleton;
|
||||||
|
|
||||||
|
ChromeWrapper::ChromeWrapper() : JSCrossCompartmentWrapper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ChromeWrapper::~ChromeWrapper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum { READ = (1<<0), WRITE = (1<<1), DENIED=0 } Permission;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
Allow(JSContext *cx, bool *yesno)
|
||||||
|
{
|
||||||
|
if(yesno) {
|
||||||
|
*yesno = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
Deny(JSContext *cx, bool *yesno, const char *error)
|
||||||
|
{
|
||||||
|
if(yesno) {
|
||||||
|
*yesno = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
JS_ReportError(cx, error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckAccess(JSContext *cx, JSObject *hallpass, jsid id, JSCrossCompartmentWrapper::Mode mode,
|
||||||
|
bool *yesno = NULL)
|
||||||
|
{
|
||||||
|
if(!hallpass) {
|
||||||
|
return Allow(cx, yesno);
|
||||||
|
}
|
||||||
|
|
||||||
|
Permission perm = DENIED;
|
||||||
|
|
||||||
|
jsval v;
|
||||||
|
if(!JS_LookupPropertyById(cx, hallpass, id, &v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!JSVAL_IS_STRING(v)) {
|
||||||
|
return Deny(cx, yesno, "property permission must be a string");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString *str = JSVAL_TO_STRING(v);
|
||||||
|
const jschar *chars = JS_GetStringChars(str);
|
||||||
|
size_t length = JS_GetStringLength(str);
|
||||||
|
for (size_t i = 0; i < length; ++i) {
|
||||||
|
switch (chars[i]) {
|
||||||
|
case 'r':
|
||||||
|
if(perm & READ) {
|
||||||
|
return Deny(cx, yesno, "duplicate 'readable' property flag");
|
||||||
|
}
|
||||||
|
perm = Permission(perm | READ);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
if(perm & WRITE) {
|
||||||
|
return Deny(cx, yesno, "duplicate 'writable' property flag");
|
||||||
|
}
|
||||||
|
perm = Permission(perm | WRITE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Deny(cx, yesno, "property permission can only be readable or read and writable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(perm == DENIED) {
|
||||||
|
return Deny(cx, yesno, "invalid property permission");
|
||||||
|
}
|
||||||
|
|
||||||
|
if((mode == JSCrossCompartmentWrapper::GET && !(perm & READ)) ||
|
||||||
|
(mode == JSCrossCompartmentWrapper::SET && !(perm & WRITE))) {
|
||||||
|
if(yesno) {
|
||||||
|
*yesno = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AccessCheck::deny(cx, id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Allow(cx, yesno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
GetHallPass(JSContext *cx, JSObject *wrappedObject, jsid id, JSObject **hallpassp)
|
||||||
|
{
|
||||||
|
jsid exposedPropsId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS);
|
||||||
|
|
||||||
|
JSBool found = JS_FALSE;
|
||||||
|
if(!JS_HasPropertyById(cx, wrappedObject, exposedPropsId, &found))
|
||||||
|
return false;
|
||||||
|
if(!found) {
|
||||||
|
*hallpassp = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsval exposedProps;
|
||||||
|
if(!JS_LookupPropertyById(cx, wrappedObject, exposedPropsId, &exposedProps))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(JSVAL_IS_VOID(exposedProps) || JSVAL_IS_NULL(exposedProps)) {
|
||||||
|
AccessCheck::deny(cx, id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!JSVAL_IS_OBJECT(exposedProps)) {
|
||||||
|
JS_ReportError(cx,
|
||||||
|
"__exposedProps__ must be undefined, null, or an object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hallpassp = JSVAL_TO_OBJECT(exposedProps);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
Filter(JSContext *cx, JSObject *wrappedObject, AutoValueVector &props)
|
||||||
|
{
|
||||||
|
JSObject *hallpass;
|
||||||
|
if(!GetHallPass(cx, wrappedObject, JSVAL_VOID, &hallpass))
|
||||||
|
return false;
|
||||||
|
if(!hallpass)
|
||||||
|
return true;
|
||||||
|
size_t w = 0;
|
||||||
|
for (size_t n = 0; n < props.length(); ++n) {
|
||||||
|
bool yes;
|
||||||
|
jsid id = props[n];
|
||||||
|
if(!CheckAccess(cx, hallpass, id, JSCrossCompartmentWrapper::GET, &yes))
|
||||||
|
return false;
|
||||||
|
if(yes) {
|
||||||
|
props[w++] = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
props.resize(w);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ChromeWrapper::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
|
||||||
|
{
|
||||||
|
return JSCrossCompartmentWrapper::getOwnPropertyNames(cx, wrapper, props) &&
|
||||||
|
Filter(cx, wrappedObject(wrapper), props);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ChromeWrapper::enumerate(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
|
||||||
|
{
|
||||||
|
return JSCrossCompartmentWrapper::enumerate(cx, wrapper, props) &&
|
||||||
|
Filter(cx, wrappedObject(wrapper), props);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ChromeWrapper::enumerateOwn(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
|
||||||
|
{
|
||||||
|
return JSCrossCompartmentWrapper::enumerateOwn(cx, wrapper, props) &&
|
||||||
|
Filter(cx, wrappedObject(wrapper), props);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ChromeWrapper::iterate(JSContext *cx, JSObject *wrapper, uintN flags, jsval *vp)
|
||||||
|
{
|
||||||
|
// We refuse to trigger the iterator hook across chrome wrappers because
|
||||||
|
// we don't know how to censor custom iterator objects. Instead we trigger
|
||||||
|
// the default proxy iterate trap, which will ask ChromeWrapper::enumerate()
|
||||||
|
// for the list of (consored) ids.
|
||||||
|
return JSProxyHandler::iterate(cx, wrapper, flags, vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ChromeWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode)
|
||||||
|
{
|
||||||
|
JSObject *hallpass;
|
||||||
|
return GetHallPass(cx, wrappedObject(wrapper), id, &hallpass) &&
|
||||||
|
CheckAccess(cx, hallpass, id, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString *
|
||||||
|
ChromeWrapper::fun_toString(JSContext *cx, JSObject *wrapper, uintN indent)
|
||||||
|
{
|
||||||
|
// Censor Function.prototype.toString.call(wrapper) and decompile Function instead.
|
||||||
|
JSObject *ctor;
|
||||||
|
if(!JS_GetClassObject(cx, wrapper->getGlobal(), JSProto_Function, &ctor))
|
||||||
|
return false;
|
||||||
|
return JS_DecompileFunction(cx, JS_ValueToConstructor(cx, OBJECT_TO_JSVAL(ctor)), indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
62
js/src/xpconnect/src/wrappers/ChromeWrapper.h
Normal file
62
js/src/xpconnect/src/wrappers/ChromeWrapper.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code, released
|
||||||
|
* June 24, 2010.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Andreas Gal <gal@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jswrapper.h"
|
||||||
|
|
||||||
|
namespace xpc {
|
||||||
|
|
||||||
|
class ChromeWrapper : public JSCrossCompartmentWrapper {
|
||||||
|
public:
|
||||||
|
ChromeWrapper();
|
||||||
|
virtual ~ChromeWrapper();
|
||||||
|
|
||||||
|
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
|
||||||
|
virtual bool enumerate(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
|
||||||
|
virtual bool enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
|
||||||
|
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
|
||||||
|
|
||||||
|
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode);
|
||||||
|
|
||||||
|
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
|
||||||
|
|
||||||
|
static ChromeWrapper singleton;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
* for the specific language governing rights and limitations under the
|
* for the specific language governing rights and limitations under the
|
||||||
* License.
|
* License.
|
||||||
*
|
*
|
||||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9.1 code, released
|
* The Original Code is mozilla.org code, released
|
||||||
* June 30, 2009.
|
* June 24, 2010.
|
||||||
*
|
*
|
||||||
* The Initial Developer of the Original Code is
|
* The Initial Developer of the Original Code is
|
||||||
* The Mozilla Foundation
|
* The Mozilla Foundation
|
||||||
@@ -37,25 +37,12 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "ContentWrapper.h"
|
||||||
#include "jswrapper.h"
|
#include "AccessCheck.h"
|
||||||
|
|
||||||
#include "XPCWrapper.h"
|
|
||||||
|
|
||||||
#include "nsJSPrincipals.h"
|
|
||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
||||||
class ContentWrapper : public JSCrossCompartmentWrapper {
|
ContentWrapper ContentWrapper::singleton;
|
||||||
public:
|
|
||||||
ContentWrapper();
|
|
||||||
virtual ~ContentWrapper();
|
|
||||||
|
|
||||||
virtual bool enter(JSContext *cx, JSObject *proxy, jsid id);
|
|
||||||
virtual void leave(JSContext *cx, JSObject *proxy);
|
|
||||||
|
|
||||||
static ContentWrapper singleton;
|
|
||||||
};
|
|
||||||
|
|
||||||
ContentWrapper::ContentWrapper() : JSCrossCompartmentWrapper()
|
ContentWrapper::ContentWrapper() : JSCrossCompartmentWrapper()
|
||||||
{
|
{
|
||||||
@@ -66,41 +53,15 @@ ContentWrapper::~ContentWrapper()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id)
|
ContentWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode)
|
||||||
{
|
{
|
||||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
return AccessCheck::enter(cx, wrapper, wrappedObject(wrapper), id, mode);
|
||||||
if(!ssm) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
JSPrincipals *subjectPrincipals = wrapper->getCompartment(cx)->principals;
|
|
||||||
JSPrincipals *objectPrincipals = wrappedObject(wrapper)->getCompartment(cx)->principals;
|
|
||||||
if(!subjectPrincipals->subsume(subjectPrincipals, objectPrincipals)) {
|
|
||||||
if(id == JSVAL_VOID) {
|
|
||||||
JS_ReportError(cx, "Permission denied to access object");
|
|
||||||
} else {
|
|
||||||
JSString *str = JS_ValueToString(cx, id);
|
|
||||||
JS_ReportError(cx, "Permission denied to access property '%hs'", str);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
JSStackFrame *fp = nsnull;
|
|
||||||
nsIPrincipal *principal = static_cast<nsJSPrincipals *>(objectPrincipals)->nsIPrincipalPtr;
|
|
||||||
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
NS_WARNING("Not allowing call because we're out of memory");
|
|
||||||
JS_ReportOutOfMemory(cx);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ContentWrapper::leave(JSContext *cx, JSObject *proxy)
|
ContentWrapper::leave(JSContext *cx, JSObject *wrapper)
|
||||||
{
|
{
|
||||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
return AccessCheck::leave(cx, wrapper, wrappedObject(wrapper));
|
||||||
if (ssm) {
|
|
||||||
ssm->PopContextPrincipal(cx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
64
js/src/xpconnect/src/wrappers/ContentWrapper.h
Normal file
64
js/src/xpconnect/src/wrappers/ContentWrapper.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code, released
|
||||||
|
* June 24, 2010.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Andreas Gal <gal@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jswrapper.h"
|
||||||
|
|
||||||
|
// Content wrappers allow unmitigated access and are only used if the
|
||||||
|
// origin (subject) compartment's principals subsume the target (object)
|
||||||
|
// compartment's principals.
|
||||||
|
//
|
||||||
|
// The main responsibility of the content wrapper is to push and pop the
|
||||||
|
// target (object) compartment's principals when entering and leaving
|
||||||
|
// that compartment.
|
||||||
|
|
||||||
|
namespace xpc {
|
||||||
|
|
||||||
|
class ContentWrapper : public JSCrossCompartmentWrapper {
|
||||||
|
public:
|
||||||
|
ContentWrapper();
|
||||||
|
virtual ~ContentWrapper();
|
||||||
|
|
||||||
|
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode);
|
||||||
|
virtual void leave(JSContext *cx, JSObject *wrapper);
|
||||||
|
|
||||||
|
static ContentWrapper singleton;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -47,7 +47,10 @@ LIBRARY_NAME = xpcwrappers_s
|
|||||||
FORCE_STATIC_LIB = 1
|
FORCE_STATIC_LIB = 1
|
||||||
LIBXUL_LIBRARY = 1
|
LIBXUL_LIBRARY = 1
|
||||||
|
|
||||||
CPPSRCS = ContentWrapper.cpp
|
CPPSRCS = ContentWrapper.cpp \
|
||||||
|
ChromeWrapper.cpp \
|
||||||
|
AccessCheck.cpp \
|
||||||
|
WrapperFactory.cpp
|
||||||
|
|
||||||
LOCAL_INCLUDES = \
|
LOCAL_INCLUDES = \
|
||||||
-I$(srcdir)/.. \
|
-I$(srcdir)/.. \
|
||||||
|
|||||||
56
js/src/xpconnect/src/wrappers/WrapperFactory.cpp
Normal file
56
js/src/xpconnect/src/wrappers/WrapperFactory.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code, released
|
||||||
|
* June 24, 2010.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Andreas Gal <gal@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "WrapperFactory.h"
|
||||||
|
#include "ContentWrapper.h"
|
||||||
|
#include "ChromeWrapper.h"
|
||||||
|
#include "AccessCheck.h"
|
||||||
|
|
||||||
|
namespace xpc {
|
||||||
|
|
||||||
|
JSCrossCompartmentWrapper *
|
||||||
|
WrapperFactory::select(JSContext *cx, JSCompartment *subject, JSCompartment *object)
|
||||||
|
{
|
||||||
|
if(AccessCheck::isPrivileged(object)) {
|
||||||
|
return &ChromeWrapper::singleton;
|
||||||
|
}
|
||||||
|
return &ContentWrapper::singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
52
js/src/xpconnect/src/wrappers/WrapperFactory.h
Normal file
52
js/src/xpconnect/src/wrappers/WrapperFactory.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||||
|
*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code, released
|
||||||
|
* June 24, 2010.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* The Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Andreas Gal <gal@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jswrapper.h"
|
||||||
|
|
||||||
|
namespace xpc {
|
||||||
|
|
||||||
|
class WrapperFactory {
|
||||||
|
// Return the wrapper handler to use, or NULL in case of error.
|
||||||
|
static JSCrossCompartmentWrapper *select(JSContext *cx,
|
||||||
|
JSCompartment *subject,
|
||||||
|
JSCompartment *object);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user