зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
a4a2be52e8
|
@ -23,21 +23,16 @@ var gSafeBrowsing = {
|
||||||
document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu")
|
document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu")
|
||||||
.hidden = !isPhishingPage;
|
.hidden = !isPhishingPage;
|
||||||
|
|
||||||
var broadcasterId = isPhishingPage
|
|
||||||
? "reportPhishingErrorBroadcaster"
|
|
||||||
: "reportPhishingBroadcaster";
|
|
||||||
|
|
||||||
var broadcaster = document.getElementById(broadcasterId);
|
|
||||||
if (!broadcaster)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Now look at the currentURI to learn which page we were trying
|
// Now look at the currentURI to learn which page we were trying
|
||||||
// to browse to.
|
// to browse to.
|
||||||
let uri = gBrowser.currentURI;
|
const uri = gBrowser.currentURI;
|
||||||
if (uri && (uri.schemeIs("http") || uri.schemeIs("https")))
|
const isReportablePage = uri && (uri.schemeIs("http") || uri.schemeIs("https"));
|
||||||
broadcaster.removeAttribute("disabled");
|
|
||||||
else
|
const disabledByPolicy = !Services.policies.isAllowed("feedbackCommands");
|
||||||
broadcaster.setAttribute("disabled", true);
|
document.getElementById("reportPhishingBroadcaster")
|
||||||
|
.disabled = disabledByPolicy || isPhishingPage || !isReportablePage;
|
||||||
|
document.getElementById("reportPhishingErrorBroadcaster")
|
||||||
|
.disabled = disabledByPolicy || !isPhishingPage || !isReportablePage;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -831,6 +831,12 @@ function openTourPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildHelpMenu() {
|
function buildHelpMenu() {
|
||||||
|
document.getElementById("feedbackPage")
|
||||||
|
.disabled = !Services.policies.isAllowed("feedbackCommands");
|
||||||
|
|
||||||
|
document.getElementById("helpSafeMode")
|
||||||
|
.disabled = !Services.policies.isAllowed("safeMode");
|
||||||
|
|
||||||
// Enable/disable the "Report Web Forgery" menu item.
|
// Enable/disable the "Report Web Forgery" menu item.
|
||||||
if (typeof gSafeBrowsing != "undefined") {
|
if (typeof gSafeBrowsing != "undefined") {
|
||||||
gSafeBrowsing.setReportPhishingMenu();
|
gSafeBrowsing.setReportPhishingMenu();
|
||||||
|
|
|
@ -135,6 +135,14 @@ var Policies = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"DisableBuiltinPDFViewer": {
|
||||||
|
onBeforeUIStartup(manager, param) {
|
||||||
|
if (param) {
|
||||||
|
manager.disallowFeature("PDF.js");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"DisableDeveloperTools": {
|
"DisableDeveloperTools": {
|
||||||
onBeforeAddons(manager, param) {
|
onBeforeAddons(manager, param) {
|
||||||
if (param) {
|
if (param) {
|
||||||
|
@ -149,6 +157,14 @@ var Policies = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"DisableFeedbackCommands": {
|
||||||
|
onBeforeUIStartup(manager, param) {
|
||||||
|
if (param) {
|
||||||
|
manager.disallowFeature("feedbackCommands");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"DisableFirefoxAccounts": {
|
"DisableFirefoxAccounts": {
|
||||||
onBeforeAddons(manager, param) {
|
onBeforeAddons(manager, param) {
|
||||||
if (param) {
|
if (param) {
|
||||||
|
@ -199,6 +215,14 @@ var Policies = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"DisableSafeMode": {
|
||||||
|
onBeforeUIStartup(manager, param) {
|
||||||
|
if (param) {
|
||||||
|
manager.disallowFeature("safeMode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"DisableSysAddonUpdate": {
|
"DisableSysAddonUpdate": {
|
||||||
onBeforeAddons(manager, param) {
|
onBeforeAddons(manager, param) {
|
||||||
if (param) {
|
if (param) {
|
||||||
|
|
|
@ -107,6 +107,13 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"DisableBuiltinPDFViewer": {
|
||||||
|
"description": "Disables PDF.js, which displays PDFs within Firefox.",
|
||||||
|
"first_available": "60.0",
|
||||||
|
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
|
||||||
"DisableDeveloperTools": {
|
"DisableDeveloperTools": {
|
||||||
"description": "Prevents access to developer tools.",
|
"description": "Prevents access to developer tools.",
|
||||||
"first_available": "60.0",
|
"first_available": "60.0",
|
||||||
|
@ -114,6 +121,13 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"DisableFeedbackCommands": {
|
||||||
|
"description": "Prevents ability to send feedback from the help menu (\"Submit Feedback\" and \"Report Deceptive Site\").",
|
||||||
|
"first_available": "60.0",
|
||||||
|
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
|
||||||
"DisableFirefoxAccounts": {
|
"DisableFirefoxAccounts": {
|
||||||
"description": "Disables Firefox Account based services, including Sync.",
|
"description": "Disables Firefox Account based services, including Sync.",
|
||||||
"first_available": "60.0",
|
"first_available": "60.0",
|
||||||
|
@ -156,6 +170,13 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"DisableSafeMode": {
|
||||||
|
"description": "Prevents ability to restart in safe mode.",
|
||||||
|
"first_available": "60.0",
|
||||||
|
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
|
||||||
"DisableSysAddonUpdate": {
|
"DisableSysAddonUpdate": {
|
||||||
"description": "Prevent the browser from installing and updating system addons.",
|
"description": "Prevent the browser from installing and updating system addons.",
|
||||||
"first_available": "60.0",
|
"first_available": "60.0",
|
||||||
|
|
|
@ -24,12 +24,15 @@ support-files =
|
||||||
[browser_policy_bookmarks.js]
|
[browser_policy_bookmarks.js]
|
||||||
[browser_policy_clear_blocked_cookies.js]
|
[browser_policy_clear_blocked_cookies.js]
|
||||||
[browser_policy_default_browser_check.js]
|
[browser_policy_default_browser_check.js]
|
||||||
|
[browser_policy_disable_feedback_commands.js]
|
||||||
[browser_policy_disable_formhistory.js]
|
[browser_policy_disable_formhistory.js]
|
||||||
[browser_policy_disable_fxaccounts.js]
|
[browser_policy_disable_fxaccounts.js]
|
||||||
[browser_policy_disable_fxscreenshots.js]
|
[browser_policy_disable_fxscreenshots.js]
|
||||||
[browser_policy_disable_masterpassword.js]
|
[browser_policy_disable_masterpassword.js]
|
||||||
|
[browser_policy_disable_pdfjs.js]
|
||||||
[browser_policy_disable_pocket.js]
|
[browser_policy_disable_pocket.js]
|
||||||
[browser_policy_disable_privatebrowsing.js]
|
[browser_policy_disable_privatebrowsing.js]
|
||||||
|
[browser_policy_disable_safemode.js]
|
||||||
[browser_policy_disable_shield.js]
|
[browser_policy_disable_shield.js]
|
||||||
[browser_policy_display_bookmarks.js]
|
[browser_policy_display_bookmarks.js]
|
||||||
[browser_policy_display_menu.js]
|
[browser_policy_display_menu.js]
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/* the buidHelpMenu() function comes from browser/base/content/utilityOverlay.js */
|
||||||
|
|
||||||
|
const NORMAL_PAGE = "http://example.com";
|
||||||
|
const PHISH_PAGE = "http://www.itisatrap.org/firefox/its-a-trap.html";
|
||||||
|
|
||||||
|
async function checkItemsAreDisabled(url) {
|
||||||
|
await BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url,
|
||||||
|
// The phishing page doesn't send a load notification
|
||||||
|
waitForLoad: false,
|
||||||
|
waitForStateStop: true,
|
||||||
|
}, async function checkItems() {
|
||||||
|
buildHelpMenu();
|
||||||
|
|
||||||
|
let reportMenu = document.getElementById("menu_HelpPopup_reportPhishingtoolmenu");
|
||||||
|
is(reportMenu.getAttribute("disabled"), "true",
|
||||||
|
"The `Report Deceptive Site` item should be disabled");
|
||||||
|
|
||||||
|
let errorMenu = document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu");
|
||||||
|
is(errorMenu.getAttribute("disabled"), "true",
|
||||||
|
"The `This isn’t a deceptive site` item should be disabled");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(async function test_policy_feedback_commands() {
|
||||||
|
await setupPolicyEngineWithJson({
|
||||||
|
"policies": {
|
||||||
|
"DisableFeedbackCommands": true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* from browser/base/content/utilityOverlay.js */
|
||||||
|
buildHelpMenu();
|
||||||
|
|
||||||
|
let feedbackPageMenu = document.getElementById("feedbackPage");
|
||||||
|
is(feedbackPageMenu.getAttribute("disabled"), "true",
|
||||||
|
"The `Submit Feedback...` item should be disabled");
|
||||||
|
|
||||||
|
await checkItemsAreDisabled(NORMAL_PAGE);
|
||||||
|
await checkItemsAreDisabled(PHISH_PAGE);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const {PdfJs} = ChromeUtils.import("resource://pdf.js/PdfJs.jsm", {});
|
||||||
|
|
||||||
|
add_task(async function test_disable_pdfjs() {
|
||||||
|
is(PdfJs.enabled, true, "PDFjs should be enabled before policy runs");
|
||||||
|
|
||||||
|
await setupPolicyEngineWithJson({
|
||||||
|
"policies": {
|
||||||
|
"DisableBuiltinPDFViewer": true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
is(PdfJs.enabled, false, "PDFjs should be disabled after policy runs");
|
||||||
|
});
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
add_task(async function setup() {
|
||||||
|
await setupPolicyEngineWithJson({
|
||||||
|
"policies": {
|
||||||
|
"DisableSafeMode": true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_help_menu() {
|
||||||
|
buildHelpMenu();
|
||||||
|
let safeModeMenu = document.getElementById("helpSafeMode");
|
||||||
|
is(safeModeMenu.getAttribute("disabled"), "true",
|
||||||
|
"The `Restart with Add-ons Disabled...` item should be disabled");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_safemode_from_about_support() {
|
||||||
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:support");
|
||||||
|
|
||||||
|
await ContentTask.spawn(tab.linkedBrowser, null, async function() {
|
||||||
|
let button = content.document.getElementById("restart-in-safe-mode-button");
|
||||||
|
is(button.getAttribute("disabled"), "true",
|
||||||
|
"The `Restart with Add-ons Disabled...` button should be disabled");
|
||||||
|
});
|
||||||
|
|
||||||
|
await BrowserTestUtils.removeTab(tab);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_safemode_from_about_profiles() {
|
||||||
|
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:profiles");
|
||||||
|
|
||||||
|
await ContentTask.spawn(tab.linkedBrowser, null, async function() {
|
||||||
|
let button = content.document.getElementById("restart-in-safe-mode-button");
|
||||||
|
is(button.getAttribute("disabled"), "true",
|
||||||
|
"The `Restart with Add-ons Disabled...` button should be disabled");
|
||||||
|
});
|
||||||
|
|
||||||
|
await BrowserTestUtils.removeTab(tab);
|
||||||
|
});
|
|
@ -51,6 +51,7 @@ skip-if = os == 'linux'
|
||||||
[browser_ext_browserAction_pageAction_icon_permissions.js]
|
[browser_ext_browserAction_pageAction_icon_permissions.js]
|
||||||
[browser_ext_browserAction_popup.js]
|
[browser_ext_browserAction_popup.js]
|
||||||
skip-if = (debug && os == 'linux' && bits == 32) || (os == 'win' && !debug) # Bug 1313372, win: Bug 1285500
|
skip-if = (debug && os == 'linux' && bits == 32) || (os == 'win' && !debug) # Bug 1313372, win: Bug 1285500
|
||||||
|
[browser_ext_browserAction_popup_port.js]
|
||||||
[browser_ext_browserAction_popup_preload.js]
|
[browser_ext_browserAction_popup_preload.js]
|
||||||
skip-if = (os == 'win' && !debug) # bug 1352668
|
skip-if = (os == 'win' && !debug) # bug 1352668
|
||||||
[browser_ext_browserAction_popup_resize.js]
|
[browser_ext_browserAction_popup_resize.js]
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||||
|
/* vim: set sts=2 sw=2 et tw=80: */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
|
||||||
|
|
||||||
|
// Tests that message ports still function correctly after a browserAction popup
|
||||||
|
// <browser> has been reparented.
|
||||||
|
add_task(async function test_browserActionPort() {
|
||||||
|
let extension = ExtensionTestUtils.loadExtension({
|
||||||
|
manifest: {
|
||||||
|
"browser_action": {
|
||||||
|
"default_popup": "popup.html",
|
||||||
|
"browser_style": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
background() {
|
||||||
|
new Promise(resolve => {
|
||||||
|
browser.runtime.onConnect.addListener(port => {
|
||||||
|
resolve(Promise.all([
|
||||||
|
new Promise(r => port.onMessage.addListener(r)),
|
||||||
|
new Promise(r => port.onDisconnect.addListener(r)),
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
}).then(([msg]) => {
|
||||||
|
browser.test.assertEq("Hallo.", msg, "Got expected message");
|
||||||
|
browser.test.notifyPass("browserAction-popup-port");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
files: {
|
||||||
|
"popup.html": scriptPage("popup.js"),
|
||||||
|
"popup.js"() {
|
||||||
|
let port = browser.runtime.connect();
|
||||||
|
window.onload = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
port.postMessage("Hallo.");
|
||||||
|
window.close();
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
await clickBrowserAction(extension);
|
||||||
|
|
||||||
|
await extension.awaitFinish("browserAction-popup-port");
|
||||||
|
await extension.unload();
|
||||||
|
});
|
|
@ -0,0 +1,48 @@
|
||||||
|
.. _browsererrorreporter:
|
||||||
|
|
||||||
|
=======================
|
||||||
|
Browser Error Reporter
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The `BrowserErrorReporter.jsm <https://dxr.mozilla.org/mozilla-central/source/browser/modules/BrowserErrorReporter.jsm>`_ module collects errors logged to the Browser Console and sends them to a remote error aggregation service.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This module and the related service is a prototype and will be removed from Firefox in later 2018.
|
||||||
|
|
||||||
|
Opt-out
|
||||||
|
=======
|
||||||
|
Collection is enabled by default in the Nightly channel, except for local builds, where it is disabled. It is not available outside of the Nightly channel.
|
||||||
|
|
||||||
|
To opt-out of collection:
|
||||||
|
|
||||||
|
1. Open ``about:preferences``.
|
||||||
|
2. Select the Privacy and Security panel and go to the Nightly Data Collection and Use section.
|
||||||
|
3. Uncheck "Allow Nightly to send browser error reports (including error messages) to Mozilla".
|
||||||
|
|
||||||
|
Collected Error Data
|
||||||
|
====================
|
||||||
|
Errors are first sampled at the rate specified by the ``browser.chrome.errorReporter.sampleRate`` preference.
|
||||||
|
|
||||||
|
The payload sent to the remote collection service contains the following info:
|
||||||
|
|
||||||
|
- Firefox version number
|
||||||
|
- Firefox update channel (usually "Nightly")
|
||||||
|
- Firefox build ID
|
||||||
|
- Revision used to build Firefox
|
||||||
|
- Timestamp when the error occurred
|
||||||
|
- A project ID specified by the ``browser.chrome.errorReporter.projectId`` preference
|
||||||
|
- The error message
|
||||||
|
- The filename that the error was thrown from
|
||||||
|
- A stacktrace, if available, of the code being executed when the error was thrown
|
||||||
|
|
||||||
|
Privacy-sensitive info
|
||||||
|
======================
|
||||||
|
Error reports may contain sensitive information about the user:
|
||||||
|
|
||||||
|
- Error messages may inadvertently contain personal info depending on the code that generated the error.
|
||||||
|
- Filenames in the stack trace may contain add-on IDs of currently-installed add-ons. They may also contain local filesystem paths.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
`Browser Error Collection wiki page <https://wiki.mozilla.org/Firefox/BrowserErrorCollection>`_
|
||||||
|
Wiki page with up-to-date information on error collection and how we restrict access to the collected data.
|
|
@ -9,3 +9,4 @@ This is the nascent documentation of the Firefox front-end code.
|
||||||
|
|
||||||
UITelemetry
|
UITelemetry
|
||||||
BrowserUsageTelemetry
|
BrowserUsageTelemetry
|
||||||
|
BrowserErrorReporter
|
||||||
|
|
|
@ -337,6 +337,10 @@ var PdfJs = {
|
||||||
* @return {boolean} Whether or not it's enabled.
|
* @return {boolean} Whether or not it's enabled.
|
||||||
*/
|
*/
|
||||||
get enabled() {
|
get enabled() {
|
||||||
|
if (!Services.policies.isAllowed("PDF.js")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Services.prefs.getBoolPref(PREF_ENABLED_CACHE_INITIALIZED, false)) {
|
if (!Services.prefs.getBoolPref(PREF_ENABLED_CACHE_INITIALIZED, false)) {
|
||||||
// If we just updated, and the cache hasn't been initialized, then we
|
// If we just updated, and the cache hasn't been initialized, then we
|
||||||
// can't assume a default state, and need to synchronously initialize
|
// can't assume a default state, and need to synchronously initialize
|
||||||
|
|
|
@ -55,9 +55,10 @@ const REPORTED_CATEGORIES = new Set([
|
||||||
* traces; see bug 1426482 for privacy review and server-side mitigation.
|
* traces; see bug 1426482 for privacy review and server-side mitigation.
|
||||||
*/
|
*/
|
||||||
class BrowserErrorReporter {
|
class BrowserErrorReporter {
|
||||||
constructor(fetchMethod = this._defaultFetch) {
|
constructor(fetchMethod = this._defaultFetch, chromeOnly = true) {
|
||||||
// A fake fetch is passed by the tests to avoid network connections
|
// Test arguments for mocks and changing behavior
|
||||||
this.fetch = fetchMethod;
|
this.fetch = fetchMethod;
|
||||||
|
this.chromeOnly = chromeOnly;
|
||||||
|
|
||||||
// Values that don't change between error reports.
|
// Values that don't change between error reports.
|
||||||
this.requestBodyTemplate = {
|
this.requestBodyTemplate = {
|
||||||
|
@ -133,7 +134,7 @@ class BrowserErrorReporter {
|
||||||
|
|
||||||
const isWarning = message.flags & message.warningFlag;
|
const isWarning = message.flags & message.warningFlag;
|
||||||
const isFromChrome = REPORTED_CATEGORIES.has(message.category);
|
const isFromChrome = REPORTED_CATEGORIES.has(message.category);
|
||||||
if (!isFromChrome || isWarning) {
|
if ((this.chromeOnly && !isFromChrome) || isWarning) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +144,22 @@ class BrowserErrorReporter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const extensions = new Map();
|
||||||
|
for (let extension of WebExtensionPolicy.getActiveExtensions()) {
|
||||||
|
extensions.set(extension.mozExtensionHostname, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replaces any instances of moz-extension:// URLs with internal UUIDs to use
|
||||||
|
// the add-on ID instead.
|
||||||
|
function mangleExtURL(string, anchored = true) {
|
||||||
|
let re = new RegExp(`${anchored ? "^" : ""}moz-extension://([^/]+)/`, "g");
|
||||||
|
|
||||||
|
return string.replace(re, (m0, m1) => {
|
||||||
|
let id = extensions.has(m1) ? extensions.get(m1).id : m1;
|
||||||
|
return `moz-extension://${id}/`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the error type from the message if present (e.g. "TypeError: Whoops").
|
// Parse the error type from the message if present (e.g. "TypeError: Whoops").
|
||||||
let errorMessage = message.errorMessage;
|
let errorMessage = message.errorMessage;
|
||||||
let errorName = "Error";
|
let errorName = "Error";
|
||||||
|
@ -156,7 +173,9 @@ class BrowserErrorReporter {
|
||||||
let frame = message.stack;
|
let frame = message.stack;
|
||||||
// Avoid an infinite loop by limiting traces to 100 frames.
|
// Avoid an infinite loop by limiting traces to 100 frames.
|
||||||
while (frame && frames.length < 100) {
|
while (frame && frames.length < 100) {
|
||||||
frames.push(await this.normalizeStackFrame(frame));
|
const normalizedFrame = await this.normalizeStackFrame(frame);
|
||||||
|
normalizedFrame.module = mangleExtURL(normalizedFrame.module, false);
|
||||||
|
frames.push(normalizedFrame);
|
||||||
frame = frame.parent;
|
frame = frame.parent;
|
||||||
}
|
}
|
||||||
// Frames are sent in order from oldest to newest.
|
// Frames are sent in order from oldest to newest.
|
||||||
|
@ -169,7 +188,7 @@ class BrowserErrorReporter {
|
||||||
values: [
|
values: [
|
||||||
{
|
{
|
||||||
type: errorName,
|
type: errorName,
|
||||||
value: errorMessage,
|
value: mangleExtURL(errorMessage),
|
||||||
module: message.sourceName,
|
module: message.sourceName,
|
||||||
stacktrace: {
|
stacktrace: {
|
||||||
frames,
|
frames,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm", this);
|
||||||
ChromeUtils.import("resource:///modules/BrowserErrorReporter.jsm", this);
|
ChromeUtils.import("resource:///modules/BrowserErrorReporter.jsm", this);
|
||||||
|
|
||||||
/* global sinon */
|
/* global sinon */
|
||||||
|
@ -406,3 +407,45 @@ add_task(async function testFetchArguments() {
|
||||||
reporter.uninit();
|
reporter.uninit();
|
||||||
resetConsole();
|
resetConsole();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(async function testAddonIDMangle() {
|
||||||
|
const fetchSpy = sinon.spy();
|
||||||
|
// Passing false here disables category checks on errors, which would
|
||||||
|
// otherwise block errors directly from extensions.
|
||||||
|
const reporter = new BrowserErrorReporter(fetchSpy, false);
|
||||||
|
await SpecialPowers.pushPrefEnv({set: [
|
||||||
|
[PREF_ENABLED, true],
|
||||||
|
[PREF_SAMPLE_RATE, "1.0"],
|
||||||
|
]});
|
||||||
|
reporter.init();
|
||||||
|
|
||||||
|
// Create and install test add-on
|
||||||
|
const id = "browsererrorcollection@example.com";
|
||||||
|
const extension = ExtensionTestUtils.loadExtension({
|
||||||
|
manifest: {
|
||||||
|
applications: {
|
||||||
|
gecko: { id },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
background() {
|
||||||
|
throw new Error("testAddonIDMangle error");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
// Just in case the error hasn't been thrown before add-on startup.
|
||||||
|
const call = await TestUtils.waitForCondition(
|
||||||
|
() => fetchCallForMessage(fetchSpy, "testAddonIDMangle error"),
|
||||||
|
`Wait for error from ${id} to be logged`,
|
||||||
|
);
|
||||||
|
const body = JSON.parse(call.args[1].body);
|
||||||
|
const stackFrame = body.exception.values[0].stacktrace.frames[0];
|
||||||
|
ok(
|
||||||
|
stackFrame.module.startsWith(`moz-extension://${id}/`),
|
||||||
|
"Stack frame filenames use the proper add-on ID instead of internal UUIDs.",
|
||||||
|
);
|
||||||
|
|
||||||
|
await extension.unload();
|
||||||
|
reporter.uninit();
|
||||||
|
resetConsole();
|
||||||
|
});
|
||||||
|
|
|
@ -217,7 +217,7 @@ BrowserAddonActor.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global instanceof Ci.nsIDOMWindow) {
|
if (global instanceof Ci.nsIDOMWindow) {
|
||||||
return global.document.nodePrincipal.addonId;
|
return global.document.nodePrincipal.addonId == this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "mozilla/dom/MessageEventBinding.h"
|
#include "mozilla/dom/MessageEventBinding.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/dom/WorkerPrivate.h"
|
#include "mozilla/dom/WorkerPrivate.h"
|
||||||
|
#include "mozilla/dom/WorkerRef.h"
|
||||||
#include "mozilla/dom/WorkerRunnable.h"
|
#include "mozilla/dom/WorkerRunnable.h"
|
||||||
#include "mozilla/dom/WorkerScope.h"
|
#include "mozilla/dom/WorkerScope.h"
|
||||||
#include "mozilla/UniquePtrExtensions.h"
|
#include "mozilla/UniquePtrExtensions.h"
|
||||||
|
@ -143,8 +144,8 @@ public:
|
||||||
void AddRefObject();
|
void AddRefObject();
|
||||||
void ReleaseObject();
|
void ReleaseObject();
|
||||||
|
|
||||||
bool RegisterWorkerHolder();
|
bool CreateWorkerRef(WorkerPrivate* aWorkerPrivate);
|
||||||
void UnregisterWorkerHolder();
|
void ReleaseWorkerRef();
|
||||||
|
|
||||||
void AssertIsOnTargetThread() const
|
void AssertIsOnTargetThread() const
|
||||||
{
|
{
|
||||||
|
@ -282,11 +283,8 @@ public:
|
||||||
nsString mLastFieldValue;
|
nsString mLastFieldValue;
|
||||||
|
|
||||||
// EventSourceImpl internal states.
|
// EventSourceImpl internal states.
|
||||||
// The worker private where the EventSource is created. nullptr if created on
|
// WorkerRef to keep the worker alive. (accessed on worker thread only)
|
||||||
// main thread. (accessed on worker thread only)
|
RefPtr<ThreadSafeWorkerRef> mWorkerRef;
|
||||||
WorkerPrivate* mWorkerPrivate;
|
|
||||||
// Holder to worker to keep worker alive. (accessed on worker thread only)
|
|
||||||
nsAutoPtr<WorkerHolder> mWorkerHolder;
|
|
||||||
// This mutex protects mFrozen and mEventSource->mReadyState that are used in
|
// This mutex protects mFrozen and mEventSource->mReadyState that are used in
|
||||||
// different threads.
|
// different threads.
|
||||||
mozilla::Mutex mMutex;
|
mozilla::Mutex mMutex;
|
||||||
|
@ -353,8 +351,6 @@ EventSourceImpl::EventSourceImpl(EventSource* aEventSource)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mEventSource);
|
MOZ_ASSERT(mEventSource);
|
||||||
if (!mIsMainThread) {
|
if (!mIsMainThread) {
|
||||||
mWorkerPrivate = GetCurrentThreadWorkerPrivate();
|
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
|
||||||
mEventSource->mIsMainThread = false;
|
mEventSource->mIsMainThread = false;
|
||||||
}
|
}
|
||||||
SetReadyState(CONNECTING);
|
SetReadyState(CONNECTING);
|
||||||
|
@ -364,11 +360,11 @@ class CleanupRunnable final : public WorkerMainThreadRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CleanupRunnable(EventSourceImpl* aEventSourceImpl)
|
explicit CleanupRunnable(EventSourceImpl* aEventSourceImpl)
|
||||||
: WorkerMainThreadRunnable(aEventSourceImpl->mWorkerPrivate,
|
: WorkerMainThreadRunnable(GetCurrentThreadWorkerPrivate(),
|
||||||
NS_LITERAL_CSTRING("EventSource :: Cleanup"))
|
NS_LITERAL_CSTRING("EventSource :: Cleanup"))
|
||||||
, mImpl(aEventSourceImpl)
|
, mImpl(aEventSourceImpl)
|
||||||
{
|
{
|
||||||
mImpl->mWorkerPrivate->AssertIsOnWorkerThread();
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainThreadRun() override
|
bool MainThreadRun() override
|
||||||
|
@ -413,7 +409,7 @@ EventSourceImpl::CloseInternal()
|
||||||
RefPtr<CleanupRunnable> runnable = new CleanupRunnable(this);
|
RefPtr<CleanupRunnable> runnable = new CleanupRunnable(this);
|
||||||
runnable->Dispatch(Killing, rv);
|
runnable->Dispatch(Killing, rv);
|
||||||
MOZ_ASSERT(!rv.Failed());
|
MOZ_ASSERT(!rv.Failed());
|
||||||
UnregisterWorkerHolder();
|
ReleaseWorkerRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mMessagesToDispatch.GetSize() != 0) {
|
while (mMessagesToDispatch.GetSize() != 0) {
|
||||||
|
@ -452,20 +448,22 @@ void EventSourceImpl::CleanupOnMainThread()
|
||||||
class InitRunnable final : public WorkerMainThreadRunnable
|
class InitRunnable final : public WorkerMainThreadRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit InitRunnable(EventSourceImpl* aEventSourceImpl,
|
InitRunnable(WorkerPrivate* aWorkerPrivate,
|
||||||
const nsAString& aURL)
|
EventSourceImpl* aEventSourceImpl,
|
||||||
: WorkerMainThreadRunnable(aEventSourceImpl->mWorkerPrivate,
|
const nsAString& aURL)
|
||||||
|
: WorkerMainThreadRunnable(aWorkerPrivate,
|
||||||
NS_LITERAL_CSTRING("EventSource :: Init"))
|
NS_LITERAL_CSTRING("EventSource :: Init"))
|
||||||
, mImpl(aEventSourceImpl)
|
, mImpl(aEventSourceImpl)
|
||||||
, mURL(aURL)
|
, mURL(aURL)
|
||||||
{
|
{
|
||||||
mImpl->mWorkerPrivate->AssertIsOnWorkerThread();
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainThreadRun() override
|
bool MainThreadRun() override
|
||||||
{
|
{
|
||||||
// Get principal from worker's owner document or from worker.
|
// Get principal from worker's owner document or from worker.
|
||||||
WorkerPrivate* wp = mImpl->mWorkerPrivate;
|
WorkerPrivate* wp = mWorkerPrivate;
|
||||||
while (wp->GetParent()) {
|
while (wp->GetParent()) {
|
||||||
wp = wp->GetParent();
|
wp = wp->GetParent();
|
||||||
}
|
}
|
||||||
|
@ -485,13 +483,36 @@ public:
|
||||||
|
|
||||||
nsresult ErrorCode() const { return mRv; }
|
nsresult ErrorCode() const { return mRv; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
// Raw pointer because this runnable is sync.
|
// Raw pointer because this runnable is sync.
|
||||||
EventSourceImpl* mImpl;
|
EventSourceImpl* mImpl;
|
||||||
const nsAString& mURL;
|
const nsAString& mURL;
|
||||||
nsresult mRv;
|
nsresult mRv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ConnectRunnable final : public WorkerMainThreadRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ConnectRunnable(WorkerPrivate* aWorkerPrivate,
|
||||||
|
EventSourceImpl* aEventSourceImpl)
|
||||||
|
: WorkerMainThreadRunnable(aWorkerPrivate,
|
||||||
|
NS_LITERAL_CSTRING("EventSource :: Connect"))
|
||||||
|
, mImpl(aEventSourceImpl)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainThreadRun() override
|
||||||
|
{
|
||||||
|
mImpl->InitChannelAndRequestEventSource();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<EventSourceImpl> mImpl;
|
||||||
|
};
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
EventSourceImpl::ParseURL(const nsAString& aURL)
|
EventSourceImpl::ParseURL(const nsAString& aURL)
|
||||||
{
|
{
|
||||||
|
@ -585,11 +606,6 @@ EventSourceImpl::Init(nsIPrincipal* aPrincipal,
|
||||||
DEFAULT_RECONNECTION_TIME_VALUE);
|
DEFAULT_RECONNECTION_TIME_VALUE);
|
||||||
|
|
||||||
mUnicodeDecoder = UTF_8_ENCODING->NewDecoderWithBOMRemoval();
|
mUnicodeDecoder = UTF_8_ENCODING->NewDecoderWithBOMRemoval();
|
||||||
|
|
||||||
// the constructor should throw a SYNTAX_ERROR only if it fails resolving the
|
|
||||||
// url parameter, so we don't care about the InitChannelAndRequestEventSource
|
|
||||||
// result.
|
|
||||||
InitChannelAndRequestEventSource();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1131,11 +1147,11 @@ class CallRestartConnection final : public WorkerMainThreadRunnable
|
||||||
public:
|
public:
|
||||||
explicit CallRestartConnection(EventSourceImpl* aEventSourceImpl)
|
explicit CallRestartConnection(EventSourceImpl* aEventSourceImpl)
|
||||||
: WorkerMainThreadRunnable(
|
: WorkerMainThreadRunnable(
|
||||||
aEventSourceImpl->mWorkerPrivate,
|
aEventSourceImpl->mWorkerRef->Private(),
|
||||||
NS_LITERAL_CSTRING("EventSource :: RestartConnection"))
|
NS_LITERAL_CSTRING("EventSource :: RestartConnection"))
|
||||||
, mImpl(aEventSourceImpl)
|
, mImpl(aEventSourceImpl)
|
||||||
{
|
{
|
||||||
mImpl->mWorkerPrivate->AssertIsOnWorkerThread();
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainThreadRun() override
|
bool MainThreadRun() override
|
||||||
|
@ -1476,8 +1492,8 @@ EventSourceImpl::DispatchAllMessageEvents()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
MOZ_ASSERT(mWorkerRef);
|
||||||
if (NS_WARN_IF(!jsapi.Init(mWorkerPrivate->GlobalScope()))) {
|
if (NS_WARN_IF(!jsapi.Init(mWorkerRef->Private()->GlobalScope()))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1777,28 +1793,6 @@ EventSourceImpl::ReleaseObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class EventSourceWorkerHolder final : public WorkerHolder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit EventSourceWorkerHolder(EventSourceImpl* aEventSourceImpl)
|
|
||||||
: WorkerHolder("EventSourceWorkerHolder")
|
|
||||||
, mEventSourceImpl(aEventSourceImpl)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Notify(WorkerStatus aStatus) override
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aStatus > Running);
|
|
||||||
if (aStatus >= Canceling) {
|
|
||||||
mEventSourceImpl->Close();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Raw pointer because the EventSourceImpl object keeps alive the holder.
|
|
||||||
EventSourceImpl* mEventSourceImpl;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WorkerRunnableDispatcher final : public WorkerRunnable
|
class WorkerRunnableDispatcher final : public WorkerRunnable
|
||||||
{
|
{
|
||||||
|
@ -1849,30 +1843,32 @@ private:
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool EventSourceImpl::RegisterWorkerHolder()
|
bool EventSourceImpl::CreateWorkerRef(WorkerPrivate* aWorkerPrivate)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!IsShutDown());
|
MOZ_ASSERT(!IsShutDown());
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
MOZ_ASSERT(!mWorkerRef);
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
MOZ_ASSERT(!mWorkerHolder);
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
mWorkerHolder = new EventSourceWorkerHolder(this);
|
|
||||||
if (NS_WARN_IF(!mWorkerHolder->HoldWorker(mWorkerPrivate, Canceling))) {
|
RefPtr<EventSourceImpl> self = this;
|
||||||
mWorkerHolder = nullptr;
|
RefPtr<StrongWorkerRef> workerRef =
|
||||||
|
StrongWorkerRef::Create(aWorkerPrivate, "EventSource", [self]() {
|
||||||
|
self->Close();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (NS_WARN_IF(!workerRef)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mWorkerRef = new ThreadSafeWorkerRef(workerRef);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventSourceImpl::UnregisterWorkerHolder()
|
void EventSourceImpl::ReleaseWorkerRef()
|
||||||
{
|
{
|
||||||
// RegisterWorkerHolder fail will destroy EventSourceImpl and invoke
|
|
||||||
// UnregisterWorkerHolder.
|
|
||||||
MOZ_ASSERT(IsClosed());
|
MOZ_ASSERT(IsClosed());
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
MOZ_ASSERT(IsCurrentThreadRunningWorker());
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
mWorkerRef = nullptr;
|
||||||
// The DTOR of this WorkerHolder will release the worker for us.
|
|
||||||
mWorkerHolder = nullptr;
|
|
||||||
mWorkerPrivate = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1896,11 +1892,11 @@ EventSourceImpl::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
|
||||||
if (IsShutDown()) {
|
if (IsShutDown()) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
|
||||||
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
|
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
|
||||||
// runnable.
|
// runnable.
|
||||||
RefPtr<WorkerRunnableDispatcher> event =
|
RefPtr<WorkerRunnableDispatcher> event =
|
||||||
new WorkerRunnableDispatcher(this, mWorkerPrivate, event_ref.forget());
|
new WorkerRunnableDispatcher(this, mWorkerRef->Private(), event_ref.forget());
|
||||||
|
|
||||||
if (!event->Dispatch()) {
|
if (!event->Dispatch()) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -1982,23 +1978,53 @@ EventSource::Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
eventSourceImp->Init(principal, aURL, aRv);
|
eventSourceImp->Init(principal, aURL, aRv);
|
||||||
} else {
|
|
||||||
// In workers we have to keep the worker alive using a WorkerHolder in order
|
|
||||||
// to dispatch messages correctly.
|
|
||||||
if (!eventSourceImp->RegisterWorkerHolder()) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
RefPtr<InitRunnable> runnable = new InitRunnable(eventSourceImp, aURL);
|
|
||||||
runnable->Dispatch(Terminating, aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
aRv = runnable->ErrorCode();
|
|
||||||
|
eventSourceImp->InitChannelAndRequestEventSource();
|
||||||
|
return eventSource.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Worker side.
|
||||||
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||||
|
MOZ_ASSERT(workerPrivate);
|
||||||
|
|
||||||
|
RefPtr<InitRunnable> initRunnable =
|
||||||
|
new InitRunnable(workerPrivate, eventSourceImp, aURL);
|
||||||
|
initRunnable->Dispatch(Terminating, aRv);
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aRv = initRunnable->ErrorCode();
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In workers we have to keep the worker alive using a WorkerRef in order
|
||||||
|
// to dispatch messages correctly.
|
||||||
|
if (!eventSourceImp->CreateWorkerRef(workerPrivate)) {
|
||||||
|
// The worker is already shutting down. Let's return an already closed
|
||||||
|
// object, but marked as Connecting.
|
||||||
|
eventSource->Close();
|
||||||
|
|
||||||
|
// EventSourceImpl must be released before returning the object, otherwise
|
||||||
|
// it will set EventSource to a CLOSED state in its DTOR.
|
||||||
|
eventSourceImp = nullptr;
|
||||||
|
|
||||||
|
eventSource->mReadyState = EventSourceImpl::CONNECTING;
|
||||||
|
return eventSource.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's connect to the server.
|
||||||
|
RefPtr<ConnectRunnable> connectRunnable =
|
||||||
|
new ConnectRunnable(workerPrivate, eventSourceImp);
|
||||||
|
connectRunnable->Dispatch(Terminating, aRv);
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return eventSource.forget();
|
return eventSource.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ struct LinkedProgramInfo final
|
||||||
: public RefCounted<LinkedProgramInfo>
|
: public RefCounted<LinkedProgramInfo>
|
||||||
, public SupportsWeakPtr<LinkedProgramInfo>
|
, public SupportsWeakPtr<LinkedProgramInfo>
|
||||||
{
|
{
|
||||||
friend class WebGLProgram;
|
friend class mozilla::WebGLProgram;
|
||||||
|
|
||||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo)
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo)
|
||||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo)
|
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
52547
|
52568
|
||||||
0/nm
|
0/nm
|
||||||
0th/pt
|
0th/pt
|
||||||
1/n1
|
1/n1
|
||||||
|
@ -14713,6 +14713,7 @@ anticyclonic
|
||||||
antidemocratic
|
antidemocratic
|
||||||
antidepressant/MS
|
antidepressant/MS
|
||||||
antidote/MS
|
antidote/MS
|
||||||
|
antifa
|
||||||
antifascist/MS
|
antifascist/MS
|
||||||
antifreeze/M
|
antifreeze/M
|
||||||
antigen/SM
|
antigen/SM
|
||||||
|
@ -16936,6 +16937,7 @@ blockader/M
|
||||||
blockage/MS
|
blockage/MS
|
||||||
blockbuster/SM
|
blockbuster/SM
|
||||||
blockbusting/M
|
blockbusting/M
|
||||||
|
blockchain/S
|
||||||
blocker/MS
|
blocker/MS
|
||||||
blockhead/SM
|
blockhead/SM
|
||||||
blockhouse/MS
|
blockhouse/MS
|
||||||
|
@ -22428,6 +22430,7 @@ demonstration/M
|
||||||
demonstrative/MYSP
|
demonstrative/MYSP
|
||||||
demonstrativeness/M
|
demonstrativeness/M
|
||||||
demonstrator/MS
|
demonstrator/MS
|
||||||
|
demonym/S
|
||||||
demote/GD
|
demote/GD
|
||||||
demotic
|
demotic
|
||||||
demount
|
demount
|
||||||
|
@ -24433,6 +24436,7 @@ ember/SM
|
||||||
embezzle/ZGLDRS
|
embezzle/ZGLDRS
|
||||||
embezzlement/M
|
embezzlement/M
|
||||||
embezzler/M
|
embezzler/M
|
||||||
|
embiggen
|
||||||
embitter/GLDS
|
embitter/GLDS
|
||||||
embitterment/M
|
embitterment/M
|
||||||
emblazon/GDLS
|
emblazon/GDLS
|
||||||
|
@ -27921,6 +27925,7 @@ glamorization/M
|
||||||
glamorize/DSG
|
glamorize/DSG
|
||||||
glamorous/Y
|
glamorous/Y
|
||||||
glamour/GMDS
|
glamour/GMDS
|
||||||
|
glamping
|
||||||
glance/DSMG
|
glance/DSMG
|
||||||
gland/SM
|
gland/SM
|
||||||
glandes
|
glandes
|
||||||
|
@ -28761,6 +28766,7 @@ hacktivist/MS
|
||||||
hackwork/M
|
hackwork/M
|
||||||
had
|
had
|
||||||
haddock/SM
|
haddock/SM
|
||||||
|
hadith/S
|
||||||
hadn't
|
hadn't
|
||||||
hadst
|
hadst
|
||||||
hafnium/M
|
hafnium/M
|
||||||
|
@ -28996,6 +29002,7 @@ harelip/SM
|
||||||
harelipped
|
harelipped
|
||||||
harem/SM
|
harem/SM
|
||||||
haricot/S
|
haricot/S
|
||||||
|
harissa
|
||||||
hark/DGS
|
hark/DGS
|
||||||
harlequin/SM
|
harlequin/SM
|
||||||
harlot/SM
|
harlot/SM
|
||||||
|
@ -29634,6 +29641,7 @@ hobnobbed
|
||||||
hobnobbing
|
hobnobbing
|
||||||
hobo/MS
|
hobo/MS
|
||||||
hoboes
|
hoboes
|
||||||
|
hoc
|
||||||
hock/MDSG
|
hock/MDSG
|
||||||
hockey/M
|
hockey/M
|
||||||
hockshop/MS
|
hockshop/MS
|
||||||
|
@ -32138,6 +32146,7 @@ kWh
|
||||||
kabbala
|
kabbala
|
||||||
kabbalah
|
kabbalah
|
||||||
kabob/SM
|
kabob/SM
|
||||||
|
kabocha
|
||||||
kaboom
|
kaboom
|
||||||
kabuki/M
|
kabuki/M
|
||||||
kaddish/MS
|
kaddish/MS
|
||||||
|
@ -32422,6 +32431,7 @@ kohl
|
||||||
kohlrabi/M
|
kohlrabi/M
|
||||||
kohlrabies
|
kohlrabies
|
||||||
kola/MS
|
kola/MS
|
||||||
|
kombucha
|
||||||
kook/MS
|
kook/MS
|
||||||
kookaburra/SM
|
kookaburra/SM
|
||||||
kookiness/M
|
kookiness/M
|
||||||
|
@ -34727,6 +34737,7 @@ microcode
|
||||||
microcomputer/MS
|
microcomputer/MS
|
||||||
microcosm/MS
|
microcosm/MS
|
||||||
microcosmic
|
microcosmic
|
||||||
|
microcredit
|
||||||
microdot/SM
|
microdot/SM
|
||||||
microeconomics/M
|
microeconomics/M
|
||||||
microelectronic/S
|
microelectronic/S
|
||||||
|
@ -34734,6 +34745,7 @@ microelectronics/M
|
||||||
microfiber/MS
|
microfiber/MS
|
||||||
microfiche/M
|
microfiche/M
|
||||||
microfilm/GMDS
|
microfilm/GMDS
|
||||||
|
microfinance
|
||||||
microfloppies
|
microfloppies
|
||||||
microgroove/SM
|
microgroove/SM
|
||||||
microlight/MS
|
microlight/MS
|
||||||
|
@ -35258,6 +35270,7 @@ moistness/M
|
||||||
moisture/M
|
moisture/M
|
||||||
moisturize/ZGDRS
|
moisturize/ZGDRS
|
||||||
moisturizer/M
|
moisturizer/M
|
||||||
|
mojo/S
|
||||||
molar/SM
|
molar/SM
|
||||||
molasses/M
|
molasses/M
|
||||||
mold/MDRJSZG
|
mold/MDRJSZG
|
||||||
|
@ -36143,6 +36156,7 @@ nelson/SM
|
||||||
nematode/SM
|
nematode/SM
|
||||||
nemeses
|
nemeses
|
||||||
nemesis/M
|
nemesis/M
|
||||||
|
neoadjuvant
|
||||||
neoclassic
|
neoclassic
|
||||||
neoclassical
|
neoclassical
|
||||||
neoclassicism/M
|
neoclassicism/M
|
||||||
|
@ -37995,6 +38009,7 @@ oxygenate/DSGN
|
||||||
oxygenation/M
|
oxygenation/M
|
||||||
oxymora
|
oxymora
|
||||||
oxymoron/M
|
oxymoron/M
|
||||||
|
oy
|
||||||
oyes
|
oyes
|
||||||
oyez
|
oyez
|
||||||
oyster/SM
|
oyster/SM
|
||||||
|
@ -42412,6 +42427,7 @@ respectful/EY
|
||||||
respectfulness/M
|
respectfulness/M
|
||||||
respective/Y
|
respective/Y
|
||||||
respell/SGD
|
respell/SGD
|
||||||
|
respellings
|
||||||
respiration/M
|
respiration/M
|
||||||
respirator/SM
|
respirator/SM
|
||||||
respiratory
|
respiratory
|
||||||
|
@ -44946,6 +44962,7 @@ site/MGDS
|
||||||
sitemap/SM
|
sitemap/SM
|
||||||
sitter/SM
|
sitter/SM
|
||||||
sitting/SM
|
sitting/SM
|
||||||
|
situ
|
||||||
situate/DSXGN
|
situate/DSXGN
|
||||||
situation/M
|
situation/M
|
||||||
situational
|
situational
|
||||||
|
@ -45404,7 +45421,7 @@ snarly/TR
|
||||||
snatch/ZGMDRS
|
snatch/ZGMDRS
|
||||||
snatcher/M
|
snatcher/M
|
||||||
snazzily
|
snazzily
|
||||||
snazzy/TR
|
snazzy/TRP
|
||||||
sneak/SMDRZG
|
sneak/SMDRZG
|
||||||
sneaker/M
|
sneaker/M
|
||||||
sneakily
|
sneakily
|
||||||
|
@ -47117,6 +47134,7 @@ subtrahend/SM
|
||||||
subtropic/S
|
subtropic/S
|
||||||
subtropical
|
subtropical
|
||||||
subtropics/M
|
subtropics/M
|
||||||
|
subtweet/S
|
||||||
suburb/MS
|
suburb/MS
|
||||||
suburban/SM
|
suburban/SM
|
||||||
suburbanite/SM
|
suburbanite/SM
|
||||||
|
@ -49875,6 +49893,7 @@ tyrannous
|
||||||
tyranny/SM
|
tyranny/SM
|
||||||
tyrant/SM
|
tyrant/SM
|
||||||
tyro/MS
|
tyro/MS
|
||||||
|
tzatziki
|
||||||
u/S
|
u/S
|
||||||
ubiquitous/Y
|
ubiquitous/Y
|
||||||
ubiquity/M
|
ubiquity/M
|
||||||
|
@ -51565,6 +51584,7 @@ wellington/MS
|
||||||
wellness/M
|
wellness/M
|
||||||
wellspring/MS
|
wellspring/MS
|
||||||
welly/S
|
welly/S
|
||||||
|
welp
|
||||||
welsh/ZGDRS
|
welsh/ZGDRS
|
||||||
welsher/M
|
welsher/M
|
||||||
welt/MDRSZG
|
welt/MDRSZG
|
||||||
|
@ -52104,6 +52124,7 @@ word's
|
||||||
word/ADSG
|
word/ADSG
|
||||||
wordage/M
|
wordage/M
|
||||||
wordbook/SM
|
wordbook/SM
|
||||||
|
wordie/S
|
||||||
wordily
|
wordily
|
||||||
wordiness/M
|
wordiness/M
|
||||||
wording/SM
|
wording/SM
|
||||||
|
|
|
@ -195,7 +195,7 @@ struct nsGridContainerFrame::TrackSize
|
||||||
eMaxContentMinSizing = 0x4,
|
eMaxContentMinSizing = 0x4,
|
||||||
eMinOrMaxContentMinSizing = eMinContentMinSizing | eMaxContentMinSizing,
|
eMinOrMaxContentMinSizing = eMinContentMinSizing | eMaxContentMinSizing,
|
||||||
eIntrinsicMinSizing = eMinOrMaxContentMinSizing | eAutoMinSizing,
|
eIntrinsicMinSizing = eMinOrMaxContentMinSizing | eAutoMinSizing,
|
||||||
// 0x8 is unused, feel free to take it!
|
eModified = 0x8,
|
||||||
eAutoMaxSizing = 0x10,
|
eAutoMaxSizing = 0x10,
|
||||||
eMinContentMaxSizing = 0x20,
|
eMinContentMaxSizing = 0x20,
|
||||||
eMaxContentMaxSizing = 0x40,
|
eMaxContentMaxSizing = 0x40,
|
||||||
|
@ -208,6 +208,7 @@ struct nsGridContainerFrame::TrackSize
|
||||||
eSkipGrowUnlimited = eSkipGrowUnlimited1 | eSkipGrowUnlimited2,
|
eSkipGrowUnlimited = eSkipGrowUnlimited1 | eSkipGrowUnlimited2,
|
||||||
eBreakBefore = 0x800,
|
eBreakBefore = 0x800,
|
||||||
eFitContent = 0x1000,
|
eFitContent = 0x1000,
|
||||||
|
eInfinitelyGrowable = 0x2000,
|
||||||
};
|
};
|
||||||
|
|
||||||
StateBits Initialize(nscoord aPercentageBasis,
|
StateBits Initialize(nscoord aPercentageBasis,
|
||||||
|
@ -1139,6 +1140,61 @@ struct nsGridContainerFrame::Tracks
|
||||||
*/
|
*/
|
||||||
void AlignBaselineSubtree(const GridItemInfo& aGridItem) const;
|
void AlignBaselineSubtree(const GridItemInfo& aGridItem) const;
|
||||||
|
|
||||||
|
enum class TrackSizingPhase
|
||||||
|
{
|
||||||
|
eIntrinsicMinimums,
|
||||||
|
eContentBasedMinimums,
|
||||||
|
eMaxContentMinimums,
|
||||||
|
eIntrinsicMaximums,
|
||||||
|
eMaxContentMaximums,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Some data we collect on each item for Step 2 of the Track Sizing Algorithm
|
||||||
|
// in ResolveIntrinsicSize below.
|
||||||
|
struct Step2ItemData final
|
||||||
|
{
|
||||||
|
uint32_t mSpan;
|
||||||
|
TrackSize::StateBits mState;
|
||||||
|
LineRange mLineRange;
|
||||||
|
nscoord mMinSize;
|
||||||
|
nscoord mMinContentContribution;
|
||||||
|
nscoord mMaxContentContribution;
|
||||||
|
nsIFrame* mFrame;
|
||||||
|
static bool IsSpanLessThan(const Step2ItemData& a, const Step2ItemData& b)
|
||||||
|
{
|
||||||
|
return a.mSpan < b.mSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<TrackSizingPhase phase>
|
||||||
|
nscoord SizeContributionForPhase() const
|
||||||
|
{
|
||||||
|
switch (phase) {
|
||||||
|
case TrackSizingPhase::eIntrinsicMinimums:
|
||||||
|
case TrackSizingPhase::eIntrinsicMaximums:
|
||||||
|
return mMinSize;
|
||||||
|
case TrackSizingPhase::eContentBasedMinimums:
|
||||||
|
return mMinContentContribution;
|
||||||
|
case TrackSizingPhase::eMaxContentMinimums:
|
||||||
|
case TrackSizingPhase::eMaxContentMaximums:
|
||||||
|
return mMaxContentContribution;
|
||||||
|
}
|
||||||
|
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected phase");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using FitContentClamper =
|
||||||
|
std::function<bool(uint32_t aTrack, nscoord aMinSize, nscoord* aSize)>;
|
||||||
|
|
||||||
|
// Helper method for ResolveIntrinsicSize.
|
||||||
|
template<TrackSizingPhase phase>
|
||||||
|
bool GrowSizeForSpanningItems(nsTArray<Step2ItemData>::iterator aIter,
|
||||||
|
const nsTArray<Step2ItemData>::iterator aEnd,
|
||||||
|
nsTArray<uint32_t>& aTracks,
|
||||||
|
nsTArray<TrackSize>& aPlan,
|
||||||
|
nsTArray<TrackSize>& aItemPlan,
|
||||||
|
TrackSize::StateBits aSelector,
|
||||||
|
const FitContentClamper& aClamper = nullptr,
|
||||||
|
bool aNeedInfinitelyGrowableFlag = false);
|
||||||
/**
|
/**
|
||||||
* Resolve Intrinsic Track Sizes.
|
* Resolve Intrinsic Track Sizes.
|
||||||
* http://dev.w3.org/csswg/css-grid/#algo-content
|
* http://dev.w3.org/csswg/css-grid/#algo-content
|
||||||
|
@ -1161,66 +1217,117 @@ struct nsGridContainerFrame::Tracks
|
||||||
SizingConstraint aConstraint,
|
SizingConstraint aConstraint,
|
||||||
const LineRange& aRange,
|
const LineRange& aRange,
|
||||||
const GridItemInfo& aGridItem);
|
const GridItemInfo& aGridItem);
|
||||||
|
|
||||||
|
// Helper method that returns the track size to use in §11.5.1.2
|
||||||
|
// https://drafts.csswg.org/css-grid/#extra-space
|
||||||
|
template<TrackSizingPhase phase> static
|
||||||
|
nscoord StartSizeInDistribution(const TrackSize& aSize)
|
||||||
|
{
|
||||||
|
switch (phase) {
|
||||||
|
case TrackSizingPhase::eIntrinsicMinimums:
|
||||||
|
case TrackSizingPhase::eContentBasedMinimums:
|
||||||
|
case TrackSizingPhase::eMaxContentMinimums:
|
||||||
|
return aSize.mBase;
|
||||||
|
case TrackSizingPhase::eIntrinsicMaximums:
|
||||||
|
case TrackSizingPhase::eMaxContentMaximums:
|
||||||
|
if (aSize.mLimit == NS_UNCONSTRAINEDSIZE) {
|
||||||
|
return aSize.mBase;
|
||||||
|
}
|
||||||
|
return aSize.mLimit;
|
||||||
|
}
|
||||||
|
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected phase");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect the tracks which are growable (matching aSelector) into
|
* Collect the tracks which are growable (matching aSelector) into
|
||||||
* aGrowableTracks, and return the amount of space that can be used
|
* aGrowableTracks, and return the amount of space that can be used
|
||||||
* to grow those tracks. Specifically, we return aAvailableSpace minus
|
* to grow those tracks. This method implements CSS Grid §11.5.1.2.
|
||||||
* the sum of mBase's (and corresponding grid gaps) in aPlan (clamped to 0)
|
* https://drafts.csswg.org/css-grid/#extra-space
|
||||||
* for the tracks in aRange, or zero when there are no growable tracks.
|
|
||||||
* @note aPlan[*].mBase represents a planned new base or limit.
|
|
||||||
*/
|
*/
|
||||||
nscoord CollectGrowable(nscoord aAvailableSpace,
|
template<TrackSizingPhase phase>
|
||||||
const nsTArray<TrackSize>& aPlan,
|
nscoord CollectGrowable(nscoord aAvailableSpace,
|
||||||
const LineRange& aRange,
|
const LineRange& aRange,
|
||||||
TrackSize::StateBits aSelector,
|
TrackSize::StateBits aSelector,
|
||||||
nsTArray<uint32_t>& aGrowableTracks) const
|
nsTArray<uint32_t>& aGrowableTracks) const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aAvailableSpace > 0, "why call me?");
|
MOZ_ASSERT(aAvailableSpace > 0, "why call me?");
|
||||||
nscoord space = aAvailableSpace - mGridGap * (aRange.Extent() - 1);
|
nscoord space = aAvailableSpace - mGridGap * (aRange.Extent() - 1);
|
||||||
const uint32_t start = aRange.mStart;
|
const uint32_t start = aRange.mStart;
|
||||||
const uint32_t end = aRange.mEnd;
|
const uint32_t end = aRange.mEnd;
|
||||||
for (uint32_t i = start; i < end; ++i) {
|
for (uint32_t i = start; i < end; ++i) {
|
||||||
const TrackSize& sz = aPlan[i];
|
const TrackSize& sz = mSizes[i];
|
||||||
space -= sz.mBase;
|
space -= StartSizeInDistribution<phase>(sz);
|
||||||
if (space <= 0) {
|
if (space <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((sz.mState & aSelector) && !sz.IsFrozen()) {
|
if (sz.mState & aSelector) {
|
||||||
aGrowableTracks.AppendElement(i);
|
aGrowableTracks.AppendElement(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return aGrowableTracks.IsEmpty() ? 0 : space;
|
return aGrowableTracks.IsEmpty() ? 0 : space;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupGrowthPlan(nsTArray<TrackSize>& aPlan,
|
template<TrackSizingPhase phase>
|
||||||
const nsTArray<uint32_t>& aTracks) const
|
void InitializeItemPlan(nsTArray<TrackSize>& aItemPlan,
|
||||||
|
const nsTArray<uint32_t>& aTracks) const
|
||||||
{
|
{
|
||||||
for (uint32_t track : aTracks) {
|
for (uint32_t track : aTracks) {
|
||||||
aPlan[track] = mSizes[track];
|
auto& plan = aItemPlan[track];
|
||||||
|
const TrackSize& sz = mSizes[track];
|
||||||
|
plan.mBase = StartSizeInDistribution<phase>(sz);
|
||||||
|
bool unlimited = sz.mState & TrackSize::eInfinitelyGrowable;
|
||||||
|
plan.mLimit = unlimited ? NS_UNCONSTRAINEDSIZE : sz.mLimit;
|
||||||
|
plan.mState = sz.mState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyPlanToBase(const nsTArray<TrackSize>& aPlan,
|
template<TrackSizingPhase phase>
|
||||||
const nsTArray<uint32_t>& aTracks)
|
void InitializePlan(nsTArray<TrackSize>& aPlan) const
|
||||||
{
|
{
|
||||||
for (uint32_t track : aTracks) {
|
for (size_t i = 0, len = aPlan.Length(); i < len; ++i) {
|
||||||
MOZ_ASSERT(mSizes[track].mBase <= aPlan[track].mBase);
|
auto& plan = aPlan[i];
|
||||||
mSizes[track].mBase = aPlan[track].mBase;
|
const auto& sz = mSizes[i];
|
||||||
|
plan.mBase = StartSizeInDistribution<phase>(sz);
|
||||||
|
MOZ_ASSERT(phase == TrackSizingPhase::eMaxContentMaximums ||
|
||||||
|
!(sz.mState & TrackSize::eInfinitelyGrowable),
|
||||||
|
"forgot to reset the eInfinitelyGrowable bit?");
|
||||||
|
plan.mState = sz.mState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyPlanToLimit(const nsTArray<TrackSize>& aPlan,
|
template<TrackSizingPhase phase>
|
||||||
const nsTArray<uint32_t>& aTracks)
|
void CopyPlanToSize(const nsTArray<TrackSize>& aPlan,
|
||||||
|
bool aNeedInfinitelyGrowableFlag = false)
|
||||||
{
|
{
|
||||||
for (uint32_t track : aTracks) {
|
for (size_t i = 0, len = mSizes.Length(); i < len; ++i) {
|
||||||
MOZ_ASSERT(mSizes[track].mLimit == NS_UNCONSTRAINEDSIZE ||
|
const auto& plan = aPlan[i];
|
||||||
mSizes[track].mLimit <= aPlan[track].mBase);
|
MOZ_ASSERT(plan.mBase >= 0);
|
||||||
mSizes[track].mLimit = aPlan[track].mBase;
|
auto& sz = mSizes[i];
|
||||||
|
switch (phase) {
|
||||||
|
case TrackSizingPhase::eIntrinsicMinimums:
|
||||||
|
case TrackSizingPhase::eContentBasedMinimums:
|
||||||
|
case TrackSizingPhase::eMaxContentMinimums:
|
||||||
|
sz.mBase = plan.mBase;
|
||||||
|
break;
|
||||||
|
case TrackSizingPhase::eIntrinsicMaximums:
|
||||||
|
if (plan.mState & TrackSize::eModified) {
|
||||||
|
if (sz.mLimit == NS_UNCONSTRAINEDSIZE &&
|
||||||
|
aNeedInfinitelyGrowableFlag) {
|
||||||
|
sz.mState |= TrackSize::eInfinitelyGrowable;
|
||||||
|
}
|
||||||
|
sz.mLimit = plan.mBase;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TrackSizingPhase::eMaxContentMaximums:
|
||||||
|
if (plan.mState & TrackSize::eModified) {
|
||||||
|
sz.mLimit = plan.mBase;
|
||||||
|
}
|
||||||
|
sz.mState &= ~TrackSize::eInfinitelyGrowable;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using FitContentClamper =
|
|
||||||
std::function<bool(uint32_t aTrack, nscoord aMinSize, nscoord* aSize)>;
|
|
||||||
/**
|
/**
|
||||||
* Grow the planned size for tracks in aGrowableTracks up to their limit
|
* Grow the planned size for tracks in aGrowableTracks up to their limit
|
||||||
* and then freeze them (all aGrowableTracks must be unfrozen on entry).
|
* and then freeze them (all aGrowableTracks must be unfrozen on entry).
|
||||||
|
@ -1280,12 +1387,13 @@ struct nsGridContainerFrame::Tracks
|
||||||
* assumed that aPlan have no aSkipFlag set for tracks in aGrowableTracks
|
* assumed that aPlan have no aSkipFlag set for tracks in aGrowableTracks
|
||||||
* on entry to this method.
|
* on entry to this method.
|
||||||
*/
|
*/
|
||||||
uint32_t MarkExcludedTracks(nsTArray<TrackSize>& aPlan,
|
static uint32_t
|
||||||
uint32_t aNumGrowable,
|
MarkExcludedTracks(nsTArray<TrackSize>& aPlan,
|
||||||
const nsTArray<uint32_t>& aGrowableTracks,
|
uint32_t aNumGrowable,
|
||||||
TrackSize::StateBits aMinSizingSelector,
|
const nsTArray<uint32_t>& aGrowableTracks,
|
||||||
TrackSize::StateBits aMaxSizingSelector,
|
TrackSize::StateBits aMinSizingSelector,
|
||||||
TrackSize::StateBits aSkipFlag) const
|
TrackSize::StateBits aMaxSizingSelector,
|
||||||
|
TrackSize::StateBits aSkipFlag)
|
||||||
{
|
{
|
||||||
bool foundOneSelected = false;
|
bool foundOneSelected = false;
|
||||||
bool foundOneGrowable = false;
|
bool foundOneGrowable = false;
|
||||||
|
@ -1315,41 +1423,60 @@ struct nsGridContainerFrame::Tracks
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increase the planned size for tracks in aGrowableTracks that match
|
* Mark all tracks in aGrowableTracks with an eSkipGrowUnlimited bit if
|
||||||
* aSelector (or all tracks if aSelector is zero) beyond their limit.
|
* they *shouldn't* grow unlimited in §11.5.1.2.3 "Distribute space beyond
|
||||||
|
* growth limits" https://drafts.csswg.org/css-grid/#extra-space
|
||||||
|
* Return the number of tracks that are still growable.
|
||||||
|
*/
|
||||||
|
template<TrackSizingPhase phase>
|
||||||
|
static uint32_t
|
||||||
|
MarkExcludedTracks(nsTArray<TrackSize>& aPlan,
|
||||||
|
const nsTArray<uint32_t>& aGrowableTracks,
|
||||||
|
TrackSize::StateBits aSelector)
|
||||||
|
{
|
||||||
|
uint32_t numGrowable = aGrowableTracks.Length();
|
||||||
|
if (phase == TrackSizingPhase::eIntrinsicMaximums ||
|
||||||
|
phase == TrackSizingPhase::eMaxContentMaximums) {
|
||||||
|
// "when handling any intrinsic growth limit: all affected tracks"
|
||||||
|
return numGrowable;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(aSelector == (aSelector & TrackSize::eIntrinsicMinSizing) &&
|
||||||
|
(aSelector & TrackSize::eMaxContentMinSizing),
|
||||||
|
"Should only get here for track sizing steps 2.1 to 2.3");
|
||||||
|
// Note that eMaxContentMinSizing is always included. We do those first:
|
||||||
|
numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks,
|
||||||
|
TrackSize::eMaxContentMinSizing,
|
||||||
|
TrackSize::eMaxContentMaxSizing,
|
||||||
|
TrackSize::eSkipGrowUnlimited1);
|
||||||
|
// Now mark min-content/auto min-sizing tracks if requested.
|
||||||
|
auto minOrAutoSelector = aSelector & ~TrackSize::eMaxContentMinSizing;
|
||||||
|
if (minOrAutoSelector) {
|
||||||
|
numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks,
|
||||||
|
minOrAutoSelector,
|
||||||
|
TrackSize::eIntrinsicMaxSizing,
|
||||||
|
TrackSize::eSkipGrowUnlimited2);
|
||||||
|
}
|
||||||
|
return numGrowable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase the planned size for tracks in aGrowableTracks that aren't
|
||||||
|
* marked with a eSkipGrowUnlimited flag beyond their limit.
|
||||||
* This implements the "Distribute space beyond growth limits" step in
|
* This implements the "Distribute space beyond growth limits" step in
|
||||||
* https://drafts.csswg.org/css-grid/#distribute-extra-space
|
* https://drafts.csswg.org/css-grid/#distribute-extra-space
|
||||||
*/
|
*/
|
||||||
void GrowSelectedTracksUnlimited(nscoord aAvailableSpace,
|
void GrowSelectedTracksUnlimited(nscoord aAvailableSpace,
|
||||||
nsTArray<TrackSize>& aPlan,
|
nsTArray<TrackSize>& aPlan,
|
||||||
const nsTArray<uint32_t>& aGrowableTracks,
|
const nsTArray<uint32_t>& aGrowableTracks,
|
||||||
TrackSize::StateBits aSelector,
|
uint32_t aNumGrowable,
|
||||||
const FitContentClamper& aFitContentClamper) const
|
const FitContentClamper& aFitContentClamper) const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aAvailableSpace > 0 && aGrowableTracks.Length() > 0);
|
MOZ_ASSERT(aAvailableSpace > 0 && aGrowableTracks.Length() > 0 &&
|
||||||
uint32_t numGrowable = aGrowableTracks.Length();
|
aNumGrowable <= aGrowableTracks.Length());
|
||||||
if (aSelector) {
|
|
||||||
MOZ_ASSERT(aSelector == (aSelector & TrackSize::eIntrinsicMinSizing) &&
|
|
||||||
(aSelector & TrackSize::eMaxContentMinSizing),
|
|
||||||
"Should only get here for track sizing steps 2.1 to 2.3");
|
|
||||||
// Note that eMaxContentMinSizing is always included. We do those first:
|
|
||||||
numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks,
|
|
||||||
TrackSize::eMaxContentMinSizing,
|
|
||||||
TrackSize::eMaxContentMaxSizing,
|
|
||||||
TrackSize::eSkipGrowUnlimited1);
|
|
||||||
// Now mark min-content/auto min-sizing tracks if requested.
|
|
||||||
auto minOrAutoSelector = aSelector & ~TrackSize::eMaxContentMinSizing;
|
|
||||||
if (minOrAutoSelector) {
|
|
||||||
numGrowable = MarkExcludedTracks(aPlan, numGrowable, aGrowableTracks,
|
|
||||||
minOrAutoSelector,
|
|
||||||
TrackSize::eIntrinsicMaxSizing,
|
|
||||||
TrackSize::eSkipGrowUnlimited2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nscoord space = aAvailableSpace;
|
nscoord space = aAvailableSpace;
|
||||||
DebugOnly<bool> didClamp = false;
|
DebugOnly<bool> didClamp = false;
|
||||||
while (numGrowable) {
|
while (aNumGrowable) {
|
||||||
nscoord spacePerTrack = std::max<nscoord>(space / numGrowable, 1);
|
nscoord spacePerTrack = std::max<nscoord>(space / aNumGrowable, 1);
|
||||||
for (uint32_t track : aGrowableTracks) {
|
for (uint32_t track : aGrowableTracks) {
|
||||||
TrackSize& sz = aPlan[track];
|
TrackSize& sz = aPlan[track];
|
||||||
if (sz.mState & TrackSize::eSkipGrowUnlimited) {
|
if (sz.mState & TrackSize::eSkipGrowUnlimited) {
|
||||||
|
@ -1365,7 +1492,7 @@ struct nsGridContainerFrame::Tracks
|
||||||
delta = newBase - sz.mBase;
|
delta = newBase - sz.mBase;
|
||||||
MOZ_ASSERT(delta >= 0, "track size shouldn't shrink");
|
MOZ_ASSERT(delta >= 0, "track size shouldn't shrink");
|
||||||
sz.mState |= TrackSize::eSkipGrowUnlimited1;
|
sz.mState |= TrackSize::eSkipGrowUnlimited1;
|
||||||
--numGrowable;
|
--aNumGrowable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sz.mBase = newBase;
|
sz.mBase = newBase;
|
||||||
|
@ -1384,46 +1511,30 @@ struct nsGridContainerFrame::Tracks
|
||||||
* Distribute aAvailableSpace to the planned base size for aGrowableTracks
|
* Distribute aAvailableSpace to the planned base size for aGrowableTracks
|
||||||
* up to their limits, then distribute the remaining space beyond the limits.
|
* up to their limits, then distribute the remaining space beyond the limits.
|
||||||
*/
|
*/
|
||||||
void DistributeToTrackBases(nscoord aAvailableSpace,
|
template<TrackSizingPhase phase>
|
||||||
|
void DistributeToTrackSizes(nscoord aAvailableSpace,
|
||||||
nsTArray<TrackSize>& aPlan,
|
nsTArray<TrackSize>& aPlan,
|
||||||
|
nsTArray<TrackSize>& aItemPlan,
|
||||||
nsTArray<uint32_t>& aGrowableTracks,
|
nsTArray<uint32_t>& aGrowableTracks,
|
||||||
TrackSize::StateBits aSelector)
|
TrackSize::StateBits aSelector,
|
||||||
|
const FitContentClamper& aFitContentClamper)
|
||||||
{
|
{
|
||||||
SetupGrowthPlan(aPlan, aGrowableTracks);
|
InitializeItemPlan<phase>(aItemPlan, aGrowableTracks);
|
||||||
nscoord space = GrowTracksToLimit(aAvailableSpace, aPlan, aGrowableTracks, nullptr);
|
nscoord space = GrowTracksToLimit(aAvailableSpace, aItemPlan, aGrowableTracks,
|
||||||
|
aFitContentClamper);
|
||||||
if (space > 0) {
|
if (space > 0) {
|
||||||
GrowSelectedTracksUnlimited(space, aPlan, aGrowableTracks, aSelector, nullptr);
|
uint32_t numGrowable =
|
||||||
|
MarkExcludedTracks<phase>(aItemPlan, aGrowableTracks, aSelector);
|
||||||
|
GrowSelectedTracksUnlimited(space, aItemPlan, aGrowableTracks,
|
||||||
|
numGrowable, aFitContentClamper);
|
||||||
}
|
}
|
||||||
CopyPlanToBase(aPlan, aGrowableTracks);
|
for (uint32_t track : aGrowableTracks) {
|
||||||
}
|
nscoord& plannedSize = aPlan[track].mBase;
|
||||||
|
nscoord itemIncurredSize = aItemPlan[track].mBase;
|
||||||
/**
|
if (plannedSize < itemIncurredSize) {
|
||||||
* Distribute aAvailableSpace to the planned limits for aGrowableTracks.
|
plannedSize = itemIncurredSize;
|
||||||
*/
|
|
||||||
void DistributeToTrackLimits(nscoord aAvailableSpace,
|
|
||||||
nsTArray<TrackSize>& aPlan,
|
|
||||||
nsTArray<uint32_t>& aGrowableTracks,
|
|
||||||
const TrackSizingFunctions& aFunctions,
|
|
||||||
nscoord aPercentageBasis)
|
|
||||||
{
|
|
||||||
auto fitContentClamper = [&aFunctions, aPercentageBasis] (uint32_t aTrack,
|
|
||||||
nscoord aMinSize,
|
|
||||||
nscoord* aSize) {
|
|
||||||
nscoord fitContentLimit =
|
|
||||||
::ResolveToDefiniteSize(aFunctions.MaxSizingFor(aTrack), aPercentageBasis);
|
|
||||||
if (*aSize > fitContentLimit) {
|
|
||||||
*aSize = std::max(aMinSize, fitContentLimit);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
};
|
|
||||||
nscoord space = GrowTracksToLimit(aAvailableSpace, aPlan, aGrowableTracks,
|
|
||||||
fitContentClamper);
|
|
||||||
if (space > 0) {
|
|
||||||
GrowSelectedTracksUnlimited(aAvailableSpace, aPlan, aGrowableTracks,
|
|
||||||
TrackSize::StateBits(0), fitContentClamper);
|
|
||||||
}
|
}
|
||||||
CopyPlanToLimit(aPlan, aGrowableTracks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4136,6 +4247,55 @@ nsGridContainerFrame::Tracks::AlignBaselineSubtree(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<nsGridContainerFrame::Tracks::TrackSizingPhase phase>
|
||||||
|
bool
|
||||||
|
nsGridContainerFrame::Tracks::GrowSizeForSpanningItems(
|
||||||
|
nsTArray<Step2ItemData>::iterator aIter,
|
||||||
|
const nsTArray<Step2ItemData>::iterator aIterEnd,
|
||||||
|
nsTArray<uint32_t>& aTracks,
|
||||||
|
nsTArray<TrackSize>& aPlan,
|
||||||
|
nsTArray<TrackSize>& aItemPlan,
|
||||||
|
TrackSize::StateBits aSelector,
|
||||||
|
const FitContentClamper& aFitContentClamper,
|
||||||
|
bool aNeedInfinitelyGrowableFlag)
|
||||||
|
{
|
||||||
|
constexpr bool isMaxSizingPhase =
|
||||||
|
phase == TrackSizingPhase::eIntrinsicMaximums ||
|
||||||
|
phase == TrackSizingPhase::eMaxContentMaximums;
|
||||||
|
bool needToUpdateSizes = false;
|
||||||
|
InitializePlan<phase>(aPlan);
|
||||||
|
for (; aIter != aIterEnd; ++aIter) {
|
||||||
|
const Step2ItemData& item = *aIter;
|
||||||
|
if (!(item.mState & aSelector)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isMaxSizingPhase) {
|
||||||
|
for (auto j = item.mLineRange.mStart, end = item.mLineRange.mEnd; j < end; ++j) {
|
||||||
|
aPlan[j].mState |= TrackSize::eModified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nscoord space = item.SizeContributionForPhase<phase>();
|
||||||
|
if (space <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
aTracks.ClearAndRetainStorage();
|
||||||
|
space = CollectGrowable<phase>(space, item.mLineRange, aSelector,
|
||||||
|
aTracks);
|
||||||
|
if (space > 0) {
|
||||||
|
DistributeToTrackSizes<phase>(space, aPlan, aItemPlan, aTracks, aSelector,
|
||||||
|
aFitContentClamper);
|
||||||
|
needToUpdateSizes = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMaxSizingPhase) {
|
||||||
|
needToUpdateSizes = true;
|
||||||
|
}
|
||||||
|
if (needToUpdateSizes) {
|
||||||
|
CopyPlanToSize<phase>(aPlan, aNeedInfinitelyGrowableFlag);
|
||||||
|
}
|
||||||
|
return needToUpdateSizes;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
|
nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
|
||||||
GridReflowInput& aState,
|
GridReflowInput& aState,
|
||||||
|
@ -4145,22 +4305,6 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
|
||||||
nscoord aPercentageBasis,
|
nscoord aPercentageBasis,
|
||||||
SizingConstraint aConstraint)
|
SizingConstraint aConstraint)
|
||||||
{
|
{
|
||||||
// Some data we collect on each item for Step 2 of the algorithm below.
|
|
||||||
struct Step2ItemData
|
|
||||||
{
|
|
||||||
uint32_t mSpan;
|
|
||||||
TrackSize::StateBits mState;
|
|
||||||
LineRange mLineRange;
|
|
||||||
nscoord mMinSize;
|
|
||||||
nscoord mMinContentContribution;
|
|
||||||
nscoord mMaxContentContribution;
|
|
||||||
nsIFrame* mFrame;
|
|
||||||
static bool IsSpanLessThan(const Step2ItemData& a, const Step2ItemData& b)
|
|
||||||
{
|
|
||||||
return a.mSpan < b.mSpan;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Resolve Intrinsic Track Sizes
|
// Resolve Intrinsic Track Sizes
|
||||||
// http://dev.w3.org/csswg/css-grid/#algo-content
|
// http://dev.w3.org/csswg/css-grid/#algo-content
|
||||||
// We're also setting eIsFlexing on the item state here to speed up
|
// We're also setting eIsFlexing on the item state here to speed up
|
||||||
|
@ -4270,6 +4414,19 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
if (maxSpan) {
|
if (maxSpan) {
|
||||||
|
auto fitContentClamper = [&aFunctions, aPercentageBasis] (uint32_t aTrack,
|
||||||
|
nscoord aMinSize,
|
||||||
|
nscoord* aSize)
|
||||||
|
{
|
||||||
|
nscoord fitContentLimit =
|
||||||
|
::ResolveToDefiniteSize(aFunctions.MaxSizingFor(aTrack), aPercentageBasis);
|
||||||
|
if (*aSize > fitContentLimit) {
|
||||||
|
*aSize = std::max(aMinSize, fitContentLimit);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
// Sort the collected items on span length, shortest first.
|
// Sort the collected items on span length, shortest first.
|
||||||
std::stable_sort(step2Items.begin(), step2Items.end(),
|
std::stable_sort(step2Items.begin(), step2Items.end(),
|
||||||
Step2ItemData::IsSpanLessThan);
|
Step2ItemData::IsSpanLessThan);
|
||||||
|
@ -4277,85 +4434,44 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
|
||||||
nsTArray<uint32_t> tracks(maxSpan);
|
nsTArray<uint32_t> tracks(maxSpan);
|
||||||
nsTArray<TrackSize> plan(mSizes.Length());
|
nsTArray<TrackSize> plan(mSizes.Length());
|
||||||
plan.SetLength(mSizes.Length());
|
plan.SetLength(mSizes.Length());
|
||||||
for (uint32_t i = 0, len = step2Items.Length(); i < len; ) {
|
nsTArray<TrackSize> itemPlan(mSizes.Length());
|
||||||
// Start / end index for items of the same span length:
|
itemPlan.SetLength(mSizes.Length());
|
||||||
const uint32_t spanGroupStartIndex = i;
|
// Start / end iterator for items of the same span length:
|
||||||
uint32_t spanGroupEndIndex = len;
|
auto spanGroupStart = step2Items.begin();
|
||||||
const uint32_t span = step2Items[i].mSpan;
|
auto spanGroupEnd = spanGroupStart;
|
||||||
for (++i; i < len; ++i) {
|
const auto end = step2Items.end();
|
||||||
if (step2Items[i].mSpan != span) {
|
for (; spanGroupStart != end; spanGroupStart = spanGroupEnd) {
|
||||||
spanGroupEndIndex = i;
|
while (spanGroupEnd != end &&
|
||||||
break;
|
!Step2ItemData::IsSpanLessThan(*spanGroupStart, *spanGroupEnd)) {
|
||||||
}
|
++spanGroupEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t span = spanGroupStart->mSpan;
|
||||||
bool updatedBase = false; // Did we update any mBase in step 2.1 - 2.3?
|
bool updatedBase = false; // Did we update any mBase in step 2.1 - 2.3?
|
||||||
TrackSize::StateBits selector(TrackSize::eIntrinsicMinSizing);
|
TrackSize::StateBits selector(TrackSize::eIntrinsicMinSizing);
|
||||||
if (stateBitsPerSpan[span] & selector) {
|
if (stateBitsPerSpan[span] & selector) {
|
||||||
// Step 2.1 MinSize to intrinsic min-sizing.
|
// Step 2.1 MinSize to intrinsic min-sizing.
|
||||||
for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) {
|
updatedBase =
|
||||||
Step2ItemData& item = step2Items[i];
|
GrowSizeForSpanningItems<TrackSizingPhase::eIntrinsicMinimums>(
|
||||||
if (!(item.mState & selector)) {
|
spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nscoord space = item.mMinSize;
|
|
||||||
if (space <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tracks.ClearAndRetainStorage();
|
|
||||||
space = CollectGrowable(space, mSizes, item.mLineRange, selector,
|
|
||||||
tracks);
|
|
||||||
if (space > 0) {
|
|
||||||
DistributeToTrackBases(space, plan, tracks, selector);
|
|
||||||
updatedBase = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selector = contentBasedMinSelector;
|
selector = contentBasedMinSelector;
|
||||||
if (stateBitsPerSpan[span] & selector) {
|
if (stateBitsPerSpan[span] & selector) {
|
||||||
// Step 2.2 MinContentContribution to min-/max-content (and 'auto' when
|
// Step 2.2 MinContentContribution to min-/max-content (and 'auto' when
|
||||||
// sizing under a min-content constraint) min-sizing.
|
// sizing under a min-content constraint) min-sizing.
|
||||||
for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) {
|
updatedBase |=
|
||||||
Step2ItemData& item = step2Items[i];
|
GrowSizeForSpanningItems<TrackSizingPhase::eContentBasedMinimums>(
|
||||||
if (!(item.mState & selector)) {
|
spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nscoord space = item.mMinContentContribution;
|
|
||||||
if (space <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tracks.ClearAndRetainStorage();
|
|
||||||
space = CollectGrowable(space, mSizes, item.mLineRange, selector,
|
|
||||||
tracks);
|
|
||||||
if (space > 0) {
|
|
||||||
DistributeToTrackBases(space, plan, tracks, selector);
|
|
||||||
updatedBase = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selector = maxContentMinSelector;
|
selector = maxContentMinSelector;
|
||||||
if (stateBitsPerSpan[span] & selector) {
|
if (stateBitsPerSpan[span] & selector) {
|
||||||
// Step 2.3 MaxContentContribution to max-content (and 'auto' when
|
// Step 2.3 MaxContentContribution to max-content (and 'auto' when
|
||||||
// sizing under a max-content constraint) min-sizing.
|
// sizing under a max-content constraint) min-sizing.
|
||||||
for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) {
|
updatedBase |=
|
||||||
Step2ItemData& item = step2Items[i];
|
GrowSizeForSpanningItems<TrackSizingPhase::eMaxContentMinimums>(
|
||||||
if (!(item.mState & selector)) {
|
spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nscoord space = item.mMaxContentContribution;
|
|
||||||
if (space <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tracks.ClearAndRetainStorage();
|
|
||||||
space = CollectGrowable(space, mSizes, item.mLineRange, selector,
|
|
||||||
tracks);
|
|
||||||
if (space > 0) {
|
|
||||||
DistributeToTrackBases(space, plan, tracks, selector);
|
|
||||||
updatedBase = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updatedBase) {
|
if (updatedBase) {
|
||||||
|
@ -4366,63 +4482,22 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stateBitsPerSpan[span] & TrackSize::eIntrinsicMaxSizing) {
|
|
||||||
plan = mSizes;
|
|
||||||
for (TrackSize& sz : plan) {
|
|
||||||
if (sz.mLimit == NS_UNCONSTRAINEDSIZE) {
|
|
||||||
// use mBase as the planned limit
|
|
||||||
} else {
|
|
||||||
sz.mBase = sz.mLimit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
selector = TrackSize::eIntrinsicMaxSizing;
|
||||||
|
if (stateBitsPerSpan[span] & selector) {
|
||||||
|
const bool willRunStep2_6 =
|
||||||
|
stateBitsPerSpan[span] & TrackSize::eAutoOrMaxContentMaxSizing;
|
||||||
// Step 2.5 MinSize to intrinsic max-sizing.
|
// Step 2.5 MinSize to intrinsic max-sizing.
|
||||||
for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) {
|
GrowSizeForSpanningItems<TrackSizingPhase::eIntrinsicMaximums>(
|
||||||
Step2ItemData& item = step2Items[i];
|
spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector,
|
||||||
if (!(item.mState & TrackSize::eIntrinsicMaxSizing)) {
|
fitContentClamper, willRunStep2_6);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nscoord space = item.mMinSize;
|
|
||||||
if (space <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tracks.ClearAndRetainStorage();
|
|
||||||
space = CollectGrowable(space, plan, item.mLineRange,
|
|
||||||
TrackSize::eIntrinsicMaxSizing,
|
|
||||||
tracks);
|
|
||||||
if (space > 0) {
|
|
||||||
DistributeToTrackLimits(space, plan, tracks, aFunctions,
|
|
||||||
aPercentageBasis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t j = 0, len = mSizes.Length(); j < len; ++j) {
|
|
||||||
TrackSize& sz = plan[j];
|
|
||||||
sz.mState &= ~(TrackSize::eFrozen | TrackSize::eSkipGrowUnlimited);
|
|
||||||
if (sz.mLimit != NS_UNCONSTRAINEDSIZE) {
|
|
||||||
sz.mLimit = sz.mBase; // collect the results from 2.5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stateBitsPerSpan[span] & TrackSize::eAutoOrMaxContentMaxSizing) {
|
if (willRunStep2_6) {
|
||||||
// Step 2.6 MaxContentContribution to max-content max-sizing.
|
// Step 2.6 MaxContentContribution to max-content max-sizing.
|
||||||
for (i = spanGroupStartIndex; i < spanGroupEndIndex; ++i) {
|
selector = TrackSize::eAutoOrMaxContentMaxSizing;
|
||||||
Step2ItemData& item = step2Items[i];
|
GrowSizeForSpanningItems<TrackSizingPhase::eMaxContentMaximums>(
|
||||||
if (!(item.mState & TrackSize::eAutoOrMaxContentMaxSizing)) {
|
spanGroupStart, spanGroupEnd, tracks, plan, itemPlan, selector,
|
||||||
continue;
|
fitContentClamper);
|
||||||
}
|
|
||||||
nscoord space = item.mMaxContentContribution;
|
|
||||||
if (space <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tracks.ClearAndRetainStorage();
|
|
||||||
space = CollectGrowable(space, plan, item.mLineRange,
|
|
||||||
TrackSize::eAutoOrMaxContentMaxSizing,
|
|
||||||
tracks);
|
|
||||||
if (space > 0) {
|
|
||||||
DistributeToTrackLimits(space, plan, tracks, aFunctions,
|
|
||||||
aPercentageBasis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6944,6 +7019,9 @@ nsGridContainerFrame::TrackSize::Dump() const
|
||||||
if (mState & eFrozen) {
|
if (mState & eFrozen) {
|
||||||
printf("frozen ");
|
printf("frozen ");
|
||||||
}
|
}
|
||||||
|
if (mState & eModified) {
|
||||||
|
printf("modified ");
|
||||||
|
}
|
||||||
if (mState & eBreakBefore) {
|
if (mState & eBreakBefore) {
|
||||||
printf("break-before ");
|
printf("break-before ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,3 +142,7 @@ support-files = file_scroll_position_restore.html
|
||||||
[test_scroll_position_restore_after_stop.html]
|
[test_scroll_position_restore_after_stop.html]
|
||||||
[test_scroll_animation_restore.html]
|
[test_scroll_animation_restore.html]
|
||||||
[test_scroll_position_iframe.html]
|
[test_scroll_position_iframe.html]
|
||||||
|
[test_grid_track_sizing_algo_001.html]
|
||||||
|
skip-if = debug == true # the test is slow
|
||||||
|
[test_grid_track_sizing_algo_002.html]
|
||||||
|
skip-if = debug == true # the test is slow
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -17,9 +17,9 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
|
||||||
clear:left;
|
clear:left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.c1 { min-width:40px; margin-bottom: 2px; margin-right: 47px; }
|
.c1 { width:40px; margin-bottom: 2px; margin-right: 47px; }
|
||||||
.r1 { min-width:70px; margin-left: 38px; margin-top: 2px; }
|
.r1 { min-width:70px; margin-left: 38px; margin-top: 2px; }
|
||||||
.c3 { min-width:0; margin: 2px 18px 1px 85px; }
|
.c3 { width:10px; margin: 2px 18px 1px 71px; }
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -52,21 +52,22 @@ x { display:inline-block; width:10px; height:18px; }
|
||||||
<span class="r1"><x> </x></span>
|
<span class="r1"><x> </x></span>
|
||||||
<span class="r1"><x> </x></span>
|
<span class="r1"><x> </x></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid" style="width:436px">
|
<div class="grid" style="width:436px">
|
||||||
<span class="c1" style="margin-right:41px"><x> </x></span>
|
<span class="c1" style="width:374px; margin-right:41px"><x> </x></span>
|
||||||
<span class="r1" style="margin-left:5px"><x> </x></span>
|
<span class="r1" style="margin-left:5px"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:405px; float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:405px; float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid" style="width:500px;">
|
<div class="grid" style="width:500px;">
|
||||||
<span class="c1" style="min-width:20px;margin-right:448px"><x> </x></span>
|
<span class="c1" style="width:20px;margin-right:448px"><x> </x></span>
|
||||||
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
||||||
<span class="r1" style="min-width:30px;margin-left:28px; margin-right:426px"><x> </x></span>
|
<span class="r1" style="min-width:30px;margin-left:28px; margin-right:426px"><x> </x></span>
|
||||||
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid" style="width:583px;">
|
<div class="grid" style="width:583px;">
|
||||||
<span class="c1" style="margin-right:55px"><x> </x></span>
|
<span class="c1" style="width:507px; margin-right:55px"><x> </x></span>
|
||||||
<span class="r1"><x> </x></span>
|
<span class="r1"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:538px; float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:538px; float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,13 +75,13 @@ x { display:inline-block; width:10px; height:18px; }
|
||||||
<div class="grid" style="width:389px;">
|
<div class="grid" style="width:389px;">
|
||||||
<span class="c1" style="width:100px"><x> </x></span>
|
<span class="c1" style="width:100px"><x> </x></span>
|
||||||
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid" style="width:389px;">
|
<div class="grid" style="width:389px;">
|
||||||
<span class="c1" style="width:100px"><x> </x></span>
|
<span class="c1" style="width:100px"><x> </x></span>
|
||||||
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,9 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
|
||||||
clear:left;
|
clear:left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.c1 { min-width:40px; margin-bottom: 2px; margin-right: 47px; }
|
.c1 { width:40px; margin-bottom: 2px; margin-right: 47px; }
|
||||||
.r1 { min-width:70px; margin-left: 38px; margin-top: 2px; }
|
.r1 { min-width:70px; margin-left: 38px; margin-top: 2px; }
|
||||||
.c3 { min-width:0; margin: 2px 18px 1px 85px; }
|
.c3 { width:10px; margin: 2px 18px 1px 71px; }
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -56,21 +56,22 @@ x { display:inline-block; width:10px; height:18px; }
|
||||||
<span class="r1"><x> </x></span>
|
<span class="r1"><x> </x></span>
|
||||||
<span class="r1"><x> </x></span>
|
<span class="r1"><x> </x></span>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
||||||
<div class="wrap"><div class="grid" style="width:436px">
|
<div class="wrap"><div class="grid" style="width:436px">
|
||||||
<span class="c1" style="margin-right:41px"><x> </x></span>
|
<span class="c1" style="width:374px; margin-right:41px"><x> </x></span>
|
||||||
<span class="r1" style="margin-left:5px"><x> </x></span>
|
<span class="r1" style="margin-left:5px"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:405px; float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:405px; float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
||||||
<div class="wrap" style="float:left;"><div class="grid" style="width:500px;">
|
<div class="wrap" style="float:left;"><div class="grid" style="width:500px;">
|
||||||
<span class="c1" style="min-width:20px;margin-right:448px"><x> </x></span>
|
<span class="c1" style="width:20px;margin-right:448px"><x> </x></span>
|
||||||
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
||||||
<span class="r1" style="min-width:30px;margin-left:28px; margin-right:426px"><x> </x></span>
|
<span class="r1" style="min-width:30px;margin-left:28px; margin-right:426px"><x> </x></span>
|
||||||
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
<span class="r1" style="min-width:10px;margin-left:28px; margin-right:426px"><x> </x></span>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
||||||
<div class="wrap"><div class="grid" style="width:583px;">
|
<div class="wrap"><div class="grid" style="width:583px;">
|
||||||
<span class="c1" style="margin-right:55px"><x> </x></span>
|
<span class="c1" style="width:507px; margin-right:55px"><x> </x></span>
|
||||||
<span class="r1"><x> </x></span>
|
<span class="r1"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:538px; float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:538px; float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
@ -78,13 +79,13 @@ x { display:inline-block; width:10px; height:18px; }
|
||||||
<div class="wrap"><div class="grid" style="width:389px;">
|
<div class="wrap"><div class="grid" style="width:389px;">
|
||||||
<span class="c1" style="width:100px"><x> </x></span>
|
<span class="c1" style="width:100px"><x> </x></span>
|
||||||
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
||||||
<div class="wrap"><div class="grid" style="width:389px;">
|
<div class="wrap"><div class="grid" style="width:389px;">
|
||||||
<span class="c1" style="width:100px"><x> </x></span>
|
<span class="c1" style="width:100px"><x> </x></span>
|
||||||
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
<span class="r1" style="width:300px;margin-left:68px;"><x> </x></span>
|
||||||
<span class="c3" style="margin-left:245px;float:left;margin-top:1px;"><x> </x></span>
|
<span class="c3" style="margin-left:131px;float:left;margin-top:1px;"><x> </x></span>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -127,10 +127,10 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
}
|
}
|
||||||
|
|
||||||
.gF {
|
.gF {
|
||||||
grid-template-columns: 22px
|
grid-template-columns: 2px
|
||||||
1px
|
20px
|
||||||
1px
|
2px
|
||||||
auto;
|
0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ x { display:inline-block; height:10px; width:18px; }
|
||||||
<div class="grid flex" style="width:1px;height:1px;"><span class="c1" style="margin-top:1px"><x></x></span></div>
|
<div class="grid flex" style="width:1px;height:1px;"><span class="c1" style="margin-top:1px"><x></x></span></div>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="grid mm" style="width:0;height:0;"><span class="c1" style="min-width:23px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div>
|
<div class="grid mm" style="width:0;height:0;"><span class="c1" style="min-width:18px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div>
|
||||||
<div class="grid mm" style="width:1px;height:1px;"><span class="c1" style="min-width:23px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div>
|
<div class="grid mm" style="width:1px;height:1px;"><span class="c1" style="min-width:18px;min-height:10px"><x></x></span><span class="c2" style="position:relative;left:14px;width:18px;min-width:0;z-index:-1"><x></x></span></div>
|
||||||
<!-- TODO: fails due to broken align:stretch
|
<!-- TODO: fails due to broken align:stretch
|
||||||
<div class="grid zero" style="width:0;height:0;"><span class="c1"><x></x></span></div>
|
<div class="grid zero" style="width:0;height:0;"><span class="c1"><x></x></span></div>
|
||||||
<div class="grid zero" style="width:1px;height:1px;"><span class="c1"><x></x></span></div>
|
<div class="grid zero" style="width:1px;height:1px;"><span class="c1"><x></x></span></div>
|
||||||
|
|
|
@ -27,34 +27,34 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
background: grey;
|
background: grey;
|
||||||
}
|
}
|
||||||
.g1 .d1 {
|
.g1 .d1 {
|
||||||
width: 52px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g2 .d1 {
|
.g2 .d1 {
|
||||||
width: 56px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g2f .d1 {
|
.g2f .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g3 .d1 {
|
.g3 .d1 {
|
||||||
width: 56px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g4 .d1 {
|
.g4 .d1 {
|
||||||
width: 96px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.g4f .d1 {
|
.g4f .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g5 .d1 {
|
.g5 .d1 {
|
||||||
width: 96px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.g6 .d1 {
|
.g6 .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g6f .d1 {
|
.g6f .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g7 .d1 {
|
.g7 .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g8 .t {
|
.g8 .t {
|
||||||
width: 196px;
|
width: 196px;
|
||||||
|
@ -63,19 +63,19 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
.g9 .d1 {
|
.g9 .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.gA .d1 {
|
.gA .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.gB .d1 {
|
.gB .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.gC .d1 {
|
.gC .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.gD .d1 {
|
.gD .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.t { grid-column: span 1; border:2px solid; }
|
.t { grid-column: span 1; border:2px solid; }
|
||||||
|
|
|
@ -27,34 +27,34 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
background: grey;
|
background: grey;
|
||||||
}
|
}
|
||||||
.g1 .d1 {
|
.g1 .d1 {
|
||||||
width: 52px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g2 .d1 {
|
.g2 .d1 {
|
||||||
width: 56px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g2f .d1 {
|
.g2f .d1 {
|
||||||
width: 69px;
|
width: 69px;
|
||||||
}
|
}
|
||||||
.g3 .d1 {
|
.g3 .d1 {
|
||||||
width: 56px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g4 .d1 {
|
.g4 .d1 {
|
||||||
width: 96px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.g4f .d1 {
|
.g4f .d1 {
|
||||||
width: 104px;
|
width: 104px;
|
||||||
}
|
}
|
||||||
.g5 .d1 {
|
.g5 .d1 {
|
||||||
width: 96px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.g6 .d1 {
|
.g6 .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g6f .d1 {
|
.g6f .d1 {
|
||||||
width: 89px;
|
width: 89px;
|
||||||
}
|
}
|
||||||
.g7 .d1 {
|
.g7 .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.g8 .t {
|
.g8 .t {
|
||||||
width: 196px;
|
width: 196px;
|
||||||
|
@ -63,19 +63,19 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
.g9 .d1 {
|
.g9 .d1 {
|
||||||
width: 69px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.gA .d1 {
|
.gA .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.gB .d1 {
|
.gB .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.gC .d1 {
|
.gC .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.gD .d1 {
|
.gD .d1 {
|
||||||
width: 93px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
.d2 {
|
.d2 {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -84,10 +84,10 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
background: blue;
|
background: blue;
|
||||||
}
|
}
|
||||||
.g1 .d2 {
|
.g1 .d2 {
|
||||||
width: 448px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
.g2 .d2 {
|
.g2 .d2 {
|
||||||
width: 444px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
.g2f .d2 {
|
.g2f .d2 {
|
||||||
right: auto;
|
right: auto;
|
||||||
|
@ -95,10 +95,10 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
width: 35px;
|
width: 35px;
|
||||||
}
|
}
|
||||||
.g3 .d2 {
|
.g3 .d2 {
|
||||||
width: 444px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
.g4 .d2 {
|
.g4 .d2 {
|
||||||
width: 404px;
|
width: 420px;
|
||||||
}
|
}
|
||||||
.g4f .d2 {
|
.g4f .d2 {
|
||||||
right: auto;
|
right: auto;
|
||||||
|
@ -106,10 +106,10 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
width: 35px;
|
width: 35px;
|
||||||
}
|
}
|
||||||
.g5 .d2 {
|
.g5 .d2 {
|
||||||
width: 404px;
|
width: 420px;
|
||||||
}
|
}
|
||||||
.g6 .d2 {
|
.g6 .d2 {
|
||||||
width: 431px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
.g6f .d2 {
|
.g6f .d2 {
|
||||||
right: auto;
|
right: auto;
|
||||||
|
@ -117,25 +117,25 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
||||||
width: 35px;
|
width: 35px;
|
||||||
}
|
}
|
||||||
.g7 .d2 {
|
.g7 .d2 {
|
||||||
width: 431px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
.g8 .d2 {
|
.g8 .d2 {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
.g9 .d2 {
|
.g9 .d2 {
|
||||||
width: 431px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
.gA .d2 {
|
.gA .d2 {
|
||||||
width: 407px;
|
width: 420px;
|
||||||
}
|
}
|
||||||
.gB .d2 {
|
.gB .d2 {
|
||||||
width: 407px;
|
width: 420px;
|
||||||
}
|
}
|
||||||
.gC .d2 {
|
.gC .d2 {
|
||||||
width: 407px;
|
width: 420px;
|
||||||
}
|
}
|
||||||
.gD .d2 {
|
.gD .d2 {
|
||||||
width: 407px;
|
width: 420px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.t { grid-column: span 1; border:2px solid; }
|
.t { grid-column: span 1; border:2px solid; }
|
||||||
|
|
|
@ -65,7 +65,14 @@ static const uint32_t kGoldenRatioU32 = 0x9E3779B9U;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
inline uint32_t
|
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
|
||||||
|
constexpr uint32_t
|
||||||
|
RotateLeft5(uint32_t aValue)
|
||||||
|
{
|
||||||
|
return (aValue << 5) | (aValue >> 27);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t
|
||||||
AddU32ToHash(uint32_t aHash, uint32_t aValue)
|
AddU32ToHash(uint32_t aHash, uint32_t aValue)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -89,7 +96,7 @@ AddU32ToHash(uint32_t aHash, uint32_t aValue)
|
||||||
* Otherwise, if |aHash| is 0 (as it often is for the beginning of a
|
* Otherwise, if |aHash| is 0 (as it often is for the beginning of a
|
||||||
* message), the expression
|
* message), the expression
|
||||||
*
|
*
|
||||||
* mozilla::WrappingMultiply(kGoldenRatioU32, RotateBitsLeft(aHash, 5))
|
* mozilla::WrappingMultiply(kGoldenRatioU32, RotateLeft5(aHash))
|
||||||
* |xor|
|
* |xor|
|
||||||
* aValue
|
* aValue
|
||||||
*
|
*
|
||||||
|
@ -110,14 +117,14 @@ AddU32ToHash(uint32_t aHash, uint32_t aValue)
|
||||||
* more than enough for our purposes.)
|
* more than enough for our purposes.)
|
||||||
*/
|
*/
|
||||||
return mozilla::WrappingMultiply(kGoldenRatioU32,
|
return mozilla::WrappingMultiply(kGoldenRatioU32,
|
||||||
RotateLeft(aHash, 5) ^ aValue);
|
RotateLeft5(aHash) ^ aValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AddUintptrToHash takes sizeof(uintptr_t) as a template parameter.
|
* AddUintptrToHash takes sizeof(uintptr_t) as a template parameter.
|
||||||
*/
|
*/
|
||||||
template<size_t PtrSize>
|
template<size_t PtrSize>
|
||||||
inline uint32_t
|
constexpr uint32_t
|
||||||
AddUintptrToHash(uint32_t aHash, uintptr_t aValue)
|
AddUintptrToHash(uint32_t aHash, uintptr_t aValue)
|
||||||
{
|
{
|
||||||
return AddU32ToHash(aHash, static_cast<uint32_t>(aValue));
|
return AddU32ToHash(aHash, static_cast<uint32_t>(aValue));
|
||||||
|
@ -173,7 +180,7 @@ AddToHash(uint32_t aHash, A* aA)
|
||||||
// implicitly converted to 32 bits and then passed to AddUintptrToHash() to be hashed.
|
// implicitly converted to 32 bits and then passed to AddUintptrToHash() to be hashed.
|
||||||
template<typename T,
|
template<typename T,
|
||||||
typename U = typename mozilla::EnableIf<mozilla::IsIntegral<T>::value>::Type>
|
typename U = typename mozilla::EnableIf<mozilla::IsIntegral<T>::value>::Type>
|
||||||
MOZ_MUST_USE inline uint32_t
|
MOZ_MUST_USE constexpr uint32_t
|
||||||
AddToHash(uint32_t aHash, T aA)
|
AddToHash(uint32_t aHash, T aA)
|
||||||
{
|
{
|
||||||
return detail::AddUintptrToHash<sizeof(T)>(aHash, aA);
|
return detail::AddUintptrToHash<sizeof(T)>(aHash, aA);
|
||||||
|
@ -213,6 +220,19 @@ HashUntilZero(const T* aStr)
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a `constexpr` alternative to HashUntilZero(const T*). It should
|
||||||
|
// only be used for compile-time computation because it uses recursion.
|
||||||
|
// XXX: once support for GCC 4.9 is dropped, this function should be removed
|
||||||
|
// and HashUntilZero(const T*) should be made `constexpr`.
|
||||||
|
template<typename T>
|
||||||
|
constexpr uint32_t
|
||||||
|
ConstExprHashUntilZero(const T* aStr, uint32_t aHash)
|
||||||
|
{
|
||||||
|
return !*aStr
|
||||||
|
? aHash
|
||||||
|
: ConstExprHashUntilZero(aStr + 1, AddToHash(aHash, *aStr));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
uint32_t
|
uint32_t
|
||||||
HashKnownLength(const T* aStr, size_t aLength)
|
HashKnownLength(const T* aStr, size_t aLength)
|
||||||
|
@ -257,6 +277,21 @@ HashString(const char16_t* aStr)
|
||||||
return detail::HashUntilZero(aStr);
|
return detail::HashUntilZero(aStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a `constexpr` alternative to HashString(const char16_t*). It should
|
||||||
|
// only be used for compile-time computation because it uses recursion.
|
||||||
|
//
|
||||||
|
// You may need to use the
|
||||||
|
// MOZ_{PUSH,POP}_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING macros if you use
|
||||||
|
// this function. See the comment on those macros' definitions for more detail.
|
||||||
|
//
|
||||||
|
// XXX: once support for GCC 4.9 is dropped, this function should be removed
|
||||||
|
// and HashString(const char16_t*) should be made `constexpr`.
|
||||||
|
MOZ_MUST_USE constexpr uint32_t
|
||||||
|
ConstExprHashString(const char16_t* aStr)
|
||||||
|
{
|
||||||
|
return detail::ConstExprHashUntilZero(aStr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_MUST_USE inline uint32_t
|
MOZ_MUST_USE inline uint32_t
|
||||||
HashString(const char16_t* aStr, size_t aLength)
|
HashString(const char16_t* aStr, size_t aLength)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,29 +94,16 @@ struct WrapToSignedHelper
|
||||||
* happening.
|
* happening.
|
||||||
*/
|
*/
|
||||||
template<typename UnsignedType>
|
template<typename UnsignedType>
|
||||||
inline constexpr typename detail::WrapToSignedHelper<UnsignedType>::SignedType
|
constexpr typename detail::WrapToSignedHelper<UnsignedType>::SignedType
|
||||||
WrapToSigned(UnsignedType aValue)
|
WrapToSigned(UnsignedType aValue)
|
||||||
{
|
{
|
||||||
return detail::WrapToSignedHelper<UnsignedType>::compute(aValue);
|
return detail::WrapToSignedHelper<UnsignedType>::compute(aValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The |mozilla::Wrapping*| functions aren't constexpr because MSVC warns about
|
|
||||||
// well-defined unsigned integer overflows that may occur within the constexpr
|
|
||||||
// math. If/when MSVC fix this bug, we should make them all constexpr.
|
|
||||||
//
|
|
||||||
// https://msdn.microsoft.com/en-us/library/4kze989h.aspx (C4307)
|
|
||||||
// https://developercommunity.visualstudio.com/content/problem/211134/unsigned-integer-overflows-in-constexpr-functionsa.html (bug report)
|
|
||||||
//
|
|
||||||
// For now there's no practical, readable way to avoid such overflows in pure
|
|
||||||
// C++. And we can't add narrow #pragmas where overflow can occur to disable
|
|
||||||
// the warnings, because constexpr apparently causes the warning to be emitted
|
|
||||||
// at the outermost call *sites* (so every user of |mozilla::Wrapping*| would
|
|
||||||
// have to add them).
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr T
|
constexpr T
|
||||||
ToResult(typename MakeUnsigned<T>::Type aUnsigned)
|
ToResult(typename MakeUnsigned<T>::Type aUnsigned)
|
||||||
{
|
{
|
||||||
// We could *always* return WrapToSigned and rely on unsigned conversion to
|
// We could *always* return WrapToSigned and rely on unsigned conversion to
|
||||||
|
@ -132,7 +119,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
|
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
|
||||||
static T compute(T aX, T aY)
|
static constexpr T compute(T aX, T aY)
|
||||||
{
|
{
|
||||||
return ToResult<T>(static_cast<UnsignedT>(aX) + static_cast<UnsignedT>(aY));
|
return ToResult<T>(static_cast<UnsignedT>(aX) + static_cast<UnsignedT>(aY));
|
||||||
}
|
}
|
||||||
|
@ -165,7 +152,7 @@ public:
|
||||||
* permissibly -- triggers different behavior.
|
* permissibly -- triggers different behavior.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T
|
constexpr T
|
||||||
WrappingAdd(T aX, T aY)
|
WrappingAdd(T aX, T aY)
|
||||||
{
|
{
|
||||||
return detail::WrappingAddHelper<T>::compute(aX, aY);
|
return detail::WrappingAddHelper<T>::compute(aX, aY);
|
||||||
|
@ -181,7 +168,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
|
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
|
||||||
static T compute(T aX, T aY)
|
static constexpr T compute(T aX, T aY)
|
||||||
{
|
{
|
||||||
return ToResult<T>(static_cast<UnsignedT>(aX) - static_cast<UnsignedT>(aY));
|
return ToResult<T>(static_cast<UnsignedT>(aX) - static_cast<UnsignedT>(aY));
|
||||||
}
|
}
|
||||||
|
@ -215,7 +202,7 @@ public:
|
||||||
* permissibly -- triggers different behavior.
|
* permissibly -- triggers different behavior.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T
|
constexpr T
|
||||||
WrappingSubtract(T aX, T aY)
|
WrappingSubtract(T aX, T aY)
|
||||||
{
|
{
|
||||||
return detail::WrappingSubtractHelper<T>::compute(aX, aY);
|
return detail::WrappingSubtractHelper<T>::compute(aX, aY);
|
||||||
|
@ -231,7 +218,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
|
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
|
||||||
static T compute(T aX, T aY)
|
static constexpr T compute(T aX, T aY)
|
||||||
{
|
{
|
||||||
// Begin with |1U| to ensure the overall operation chain is never promoted
|
// Begin with |1U| to ensure the overall operation chain is never promoted
|
||||||
// to signed integer operations that might have *signed* integer overflow.
|
// to signed integer operations that might have *signed* integer overflow.
|
||||||
|
@ -277,12 +264,36 @@ public:
|
||||||
* or similar -- quite permissibly -- triggers different behavior.
|
* or similar -- quite permissibly -- triggers different behavior.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T
|
constexpr T
|
||||||
WrappingMultiply(T aX, T aY)
|
WrappingMultiply(T aX, T aY)
|
||||||
{
|
{
|
||||||
return detail::WrappingMultiplyHelper<T>::compute(aX, aY);
|
return detail::WrappingMultiplyHelper<T>::compute(aX, aY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The |mozilla::Wrapping*| functions are constexpr. Unfortunately, MSVC warns
|
||||||
|
// about well-defined unsigned integer overflows that may occur within the
|
||||||
|
// constexpr math.
|
||||||
|
//
|
||||||
|
// https://msdn.microsoft.com/en-us/library/4kze989h.aspx (C4307)
|
||||||
|
// https://developercommunity.visualstudio.com/content/problem/211134/unsigned-integer-overflows-in-constexpr-functionsa.html (bug report)
|
||||||
|
//
|
||||||
|
// So we need a way to suppress these warnings. Unfortunately, the warnings are
|
||||||
|
// issued at the very top of the `constexpr` chain, which is often some
|
||||||
|
// distance from the triggering Wrapping*() operation. So we can't suppress
|
||||||
|
// them within this file. Instead, callers have to do it with these macros.
|
||||||
|
//
|
||||||
|
// If/when MSVC fix this bug, we should remove these macros.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING \
|
||||||
|
__pragma(warning(push)) \
|
||||||
|
__pragma(warning(disable:4307))
|
||||||
|
#define MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING \
|
||||||
|
__pragma(warning(pop))
|
||||||
|
#else
|
||||||
|
#define MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
||||||
|
#define MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
||||||
|
#endif
|
||||||
|
|
||||||
} /* namespace mozilla */
|
} /* namespace mozilla */
|
||||||
|
|
||||||
#endif /* mozilla_WrappingOperations_h */
|
#endif /* mozilla_WrappingOperations_h */
|
||||||
|
|
|
@ -5,6 +5,14 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import platform
|
||||||
|
try:
|
||||||
|
import winreg
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import _winreg as winreg
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
from marionette_harness import MarionetteTestCase
|
from marionette_harness import MarionetteTestCase
|
||||||
|
|
||||||
|
@ -34,9 +42,36 @@ class TestCommandLineArguments(MarionetteTestCase):
|
||||||
|
|
||||||
return Services.appinfo.inSafeMode;
|
return Services.appinfo.inSafeMode;
|
||||||
""")
|
""")
|
||||||
|
|
||||||
self.assertTrue(safe_mode, "Safe Mode has not been enabled")
|
self.assertTrue(safe_mode, "Safe Mode has not been enabled")
|
||||||
|
|
||||||
|
def test_safe_mode_blocked_by_policy(self):
|
||||||
|
if platform.system() != 'Windows':
|
||||||
|
return
|
||||||
|
|
||||||
|
reg_policies = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, "SOFTWARE\\Policies", 0, winreg.KEY_WRITE)
|
||||||
|
reg_mozilla = winreg.CreateKeyEx(reg_policies, "Mozilla", 0, winreg.KEY_WRITE)
|
||||||
|
reg_firefox = winreg.CreateKeyEx(reg_mozilla, "Firefox", 0, winreg.KEY_WRITE)
|
||||||
|
winreg.SetValueEx(reg_firefox, "DisableSafeMode", 0, winreg.REG_DWORD, 1)
|
||||||
|
|
||||||
|
self.marionette.instance.app_args.append("-safe-mode")
|
||||||
|
|
||||||
|
self.marionette.quit()
|
||||||
|
self.marionette.start_session()
|
||||||
|
|
||||||
|
with self.marionette.using_context("chrome"):
|
||||||
|
safe_mode = self.marionette.execute_script("""
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
return Services.appinfo.inSafeMode;
|
||||||
|
""")
|
||||||
|
self.assertFalse(safe_mode, "Safe Mode has been enabled")
|
||||||
|
|
||||||
|
winreg.CloseKey(reg_firefox)
|
||||||
|
winreg.DeleteKey(reg_mozilla, "Firefox")
|
||||||
|
winreg.CloseKey(reg_mozilla)
|
||||||
|
winreg.DeleteKey(reg_policies, "Mozilla")
|
||||||
|
winreg.CloseKey(reg_policies)
|
||||||
|
|
||||||
def test_startup_timeout(self):
|
def test_startup_timeout(self):
|
||||||
startup_timeout = self.marionette.startup_timeout
|
startup_timeout = self.marionette.startup_timeout
|
||||||
|
|
||||||
|
|
|
@ -319484,6 +319484,12 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"eventsource/dedicated-worker/eventsource-close2.htm": [
|
||||||
|
[
|
||||||
|
"/eventsource/dedicated-worker/eventsource-close2.htm",
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [
|
"eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [
|
||||||
[
|
[
|
||||||
"/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm",
|
"/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm",
|
||||||
|
@ -390178,7 +390184,7 @@
|
||||||
"manual"
|
"manual"
|
||||||
],
|
],
|
||||||
"FileAPI/FileReader/workers.html": [
|
"FileAPI/FileReader/workers.html": [
|
||||||
"7e9f00c9af5bb982a1b549ebc9f5a3d0b5cf4387",
|
"d7894a0abb064411d4811d8cfb9c3ce65f99babd",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"FileAPI/FileReaderSync.worker.js": [
|
"FileAPI/FileReaderSync.worker.js": [
|
||||||
|
@ -542317,6 +542323,10 @@
|
||||||
"700107771158b22fa280f30a5a52d1aac617ff6e",
|
"700107771158b22fa280f30a5a52d1aac617ff6e",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
|
"eventsource/dedicated-worker/eventsource-close2.htm": [
|
||||||
|
"a3d13b0261b05eba56effb9ca3f6c31e312e777a",
|
||||||
|
"testharness"
|
||||||
|
],
|
||||||
"eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [
|
"eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [
|
||||||
"9614ac5ce1967bbbcae6a1cc8d64465579f6410d",
|
"9614ac5ce1967bbbcae6a1cc8d64465579f6410d",
|
||||||
"testharness"
|
"testharness"
|
||||||
|
@ -546826,7 +546836,7 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html": [
|
"html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-height.html": [
|
||||||
"caaede75e5c16cc78023ce410f48e37e612cffbb",
|
"6da68164fdba8986d4dd217ad48198f675e83165",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html": [
|
"html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-non-integer-innerheight.html": [
|
||||||
|
@ -594606,7 +594616,7 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"websockets/Create-on-worker-shutdown.html": [
|
"websockets/Create-on-worker-shutdown.html": [
|
||||||
"6c1e57e92b617fdb3d8dd86528af7073d21ece03",
|
"e710493c0cd84630a1c853ada23c37908bece9cb",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"websockets/Create-protocol-with-space.htm": [
|
"websockets/Create-protocol-with-space.htm": [
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!--
|
||||||
|
self.close()
|
||||||
|
var source = new EventSource("../resources/message.py")
|
||||||
|
postMessage(source.readyState)
|
||||||
|
/*-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>dedicated worker - EventSource created after: worker.close()</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
var test = async_test();
|
||||||
|
test.step(function() {
|
||||||
|
var worker = new Worker('#')
|
||||||
|
worker.onmessage = function(e) {
|
||||||
|
test.step(function() {
|
||||||
|
assert_equals(e.data, EventSource.CONNECTING, 'this.readyState')
|
||||||
|
})
|
||||||
|
test.done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<!--*/ //-->
|
|
@ -85,7 +85,11 @@ function refreshUI() {
|
||||||
createButton.onclick = createProfileWizard;
|
createButton.onclick = createProfileWizard;
|
||||||
|
|
||||||
let restartSafeModeButton = document.getElementById("restart-in-safe-mode-button");
|
let restartSafeModeButton = document.getElementById("restart-in-safe-mode-button");
|
||||||
restartSafeModeButton.onclick = function() { restart(true); };
|
if (!Services.policies || Services.policies.isAllowed("safeMode")) {
|
||||||
|
restartSafeModeButton.onclick = function() { restart(true); };
|
||||||
|
} else {
|
||||||
|
restartSafeModeButton.setAttribute("disabled", "true");
|
||||||
|
}
|
||||||
|
|
||||||
let restartNormalModeButton = document.getElementById("restart-button");
|
let restartNormalModeButton = document.getElementById("restart-button");
|
||||||
restartNormalModeButton.onclick = function() { restart(false); };
|
restartNormalModeButton.onclick = function() { restart(false); };
|
||||||
|
|
|
@ -1206,6 +1206,10 @@ function populateActionBox() {
|
||||||
if (!Services.appinfo.inSafeMode && AppConstants.platform !== "android") {
|
if (!Services.appinfo.inSafeMode && AppConstants.platform !== "android") {
|
||||||
$("safe-mode-box").style.display = "block";
|
$("safe-mode-box").style.display = "block";
|
||||||
$("action-box").style.display = "block";
|
$("action-box").style.display = "block";
|
||||||
|
|
||||||
|
if (Services.policies && !Services.policies.isAllowed("safeMode")) {
|
||||||
|
$("restart-in-safe-mode-button").setAttribute("disabled", "true");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2778,17 +2778,12 @@ var gDetailView = {
|
||||||
desc.textContent = aAddon.description;
|
desc.textContent = aAddon.description;
|
||||||
|
|
||||||
var fullDesc = document.getElementById("detail-fulldesc");
|
var fullDesc = document.getElementById("detail-fulldesc");
|
||||||
if (aAddon.fullDescription) {
|
if (aAddon.getFullDescription) {
|
||||||
// The following is part of an awful hack to include the licenses for GMP
|
fullDesc.textContent = "";
|
||||||
// plugins without having bug 624602 fixed yet, and intentionally ignores
|
fullDesc.append(aAddon.getFullDescription(document));
|
||||||
// localisation.
|
fullDesc.hidden = false;
|
||||||
if (aAddon.isGMPlugin) {
|
} else if (aAddon.fullDescription) {
|
||||||
// eslint-disable-next-line no-unsanitized/property
|
fullDesc.textContent = aAddon.fullDescription;
|
||||||
fullDesc.unsafeSetInnerHTML(aAddon.fullDescription);
|
|
||||||
} else {
|
|
||||||
fullDesc.textContent = aAddon.fullDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullDesc.hidden = false;
|
fullDesc.hidden = false;
|
||||||
} else {
|
} else {
|
||||||
fullDesc.hidden = true;
|
fullDesc.hidden = true;
|
||||||
|
|
|
@ -29,6 +29,8 @@ const SEC_IN_A_DAY = 24 * 60 * 60;
|
||||||
// How long to wait after a user enabled EME before attempting to download CDMs.
|
// How long to wait after a user enabled EME before attempting to download CDMs.
|
||||||
const GMP_CHECK_DELAY = 10 * 1000; // milliseconds
|
const GMP_CHECK_DELAY = 10 * 1000; // milliseconds
|
||||||
|
|
||||||
|
const XHTML = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
const NS_GRE_DIR = "GreD";
|
const NS_GRE_DIR = "GreD";
|
||||||
const CLEARKEY_PLUGIN_ID = "gmp-clearkey";
|
const CLEARKEY_PLUGIN_ID = "gmp-clearkey";
|
||||||
const CLEARKEY_VERSION = "0.1";
|
const CLEARKEY_VERSION = "0.1";
|
||||||
|
@ -95,8 +97,9 @@ function configureLogging() {
|
||||||
* The GMPWrapper provides the info for the various GMP plugins to public
|
* The GMPWrapper provides the info for the various GMP plugins to public
|
||||||
* callers through the API.
|
* callers through the API.
|
||||||
*/
|
*/
|
||||||
function GMPWrapper(aPluginInfo) {
|
function GMPWrapper(aPluginInfo, aRawPluginInfo) {
|
||||||
this._plugin = aPluginInfo;
|
this._plugin = aPluginInfo;
|
||||||
|
this._rawPlugin = aRawPluginInfo;
|
||||||
this._log =
|
this._log =
|
||||||
Log.repository.getLoggerWithMessagePrefix("Toolkit.GMP",
|
Log.repository.getLoggerWithMessagePrefix("Toolkit.GMP",
|
||||||
"GMPWrapper(" +
|
"GMPWrapper(" +
|
||||||
|
@ -140,7 +143,31 @@ GMPWrapper.prototype = {
|
||||||
get homepageURL() { return this._plugin.homepageURL; },
|
get homepageURL() { return this._plugin.homepageURL; },
|
||||||
|
|
||||||
get description() { return this._plugin.description; },
|
get description() { return this._plugin.description; },
|
||||||
get fullDescription() { return this._plugin.fullDescription; },
|
get fullDescription() { return null; },
|
||||||
|
|
||||||
|
getFullDescription(doc) {
|
||||||
|
let plugin = this._rawPlugin;
|
||||||
|
|
||||||
|
let frag = doc.createDocumentFragment();
|
||||||
|
for (let [urlProp, labelId] of [["learnMoreURL", GMP_LEARN_MORE],
|
||||||
|
["licenseURL", this.id == WIDEVINE_ID ?
|
||||||
|
GMP_PRIVACY_INFO : GMP_LICENSE_INFO]]) {
|
||||||
|
if (plugin[urlProp]) {
|
||||||
|
let a = doc.createElementNS(XHTML, "a");
|
||||||
|
a.href = plugin[urlProp];
|
||||||
|
a.target = "_blank";
|
||||||
|
a.textContent = pluginsBundle.GetStringFromName(labelId);
|
||||||
|
|
||||||
|
if (frag.childElementCount) {
|
||||||
|
frag.append(doc.createElementNS(XHTML, "br"),
|
||||||
|
doc.createElementNS(XHTML, "br"));
|
||||||
|
}
|
||||||
|
frag.append(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return frag;
|
||||||
|
},
|
||||||
|
|
||||||
get version() {
|
get version() {
|
||||||
return GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_VERSION, null, this._plugin.id);
|
return GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_VERSION, null, this._plugin.id);
|
||||||
|
@ -633,19 +660,6 @@ var GMPProvider = {
|
||||||
return GMPPrefs.getBool(GMPPrefs.KEY_PROVIDER_ENABLED, false);
|
return GMPPrefs.getBool(GMPPrefs.KEY_PROVIDER_ENABLED, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
generateFullDescription(aPlugin) {
|
|
||||||
let rv = [];
|
|
||||||
for (let [urlProp, labelId] of [["learnMoreURL", GMP_LEARN_MORE],
|
|
||||||
["licenseURL", aPlugin.id == WIDEVINE_ID ?
|
|
||||||
GMP_PRIVACY_INFO : GMP_LICENSE_INFO]]) {
|
|
||||||
if (aPlugin[urlProp]) {
|
|
||||||
let label = pluginsBundle.GetStringFromName(labelId);
|
|
||||||
rv.push(`<xhtml:a href="${aPlugin[urlProp]}" target="_blank">${label}</xhtml:a>.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv.length ? rv.join("<xhtml:br /><xhtml:br />") : undefined;
|
|
||||||
},
|
|
||||||
|
|
||||||
buildPluginList() {
|
buildPluginList() {
|
||||||
this._plugins = new Map();
|
this._plugins = new Map();
|
||||||
for (let aPlugin of GMP_PLUGINS) {
|
for (let aPlugin of GMP_PLUGINS) {
|
||||||
|
@ -658,8 +672,7 @@ var GMPProvider = {
|
||||||
wrapper: null,
|
wrapper: null,
|
||||||
isEME: aPlugin.isEME,
|
isEME: aPlugin.isEME,
|
||||||
};
|
};
|
||||||
plugin.fullDescription = this.generateFullDescription(aPlugin);
|
plugin.wrapper = new GMPWrapper(plugin, aPlugin);
|
||||||
plugin.wrapper = new GMPWrapper(plugin);
|
|
||||||
this._plugins.set(plugin.id, plugin);
|
this._plugins.set(plugin.id, plugin);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -511,7 +511,10 @@ add_task(async function test_permissions_prompt() {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
await promiseCompleteInstall(install);
|
await Promise.all([
|
||||||
|
promiseCompleteInstall(install),
|
||||||
|
promiseWebExtensionStartup(),
|
||||||
|
]);
|
||||||
|
|
||||||
notEqual(perminfo, undefined, "Permission handler was invoked");
|
notEqual(perminfo, undefined, "Permission handler was invoked");
|
||||||
equal(perminfo.existingAddon, null, "Permission info does not include an existing addon");
|
equal(perminfo.existingAddon, null, "Permission info does not include an existing addon");
|
||||||
|
|
|
@ -3154,6 +3154,40 @@ public:
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool PolicyHasRegValue(HKEY aKey, LPCTSTR aName, DWORD* aValue)
|
||||||
|
{
|
||||||
|
HKEY hkey = NULL;
|
||||||
|
LONG ret = RegOpenKeyExW(aKey,
|
||||||
|
L"SOFTWARE\\Policies\\Mozilla\\Firefox", 0, KEY_READ, &hkey);
|
||||||
|
if (ret != ERROR_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nsAutoRegKey key(hkey);
|
||||||
|
DWORD len = sizeof(aValue);
|
||||||
|
ret = RegQueryValueExW(hkey, aName, 0, NULL, (LPBYTE)aValue, &len);
|
||||||
|
RegCloseKey(key);
|
||||||
|
return ret == ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SafeModeBlockedByPolicy()
|
||||||
|
{
|
||||||
|
LPCTSTR policyName = L"DisableSafeMode";
|
||||||
|
DWORD value;
|
||||||
|
if (PolicyHasRegValue(HKEY_LOCAL_MACHINE, policyName, &value)) {
|
||||||
|
return value == 1;
|
||||||
|
}
|
||||||
|
if (PolicyHasRegValue(HKEY_CURRENT_USER, policyName, &value)) {
|
||||||
|
return value == 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
#endif // XP_WIN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XRE_mainInit - Initial setup and command line parameter processing.
|
* XRE_mainInit - Initial setup and command line parameter processing.
|
||||||
* Main() will exit early if either return value != 0 or if aExitFlag is
|
* Main() will exit early if either return value != 0 or if aExitFlag is
|
||||||
|
@ -3490,12 +3524,6 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
||||||
gRestartArgv[gRestartArgc] = nullptr;
|
gRestartArgv[gRestartArgc] = nullptr;
|
||||||
|
|
||||||
|
|
||||||
if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
|
|
||||||
gSafeMode = true;
|
|
||||||
// unset the env variable
|
|
||||||
SaveToEnv("MOZ_SAFE_MODE_RESTART=");
|
|
||||||
}
|
|
||||||
|
|
||||||
ar = CheckArg("safe-mode", true);
|
ar = CheckArg("safe-mode", true);
|
||||||
if (ar == ARG_BAD) {
|
if (ar == ARG_BAD) {
|
||||||
PR_fprintf(PR_STDERR, "Error: argument --safe-mode is invalid when argument --osint is specified\n");
|
PR_fprintf(PR_STDERR, "Error: argument --safe-mode is invalid when argument --osint is specified\n");
|
||||||
|
@ -3525,6 +3553,20 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
||||||
gSafeMode = true;
|
gSafeMode = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
if (gSafeMode && SafeModeBlockedByPolicy()) {
|
||||||
|
gSafeMode = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The Safe Mode Policy should not be enforced for the env var case
|
||||||
|
// (used by updater and crash-recovery).
|
||||||
|
if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
|
||||||
|
gSafeMode = true;
|
||||||
|
// unset the env variable
|
||||||
|
SaveToEnv("MOZ_SAFE_MODE_RESTART=");
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
{
|
{
|
||||||
// Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
|
// Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
|
||||||
|
|
Загрузка…
Ссылка в новой задаче