mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team.
This commit is contained in:
commit
4dbf69049f
@ -35,6 +35,7 @@ pref("prompts.tab_modal.enabled", true);
|
||||
// Enable off main thread compositing
|
||||
pref("layers.offmainthreadcomposition.enabled", true);
|
||||
pref("layers.async-pan-zoom.enabled", false);
|
||||
pref("layers.componentalpha.enabled", false);
|
||||
pref("gfx.axis.fling_friction", "0.002");
|
||||
|
||||
// Enable Microsoft TSF support by default for imes.
|
||||
|
@ -615,6 +615,8 @@ MOCHITEST_FILES_C= \
|
||||
file_mixed_content_frameNavigation_secure.html \
|
||||
file_mixed_content_frameNavigation_secure_grandchild.html \
|
||||
file_mixed_content_frameNavigation_blankTarget.html \
|
||||
file_bug902350.html \
|
||||
file_bug902350_frame.html \
|
||||
test_bug789856.html \
|
||||
file_bug804395.jar \
|
||||
test_bug804395.html \
|
||||
@ -705,6 +707,7 @@ MOCHITEST_FILES_PARTS = $(foreach s,A B C,MOCHITEST_FILES_$(s))
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
browser_bug593387.js \
|
||||
browser_bug902350.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
65
content/base/test/browser_bug902350.js
Normal file
65
content/base/test/browser_bug902350.js
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Mixed Content Block frame navigates for target="_top" - Test for Bug 902350
|
||||
*/
|
||||
|
||||
|
||||
const PREF_ACTIVE = "security.mixed_content.block_active_content";
|
||||
const gHttpTestRoot = "https://example.com/tests/content/base/test/";
|
||||
var origBlockActive;
|
||||
var gTestBrowser = null;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
// Set preferences back to their original values
|
||||
Services.prefs.setBoolPref(PREF_ACTIVE, origBlockActive);
|
||||
});
|
||||
|
||||
function MixedTestsCompleted() {
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
origBlockActive = Services.prefs.getBoolPref(PREF_ACTIVE);
|
||||
|
||||
Services.prefs.setBoolPref(PREF_ACTIVE, true);
|
||||
|
||||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
newTab.linkedBrowser.stop()
|
||||
|
||||
gTestBrowser.addEventListener("load", MixedTest1A, true);
|
||||
var url = gHttpTestRoot + "file_bug902350.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
// Need to capture 2 loads, one for the main page and one for the iframe
|
||||
function MixedTest1A() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest1A, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest1B, true);
|
||||
}
|
||||
|
||||
// Find the iframe and click the link in it
|
||||
function MixedTest1B() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest1B, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest1C, true);
|
||||
var frame = content.document.getElementById("testing_frame");
|
||||
var topTarget = frame.contentWindow.document.getElementById("topTarget");
|
||||
topTarget.click();
|
||||
|
||||
// The link click should have caused a load and should not invoke the Mixed Content Blocker
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(!notification, "Mixed Content Doorhanger appears when trying to navigate top");
|
||||
|
||||
}
|
||||
|
||||
function MixedTest1C() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest1C, true);
|
||||
ok(gTestBrowser.contentWindow.location == "http://example.com/", "Navigating to insecure domain through target='_top' failed.")
|
||||
MixedTestsCompleted();
|
||||
}
|
||||
|
||||
|
19
content/base/test/file_bug902350.html
Normal file
19
content/base/test/file_bug902350.html
Normal file
@ -0,0 +1,19 @@
|
||||
<DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test for Mixed Content Blocker target="_top" frame navigation
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=902350
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 902350</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="framediv">
|
||||
<iframe src="https://example.com/tests/content/base/test/file_bug902350_frame.html" id="testing_frame"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
14
content/base/test/file_bug902350_frame.html
Normal file
14
content/base/test/file_bug902350_frame.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Tests for Mixed Content Blocker - Opening link with _top target from an https iframe.
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=902350
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for Mixed Content Frame Navigation</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="http://example.com/" id="topTarget" target="_top">Go to http site</a>
|
||||
</body>
|
||||
</html>
|
@ -8635,6 +8635,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
uint32_t contentType;
|
||||
bool isNewDocShell = false;
|
||||
bool isTargetTopLevelDocShell = false;
|
||||
nsCOMPtr<nsIDocShell> targetDocShell;
|
||||
if (aWindowTarget && *aWindowTarget) {
|
||||
// Locate the target DocShell.
|
||||
@ -8646,8 +8647,23 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
// If the targetDocShell doesn't exist, then this is a new docShell
|
||||
// and we should consider this a TYPE_DOCUMENT load
|
||||
isNewDocShell = !targetDocShell;
|
||||
|
||||
// If the targetDocShell and the rootDocShell are the same, then the
|
||||
// targetDocShell is the top level document and hence we should
|
||||
// consider this TYPE_DOCUMENT
|
||||
if (targetDocShell) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
targetDocShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from targetDocShell!");
|
||||
nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(sameTypeRoot);
|
||||
NS_ASSERTION(rootShell, "No root docshell from document shell root tree item.");
|
||||
|
||||
if (targetDocShell == rootShell) {
|
||||
isTargetTopLevelDocShell = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (IsFrame() && !isNewDocShell) {
|
||||
if (IsFrame() && !isNewDocShell && !isTargetTopLevelDocShell) {
|
||||
NS_ASSERTION(requestingElement, "A frame but no DOM element!?");
|
||||
contentType = nsIContentPolicy::TYPE_SUBDOCUMENT;
|
||||
} else {
|
||||
|
@ -189,6 +189,27 @@ nsJSUtils::CompileFunction(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS AutoDontReportUncaught {
|
||||
JSContext* mContext;
|
||||
bool mWasSet;
|
||||
|
||||
public:
|
||||
AutoDontReportUncaught(JSContext* aContext) : mContext(aContext) {
|
||||
MOZ_ASSERT(aContext);
|
||||
uint32_t oldOptions = JS_GetOptions(mContext);
|
||||
mWasSet = oldOptions & JSOPTION_DONT_REPORT_UNCAUGHT;
|
||||
if (!mWasSet) {
|
||||
JS_SetOptions(mContext, oldOptions | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
}
|
||||
}
|
||||
~AutoDontReportUncaught() {
|
||||
if (!mWasSet) {
|
||||
JS_SetOptions(mContext,
|
||||
JS_GetOptions(mContext) & ~JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
const nsAString& aScript,
|
||||
@ -224,6 +245,13 @@ nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(ok, NS_OK);
|
||||
|
||||
mozilla::Maybe<AutoDontReportUncaught> dontReport;
|
||||
if (!aEvaluateOptions.reportUncaught) {
|
||||
// We need to prevent AutoLastFrameCheck from reporting and clearing
|
||||
// any pending exceptions.
|
||||
dontReport.construct(aCx);
|
||||
}
|
||||
|
||||
// Scope the JSAutoCompartment so that we can later wrap the return value
|
||||
// into the caller's cx.
|
||||
{
|
||||
|
@ -184,6 +184,7 @@ AppendToString(nsACString& s, const Filter filter,
|
||||
s += pfx;
|
||||
|
||||
switch (filter) {
|
||||
case FILTER_GOOD: s += "FILTER_GOOD"; break;
|
||||
case FILTER_LINEAR: s += "FILTER_LINEAR"; break;
|
||||
case FILTER_POINT: s += "FILTER_POINT"; break;
|
||||
}
|
||||
|
@ -320,7 +320,11 @@ DeprecatedTextureClientShmem::EnsureAllocated(gfx::IntSize aSize,
|
||||
NS_WARNING("creating SurfaceDescriptor failed!");
|
||||
}
|
||||
if (mContentType == gfxASurface::CONTENT_COLOR_ALPHA) {
|
||||
nsRefPtr<gfxContext> context = new gfxContext(GetSurface());
|
||||
gfxASurface* surface = GetSurface();
|
||||
if (!surface) {
|
||||
return false;
|
||||
}
|
||||
nsRefPtr<gfxContext> context = new gfxContext(surface);
|
||||
context->SetColor(gfxRGBA(0, 0, 0, 0));
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
@ -332,16 +336,17 @@ DeprecatedTextureClientShmem::EnsureAllocated(gfx::IntSize aSize,
|
||||
void
|
||||
DeprecatedTextureClientShmem::SetDescriptor(const SurfaceDescriptor& aDescriptor)
|
||||
{
|
||||
if (IsSurfaceDescriptorValid(aDescriptor)) {
|
||||
ReleaseResources();
|
||||
mDescriptor = aDescriptor;
|
||||
} else {
|
||||
if (aDescriptor.type() == SurfaceDescriptor::Tnull_t) {
|
||||
EnsureAllocated(mSize, mContentType);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mSurface);
|
||||
ReleaseResources();
|
||||
mDescriptor = aDescriptor;
|
||||
|
||||
NS_ASSERTION(mDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorGralloc ||
|
||||
MOZ_ASSERT(!mSurface);
|
||||
NS_ASSERTION(mDescriptor.type() == SurfaceDescriptor::T__None ||
|
||||
mDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorGralloc ||
|
||||
mDescriptor.type() == SurfaceDescriptor::TShmem ||
|
||||
mDescriptor.type() == SurfaceDescriptor::TMemoryImage ||
|
||||
mDescriptor.type() == SurfaceDescriptor::TRGBImage,
|
||||
@ -375,6 +380,10 @@ DeprecatedTextureClientShmem::LockDrawTarget()
|
||||
}
|
||||
|
||||
gfxASurface* surface = GetSurface();
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, mSize);
|
||||
|
||||
return mDrawTarget;
|
||||
@ -394,7 +403,11 @@ gfxImageSurface*
|
||||
DeprecatedTextureClientShmem::LockImageSurface()
|
||||
{
|
||||
if (!mSurfaceAsImage) {
|
||||
mSurfaceAsImage = GetSurface()->GetAsImageSurface();
|
||||
gfxASurface* surface = GetSurface();
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
mSurfaceAsImage = surface->GetAsImageSurface();
|
||||
}
|
||||
|
||||
return mSurfaceAsImage.get();
|
||||
@ -417,13 +430,13 @@ DeprecatedTextureClientShmemYCbCr::ReleaseResources()
|
||||
void
|
||||
DeprecatedTextureClientShmemYCbCr::SetDescriptor(const SurfaceDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TYCbCrImage);
|
||||
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TYCbCrImage ||
|
||||
aDescriptor.type() == SurfaceDescriptor::T__None);
|
||||
|
||||
if (IsSurfaceDescriptorValid(mDescriptor)) {
|
||||
GetForwarder()->DestroySharedSurface(&mDescriptor);
|
||||
}
|
||||
mDescriptor = aDescriptor;
|
||||
MOZ_ASSERT(IsSurfaceDescriptorValid(mDescriptor));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -362,17 +362,18 @@ gfxPlatform::Init()
|
||||
mozilla::gl::GLContext::StaticInit();
|
||||
#endif
|
||||
|
||||
bool useOffMainThreadCompositing = GetPrefLayersOffMainThreadCompositionEnabled() ||
|
||||
Preferences::GetBool("browser.tabs.remote", false);
|
||||
useOffMainThreadCompositing &= GetPlatform()->SupportsOffMainThreadCompositing();
|
||||
bool useOffMainThreadCompositing = OffMainThreadCompositionRequired() ||
|
||||
GetPrefLayersOffMainThreadCompositionEnabled();
|
||||
|
||||
if (useOffMainThreadCompositing && (XRE_GetProcessType() ==
|
||||
GeckoProcessType_Default)) {
|
||||
if (!OffMainThreadCompositionRequired()) {
|
||||
useOffMainThreadCompositing &= GetPlatform()->SupportsOffMainThreadCompositing();
|
||||
}
|
||||
|
||||
if (useOffMainThreadCompositing && (XRE_GetProcessType() == GeckoProcessType_Default)) {
|
||||
CompositorParent::StartUp();
|
||||
if (Preferences::GetBool("layers.async-video.enabled",false)) {
|
||||
if (Preferences::GetBool("layers.async-video.enabled", false)) {
|
||||
ImageBridgeChild::StartUp();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
@ -1886,6 +1887,7 @@ static bool sLayersSupportsD3D9 = true;
|
||||
static int sPrefLayoutFrameRate = -1;
|
||||
static bool sBufferRotationEnabled = false;
|
||||
static bool sComponentAlphaEnabled = true;
|
||||
static bool sPrefBrowserTabsRemote = false;
|
||||
|
||||
static bool sLayersAccelerationPrefsInitialized = false;
|
||||
|
||||
@ -1904,6 +1906,7 @@ InitLayersAccelerationPrefs()
|
||||
sPrefLayoutFrameRate = Preferences::GetInt("layout.frame_rate", -1);
|
||||
sBufferRotationEnabled = Preferences::GetBool("layers.bufferrotation.enabled", true);
|
||||
sComponentAlphaEnabled = Preferences::GetBool("layers.componentalpha.enabled", true);
|
||||
sPrefBrowserTabsRemote = Preferences::GetBool("browser.tabs.remote", false);
|
||||
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
||||
if (gfxInfo) {
|
||||
@ -1942,6 +1945,12 @@ gfxPlatform::GetPrefLayersAccelerationForceEnabled()
|
||||
return sPrefLayersAccelerationForceEnabled;
|
||||
}
|
||||
|
||||
bool gfxPlatform::OffMainThreadCompositionRequired()
|
||||
{
|
||||
InitLayersAccelerationPrefs();
|
||||
return sPrefBrowserTabsRemote;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::GetPrefLayersAccelerationDisabled()
|
||||
{
|
||||
|
@ -487,6 +487,8 @@ public:
|
||||
static bool CanUseDirect3D9();
|
||||
static int GetPrefLayoutFrameRate();
|
||||
|
||||
static bool OffMainThreadCompositionRequired();
|
||||
|
||||
/**
|
||||
* Is it possible to use buffer rotation
|
||||
*/
|
||||
|
@ -502,7 +502,8 @@ gfxPlatformGtk::GetScreenDepth() const
|
||||
bool
|
||||
gfxPlatformGtk::SupportsOffMainThreadCompositing()
|
||||
{
|
||||
#ifdef MOZ_X11
|
||||
// Nightly builds have OMTC support by default for Electrolysis testing.
|
||||
#if defined(MOZ_X11) && !defined(NIGHTLY_BUILD)
|
||||
return (PR_GetEnv("MOZ_USE_OMTC") != nullptr) ||
|
||||
(PR_GetEnv("MOZ_OMTC_ENABLED") != nullptr);
|
||||
#else
|
||||
|
@ -228,9 +228,12 @@ InterpreterStack::purge(JSRuntime *rt)
|
||||
uint8_t *
|
||||
InterpreterStack::allocateFrame(JSContext *cx, size_t size)
|
||||
{
|
||||
size_t maxFrames = cx->compartment()->principals == cx->runtime()->trustedPrincipals()
|
||||
? MAX_FRAMES_TRUSTED
|
||||
: MAX_FRAMES;
|
||||
size_t maxFrames;
|
||||
if (cx->compartment()->principals == cx->runtime()->trustedPrincipals())
|
||||
maxFrames = MAX_FRAMES_TRUSTED;
|
||||
else
|
||||
maxFrames = MAX_FRAMES;
|
||||
|
||||
if (JS_UNLIKELY(frameCount_ >= maxFrames)) {
|
||||
js_ReportOverRecursed(cx);
|
||||
return NULL;
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/XPTInterfaceInfoManager.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace js;
|
||||
@ -2935,6 +2937,353 @@ CreateXMLHttpRequest(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NewFunctionForwarder(JSContext *cx, HandleId id, HandleObject callable,
|
||||
bool doclone, MutableHandleValue vp);
|
||||
|
||||
/*
|
||||
* Instead of simply wrapping a function into another compartment,
|
||||
* this helper function creates a native function in the target
|
||||
* compartment and forwards the call to the original function.
|
||||
* That call will be different than a regular JS function call in
|
||||
* that, the |this| is left unbound, and all the non-native JS
|
||||
* object arguments will be cloned using the structured clone
|
||||
* algorithm.
|
||||
* The return value is the new forwarder function, wrapped into
|
||||
* the caller's compartment.
|
||||
* The 3rd argument is the name of the property that will
|
||||
* be set on the target scope, with the forwarder function as
|
||||
* the value.
|
||||
* The principal of the caller must subsume that of the target.
|
||||
*
|
||||
* Expected type of the arguments and the return value:
|
||||
* function exportFunction(function funToExport,
|
||||
* object targetScope,
|
||||
* string name)
|
||||
*/
|
||||
static bool
|
||||
ExportFunction(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
if (argc < 3) {
|
||||
JS_ReportError(cx, "Function requires at least 3 arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!args[0].isObject() || !args[1].isObject() || !args[2].isString()) {
|
||||
JS_ReportError(cx, "Invalid argument");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject funObj(cx, &args[0].toObject());
|
||||
RootedObject targetScope(cx, &args[1].toObject());
|
||||
RootedString funName(cx, args[2].toString());
|
||||
|
||||
// We can only export functions to scopes those are transparent for us,
|
||||
// so if there is a security wrapper around targetScope we must throw.
|
||||
targetScope = CheckedUnwrap(targetScope);
|
||||
if (!targetScope) {
|
||||
JS_ReportError(cx, "Permission denied to export function into scope");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JS_GetStringLength(funName) == 0) {
|
||||
JS_ReportError(cx, "3rd argument should be a non-empty string");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// We need to operate in the target scope from here on, let's enter
|
||||
// its compartment.
|
||||
JSAutoCompartment ac(cx, targetScope);
|
||||
|
||||
// Unwrapping to see if we have a callable.
|
||||
funObj = UncheckedUnwrap(funObj);
|
||||
if (!JS_ObjectIsCallable(cx, funObj)) {
|
||||
JS_ReportError(cx, "First argument must be a function");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The function forwarder will live in the target compartment. Since
|
||||
// this function will be referenced from its private slot, to avoid a
|
||||
// GC hazard, we must wrap it to the same compartment.
|
||||
if (!JS_WrapObject(cx, funObj.address()))
|
||||
return false;
|
||||
|
||||
RootedId id(cx);
|
||||
if (!JS_ValueToId(cx, args[2], id.address()))
|
||||
return false;
|
||||
|
||||
// And now, let's create the forwarder function in the target compartment
|
||||
// for the function the be exported.
|
||||
if (!NewFunctionForwarder(cx, id, funObj, /* doclone = */ true, args.rval())) {
|
||||
JS_ReportError(cx, "Exporting function failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have the forwarder function in the target compartment, now
|
||||
// we have to add it to the target scope as a property.
|
||||
if (!JS_DefinePropertyById(cx, targetScope, id, args.rval(),
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finally we have to re-wrap the exported function back to the caller compartment.
|
||||
if (!JS_WrapValue(cx, args.rval().address()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetFilenameAndLineNumber(JSContext *cx, nsACString &filename, unsigned &lineno)
|
||||
{
|
||||
JSScript *script;
|
||||
if (JS_DescribeScriptedCaller(cx, &script, &lineno)) {
|
||||
if (const char *cfilename = JS_GetScriptFilename(cx, script)) {
|
||||
filename.Assign(nsDependentCString(cfilename));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace xpc {
|
||||
bool
|
||||
IsReflector(JSObject *obj)
|
||||
{
|
||||
return IS_WN_REFLECTOR(obj) || dom::IsDOMObject(obj);
|
||||
}
|
||||
} /* namespace xpc */
|
||||
|
||||
enum ForwarderCloneTags {
|
||||
SCTAG_BASE = JS_SCTAG_USER_MIN,
|
||||
SCTAG_REFLECTOR
|
||||
};
|
||||
|
||||
static JSObject *
|
||||
CloneNonReflectorsRead(JSContext *cx, JSStructuredCloneReader *reader, uint32_t tag,
|
||||
uint32_t data, void *closure)
|
||||
{
|
||||
MOZ_ASSERT(closure, "Null pointer!");
|
||||
AutoObjectVector *reflectors = static_cast<AutoObjectVector *>(closure);
|
||||
if (tag == SCTAG_REFLECTOR) {
|
||||
MOZ_ASSERT(!data);
|
||||
|
||||
size_t idx;
|
||||
if (JS_ReadBytes(reader, &idx, sizeof(size_t))) {
|
||||
RootedObject reflector(cx, reflectors->handleAt(idx));
|
||||
MOZ_ASSERT(reflector, "No object pointer?");
|
||||
MOZ_ASSERT(IsReflector(reflector), "Object pointer must be a reflector!");
|
||||
|
||||
JS_WrapObject(cx, reflector.address());
|
||||
JS_ASSERT(WrapperFactory::IsXrayWrapper(reflector) ||
|
||||
IsReflector(reflector));
|
||||
|
||||
return reflector;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "CloneNonReflectorsRead error");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
CloneNonReflectorsWrite(JSContext *cx, JSStructuredCloneWriter *writer,
|
||||
Handle<JSObject *> obj, void *closure)
|
||||
{
|
||||
MOZ_ASSERT(closure, "Null pointer!");
|
||||
|
||||
// We need to maintain a list of reflectors to make sure all these objects
|
||||
// are properly rooter. Only their indices will be serialized.
|
||||
AutoObjectVector *reflectors = static_cast<AutoObjectVector *>(closure);
|
||||
if (IsReflector(obj)) {
|
||||
if (!reflectors->append(obj))
|
||||
return false;
|
||||
|
||||
size_t idx = reflectors->length()-1;
|
||||
if (JS_WriteUint32Pair(writer, SCTAG_REFLECTOR, 0) &&
|
||||
JS_WriteBytes(writer, &idx, sizeof(size_t))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "CloneNonReflectorsWrite error");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSStructuredCloneCallbacks gForwarderStructuredCloneCallbacks = {
|
||||
CloneNonReflectorsRead,
|
||||
CloneNonReflectorsWrite,
|
||||
nullptr
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a special structured cloning, that clones only non-reflectors.
|
||||
* The function assumes the cx is already entered the compartment we want
|
||||
* to clone to, and that if val is an object is from the compartment we
|
||||
* clone from.
|
||||
*/
|
||||
bool
|
||||
CloneNonReflectors(JSContext *cx, MutableHandleValue val)
|
||||
{
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
AutoObjectVector rootedReflectors(cx);
|
||||
{
|
||||
// For parsing val we have to enter its compartment.
|
||||
// (unless it's a primitive)
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (val.isObject()) {
|
||||
ac.construct(cx, &val.toObject());
|
||||
}
|
||||
|
||||
if (!buffer.write(cx, val,
|
||||
&gForwarderStructuredCloneCallbacks,
|
||||
&rootedReflectors))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now recreate the clones in the target compartment.
|
||||
RootedValue rval(cx);
|
||||
if (!buffer.read(cx, val.address(),
|
||||
&gForwarderStructuredCloneCallbacks,
|
||||
&rootedReflectors))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to evalInSandbox except this one is used to eval a script in the
|
||||
* scope of a window. Also note, that the return value and the possible exceptions
|
||||
* in the script are structured cloned, unless they are natives (then they are just
|
||||
* wrapped).
|
||||
* Principal of the caller must subsume the target's.
|
||||
*
|
||||
* Expected type of the arguments:
|
||||
* value evalInWindow(string script,
|
||||
* object window)
|
||||
*/
|
||||
static bool
|
||||
EvalInWindow(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
if (argc < 2) {
|
||||
JS_ReportError(cx, "Function requires two arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!args[0].isString() || !args[1].isObject()) {
|
||||
JS_ReportError(cx, "Invalid arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedString srcString(cx, args[0].toString());
|
||||
RootedObject targetScope(cx, &args[1].toObject());
|
||||
|
||||
// If we cannot unwrap we must not eval in it.
|
||||
targetScope = CheckedUnwrap(targetScope);
|
||||
if (!targetScope) {
|
||||
JS_ReportError(cx, "Permission denied to eval in target scope");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that we have a window object.
|
||||
RootedObject inner(cx, CheckedUnwrap(targetScope, /* stopAtOuter = */ false));
|
||||
nsCOMPtr<nsIGlobalObject> global;
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
if (!JS_IsGlobalObject(inner) ||
|
||||
!(global = GetNativeForGlobal(inner)) ||
|
||||
!(window = do_QueryInterface(global)))
|
||||
{
|
||||
JS_ReportError(cx, "Second argument must be a window");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context =
|
||||
(static_cast<nsGlobalWindow*>(window.get()))->GetScriptContext();
|
||||
if (!context) {
|
||||
JS_ReportError(cx, "Script context needed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!context->GetScriptsEnabled()) {
|
||||
JS_ReportError(cx, "Scripts are disabled in this window");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCString filename;
|
||||
unsigned lineNo;
|
||||
if (!GetFilenameAndLineNumber(cx, filename, lineNo)) {
|
||||
// Default values for non-scripted callers.
|
||||
filename.Assign("Unknown");
|
||||
lineNo = 0;
|
||||
}
|
||||
|
||||
nsDependentJSString srcDepString;
|
||||
srcDepString.init(cx, srcString);
|
||||
|
||||
{
|
||||
// CompileOptions must be created from the context
|
||||
// we will execute this script in.
|
||||
JSContext *wndCx = context->GetNativeContext();
|
||||
AutoCxPusher pusher(wndCx);
|
||||
JS::CompileOptions compileOptions(wndCx);
|
||||
compileOptions.setFileAndLine(filename.get(), lineNo);
|
||||
|
||||
// We don't want the JS engine to automatically report
|
||||
// uncaught exceptions.
|
||||
nsJSUtils::EvaluateOptions evaluateOptions;
|
||||
evaluateOptions.setReportUncaught(false);
|
||||
|
||||
nsresult rv = nsJSUtils::EvaluateString(wndCx,
|
||||
srcDepString,
|
||||
targetScope,
|
||||
compileOptions,
|
||||
evaluateOptions,
|
||||
args.rval().address());
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// If there was an exception we get it as a return value, if
|
||||
// the evaluation failed for some other reason, then a default
|
||||
// exception is raised.
|
||||
MOZ_ASSERT(!JS_IsExceptionPending(wndCx),
|
||||
"Exception should be delivered as return value.");
|
||||
if (args.rval().isUndefined()) {
|
||||
MOZ_ASSERT(rv == NS_ERROR_OUT_OF_MEMORY);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there was an exception thrown we should set it
|
||||
// on the calling context.
|
||||
RootedValue exn(wndCx, args.rval());
|
||||
// First we should reset the return value.
|
||||
args.rval().set(UndefinedValue());
|
||||
|
||||
// Then clone the exception.
|
||||
if (CloneNonReflectors(cx, &exn))
|
||||
JS_SetPendingException(cx, exn);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Let's clone the return value back to the callers compartment.
|
||||
if (!CloneNonReflectors(cx, args.rval())) {
|
||||
args.rval().set(UndefinedValue());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
sandbox_enumerate(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
@ -3350,6 +3699,12 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo
|
||||
if (options.wantXHRConstructor &&
|
||||
!JS_DefineFunction(cx, sandbox, "XMLHttpRequest", CreateXMLHttpRequest, 0, JSFUN_CONSTRUCTOR))
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
if (options.wantExportHelpers &&
|
||||
(!JS_DefineFunction(cx, sandbox, "exportFunction", ExportFunction, 3, 0) ||
|
||||
!JS_DefineFunction(cx, sandbox, "evalInWindow", EvalInWindow, 2, 0)))
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
}
|
||||
|
||||
if (vp) {
|
||||
@ -3620,6 +3975,10 @@ ParseOptionsObject(JSContext *cx, jsval from, SandboxOptions &options)
|
||||
"wantXHRConstructor", &options.wantXHRConstructor);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = GetBoolPropFromOptions(cx, optionsObject,
|
||||
"wantExportHelpers", &options.wantExportHelpers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = GetStringPropFromOptions(cx, optionsObject,
|
||||
"sandboxName", options.sandboxName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -4205,7 +4564,7 @@ nsXPCComponents_Utils::CreateDateIn(const Value &vobj, int64_t msec, JSContext *
|
||||
}
|
||||
|
||||
bool
|
||||
FunctionWrapper(JSContext *cx, unsigned argc, Value *vp)
|
||||
NonCloningFunctionForwarder(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
@ -4219,17 +4578,54 @@ FunctionWrapper(JSContext *cx, unsigned argc, Value *vp)
|
||||
return JS_CallFunctionValue(cx, obj, v, args.length(), args.array(), vp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Forwards the call to the exported function. Clones all the non reflectors, ignores
|
||||
* the |this| argument.
|
||||
*/
|
||||
bool
|
||||
WrapCallable(JSContext *cx, HandleObject obj, HandleId id, HandleObject propobj,
|
||||
MutableHandleValue vp)
|
||||
CloningFunctionForwarder(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
JSFunction *fun = js::NewFunctionByIdWithReserved(cx, FunctionWrapper, 0, 0,
|
||||
JS_GetGlobalForObject(cx, obj), id);
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
RootedValue v(cx, js::GetFunctionNativeReserved(&args.callee(), 0));
|
||||
NS_ASSERTION(v.isObject(), "weird function");
|
||||
RootedObject origFunObj(cx, UncheckedUnwrap(&v.toObject()));
|
||||
{
|
||||
JSAutoCompartment ac(cx, origFunObj);
|
||||
// Note: only the arguments are cloned not the |this| or the |callee|.
|
||||
// Function forwarder does not use those.
|
||||
for (unsigned i = 0; i < args.length(); i++) {
|
||||
if (!CloneNonReflectors(cx, args[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// JS API does not support any JSObject to JSFunction conversion,
|
||||
// so let's use JS_CallFunctionValue instead.
|
||||
RootedValue functionVal(cx);
|
||||
functionVal.setObject(*origFunObj);
|
||||
|
||||
if (!JS_CallFunctionValue(cx, nullptr, functionVal, args.length(), args.array(), vp))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return value must be wrapped.
|
||||
return JS_WrapValue(cx, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
NewFunctionForwarder(JSContext *cx, HandleId id, HandleObject callable, bool doclone,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
JSFunction *fun = js::NewFunctionByIdWithReserved(cx, doclone ? CloningFunctionForwarder :
|
||||
NonCloningFunctionForwarder,
|
||||
0,0, JS::CurrentGlobalOrNull(cx), id);
|
||||
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||
js::SetFunctionNativeReserved(funobj, 0, ObjectValue(*propobj));
|
||||
js::SetFunctionNativeReserved(funobj, 0, ObjectValue(*callable));
|
||||
vp.setObject(*funobj);
|
||||
return true;
|
||||
}
|
||||
@ -4267,7 +4663,7 @@ nsXPCComponents_Utils::MakeObjectPropsNormal(const Value &vobj, JSContext *cx)
|
||||
if (!js::IsWrapper(propobj) || !JS_ObjectIsCallable(cx, propobj))
|
||||
continue;
|
||||
|
||||
if (!WrapCallable(cx, obj, id, propobj, &v) ||
|
||||
if (!NewFunctionForwarder(cx, id, propobj, /* doclone = */ false, &v) ||
|
||||
!JS_SetPropertyById(cx, obj, id, v))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -3700,6 +3700,7 @@ struct SandboxOptions {
|
||||
: wantXrays(true)
|
||||
, wantComponents(true)
|
||||
, wantXHRConstructor(false)
|
||||
, wantExportHelpers(false)
|
||||
, proto(xpc_GetSafeJSContext())
|
||||
, sameZoneAs(xpc_GetSafeJSContext())
|
||||
{ }
|
||||
@ -3707,6 +3708,7 @@ struct SandboxOptions {
|
||||
bool wantXrays;
|
||||
bool wantComponents;
|
||||
bool wantXHRConstructor;
|
||||
bool wantExportHelpers;
|
||||
JS::RootedObject proto;
|
||||
nsCString sandboxName;
|
||||
JS::RootedObject sameZoneAs;
|
||||
|
@ -66,6 +66,8 @@ AllowXBLScope(JSCompartment *c);
|
||||
bool
|
||||
IsSandboxPrototypeProxy(JSObject *obj);
|
||||
|
||||
bool
|
||||
IsReflector(JSObject *obj);
|
||||
} /* namespace xpc */
|
||||
|
||||
namespace JS {
|
||||
|
@ -61,6 +61,7 @@ MOCHITEST_CHROME_FILES = \
|
||||
test_doublewrappedcompartments.xul \
|
||||
test_evalInSandbox.xul \
|
||||
file_evalInSandbox.html \
|
||||
test_evalInWindow.xul \
|
||||
test_exnstack.xul \
|
||||
test_expandosharing.xul \
|
||||
file_expandosharing.jsm \
|
||||
|
75
js/xpconnect/tests/chrome/test_evalInWindow.xul
Normal file
75
js/xpconnect/tests/chrome/test_evalInWindow.xul
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=877673
|
||||
-->
|
||||
<window title="Mozilla Bug 877673"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const Cu = Components.utils;
|
||||
var sb = new Cu.Sandbox("http://example.org", {wantExportHelpers: true});
|
||||
sb.ok = ok;
|
||||
|
||||
function executeIn(frame, script, exceptionCb) {
|
||||
sb.frame = frame;
|
||||
sb.exceptionCb = exceptionCb;
|
||||
if (exceptionCb) {
|
||||
return Cu.evalInSandbox("try {evalInWindow('" + script + "',frame); ok(false, 'Exception should have been thrown.')} catch(e) {exceptionCb(e)}", sb);
|
||||
}
|
||||
|
||||
return Cu.evalInSandbox("evalInWindow('" + script + "',frame)", sb);
|
||||
}
|
||||
|
||||
function testSameOrigin(frame) {
|
||||
frame.contentWindow.document.wrappedJSObject.str = "foobar";
|
||||
is(executeIn(frame.contentWindow, "document.str"), "foobar",
|
||||
"Same origin string property access.");
|
||||
|
||||
executeIn(frame.contentWindow, 'document.obj = {prop: "foobar"}');
|
||||
is((executeIn(frame.contentWindow, "document.obj")).prop, "foobar",
|
||||
"Same origin object property access (cloning).");
|
||||
isnot(executeIn(frame.contentWindow, "document.obj"), frame.contentWindow.document.wrappedJSObject.obj,
|
||||
"Ensure cloning for js objects.");
|
||||
is(executeIn(frame.contentWindow, "document"), frame.contentWindow.document,
|
||||
"Xrayables should just pass without cloning.");
|
||||
is( executeIn(frame.contentWindow, "({a:{doc: document}})").a.doc, frame.contentWindow.document,
|
||||
"Deep cloning works.");
|
||||
|
||||
executeIn(frame.contentWindow, "throw 42", function(e){is(e, 42,
|
||||
"Exception was thrown from script.")});
|
||||
|
||||
executeIn(frame.contentDocument, "var a = 42;", function(e){ok(e.toString().indexOf("Second argument must be a window") > -1,
|
||||
"Passing non-window to evalInWindow should throw.");});
|
||||
testDone();
|
||||
}
|
||||
|
||||
function testCrossOrigin(frame) {
|
||||
executeIn(frame.contentWindow, "var a = 42;", function(e){ok(e.toString().indexOf("Permission denied") > -1,
|
||||
"Executing script in a window from cross origin should throw.");});
|
||||
testDone();
|
||||
}
|
||||
|
||||
var testsRun = 0;
|
||||
function testDone() {
|
||||
if (++testsRun == 2)
|
||||
SimpleTest.finish();
|
||||
}
|
||||
]]></script>
|
||||
<iframe src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"
|
||||
onload="testSameOrigin(this)">
|
||||
</iframe>
|
||||
<iframe src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_empty.html"
|
||||
onload="testCrossOrigin(this)">
|
||||
</iframe>
|
||||
</window>
|
73
js/xpconnect/tests/unit/test_exportFunction.js
Normal file
73
js/xpconnect/tests/unit/test_exportFunction.js
Normal file
@ -0,0 +1,73 @@
|
||||
function run_test() {
|
||||
var Cu = Components.utils;
|
||||
var epsb = new Cu.Sandbox(["http://example.com", "http://example.org"], { wantExportHelpers: true });
|
||||
subsb = new Cu.Sandbox("http://example.com", { wantXHRConstructor: true });
|
||||
subsb2 = new Cu.Sandbox("http://example.com", { wantXHRConstructor: true });
|
||||
xorigsb = new Cu.Sandbox("http://test.com");
|
||||
|
||||
epsb.subsb = subsb;
|
||||
epsb.xorigsb = xorigsb;
|
||||
epsb.do_check_true = do_check_true;
|
||||
epsb.do_check_eq = do_check_eq;
|
||||
epsb.do_check_neq = do_check_neq;
|
||||
|
||||
// Exporting should work if prinicipal of the source sandbox
|
||||
// subsumes the principal of the target sandbox.
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
Object.prototype.protoProp = "common";
|
||||
var wasCalled = false;
|
||||
var _this = this;
|
||||
var funToExport = function(a, obj, native, mixed) {
|
||||
do_check_eq(a, 42);
|
||||
do_check_neq(obj, subsb.tobecloned);
|
||||
do_check_eq(obj.cloned, "cloned");
|
||||
do_check_eq(obj.protoProp, "common");
|
||||
do_check_eq(native, subsb.native);
|
||||
do_check_eq(_this, this);
|
||||
do_check_eq(mixed.xrayed, subsb.xrayed);
|
||||
do_check_eq(mixed.xrayed2, subsb.xrayed2);
|
||||
wasCalled = true;
|
||||
};
|
||||
this.checkIfCalled = function() {
|
||||
do_check_true(wasCalled);
|
||||
wasCalled = false;
|
||||
}
|
||||
exportFunction(funToExport, subsb, "imported");
|
||||
}.toSource() + ")()", epsb);
|
||||
|
||||
subsb.xrayed = Cu.evalInSandbox("(" + function () {
|
||||
return new XMLHttpRequest();
|
||||
}.toSource() + ")()", subsb2);
|
||||
|
||||
// Exported function should be able to be call from the
|
||||
// target sandbox. Native arguments should be just wrapped
|
||||
// every other argument should be cloned.
|
||||
Cu.evalInSandbox("(" + function () {
|
||||
native = new XMLHttpRequest();
|
||||
xrayed2 = XPCNativeWrapper(new XMLHttpRequest());
|
||||
mixed = { xrayed: xrayed, xrayed2: xrayed2 };
|
||||
tobecloned = { cloned: "cloned" };
|
||||
imported(42,tobecloned, native, mixed);
|
||||
}.toSource() + ")()", subsb);
|
||||
|
||||
// Apply should work but the |this| argument should not be
|
||||
// possible to be changed.
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
imported.apply("something", [42, tobecloned, native, mixed]);
|
||||
}.toSource() + ")()", subsb);
|
||||
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
checkIfCalled();
|
||||
}.toSource() + ")()", epsb);
|
||||
|
||||
// Exporting should throw if princpal of the source sandbox does
|
||||
// not subsume the principal of the target.
|
||||
Cu.evalInSandbox("(" + function() {
|
||||
try{
|
||||
exportFunction(function(){}, this.xorigsb, "denied");
|
||||
do_check_true(false);
|
||||
} catch (e) {
|
||||
do_check_true(e.toString().indexOf('Permission denied') > -1);
|
||||
}
|
||||
}.toSource() + ")()", epsb);
|
||||
}
|
@ -47,4 +47,5 @@ fail-if = os == "android"
|
||||
[test_allowedDomains.js]
|
||||
[test_allowedDomainsXHR.js]
|
||||
[test_nuke_sandbox.js]
|
||||
[test_exportFunction.js]
|
||||
[test_watchdog.js]
|
||||
|
@ -568,8 +568,9 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
|
||||
|
||||
// if font features are not enabled, pointers for fontVariant
|
||||
// values above may be null since the shorthand check ignores them
|
||||
// font-variant-alternates enabled ==> layout.css.font-features.enabled is true
|
||||
bool fontFeaturesEnabled =
|
||||
mozilla::Preferences::GetBool("layout.css.font-features.enabled");
|
||||
nsCSSProps::IsEnabled(eCSSProperty_font_variant_alternates);
|
||||
|
||||
if (systemFont &&
|
||||
systemFont->GetUnit() != eCSSUnit_None &&
|
||||
|
@ -8515,8 +8515,9 @@ CSSParserImpl::ParseFont()
|
||||
eCSSProperty_font_weight
|
||||
};
|
||||
|
||||
// font-variant-alternates enabled ==> layout.css.font-features.enabled is true
|
||||
bool featuresEnabled =
|
||||
mozilla::Preferences::GetBool("layout.css.font-features.enabled");
|
||||
nsCSSProps::IsEnabled(eCSSProperty_font_variant_alternates);
|
||||
nsCSSValue family;
|
||||
if (ParseVariant(family, VARIANT_HK, nsCSSProps::kFontKTable)) {
|
||||
if (ExpectEndProperty()) {
|
||||
|
@ -412,9 +412,12 @@ nsCSSProps::LookupFontDesc(const nsAString& aFontDesc)
|
||||
NS_ABORT_IF_FALSE(gFontDescTable, "no lookup table, needs addref");
|
||||
nsCSSFontDesc which = nsCSSFontDesc(gFontDescTable->Lookup(aFontDesc));
|
||||
|
||||
// font-variant-alternates enabled ==> layout.css.font-features.enabled is true
|
||||
bool fontFeaturesEnabled =
|
||||
nsCSSProps::IsEnabled(eCSSProperty_font_variant_alternates);
|
||||
|
||||
// check for unprefixed font-feature-settings/font-language-override
|
||||
if (which == eCSSFontDesc_UNKNOWN &&
|
||||
mozilla::Preferences::GetBool("layout.css.font-features.enabled")) {
|
||||
if (which == eCSSFontDesc_UNKNOWN && fontFeaturesEnabled) {
|
||||
nsAutoString prefixedProp;
|
||||
prefixedProp.AppendLiteral("-moz-");
|
||||
prefixedProp.Append(aFontDesc);
|
||||
|
@ -335,7 +335,11 @@ public:
|
||||
|
||||
static bool PrefEnabled()
|
||||
{
|
||||
return mozilla::Preferences::GetBool("layout.css.font-features.enabled");
|
||||
// font-variant-alternates enabled ==> layout.css.font-features.enabled is true
|
||||
bool fontFeaturesEnabled =
|
||||
nsCSSProps::IsEnabled(eCSSProperty_font_variant_alternates);
|
||||
|
||||
return fontFeaturesEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -3370,11 +3370,19 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
|
||||
// (called inside gdk_display_open). This is a requirement for off main tread compositing.
|
||||
// This is done only on X11 platforms if the environment variable MOZ_USE_OMTC is set so
|
||||
// as to avoid overhead when omtc is not used.
|
||||
//
|
||||
// On nightly builds, we call this by default to enable OMTC for Electrolysis testing. On
|
||||
// aurora, beta, and release builds, there is a small tpaint regression from enabling this
|
||||
// call, so it sits behind an environment variable.
|
||||
//
|
||||
// An environment variable is used instead of a pref on X11 platforms because we start having
|
||||
// access to prefs long after the first call to XOpenDisplay which is hard to change due to
|
||||
// interdependencies in the initialization.
|
||||
# ifndef NIGHTLY_BUILD
|
||||
if (PR_GetEnv("MOZ_USE_OMTC") ||
|
||||
PR_GetEnv("MOZ_OMTC_ENABLED")) {
|
||||
PR_GetEnv("MOZ_OMTC_ENABLED"))
|
||||
# endif
|
||||
{
|
||||
XInitThreads();
|
||||
}
|
||||
#endif
|
||||
|
@ -1534,8 +1534,7 @@ nsChildView::ComputeShouldAccelerate(bool aDefault)
|
||||
bool
|
||||
nsChildView::ShouldUseOffMainThreadCompositing()
|
||||
{
|
||||
// Don't use OMTC (which requires OpenGL) for transparent windows or for
|
||||
// popup windows.
|
||||
// Don't use OMTC for transparent windows or for popup windows.
|
||||
if (!mView || ![[mView window] isOpaque] ||
|
||||
[[mView window] isKindOfClass:[PopupWindow class]])
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user