diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index b38df8376bd2..2f8df362de18 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1759,9 +1759,19 @@ pref("app.shield.optoutstudies.enabled", false);
pref("intl.multilingual.enabled", false);
// Prio preferences
+// Only enable by default on Nightly.
+// On platforms that do not build libprio, do not set these prefs at all, which gives us a way to detect support.
+
// Curve25519 public keys for Prio servers
+#ifdef MOZ_LIBPRIO
pref("prio.publicKeyA", "35AC1C7576C7C6EDD7FED6BCFC337B34D48CB4EE45C86BEEFB40BD8875707733");
pref("prio.publicKeyB", "26E6674E65425B823F1F1D5F96E3BB3EF9E406EC7FBA7DEF8B08A35DD135AF50");
+#endif
+
+// Whether or not Prio-encoded Telemetry will be sent along with the main ping.
+#if defined(NIGHTLY_BUILD) && defined(MOZ_LIBPRIO)
+pref("prio.enabled", true);
+#endif
#ifdef NIGHTLY_BUILD
pref("browser.fastblock.enabled", true);
diff --git a/browser/base/content/test/siteIdentity/browser.ini b/browser/base/content/test/siteIdentity/browser.ini
index d8ddbaeca8f7..346503d052e9 100644
--- a/browser/base/content/test/siteIdentity/browser.ini
+++ b/browser/base/content/test/siteIdentity/browser.ini
@@ -55,7 +55,6 @@ support-files =
!/toolkit/components/passwordmgr/test/browser/insecure_test.html
!/toolkit/components/passwordmgr/test/browser/insecure_test_subframe.html
[browser_mcb_redirect.js]
-skip-if = (verify && !debug && os == 'mac') || (os == 'linux') || (os == 'mac') # Bug 1376771
tags = mcb
support-files =
test_mcb_redirect.html
diff --git a/browser/base/content/test/siteIdentity/browser_mcb_redirect.js b/browser/base/content/test/siteIdentity/browser_mcb_redirect.js
index 9bfc072b29ea..8ecaa21e048d 100644
--- a/browser/base/content/test/siteIdentity/browser_mcb_redirect.js
+++ b/browser/base/content/test/siteIdentity/browser_mcb_redirect.js
@@ -91,16 +91,16 @@ function test1() {
Services.prefs.setBoolPref(PREF_INSECURE_ICON, false);
var url = HTTPS_TEST_ROOT + "test_mcb_redirect.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkUIForTest1);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkUIForTest1);
}
function testInsecure1() {
Services.prefs.setBoolPref(PREF_INSECURE_ICON, true);
var url = HTTPS_TEST_ROOT + "test_mcb_redirect.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkUIForTest1);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkUIForTest1);
}
async function checkUIForTest1() {
@@ -118,8 +118,8 @@ async function checkUIForTest1() {
function test2() {
var url = HTTP_TEST_ROOT + "test_mcb_redirect.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkUIForTest2);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkUIForTest2);
}
async function checkUIForTest2() {
@@ -138,8 +138,8 @@ async function checkUIForTest2() {
function test3() {
info("test3");
var url = HTTPS_TEST_ROOT + "test_mcb_redirect_image.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkLoadEventForTest3);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkLoadEventForTest3);
}
function checkLoadEventForTest3() {
@@ -156,8 +156,8 @@ function checkLoadEventForTest3() {
function test4() {
info("test4");
var url = HTTP_TEST_ROOT + "test_mcb_redirect_image.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkLoadEventForTest4);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkLoadEventForTest4);
}
function checkLoadEventForTest4() {
@@ -179,8 +179,8 @@ function test5() {
info("test5");
Services.io.offline = true;
var url = HTTP_TEST_ROOT + "test_mcb_redirect_image.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkLoadEventForTest5);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkLoadEventForTest5);
}
function checkLoadEventForTest5() {
@@ -206,8 +206,8 @@ function test6() {
info("test6");
Services.io.offline = true;
var url = HTTPS_TEST_ROOT + "test_mcb_redirect_image.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkLoadEventForTest6);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkLoadEventForTest6);
}
function checkLoadEventForTest6() {
@@ -227,8 +227,8 @@ function checkLoadEventForTest6() {
// HTTP page loading insecure image that went through a double redirect
function test7() {
var url = HTTP_TEST_ROOT + "test_mcb_double_redirect_image.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkLoadEventForTest7);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkLoadEventForTest7);
}
function checkLoadEventForTest7() {
@@ -249,8 +249,8 @@ function test8() {
// Go into offline mode
Services.io.offline = true;
var url = HTTP_TEST_ROOT + "test_mcb_double_redirect_image.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkLoadEventForTest8);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkLoadEventForTest8);
}
function checkLoadEventForTest8() {
@@ -275,8 +275,8 @@ function test9() {
// Go into offline mode
Services.io.offline = true;
var url = HTTPS_TEST_ROOT + "test_mcb_double_redirect_image.html";
+ BrowserTestUtils.browserLoaded(gTestBrowser, false, url).then(checkLoadEventForTest9);
BrowserTestUtils.loadURI(gTestBrowser, url);
- BrowserTestUtils.browserLoaded(gTestBrowser).then(checkLoadEventForTest9);
}
function checkLoadEventForTest9() {
diff --git a/browser/components/payments/res/containers/completion-error-page.js b/browser/components/payments/res/containers/completion-error-page.js
index 0c379402da29..ec54ad7db622 100644
--- a/browser/components/payments/res/containers/completion-error-page.js
+++ b/browser/components/payments/res/containers/completion-error-page.js
@@ -26,6 +26,10 @@ export default class CompletionErrorPage extends PaymentStateSubscriberMixin(Pay
this.suggestions = [];
this.body.append(this.suggestionsList);
+ this.brandingSpan = document.createElement("span");
+ this.brandingSpan.classList.add("branding");
+ this.footer.appendChild(this.brandingSpan);
+
this.doneButton = document.createElement("button");
this.doneButton.classList.add("done-button", "primary");
this.doneButton.addEventListener("click", this);
@@ -51,6 +55,7 @@ export default class CompletionErrorPage extends PaymentStateSubscriberMixin(Pay
this.pageTitleHeading.textContent = this.dataset.pageTitle;
this.suggestionHeading.textContent = this.dataset.suggestionHeading;
+ this.brandingSpan.textContent = this.dataset.brandingLabel;
this.doneButton.textContent = this.dataset.doneButtonLabel;
this.suggestionsList.textContent = "";
diff --git a/browser/components/payments/res/containers/error-page.css b/browser/components/payments/res/containers/error-page.css
index e950f0a9dcee..ba47b9a0dcc5 100644
--- a/browser/components/payments/res/containers/error-page.css
+++ b/browser/components/payments/res/containers/error-page.css
@@ -1,9 +1,11 @@
.error-page.illustrated > .page-body {
- min-height: 300px;
+ display: flex;
+ justify-content: center;
+ min-height: 160px;
background-position: left center;
background-repeat: no-repeat;
- background-size: 38%;
- padding-inline-start: 38%;
+ background-size: 160px;
+ padding-inline-start: 160px;
}
.error-page.illustrated > .page-body:dir(rtl) {
@@ -14,6 +16,17 @@
background: none;
padding-inline-start: 0;
margin-inline-start: 0;
+ font-weight: lighter;
+ font-size: 2rem;
+}
+
+.error-page.illustrated > .page-body > p {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+.error-page.illustrated > .page-body > ul {
+ margin-top: .5rem;
}
.error-page#completion-timeout-error > .page-body {
diff --git a/browser/components/payments/res/debugging.js b/browser/components/payments/res/debugging.js
index 26b15c64a2f4..a15196ddd826 100644
--- a/browser/components/payments/res/debugging.js
+++ b/browser/components/payments/res/debugging.js
@@ -37,7 +37,7 @@ const paymentOptionsUpdater = {
let REQUEST_1 = {
tabId: 9,
- topLevelPrincipal: {URI: {displayHost: "tschaeff.github.io"}},
+ topLevelPrincipal: {URI: {displayHost: "debugging.example.com"}},
requestId: "3797081f-a96b-c34b-a58b-1083c6e66e25",
completeStatus: "",
paymentMethods: [],
diff --git a/browser/components/payments/res/paymentRequest.css b/browser/components/payments/res/paymentRequest.css
index e6bc4ffd15d6..991927260b9d 100644
--- a/browser/components/payments/res/paymentRequest.css
+++ b/browser/components/payments/res/paymentRequest.css
@@ -159,10 +159,6 @@ payment-dialog[changes-prevented][complete-status="success"] #pay {
z-index: 1;
}
-#cancel {
- margin-inline-start: auto;
-}
-
#disabled-overlay {
background: white;
grid-area: disabled-overlay;
@@ -176,15 +172,16 @@ payment-dialog[changes-prevented][complete-status="success"] #pay {
left: 0;
}
-#branding {
+.branding {
background-image: url(chrome://branding/content/icon32.png);
background-size: 16px;
background-repeat: no-repeat;
background-position: left center;
padding-inline-start: 20px;
line-height: 20px;
+ margin-inline-end: auto;
}
-body[dir="rtl"] #branding {
+body[dir="rtl"] .branding {
background-position: right center;
}
diff --git a/browser/components/payments/res/paymentRequest.xhtml b/browser/components/payments/res/paymentRequest.xhtml
index cf3a4ff1bdf2..6ebcc4169260 100644
--- a/browser/components/payments/res/paymentRequest.xhtml
+++ b/browser/components/payments/res/paymentRequest.xhtml
@@ -154,7 +154,7 @@
@@ -44,6 +45,7 @@ add_task(async function test_no_values() {
"Suggestion 1 set on page");
is(page.dataset["suggestion-2"], "Sample suggestion",
"Suggestion 2 set on page");
+ is(page.dataset.brandingLabel, "Sample Brand", "Branding string set");
page.dataset.pageTitle = "Oh noes! **host-name** is having an issue";
page.dataset["suggestion-2"] = "You should probably blame **host-name**, not us";
@@ -72,6 +74,12 @@ add_task(async function test_no_values() {
is(page.querySelector("li:nth-child(2)").textContent,
`You should probably blame ${displayHost}, not us`,
"Suggestion 2 includes host-name");
+ is(page.querySelector(".branding").textContent,
+ "Sample Brand",
+ "Branding set on page");
+ is(page.querySelector(".primary").textContent,
+ "OK",
+ "Primary button label set correctly");
});
diff --git a/browser/moz.build b/browser/moz.build
index 15e11f45ff4a..217697e48754 100644
--- a/browser/moz.build
+++ b/browser/moz.build
@@ -45,6 +45,9 @@ for cdm in CONFIG['MOZ_EME_MODULES']:
if CONFIG['MOZ_GPSD']:
DEFINES['MOZ_GPSD'] = True
+if CONFIG['MOZ_LIBPRIO']:
+ DEFINES['MOZ_LIBPRIO'] = True
+
# These files are specified in this moz.build to pick up DIST_SUBDIR as set in
# this directory, which is un-set in browser/app.
JS_PREFERENCE_PP_FILES += [
diff --git a/devtools/client/inspector/test/browser.ini b/devtools/client/inspector/test/browser.ini
index 832f1fa3ad00..db9ed2315126 100644
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -31,6 +31,7 @@ support-files =
doc_inspector_long-divs.html
doc_inspector_menu.html
doc_inspector_outerhtml.html
+ doc_inspector_reload_xul.xul
doc_inspector_remove-iframe-during-load.html
doc_inspector_search.html
doc_inspector_search-reserved.html
@@ -169,6 +170,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_inspector_pseudoclass-menu.js]
[browser_inspector_reload-01.js]
[browser_inspector_reload-02.js]
+[browser_inspector_reload_xul.js]
[browser_inspector_remove-iframe-during-load.js]
[browser_inspector_search-01.js]
[browser_inspector_search-02.js]
diff --git a/devtools/client/inspector/test/browser_inspector_reload_xul.js b/devtools/client/inspector/test/browser_inspector_reload_xul.js
new file mode 100644
index 000000000000..ba3167cca9bf
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_reload_xul.js
@@ -0,0 +1,60 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+/* globals getTestActorWithoutToolbox */
+"use strict";
+
+// Tests for inspecting a node on a XUL document, spanning a tab reload.
+
+const TEST_URI = URL_ROOT + "doc_inspector_reload_xul.xul";
+
+add_task(async function() {
+ await pushPref("dom.allow_XUL_XBL_for_file", false);
+
+ const { tab, inspector, toolbox } = await openInspectorForURL(TEST_URI);
+ await testToolboxInitialization(tab, inspector, toolbox);
+});
+
+async function testToolboxInitialization(tab, inspector, toolbox) {
+ const target = TargetFactory.forTab(tab);
+
+ ok(true, "Inspector started, and notification received.");
+ ok(inspector, "Inspector instance is accessible.");
+ ok(inspector.isReady, "Inspector instance is ready.");
+ is(inspector.target.tab, tab, "Valid target.");
+
+ await selectNode("#p", inspector);
+ await testMarkupView("#p", inspector);
+
+ info("Reloading the page.");
+ const markuploaded = inspector.once("markuploaded");
+ const onNewRoot = inspector.once("new-root");
+ const onUpdated = inspector.once("inspector-updated");
+ await toolbox.target.activeTab.reload();
+ info("Waiting for inspector to be ready.");
+ await markuploaded;
+ await onNewRoot;
+ await onUpdated;
+
+ await selectNode("#q", inspector);
+ await testMarkupView("#q", inspector);
+
+ info("Destroying toolbox.");
+ await toolbox.destroy();
+
+ ok("true", "'destroyed' notification received.");
+ ok(!gDevTools.getToolbox(target), "Toolbox destroyed.");
+}
+
+async function testMarkupView(selector, inspector) {
+ const nodeFront = await getNodeFront(selector, inspector);
+ try {
+ is(inspector.selection.nodeFront, nodeFront,
+ "Right node is selected in the markup view");
+ } catch (ex) {
+ ok(false, "Got exception while resolving selected node of markup view.");
+ console.error(ex);
+ }
+}
diff --git a/devtools/client/inspector/test/doc_inspector_reload_xul.xul b/devtools/client/inspector/test/doc_inspector_reload_xul.xul
new file mode 100644
index 000000000000..b46ab0cfcea2
--- /dev/null
+++ b/devtools/client/inspector/test/doc_inspector_reload_xul.xul
@@ -0,0 +1,9 @@
+
+
+
+
+
+
a node inspected before reload
+
a node inspected after reload
+
+
diff --git a/devtools/server/actors/inspector/inspector.js b/devtools/server/actors/inspector/inspector.js
index 9fe90cdbb3a4..4b615924776a 100644
--- a/devtools/server/actors/inspector/inspector.js
+++ b/devtools/server/actors/inspector/inspector.js
@@ -106,10 +106,14 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
const deferred = defer();
this._walkerPromise = deferred.promise;
+ const isXULDocument =
+ this.targetActor.window.document.documentElement.namespaceURI === XUL_NS;
+ const loadEvent = isXULDocument ? "load" : "DOMContentLoaded";
+
const window = this.window;
const domReady = () => {
const targetActor = this.targetActor;
- window.removeEventListener("DOMContentLoaded", domReady, true);
+ window.removeEventListener(loadEvent, domReady, true);
this.walker = WalkerActor(this.conn, targetActor, options);
this.manage(this.walker);
this.walker.once("destroyed", () => {
@@ -120,7 +124,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
};
if (window.document.readyState === "loading") {
- window.addEventListener("DOMContentLoaded", domReady, true);
+ window.addEventListener(loadEvent, domReady, true);
} else {
domReady();
}
diff --git a/devtools/server/actors/inspector/walker.js b/devtools/server/actors/inspector/walker.js
index 35729a832693..4821d191c7c4 100644
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -42,6 +42,8 @@ loader.lazyRequireGetter(this, "WalkerSearch", "devtools/server/actors/utils/wal
loader.lazyServiceGetter(this, "eventListenerService",
"@mozilla.org/eventlistenerservice;1", "nsIEventListenerService");
+loader.lazyRequireGetter(this, "ChromeUtils");
+
// Minimum delay between two "new-mutations" events.
const MUTATIONS_THROTTLING_DELAY = 100;
// List of mutation types that should -not- be throttled.
@@ -1844,7 +1846,15 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
onFrameLoad: function({ window, isTopLevel }) {
const { readyState } = window.document;
if (readyState != "interactive" && readyState != "complete") {
- window.addEventListener("DOMContentLoaded",
+ // The document is not loaded, so we want to register to fire again when the
+ // DOM has been loaded. To do this, we need to know if this is a XUL document.
+ // We listen for "DOMContentLoaded" on HTML documents, but XUL documents don't
+ // fire this event, so we fallback to the "load" event for XUL. Unfortunately,
+ // since the document isn't loaded yet, we can't check its namespace declaration
+ // to determine if it is XUL. Instead, we use ChromeUtils to see if the document
+ // object class is XULDocument.
+ const isXULDocument = (ChromeUtils.getClassName(window.document) == "XULDocument");
+ window.addEventListener(isXULDocument ? "load" : "DOMContentLoaded",
this.onFrameLoad.bind(this, { window, isTopLevel }),
{ once: true });
return;
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 4b7fbc780102..f51b344a1569 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -8682,9 +8682,9 @@ nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget,
// documents have their fullscreen state reset.
CleanupFullscreenState();
- // If anyone was listening to this document's state, advertizing the state
- // change would be the least of the politeness.
- DispatchFullScreenChange(this);
+ // The fullscreenchange event is to be queued in the refresh driver,
+ // however a hidden page wouldn't trigger that again, so it makes no
+ // sense to dispatch such event here.
}
}
@@ -10669,113 +10669,6 @@ nsIDocument::IsFullscreenLeaf()
return CountFullscreenSubDocuments(this) == 0;
}
-static bool
-ResetFullScreen(nsIDocument* aDocument, void* aData)
-{
- if (aDocument->FullScreenStackTop()) {
- NS_ASSERTION(CountFullscreenSubDocuments(aDocument) <= 1,
- "Should have at most 1 fullscreen subdocument.");
- aDocument->CleanupFullscreenState();
- NS_ASSERTION(!aDocument->FullScreenStackTop(),
- "Should reset full-screen");
- auto changed = reinterpret_cast*>(aData);
- changed->AppendElement(aDocument);
- aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
- }
- return true;
-}
-
-// Since nsIDocument::ExitFullscreenInDocTree() could be called from
-// Element::UnbindFromTree() where it is not safe to synchronously run
-// script. This runnable is the script part of that function.
-class ExitFullscreenScriptRunnable : public Runnable
-{
-public:
- explicit ExitFullscreenScriptRunnable(nsCOMArray&& aDocuments)
- : mozilla::Runnable("ExitFullscreenScriptRunnable")
- , mDocuments(std::move(aDocuments))
- {
- }
-
- NS_IMETHOD Run() override
- {
- // Dispatch MozDOMFullscreen:Exited to the last document in
- // the list since we want this event to follow the same path
- // MozDOMFullscreen:Entered dispatched.
- nsIDocument* lastDocument = mDocuments[mDocuments.Length() - 1];
- nsContentUtils::DispatchEventOnlyToChrome(
- lastDocument, ToSupports(lastDocument),
- NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
- CanBubble::eYes, Cancelable::eNo, /* DefaultAction */ nullptr);
- // Ensure the window exits fullscreen.
- if (nsPIDOMWindowOuter* win = mDocuments[0]->GetWindow()) {
- win->SetFullscreenInternal(FullscreenReason::ForForceExitFullscreen, false);
- }
- return NS_OK;
- }
-
-private:
- nsCOMArray mDocuments;
-};
-
-/* static */ void
-nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
-{
- MOZ_ASSERT(aMaybeNotARootDoc);
-
- // Unlock the pointer
- UnlockPointer();
-
- nsCOMPtr root = aMaybeNotARootDoc->GetFullscreenRoot();
- if (!root || !root->FullScreenStackTop()) {
- // If a document was detached before exiting from fullscreen, it is
- // possible that the root had left fullscreen state. In this case,
- // we would not get anything from the ResetFullScreen() call. Root's
- // not being a fullscreen doc also means the widget should have
- // exited fullscreen state. It means even if we do not return here,
- // we would actually do nothing below except crashing ourselves via
- // dispatching the "MozDOMFullscreen:Exited" event to an nonexistent
- // document.
- return;
- }
-
- // Stores a list of documents to which we must dispatch "fullscreenchange".
- // We're required by the spec to dispatch the events in leaf-to-root
- // order when exiting fullscreen, but we traverse the doctree in a
- // root-to-leaf order, so we save references to the documents we must
- // dispatch to so that we dispatch in the specified order.
- nsCOMArray changed;
-
- // Walk the tree of fullscreen documents, and reset their fullscreen state.
- ResetFullScreen(root, static_cast(&changed));
-
- // Dispatch "fullscreenchange" events. Note this loop is in reverse
- // order so that the events for the leaf document arrives before the root
- // document, as required by the spec.
- for (uint32_t i = 0; i < changed.Length(); ++i) {
- DispatchFullScreenChange(changed[changed.Length() - i - 1]);
- }
-
- NS_ASSERTION(!root->FullScreenStackTop(),
- "Fullscreen root should no longer be a fullscreen doc...");
-
- // Move the top-level window out of fullscreen mode.
- FullscreenRoots::Remove(root);
-
- nsContentUtils::AddScriptRunner(
- new ExitFullscreenScriptRunnable(std::move(changed)));
-}
-
-static void
-DispatchFullscreenNewOriginEvent(nsIDocument* aDoc)
-{
- RefPtr asyncDispatcher =
- new AsyncEventDispatcher(
- aDoc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
- CanBubble::eYes, ChromeOnlyDispatch::eYes);
- asyncDispatcher->PostDOMEvent();
-}
-
bool
GetFullscreenLeaf(nsIDocument* aDoc, void* aData)
{
@@ -10809,6 +10702,105 @@ GetFullscreenLeaf(nsIDocument* aDoc)
return leaf;
}
+static bool
+ResetFullScreen(nsIDocument* aDocument, void* aData)
+{
+ if (aDocument->FullScreenStackTop()) {
+ NS_ASSERTION(CountFullscreenSubDocuments(aDocument) <= 1,
+ "Should have at most 1 fullscreen subdocument.");
+ aDocument->CleanupFullscreenState();
+ NS_ASSERTION(!aDocument->FullScreenStackTop(),
+ "Should reset full-screen");
+ DispatchFullScreenChange(aDocument);
+ aDocument->EnumerateSubDocuments(ResetFullScreen, nullptr);
+ }
+ return true;
+}
+
+// Since nsIDocument::ExitFullscreenInDocTree() could be called from
+// Element::UnbindFromTree() where it is not safe to synchronously run
+// script. This runnable is the script part of that function.
+class ExitFullscreenScriptRunnable : public Runnable
+{
+public:
+ explicit ExitFullscreenScriptRunnable(nsIDocument* aRoot, nsIDocument* aLeaf)
+ : mozilla::Runnable("ExitFullscreenScriptRunnable")
+ , mRoot(aRoot)
+ , mLeaf(aLeaf)
+ {
+ }
+
+ NS_IMETHOD Run() override
+ {
+ // Dispatch MozDOMFullscreen:Exited to the original fullscreen leaf
+ // document since we want this event to follow the same path that
+ // MozDOMFullscreen:Entered was dispatched.
+ nsContentUtils::DispatchEventOnlyToChrome(
+ mLeaf, ToSupports(mLeaf),
+ NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
+ CanBubble::eYes, Cancelable::eNo, /* DefaultAction */ nullptr);
+ // Ensure the window exits fullscreen.
+ if (nsPIDOMWindowOuter* win = mRoot->GetWindow()) {
+ win->SetFullscreenInternal(FullscreenReason::ForForceExitFullscreen, false);
+ }
+ return NS_OK;
+ }
+
+private:
+ nsCOMPtr mRoot;
+ nsCOMPtr mLeaf;
+};
+
+/* static */ void
+nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
+{
+ MOZ_ASSERT(aMaybeNotARootDoc);
+
+ // Unlock the pointer
+ UnlockPointer();
+
+ nsCOMPtr root = aMaybeNotARootDoc->GetFullscreenRoot();
+ if (!root || !root->FullScreenStackTop()) {
+ // If a document was detached before exiting from fullscreen, it is
+ // possible that the root had left fullscreen state. In this case,
+ // we would not get anything from the ResetFullScreen() call. Root's
+ // not being a fullscreen doc also means the widget should have
+ // exited fullscreen state. It means even if we do not return here,
+ // we would actually do nothing below except crashing ourselves via
+ // dispatching the "MozDOMFullscreen:Exited" event to an nonexistent
+ // document.
+ return;
+ }
+
+ // Record the fullscreen leaf document for MozDOMFullscreen:Exited.
+ // See ExitFullscreenScriptRunnable::Run for details. We have to
+ // record it here because we don't have such information after we
+ // reset the fullscreen state below.
+ nsIDocument* fullscreenLeaf = GetFullscreenLeaf(root);
+
+ // Walk the tree of fullscreen documents, and reset their fullscreen state.
+ ResetFullScreen(root, nullptr);
+
+ NS_ASSERTION(!root->FullScreenStackTop(),
+ "Fullscreen root should no longer be a fullscreen doc...");
+
+ // Move the top-level window out of fullscreen mode.
+ FullscreenRoots::Remove(root);
+
+ nsContentUtils::AddScriptRunner(
+ new ExitFullscreenScriptRunnable(root, fullscreenLeaf));
+}
+
+static void
+DispatchFullscreenNewOriginEvent(nsIDocument* aDoc)
+{
+ RefPtr asyncDispatcher =
+ new AsyncEventDispatcher(
+ aDoc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
+ CanBubble::eYes, ChromeOnlyDispatch::eYes);
+ asyncDispatcher->PostDOMEvent();
+}
+
void
nsIDocument::RestorePreviousFullScreenState()
{
@@ -10874,8 +10866,10 @@ nsIDocument::RestorePreviousFullScreenState()
lastDoc->CleanupFullscreenState();
newFullscreenDoc = lastDoc->GetParentDocument();
}
- // Dispatch the fullscreenchange event to all document listed.
- for (nsIDocument* d : exitDocs) {
+ // Dispatch the fullscreenchange event to all document listed. Note
+ // that the loop order is reversed so that events are dispatched in
+ // the tree order as indicated in the spec.
+ for (nsIDocument* d : Reversed(exitDocs)) {
DispatchFullScreenChange(d);
}
@@ -11527,11 +11521,11 @@ nsIDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
DispatchFullscreenNewOriginEvent(this);
}
- // Dispatch "fullscreenchange" events. Note this loop is in reverse
- // order so that the events for the root document arrives before the leaf
- // document, as required by the spec.
- for (uint32_t i = 0; i < changed.Length(); ++i) {
- DispatchFullScreenChange(changed[changed.Length() - i - 1]);
+ // Dispatch "fullscreenchange" events. Note that the loop order is
+ // reversed so that events are dispatched in the tree order as
+ // indicated in the spec.
+ for (nsIDocument* d : Reversed(changed)) {
+ DispatchFullScreenChange(d);
}
return true;
}
diff --git a/dom/chrome-webidl/PrioEncoder.webidl b/dom/chrome-webidl/PrioEncoder.webidl
index c32c5ecb9d1e..3b0243326bcc 100644
--- a/dom/chrome-webidl/PrioEncoder.webidl
+++ b/dom/chrome-webidl/PrioEncoder.webidl
@@ -7,13 +7,13 @@
[ChromeOnly, Exposed=(Window,System)]
namespace PrioEncoder {
[Throws, NewObject]
- Promise encode(ByteString batchID, PrioParams params);
+ PrioEncodedData encode(ByteString batchID, PrioParams params);
};
dictionary PrioParams {
- required boolean startupCrashDetected;
- required boolean safeModeUsage;
required boolean browserIsUserDefault;
+ required boolean newTabPageEnabled;
+ required boolean pdfViewerUsed;
};
dictionary PrioEncodedData {
diff --git a/dom/html/test/file_fullscreen-event-order.html b/dom/html/test/file_fullscreen-event-order.html
new file mode 100644
index 000000000000..c6c3f47f8930
--- /dev/null
+++ b/dom/html/test/file_fullscreen-event-order.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
diff --git a/dom/html/test/mochitest.ini b/dom/html/test/mochitest.ini
index 114efe29be66..068a1c4a9f33 100644
--- a/dom/html/test/mochitest.ini
+++ b/dom/html/test/mochitest.ini
@@ -445,6 +445,7 @@ support-files =
file_fullscreen-denied.html
file_fullscreen-esc-exit-inner.html
file_fullscreen-esc-exit.html
+ file_fullscreen-event-order.html
file_fullscreen-hidden.html
file_fullscreen-lenient-setters.html
file_fullscreen-multiple-inner.html
diff --git a/dom/html/test/test_fullscreen-api.html b/dom/html/test/test_fullscreen-api.html
index 25f1d5d9f953..c9a6d5d86609 100644
--- a/dom/html/test/test_fullscreen-api.html
+++ b/dom/html/test/test_fullscreen-api.html
@@ -47,6 +47,7 @@ var gTestWindows = [
"file_fullscreen-unprefix-disabled.html",
"file_fullscreen-lenient-setters.html",
"file_fullscreen-table.html",
+ "file_fullscreen-event-order.html",
];
var testWindow = null;
diff --git a/dom/prio/PrioEncoder.cpp b/dom/prio/PrioEncoder.cpp
index c49dead2d2be..77ff45ba82f7 100644
--- a/dom/prio/PrioEncoder.cpp
+++ b/dom/prio/PrioEncoder.cpp
@@ -5,10 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/Promise.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/ScopeExit.h"
#include "mozilla/Services.h"
#include "mozilla/TextUtils.h"
+#include "mozilla/dom/ToJSValue.h"
+
#include "PrioEncoder.h"
namespace mozilla {
@@ -35,15 +38,17 @@ PrioEncoder::~PrioEncoder()
Prio_clear();
}
-/* static */
-already_AddRefed
-PrioEncoder::Encode(GlobalObject& aGlobal, const nsCString& aBatchID, const PrioParams& aPrioParams, ErrorResult& aRv)
+/* static */ void
+PrioEncoder::Encode(GlobalObject& aGlobal,
+ const nsCString& aBatchID,
+ const PrioParams& aPrioParams,
+ RootedDictionary& aData,
+ ErrorResult& aRv)
{
nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports());
-
if (!global) {
aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
+ return;
}
SECStatus prio_rv = SECSuccess;
@@ -55,18 +60,20 @@ PrioEncoder::Encode(GlobalObject& aGlobal, const nsCString& aBatchID, const Prio
Prio_init();
+ nsresult rv;
+
nsAutoCStringN prioKeyA;
- nsresult rv = Preferences::GetCString("prio.publicKeyA", prioKeyA);
+ rv = Preferences::GetCString("prio.publicKeyA", prioKeyA);
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
+ return;
}
nsAutoCStringN prioKeyB;
rv = Preferences::GetCString("prio.publicKeyB", prioKeyB);
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
+ return;
}
// Check that both public keys are of the right length
@@ -74,35 +81,41 @@ PrioEncoder::Encode(GlobalObject& aGlobal, const nsCString& aBatchID, const Prio
if (!PrioEncoder::IsValidHexPublicKey(prioKeyA)
|| !PrioEncoder::IsValidHexPublicKey(prioKeyB)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
+ return;
}
- prio_rv = PublicKey_import_hex(&sPublicKeyA, reinterpret_cast(prioKeyA.BeginReading()), CURVE25519_KEY_LEN_HEX);
+ prio_rv = PublicKey_import_hex(&sPublicKeyA,
+ reinterpret_cast(prioKeyA.BeginReading()),
+ CURVE25519_KEY_LEN_HEX);
if (prio_rv != SECSuccess) {
aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
+ return;
}
- prio_rv = PublicKey_import_hex(&sPublicKeyB, reinterpret_cast(prioKeyB.BeginReading()), CURVE25519_KEY_LEN_HEX);
+ prio_rv = PublicKey_import_hex(&sPublicKeyB,
+ reinterpret_cast(prioKeyB.BeginReading()),
+ CURVE25519_KEY_LEN_HEX);
if (prio_rv != SECSuccess) {
aRv.Throw(NS_ERROR_UNEXPECTED);
- return nullptr;
+ return;
}
}
- RefPtr promise = Promise::Create(global, aRv);
-
bool dataItems[] = {
- aPrioParams.mStartupCrashDetected,
- aPrioParams.mSafeModeUsage,
- aPrioParams.mBrowserIsUserDefault
+ aPrioParams.mBrowserIsUserDefault,
+ aPrioParams.mNewTabPageEnabled,
+ aPrioParams.mPdfViewerUsed,
};
- PrioConfig prioConfig = PrioConfig_new(mozilla::ArrayLength(dataItems), sPublicKeyA, sPublicKeyB, reinterpret_cast(aBatchID.BeginReading()), aBatchID.Length());
+ PrioConfig prioConfig = PrioConfig_new(mozilla::ArrayLength(dataItems),
+ sPublicKeyA,
+ sPublicKeyB,
+ reinterpret_cast(aBatchID.BeginReading()),
+ aBatchID.Length());
if (!prioConfig) {
- promise->MaybeReject(NS_ERROR_FAILURE);
- return promise.forget();
+ aRv.Throw(NS_ERROR_FAILURE);
+ return;
}
auto configGuard = MakeScopeExit([&] {
@@ -114,50 +127,54 @@ PrioEncoder::Encode(GlobalObject& aGlobal, const nsCString& aBatchID, const Prio
unsigned char* forServerB = nullptr;
unsigned int lenB = 0;
- prio_rv = PrioClient_encode(prioConfig, dataItems, &forServerA, &lenA, &forServerB, &lenB);
-
- // Package the data into the dictionary
- PrioEncodedData data;
+ prio_rv = PrioClient_encode(prioConfig,
+ dataItems,
+ &forServerA,
+ &lenA,
+ &forServerB,
+ &lenB);
nsTArray arrayForServerA;
nsTArray arrayForServerB;
- if (!arrayForServerA.AppendElements(reinterpret_cast(forServerA), lenA, fallible)) {
- promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
- return promise.forget();
+ if (!arrayForServerA.AppendElements(reinterpret_cast(forServerA),
+ lenA,
+ fallible)) {
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
}
free(forServerA);
- if (!arrayForServerB.AppendElements(reinterpret_cast(forServerB), lenB, fallible)) {
- promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
- return promise.forget();
+ if (!arrayForServerB.AppendElements(reinterpret_cast(forServerB),
+ lenB,
+ fallible)) {
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return ;
}
free(forServerB);
+ if (prio_rv != SECSuccess) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return;
+ }
+
JS::Rooted valueA(aGlobal.Context());
if (!ToJSValue(aGlobal.Context(), TypedArrayCreator(arrayForServerA), &valueA)) {
- promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
- return promise.forget();
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
}
- data.mA.Construct().Init(&valueA.toObject());
+
+ aData.mA.Construct().Init(&valueA.toObject());
JS::Rooted valueB(aGlobal.Context());
if (!ToJSValue(aGlobal.Context(), TypedArrayCreator(arrayForServerB), &valueB)) {
- promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
- return promise.forget();
- }
- data.mB.Construct().Init(&valueB.toObject());
-
- if (prio_rv != SECSuccess) {
- promise->MaybeReject(NS_ERROR_FAILURE);
- return promise.forget();
+ aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
}
- promise->MaybeResolve(data);
-
- return promise.forget();
+ aData.mB.Construct().Init(&valueB.toObject());
}
bool
diff --git a/dom/prio/PrioEncoder.h b/dom/prio/PrioEncoder.h
index 53055a250ac3..faa3beef76c2 100644
--- a/dom/prio/PrioEncoder.h
+++ b/dom/prio/PrioEncoder.h
@@ -21,8 +21,12 @@ class PrioEncoder
public:
NS_INLINE_DECL_REFCOUNTING(PrioEncoder)
- static already_AddRefed
- Encode(GlobalObject& aGlobal, const nsCString& aBatchID, const PrioParams& aPrioParams, ErrorResult& aRv);
+ static
+ void Encode(GlobalObject& aGlobal,
+ const nsCString& aBatchID,
+ const PrioParams& aPrioParams,
+ RootedDictionary& aData,
+ ErrorResult& aRv);
private:
PrioEncoder();
diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp
index 7f0d1ff4119f..53dc74bee4c9 100644
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -381,10 +381,15 @@ ParseCacheIRStub(ICStub* stub)
case CacheOp::Int32BitAndResult:
case CacheOp::Int32LeftShiftResult:
case CacheOp::Int32RightShiftResult:
- case CacheOp::Int32URightShiftResult:
case CacheOp::Int32NotResult:
case CacheOp::Int32NegationResult:
return MIRType::Int32;
+ // Int32URightShiftResult may return a double under some
+ // circumstances.
+ case CacheOp::Int32URightShiftResult:
+ reader.skip(); // Skip over lhs
+ reader.skip(); // Skip over rhs
+ return reader.readByte() == 0 ? MIRType::Int32 : MIRType::Double;
case CacheOp::LoadValueResult:
return MIRType::Value;
default:
diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp
index a225b2884e90..35a975b559f1 100644
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -4252,10 +4252,8 @@ nsFlexContainerFrame::SizeItemInCrossAxis(
// Tentatively store the child's desired content-box cross-size.
// Note that childDesiredSize is the border-box size, so we have to
// subtract border & padding to get the content-box size.
- // (Note that at this point in the code, we know our cross axis is vertical,
- // so we don't bother with making aAxisTracker pick the cross-axis component
- // for us.)
- nscoord crossAxisBorderPadding = aItem.GetBorderPadding().TopBottom();
+ nscoord crossAxisBorderPadding =
+ aItem.GetBorderPaddingSizeInAxis(aAxisTracker.GetCrossAxis());
if (reflowResult.BSize() < crossAxisBorderPadding) {
// Child's requested size isn't large enough for its border/padding!
// This is OK for the trivial nsFrame::Reflow() impl, but other frame
diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-writing-mode-016-ref.html b/layout/reftests/w3c-css/submitted/flexbox/flexbox-writing-mode-016-ref.html
new file mode 100644
index 000000000000..c3a223389d04
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-writing-mode-016-ref.html
@@ -0,0 +1,136 @@
+
+
+
+
+ CSS Reftest Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/w3c-css/submitted/flexbox/flexbox-writing-mode-016.html b/layout/reftests/w3c-css/submitted/flexbox/flexbox-writing-mode-016.html
new file mode 100644
index 000000000000..94c732358351
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/flexbox/flexbox-writing-mode-016.html
@@ -0,0 +1,144 @@
+
+
+
+
+
+ CSS Test: Testing auto-sized flex containers
+ with various 'writing-mode' values
+ and various padding amounts on flex items.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/w3c-css/submitted/flexbox/reftest.list b/layout/reftests/w3c-css/submitted/flexbox/reftest.list
index 198a5ce0ecbb..8fb6e6ba651d 100644
--- a/layout/reftests/w3c-css/submitted/flexbox/reftest.list
+++ b/layout/reftests/w3c-css/submitted/flexbox/reftest.list
@@ -261,6 +261,7 @@ fails == flexbox-min-height-auto-002b.html flexbox-min-height-auto-002-ref.html
== flexbox-writing-mode-013.html flexbox-writing-mode-013-ref.html
== flexbox-writing-mode-014.html flexbox-writing-mode-014-ref.html
== flexbox-writing-mode-015.html flexbox-writing-mode-015-ref.html
+== flexbox-writing-mode-016.html flexbox-writing-mode-016-ref.html
# Single-line size clamping
== flexbox-single-line-clamp-1.html flexbox-single-line-clamp-1-ref.html
diff --git a/layout/xul/nsXULTooltipListener.cpp b/layout/xul/nsXULTooltipListener.cpp
index 98dc96671320..5a6b1e4994a4 100644
--- a/layout/xul/nsXULTooltipListener.cpp
+++ b/layout/xul/nsXULTooltipListener.cpp
@@ -589,8 +589,8 @@ nsXULTooltipListener::FindTooltip(nsIContent* aTarget, nsIContent** aTooltip)
return NS_OK;
}
- // non-XUL documents should just use the default tooltip
- if (!document->IsXULDocument()) {
+ // non-XUL elements should just use the default tooltip
+ if (!aTarget->IsXULElement()) {
nsIPopupContainer* popupContainer =
nsIPopupContainer::GetPopupContainer(document->GetShell());
NS_ENSURE_STATE(popupContainer);
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 0c0b38737207..106ec5d1441c 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5895,3 +5895,8 @@ pref("dom.datatransfer.mozAtAPIs", false);
#else
pref("dom.datatransfer.mozAtAPIs", true);
#endif
+
+// Whether or not Prio is supported on this platform.
+#ifdef MOZ_LIBPRIO
+pref("prio.enabled", false);
+#endif
diff --git a/python/mozbuild/mozbuild/backend/tup.py b/python/mozbuild/mozbuild/backend/tup.py
index 8691c4ba4269..2163f7215c4f 100644
--- a/python/mozbuild/mozbuild/backend/tup.py
+++ b/python/mozbuild/mozbuild/backend/tup.py
@@ -701,11 +701,26 @@ class TupBackend(CommonBackend):
fh.write('IDL_PARSER_DIR = $(topsrcdir)/xpcom/idl-parser\n')
fh.write('IDL_PARSER_CACHE_DIR = $(MOZ_OBJ_ROOT)/xpcom/idl-parser/xpidl\n')
- # Run 'tup init' if necessary.
- if not os.path.exists(mozpath.join(self.environment.topsrcdir, ".tup")):
+ # Run 'tup init' if necessary, attempting to cover both the objdir
+ # and srcdir.
+ tup_base_dir = os.path.commonprefix([self.environment.topsrcdir,
+ self.environment.topobjdir])
+ if tup_base_dir != self.environment.topsrcdir:
+ if os.path.isdir(mozpath.join(self.environment.topsrcdir, '.tup')):
+ print("Found old tup root at '%s', removing..." %
+ mozpath.join(self.environment.topsrcdir, '.tup'))
+ shutil.rmtree(mozpath.join(self.environment.topsrcdir, '.tup'))
+ if not os.path.isdir(mozpath.join(tup_base_dir, '.tup')):
+ if tup_base_dir != self.environment.topsrcdir:
+ # Ask the user to figure out where to run 'tup init' before
+ # continuing.
+ raise Exception("Please run `tup init --no-sync` in a common "
+ "ancestor directory of your objdir and srcdir, possibly "
+ "%s. To reduce file scanning overhead, this directory "
+ "should contain the fewest files possible that are not "
+ "necessary for this build." % tup_base_dir)
tup = self.environment.substs.get('TUP', 'tup')
- self._cmd.run_process(cwd=self.environment.topsrcdir, log_name='tup', args=[tup, 'init', '--no-sync'])
-
+ self._cmd.run_process(cwd=tup_base_dir, log_name='tup', args=[tup, 'init', '--no-sync'])
def _get_cargo_flags(self, obj):
cargo_flags = ['--build-plan', '-Z', 'unstable-options']
diff --git a/toolkit/components/places/UnifiedComplete.js b/toolkit/components/places/UnifiedComplete.js
index 08a2c0452366..37e5dc23da9b 100644
--- a/toolkit/components/places/UnifiedComplete.js
+++ b/toolkit/components/places/UnifiedComplete.js
@@ -263,8 +263,7 @@ const QUERYINDEX_ORIGIN_FRECENCY = 3;
// `WITH` clause for the autofill queries. autofill_frecency_threshold.value is
// the mean of all moz_origins.frecency values + stddevMultiplier * one standard
// deviation. This is inlined directly in the SQL (as opposed to being a custom
-// Sqlite function for example) in order to be as efficient as possible. The
-// MAX() is to make sure that places with <= 0 frecency are never autofilled.
+// Sqlite function for example) in order to be as efficient as possible.
const SQL_AUTOFILL_WITH = `
WITH
frecency_stats(count, sum, squares) AS (
@@ -274,13 +273,13 @@ const SQL_AUTOFILL_WITH = `
CAST((SELECT IFNULL(value, 0.0) FROM moz_meta WHERE key = "origin_frecency_sum_of_squares") AS REAL)
),
autofill_frecency_threshold(value) AS (
- SELECT MAX(1,
+ SELECT
CASE count
WHEN 0 THEN 0.0
WHEN 1 THEN sum
ELSE (sum / count) + (:stddevMultiplier * sqrt((squares - ((sum * sum) / count)) / count))
END
- ) FROM frecency_stats
+ FROM frecency_stats
)
`;
@@ -357,7 +356,8 @@ function urlQuery(conditions1, conditions2) {
id
FROM moz_places
WHERE rev_host = :revHost
- AND frecency >= ${SQL_AUTOFILL_FRECENCY_THRESHOLD}
+ AND MAX(frecency, 0) >= ${SQL_AUTOFILL_FRECENCY_THRESHOLD}
+ AND hidden = 0
${conditions1}
UNION ALL
SELECT :query_type,
@@ -368,7 +368,8 @@ function urlQuery(conditions1, conditions2) {
id
FROM moz_places
WHERE rev_host = :revHost || 'www.'
- AND frecency >= ${SQL_AUTOFILL_FRECENCY_THRESHOLD}
+ AND MAX(frecency, 0) >= ${SQL_AUTOFILL_FRECENCY_THRESHOLD}
+ AND hidden = 0
${conditions2}
ORDER BY frecency DESC, id DESC
LIMIT 1 `;
diff --git a/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js b/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js
index f03606062536..5e7a9bad438a 100644
--- a/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js
+++ b/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js
@@ -671,4 +671,62 @@ function addAutofillTasks(origins) {
await cleanup();
});
+
+ // Bookmark a page and then clear history. The bookmarked origin/URL should
+ // be autofilled even though its frecency is <= 0 since the autofill threshold
+ // is 0.
+ add_task(async function zeroThreshold() {
+ await addBookmark({
+ uri: "http://" + url,
+ });
+
+ await PlacesUtils.history.clear();
+
+ // Make sure the place's frecency is <= 0. (It will be reset to -1 on the
+ // history.clear() above, and then on idle it will be reset to 0. xpcshell
+ // tests disable the idle service, so in practice it should always be -1,
+ // but in order to avoid possible intermittent failures in the future, don't
+ // assume that.)
+ let placeFrecency =
+ await PlacesTestUtils.fieldInDB("http://" + url, "frecency");
+ Assert.ok(placeFrecency <= 0);
+
+ // Make sure the origin's frecency is 0.
+ let db = await PlacesUtils.promiseDBConnection();
+ let rows = await db.execute(`
+ SELECT frecency FROM moz_origins WHERE host = '${host}';
+ `);
+ Assert.equal(rows.length, 1);
+ let originFrecency = rows[0].getResultByIndex(0);
+ Assert.equal(originFrecency, 0);
+
+ // Make sure the autofill threshold is 0.
+ rows = await db.execute(`
+ SELECT
+ IFNULL((SELECT value FROM moz_meta WHERE key = "origin_frecency_count"), 0),
+ IFNULL((SELECT value FROM moz_meta WHERE key = "origin_frecency_sum"), 0),
+ IFNULL((SELECT value FROM moz_meta WHERE key = "origin_frecency_sum_of_squares"), 0)
+ `);
+ let count = rows[0].getResultByIndex(0);
+ let sum = rows[0].getResultByIndex(1);
+ let squares = rows[0].getResultByIndex(2);
+ Assert.equal(count, 0);
+ Assert.equal(sum, 0);
+ Assert.equal(squares, 0);
+
+ await check_autocomplete({
+ search,
+ autofilled: url,
+ completed: "http://" + url,
+ matches: [
+ {
+ value: url,
+ comment,
+ style: ["autofill", "heuristic"],
+ },
+ ],
+ });
+
+ await cleanup();
+ });
}
diff --git a/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js b/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js
deleted file mode 100644
index 37e36a0c5191..000000000000
--- a/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* 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/. */
-
-// Ensure inline autocomplete doesn't return zero frecency pages.
-
-add_task(async function test_zero_frec_domain() {
- info("Searching for zero frecency domain should not autoFill it");
- await PlacesTestUtils.addVisits({
- uri: NetUtil.newURI("http://mozilla.org/framed_link/"),
- transition: TRANSITION_FRAMED_LINK,
- });
- await check_autocomplete({
- search: "moz",
- autofilled: "moz",
- completed: "moz",
- });
- await cleanup();
-});
-
-add_task(async function test_zero_frec_url() {
- info("Searching for zero frecency url should not autoFill it");
- await PlacesTestUtils.addVisits({
- uri: NetUtil.newURI("http://mozilla.org/framed_link/"),
- transition: TRANSITION_FRAMED_LINK,
- });
- await check_autocomplete({
- search: "mozilla.org/f",
- autofilled: "mozilla.org/f",
- completed: "mozilla.org/f",
- });
- await cleanup();
-});
diff --git a/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini b/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini
index 7b7a532892a8..a0b037069cdf 100644
--- a/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini
+++ b/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini
@@ -56,4 +56,3 @@ skip-if = !sync
[test_trimming.js]
[test_visit_url.js]
[test_word_boundary_search.js]
-[test_zero_frecency.js]
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index 68cb988e4cf6..146c996e1c77 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -12834,9 +12834,9 @@
},
"NUMBER_OF_PROFILES": {
"record_in_processes": ["main", "content"],
- "alert_emails": ["amarchesini@mozilla.com"],
- "expires_in_version": "59",
- "bug_numbers": [1296606],
+ "alert_emails": ["dtownsend@mozilla.com"],
+ "expires_in_version": "70",
+ "bug_numbers": [1296606, 1488881],
"kind": "count",
"description": "Number of named browser profiles for the current user, as reported by the profile service at startup."
},
diff --git a/toolkit/components/telemetry/build_scripts/README.md b/toolkit/components/telemetry/build_scripts/README.md
new file mode 100644
index 000000000000..4823580735a0
--- /dev/null
+++ b/toolkit/components/telemetry/build_scripts/README.md
@@ -0,0 +1,5 @@
+# Telemetry Registries Parsers
+This package exports the parsers for Mozilla's probes registries. These registry file contains the definitions for the different probes (i.e. [scalars](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/scalars.html), [histograms](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/histograms.html) and [events](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/events.html)) that can be used to collect data.
+
+# License
+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/.
diff --git a/toolkit/components/telemetry/build_scripts/gen_event_data.py b/toolkit/components/telemetry/build_scripts/gen_event_data.py
index 97dce90688f7..ca95903c85ff 100644
--- a/toolkit/components/telemetry/build_scripts/gen_event_data.py
+++ b/toolkit/components/telemetry/build_scripts/gen_event_data.py
@@ -7,8 +7,12 @@
from __future__ import print_function
from collections import OrderedDict
-from parsers.shared_telemetry_utils import StringTable, static_assert, ParserError
-from parsers import parse_events
+from python_mozparsers.shared_telemetry_utils import (
+ StringTable,
+ static_assert,
+ ParserError
+)
+from python_mozparsers import parse_events
import json
import sys
diff --git a/toolkit/components/telemetry/build_scripts/gen_event_enum.py b/toolkit/components/telemetry/build_scripts/gen_event_enum.py
index 7b1f7d2fb76a..b1dc840219cc 100644
--- a/toolkit/components/telemetry/build_scripts/gen_event_enum.py
+++ b/toolkit/components/telemetry/build_scripts/gen_event_enum.py
@@ -7,8 +7,8 @@
# The events are defined in files provided as command-line arguments.
from __future__ import print_function
-from parsers.shared_telemetry_utils import ParserError
-from parsers import parse_events
+from python_mozparsers.shared_telemetry_utils import ParserError
+from python_mozparsers import parse_events
import sys
diff --git a/toolkit/components/telemetry/build_scripts/gen_histogram_data.py b/toolkit/components/telemetry/build_scripts/gen_histogram_data.py
index 76a9cfaa6525..bc25738ef397 100644
--- a/toolkit/components/telemetry/build_scripts/gen_histogram_data.py
+++ b/toolkit/components/telemetry/build_scripts/gen_histogram_data.py
@@ -6,8 +6,12 @@
# in a file provided as a command-line argument.
from __future__ import print_function
-from parsers.shared_telemetry_utils import StringTable, static_assert, ParserError
-from parsers import parse_histograms
+from python_mozparsers.shared_telemetry_utils import (
+ StringTable,
+ static_assert,
+ ParserError
+)
+from python_mozparsers import parse_histograms
import sys
import buildconfig
diff --git a/toolkit/components/telemetry/build_scripts/gen_histogram_enum.py b/toolkit/components/telemetry/build_scripts/gen_histogram_enum.py
index 75c4f7bcc3b7..3a122128623f 100644
--- a/toolkit/components/telemetry/build_scripts/gen_histogram_enum.py
+++ b/toolkit/components/telemetry/build_scripts/gen_histogram_enum.py
@@ -13,8 +13,8 @@
# The histograms are defined in files provided as command-line arguments.
from __future__ import print_function
-from parsers.shared_telemetry_utils import ParserError
-from parsers import parse_histograms
+from python_mozparsers.shared_telemetry_utils import ParserError
+from python_mozparsers import parse_histograms
import itertools
import sys
diff --git a/toolkit/components/telemetry/build_scripts/gen_histogram_phf.py b/toolkit/components/telemetry/build_scripts/gen_histogram_phf.py
index 8918967f5e5c..e177d4211df2 100644
--- a/toolkit/components/telemetry/build_scripts/gen_histogram_phf.py
+++ b/toolkit/components/telemetry/build_scripts/gen_histogram_phf.py
@@ -3,12 +3,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import print_function
-from parsers.shared_telemetry_utils import ParserError
+from python_mozparsers.shared_telemetry_utils import ParserError
from perfecthash import PerfectHash
PHFSIZE = 512
-from parsers import parse_histograms
+from python_mozparsers import parse_histograms
import sys
import buildconfig
diff --git a/toolkit/components/telemetry/build_scripts/gen_process_data.py b/toolkit/components/telemetry/build_scripts/gen_process_data.py
index 8bfe90fdf0c5..7ca5e48f5df4 100644
--- a/toolkit/components/telemetry/build_scripts/gen_process_data.py
+++ b/toolkit/components/telemetry/build_scripts/gen_process_data.py
@@ -6,7 +6,7 @@
# in a file provided as a command-line argument.
from __future__ import print_function
-from parsers.shared_telemetry_utils import ParserError, load_yaml_file
+from python_mozparsers.shared_telemetry_utils import ParserError, load_yaml_file
import sys
import collections
diff --git a/toolkit/components/telemetry/build_scripts/gen_process_enum.py b/toolkit/components/telemetry/build_scripts/gen_process_enum.py
index c70326b2b003..900ca425c3e0 100644
--- a/toolkit/components/telemetry/build_scripts/gen_process_enum.py
+++ b/toolkit/components/telemetry/build_scripts/gen_process_enum.py
@@ -6,7 +6,7 @@
# in a file provided as a command-line argument.
from __future__ import print_function
-from parsers.shared_telemetry_utils import ParserError, load_yaml_file
+from python_mozparsers.shared_telemetry_utils import ParserError, load_yaml_file
import sys
import collections
diff --git a/toolkit/components/telemetry/build_scripts/gen_scalar_data.py b/toolkit/components/telemetry/build_scripts/gen_scalar_data.py
index e86b30ecfdc6..8b0ef53e7473 100644
--- a/toolkit/components/telemetry/build_scripts/gen_scalar_data.py
+++ b/toolkit/components/telemetry/build_scripts/gen_scalar_data.py
@@ -7,8 +7,12 @@
from __future__ import print_function
from collections import OrderedDict
-from parsers.shared_telemetry_utils import StringTable, static_assert, ParserError
-from parsers import parse_scalars
+from python_mozparsers.shared_telemetry_utils import (
+ StringTable,
+ static_assert,
+ ParserError
+)
+from python_mozparsers import parse_scalars
import json
import sys
diff --git a/toolkit/components/telemetry/build_scripts/gen_scalar_enum.py b/toolkit/components/telemetry/build_scripts/gen_scalar_enum.py
index 4ae2ceeb6ba2..0c088a6f03db 100644
--- a/toolkit/components/telemetry/build_scripts/gen_scalar_enum.py
+++ b/toolkit/components/telemetry/build_scripts/gen_scalar_enum.py
@@ -8,8 +8,8 @@
# The scalars are defined in files provided as command-line arguments.
from __future__ import print_function
-from parsers.shared_telemetry_utils import ParserError
-from parsers import parse_scalars
+from python_mozparsers.shared_telemetry_utils import ParserError
+from python_mozparsers import parse_scalars
import sys
diff --git a/toolkit/components/telemetry/build_scripts/parsers/__init__.py b/toolkit/components/telemetry/build_scripts/python_mozparsers/__init__.py
similarity index 100%
rename from toolkit/components/telemetry/build_scripts/parsers/__init__.py
rename to toolkit/components/telemetry/build_scripts/python_mozparsers/__init__.py
diff --git a/toolkit/components/telemetry/build_scripts/parsers/parse_events.py b/toolkit/components/telemetry/build_scripts/python_mozparsers/parse_events.py
similarity index 100%
rename from toolkit/components/telemetry/build_scripts/parsers/parse_events.py
rename to toolkit/components/telemetry/build_scripts/python_mozparsers/parse_events.py
diff --git a/toolkit/components/telemetry/build_scripts/parsers/parse_histograms.py b/toolkit/components/telemetry/build_scripts/python_mozparsers/parse_histograms.py
similarity index 100%
rename from toolkit/components/telemetry/build_scripts/parsers/parse_histograms.py
rename to toolkit/components/telemetry/build_scripts/python_mozparsers/parse_histograms.py
diff --git a/toolkit/components/telemetry/build_scripts/parsers/parse_scalars.py b/toolkit/components/telemetry/build_scripts/python_mozparsers/parse_scalars.py
similarity index 100%
rename from toolkit/components/telemetry/build_scripts/parsers/parse_scalars.py
rename to toolkit/components/telemetry/build_scripts/python_mozparsers/parse_scalars.py
diff --git a/toolkit/components/telemetry/build_scripts/parsers/shared_telemetry_utils.py b/toolkit/components/telemetry/build_scripts/python_mozparsers/shared_telemetry_utils.py
similarity index 100%
rename from toolkit/components/telemetry/build_scripts/parsers/shared_telemetry_utils.py
rename to toolkit/components/telemetry/build_scripts/python_mozparsers/shared_telemetry_utils.py
diff --git a/toolkit/components/telemetry/build_scripts/setup.py b/toolkit/components/telemetry/build_scripts/setup.py
new file mode 100644
index 000000000000..b6362661cdb9
--- /dev/null
+++ b/toolkit/components/telemetry/build_scripts/setup.py
@@ -0,0 +1,30 @@
+# 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/.
+
+from setuptools import setup, find_packages
+
+VERSION = '1.0.0'
+
+with open("README.md", "r") as fh:
+ long_description = fh.read()
+
+setup(
+ author='Mozilla Telemetry Team',
+ author_email='telemetry-client-dev@mozilla.com',
+ url=('https://firefox-source-docs.mozilla.org/'
+ 'toolkit/components/telemetry/telemetry/collection/index.html'),
+ name='python_mozparsers',
+ description='Shared parsers for the Telemetry probe regitries.',
+ long_description=long_description,
+ long_description_content_type="text/markdown",
+ license='MPL 2.0',
+ packages=find_packages(),
+ version=VERSION,
+ classifiers=[
+ 'Topic :: Software Development :: Build Tools',
+ 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
+ 'Programming Language :: Python :: 2.7',
+ ],
+ keywords=['mozilla', 'telemetry', 'parsers'],
+)
diff --git a/toolkit/components/telemetry/docs/data/main-ping.rst b/toolkit/components/telemetry/docs/data/main-ping.rst
index eab537810ec0..7effba27023b 100644
--- a/toolkit/components/telemetry/docs/data/main-ping.rst
+++ b/toolkit/components/telemetry/docs/data/main-ping.rst
@@ -677,6 +677,24 @@ Structure:
...
],
+Prio
+----
+This section contains experimental data encoded with a basic version of the Prio system for private aggregation.
+See `the Prio paper `_ and `the libprio Github repo `_
+for more information.
+
+Prio splits data packets into two "shares", signed for different servers that will do the decryption+decoding and
+aggregation. We call these "Server A" and "Server B", represented as `a` and `b` keys in `payload.prio`.
+
+Structure:
+
+.. code-block:: js
+ "prio": {
+ a: ... // Uint8Array containing data signed for Server A
+ b: ... // Uint8Array containing data signed for Server B
+ }
+
+
Version History
---------------
diff --git a/toolkit/components/telemetry/pings/TelemetrySession.jsm b/toolkit/components/telemetry/pings/TelemetrySession.jsm
index 7d19c385c0a0..824f738d9662 100644
--- a/toolkit/components/telemetry/pings/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/pings/TelemetrySession.jsm
@@ -87,6 +87,9 @@ const TOPIC_CYCLE_COLLECTOR_BEGIN = "cycle-collector-begin";
// How long to wait in millis for all the child memory reports to come in
const TOTAL_MEMORY_COLLECTOR_TIMEOUT = 200;
+// Control whether Telemetry data should be encrypted with Prio.
+const PRIO_ENABLED_PREF = "prio.enabled";
+
var gLastMemoryPoll = null;
var gWasDebuggerAttached = false;
@@ -1168,6 +1171,11 @@ var Impl = {
payloadObj.info = info;
+ // Collect Prio-encoded measurements.
+ if (Services.prefs.getBoolPref(PRIO_ENABLED_PREF, false)) {
+ payloadObj.prio = protect(() => this._prioEncode());
+ }
+
// Add extended set measurements for chrome process.
if (Telemetry.canRecordExtended) {
payloadObj.slowSQL = protect(() => Telemetry.slowSQL);
@@ -1947,4 +1955,44 @@ var Impl = {
this._newProfilePingSent = true;
return TelemetryStorage.saveSessionData(this._getSessionDataObject());
},
+
+ /**
+ * Encodes data for experimental Prio pilot project.
+ *
+ * @return {Object} An object containing Prio-encoded data.
+ */
+ _prioEncode() {
+ // First, map the Telemetry histogram names to the params PrioEncoder.encode() expects.
+ const prioEncodedHistograms = {
+ "BROWSER_IS_USER_DEFAULT": "browserIsUserDefault",
+ "NEWTAB_PAGE_ENABLED": "newTabPageEnabled",
+ "PDF_VIEWER_USED": "pdfViewerUsed",
+ };
+
+ // Build list of Prio parameters, using the first value recorded in each histogram.
+ let prioParams = {};
+ for (const [histogramName, prioName] of Object.entries(prioEncodedHistograms)) {
+ try {
+ const histogram = Telemetry.getHistogramById(histogramName);
+ const firstCount = Boolean(histogram.snapshot().sum);
+ prioParams[prioName] = firstCount;
+
+ } catch (ex) {
+ this._log.error(ex);
+ }
+ }
+
+ // Prio encode the data and add to payload.
+ const batchID = Policy.now();
+
+ let prioEncodedData;
+
+ try {
+ prioEncodedData = PrioEncoder.encode(batchID, prioParams);
+ } catch (ex) {
+ this._log.error(ex);
+ }
+
+ return prioEncodedData;
+ },
};
diff --git a/toolkit/components/telemetry/tests/python/test_histogramtools_non_strict.py b/toolkit/components/telemetry/tests/python/test_histogramtools_non_strict.py
index 193d84659096..00d73cc6e68c 100644
--- a/toolkit/components/telemetry/tests/python/test_histogramtools_non_strict.py
+++ b/toolkit/components/telemetry/tests/python/test_histogramtools_non_strict.py
@@ -13,7 +13,7 @@ sys.path.append(TELEMETRY_ROOT_PATH)
# The parsers live in a subdirectory of "build_scripts", account for that.
# NOTE: if the parsers are moved, this logic will need to be updated.
sys.path.append(path.join(TELEMETRY_ROOT_PATH, "build_scripts"))
-from parsers import parse_histograms # noqa: E402
+from python_mozparsers import parse_histograms # noqa: E402
def load_histogram(histograms):
diff --git a/toolkit/components/telemetry/tests/python/test_histogramtools_strict.py b/toolkit/components/telemetry/tests/python/test_histogramtools_strict.py
index 2c557667339c..35a4fcca824b 100644
--- a/toolkit/components/telemetry/tests/python/test_histogramtools_strict.py
+++ b/toolkit/components/telemetry/tests/python/test_histogramtools_strict.py
@@ -13,8 +13,8 @@ sys.path.append(TELEMETRY_ROOT_PATH)
# The parsers live in a subdirectory of "build_scripts", account for that.
# NOTE: if the parsers are moved, this logic will need to be updated.
sys.path.append(path.join(TELEMETRY_ROOT_PATH, "build_scripts"))
-from parsers.shared_telemetry_utils import ParserError
-from parsers import parse_histograms
+from python_mozparsers.shared_telemetry_utils import ParserError
+from python_mozparsers import parse_histograms
class TestParser(unittest.TestCase):
diff --git a/toolkit/components/telemetry/tests/python/test_parse_scalars.py b/toolkit/components/telemetry/tests/python/test_parse_scalars.py
index ce3a22821d49..57938d01040d 100644
--- a/toolkit/components/telemetry/tests/python/test_parse_scalars.py
+++ b/toolkit/components/telemetry/tests/python/test_parse_scalars.py
@@ -13,8 +13,8 @@ sys.path.append(TELEMETRY_ROOT_PATH)
# The parsers live in a subdirectory of "build_scripts", account for that.
# NOTE: if the parsers are moved, this logic will need to be updated.
sys.path.append(path.join(TELEMETRY_ROOT_PATH, "build_scripts"))
-from parsers.shared_telemetry_utils import ParserError
-from parsers import parse_scalars
+from python_mozparsers.shared_telemetry_utils import ParserError
+from python_mozparsers import parse_scalars
def load_scalar(scalar):
diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
index bab5b1de5926..da30473ff62f 100644
--- a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
@@ -403,6 +403,11 @@ function checkPayload(payload, reason, successfulPings) {
Assert.ok("processes" in payload, "The payload must have a processes section.");
Assert.ok("parent" in payload.processes, "There must be at least a parent process.");
+
+ if (Services.prefs.getBoolPref("prio.enabled", false)) {
+ Assert.ok("prio" in payload, "The payload must have a prio section.");
+ }
+
checkScalars(payload.processes);
}
diff --git a/toolkit/moz.configure b/toolkit/moz.configure
index 85551e7739d9..8685d8cc46ce 100644
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -1070,10 +1070,12 @@ set_define('MOZ_LAUNCHER_PROCESS', launcher)
# Prio
# ==============================================================
-@depends(c_compiler)
-def libprio(info):
+@depends(c_compiler, target)
+def libprio(info, target):
if info:
- if info.type in ('msvc',):
+ # TODO - re-enable Windows when bug 1489691 is fixed.
+ # Note that we will probably never support MSVC however.
+ if info.type in ('msvc',) or target.os in ('WINNT',):
return None
return True
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index 70370e68669d..1a34e1f60eb4 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -1176,8 +1176,12 @@ GetCachedHash(HKEY rootKey, const nsAString ®Path, const nsAString &path,
#endif
+// Compatibility Mode (aUseCompatibilityMode) outputs hashes that are what this
+// function has historically returned. The new default is to output hashes that
+// are consistent with those generated by the installer.
nsresult
-nsXREDirProvider::GetInstallHash(nsAString & aPathHash)
+nsXREDirProvider::GetInstallHash(nsAString & aPathHash,
+ bool aUseCompatibilityMode /* = false */)
{
nsCOMPtr updRoot;
nsCOMPtr appFile;
@@ -1191,6 +1195,8 @@ nsXREDirProvider::GetInstallHash(nsAString & aPathHash)
rv = updRoot->GetPath(appDirPath);
NS_ENSURE_SUCCESS(rv, rv);
+ aPathHash.Truncate();
+
#ifdef XP_WIN
// Figure out where we should check for a cached hash value. If the
// application doesn't have the nsXREAppData vendor value defined check
@@ -1216,13 +1222,17 @@ nsXREDirProvider::GetInstallHash(nsAString & aPathHash)
void* buffer = appDirPath.BeginWriting();
uint32_t length = appDirPath.Length() * sizeof(nsAutoString::char_type);
uint64_t hash = CityHash64(static_cast(buffer), length);
- aPathHash.AppendInt((int)(hash >> 32), 16);
- aPathHash.AppendInt((int)hash, 16);
- // The installer implementation writes the registry values that were checked
- // in the previous block for this value in uppercase and since it is an
- // option to have a case sensitive file system on Windows this value must
- // also be in uppercase.
- ToUpperCase(aPathHash);
+ if (aUseCompatibilityMode) {
+ aPathHash.AppendInt((int)(hash >> 32), 16);
+ aPathHash.AppendInt((int)hash, 16);
+ // The installer implementation writes the registry values that were checked
+ // in the previous block for this value in uppercase and since it is an
+ // option to have a case sensitive file system on Windows this value must
+ // also be in uppercase.
+ ToUpperCase(aPathHash);
+ } else {
+ aPathHash.AppendPrintf("%" PRIX64, hash);
+ }
return NS_OK;
}
@@ -1275,7 +1285,7 @@ nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
#elif XP_WIN
nsAutoString pathHash;
- rv = GetInstallHash(pathHash);
+ rv = GetInstallHash(pathHash, true);
NS_ENSURE_SUCCESS(rv, rv);
// As a last ditch effort, get the local app data directory and if a vendor
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
index b57fe887f9f3..1a9de63e741e 100644
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -72,7 +72,8 @@ public:
/**
* Get a hash for the install directory.
*/
- nsresult GetInstallHash(nsAString & aPathHash);
+ nsresult GetInstallHash(nsAString & aPathHash,
+ bool aUseCompatibilityMode = false);
/**
* Get the directory under which update directory is created.
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
index de27179d2b2f..2b3a5ab96814 100644
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
@@ -55,6 +55,7 @@ module.exports = {
// Specific to Firefox (Chrome code only).
"PlacesObservers": false,
"PlacesWeakCallbackWrapper": false,
+ "PrioEncoder": false,
// Specific to Firefox (Chrome code only).
"SharedArrayBuffer": false,
"SimpleGestureEvent": false,