Merge m-c to fx-team. a=merge
Merge m-c to fx-team. a=merge
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1239,16 +1239,19 @@ pref("services.sync.prefs.sync.addons.ig
// The addons prefs related to repository verification are intentionally
// not synced for security reasons. If a system is compromised, a user
// could weaken the pref locally, install an add-on from an untrusted
// source, and this would propagate automatically to other,
// uncompromised Sync-connected devices.
pref("services.sync.prefs.sync.app.update.mode", true);
pref("services.sync.prefs.sync.browser.formfill.enable", true);
pref("services.sync.prefs.sync.browser.link.open_newwindow", true);
+pref("services.sync.prefs.sync.browser.newtabpage.enabled", true);
+pref("services.sync.prefs.sync.browser.newtabpage.enhanced", true);
+pref("services.sync.prefs.sync.browser.newtabpage.pinned", true);
pref("services.sync.prefs.sync.browser.offline-apps.notify", true);
pref("services.sync.prefs.sync.browser.safebrowsing.enabled", true);
pref("services.sync.prefs.sync.browser.safebrowsing.malware.enabled", true);
pref("services.sync.prefs.sync.browser.search.update", true);
pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);
pref("services.sync.prefs.sync.browser.startup.homepage", true);
pref("services.sync.prefs.sync.browser.startup.page", true);
pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true);
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -387,23 +387,23 @@ skip-if = e10s
skip-if = e10s
[browser_dbg_searchbox-help-popup-01.js]
skip-if = e10s
[browser_dbg_searchbox-help-popup-02.js]
skip-if = e10s
[browser_dbg_searchbox-parse.js]
skip-if = e10s
[browser_dbg_source-maps-01.js]
-skip-if = e10s
+skip-if = e10s && debug
[browser_dbg_source-maps-02.js]
-skip-if = e10s
+skip-if = e10s && debug
[browser_dbg_source-maps-03.js]
-skip-if = e10s
+skip-if = e10s && debug
[browser_dbg_source-maps-04.js]
-skip-if = e10s
+skip-if = e10s # Bug 1093535
[browser_dbg_sources-cache.js]
skip-if = e10s
[browser_dbg_sources-labels.js]
skip-if = e10s
[browser_dbg_sources-sorting.js]
skip-if = e10s
[browser_dbg_split-console-paused-reload.js]
skip-if = e10s
--- a/browser/devtools/debugger/test/browser_dbg_source-maps-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_source-maps-01.js
@@ -4,23 +4,22 @@
/**
* Test that we can set breakpoints and step through source mapped
* coffee script.
*/
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
const COFFEE_URL = EXAMPLE_URL + "code_binary_search.coffee";
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
let gEditor, gSources;
function test() {
- initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+ initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
gTab = aTab;
- gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
checkSourceMapsEnabled();
waitForSourceShown(gPanel, ".coffee")
@@ -114,17 +113,17 @@ function testHitBreakpoint() {
is(aPacket.frame.environment.bindings.variables.pivot.value.type, "undefined",
"'pivot' hasn't been assigned to yet.");
waitForCaretUpdated(gPanel, 5).then(deferred.resolve);
});
// This will cause the breakpoint to be hit, and put us back in the
// paused state.
- gDebuggee.binary_search([0, 2, 3, 5, 7, 10], 5);
+ callInTab(gTab, "binary_search", [0, 2, 3, 5, 7, 10], 5);
});
return deferred.promise;
}
function testStepping() {
let deferred = promise.defer();
@@ -152,14 +151,13 @@ function testStepping() {
});
});
return deferred.promise;
}
registerCleanupFunction(function() {
gTab = null;
- gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
});
--- a/browser/devtools/debugger/test/browser_dbg_source-maps-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_source-maps-02.js
@@ -3,22 +3,22 @@
/**
* Test that we can toggle between the original and generated sources.
*/
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
const JS_URL = EXAMPLE_URL + "code_binary_search.js";
-let gDebuggee, gPanel, gDebugger, gEditor;
+let gTab, gPanel, gDebugger, gEditor;
let gSources, gFrames, gPrefs, gOptions;
function test() {
- initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
- gDebuggee = aDebuggee;
+ initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
+ gTab = aTab;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gFrames = gDebugger.DebuggerView.StackFrames;
gPrefs = gDebugger.Prefs;
gOptions = gDebugger.DebuggerView.Options;
@@ -76,17 +76,17 @@ function testSetBreakpoint() {
isnot(gFrames.getItemAtIndex(0).attachment.url.indexOf(".js"), -1,
"First frame should be a JS frame.");
deferred.resolve();
});
// This will cause the breakpoint to be hit, and put us back in the
// paused state.
- gDebuggee.binary_search([0, 2, 3, 5, 7, 10], 5);
+ callInTab(gTab, "binary_search", [0, 2, 3, 5, 7, 10], 5);
});
});
return deferred.promise;
}
function testToggleOnPause() {
let finished = waitForSourceAndCaretAndScopes(gPanel, ".coffee", 5).then(() => {
@@ -130,17 +130,17 @@ function testResume() {
deferred.resolve();
});
return deferred.promise;
}
registerCleanupFunction(function() {
- gDebuggee = null;
+ gTab = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
gFrames = null;
gPrefs = null;
gOptions = null;
});
--- a/browser/devtools/debugger/test/browser_dbg_source-maps-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_source-maps-03.js
@@ -3,22 +3,22 @@
/**
* Test that we can debug minified javascript with source maps.
*/
const TAB_URL = EXAMPLE_URL + "doc_minified.html";
const JS_URL = EXAMPLE_URL + "code_math.js";
-let gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
let gEditor, gSources, gFrames;
function test() {
- initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
- gDebuggee = aDebuggee;
+ initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
+ gTab = aTab;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gFrames = gDebugger.DebuggerView.StackFrames;
waitForSourceShown(gPanel, JS_URL)
.then(checkInitialSource)
@@ -59,23 +59,23 @@ function testSetBreakpoint() {
isnot(gFrames.getItemAtIndex(0).attachment.url.indexOf(".js"), -1,
"First frame should be a JS frame.");
deferred.resolve();
});
// This will cause the breakpoint to be hit, and put us back in the
// paused state.
- gDebuggee.arithmetic();
+ callInTab(gTab, "arithmetic");
});
});
return deferred.promise;
}
registerCleanupFunction(function() {
- gDebuggee = null;
+ gTab = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
gFrames = null;
});
--- a/browser/devtools/debugger/test/browser_dbg_source-maps-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_source-maps-04.js
@@ -11,17 +11,17 @@ const JS_URL = EXAMPLE_URL + "code_math_
// This test causes an error to be logged in the console, which appears in TBPL
// logs, so we are disabling that here.
let { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
DevToolsUtils.reportingDisabled = true;
let gPanel, gDebugger, gFrames, gSources, gPrefs, gOptions;
function test() {
- initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+ initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gFrames = gDebugger.DebuggerView.StackFrames;
gSources = gDebugger.DebuggerView.Sources;
gPrefs = gDebugger.Prefs;
gOptions = gDebugger.DebuggerView.Options;
is(gPrefs.pauseOnExceptions, false,
--- a/browser/devtools/debugger/test/code_frame-script.js
+++ b/browser/devtools/debugger/test/code_frame-script.js
@@ -5,19 +5,20 @@ const { loadSubScript } = Cc['@mozilla.o
getService(Ci.mozIJSSubScriptLoader);
const EventUtils = {};
loadSubScript("chrome://marionette/content/EventUtils.js", EventUtils);
dump("Frame script loaded.\n");
addMessageListener("test:call", function (message) {
- dump("Calling function with name " + message.data + ".\n");
+ dump("Calling function with name " + message.data.name + ".\n");
- XPCNativeWrapper.unwrap(content)[message.data]();
+ let data = message.data;
+ XPCNativeWrapper.unwrap(content)[data.name].apply(undefined, data.args);
sendAsyncMessage("test:call");
});
addMessageListener("test:click", function (message) {
dump("Sending mouse click.\n");
let target = message.objects.target;
EventUtils.synthesizeMouseAtCenter(target, {},
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -958,17 +958,20 @@ function waitForMessageFromTab(tab, name
resolve(message);
});
});
}
function callInTab(tab, name) {
info("Calling function with name " + name + " in tab.");
- sendMessageToTab(tab, "test:call", name);
+ sendMessageToTab(tab, "test:call", {
+ name: name,
+ args: Array.prototype.slice.call(arguments, 2)
+ });
waitForMessageFromTab(tab, "test:call");
}
function sendMouseClickToTab(tab, target) {
info("Sending mouse click to tab.");
sendMessageToTab(tab, "test:click", undefined, {
target: target
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -2291,16 +2291,22 @@ WebSocketImpl::Cancel(nsresult aStatus)
return CancelInternal();
}
nsresult
WebSocketImpl::CancelInternal()
{
AssertIsOnTargetThread();
+ // If CancelInternal is called by a runnable, we may already be disconnected
+ // by the time it runs.
+ if (mDisconnected) {
+ return NS_OK;
+ }
+
int64_t readyState = mWebSocket->ReadyState();
if (readyState == WebSocket::CLOSING || readyState == WebSocket::CLOSED) {
return NS_OK;
}
ConsoleError();
return CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
--- a/dom/base/nsCSPContext.cpp
+++ b/dom/base/nsCSPContext.cpp
@@ -180,18 +180,19 @@ nsCSPContext::ShouldLoad(nsContentPolicy
CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, nsIContentPolicy::REJECT_SERVER"));
*outDecision = nsIContentPolicy::REJECT_SERVER;
}
// Do not send a report or notify observers if this is a preload - the
// decision may be wrong due to the inability to get the nonce, and will
// incorrectly fail the unit tests.
if (!isPreload) {
+ nsCOMPtr<nsIURI> originalURI = do_QueryInterface(aExtra);
this->AsyncReportViolation(aContentLocation,
- mSelfURI,
+ originalURI, /* in case of redirect originalURI is not null */
violatedDirective,
p, /* policy index */
EmptyString(), /* no observer subject */
EmptyString(), /* no source file */
EmptyString(), /* no script sample */
0); /* no line number */
}
}
@@ -413,17 +414,17 @@ nsCSPContext::GetAllowsHash(const nsAStr
PR_BEGIN_MACRO \
if (!mPolicies[p]->allows(nsIContentPolicy::TYPE_ ## contentPolicyType, \
keyword, nonceOrHash)) \
{ \
nsAutoString violatedDirective; \
mPolicies[p]->getDirectiveStringForContentType( \
nsIContentPolicy::TYPE_ ## contentPolicyType, \
violatedDirective); \
- this->AsyncReportViolation(selfISupports, mSelfURI, violatedDirective, p, \
+ this->AsyncReportViolation(selfISupports, nullptr, violatedDirective, p, \
NS_LITERAL_STRING(observerTopic), \
aSourceFile, aScriptSample, aLineNum); \
} \
PR_END_MACRO; \
break
/**
* For each policy, log any violation on the Error Console and send a report
@@ -535,16 +536,33 @@ nsCSPContext::SetRequestContext(nsIURI*
else {
NS_WARNING("Channel provided to SetRequestContext is not an nsIHttpChannel so referrer is not available for reporting." );
}
}
return NS_OK;
}
+/**
+ * Sends CSP violation reports to all sources listed under report-uri.
+ *
+ * @param aBlockedContentSource
+ * Either a CSP Source (like 'self', as string) or nsIURI: the source
+ * of the violation.
+ * @param aOriginalUri
+ * The original URI if the blocked content is a redirect, else null
+ * @param aViolatedDirective
+ * the directive that was violated (string).
+ * @param aSourceFile
+ * name of the file containing the inline script violation
+ * @param aScriptSample
+ * a sample of the violating inline script
+ * @param aLineNum
+ * source line number of the violation (if available)
+ */
nsresult
nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
nsIURI* aOriginalURI,
nsAString& aViolatedDirective,
uint32_t aViolatedPolicyIndex,
nsAString& aSourceFile,
nsAString& aScriptSample,
uint32_t aLineNum)
@@ -564,37 +582,43 @@ nsCSPContext::SendReports(nsISupports* a
nsresult rv;
// blocked-uri
if (aBlockedContentSource) {
nsAutoCString reportBlockedURI;
nsCOMPtr<nsIURI> uri = do_QueryInterface(aBlockedContentSource);
// could be a string or URI
if (uri) {
- uri->GetSpecIgnoringRef(reportBlockedURI);
+ // aOriginalURI will only be *not* null in case of a redirect in which
+ // case aOriginalURI is the uri before the redirect.
+ if (aOriginalURI) {
+ // do not report anything else than the origin in case of a redirect, see:
+ // http://www.w3.org/TR/CSP/#violation-reports
+ uri->GetPrePath(reportBlockedURI);
+ } else {
+ uri->GetSpecIgnoringRef(reportBlockedURI);
+ }
} else {
nsCOMPtr<nsISupportsCString> cstr = do_QueryInterface(aBlockedContentSource);
if (cstr) {
cstr->GetData(reportBlockedURI);
}
}
if (reportBlockedURI.IsEmpty()) {
// this can happen for frame-ancestors violation where the violating
// ancestor is cross-origin.
NS_WARNING("No blocked URI (null aBlockedContentSource) for CSP violation report.");
}
report.mCsp_report.mBlocked_uri = NS_ConvertUTF8toUTF16(reportBlockedURI);
}
// document-uri
- if (aOriginalURI) {
- nsAutoCString reportDocumentURI;
- aOriginalURI->GetSpecIgnoringRef(reportDocumentURI);
- report.mCsp_report.mDocument_uri = NS_ConvertUTF8toUTF16(reportDocumentURI);
- }
+ nsAutoCString reportDocumentURI;
+ mSelfURI->GetSpecIgnoringRef(reportDocumentURI);
+ report.mCsp_report.mDocument_uri = NS_ConvertUTF8toUTF16(reportDocumentURI);
// original-policy
nsAutoString originalPolicy;
rv = this->GetPolicy(aViolatedPolicyIndex, originalPolicy);
NS_ENSURE_SUCCESS(rv, rv);
report.mCsp_report.mOriginal_policy = originalPolicy;
// referrer
@@ -726,17 +750,17 @@ nsCSPContext::SendReports(nsISupports* a
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsCOMPtr<nsIContentPolicy> cp = do_GetService(NS_CONTENTPOLICY_CONTRACTID);
if (!cp) {
return NS_ERROR_FAILURE;
}
rv = cp->ShouldLoad(nsIContentPolicy::TYPE_CSP_REPORT,
reportURI,
- aOriginalURI,
+ mSelfURI,
nullptr, // Context
EmptyCString(), // mime type
nullptr, // Extra parameter
nullptr, // optional request principal
&shouldLoad);
// refuse to load if we can't do a security check
NS_ENSURE_SUCCESS(rv, rv);
@@ -1042,17 +1066,17 @@ nsCSPContext::PermitsAncestry(nsIDocShel
false, // no redirect
violatedDirective)) {
// Policy is violated
// Send reports, but omit the ancestor URI if cross-origin as per spec
// (it is a violation of the same-origin policy).
bool okToSendAncestor = NS_SecurityCompareURIs(ancestorsArray[a], mSelfURI, true);
this->AsyncReportViolation((okToSendAncestor ? ancestorsArray[a] : nullptr),
- mSelfURI,
+ nullptr, /* originalURI in case of redirect */
violatedDirective,
i, /* policy index */
EmptyString(), /* no observer subject */
EmptyString(), /* no source file */
EmptyString(), /* no script sample */
0); /* no line number */
*outPermitsAncestry = false;
}
@@ -1075,17 +1099,17 @@ nsCSPContext::PermitsBaseURI(nsIURI* aUR
if (!mPolicies[i]->permitsBaseURI(aURI)) {
// policy is violated, report to caller if not report-only
if (!mPolicies[i]->getReportOnlyFlag()) {
*outPermitsBaseURI = false;
}
nsAutoString violatedDirective;
mPolicies[i]->getDirectiveStringForBaseURI(violatedDirective);
this->AsyncReportViolation(aURI,
- mSelfURI,
+ nullptr, /* originalURI in case of redirect */
violatedDirective,
i, /* policy index */
EmptyString(), /* no observer subject */
EmptyString(), /* no source file */
EmptyString(), /* no script sample */
0); /* no line number */
}
}
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -270,18 +270,23 @@ nsDOMWindowUtils::Redraw(uint32_t aCount
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDOMWindowUtils::UpdateLayerTree()
{
if (nsIPresShell* presShell = GetPresShell()) {
+ presShell->FlushPendingNotifications(Flush_Display);
nsRefPtr<nsViewManager> vm = presShell->GetViewManager();
- vm->ProcessPendingUpdates();
+ nsView* view = vm->GetRootView();
+ if (view) {
+ presShell->Paint(view, view->GetBounds(),
+ nsIPresShell::PAINT_LAYERS | nsIPresShell::PAINT_SYNC_DECODE_IMAGES);
+ }
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetCSSViewport(float aWidthPx, float aHeightPx)
{
if (!nsContentUtils::IsCallerChrome()) {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -189,17 +189,16 @@
#ifdef MOZ_GAMEPAD
#include "mozilla/dom/GamepadService.h"
#endif
#include "nsRefreshDriver.h"
#include "mozilla/dom/SelectionChangeEvent.h"
-#include "mozilla/AddonPathService.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "nsLocation.h"
#include "nsHTMLDocument.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "prrng.h"
#include "nsSandboxFlags.h"
@@ -2261,22 +2260,16 @@ CreateNativeGlobalForInner(JSContext* aC
nsCOMPtr<nsIExpandedPrincipal> nsEP = do_QueryInterface(aPrincipal);
MOZ_RELEASE_ASSERT(!nsEP, "DOMWindow with nsEP is not supported");
nsGlobalWindow *top = nullptr;
if (aNewInner->GetOuterWindow()) {
top = aNewInner->GetTop();
}
JS::CompartmentOptions options;
-
- // Sometimes add-ons load their own XUL windows, either as separate top-level
- // windows or inside a browser element. In such cases we want to tag the
- // window's compartment with the add-on ID. See bug 1092156.
- options.setAddonId(MapURIToAddonID(aURI));
-
if (top) {
if (top->GetGlobalJSObject()) {
options.setSameZoneAs(top->GetGlobalJSObject());
}
}
// Determine if we need the Components object.
bool needComponents = nsContentUtils::IsSystemPrincipal(aPrincipal) ||
--- a/dom/media/webspeech/recognition/SpeechRecognition.cpp
+++ b/dom/media/webspeech/recognition/SpeechRecognition.cpp
@@ -935,21 +935,21 @@ SpeechEvent::Run()
return NS_OK;
}
NS_IMPL_ISUPPORTS(SpeechRecognition::GetUserMediaSuccessCallback, nsIDOMGetUserMediaSuccessCallback)
NS_IMETHODIMP
SpeechRecognition::GetUserMediaSuccessCallback::OnSuccess(nsISupports* aStream)
{
- DOMLocalMediaStream *localStream = nullptr;
- nsresult rv = CallQueryInterface(aStream, &localStream);
- if (NS_SUCCEEDED(rv)) {
- mRecognition->StartRecording(localStream);
+ nsRefPtr<DOMMediaStream> stream = do_QueryObject(aStream);
+ if (!stream) {
+ return NS_ERROR_NO_INTERFACE;
}
+ mRecognition->StartRecording(stream);
return NS_OK;
}
NS_IMPL_ISUPPORTS(SpeechRecognition::GetUserMediaErrorCallback, nsIDOMGetUserMediaErrorCallback)
NS_IMETHODIMP
SpeechRecognition::GetUserMediaErrorCallback::OnError(nsISupports* aError)
{
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -38,16 +38,54 @@
using namespace mozilla;
using namespace mozilla::image;
using namespace mozilla::layers;
using namespace mozilla::gfx;
#include "DeprecatedPremultiplyTables.h"
+extern "C" {
+
+/**
+ * Dump a raw image to the default log. This function is exported
+ * from libxul, so it can be called from any library in addition to
+ * (of course) from a debugger.
+ *
+ * Note: this helper currently assumes that all 2-bytepp images are
+ * r5g6b5, and that all 4-bytepp images are r8g8b8a8.
+ */
+NS_EXPORT
+void mozilla_dump_image(void* bytes, int width, int height, int bytepp,
+ int strideBytes)
+{
+ if (0 == strideBytes) {
+ strideBytes = width * bytepp;
+ }
+ SurfaceFormat format;
+ // TODO more flexible; parse string?
+ switch (bytepp) {
+ case 2:
+ format = SurfaceFormat::R5G6B5;
+ break;
+ case 4:
+ default:
+ format = SurfaceFormat::R8G8B8A8;
+ break;
+ }
+
+ RefPtr<DataSourceSurface> surf =
+ Factory::CreateWrappingDataSourceSurface((uint8_t*)bytes, strideBytes,
+ gfx::IntSize(width, height),
+ format);
+ gfxUtils::DumpAsDataURI(surf);
+}
+
+}
+
static const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
return gfxUtils::sPremultiplyTable[a*256+v];
}
static const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
return gfxUtils::sUnpremultiplyTable[a*256+v];
}
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1218,17 +1218,19 @@ static const JSStdName builtin_property_
{ EAGER_ATOM(encodeURIComponent), JSProto_String },
#if JS_HAS_UNEVAL
{ EAGER_ATOM(uneval), JSProto_String },
#endif
#ifdef ENABLE_BINARYDATA
{ EAGER_ATOM(SIMD), JSProto_SIMD },
{ EAGER_ATOM(TypedObject), JSProto_TypedObject },
#endif
+#ifdef ENABLE_SHARED_ARRAY_BUFFER
{ EAGER_ATOM(Atomics), JSProto_Atomics },
+#endif
{ 0, JSProto_LIMIT }
};
#undef EAGER_ATOM
JS_PUBLIC_API(bool)
JS_ResolveStandardClass(JSContext *cx, HandleObject obj, HandleId id, bool *resolved)
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -341,26 +341,16 @@ XPCWrappedNativeScope::EnsureAddonScope(
{
JS::RootedObject global(cx, GetGlobalJSObject());
MOZ_ASSERT(js::IsObjectInContextCompartment(global, cx));
MOZ_ASSERT(!mIsContentXBLScope);
MOZ_ASSERT(!mIsAddonScope);
MOZ_ASSERT(addonId);
MOZ_ASSERT(nsContentUtils::IsSystemPrincipal(GetPrincipal()));
- // In bug 1092156, we found that add-on scopes don't work correctly when the
- // window navigates. The add-on global's prototype is an outer window, so,
- // after the navigation, looking up window properties in the add-on scope
- // will fail. However, in most cases where the window can be navigated, the
- // entire window is part of the add-on. To solve the problem, we avoid
- // returning an add-on scope for a window that is already tagged with the
- // add-on ID.
- if (AddonIdOfObject(global) == addonId)
- return global;
-
// If we already have an addon scope object, we know what to use.
for (size_t i = 0; i < mAddonScopes.Length(); i++) {
if (JS::AddonIdOfObject(js::UncheckedUnwrap(mAddonScopes[i])) == addonId)
return mAddonScopes[i];
}
SandboxOptions options;
options.wantComponents = true;
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1419,16 +1419,18 @@ public:
enum PaintFlags {
/* Update the layer tree and paint PaintedLayers. If this is not specified,
* we may still have to do it if the layer tree lost PaintedLayer contents
* we need for compositing. */
PAINT_LAYERS = 0x01,
/* Composite layers to the window. */
PAINT_COMPOSITE = 0x02,
+ /* Sync-decode images. */
+ PAINT_SYNC_DECODE_IMAGES = 0x04
};
virtual void Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
uint32_t aFlags) = 0;
virtual nsresult HandleEvent(nsIFrame* aFrame,
mozilla::WidgetGUIEvent* aEvent,
bool aDontRetargetEvents,
nsEventStatus* aEventStatus) = 0;
virtual bool ShouldIgnoreInvalidation() = 0;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6265,17 +6265,18 @@ PresShell::Paint(nsView* aViewToP
if (!(aFlags & PAINT_LAYERS)) {
if (layerManager->EndEmptyTransaction()) {
return;
}
NS_WARNING("Must complete empty transaction when compositing!");
}
- if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE) &&
+ if (!(aFlags & PAINT_SYNC_DECODE_IMAGES) &&
+ !(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE) &&
!mNextPaintCompressed) {
NotifySubDocInvalidationFunc computeInvalidFunc =
presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
bool computeInvalidRect = computeInvalidFunc ||
(layerManager->GetBackendType() == LayersBackend::LAYERS_BASIC);
UniquePtr<LayerProperties> props;
if (computeInvalidRect) {
@@ -6318,16 +6319,19 @@ PresShell::Paint(nsView* aViewToP
frame->ClearPresShellsFromLastPaint();
}
nscolor bgcolor = ComputeBackstopColor(aViewToPaint);
uint32_t flags = nsLayoutUtils::PAINT_WIDGET_LAYERS | nsLayoutUtils::PAINT_EXISTING_TRANSACTION;
if (!(aFlags & PAINT_COMPOSITE)) {
flags |= nsLayoutUtils::PAINT_NO_COMPOSITE;
}
+ if (aFlags & PAINT_SYNC_DECODE_IMAGES) {
+ flags |= nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES;
+ }
if (mNextPaintCompressed) {
flags |= nsLayoutUtils::PAINT_COMPRESSED;
mNextPaintCompressed = false;
}
if (frame) {
// We can paint directly into the widget using its layer manager.
nsLayoutUtils::PaintFrame(nullptr, frame, aDirtyRegion, bgcolor, flags);
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/bug1093686_inner.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html id="html" style="height:100%">
+<head>
+ <title>Testing effect of listener on body</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ .target { position:absolute; left:200px; top:200px; width:200px; height:200px; background:blue; }
+ </style>
+</head>
+<body id="body" onload="setTimeout(runTest, 0)" style="margin:0; width:100%; height:100%; overflow:hidden">
+<div id="content">
+ <div id="ruler" style="position:absolute; left:0; top:0; width:1mozmm; height:0;"></div>
+ <div class="target" id="t"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+var eventTarget;
+window.onmousedown = function(event) { eventTarget = event.target; };
+
+// Make sure the target div is "clickable" by adding a click listener on it.
+document.getElementById('t').addEventListener('click', function(e) {
+ parent.ok(true, "target was clicked on");
+}, false);
+
+// Helper functions
+
+function testMouseClick(aX, aY, aExpectedId, aMsg) {
+ eventTarget = null;
+ synthesizeMouseAtPoint(aX, aY, {});
+ try {
+ parent.is(eventTarget.id, aExpectedId,
+ "checking offset " + aX + "," + aY + " hit " + aExpectedId + " [" + aMsg + "]");
+ } catch (ex) {
+ parent.ok(false, "checking offset " + aX + "," + aY + " hit " + aExpectedId + " [" + aMsg + "]; got " + eventTarget);
+ }
+}
+
+function testWithAndWithoutBodyListener(aX, aY, aExpectedId, aMsg) {
+ var func = function(e) {
+ // no-op function
+ parent.ok(true, "body was clicked on");
+ };
+ testMouseClick(aX, aY, aExpectedId, aMsg + " without listener on body");
+ document.body.addEventListener("click", func, false);
+ testMouseClick(aX, aY, aExpectedId, aMsg + " with listener on body");
+ document.body.removeEventListener("click", func, false);
+}
+
+// Main tests
+
+var mm;
+function runTest() {
+ mm = document.getElementById("ruler").getBoundingClientRect().width;
+ parent.ok(4*mm >= 10, "WARNING: mm " + mm + " too small in this configuration. Test results will be bogus");
+
+ // Test near the target, check it hits the target
+ testWithAndWithoutBodyListener(200 - 2*mm, 200 - 2*mm, "t", "basic click retargeting");
+ // Test on the target, check it hits the target
+ testWithAndWithoutBodyListener(200 + 2*mm, 200 + 2*mm, "t", "direct click");
+ // Test outside the target, check it hits the root
+ testWithAndWithoutBodyListener(40, 40, "body", "click way outside target");
+
+ SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.enabled", false]]}, runTest2);
+}
+
+function runTest2() {
+ // In this test, mouse event retargeting is disabled.
+
+ // Test near the target, check it hits the body
+ testWithAndWithoutBodyListener(200 - 2*mm, 200 - 2*mm, "body", "basic click retargeting");
+ // Test on the target, check it hits the target
+ testWithAndWithoutBodyListener(200 + 2*mm, 200 + 2*mm, "t", "direct click");
+ // Test outside the target, check it hits the root
+ testWithAndWithoutBodyListener(40, 40, "body", "click way outside target");
+
+ parent.finishTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -501,8 +501,10 @@ support-files =
[test_bug1070851.html]
[test_bug1080360.html]
support-files = bug1080360_inner.html
[test_bug1078327.html]
support-files = bug1078327_inner.html
[test_bug1080361.html]
support-files = bug1080361_inner.html
[test_touchcaret_visibility.html]
+[test_bug1093686.html]
+support-files = bug1093686_inner.html
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_bug1093686.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1093686
+-->
+ <head>
+ <meta charset="utf-8">
+ <title>Testing effect of listener on body with respect to event retargeting</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ var iframe = undefined;
+ function prepareTest() {
+ SimpleTest.waitForExplicitFinish();
+ iframe = document.getElementById("testFrame");
+ turnOnEventRetargeting(startTest);
+ }
+ function turnOnEventRetargeting(callback) {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["ui.mouse.radius.enabled", true],
+ ["ui.mouse.radius.inputSource.touchOnly", false],
+ ["ui.mouse.radius.leftmm", 8],
+ ["ui.mouse.radius.topmm", 12],
+ ["ui.mouse.radius.rightmm", 8],
+ ["ui.mouse.radius.bottommm", 4]
+ ]
+ }, callback);
+ }
+ function startTest() {
+ iframe.src = "bug1093686_inner.html";
+ }
+ function finishTest() {
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onload="prepareTest()">
+ <iframe id="testFrame" height="700" width="700"></iframe>
+ </body>
+</html>
--- a/memory/build/jemalloc_config.c
+++ b/memory/build/jemalloc_config.c
@@ -5,17 +5,17 @@
#ifdef MOZ_JEMALLOC3
#define MOZ_JEMALLOC_IMPL
#include "mozmemory_wrap.h"
#include "mozilla/Types.h"
/* Override some jemalloc defaults */
-MFBT_DATA const char * je_(malloc_conf) = "narenas:1,lg_chunk:20";
+MFBT_DATA const char * je_(malloc_conf) = "narenas:1,lg_chunk:20,tcache:false";
#ifdef ANDROID
#include <android/log.h>
static void
_je_malloc_message(void *cbopaque, const char *s)
{
__android_log_print(ANDROID_LOG_INFO, "GeckoJemalloc", "%s", s);
--- a/netwerk/protocol/websocket/WebSocketChannelChild.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannelChild.cpp
@@ -115,16 +115,41 @@ WebSocketChannelChild::DispatchToTargetT
MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(mTargetThread);
MOZ_RELEASE_ASSERT(aChannelEvent);
mTargetThread->Dispatch(new WrappedChannelEvent(aChannelEvent),
NS_DISPATCH_NORMAL);
}
+class EventTargetDispatcher : public ChannelEvent
+{
+public:
+ EventTargetDispatcher(ChannelEvent* aChannelEvent,
+ nsIEventTarget* aEventTarget)
+ : mChannelEvent(aChannelEvent)
+ , mEventTarget(aEventTarget)
+ {}
+
+ void Run()
+ {
+ if (mEventTarget) {
+ mEventTarget->Dispatch(new WrappedChannelEvent(mChannelEvent.forget()),
+ NS_DISPATCH_NORMAL);
+ return;
+ }
+
+ mChannelEvent->Run();
+ }
+
+private:
+ nsAutoPtr<ChannelEvent> mChannelEvent;
+ nsCOMPtr<nsIEventTarget> mEventTarget;
+};
+
class StartEvent : public ChannelEvent
{
public:
StartEvent(WebSocketChannelChild* aChild,
const nsCString& aProtocol,
const nsCString& aExtensions,
const nsString& aEffectiveURL,
bool aEncrypted)
@@ -149,18 +174,20 @@ class StartEvent : public ChannelEvent
bool
WebSocketChannelChild::RecvOnStart(const nsCString& aProtocol,
const nsCString& aExtensions,
const nsString& aEffectiveURL,
const bool& aEncrypted)
{
if (mEventQ->ShouldEnqueue()) {
- mEventQ->Enqueue(new StartEvent(this, aProtocol, aExtensions,
- aEffectiveURL, aEncrypted));
+ mEventQ->Enqueue(new EventTargetDispatcher(
+ new StartEvent(this, aProtocol, aExtensions,
+ aEffectiveURL, aEncrypted),
+ mTargetThread));
} else if (mTargetThread) {
DispatchToTargetThread(new StartEvent(this, aProtocol, aExtensions,
aEffectiveURL, aEncrypted));
} else {
OnStart(aProtocol, aExtensions, aEffectiveURL, aEncrypted);
}
return true;
}
@@ -200,17 +227,18 @@ class StopEvent : public ChannelEvent
WebSocketChannelChild* mChild;
nsresult mStatusCode;
};
bool
WebSocketChannelChild::RecvOnStop(const nsresult& aStatusCode)
{
if (mEventQ->ShouldEnqueue()) {
- mEventQ->Enqueue(new StopEvent(this, aStatusCode));
+ mEventQ->Enqueue(new EventTargetDispatcher(
+ new StopEvent(this, aStatusCode), mTargetThread));
} else if (mTargetThread) {
DispatchToTargetThread(new StopEvent(this, aStatusCode));
} else {
OnStop(aStatusCode);
}
return true;
}
@@ -248,17 +276,18 @@ class MessageEvent : public ChannelEvent
nsCString mMessage;
bool mBinary;
};
bool
WebSocketChannelChild::RecvOnMessageAvailable(const nsCString& aMsg)
{
if (mEventQ->ShouldEnqueue()) {
- mEventQ->Enqueue(new MessageEvent(this, aMsg, false));
+ mEventQ->Enqueue(new EventTargetDispatcher(
+ new MessageEvent(this, aMsg, false), mTargetThread));
} else if (mTargetThread) {
DispatchToTargetThread(new MessageEvent(this, aMsg, false));
} else {
OnMessageAvailable(aMsg);
}
return true;
}
@@ -271,17 +300,18 @@ WebSocketChannelChild::OnMessageAvailabl
mListener->OnMessageAvailable(mContext, aMsg);
}
}
bool
WebSocketChannelChild::RecvOnBinaryMessageAvailable(const nsCString& aMsg)
{
if (mEventQ->ShouldEnqueue()) {
- mEventQ->Enqueue(new MessageEvent(this, aMsg, true));
+ mEventQ->Enqueue(new EventTargetDispatcher(
+ new MessageEvent(this, aMsg, true), mTargetThread));
} else if (mTargetThread) {
DispatchToTargetThread(new MessageEvent(this, aMsg, true));
} else {
OnBinaryMessageAvailable(aMsg);
}
return true;
}
@@ -312,17 +342,18 @@ class AcknowledgeEvent : public ChannelE
WebSocketChannelChild* mChild;
uint32_t mSize;
};
bool
WebSocketChannelChild::RecvOnAcknowledge(const uint32_t& aSize)
{
if (mEventQ->ShouldEnqueue()) {
- mEventQ->Enqueue(new AcknowledgeEvent(this, aSize));
+ mEventQ->Enqueue(new EventTargetDispatcher(
+ new AcknowledgeEvent(this, aSize), mTargetThread));
} else if (mTargetThread) {
DispatchToTargetThread(new AcknowledgeEvent(this, aSize));
} else {
OnAcknowledge(aSize);
}
return true;
}
@@ -357,17 +388,19 @@ class ServerCloseEvent : public ChannelE
nsCString mReason;
};
bool
WebSocketChannelChild::RecvOnServerClose(const uint16_t& aCode,
const nsCString& aReason)
{
if (mEventQ->ShouldEnqueue()) {
- mEventQ->Enqueue(new ServerCloseEvent(this, aCode, aReason));
+ mEventQ->Enqueue(new EventTargetDispatcher(
+ new ServerCloseEvent(this, aCode, aReason),
+ mTargetThread));
} else if (mTargetThread) {
DispatchToTargetThread(new ServerCloseEvent(this, aCode, aReason));
} else {
OnServerClose(aCode, aReason);
}
return true;
}
--- a/testing/marionette/client/marionette/runner/base.py
+++ b/testing/marionette/client/marionette/runner/base.py
@@ -18,16 +18,17 @@ import xml.dom.minidom as dom
from manifestparser import TestManifest
from marionette import Marionette
from mixins.b2g import B2GTestResultMixin, get_b2g_pid, get_dm
from mozhttpd import MozHttpd
from mozlog.structured.structuredlog import get_default_logger
from moztest.adapters.unit import StructuredTestRunner, StructuredTestResult
from moztest.results import TestResultCollection, TestResult, relevant_line
+import mozversion
class MarionetteTest(TestResult):
@property
def test_name(self):
if self.test_class is not None:
return '%s.py %s.%s' % (self.test_class.split('.')[0],
self.test_class,
@@ -707,17 +708,28 @@ setReq.onerror = function() {
if not self.httpd:
self.logger.info("starting httpd")
self.start_httpd(need_external_ip)
for test in tests:
self.add_test(test)
- self.logger.suite_start(self.tests)
+ version_info = mozversion.get_version(binary=self.bin,
+ sources=self.sources,
+ dm_type=os.environ.get('DM_TRANS', 'adb'))
+
+ device_info = None
+ if self.capabilities['device'] != 'desktop' and self.capabilities['browserName'] == 'B2G':
+ dm = get_dm(self.marionette)
+ device_info = dm.getInfo()
+
+ self.logger.suite_start(self.tests,
+ version_info=version_info,
+ device_info=device_info)
for test in self.manifest_skipped_tests:
name = os.path.basename(test['path'])
self.logger.test_start(name)
self.logger.test_end(name,
'SKIP',
message=test['disabled'])
self.todo += 1
--- a/testing/marionette/client/requirements.txt
+++ b/testing/marionette/client/requirements.txt
@@ -1,13 +1,13 @@
marionette-transport == 0.3
manifestparser
mozhttpd >= 0.5
mozinfo >= 0.7
mozprocess >= 0.9
mozrunner >= 6.2
mozdevice >= 0.37
-mozlog >= 2.6
+mozlog >= 2.7
moznetwork >= 0.21
mozcrash >= 0.5
mozprofile >= 0.7
moztest >= 0.7
mozversion >= 0.2
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -924,31 +924,31 @@ nsWindow::OnGlobalAndroidEvent(AndroidGe
// Keys synthesized by Java IME code are saved in the mIMEKeyEvents
// array until the next IME_REPLACE_TEXT event, at which point
// these keys are dispatched in sequence.
if (win->mFocus) {
win->mFocus->mIMEKeyEvents.AppendElement(*ae);
}
break;
- case AndroidGeckoEvent::COMPOSITOR_CREATE:
- win->CreateLayerManager(ae->Width(), ae->Height());
- break;
-
case AndroidGeckoEvent::COMPOSITOR_PAUSE:
// The compositor gets paused when the app is about to go into the
// background. While the compositor is paused, we need to ensure that
// no layer tree updates (from draw events) occur, since the compositor
// cannot make a GL context current in order to process updates.
if (sCompositorChild) {
sCompositorChild->SendPause();
}
sCompositorPaused = true;
break;
+ case AndroidGeckoEvent::COMPOSITOR_CREATE:
+ win->CreateLayerManager(ae->Width(), ae->Height());
+ // Fallthrough
+
case AndroidGeckoEvent::COMPOSITOR_RESUME:
// When we receive this, the compositor has already been told to
// resume. (It turns out that waiting till we reach here to tell
// the compositor to resume takes too long, resulting in a black
// flash.) This means it's now safe for layer updates to occur.
// Since we might have prevented one or more draw events from
// occurring while the compositor was paused, we need to schedule
// a draw event now.
--- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
@@ -219,16 +219,17 @@ static inline void copy_dword(uint32_t*
{
if (ireg_args + 1 < end) {
if ((uint32_t)ireg_args & 4) {
ireg_args++;
}
*(uint64_t *)ireg_args = data;
ireg_args += 2;
} else {
+ ireg_args = end;
if ((uint32_t)stack_args & 4) {
stack_args++;
}
*(uint64_t *)stack_args = data;
stack_args += 2;
}
}