mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Merge autoland to mozilla-central. a=merge
This commit is contained in:
commit
2b539c7b7e
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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 = "";
|
||||
|
@ -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 {
|
||||
|
@ -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: [],
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -154,7 +154,7 @@
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<span id="branding">&webPaymentsBranding.label;</span>
|
||||
<span class="branding">&webPaymentsBranding.label;</span>
|
||||
<button id="cancel">&cancelPaymentButton.label;</button>
|
||||
<button id="pay"
|
||||
class="primary"
|
||||
@ -198,6 +198,7 @@
|
||||
<completion-error-page id="completion-timeout-error" class="illustrated"
|
||||
data-page-title="&timeoutErrorPage.title;"
|
||||
data-suggestion-heading="&timeoutErrorPage.suggestionHeading;"
|
||||
data-branding-label="&webPaymentsBranding.label;"
|
||||
data-done-button-label="&timeoutErrorPage.doneButton.label;"
|
||||
hidden="hidden"></completion-error-page>
|
||||
<completion-error-page id="completion-fail-error" class="illustrated"
|
||||
@ -205,6 +206,7 @@
|
||||
data-suggestion-heading="&failErrorPage.suggestionHeading;"
|
||||
data-suggestion-1="&failErrorPage.suggestion1;"
|
||||
data-suggestion-2="&failErrorPage.suggestion2;"
|
||||
data-branding-label="&webPaymentsBranding.label;"
|
||||
data-done-button-label="&failErrorPage.doneButton.label;"
|
||||
hidden="hidden"></completion-error-page>
|
||||
</div>
|
||||
|
@ -21,6 +21,7 @@ Test the completion-error-page component
|
||||
data-suggestion-heading="Sample suggestion heading"
|
||||
data-suggestion-1="Sample suggestion"
|
||||
data-suggestion-2="Sample suggestion"
|
||||
data-branding-label="Sample Brand"
|
||||
data-done-button-label="OK"></completion-error-page>
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
@ -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");
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -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 += [
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
|
||||
<!DOCTYPE window>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<div id="p">a node inspected before reload</div>
|
||||
<div id="q">a node inspected after reload</div>
|
||||
</body>
|
||||
</window>
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<nsCOMArray<nsIDocument>*>(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<nsIDocument>&& 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<nsIDocument> mDocuments;
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
|
||||
{
|
||||
MOZ_ASSERT(aMaybeNotARootDoc);
|
||||
|
||||
// Unlock the pointer
|
||||
UnlockPointer();
|
||||
|
||||
nsCOMPtr<nsIDocument> 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<nsIDocument> changed;
|
||||
|
||||
// Walk the tree of fullscreen documents, and reset their fullscreen state.
|
||||
ResetFullScreen(root, static_cast<void*>(&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<AsyncEventDispatcher> 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<nsIDocument> mRoot;
|
||||
nsCOMPtr<nsIDocument> mLeaf;
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
|
||||
{
|
||||
MOZ_ASSERT(aMaybeNotARootDoc);
|
||||
|
||||
// Unlock the pointer
|
||||
UnlockPointer();
|
||||
|
||||
nsCOMPtr<nsIDocument> 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<AsyncEventDispatcher> 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;
|
||||
}
|
||||
|
@ -7,13 +7,13 @@
|
||||
[ChromeOnly, Exposed=(Window,System)]
|
||||
namespace PrioEncoder {
|
||||
[Throws, NewObject]
|
||||
Promise<PrioEncodedData> 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 {
|
||||
|
49
dom/html/test/file_fullscreen-event-order.html
Normal file
49
dom/html/test/file_fullscreen-event-order.html
Normal file
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="file_fullscreen-utils.js"></script>
|
||||
<iframe src="about:blank" allowfullscreen></iframe>
|
||||
<script>
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, "[event-order] " + msg);
|
||||
}
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, "[event-order] " + msg);
|
||||
}
|
||||
|
||||
let fullscreenEvents = [];
|
||||
let iframeDoc;
|
||||
|
||||
function begin() {
|
||||
iframeDoc = document.querySelector("iframe").contentDocument;
|
||||
document.addEventListener("fullscreenchange", evt => {
|
||||
fullscreenEvents.push(evt);
|
||||
});
|
||||
iframeDoc.addEventListener("fullscreenchange", evt => {
|
||||
fullscreenEvents.push(evt);
|
||||
});
|
||||
addFullscreenChangeContinuation("enter", enterFullscreen);
|
||||
iframeDoc.body.requestFullscreen();
|
||||
}
|
||||
|
||||
function assertFullscreenEvents(action) {
|
||||
is(fullscreenEvents.length, 2,
|
||||
"Two documents should have event dispatched for " + action);
|
||||
is(fullscreenEvents[0].target, document,
|
||||
"Root document should have the event dispatched first after " + action);
|
||||
is(fullscreenEvents[1].target, iframeDoc,
|
||||
"Inner document should have the event dispatched second after " + action);
|
||||
}
|
||||
|
||||
function enterFullscreen() {
|
||||
assertFullscreenEvents("requestFullscreen");
|
||||
fullscreenEvents = [];
|
||||
addFullscreenChangeContinuation("exit", exitFullscreen);
|
||||
document.exitFullscreen();
|
||||
}
|
||||
|
||||
function exitFullscreen() {
|
||||
assertFullscreenEvents("exitFullscreen");
|
||||
opener.nextTest();
|
||||
}
|
||||
</script>
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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<Promise>
|
||||
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<PrioEncodedData>& aData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> 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<CURVE25519_KEY_LEN_HEX + 1> 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<CURVE25519_KEY_LEN_HEX + 1> 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<const unsigned char*>(prioKeyA.BeginReading()), CURVE25519_KEY_LEN_HEX);
|
||||
prio_rv = PublicKey_import_hex(&sPublicKeyA,
|
||||
reinterpret_cast<const unsigned char*>(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<const unsigned char*>(prioKeyB.BeginReading()), CURVE25519_KEY_LEN_HEX);
|
||||
prio_rv = PublicKey_import_hex(&sPublicKeyB,
|
||||
reinterpret_cast<const unsigned char*>(prioKeyB.BeginReading()),
|
||||
CURVE25519_KEY_LEN_HEX);
|
||||
if (prio_rv != SECSuccess) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<Promise> 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<const unsigned char*>(aBatchID.BeginReading()), aBatchID.Length());
|
||||
PrioConfig prioConfig = PrioConfig_new(mozilla::ArrayLength(dataItems),
|
||||
sPublicKeyA,
|
||||
sPublicKeyB,
|
||||
reinterpret_cast<const unsigned char*>(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<uint8_t> arrayForServerA;
|
||||
nsTArray<uint8_t> arrayForServerB;
|
||||
|
||||
if (!arrayForServerA.AppendElements(reinterpret_cast<uint8_t*>(forServerA), lenA, fallible)) {
|
||||
promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
|
||||
return promise.forget();
|
||||
if (!arrayForServerA.AppendElements(reinterpret_cast<uint8_t*>(forServerA),
|
||||
lenA,
|
||||
fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
free(forServerA);
|
||||
|
||||
if (!arrayForServerB.AppendElements(reinterpret_cast<uint8_t*>(forServerB), lenB, fallible)) {
|
||||
promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
|
||||
return promise.forget();
|
||||
if (!arrayForServerB.AppendElements(reinterpret_cast<uint8_t*>(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<JS::Value> valueA(aGlobal.Context());
|
||||
if (!ToJSValue(aGlobal.Context(), TypedArrayCreator<Uint8Array>(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<JS::Value> valueB(aGlobal.Context());
|
||||
if (!ToJSValue(aGlobal.Context(), TypedArrayCreator<Uint8Array>(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
|
||||
|
@ -21,8 +21,12 @@ class PrioEncoder
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(PrioEncoder)
|
||||
|
||||
static already_AddRefed<Promise>
|
||||
Encode(GlobalObject& aGlobal, const nsCString& aBatchID, const PrioParams& aPrioParams, ErrorResult& aRv);
|
||||
static
|
||||
void Encode(GlobalObject& aGlobal,
|
||||
const nsCString& aBatchID,
|
||||
const PrioParams& aPrioParams,
|
||||
RootedDictionary<PrioEncodedData>& aData,
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
PrioEncoder();
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -0,0 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Reftest Reference</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<style>
|
||||
.container {
|
||||
display: block;
|
||||
border: 2px solid purple;
|
||||
margin: 3px;
|
||||
/* This red should't be visible, because each container should shrinkwrap
|
||||
its sole child (and the child should cover up this background). */
|
||||
background: red;
|
||||
/* Float the containers, to test in "rows", with 1 row per writing-mode. */
|
||||
float: left;
|
||||
}
|
||||
br { clear: both; }
|
||||
|
||||
.container > * {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: teal;
|
||||
border: 1px solid yellow;
|
||||
}
|
||||
.container > * > * {
|
||||
background: pink;
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.pad_top { padding-top: 3px; }
|
||||
.pad_right { padding-right: 4px; }
|
||||
.pad_bottom { padding-bottom: 5px; }
|
||||
.pad_left { padding-left: 6px; }
|
||||
|
||||
.hl { writing-mode: horizontal-tb; direction: ltr; }
|
||||
.hr { writing-mode: horizontal-tb; direction: rtl; }
|
||||
.vl { writing-mode: vertical-lr; direction: ltr; }
|
||||
.vr { writing-mode: vertical-rl; direction: ltr; }
|
||||
.vl_rtl { writing-mode: vertical-lr; direction: rtl; }
|
||||
.vr_rtl { writing-mode: vertical-rl; direction: rtl; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Here, we test padding on each side of a flex item, across 6 different
|
||||
writing-mode combinations (writing-mode X direction). -->
|
||||
<div class="container hl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container hl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container hl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container hl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container hr">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container hr">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container hr">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container hr">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vr">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
CSS Test: Testing auto-sized flex containers
|
||||
with various 'writing-mode' values
|
||||
and various padding amounts on flex items.
|
||||
</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#flex-direction-property">
|
||||
<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#propdef-writing-mode">
|
||||
<link rel="match" href="flexbox-writing-mode-016-ref.html">
|
||||
<style>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border: 2px solid purple;
|
||||
margin: 3px;
|
||||
/* This red should't be visible, because each container should shrinkwrap
|
||||
its sole child (and the child should cover up this background). */
|
||||
background: red;
|
||||
/* Float the containers, to test in "rows", with 1 row per writing-mode. */
|
||||
float: left;
|
||||
}
|
||||
br { clear: both; }
|
||||
|
||||
.container > * {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: teal;
|
||||
border: 1px solid yellow;
|
||||
}
|
||||
.container > * > * {
|
||||
background: pink;
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.pad_top { padding-top: 3px; }
|
||||
.pad_right { padding-right: 4px; }
|
||||
.pad_bottom { padding-bottom: 5px; }
|
||||
.pad_left { padding-left: 6px; }
|
||||
|
||||
.hl { writing-mode: horizontal-tb; direction: ltr; }
|
||||
.hr { writing-mode: horizontal-tb; direction: rtl; }
|
||||
.vl { writing-mode: vertical-lr; direction: ltr; }
|
||||
.vr { writing-mode: vertical-rl; direction: ltr; }
|
||||
.vl_rtl { writing-mode: vertical-lr; direction: rtl; }
|
||||
.vr_rtl { writing-mode: vertical-rl; direction: rtl; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Here, we test padding on each side of a flex item, across 6 different
|
||||
writing-mode combinations (writing-mode X direction). -->
|
||||
<div class="container hl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container hl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container hl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container hl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container hr">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container hr">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container hr">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container hr">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vr">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vl_rtl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_top"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_right"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_bottom"><div></div></div>
|
||||
</div>
|
||||
<div class="container vr_rtl">
|
||||
<div class="pad_left"><div></div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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']
|
||||
|
@ -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 `;
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
@ -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();
|
||||
});
|
@ -56,4 +56,3 @@ skip-if = !sync
|
||||
[test_trimming.js]
|
||||
[test_visit_url.js]
|
||||
[test_word_boundary_search.js]
|
||||
[test_zero_frecency.js]
|
||||
|
@ -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."
|
||||
},
|
||||
|
5
toolkit/components/telemetry/build_scripts/README.md
Normal file
5
toolkit/components/telemetry/build_scripts/README.md
Normal file
@ -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/.
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
30
toolkit/components/telemetry/build_scripts/setup.py
Normal file
30
toolkit/components/telemetry/build_scripts/setup.py
Normal file
@ -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'],
|
||||
)
|
@ -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 <https://crypto.stanford.edu/prio/>`_ and `the libprio Github repo <https://github.com/mozilla/libprio>`_
|
||||
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
|
||||
---------------
|
||||
|
||||
|
@ -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;
|
||||
},
|
||||
};
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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<nsIFile> updRoot;
|
||||
nsCOMPtr<nsIFile> 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<const char*>(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
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user