Merge autoland to mozilla-central. a=merge

This commit is contained in:
Andreea Pavel 2018-09-11 00:58:48 +03:00
commit 2b539c7b7e
61 changed files with 930 additions and 281 deletions

View File

@ -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);

View File

@ -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

View File

@ -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() {

View File

@ -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 = "";

View File

@ -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 {

View File

@ -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: [],

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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 += [

View File

@ -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]

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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 {

View 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>

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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:

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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']

View File

@ -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 `;

View File

@ -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();
});
}

View File

@ -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();
});

View File

@ -56,4 +56,3 @@ skip-if = !sync
[test_trimming.js]
[test_visit_url.js]
[test_word_boundary_search.js]
[test_zero_frecency.js]

View File

@ -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."
},

View 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/.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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'],
)

View File

@ -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
---------------

View File

@ -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;
},
};

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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);
}

View File

@ -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

View File

@ -1176,8 +1176,12 @@ GetCachedHash(HKEY rootKey, const nsAString &regPath, 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

View File

@ -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.

View File

@ -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,