2014-04-03 15:58:00 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
2012-05-21 15:12:37 +04:00
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2010-06-26 02:58:09 +04:00
|
|
|
|
2010-07-03 00:54:53 +04:00
|
|
|
#include "AccessCheck.h"
|
2010-06-26 02:58:09 +04:00
|
|
|
|
|
|
|
#include "nsJSPrincipals.h"
|
2017-03-07 07:09:49 +03:00
|
|
|
#include "BasePrincipal.h"
|
2018-05-25 06:32:19 +03:00
|
|
|
#include "nsDOMWindowList.h"
|
2013-11-05 12:47:59 +04:00
|
|
|
#include "nsGlobalWindow.h"
|
2010-06-26 02:58:09 +04:00
|
|
|
|
2010-07-03 00:54:53 +04:00
|
|
|
#include "XPCWrapper.h"
|
2010-09-18 01:54:40 +04:00
|
|
|
#include "XrayWrapper.h"
|
2016-12-02 23:24:20 +03:00
|
|
|
#include "FilteringWrapper.h"
|
2010-06-26 02:58:09 +04:00
|
|
|
|
2011-04-13 20:27:37 +04:00
|
|
|
#include "jsfriendapi.h"
|
2017-02-02 20:48:49 +03:00
|
|
|
#include "mozilla/ErrorResult.h"
|
2012-09-13 00:29:30 +04:00
|
|
|
#include "mozilla/dom/BindingUtils.h"
|
2014-07-12 03:34:44 +04:00
|
|
|
#include "mozilla/dom/LocationBinding.h"
|
2013-12-09 19:34:03 +04:00
|
|
|
#include "mozilla/dom/WindowBinding.h"
|
2015-01-27 00:32:18 +03:00
|
|
|
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
2013-11-05 12:47:59 +04:00
|
|
|
#include "nsJSUtils.h"
|
2016-08-04 21:14:35 +03:00
|
|
|
#include "xpcprivate.h"
|
2010-10-28 19:15:53 +04:00
|
|
|
|
2011-10-11 09:50:08 +04:00
|
|
|
using namespace mozilla;
|
2013-09-02 08:51:02 +04:00
|
|
|
using namespace JS;
|
2011-09-09 07:29:15 +04:00
|
|
|
using namespace js;
|
|
|
|
|
2010-06-26 02:58:09 +04:00
|
|
|
namespace xpc {
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
nsIPrincipal*
|
2018-06-07 17:44:40 +03:00
|
|
|
GetCompartmentPrincipal(JS::Compartment* compartment)
|
2010-06-26 02:58:09 +04:00
|
|
|
{
|
2012-03-09 13:48:50 +04:00
|
|
|
return nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment));
|
2010-06-26 02:58:09 +04:00
|
|
|
}
|
|
|
|
|
2018-06-02 12:58:29 +03:00
|
|
|
nsIPrincipal*
|
|
|
|
GetRealmPrincipal(JS::Realm* realm)
|
|
|
|
{
|
|
|
|
return nsJSPrincipals::get(JS::GetRealmPrincipals(realm));
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
nsIPrincipal*
|
|
|
|
GetObjectPrincipal(JSObject* obj)
|
2013-05-07 03:53:10 +04:00
|
|
|
{
|
2018-08-10 12:57:40 +03:00
|
|
|
return GetRealmPrincipal(js::GetNonCCWObjectRealm(obj));
|
2013-05-07 03:53:10 +04:00
|
|
|
}
|
|
|
|
|
2012-07-12 12:10:15 +04:00
|
|
|
// Does the principal of compartment a subsume the principal of compartment b?
|
2010-06-26 02:58:09 +04:00
|
|
|
bool
|
2018-06-07 17:44:40 +03:00
|
|
|
AccessCheck::subsumes(JS::Compartment* a, JS::Compartment* b)
|
2010-07-03 00:54:53 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
nsIPrincipal* aprin = GetCompartmentPrincipal(a);
|
|
|
|
nsIPrincipal* bprin = GetCompartmentPrincipal(b);
|
2017-03-07 07:09:49 +03:00
|
|
|
return BasePrincipal::Cast(aprin)->FastSubsumes(bprin);
|
2010-07-03 00:54:53 +04:00
|
|
|
}
|
|
|
|
|
2012-12-08 02:49:11 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
AccessCheck::subsumes(JSObject* a, JSObject* b)
|
2012-12-08 02:49:11 +04:00
|
|
|
{
|
|
|
|
return subsumes(js::GetObjectCompartment(a), js::GetObjectCompartment(b));
|
|
|
|
}
|
|
|
|
|
2014-02-14 06:57:34 +04:00
|
|
|
// Same as above, but considering document.domain.
|
|
|
|
bool
|
2018-06-07 17:44:40 +03:00
|
|
|
AccessCheck::subsumesConsideringDomain(JS::Compartment* a, JS::Compartment* b)
|
2014-02-14 06:57:34 +04:00
|
|
|
{
|
2017-01-18 15:34:31 +03:00
|
|
|
MOZ_ASSERT(OriginAttributes::IsRestrictOpenerAccessForFPI());
|
2015-03-29 01:22:11 +03:00
|
|
|
nsIPrincipal* aprin = GetCompartmentPrincipal(a);
|
|
|
|
nsIPrincipal* bprin = GetCompartmentPrincipal(b);
|
2017-03-07 07:09:49 +03:00
|
|
|
return BasePrincipal::Cast(aprin)->FastSubsumesConsideringDomain(bprin);
|
2012-09-11 21:23:20 +04:00
|
|
|
}
|
|
|
|
|
2017-01-18 15:34:31 +03:00
|
|
|
bool
|
2018-06-07 17:44:40 +03:00
|
|
|
AccessCheck::subsumesConsideringDomainIgnoringFPD(JS::Compartment* a,
|
|
|
|
JS::Compartment* b)
|
2017-01-18 15:34:31 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(!OriginAttributes::IsRestrictOpenerAccessForFPI());
|
|
|
|
nsIPrincipal* aprin = GetCompartmentPrincipal(a);
|
|
|
|
nsIPrincipal* bprin = GetCompartmentPrincipal(b);
|
2017-03-07 07:09:49 +03:00
|
|
|
return BasePrincipal::Cast(aprin)->FastSubsumesConsideringDomainIgnoringFPD(bprin);
|
2017-01-18 15:34:31 +03:00
|
|
|
}
|
|
|
|
|
2012-09-11 12:05:10 +04:00
|
|
|
// Does the compartment of the wrapper subsumes the compartment of the wrappee?
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
AccessCheck::wrapperSubsumes(JSObject* wrapper)
|
2012-09-11 12:05:10 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(js::IsWrapper(wrapper));
|
2015-03-29 01:22:11 +03:00
|
|
|
JSObject* wrapped = js::UncheckedUnwrap(wrapper);
|
2012-09-11 12:05:10 +04:00
|
|
|
return AccessCheck::subsumes(js::GetObjectCompartment(wrapper),
|
|
|
|
js::GetObjectCompartment(wrapped));
|
|
|
|
}
|
|
|
|
|
2010-07-03 00:54:53 +04:00
|
|
|
bool
|
2018-06-07 17:44:40 +03:00
|
|
|
AccessCheck::isChrome(JS::Compartment* compartment)
|
2010-06-26 02:58:09 +04:00
|
|
|
{
|
2018-08-11 14:12:49 +03:00
|
|
|
return js::IsSystemCompartment(compartment);
|
2010-07-03 00:54:53 +04:00
|
|
|
}
|
|
|
|
|
2012-09-11 12:05:10 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
AccessCheck::isChrome(JSObject* obj)
|
2012-09-11 12:05:10 +04:00
|
|
|
{
|
|
|
|
return isChrome(js::GetObjectCompartment(obj));
|
|
|
|
}
|
|
|
|
|
2014-07-15 20:04:19 +04:00
|
|
|
// Hardcoded policy for cross origin property access. See the HTML5 Spec.
|
2010-07-03 00:54:53 +04:00
|
|
|
static bool
|
2015-03-29 01:22:11 +03:00
|
|
|
IsPermitted(CrossOriginObjectType type, JSFlatString* prop, bool set)
|
2010-07-03 00:54:53 +04:00
|
|
|
{
|
2014-07-10 19:36:35 +04:00
|
|
|
size_t propLength = JS_GetStringLength(JS_FORGET_STRING_FLATNESS(prop));
|
2018-09-12 19:16:15 +03:00
|
|
|
if (!propLength) {
|
2010-10-28 19:15:53 +04:00
|
|
|
return false;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-07-10 19:36:35 +04:00
|
|
|
|
2014-07-22 08:43:21 +04:00
|
|
|
char16_t propChar0 = JS_GetFlatStringCharAt(prop, 0);
|
2018-09-12 19:16:15 +03:00
|
|
|
if (type == CrossOriginLocation) {
|
2018-06-26 00:20:54 +03:00
|
|
|
return dom::Location_Binding::IsPermitted(prop, propChar0, set);
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
|
|
|
if (type == CrossOriginWindow) {
|
2018-06-26 00:20:54 +03:00
|
|
|
return dom::Window_Binding::IsPermitted(prop, propChar0, set);
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-07-15 20:04:19 +04:00
|
|
|
|
2010-07-03 00:54:53 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-09-20 21:32:32 +04:00
|
|
|
static bool
|
2015-04-10 00:09:54 +03:00
|
|
|
IsFrameId(JSContext* cx, JSObject* obj, jsid idArg)
|
2013-09-20 21:32:32 +04:00
|
|
|
{
|
2015-04-10 00:09:54 +03:00
|
|
|
MOZ_ASSERT(!js::IsWrapper(obj));
|
2013-09-20 21:32:32 +04:00
|
|
|
RootedId id(cx, idArg);
|
|
|
|
|
2017-11-04 01:25:38 +03:00
|
|
|
nsGlobalWindowInner* win = WindowOrNull(obj);
|
2013-11-05 12:47:59 +04:00
|
|
|
if (!win) {
|
2013-09-20 21:32:32 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-25 06:32:19 +03:00
|
|
|
nsDOMWindowList* col = win->GetFrames();
|
2013-09-20 21:32:32 +04:00
|
|
|
if (!col) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<mozIDOMWindowProxy> domwin;
|
2013-09-20 21:32:32 +04:00
|
|
|
if (JSID_IS_INT(id)) {
|
2018-05-25 06:32:19 +03:00
|
|
|
domwin = col->IndexedGetter(JSID_TO_INT(id));
|
2013-09-20 21:32:32 +04:00
|
|
|
} else if (JSID_IS_STRING(id)) {
|
2014-07-05 19:30:54 +04:00
|
|
|
nsAutoJSString idAsString;
|
|
|
|
if (!idAsString.init(cx, JSID_TO_STRING(id))) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-25 06:32:19 +03:00
|
|
|
domwin = col->NamedItem(idAsString);
|
2013-09-20 21:32:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return domwin != nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-17 18:17:02 +04:00
|
|
|
CrossOriginObjectType
|
2015-03-29 01:22:11 +03:00
|
|
|
IdentifyCrossOriginObject(JSObject* obj)
|
2013-09-20 21:32:32 +04:00
|
|
|
{
|
2015-11-06 21:03:52 +03:00
|
|
|
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
|
2015-03-29 01:22:11 +03:00
|
|
|
const js::Class* clasp = js::GetObjectClass(obj);
|
2014-10-17 18:17:02 +04:00
|
|
|
|
2018-09-12 19:16:15 +03:00
|
|
|
if (clasp->name[0] == 'L' && !strcmp(clasp->name, "Location")) {
|
2014-10-17 18:17:02 +04:00
|
|
|
return CrossOriginLocation;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
|
|
|
if (clasp->name[0] == 'W' && !strcmp(clasp->name, "Window")) {
|
2014-10-17 18:17:02 +04:00
|
|
|
return CrossOriginWindow;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-10-17 18:17:02 +04:00
|
|
|
|
|
|
|
return CrossOriginOpaque;
|
2013-09-20 21:32:32 +04:00
|
|
|
}
|
|
|
|
|
2010-07-03 00:54:53 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
AccessCheck::isCrossOriginAccessPermitted(JSContext* cx, HandleObject wrapper, HandleId id,
|
2011-09-09 07:29:15 +04:00
|
|
|
Wrapper::Action act)
|
2010-07-03 00:54:53 +04:00
|
|
|
{
|
2018-09-12 19:16:15 +03:00
|
|
|
if (act == Wrapper::CALL) {
|
2013-05-23 08:27:16 +04:00
|
|
|
return false;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2010-09-18 01:54:40 +04:00
|
|
|
|
2018-09-12 19:16:15 +03:00
|
|
|
if (act == Wrapper::ENUMERATE) {
|
2014-07-30 23:23:02 +04:00
|
|
|
return true;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-07-30 23:23:02 +04:00
|
|
|
|
2014-07-30 23:23:03 +04:00
|
|
|
// For the case of getting a property descriptor, we allow if either GET or SET
|
|
|
|
// is allowed, and rely on FilteringWrapper to filter out any disallowed accessors.
|
|
|
|
if (act == Wrapper::GET_PROPERTY_DESCRIPTOR) {
|
2014-07-30 23:23:04 +04:00
|
|
|
return isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::GET) ||
|
|
|
|
isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::SET);
|
2014-07-30 23:23:03 +04:00
|
|
|
}
|
|
|
|
|
2015-11-06 21:03:52 +03:00
|
|
|
RootedObject obj(cx, js::UncheckedUnwrap(wrapper, /* stopAtWindowProxy = */ false));
|
2014-10-17 18:17:02 +04:00
|
|
|
CrossOriginObjectType type = IdentifyCrossOriginObject(obj);
|
2012-01-15 12:13:07 +04:00
|
|
|
if (JSID_IS_STRING(id)) {
|
2018-09-12 19:16:15 +03:00
|
|
|
if (IsPermitted(type, JSID_TO_FLAT_STRING(id), act == Wrapper::SET)) {
|
2010-07-03 00:54:53 +04:00
|
|
|
return true;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2018-02-10 09:21:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (type != CrossOriginOpaque &&
|
|
|
|
IsCrossOriginWhitelistedProp(cx, id)) {
|
|
|
|
// We always allow access to "then", @@toStringTag, @@hasInstance, and
|
2016-12-02 23:24:20 +03:00
|
|
|
// @@isConcatSpreadable. But then we nerf them to be a value descriptor
|
|
|
|
// with value undefined in CrossOriginXrayWrapper.
|
|
|
|
return true;
|
2010-07-03 00:54:53 +04:00
|
|
|
}
|
|
|
|
|
2018-09-12 19:16:15 +03:00
|
|
|
if (act != Wrapper::GET) {
|
2013-09-20 21:32:32 +04:00
|
|
|
return false;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2013-09-20 21:32:32 +04:00
|
|
|
|
|
|
|
// Check for frame IDs. If we're resolving named frames, make sure to only
|
|
|
|
// resolve ones that don't shadow native properties. See bug 860494.
|
2014-10-17 18:17:02 +04:00
|
|
|
if (type == CrossOriginWindow) {
|
2014-09-15 16:13:02 +04:00
|
|
|
if (JSID_IS_STRING(id)) {
|
2013-09-20 21:32:32 +04:00
|
|
|
bool wouldShadow = false;
|
|
|
|
if (!XrayUtils::HasNativeProperty(cx, wrapper, id, &wouldShadow) ||
|
|
|
|
wouldShadow)
|
|
|
|
{
|
2014-07-30 23:23:03 +04:00
|
|
|
// If the named subframe matches the name of a DOM constructor,
|
|
|
|
// the global resolve triggered by the HasNativeProperty call
|
|
|
|
// above will try to perform a CheckedUnwrap on |wrapper|, and
|
|
|
|
// throw a security error if it fails. That exception isn't
|
|
|
|
// really useful for our callers, so we silence it and just
|
|
|
|
// deny access to the property (since it matched a builtin).
|
|
|
|
//
|
|
|
|
// Note that this would be a problem if the resolve code ever
|
|
|
|
// tried to CheckedUnwrap the wrapper _before_ concluding that
|
|
|
|
// the name corresponds to a builtin global property, since it
|
|
|
|
// would mean that we'd never permit cross-origin named subframe
|
|
|
|
// access (something we regrettably need to support).
|
|
|
|
JS_ClearPendingException(cx);
|
2013-09-20 21:32:32 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return IsFrameId(cx, obj, id);
|
|
|
|
}
|
2013-04-23 20:50:17 +04:00
|
|
|
return false;
|
2010-07-03 00:54:53 +04:00
|
|
|
}
|
|
|
|
|
2014-10-20 17:52:52 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
AccessCheck::checkPassToPrivilegedCode(JSContext* cx, HandleObject wrapper, HandleValue v)
|
2014-10-20 17:52:52 +04:00
|
|
|
{
|
|
|
|
// Primitives are fine.
|
2018-09-12 19:16:15 +03:00
|
|
|
if (!v.isObject()) {
|
2014-10-20 17:52:52 +04:00
|
|
|
return true;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-10-20 17:52:52 +04:00
|
|
|
RootedObject obj(cx, &v.toObject());
|
|
|
|
|
|
|
|
// Non-wrappers are fine.
|
2018-09-12 19:16:15 +03:00
|
|
|
if (!js::IsWrapper(obj)) {
|
2014-10-20 17:52:52 +04:00
|
|
|
return true;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-10-20 17:52:52 +04:00
|
|
|
|
|
|
|
// CPOWs use COWs (in the unprivileged junk scope) for all child->parent
|
|
|
|
// references. Without this test, the child process wouldn't be able to
|
|
|
|
// pass any objects at all to CPOWs.
|
|
|
|
if (mozilla::jsipc::IsWrappedCPOW(obj) &&
|
|
|
|
js::GetObjectCompartment(wrapper) == js::GetObjectCompartment(xpc::UnprivilegedJunkScope()) &&
|
2015-07-04 04:29:00 +03:00
|
|
|
XRE_IsParentProcess())
|
2014-10-20 17:52:52 +04:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Same-origin wrappers are fine.
|
2018-09-12 19:16:15 +03:00
|
|
|
if (AccessCheck::wrapperSubsumes(obj)) {
|
2014-10-20 17:52:52 +04:00
|
|
|
return true;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-10-20 17:52:52 +04:00
|
|
|
|
|
|
|
// Badness.
|
2016-08-14 14:39:28 +03:00
|
|
|
JS_ReportErrorASCII(cx, "Permission denied to pass object to privileged code");
|
2014-10-20 17:52:52 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
AccessCheck::checkPassToPrivilegedCode(JSContext* cx, HandleObject wrapper, const CallArgs& args)
|
2014-10-20 17:52:52 +04:00
|
|
|
{
|
2018-09-12 19:16:15 +03:00
|
|
|
if (!checkPassToPrivilegedCode(cx, wrapper, args.thisv())) {
|
2014-10-20 17:52:52 +04:00
|
|
|
return false;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-10-20 17:52:52 +04:00
|
|
|
for (size_t i = 0; i < args.length(); ++i) {
|
2018-09-12 19:16:15 +03:00
|
|
|
if (!checkPassToPrivilegedCode(cx, wrapper, args[i])) {
|
2014-10-20 17:52:52 +04:00
|
|
|
return false;
|
2018-09-12 19:16:15 +03:00
|
|
|
}
|
2014-10-20 17:52:52 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-02-02 20:48:49 +03:00
|
|
|
void
|
|
|
|
AccessCheck::reportCrossOriginDenial(JSContext* cx, JS::HandleId id,
|
|
|
|
const nsACString& accessType)
|
|
|
|
{
|
|
|
|
// This function exists because we want to report DOM SecurityErrors, not JS
|
|
|
|
// Errors, when denying access on cross-origin DOM objects. It's
|
|
|
|
// conceptually pretty similar to
|
|
|
|
// AutoEnterPolicy::reportErrorIfExceptionIsNotPending.
|
|
|
|
if (JS_IsExceptionPending(cx)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoCString message;
|
|
|
|
if (JSID_IS_VOID(id)) {
|
|
|
|
message = NS_LITERAL_CSTRING("Permission denied to access object");
|
|
|
|
} else {
|
|
|
|
// We want to use JS_ValueToSource here, because that most closely
|
|
|
|
// matches what AutoEnterPolicy::reportErrorIfExceptionIsNotPending
|
|
|
|
// does.
|
|
|
|
JS::RootedValue idVal(cx, js::IdToValue(id));
|
|
|
|
nsAutoJSString propName;
|
|
|
|
JS::RootedString idStr(cx, JS_ValueToSource(cx, idVal));
|
|
|
|
if (!idStr || !propName.init(cx, idStr)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
message = NS_LITERAL_CSTRING("Permission denied to ") +
|
|
|
|
accessType +
|
|
|
|
NS_LITERAL_CSTRING(" property ") +
|
|
|
|
NS_ConvertUTF16toUTF8(propName) +
|
|
|
|
NS_LITERAL_CSTRING(" on cross-origin object");
|
|
|
|
}
|
|
|
|
ErrorResult rv;
|
|
|
|
rv.ThrowDOMException(NS_ERROR_DOM_SECURITY_ERR, message);
|
2017-02-15 03:17:02 +03:00
|
|
|
MOZ_ALWAYS_TRUE(rv.MaybeSetPendingException(cx));
|
2017-02-02 20:48:49 +03:00
|
|
|
}
|
|
|
|
|
2014-10-03 12:05:51 +04:00
|
|
|
bool
|
2017-09-07 21:17:16 +03:00
|
|
|
OpaqueWithSilentFailing::deny(JSContext* cx, js::Wrapper::Action act, HandleId id,
|
|
|
|
bool mayThrow)
|
2014-10-03 12:05:51 +04:00
|
|
|
{
|
|
|
|
// Fail silently for GET, ENUMERATE, and GET_PROPERTY_DESCRIPTOR.
|
|
|
|
if (act == js::Wrapper::GET || act == js::Wrapper::ENUMERATE ||
|
|
|
|
act == js::Wrapper::GET_PROPERTY_DESCRIPTOR)
|
|
|
|
{
|
2017-02-02 20:48:49 +03:00
|
|
|
// Note that ReportWrapperDenial doesn't do any _exception_ reporting,
|
|
|
|
// so we want to do this regardless of the value of mayThrow.
|
2014-10-03 12:05:51 +04:00
|
|
|
return ReportWrapperDenial(cx, id, WrapperDenialForCOW,
|
|
|
|
"Access to privileged JS object not permitted");
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace xpc
|