Bug 1340719 - Throw an exception if accessing Xray from wrong docgroup (r=bholley)

MozReview-Commit-ID: BBrRsk3KvGb
This commit is contained in:
Bill McCloskey 2017-02-16 12:48:57 -08:00
Родитель ea4ae58e28
Коммит fcdb251c4b
16 изменённых файлов: 556 добавлений и 2 удалений

Просмотреть файл

@ -93,6 +93,12 @@ public:
mTabGroup->ValidateAccess();
}
// Like ValidateAccess, but it returns a bool rather than asserting.
bool AccessAllowed() const
{
return mTabGroup->AccessAllowed();
}
// Return a pointer that can be continually checked to see if access to this
// DocGroup is valid. This pointer should live at least as long as the
// DocGroup.

Просмотреть файл

@ -1717,6 +1717,7 @@ nsMessageManagerScriptExecutor::InitChildGlobalInternal(
// Set the location information for the new global, so that tools like
// about:memory may use that information.
xpc::SetLocationForGlobal(global, aID);
xpc::SetDocGroupValidation(global);
DidCreateGlobal();
return true;

Просмотреть файл

@ -9,6 +9,7 @@ support-files =
file_bug1303838.html
file_bug1303838_target.html
file_bug1303838_with_iframe.html
file_docgroup_forbid.html
file_messagemanager_unload.html
file_pluginAudio.html
file_use_counter_outer.html
@ -26,6 +27,8 @@ support-files =
tags = mcb
[browser_bug1011748.js]
[browser_bug1058164.js]
[browser_docgroup_forbid.js]
skip-if = !e10s
[browser_messagemanager_loadprocessscript.js]
[browser_messagemanager_targetframeloader.js]
[browser_messagemanager_unload.js]

Просмотреть файл

@ -0,0 +1,74 @@
const url = "https://example.com/browser/dom/base/test/file_docgroup_forbid.html";
function frameScript() {
let e = Services.ww.getWindowEnumerator();
let exception = false;
while (e.hasMoreElements()) {
try {
/*
* If this is a window we're not supposed to touch, we'll get an
* error very early here (during the QI).
*/
var window = e.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
var doc = window.document;
} catch (e) {
if (/accessing object in wrong DocGroup/.test(e.toString())) {
exception = true;
break;
}
throw e;
}
/*
* Do some stuff that will trigger the DocGroup assertions if we
* didn't throw.
*/
let elt = doc.createElement("div");
elt.innerHTML = "hello!";
doc.body.appendChild(elt);
let evt = new window.CustomEvent("foopy");
doc.dispatchEvent(evt);
}
sendAsyncMessage("DocGroupTest:Done", exception);
}
function promiseMessage(messageManager, message) {
return new Promise(resolve => {
let listener = (msg) => {
messageManager.removeMessageListener(message, listener);
resolve(msg);
};
messageManager.addMessageListener(message, listener);
})
}
add_task(function*() {
// This pref is normally disabled during tests, but we want to test
// it here, so we enable it.
yield new Promise(go => {
SpecialPowers.pushPrefEnv({set: [["extensions.throw_on_docgroup_mismatch.enabled", true]]}, go)
});
let url1 = url + "?tab=1";
let url2 = url + "?tab=2";
let browser1 = gBrowser.selectedBrowser;
let tab2 = gBrowser.addTab(url2, {sameProcessAsFrameLoader: browser1.frameLoader});
let browser2 = tab2.linkedBrowser;
yield BrowserTestUtils.browserLoaded(browser2, false, url2);
browser1.loadURI(url1);
yield BrowserTestUtils.browserLoaded(browser1, false, url1);
browser1.messageManager.loadFrameScript(`data:,(${frameScript})();`, false);
let exception = yield promiseMessage(browser1.messageManager, "DocGroupTest:Done");
ok(exception, "Touching two windows threw an exception (that's good!)");
gBrowser.removeTab(tab2);
});

Просмотреть файл

@ -0,0 +1,7 @@
<html>
<body>
<script>
document.addEventListener("foopy", function() { dump("ran event handler\n"); });
</script>
</body>
</html>

Просмотреть файл

@ -97,6 +97,7 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext* cx,
mNext(nullptr),
mGlobalJSObject(aGlobal),
mHasCallInterpositions(false),
mDocGroupValidation(false),
mIsContentXBLScope(false),
mIsAddonScope(false)
{
@ -167,6 +168,9 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext* cx,
if (addonId) {
// We forbid CPOWs unless they're specifically allowed.
priv->allowCPOWs = gAllowCPOWAddonSet ? gAllowCPOWAddonSet->has(addonId) : false;
// Automatically opt into DocGroup validation for add-on compartments.
mDocGroupValidation = true;
}
}

Просмотреть файл

@ -1373,6 +1373,12 @@ AllowCPOWsInAddon(const nsACString& addonIdStr, bool allow)
return XPCWrappedNativeScope::AllowCPOWsInAddon(jsapi.cx(), addonId, allow);
}
void
SetDocGroupValidation(JSObject* global)
{
CompartmentPrivate::Get(global)->scope->SetDocGroupValidation();
}
} // namespace xpc
namespace mozilla {

Просмотреть файл

@ -866,6 +866,9 @@ public:
bool AttachComponentsObject(JSContext* aCx);
void SetDocGroupValidation() { mDocGroupValidation = true; }
bool HasDocGroupValidation() const { return mDocGroupValidation; }
// Returns the JS object reflection of the Components object.
bool
GetComponentsJSObject(JS::MutableHandleObject obj);
@ -1067,6 +1070,12 @@ private:
// from this scope if the caller scope has mInterposition set.
bool mHasCallInterpositions;
// If this flag is set, Xray wrappers from this compartment to content
// compartments will be DocGroupValidationWrappers of some
// sort. Consequently, this compartment will throw instead of asserting for
// DocGroup mismatches.
bool mDocGroupValidation;
nsAutoPtr<DOMExpandoSet> mDOMExpandoSet;
JS::WeakMapPtr<JSObject*, JSObject*> mXrayExpandos;

Просмотреть файл

@ -415,6 +415,8 @@ void NukeAllWrappersForCompartment(JSContext* cx, JSCompartment* compartment,
void SetLocationForGlobal(JSObject* global, const nsACString& location);
void SetLocationForGlobal(JSObject* global, nsIURI* locationURI);
void SetDocGroupValidation(JSObject* global);
// ReportJSRuntimeExplicitTreeStats will expect this in the |extra| member
// of JS::ZoneStats.
class ZoneStatsExtras {

Просмотреть файл

@ -0,0 +1,274 @@
/* -*- 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
* 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/. */
#include "DocGroupValidationWrapper.h"
#include "AddonWrapper.h"
#include "WaiveXrayWrapper.h"
#include "mozilla/dom/DocGroup.h"
#include "nsGlobalWindow.h"
using namespace xpc;
static bool
AccessAllowed(JSContext* cx, JS::Handle<JSObject*> wrapper)
{
RootedObject unwrapped(cx, UncheckedUnwrap(wrapper));
RefPtr<nsGlobalWindow> window = WindowGlobalOrNull(unwrapped);
if (!window) {
// Access to non-windows is always kosher.
return true;
}
if (window->GetDocGroup()->AccessAllowed())
return true;
static bool sThrowOnMismatch;
static bool sPrefInitialized;
if (!sPrefInitialized) {
sPrefInitialized = true;
Preferences::AddBoolVarCache(&sThrowOnMismatch,
"extensions.throw_on_docgroup_mismatch.enabled");
}
// If DocGroup validation is disabled, don't throw.
if (!sThrowOnMismatch)
return true;
JS_ReportErrorASCII(cx, "accessing object in wrong DocGroup");
return false;
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<PropertyDescriptor> desc) const
{
return AccessAllowed(cx, wrapper) &&
Base::getOwnPropertyDescriptor(cx, wrapper, id, desc);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const
{
return AccessAllowed(cx, wrapper) &&
Base::defineProperty(cx, wrapper, id, desc, result);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const
{
return AccessAllowed(cx, wrapper) &&
Base::ownPropertyKeys(cx, wrapper, props);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::delete_(JSContext* cx, HandleObject wrapper, HandleId id,
ObjectOpResult& result) const
{
return AccessAllowed(cx, wrapper) &&
Base::delete_(cx, wrapper, id, result);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::enumerate(JSContext* cx, HandleObject wrapper, MutableHandleObject objp) const
{
return AccessAllowed(cx, wrapper) &&
Base::enumerate(cx, wrapper, objp);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::getPrototype(JSContext* cx, HandleObject proxy,
MutableHandleObject protop) const
{
return AccessAllowed(cx, proxy) &&
Base::getPrototype(cx, proxy, protop);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
ObjectOpResult& result) const
{
return AccessAllowed(cx, proxy) &&
Base::setPrototype(cx, proxy, proto, result);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
MutableHandleObject protop) const
{
return AccessAllowed(cx, proxy) &&
Base::getPrototypeIfOrdinary(cx, proxy, isOrdinary, protop);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::setImmutablePrototype(JSContext* cx, HandleObject proxy,
bool* succeeded) const
{
return AccessAllowed(cx, proxy) &&
Base::setImmutablePrototype(cx, proxy, succeeded);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::preventExtensions(JSContext* cx, HandleObject wrapper,
ObjectOpResult& result) const
{
return AccessAllowed(cx, wrapper) &&
Base::preventExtensions(cx, wrapper, result);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const
{
return AccessAllowed(cx, wrapper) &&
Base::isExtensible(cx, wrapper, extensible);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::has(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const
{
return AccessAllowed(cx, wrapper) &&
Base::has(cx, wrapper, id, bp);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
HandleId id, MutableHandleValue vp) const
{
return AccessAllowed(cx, wrapper) &&
Base::get(cx, wrapper, receiver, id, vp);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::set(JSContext* cx, HandleObject wrapper, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult& result) const
{
return AccessAllowed(cx, wrapper) &&
Base::set(cx, wrapper, id, v, receiver, result);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
{
return AccessAllowed(cx, wrapper) &&
Base::call(cx, wrapper, args);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
{
return AccessAllowed(cx, wrapper) &&
Base::construct(cx, wrapper, args);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<PropertyDescriptor> desc) const
{
return AccessAllowed(cx, wrapper) &&
Base::getPropertyDescriptor(cx, wrapper, id, desc);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::hasOwn(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const
{
return AccessAllowed(cx, wrapper) &&
Base::hasOwn(cx, wrapper, id, bp);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const
{
return AccessAllowed(cx, wrapper) &&
Base::getOwnEnumerablePropertyKeys(cx, wrapper, props);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::hasInstance(JSContext* cx, HandleObject wrapper, MutableHandleValue v,
bool* bp) const
{
return AccessAllowed(cx, wrapper) &&
Base::hasInstance(cx, wrapper, v, bp);
}
template<typename Base>
const char*
DocGroupValidationWrapper<Base>::className(JSContext* cx, HandleObject proxy) const
{
return AccessAllowed(cx, proxy)
? Base::className(cx, proxy)
: "forbidden";
}
template<typename Base>
JSString*
DocGroupValidationWrapper<Base>::fun_toString(JSContext* cx, HandleObject wrapper,
unsigned indent) const
{
return AccessAllowed(cx, wrapper)
? Base::fun_toString(cx, wrapper, indent)
: nullptr;
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::regexp_toShared(JSContext* cx, HandleObject proxy, MutableHandle<RegExpShared*> g) const
{
return AccessAllowed(cx, proxy) &&
Base::regexp_toShared(cx, proxy, g);
}
template<typename Base>
bool
DocGroupValidationWrapper<Base>::boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const
{
return AccessAllowed(cx, proxy) &&
Base::boxedValue_unbox(cx, proxy, vp);
}
namespace xpc {
template<typename Base>
const DocGroupValidationWrapper<Base> DocGroupValidationWrapper<Base>::singleton(0);
#define DEFINE_SINGLETON(Base) \
template class DocGroupValidationWrapper<Base>
DEFINE_SINGLETON(CrossCompartmentWrapper);
DEFINE_SINGLETON(PermissiveXrayXPCWN);
DEFINE_SINGLETON(PermissiveXrayDOM);
DEFINE_SINGLETON(PermissiveXrayJS);
DEFINE_SINGLETON(AddonWrapper<CrossCompartmentWrapper>);
DEFINE_SINGLETON(AddonWrapper<PermissiveXrayXPCWN>);
DEFINE_SINGLETON(AddonWrapper<PermissiveXrayDOM>);
DEFINE_SINGLETON(WaiveXrayWrapper);
} // namespace xpc

Просмотреть файл

@ -0,0 +1,87 @@
/* -*- 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
* 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/. */
#ifndef xpc_DocGroupValidationWrapper_h
#define xpc_DocGroupValidationWrapper_h
#include "mozilla/Attributes.h"
#include "jswrapper.h"
#include "WaiveXrayWrapper.h"
#include "XrayWrapper.h"
namespace xpc {
template<typename Base>
class DocGroupValidationWrapper : public Base {
public:
explicit constexpr DocGroupValidationWrapper(unsigned flags) : Base(flags) { }
/* Standard internal methods. */
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<PropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const override;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
ObjectOpResult& result) const override;
virtual bool enumerate(JSContext* cx, HandleObject wrapper, MutableHandleObject objp) const override;
virtual bool getPrototype(JSContext* cx, HandleObject proxy,
MutableHandleObject protop) const override;
virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
ObjectOpResult& result) const override;
virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
MutableHandleObject protop) const override;
virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
bool* succeeded) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
ObjectOpResult& result) const override;
virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
virtual bool has(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
virtual bool get(JSContext* cx, HandleObject wrapper, HandleValue receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext* cx, HandleObject wrapper, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult& result) const override;
virtual bool call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
virtual bool construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
/* SpiderMonkey extensions. */
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<PropertyDescriptor> desc) const override;
virtual bool hasOwn(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
virtual bool hasInstance(JSContext* cx, HandleObject wrapper, MutableHandleValue v,
bool* bp) const override;
virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject wrapper,
unsigned indent) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, MutableHandle<RegExpShared*> g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
static const DocGroupValidationWrapper singleton;
};
#define DECLARE_SINGLETON(Base) \
extern template class DocGroupValidationWrapper<Base>
DECLARE_SINGLETON(CrossCompartmentWrapper);
DECLARE_SINGLETON(PermissiveXrayXPCWN);
DECLARE_SINGLETON(PermissiveXrayDOM);
DECLARE_SINGLETON(PermissiveXrayJS);
DECLARE_SINGLETON(AddonWrapper<CrossCompartmentWrapper>);
DECLARE_SINGLETON(AddonWrapper<PermissiveXrayXPCWN>);
DECLARE_SINGLETON(AddonWrapper<PermissiveXrayDOM>);
DECLARE_SINGLETON(WaiveXrayWrapper);
} // namespace xpc
#endif // xpc_DocGroupValidationWrapper_h

Просмотреть файл

@ -7,6 +7,7 @@
#include "WaiveXrayWrapper.h"
#include "FilteringWrapper.h"
#include "AddonWrapper.h"
#include "DocGroupValidationWrapper.h"
#include "XrayWrapper.h"
#include "AccessCheck.h"
#include "XPCWrapper.h"
@ -447,6 +448,66 @@ SelectAddonWrapper(JSContext* cx, HandleObject obj, const Wrapper* wrapper)
return wrapper;
}
static bool
NeedsDocGroupValidationWrapper(JSContext* cx, HandleObject obj,
JSCompartment* origin, JSCompartment* target,
CompartmentPrivate* targetCompartmentPrivate)
{
// We do DocGroup validation in the following circumstances:
// - Only if the target compartment has the DocGroupValidation()
// flag set (which includes any add-on compartments).
// - Only if we're in the content process.
// - Only if the origin compartment is not system principled and is not a sandbox.
// - Only if the target compartment is system principled.
if (!targetCompartmentPrivate->scope->HasDocGroupValidation())
return false;
if (!XRE_IsContentProcess())
return false;
if (!AccessCheck::isChrome(target))
return false;
if (AccessCheck::isChrome(origin) ||
IsSandbox(js::GetGlobalForObjectCrossCompartment(obj)))
{
return false;
}
return true;
}
static const Wrapper*
SelectDocGroupValidationWrapper(JSContext* cx, HandleObject obj, const Wrapper* wrapper)
{
// Validation wrappers only supports certain wrapper types, so we check if
// we would have used one of the supported ones.
if (wrapper == &CrossCompartmentWrapper::singleton)
return &DocGroupValidationWrapper<CrossCompartmentWrapper>::singleton;
else if (wrapper == &PermissiveXrayXPCWN::singleton)
return &DocGroupValidationWrapper<PermissiveXrayXPCWN>::singleton;
else if (wrapper == &PermissiveXrayDOM::singleton)
return &DocGroupValidationWrapper<PermissiveXrayDOM>::singleton;
else if (wrapper == &PermissiveXrayJS::singleton)
return &DocGroupValidationWrapper<PermissiveXrayJS>::singleton;
else if (wrapper == &AddonWrapper<CrossCompartmentWrapper>::singleton)
return &DocGroupValidationWrapper<AddonWrapper<CrossCompartmentWrapper>>::singleton;
else if (wrapper == &AddonWrapper<PermissiveXrayXPCWN>::singleton)
return &DocGroupValidationWrapper<AddonWrapper<PermissiveXrayXPCWN>>::singleton;
else if (wrapper == &AddonWrapper<PermissiveXrayDOM>::singleton)
return &DocGroupValidationWrapper<AddonWrapper<PermissiveXrayDOM>>::singleton;
else if (wrapper == &WaiveXrayWrapper::singleton)
return &DocGroupValidationWrapper<WaiveXrayWrapper>::singleton;
// If NeedsDocGroupValidationWrapper is true, then securityWrapper should be false
// and xrayType should never be NotXray (since the target always subsumes the origin
// and the origin never subsumes the target).
MOZ_ASSERT(wrapper == &WaiveXrayWrapper::singleton ||
wrapper == &(PermissiveXrayOpaque::singleton));
return wrapper;
}
JSObject*
WrapperFactory::Rewrap(JSContext* cx, HandleObject existing, HandleObject obj)
{
@ -556,6 +617,13 @@ WrapperFactory::Rewrap(JSContext* cx, HandleObject existing, HandleObject obj)
// then we try to "upgrade" the wrapper to an interposing one.
if (targetCompartmentPrivate->scope->HasInterposition())
wrapper = SelectAddonWrapper(cx, obj, wrapper);
// Now try another "upgrade" to a DocGroupValidationWrapper.
if (NeedsDocGroupValidationWrapper(cx, obj, origin, target,
targetCompartmentPrivate))
{
wrapper = SelectDocGroupValidationWrapper(cx, obj, wrapper);
}
}
if (!targetSubsumesOrigin) {

Просмотреть файл

@ -12,6 +12,7 @@ UNIFIED_SOURCES += [
'AccessCheck.cpp',
'AddonWrapper.cpp',
'ChromeObjectWrapper.cpp',
'DocGroupValidationWrapper.cpp',
'FilteringWrapper.cpp',
'WaiveXrayWrapper.cpp',
'WrapperFactory.cpp',

Просмотреть файл

@ -5658,3 +5658,7 @@ pref("layers.advanced.boxshadow-outer-layers", 2);
pref("layers.advanced.caret-layers", 2);
pref("layers.advanced.displaybuttonborder-layers", 2);
pref("layers.advanced.outline-layers", 2);
// Determines whether we throw an exception when a frame script
// accesses the wrong DocGroup. The alternative is to crash.
user_pref("extensions.throw_on_docgroup_mismatch.enabled", true);

Просмотреть файл

@ -370,3 +370,5 @@ user_pref("browser.formautofill.experimental", true);
// The prefs recommended by Marionette are typically geared towards
// consumer automation; not vendor testing.
user_pref("marionette.prefs.recommended", false);
user_pref("extensions.throw_on_docgroup_mismatch.enabled", false);

Просмотреть файл

@ -77,10 +77,16 @@ public:
ValidatingDispatcher* mPrevRunningDispatcher;
};
// Ensure that it's valid to access the TabGroup at this time.
// Return true if it's valid to access the TabGroup at this time.
bool AccessAllowed() const
{
return !sRunningDispatcher || mAccessValid;
}
// Like AccessAllowed(), but asserts.
void ValidateAccess() const
{
MOZ_ASSERT(!sRunningDispatcher || mAccessValid);
MOZ_ASSERT(AccessAllowed());
}
class Runnable;