diff --git a/.taskcluster.yml b/.taskcluster.yml
index 1759d3806b7b..95d250d5b699 100644
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -45,6 +45,7 @@
# taskGroupId, // targetted taskGroupId
# action: {name, title, description, taskGroupId, symbol, repo_scope, cb_name}
# ownTaskId: // taskId of the task that will be created
+# clientId: // clientId that triggered this hook
# }
version: 1
@@ -58,6 +59,11 @@ tasks:
ownerEmail: {$if: '"@" in push.owner', then: '${push.owner}', else: '${push.owner}@noreply.mozilla.org'}
# ensure there's no trailing `/` on the repo URL
repoUrl: {$if: 'repository.url[-1] == "/"', then: {$eval: 'repository.url[:-1]'}, else: {$eval: 'repository.url'}}
+ # expire try earlier than other branches
+ expires:
+ $if: 'repository.project == "try"'
+ then: {$fromNow: '28 days'}
+ else: {$fromNow: '1 year'}
in:
taskId: {$if: 'tasks_for != "action"', then: '${ownTaskId}'}
taskGroupId:
@@ -70,7 +76,7 @@ tasks:
created: {$fromNow: ''}
deadline: {$fromNow: '1 day'}
- expires: {$fromNow: '1 year 1 second'} # 1 second so artifacts expire first, despite rounding errors
+ expires: {$eval: 'expires'}
metadata:
$merge:
- owner: "${ownerEmail}"
@@ -254,7 +260,7 @@ tasks:
'public':
type: 'directory'
path: '/builds/worker/artifacts'
- expires: {$fromNow: '1 year'}
+ expires: {$eval: expires}
extra:
$merge:
diff --git a/browser/actors/NetErrorChild.jsm b/browser/actors/NetErrorChild.jsm
index b0b9cd80abd0..f6aa0742b96f 100644
--- a/browser/actors/NetErrorChild.jsm
+++ b/browser/actors/NetErrorChild.jsm
@@ -483,16 +483,6 @@ class NetErrorChild extends ActorChild {
if (Math.abs(difference) > 60 * 60 * 24 && (now - lastFetched) <= 60 * 60 * 24 * 5 &&
certRange.notBefore < approximateDate && certRange.notAfter > approximateDate) {
clockSkew = true;
- let systemDate = formatter.format(new Date());
- // negative difference means local time is behind server time
- approximateDate = formatter.format(new Date(approximateDate));
-
- doc.getElementById("wrongSystemTime_URL").textContent = doc.location.hostname;
- doc.getElementById("wrongSystemTime_systemDate").textContent = systemDate;
- doc.getElementById("wrongSystemTime_actualDate").textContent = approximateDate;
-
- doc.getElementById("errorShortDesc").style.display = "none";
- doc.getElementById("wrongSystemTimePanel").style.display = "block";
// If there is no clock skew with Kinto servers, check against the build date.
// (The Kinto ping could have happened when the time was still right, or not at all)
@@ -512,11 +502,6 @@ class NetErrorChild extends ActorChild {
// since the build date.
if (buildDate > systemDate && new Date(certRange.notAfter) > buildDate) {
clockSkew = true;
-
- doc.getElementById("wrongSystemTimeWithoutReference_URL")
- .textContent = doc.location.hostname;
- doc.getElementById("wrongSystemTimeWithoutReference_systemDate")
- .textContent = formatter.format(systemDate);
}
}
@@ -530,7 +515,6 @@ class NetErrorChild extends ActorChild {
doc.querySelector(".title-text").textContent = clockErrTitle.textContent;
let desc = doc.getElementById("errorShortDescText");
doc.getElementById("errorShortDesc").style.display = "block";
- doc.getElementById("wrongSystemTimePanel").style.display = "none";
doc.getElementById("certificateErrorReporting").style.display = "none";
if (desc) {
// eslint-disable-next-line no-unsanitized/property
diff --git a/browser/base/content/aboutNetError.xhtml b/browser/base/content/aboutNetError.xhtml
index 72a4e2db6cc3..1e703c5b0c07 100644
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -170,14 +170,6 @@
&certerror.whatShouldIDo.badStsCertExplanation1;
-
- &certerror.wrongSystemTime2;
-
-
-
- &certerror.wrongSystemTimeWithoutReference;
-
-
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 48b26696ddf6..83e146e63c94 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3726,10 +3726,8 @@ var browserDragAndDrop = {
return Services.droppedLinkHandler.getCSP(aEvent);
},
- validateURIsForDrop(aEvent, aURIsCount, aURIs) {
- return Services.droppedLinkHandler.validateURIsForDrop(aEvent,
- aURIsCount,
- aURIs);
+ validateURIsForDrop(aEvent, aURIs) {
+ return Services.droppedLinkHandler.validateURIsForDrop(aEvent, aURIs);
},
dropLinks(aEvent, aDisallowInherit) {
@@ -3752,7 +3750,7 @@ var homeButtonObserver = {
}
try {
- browserDragAndDrop.validateURIsForDrop(aEvent, urls.length, urls);
+ browserDragAndDrop.validateURIsForDrop(aEvent, urls);
} catch (e) {
return;
}
diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js
index 2e698612a23b..1c7baa01c9b6 100644
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -781,7 +781,10 @@ nsContextMenu.prototype = {
},
openPasswordManager() {
- LoginHelper.openPasswordManager(window, gContextMenuContentData.documentURIObject.host);
+ LoginHelper.openPasswordManager(window, {
+ filterString: gContextMenuContentData.documentURIObject.host,
+ entryPoint: "contextmenu",
+ });
},
inspectNode() {
diff --git a/browser/base/content/pageinfo/security.js b/browser/base/content/pageinfo/security.js
index 49c47244d211..a992c0b30e9b 100644
--- a/browser/base/content/pageinfo/security.js
+++ b/browser/base/content/pageinfo/security.js
@@ -180,7 +180,10 @@ var security = {
* Open the login manager window
*/
viewPasswords() {
- LoginHelper.openPasswordManager(window, this._getSecurityInfo().hostName);
+ LoginHelper.openPasswordManager(window, {
+ filterString: this._getSecurityInfo().hostName,
+ entryPoint: "pageinfo",
+ });
},
_cert: null,
diff --git a/browser/base/content/test/siteIdentity/browser.ini b/browser/base/content/test/siteIdentity/browser.ini
index 45f8b1f389a9..e2be05580426 100644
--- a/browser/base/content/test/siteIdentity/browser.ini
+++ b/browser/base/content/test/siteIdentity/browser.ini
@@ -114,3 +114,4 @@ support-files =
support-files =
file_mixedPassiveContent.html
file_bug1045809_1.html
+[browser_deprecatedTLSVersions.js]
diff --git a/browser/base/content/test/siteIdentity/browser_deprecatedTLSVersions.js b/browser/base/content/test/siteIdentity/browser_deprecatedTLSVersions.js
new file mode 100644
index 000000000000..561856584bf8
--- /dev/null
+++ b/browser/base/content/test/siteIdentity/browser_deprecatedTLSVersions.js
@@ -0,0 +1,61 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Tests for Bug 1535210 - Set SSL STATE_IS_BROKEN flag for TLS1.0 and TLS 1.1 connections
+ */
+
+const HTTPS_TLS1_0 = "https://tls1.example.com";
+const HTTPS_TLS1_1 = "https://tls11.example.com";
+const HTTPS_TLS1_2 = "https://tls12.example.com";
+const HTTPS_TLS1_3 = "https://tls13.example.com";
+
+
+function getIdentityMode(aWindow = window) {
+ return aWindow.document.getElementById("identity-box").className;
+}
+
+function getConnectionState() {
+ // Prevents items that are being lazy loaded causing issues
+ document.getElementById("identity-box").click();
+ gIdentityHandler.refreshIdentityPopup();
+ return document.getElementById("identity-popup").getAttribute("connection");
+}
+
+add_task(async function() {
+ await BrowserTestUtils.withNewTab("about:blank", async function(browser) {
+ // Try deprecated versions
+ await BrowserTestUtils.loadURI(browser, HTTPS_TLS1_0);
+ await BrowserTestUtils.browserLoaded(browser);
+ isSecurityState(browser, "broken");
+ is(getIdentityMode(), "unknownIdentity weakCipher", "Identity should be unknownIdentity");
+ is(getConnectionState(), "not-secure", "connectionState should be not-secure");
+
+ await BrowserTestUtils.loadURI(browser, HTTPS_TLS1_1);
+ await BrowserTestUtils.browserLoaded(browser);
+ isSecurityState(browser, "broken");
+ is(getIdentityMode(), "unknownIdentity weakCipher", "Identity should be unknownIdentity");
+ is(getConnectionState(), "not-secure", "connectionState should be not-secure");
+
+ // Transition to secure
+ await BrowserTestUtils.loadURI(browser, HTTPS_TLS1_2);
+ await BrowserTestUtils.browserLoaded(browser);
+ isSecurityState(browser, "secure");
+ is(getIdentityMode(), "verifiedDomain", "Identity should be verified");
+ is(getConnectionState(), "secure", "connectionState should be secure");
+
+ // Transition back to broken
+ await BrowserTestUtils.loadURI(browser, HTTPS_TLS1_1);
+ await BrowserTestUtils.browserLoaded(browser);
+ isSecurityState(browser, "broken");
+ is(getIdentityMode(), "unknownIdentity weakCipher", "Identity should be unknownIdentity");
+ is(getConnectionState(), "not-secure", "connectionState should be not-secure");
+
+ // TLS1.3 for completeness
+ await BrowserTestUtils.loadURI(browser, HTTPS_TLS1_3);
+ await BrowserTestUtils.browserLoaded(browser);
+ isSecurityState(browser, "secure");
+ is(getIdentityMode(), "verifiedDomain", "Identity should be verified");
+ is(getConnectionState(), "secure", "connectionState should be secure");
+ });
+});
diff --git a/browser/base/content/test/static/browser_misused_characters_in_strings.js b/browser/base/content/test/static/browser_misused_characters_in_strings.js
index c9aaef613897..9bd46b1b6719 100644
--- a/browser/base/content/test/static/browser_misused_characters_in_strings.js
+++ b/browser/base/content/test/static/browser_misused_characters_in_strings.js
@@ -32,14 +32,6 @@ let gWhitelist = [{
file: "netError.dtd",
key: "inadequateSecurityError.longDesc",
type: "single-quote",
- }, {
- file: "netError.dtd",
- key: "certerror.wrongSystemTime2",
- type: "single-quote",
- }, {
- file: "netError.dtd",
- key: "certerror.wrongSystemTimeWithoutReference",
- type: "single-quote",
}, {
file: "netError.dtd",
key: "clockSkewError.longDesc",
diff --git a/browser/components/customizableui/content/panelUI.inc.xul b/browser/components/customizableui/content/panelUI.inc.xul
index fafa026c2125..62c73ee363ad 100644
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -336,7 +336,7 @@
Meet the rest of { -brand-product-name }.
onboarding-welcome-learn-more = Learn more about the benefits.
onboarding-join-form-header = Join { -brand-product-name }
-onboarding-join-form-body = Enter your email address to get started.
+onboarding-join-form-body = Enter your email address to get started.
onboarding-join-form-email =
.placeholder = Enter email
onboarding-join-form-email-error = Valid email required
-onboarding-join-form-legal = By proceeding, you agree to the Terms of Service and Privacy Notice .
+onboarding-join-form-legal = By proceeding, you agree to the Terms of Service and Privacy Notice .
onboarding-join-form-continue = Continue
onboarding-start-browsing-button-label = Start Browsing
@@ -29,7 +37,7 @@ onboarding-benefit-products-title = Useful Products
onboarding-benefit-products-text = Get things done with a family of tools that respects your privacy across your devices.
onboarding-benefit-knowledge-title = Practical Knowledge
-onboarding-benefit-knowledge-text = Learn everything you need to know to stay smarter and safer online.
+onboarding-benefit-knowledge-text = Learn everything you need to know to stay smarter and safer online.
onboarding-benefit-privacy-title = True Privacy
# "Personal Data Promise" is a concept that should be translated consistently
@@ -65,12 +73,12 @@ onboarding-tracking-protection-title2 = Protection From Tracking
onboarding-tracking-protection-text2 = { -brand-short-name } helps stop websites from tracking you online, making it harder for ads to follow you around the web.
onboarding-tracking-protection-button2 = How it Works
-onboarding-data-sync-title = Take Your Settings with You
+onboarding-data-sync-title = Take Your Settings with You
# "Sync" is short for synchronize.
onboarding-data-sync-text2 = Sync your bookmarks, passwords, and more everywhere you use { -brand-product-name }.
onboarding-data-sync-button2 = Sign in to { -sync-brand-short-name }
-onboarding-firefox-monitor-title = Stay Alert to Data Breaches
+onboarding-firefox-monitor-title = Stay Alert to Data Breaches
onboarding-firefox-monitor-text = { -monitor-brand-name } monitors if your email has appeared in a data breach and alerts you if it appears in a new breach.
onboarding-firefox-monitor-button = Sign up for Alerts
@@ -78,7 +86,7 @@ onboarding-browse-privately-title = Browse Privately
onboarding-browse-privately-text = Private Browsing clears your search and browsing history to keep it secret from anyone who uses your computer.
onboarding-browse-privately-button = Open a Private Window
-onboarding-firefox-send-title = Keep Your Shared Files Private
+onboarding-firefox-send-title = Keep Your Shared Files Private
onboarding-firefox-send-text2 = Upload your files to { -send-brand-name } to share them with end-to-end encryption and a link that automatically expires.
onboarding-firefox-send-button = Try { -send-brand-name }
@@ -88,21 +96,21 @@ onboarding-mobile-phone-text = Download { -brand-product-name } for iOS or Andro
# browser.
onboarding-mobile-phone-button = Download Mobile Browser
-onboarding-send-tabs-title = Instantly Send Yourself Tabs
+onboarding-send-tabs-title = Instantly Send Yourself Tabs
# "Send Tabs" refers to "Send Tab to Device" feature that appears when opening a
# tab's context menu.
onboarding-send-tabs-text = Send Tabs instantly shares pages between your devices without having to copy, paste, or leave the browser.
onboarding-send-tabs-button = Start Using Send Tabs
onboarding-pocket-anywhere-title = Read and Listen Anywhere
-onboarding-pocket-anywhere-text2 = Save your favorite content offline with the { -pocket-brand-name } App and read, listen, and watch whenever it’s convenient for you.
+onboarding-pocket-anywhere-text2 = Save your favorite content offline with the { -pocket-brand-name } App and read, listen, and watch whenever it’s convenient for you.
onboarding-pocket-anywhere-button = Try { -pocket-brand-name }
-onboarding-lockwise-passwords-title = Take Your Passwords Everywhere
+onboarding-lockwise-passwords-title = Take Your Passwords Everywhere
onboarding-lockwise-passwords-text2 = Keep the passwords you save secure and easily log in to your accounts with { -lockwise-brand-name }.
onboarding-lockwise-passwords-button2 = Get the App
-onboarding-facebook-container-title = Set Boundaries with Facebook
+onboarding-facebook-container-title = Set Boundaries with Facebook
onboarding-facebook-container-text2 = { -facebook-container-brand-name } keeps your profile separate from everything else, making it harder for Facebook to target you with ads.
onboarding-facebook-container-button = Add the Extension
diff --git a/browser/locales/en-US/chrome/overrides/netError.dtd b/browser/locales/en-US/chrome/overrides/netError.dtd
index 29e34c518fb1..e0b0ce9b5bc4 100644
--- a/browser/locales/en-US/chrome/overrides/netError.dtd
+++ b/browser/locales/en-US/chrome/overrides/netError.dtd
@@ -205,12 +205,6 @@ was trying to connect. -->
"SSL_ERROR_UNSUPPORTED_VERSION". -->
-
- &brandShortName; did not connect to because your computer’s clock appears to show the wrong time and this is preventing a secure connection. Your computer is set to , when it should be . To fix this problem, change your date and time settings to match the correct time.
">
-&brandShortName; did not connect to because your computer’s clock appears to show the wrong time and this is preventing a secure connection. Your computer is set to . To fix this problem, change your date and time settings to match the correct time.
">
-
has a security policy called HTTP Strict Transport Security (HSTS), which means that &brandShortName; can only connect to it securely. You can’t add an exception to visit this site.">
diff --git a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm
index 243d06a8f80c..1f90daeca329 100644
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm
@@ -149,16 +149,17 @@ async function allTabTitlesDisplayed(browserWindow) {
let tabTitlePromises = [];
for (let tab of browserWindow.gBrowser.tabs) {
- function tabTitleLoaded(spec) {
- return () => {
- return spec ? tab.label == specToTitleMap[spec] : false;
- };
+ function getSpec() {
+ return tab.linkedBrowser &&
+ tab.linkedBrowser.documentURI &&
+ tab.linkedBrowser.documentURI.spec;
+ }
+ function tabTitleLoaded() {
+ let spec = getSpec();
+ return spec ? tab.label == specToTitleMap[spec] : false;
}
- let spec = tab.linkedBrowser &&
- tab.linkedBrowser.documentURI &&
- tab.linkedBrowser.documentURI.spec;
let promise =
- TestUtils.waitForCondition(tabTitleLoaded(spec), `Tab (${spec}) should be showing "${specToTitleMap[spec]}". Got "${tab.label}"`);
+ TestUtils.waitForCondition(tabTitleLoaded, `Tab (${getSpec()}) should be showing "${specToTitleMap[getSpec()]}". Got "${tab.label}"`);
tabTitlePromises.push(promise);
}
diff --git a/build/pgo/certs/cert9.db b/build/pgo/certs/cert9.db
index 449e713dd95d..5a3baaf54bbb 100644
Binary files a/build/pgo/certs/cert9.db and b/build/pgo/certs/cert9.db differ
diff --git a/build/pgo/certs/key4.db b/build/pgo/certs/key4.db
index 33da46fa1c9d..c0de19d70781 100644
Binary files a/build/pgo/certs/key4.db and b/build/pgo/certs/key4.db differ
diff --git a/build/pgo/certs/mochitest.client b/build/pgo/certs/mochitest.client
index c7a408b7a6cb..43c8c200fb5a 100644
Binary files a/build/pgo/certs/mochitest.client and b/build/pgo/certs/mochitest.client differ
diff --git a/build/pgo/server-locations.txt b/build/pgo/server-locations.txt
index dc51a21cb160..a762420899cb 100644
--- a/build/pgo/server-locations.txt
+++ b/build/pgo/server-locations.txt
@@ -286,11 +286,14 @@ https://sha256ee.example.com:443 privileged,cer
# Hosts for imminent distrust warning tests
https://imminently-distrusted.example.com:443 privileged,cert=imminently_distrusted
-# Hosts for ssl3/rc4 console warning tests
-https://ssl3.example.com:443 privileged,ssl3
-https://rc4.example.com:443 privileged,rc4
-https://ssl3rc4.example.com:443 privileged,ssl3,rc4
-https://tls1.example.com:443 privileged,tls1
+# Hosts for ssl3/rc4/tls1 warning tests
+https://ssl3.example.com:443 privileged,ssl3
+https://rc4.example.com:443 privileged,rc4
+https://ssl3rc4.example.com:443 privileged,ssl3,rc4
+https://tls1.example.com:443 privileged,tls1
+https://tls11.example.com:443 privileged,tls1_1
+https://tls12.example.com:443 privileged,tls1_2
+https://tls13.example.com:443 privileged,tls1,tls1_3
# Hosts for youtube rewrite tests
https://mochitest.youtube.com:443
diff --git a/devtools/client/debugger/dist/parser-worker.js b/devtools/client/debugger/dist/parser-worker.js
index 262138025be2..96b824b141a0 100644
--- a/devtools/client/debugger/dist/parser-worker.js
+++ b/devtools/client/debugger/dist/parser-worker.js
@@ -17945,18 +17945,22 @@ const { workerHandler } = _devtoolsUtils.workerUtils; /* This Source Code Form i
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at . */
+function clearState() {
+ (0, _ast.clearASTs)();
+ (0, _getScopes.clearScopes)();
+ (0, _sources.clearSources)();
+ (0, _getSymbols.clearSymbols)();
+}
+
self.onmessage = workerHandler({
findOutOfScopeLocations: _findOutOfScopeLocations2.default,
getSymbols: _getSymbols.getSymbols,
getScopes: _getScopes2.default,
- clearSymbols: _getSymbols.clearSymbols,
- clearScopes: _getScopes.clearScopes,
- clearASTs: _ast.clearASTs,
- setSource: _sources.setSource,
- clearSources: _sources.clearSources,
+ clearState,
getNextStep: _steps.getNextStep,
hasSyntaxError: _validate.hasSyntaxError,
- mapExpression: _mapExpression2.default
+ mapExpression: _mapExpression2.default,
+ setSource: _sources.setSource
});
/***/ }),
diff --git a/devtools/client/debugger/panel.js b/devtools/client/debugger/panel.js
index 8b9f901edc27..8f2dd1e4a6eb 100644
--- a/devtools/client/debugger/panel.js
+++ b/devtools/client/debugger/panel.js
@@ -33,7 +33,10 @@ DebuggerPanel.prototype = {
threadClient: this.toolbox.threadClient,
tabTarget: this.toolbox.target,
debuggerClient: this.toolbox.target.client,
- sourceMaps: this.toolbox.sourceMapService,
+ workers: {
+ sourceMaps: this.toolbox.sourceMapService,
+ evaluationsParser: this.toolbox.parserService
+ },
panel: this
});
diff --git a/devtools/client/debugger/src/actions/ast.js b/devtools/client/debugger/src/actions/ast.js
index ae934576ae66..e7aeb71d598f 100644
--- a/devtools/client/debugger/src/actions/ast.js
+++ b/devtools/client/debugger/src/actions/ast.js
@@ -8,13 +8,11 @@ import { getSourceWithContent, getSelectedLocation } from "../selectors";
import { setInScopeLines } from "./ast/setInScopeLines";
-import * as parser from "../workers/parser";
-
import type { Context } from "../types";
import type { ThunkArgs, Action } from "./types";
export function setOutOfScopeLocations(cx: Context) {
- return async ({ dispatch, getState }: ThunkArgs) => {
+ return async ({ dispatch, getState, parser }: ThunkArgs) => {
const location = getSelectedLocation(getState());
if (!location) {
return;
diff --git a/devtools/client/debugger/src/actions/breakpoints/breakpointPositions.js b/devtools/client/debugger/src/actions/breakpoints/breakpointPositions.js
index 4503eff9abfc..b524a7dfb8ef 100644
--- a/devtools/client/debugger/src/actions/breakpoints/breakpointPositions.js
+++ b/devtools/client/debugger/src/actions/breakpoints/breakpointPositions.js
@@ -44,6 +44,7 @@ async function mapLocations(
}
const { sourceId } = generatedLocations[0];
+
const originalLocations = await sourceMaps.getOriginalLocations(
sourceId,
generatedLocations
diff --git a/devtools/client/debugger/src/actions/expressions.js b/devtools/client/debugger/src/actions/expressions.js
index 4ebd5c28c2a2..9185c6de33b1 100644
--- a/devtools/client/debugger/src/actions/expressions.js
+++ b/devtools/client/debugger/src/actions/expressions.js
@@ -22,7 +22,6 @@ import { wrapExpression } from "../utils/expressions";
import { features } from "../utils/prefs";
import { isOriginal } from "../utils/source";
-import * as parser from "../workers/parser";
import type { Expression, ThreadContext } from "../types";
import type { ThunkArgs } from "./types";
@@ -35,12 +34,12 @@ import type { ThunkArgs } from "./types";
* @static
*/
export function addExpression(cx: ThreadContext, input: string) {
- return async ({ dispatch, getState }: ThunkArgs) => {
+ return async ({ dispatch, getState, evaluationsParser }: ThunkArgs) => {
if (!input) {
return;
}
- const expressionError = await parser.hasSyntaxError(input);
+ const expressionError = await evaluationsParser.hasSyntaxError(input);
const expression = getExpression(getState(), input);
if (expression) {
@@ -80,7 +79,7 @@ export function updateExpression(
input: string,
expression: Expression
) {
- return async ({ dispatch, getState }: ThunkArgs) => {
+ return async ({ dispatch, getState, parser }: ThunkArgs) => {
if (!input) {
return;
}
@@ -177,14 +176,20 @@ function evaluateExpression(cx: ThreadContext, expression: Expression) {
* and replaces all posible generated names.
*/
export function getMappedExpression(expression: string) {
- return async function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
+ return async function({
+ dispatch,
+ getState,
+ client,
+ sourceMaps,
+ evaluationsParser
+ }: ThunkArgs) {
const thread = getCurrentThread(getState());
const mappings = getSelectedScopeMappings(getState(), thread);
const bindings = getSelectedFrameBindings(getState(), thread);
// We bail early if we do not need to map the expression. This is important
- // because mapping an expression can be slow if the parser worker is
- // busy doing other work.
+ // because mapping an expression can be slow if the evaluationsParser
+ // worker is busy doing other work.
//
// 1. there are no mappings - we do not need to map original expressions
// 2. does not contain `await` - we do not need to map top level awaits
@@ -194,7 +199,7 @@ export function getMappedExpression(expression: string) {
return null;
}
- return parser.mapExpression(
+ return evaluationsParser.mapExpression(
expression,
mappings,
bindings || [],
diff --git a/devtools/client/debugger/src/actions/navigation.js b/devtools/client/debugger/src/actions/navigation.js
index 1a066e727074..1f8a0eb2e423 100644
--- a/devtools/client/debugger/src/actions/navigation.js
+++ b/devtools/client/debugger/src/actions/navigation.js
@@ -12,13 +12,6 @@ import { waitForMs } from "../utils/utils";
import { newGeneratedSources } from "./sources";
import { updateWorkers } from "./debuggee";
-import {
- clearASTs,
- clearSymbols,
- clearScopes,
- clearSources
-} from "../workers/parser";
-
import { clearWasmStates } from "../utils/wasm";
import { getMainThread } from "../selectors";
import type { Action, ThunkArgs } from "./types";
@@ -33,15 +26,18 @@ import type { Action, ThunkArgs } from "./types";
* @static
*/
export function willNavigate(event: Object) {
- return function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
+ return async function({
+ dispatch,
+ getState,
+ client,
+ sourceMaps,
+ parser
+ }: ThunkArgs) {
sourceQueue.clear();
sourceMaps.clearSourceMaps();
clearWasmStates();
clearDocuments();
- clearSymbols();
- clearASTs();
- clearScopes();
- clearSources();
+ parser.clear();
client.detachWorkers();
const thread = getMainThread(getState());
diff --git a/devtools/client/debugger/src/actions/pause/commands.js b/devtools/client/debugger/src/actions/pause/commands.js
index 9bf9e70773a8..c98993e9a767 100644
--- a/devtools/client/debugger/src/actions/pause/commands.js
+++ b/devtools/client/debugger/src/actions/pause/commands.js
@@ -13,7 +13,6 @@ import {
getThreadContext
} from "../../selectors";
import { PROMISE } from "../utils/middleware/promise";
-import { getNextStep } from "../../workers/parser";
import { addHiddenBreakpoint } from "../breakpoints";
import { evaluateExpressions } from "../expressions";
import { selectLocation } from "../sources";
@@ -213,7 +212,7 @@ function hasAwait(content: AsyncValue | null, pauseLocation) {
* @returns {function(ThunkArgs)}
*/
export function astCommand(cx: ThreadContext, stepType: Command) {
- return async ({ dispatch, getState, sourceMaps }: ThunkArgs) => {
+ return async ({ dispatch, getState, sourceMaps, parser }: ThunkArgs) => {
if (!features.asyncStepping) {
return dispatch(command(cx, stepType));
}
@@ -225,7 +224,10 @@ export function astCommand(cx: ThreadContext, stepType: Command) {
const content = source ? getSourceContent(getState(), source.id) : null;
if (source && hasAwait(content, frame.location)) {
- const nextLocation = await getNextStep(source.id, frame.location);
+ const nextLocation = await parser.getNextStep(
+ source.id,
+ frame.location
+ );
if (nextLocation) {
await dispatch(addHiddenBreakpoint(cx, nextLocation));
return dispatch(command(cx, "resume"));
diff --git a/devtools/client/debugger/src/actions/pause/mapScopes.js b/devtools/client/debugger/src/actions/pause/mapScopes.js
index 6245a05b50c3..850fffb20af2 100644
--- a/devtools/client/debugger/src/actions/pause/mapScopes.js
+++ b/devtools/client/debugger/src/actions/pause/mapScopes.js
@@ -55,7 +55,8 @@ export function mapScopes(
scopes: Promise,
frame: Frame
) {
- return async function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
+ return async function(thunkArgs: ThunkArgs) {
+ const { dispatch, getState } = thunkArgs;
assert(cx.thread == frame.thread, "Thread mismatch");
const generatedSource = getSource(
@@ -99,8 +100,7 @@ export function mapScopes(
: { type: "text", value: "", contentType: undefined },
frame,
await scopes,
- sourceMaps,
- client
+ thunkArgs
);
} catch (e) {
log(e);
diff --git a/devtools/client/debugger/src/actions/sources/loadSourceText.js b/devtools/client/debugger/src/actions/sources/loadSourceText.js
index a3c20ea1c985..2dea3282abaa 100644
--- a/devtools/client/debugger/src/actions/sources/loadSourceText.js
+++ b/devtools/client/debugger/src/actions/sources/loadSourceText.js
@@ -21,7 +21,6 @@ import { prettyPrintSource } from "./prettyPrint";
import { setBreakableLines } from "./breakableLines";
import { isFulfilled } from "../../utils/async-value";
-import * as parser from "../../workers/parser";
import { isOriginal, isPretty } from "../../utils/source";
import {
memoizeableAction,
@@ -93,7 +92,7 @@ async function loadSource(
async function loadSourceTextPromise(
cx: Context,
source: Source,
- { dispatch, getState, client, sourceMaps }: ThunkArgs
+ { dispatch, getState, client, sourceMaps, parser }: ThunkArgs
): Promise {
const epoch = getSourcesEpoch(getState());
await dispatch({
diff --git a/devtools/client/debugger/src/actions/sources/symbols.js b/devtools/client/debugger/src/actions/sources/symbols.js
index fd3f8ea31a09..a544435fbb2e 100644
--- a/devtools/client/debugger/src/actions/sources/symbols.js
+++ b/devtools/client/debugger/src/actions/sources/symbols.js
@@ -10,8 +10,6 @@ import { PROMISE } from "../utils/middleware/promise";
import { updateTab } from "../tabs";
import { loadSourceText } from "./loadSourceText";
-import * as parser from "../../workers/parser";
-
import {
memoizeableAction,
type MemoizedAction
@@ -20,7 +18,7 @@ import {
import type { Source, Context } from "../../types";
import type { Symbols } from "../../reducers/types";
-async function doSetSymbols(cx, source, { dispatch, getState }) {
+async function doSetSymbols(cx, source, { dispatch, getState, parser }) {
const sourceId = source.id;
await dispatch(loadSourceText({ cx, source }));
diff --git a/devtools/client/debugger/src/actions/tests/__snapshots__/project-text-search.spec.js.snap b/devtools/client/debugger/src/actions/tests/__snapshots__/project-text-search.spec.js.snap
index e7f0e40d64be..c75282e0e421 100644
--- a/devtools/client/debugger/src/actions/tests/__snapshots__/project-text-search.spec.js.snap
+++ b/devtools/client/debugger/src/actions/tests/__snapshots__/project-text-search.spec.js.snap
@@ -124,6 +124,27 @@ Array [
]
`;
+exports[`project text search should search a specific source 2`] = `
+Array [
+ Object {
+ "filepath": "http://localhost:8000/examples/bar",
+ "matches": Array [
+ Object {
+ "column": 9,
+ "line": 1,
+ "match": "bla",
+ "matchIndex": 9,
+ "sourceId": "bar",
+ "type": "MATCH",
+ "value": "function bla(x, y) {",
+ },
+ ],
+ "sourceId": "bar",
+ "type": "RESULT",
+ },
+]
+`;
+
exports[`project text search should search all the loaded sources based on the query 1`] = `
Array [
Object {
diff --git a/devtools/client/debugger/src/actions/types/index.js b/devtools/client/debugger/src/actions/types/index.js
index 6d6f13c6ffcc..27ab60d55694 100644
--- a/devtools/client/debugger/src/actions/types/index.js
+++ b/devtools/client/debugger/src/actions/types/index.js
@@ -19,6 +19,7 @@ import type { PauseAction } from "./PauseAction";
import type { ASTAction } from "./ASTAction";
import { clientCommands } from "../../client/firefox";
import type { Panel } from "../../client/firefox/types";
+import type { ParserDispatcher } from "../../workers/parser";
/**
* Flow types
@@ -38,6 +39,8 @@ export type ThunkArgs = {
getState: () => State,
client: typeof clientCommands,
sourceMaps: SourceMaps,
+ parser: ParserDispatcher,
+ evaluationsParser: ParserDispatcher,
panel: Panel
};
diff --git a/devtools/client/debugger/src/actions/utils/middleware/log.js b/devtools/client/debugger/src/actions/utils/middleware/log.js
index 17005ad569a6..d44be560b7b1 100644
--- a/devtools/client/debugger/src/actions/utils/middleware/log.js
+++ b/devtools/client/debugger/src/actions/utils/middleware/log.js
@@ -20,7 +20,8 @@ const blacklist = [
"REMOVE_BREAKPOINT",
"NODE_PROPERTIES_LOADED",
"SET_FOCUSED_SOURCE_ITEM",
- "NODE_EXPAND"
+ "NODE_EXPAND",
+ "IN_SCOPE_LINES"
];
function cloneAction(action: any) {
diff --git a/devtools/client/debugger/src/client/index.js b/devtools/client/debugger/src/client/index.js
index d18a23dd4280..6c0f21558bb4 100644
--- a/devtools/client/debugger/src/client/index.js
+++ b/devtools/client/debugger/src/client/index.js
@@ -59,7 +59,7 @@ function getClient(connection: any) {
export async function onConnect(
connection: Object,
- sourceMaps: Object,
+ panelWorkers: Object,
panel: Panel
) {
// NOTE: the landing page does not connect to a JS process
@@ -73,15 +73,15 @@ export async function onConnect(
const commands = client.clientCommands;
const initialState = await loadInitialState();
+ const workers = bootstrapWorkers(panelWorkers);
const { store, actions, selectors } = bootstrapStore(
commands,
- sourceMaps,
+ workers,
panel,
initialState
);
- const workers = bootstrapWorkers();
await client.onConnect(connection, actions);
await syncBreakpoints();
@@ -90,7 +90,7 @@ export async function onConnect(
store,
actions,
selectors,
- workers: { ...workers, sourceMaps },
+ workers,
connection,
client: client.clientCommands
});
diff --git a/devtools/client/debugger/src/main.js b/devtools/client/debugger/src/main.js
index d19b0dde604d..2da9f777c9c1 100644
--- a/devtools/client/debugger/src/main.js
+++ b/devtools/client/debugger/src/main.js
@@ -19,7 +19,7 @@ module.exports = {
threadClient,
tabTarget,
debuggerClient,
- sourceMaps,
+ workers,
panel
}: any) =>
onConnect(
@@ -31,7 +31,7 @@ module.exports = {
debuggerClient
}
},
- sourceMaps,
+ workers,
panel
),
destroy: () => {
diff --git a/devtools/client/debugger/src/test/tests-setup.js b/devtools/client/debugger/src/test/tests-setup.js
index 0564674062a8..f920027452ea 100644
--- a/devtools/client/debugger/src/test/tests-setup.js
+++ b/devtools/client/debugger/src/test/tests-setup.js
@@ -23,12 +23,7 @@ import {
stop as stopPrettyPrintWorker
} from "../workers/pretty-print";
-import {
- start as startParserWorker,
- stop as stopParserWorker,
- clearSymbols,
- clearASTs
-} from "../workers/parser";
+import { ParserDispatcher } from "../workers/parser";
import {
start as startSearchWorker,
stop as stopSearchWorker
@@ -68,6 +63,8 @@ function formatException(reason, p) {
console && console.log("Unhandled Rejection at:", p, "reason:", reason);
}
+export const parserWorker = new ParserDispatcher();
+
beforeAll(() => {
startSourceMapWorker(
path.join(rootPath, "node_modules/devtools-source-map/src/worker.js"),
@@ -76,7 +73,7 @@ beforeAll(() => {
startPrettyPrintWorker(
path.join(rootPath, "src/workers/pretty-print/worker.js")
);
- startParserWorker(path.join(rootPath, "src/workers/parser/worker.js"));
+ parserWorker.start(path.join(rootPath, "src/workers/parser/worker.js"));
startSearchWorker(path.join(rootPath, "src/workers/search/worker.js"));
process.on("unhandledRejection", formatException);
});
@@ -84,7 +81,7 @@ beforeAll(() => {
afterAll(() => {
stopSourceMapWorker();
stopPrettyPrintWorker();
- stopParserWorker();
+ parserWorker.stop();
stopSearchWorker();
process.removeListener("unhandledRejection", formatException);
});
@@ -92,8 +89,7 @@ afterAll(() => {
afterEach(() => {});
beforeEach(async () => {
- clearASTs();
- await clearSymbols();
+ parserWorker.clear();
clearHistory();
clearDocuments();
prefs.projectDirectoryRoot = "";
diff --git a/devtools/client/debugger/src/utils/bootstrap.js b/devtools/client/debugger/src/utils/bootstrap.js
index 3fd75b37a9d4..5f587e5c3a38 100644
--- a/devtools/client/debugger/src/utils/bootstrap.js
+++ b/devtools/client/debugger/src/utils/bootstrap.js
@@ -16,7 +16,7 @@ import SourceMaps, {
} from "devtools-source-map";
import * as search from "../workers/search";
import * as prettyPrint from "../workers/pretty-print";
-import * as parser from "../workers/parser";
+import { ParserDispatcher } from "../workers/parser";
import configureStore from "../actions/utils/create-store";
import reducers from "../reducers";
@@ -26,6 +26,8 @@ import { asyncStore, prefs } from "./prefs";
import type { Panel } from "../client/firefox/types";
+let parser;
+
function renderPanel(component, store) {
const root = document.createElement("div");
root.className = "launchpad-root theme-body";
@@ -42,9 +44,14 @@ function renderPanel(component, store) {
);
}
+type Workers = {
+ sourceMaps: typeof SourceMaps,
+ evaluationsParser: typeof ParserDispatcher
+};
+
export function bootstrapStore(
client: any,
- sourceMaps: typeof SourceMaps,
+ workers: Workers,
panel: Panel,
initialState: Object
) {
@@ -52,7 +59,7 @@ export function bootstrapStore(
log: prefs.logging || isTesting(),
timing: isDevelopment(),
makeThunkArgs: (args, state) => {
- return { ...args, client, sourceMaps, panel };
+ return { ...args, client, ...workers, panel };
}
});
@@ -67,7 +74,7 @@ export function bootstrapStore(
return { store, actions, selectors };
}
-export function bootstrapWorkers() {
+export function bootstrapWorkers(panelWorkers: Workers) {
const workerPath = isDevelopment()
? "assets/build"
: "resource://devtools/client/debugger/dist";
@@ -82,9 +89,11 @@ export function bootstrapWorkers() {
}
prettyPrint.start(`${workerPath}/pretty-print-worker.js`);
+ parser = new ParserDispatcher();
+
parser.start(`${workerPath}/parser-worker.js`);
search.start(`${workerPath}/search-worker.js`);
- return { prettyPrint, parser, search };
+ return { ...panelWorkers, prettyPrint, parser, search };
}
export function teardownWorkers() {
diff --git a/devtools/client/debugger/src/utils/pause/mapScopes/index.js b/devtools/client/debugger/src/utils/pause/mapScopes/index.js
index d59dda90631a..075dc7dc8119 100644
--- a/devtools/client/debugger/src/utils/pause/mapScopes/index.js
+++ b/devtools/client/debugger/src/utils/pause/mapScopes/index.js
@@ -7,7 +7,6 @@
import typeof SourceMaps from "devtools-source-map";
import {
- getScopes,
type SourceScope,
type BindingData,
type BindingLocation
@@ -37,6 +36,8 @@ import {
} from "./getApplicableBindingsForOriginalPosition";
import { log } from "../../log";
+import type { ThunkArgs } from "../../../actions/types";
+
import type {
PartialPosition,
Frame,
@@ -54,16 +55,15 @@ export async function buildMappedScopes(
content: SourceContent,
frame: Frame,
scopes: Scope,
- sourceMaps: any,
- client: any
+ { client, parser, sourceMaps }: ThunkArgs
): Promise{
mappings: {
[string]: string
},
scope: OriginalScope
}> {
- const originalAstScopes = await getScopes(frame.location);
- const generatedAstScopes = await getScopes(frame.generatedLocation);
+ const originalAstScopes = await parser.getScopes(frame.location);
+ const generatedAstScopes = await parser.getScopes(frame.generatedLocation);
if (!originalAstScopes || !generatedAstScopes) {
return null;
diff --git a/devtools/client/debugger/src/utils/test-head.js b/devtools/client/debugger/src/utils/test-head.js
index eca2dcd5373f..cc1814a159fb 100644
--- a/devtools/client/debugger/src/utils/test-head.js
+++ b/devtools/client/debugger/src/utils/test-head.js
@@ -15,6 +15,7 @@ import reducers from "../reducers";
import actions from "../actions";
import * as selectors from "../selectors";
import { getHistory } from "../test/utils/history";
+import { parserWorker } from "../test/tests-setup";
import configureStore from "../actions/utils/create-store";
import sourceQueue from "../utils/source-queue";
import type { Source, OriginalSourceData, GeneratedSourceData } from "../types";
@@ -41,7 +42,8 @@ function createStore(client: any, initialState: any = {}, sourceMapsMock: any) {
return {
...args,
client,
- sourceMaps: sourceMapsMock !== undefined ? sourceMapsMock : sourceMaps
+ sourceMaps: sourceMapsMock !== undefined ? sourceMapsMock : sourceMaps,
+ parser: parserWorker
};
}
})(combineReducers(reducers), initialState);
diff --git a/devtools/client/debugger/src/workers/parser/index.js b/devtools/client/debugger/src/workers/parser/index.js
index f4936d09bdb8..f7706977330d 100644
--- a/devtools/client/debugger/src/workers/parser/index.js
+++ b/devtools/client/debugger/src/workers/parser/index.js
@@ -12,77 +12,71 @@ import type { SourceLocation, SourceId, SourceContent } from "../../types";
import type { SourceScope } from "./getScopes/visitor";
import type { SymbolDeclarations } from "./getSymbols";
-const dispatcher = new WorkerDispatcher();
-export const start = (url: string, win: any = window) =>
- dispatcher.start(url, win);
-export const stop = () => dispatcher.stop();
+export class ParserDispatcher extends WorkerDispatcher {
+ async findOutOfScopeLocations(
+ sourceId: string,
+ position: AstPosition
+ ): Promise {
+ return this.invoke("findOutOfScopeLocations", sourceId, position);
+ }
-export const findOutOfScopeLocations = async (
- sourceId: string,
- position: AstPosition
-): Promise =>
- dispatcher.invoke("findOutOfScopeLocations", sourceId, position);
+ async getNextStep(
+ sourceId: SourceId,
+ pausedPosition: AstPosition
+ ): Promise {
+ return this.invoke("getNextStep", sourceId, pausedPosition);
+ }
-export const getNextStep = async (
- sourceId: SourceId,
- pausedPosition: AstPosition
-): Promise =>
- dispatcher.invoke("getNextStep", sourceId, pausedPosition);
+ async clearState(): Promise {
+ return this.invoke("clearState");
+ }
-export const clearASTs = async (): Promise =>
- dispatcher.invoke("clearASTs");
+ async getScopes(location: SourceLocation): Promise {
+ return this.invoke("getScopes", location);
+ }
-export const getScopes = async (
- location: SourceLocation
-): Promise => dispatcher.invoke("getScopes", location);
+ async getSymbols(sourceId: string): Promise {
+ return this.invoke("getSymbols", sourceId);
+ }
-export const clearScopes = async (): Promise =>
- dispatcher.invoke("clearScopes");
+ async setSource(sourceId: SourceId, content: SourceContent): Promise {
+ const astSource: AstSource = {
+ id: sourceId,
+ text: content.type === "wasm" ? "" : content.value,
+ contentType: content.contentType || null,
+ isWasm: content.type === "wasm"
+ };
-export const clearSymbols = async (): Promise =>
- dispatcher.invoke("clearSymbols");
+ return this.invoke("setSource", astSource);
+ }
-export const getSymbols = async (
- sourceId: string
-): Promise => dispatcher.invoke("getSymbols", sourceId);
+ async hasSyntaxError(input: string): Promise {
+ return this.invoke("hasSyntaxError", input);
+ }
-export const setSource = async (
- sourceId: SourceId,
- content: SourceContent
-): Promise => {
- const astSource: AstSource = {
- id: sourceId,
- text: content.type === "wasm" ? "" : content.value,
- contentType: content.contentType || null,
- isWasm: content.type === "wasm"
- };
+ async mapExpression(
+ expression: string,
+ mappings: {
+ [string]: string | null
+ } | null,
+ bindings: string[],
+ shouldMapBindings?: boolean,
+ shouldMapAwait?: boolean
+ ): Promise<{ expression: string }> {
+ return this.invoke(
+ "mapExpression",
+ expression,
+ mappings,
+ bindings,
+ shouldMapBindings,
+ shouldMapAwait
+ );
+ }
- await dispatcher.invoke("setSource", astSource);
-};
-
-export const clearSources = async (): Promise =>
- dispatcher.invoke("clearSources");
-
-export const hasSyntaxError = async (input: string): Promise =>
- dispatcher.invoke("hasSyntaxError", input);
-
-export const mapExpression = async (
- expression: string,
- mappings: {
- [string]: string | null
- } | null,
- bindings: string[],
- shouldMapBindings?: boolean,
- shouldMapAwait?: boolean
-): Promise<{ expression: string }> =>
- dispatcher.invoke(
- "mapExpression",
- expression,
- mappings,
- bindings,
- shouldMapBindings,
- shouldMapAwait
- );
+ async clear() {
+ await this.clearState();
+ }
+}
export type {
SourceScope,
diff --git a/devtools/client/debugger/src/workers/parser/worker.js b/devtools/client/debugger/src/workers/parser/worker.js
index 3144c1413185..c13b33a8439e 100644
--- a/devtools/client/debugger/src/workers/parser/worker.js
+++ b/devtools/client/debugger/src/workers/parser/worker.js
@@ -16,16 +16,20 @@ import mapExpression from "./mapExpression";
import { workerUtils } from "devtools-utils";
const { workerHandler } = workerUtils;
+function clearState() {
+ clearASTs();
+ clearScopes();
+ clearSources();
+ clearSymbols();
+}
+
self.onmessage = workerHandler({
findOutOfScopeLocations,
getSymbols,
getScopes,
- clearSymbols,
- clearScopes,
- clearASTs,
- setSource,
- clearSources,
+ clearState,
getNextStep,
hasSyntaxError,
- mapExpression
+ mapExpression,
+ setSource
});
diff --git a/devtools/client/debugger/test/mochitest/helpers.js b/devtools/client/debugger/test/mochitest/helpers.js
index 40dd62c43474..3c36f1355d19 100644
--- a/devtools/client/debugger/test/mochitest/helpers.js
+++ b/devtools/client/debugger/test/mochitest/helpers.js
@@ -1060,8 +1060,8 @@ const keyMappings = {
fileSearchPrev: { code: "g", modifiers: cmdShift },
Enter: { code: "VK_RETURN" },
ShiftEnter: { code: "VK_RETURN", modifiers: shiftOrAlt },
- AltEnter: {
- code: "VK_RETURN",
+ AltEnter: {
+ code: "VK_RETURN",
modifiers: { altKey: true }
},
Up: { code: "VK_UP" },
diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js
index a6dc58716d08..764b66b15bda 100644
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -937,6 +937,24 @@ Toolbox.prototype = {
return this._createSourceMapService();
},
+ /**
+ * A common access point for the client-side parser service that any panel can use.
+ */
+ get parserService() {
+ if (this._parserService) {
+ return this._parserService;
+ }
+
+ const { ParserDispatcher } =
+ require("devtools/client/debugger/src/workers/parser/index");
+
+ this._parserService = new ParserDispatcher();
+ this._parserService.start(
+ "resource://devtools/client/debugger/dist/parser-worker.js",
+ this.win);
+ return this._parserService;
+ },
+
/**
* Clients wishing to use source maps but that want the toolbox to
* track the source and style sheet actor mapping can use this
@@ -3074,11 +3092,17 @@ Toolbox.prototype = {
this._sourceMapURLService.destroy();
this._sourceMapURLService = null;
}
+
if (this._sourceMapService) {
this._sourceMapService.stopSourceMapWorker();
this._sourceMapService = null;
}
+ if (this._parserService) {
+ this._parserService.stop();
+ this._parserService = null;
+ }
+
if (this.webconsolePanel) {
this._saveSplitConsoleHeight();
this.webconsolePanel.removeEventListener("resize",
diff --git a/devtools/client/webconsole/webconsole.js b/devtools/client/webconsole/webconsole.js
index 979335aad1f4..883d13dd2967 100644
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -301,17 +301,15 @@ class WebConsole {
return null;
}
- /**
- * A common access point for the client-side parser service that any panel can use.
- */
get parserService() {
if (this._parserService) {
return this._parserService;
}
- this._parserService =
+ const { ParserDispatcher } =
require("devtools/client/debugger/src/workers/parser/index");
+ this._parserService = new ParserDispatcher();
this._parserService.start(
"resource://devtools/client/debugger/dist/parser-worker.js",
this.chromeUtilsWindow);
diff --git a/devtools/server/actors/animation-type-longhand.js b/devtools/server/actors/animation-type-longhand.js
index 60c40195f0b6..d9b8dd703ca0 100644
--- a/devtools/server/actors/animation-type-longhand.js
+++ b/devtools/server/actors/animation-type-longhand.js
@@ -293,6 +293,8 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"bottom",
"column-gap",
"column-width",
+ "cx",
+ "cy",
"flex-basis",
"height",
"left",
@@ -315,6 +317,9 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"padding-right",
"padding-top",
"perspective",
+ "r",
+ "rx",
+ "ry",
"right",
"row-gap",
"scroll-padding-block-start",
@@ -342,6 +347,8 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"vertical-align",
"width",
"word-spacing",
+ "x",
+ "y",
"z-index",
])],
["float", new Set([
diff --git a/devtools/shared/css/generated/properties-db.js b/devtools/shared/css/generated/properties-db.js
index abeac8eba0f0..b057e8b53571 100644
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -3315,6 +3315,13 @@ exports.CSS_PROPERTIES = {
"mask-size",
"mask-composite",
"mask-image",
+ "x",
+ "y",
+ "cx",
+ "cy",
+ "rx",
+ "ry",
+ "r",
"-moz-box-align",
"-moz-box-direction",
"-moz-box-flex",
@@ -5832,6 +5839,32 @@ exports.CSS_PROPERTIES = {
"zoom-out"
]
},
+ "cx": {
+ "isInherited": false,
+ "subproperties": [
+ "cx"
+ ],
+ "supports": [],
+ "values": [
+ "inherit",
+ "initial",
+ "revert",
+ "unset"
+ ]
+ },
+ "cy": {
+ "isInherited": false,
+ "subproperties": [
+ "cy"
+ ],
+ "supports": [],
+ "values": [
+ "inherit",
+ "initial",
+ "revert",
+ "unset"
+ ]
+ },
"direction": {
"isInherited": true,
"subproperties": [
@@ -8915,6 +8948,19 @@ exports.CSS_PROPERTIES = {
"unset"
]
},
+ "r": {
+ "isInherited": false,
+ "subproperties": [
+ "r"
+ ],
+ "supports": [],
+ "values": [
+ "inherit",
+ "initial",
+ "revert",
+ "unset"
+ ]
+ },
"resize": {
"isInherited": false,
"subproperties": [
@@ -8994,6 +9040,34 @@ exports.CSS_PROPERTIES = {
"unset"
]
},
+ "rx": {
+ "isInherited": false,
+ "subproperties": [
+ "rx"
+ ],
+ "supports": [],
+ "values": [
+ "auto",
+ "inherit",
+ "initial",
+ "revert",
+ "unset"
+ ]
+ },
+ "ry": {
+ "isInherited": false,
+ "subproperties": [
+ "ry"
+ ],
+ "supports": [],
+ "values": [
+ "auto",
+ "inherit",
+ "initial",
+ "revert",
+ "unset"
+ ]
+ },
"scroll-behavior": {
"isInherited": false,
"subproperties": [
@@ -10444,6 +10518,32 @@ exports.CSS_PROPERTIES = {
"vertical-rl"
]
},
+ "x": {
+ "isInherited": false,
+ "subproperties": [
+ "x"
+ ],
+ "supports": [],
+ "values": [
+ "inherit",
+ "initial",
+ "revert",
+ "unset"
+ ]
+ },
+ "y": {
+ "isInherited": false,
+ "subproperties": [
+ "y"
+ ],
+ "supports": [],
+ "values": [
+ "inherit",
+ "initial",
+ "revert",
+ "unset"
+ ]
+ },
"z-index": {
"isInherited": false,
"subproperties": [
@@ -10596,38 +10696,6 @@ exports.PREFERENCES = [
"-moz-binding",
"layout.css.moz-binding.content.enabled"
],
- [
- "scroll-padding-block-end",
- "layout.css.scroll-snap-v1.enabled"
- ],
- [
- "scroll-padding-block-start",
- "layout.css.scroll-snap-v1.enabled"
- ],
- [
- "scroll-padding-bottom",
- "layout.css.scroll-snap-v1.enabled"
- ],
- [
- "scroll-padding-inline-end",
- "layout.css.scroll-snap-v1.enabled"
- ],
- [
- "scroll-padding-inline-start",
- "layout.css.scroll-snap-v1.enabled"
- ],
- [
- "scroll-padding-left",
- "layout.css.scroll-snap-v1.enabled"
- ],
- [
- "scroll-padding-right",
- "layout.css.scroll-snap-v1.enabled"
- ],
- [
- "scroll-padding-top",
- "layout.css.scroll-snap-v1.enabled"
- ],
[
"scroll-margin-block-end",
"layout.css.scroll-snap-v1.enabled"
@@ -10660,6 +10728,38 @@ exports.PREFERENCES = [
"scroll-margin-top",
"layout.css.scroll-snap-v1.enabled"
],
+ [
+ "scroll-padding-block-end",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
+ [
+ "scroll-padding-block-start",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
+ [
+ "scroll-padding-bottom",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
+ [
+ "scroll-padding-inline-end",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
+ [
+ "scroll-padding-inline-start",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
+ [
+ "scroll-padding-left",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
+ [
+ "scroll-padding-right",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
+ [
+ "scroll-padding-top",
+ "layout.css.scroll-snap-v1.enabled"
+ ],
[
"-webkit-text-stroke-width",
"layout.css.prefixes.webkit"
diff --git a/docshell/base/nsDocShellTreeOwner.cpp b/docshell/base/nsDocShellTreeOwner.cpp
index eb9a7b5e3575..a80424ce4268 100644
--- a/docshell/base/nsDocShellTreeOwner.cpp
+++ b/docshell/base/nsDocShellTreeOwner.cpp
@@ -873,11 +873,9 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
} else if (eventType.EqualsLiteral("drop")) {
nsIWebNavigation* webnav = static_cast(mWebBrowser);
- uint32_t linksCount;
- nsIDroppedLinkItem** links;
- if (webnav && NS_SUCCEEDED(handler->DropLinks(dragEvent, true, &linksCount,
- &links))) {
- if (linksCount >= 1) {
+ nsTArray> links;
+ if (webnav && NS_SUCCEEDED(handler->DropLinks(dragEvent, true, links))) {
+ if (links.Length() >= 1) {
nsCOMPtr triggeringPrincipal;
handler->GetTriggeringPrincipal(dragEvent,
getter_AddRefs(triggeringPrincipal));
@@ -888,11 +886,7 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
nsCOMPtr browserChild =
do_QueryInterface(webBrowserChrome);
if (browserChild) {
- nsresult rv = browserChild->RemoteDropLinks(linksCount, links);
- for (uint32_t i = 0; i < linksCount; i++) {
- NS_RELEASE(links[i]);
- }
- free(links);
+ nsresult rv = browserChild->RemoteDropLinks(links);
return rv;
}
}
@@ -912,11 +906,6 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
webnav->LoadURI(url, loadURIOptions);
}
}
-
- for (uint32_t i = 0; i < linksCount; i++) {
- NS_RELEASE(links[i]);
- }
- free(links);
}
}
} else {
diff --git a/dom/base/ContentAreaDropListener.jsm b/dom/base/ContentAreaDropListener.jsm
index 7cbb7f659475..03b4f5841fe9 100644
--- a/dom/base/ContentAreaDropListener.jsm
+++ b/dom/base/ContentAreaDropListener.jsm
@@ -276,7 +276,7 @@ ContentAreaDropListener.prototype =
return url;
},
- dropLinks: function(aEvent, aDisallowInherit, aCount)
+ dropLinks: function(aEvent, aDisallowInherit)
{
if (aEvent && this._eventTargetIsDisabled(aEvent))
return [];
@@ -297,13 +297,11 @@ ContentAreaDropListener.prototype =
throw ex;
}
}
- if (aCount)
- aCount.value = links.length;
return links;
},
- validateURIsForDrop: function(aEvent, aURIsCount, aURIs, aDisallowInherit)
+ validateURIsForDrop: function(aEvent, aURIs, aDisallowInherit)
{
let dataTransfer = aEvent.dataTransfer;
let triggeringPrincipal = this._getTriggeringPrincipalFromDataTransfer(dataTransfer, false);
@@ -314,13 +312,9 @@ ContentAreaDropListener.prototype =
}
},
- queryLinks: function(aDataTransfer, aCount)
+ queryLinks: function(aDataTransfer)
{
- let links = this._getDropLinks(aDataTransfer);
- if (aCount) {
- aCount.value = links.length;
- }
- return links;
+ return this._getDropLinks(aDataTransfer);
},
_eventTargetIsDisabled: function(aEvent)
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp
index d5108bc1ceba..a5e6dfbc35b4 100644
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -293,6 +293,7 @@ void DOMIntersectionObserver::Update(Document* aDocument,
for (size_t i = 0; i < mObservationTargets.Length(); ++i) {
Element* target = mObservationTargets.ElementAt(i);
nsIFrame* targetFrame = target->GetPrimaryFrame();
+ nsIFrame* originalTargetFrame = targetFrame;
nsRect targetRect;
Maybe intersectionRect;
bool isSameDoc = root && root->GetComposedDoc() == target->GetComposedDoc();
@@ -374,7 +375,7 @@ void DOMIntersectionObserver::Update(Document* aDocument,
intersectionRectRelativeToRoot, rootIntersectionRect);
if (intersectionRect.isSome() && !isSameDoc) {
nsRect rect = intersectionRect.value();
- nsPresContext* presContext = targetFrame->PresContext();
+ nsPresContext* presContext = originalTargetFrame->PresContext();
nsIFrame* rootScrollFrame =
presContext->PresShell()->GetRootScrollFrame();
if (rootScrollFrame) {
diff --git a/dom/base/nsIDroppedLinkHandler.idl b/dom/base/nsIDroppedLinkHandler.idl
index 3dbfcbb296fb..4967894e821d 100644
--- a/dom/base/nsIDroppedLinkHandler.idl
+++ b/dom/base/nsIDroppedLinkHandler.idl
@@ -65,7 +65,7 @@ interface nsIDroppedLinkHandler : nsISupports
/**
* Given a drop event aEvent, determines links being dragged and returns
* them. If links are returned the caller can, for instance, load them. If
- * the count of links is 0, there is no valid link to be dropped.
+ * the returned array is empty, there is no valid link to be dropped.
*
* A NS_ERROR_DOM_SECURITY_ERR error will be thrown and the event cancelled if
* the receiving target should not load the uri for security reasons. This
@@ -76,10 +76,8 @@ interface nsIDroppedLinkHandler : nsISupports
* - aDisallowInherit is true, and the URI being dropped would inherit the
* current document's security context (URI_INHERITS_SECURITY_CONTEXT).
*/
- void dropLinks(in DragEvent aEvent,
- [optional] in boolean aDisallowInherit,
- [optional] out unsigned long aCount,
- [retval, array, size_is(aCount)] out nsIDroppedLinkItem aLinks);
+ Array dropLinks(in DragEvent aEvent,
+ [optional] in boolean aDisallowInherit);
/**
* Given a drop event aEvent, validate the extra URIs for the event,
@@ -87,8 +85,7 @@ interface nsIDroppedLinkHandler : nsISupports
* text, like home button that splits the text with "|".
*/
void validateURIsForDrop(in DragEvent aEvent,
- in unsigned long aURIsCount,
- [array, size_is(aURIsCount)] in wstring aURIs,
+ in Array aURIs,
[optional] in boolean aDisallowInherit);
/**
@@ -97,9 +94,7 @@ interface nsIDroppedLinkHandler : nsISupports
* it allows the parent to verify that the child did not modify links
* being dropped.
*/
- void queryLinks(in DataTransfer aDataTransfer,
- [optional] out unsigned long aCount,
- [retval, array, size_is(aCount)] out nsIDroppedLinkItem aLinks);
+ Array queryLinks(in DataTransfer aDataTransfer);
/**
* Given a drop event aEvent, determines the triggering principal for the
diff --git a/dom/credentialmanagement/tests/mochitest/test_credman_iframes.html b/dom/credentialmanagement/tests/mochitest/test_credman_iframes.html
index 3c5a3a01262f..e5d3fccc5516 100644
--- a/dom/credentialmanagement/tests/mochitest/test_credman_iframes.html
+++ b/dom/credentialmanagement/tests/mochitest/test_credman_iframes.html
@@ -45,7 +45,8 @@ function handleEventMessage(event) {
window.addEventListener("message", handleEventMessage);
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
- ["security.webauth.webauthn_enable_usbtoken", false]]},
+ ["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false]]},
function() {
document.getElementById("frame_top").src = "https://example.com/tests/dom/credentialmanagement/tests/mochitest/frame_credman_iframes.html";
diff --git a/dom/interfaces/base/nsIBrowser.idl b/dom/interfaces/base/nsIBrowser.idl
index 7137ca8fde53..85b161f9b7de 100644
--- a/dom/interfaces/base/nsIBrowser.idl
+++ b/dom/interfaces/base/nsIBrowser.idl
@@ -25,14 +25,12 @@ interface nsIBrowser : nsISupports
* Called by the child to inform the parent that links are dropped into
* content area.
*
- * @param linksCount length of links
* @param links a flat array of url, name, and type for each link
* @param triggeringPrincipal a principal that initiated loading
* of the dropped links
*/
- void dropLinks(in unsigned long linksCount,
- [array, size_is(linksCount)] in wstring links,
- in nsIPrincipal aTriggeringPrincipal);
+ void dropLinks(in Array links,
+ in nsIPrincipal triggeringPrincipal);
/**
* Swapping of frameloaders are usually initiated from a frameloader owner
@@ -73,16 +71,12 @@ interface nsIBrowser : nsISupports
* and the supplied set of commands are now enabled and disabled.
*
* @param action command updater action
- * @param enabledLength length of enabledCommands array
* @param enabledCommands commands to enable
- * @param disabledLength length of disabledCommands array
* @param disabledCommand commands to disable
*/
void enableDisableCommandsRemoteOnly(in AString action,
- in unsigned long enabledLength,
- [array, size_is(enabledLength)] in string enabledCommands,
- in unsigned long disabledLength,
- [array, size_is(disabledLength)] in string disabledCommands);
+ in Array enabledCommands,
+ in Array disabledCommands);
readonly attribute nsIPrincipal contentPrincipal;
readonly attribute nsIContentSecurityPolicy csp;
diff --git a/dom/interfaces/base/nsIBrowserChild.idl b/dom/interfaces/base/nsIBrowserChild.idl
index f886af7da10f..278898ced863 100644
--- a/dom/interfaces/base/nsIBrowserChild.idl
+++ b/dom/interfaces/base/nsIBrowserChild.idl
@@ -29,8 +29,7 @@ interface nsIBrowserChild : nsISupports
[noscript] void remoteSizeShellTo(in int32_t width, in int32_t height,
in int32_t shellItemWidth, in int32_t shellItemHeight);
- [noscript] void remoteDropLinks(in unsigned long linksCount,
- [array, size_is(linksCount)] in nsIDroppedLinkItem links);
+ void remoteDropLinks(in Array links);
readonly attribute uint64_t tabId;
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
index a97ae84febbf..1c16e7be4a6b 100644
--- a/dom/ipc/BrowserChild.cpp
+++ b/dom/ipc/BrowserChild.cpp
@@ -735,25 +735,25 @@ BrowserChild::RemoteSizeShellTo(int32_t aWidth, int32_t aHeight,
}
NS_IMETHODIMP
-BrowserChild::RemoteDropLinks(uint32_t aLinksCount,
- nsIDroppedLinkItem** aLinks) {
+BrowserChild::RemoteDropLinks(
+ const nsTArray>& aLinks) {
nsTArray linksArray;
nsresult rv = NS_OK;
- for (uint32_t i = 0; i < aLinksCount; i++) {
+ for (nsIDroppedLinkItem* link : aLinks) {
nsString tmp;
- rv = aLinks[i]->GetUrl(tmp);
+ rv = link->GetUrl(tmp);
if (NS_FAILED(rv)) {
return rv;
}
linksArray.AppendElement(tmp);
- rv = aLinks[i]->GetName(tmp);
+ rv = link->GetName(tmp);
if (NS_FAILED(rv)) {
return rv;
}
linksArray.AppendElement(tmp);
- rv = aLinks[i]->GetType(tmp);
+ rv = link->GetType(tmp);
if (NS_FAILED(rv)) {
return rv;
}
@@ -1816,7 +1816,8 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealTouchEvent(
}
UniquePtr postLayerization =
APZCCallbackHelper::SendSetTargetAPZCNotification(
- mPuppetWidget, document, localEvent, aGuid.mLayersId, aInputBlockId);
+ mPuppetWidget, document, localEvent, aGuid.mLayersId,
+ aInputBlockId);
if (postLayerization && postLayerization->Register()) {
Unused << postLayerization.release();
}
diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp
index 3df0d4fde821..843a690a01cc 100644
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -809,15 +809,12 @@ mozilla::ipc::IPCResult BrowserParent::RecvDropLinks(
if (aLinks.Length() != mVerifyDropLinks.Length()) {
loadUsingSystemPrincipal = false;
}
- UniquePtr links;
- links = MakeUnique(aLinks.Length());
for (uint32_t i = 0; i < aLinks.Length(); i++) {
if (loadUsingSystemPrincipal) {
if (!aLinks[i].Equals(mVerifyDropLinks[i])) {
loadUsingSystemPrincipal = false;
}
}
- links[i] = aLinks[i].get();
}
mVerifyDropLinks.Clear();
nsCOMPtr triggeringPrincipal;
@@ -826,7 +823,7 @@ mozilla::ipc::IPCResult BrowserParent::RecvDropLinks(
} else {
triggeringPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
}
- browser->DropLinks(aLinks.Length(), links.get(), triggeringPrincipal);
+ browser->DropLinks(aLinks, triggeringPrincipal);
}
return IPC_OK();
}
@@ -1394,42 +1391,36 @@ bool BrowserParent::QueryDropLinksForVerification() {
// verification array and store all links that are being dragged.
mVerifyDropLinks.Clear();
- uint32_t linksCount = 0;
- nsIDroppedLinkItem** droppedLinkedItems = nullptr;
- dropHandler->QueryLinks(initialDataTransfer, &linksCount,
- &droppedLinkedItems);
+ nsTArray> droppedLinkItems;
+ dropHandler->QueryLinks(initialDataTransfer, droppedLinkItems);
// Since the entire event is cancelled if one of the links is invalid,
// we can store all links on the parent side without any prior
// validation checks.
nsresult rv = NS_OK;
- for (uint32_t i = 0; i < linksCount; i++) {
+ for (nsIDroppedLinkItem* item : droppedLinkItems) {
nsString tmp;
- rv = droppedLinkedItems[i]->GetUrl(tmp);
+ rv = item->GetUrl(tmp);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to query url for verification");
break;
}
mVerifyDropLinks.AppendElement(tmp);
- rv = droppedLinkedItems[i]->GetName(tmp);
+ rv = item->GetName(tmp);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to query name for verification");
break;
}
mVerifyDropLinks.AppendElement(tmp);
- rv = droppedLinkedItems[i]->GetType(tmp);
+ rv = item->GetType(tmp);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to query type for verification");
break;
}
mVerifyDropLinks.AppendElement(tmp);
}
- for (uint32_t i = 0; i < linksCount; i++) {
- NS_IF_RELEASE(droppedLinkedItems[i]);
- }
- free(droppedLinkedItems);
if (NS_FAILED(rv)) {
mVerifyDropLinks.Clear();
return false;
@@ -2163,25 +2154,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvEnableDisableCommands(
browser->GetIsRemoteBrowser(&isRemoteBrowser);
}
if (isRemoteBrowser) {
- UniquePtr enabledCommands, disabledCommands;
-
- if (aEnabledCommands.Length()) {
- enabledCommands = MakeUnique(aEnabledCommands.Length());
- for (uint32_t c = 0; c < aEnabledCommands.Length(); c++) {
- enabledCommands[c] = aEnabledCommands[c].get();
- }
- }
-
- if (aDisabledCommands.Length()) {
- disabledCommands = MakeUnique(aDisabledCommands.Length());
- for (uint32_t c = 0; c < aDisabledCommands.Length(); c++) {
- disabledCommands[c] = aDisabledCommands[c].get();
- }
- }
-
- browser->EnableDisableCommandsRemoteOnly(
- aAction, aEnabledCommands.Length(), enabledCommands.get(),
- aDisabledCommands.Length(), disabledCommands.get());
+ browser->EnableDisableCommandsRemoteOnly(aAction, aEnabledCommands,
+ aDisabledCommands);
}
return IPC_OK();
diff --git a/dom/smil/SMILCompositor.cpp b/dom/smil/SMILCompositor.cpp
index 17363a5ddf92..bd1bae189852 100644
--- a/dom/smil/SMILCompositor.cpp
+++ b/dom/smil/SMILCompositor.cpp
@@ -6,6 +6,7 @@
#include "SMILCompositor.h"
+#include "mozilla/dom/SVGSVGElement.h"
#include "nsComputedDOMStyle.h"
#include "nsCSSProps.h"
#include "nsHashKeys.h"
@@ -147,19 +148,21 @@ nsCSSPropertyID SMILCompositor::GetCSSPropertyToAnimate() const {
// If we are animating the 'width' or 'height' of an outer SVG
// element we should animate it as a CSS property, but for other elements
- // (e.g. ) we should animate it as a length attribute.
- // The easiest way to test for an outer SVG element, is to see if it is an
- // SVG-namespace element mapping its width/height attribute to style.
- //
- // If we have animation of 'width' or 'height' on an SVG element that is
- // NOT mapping that attributes to style then it must not be an outermost SVG
- // element so we should return eCSSProperty_UNKNOWN to indicate that we
- // should animate as an attribute instead.
+ // in SVG namespace (e.g. ) we should animate it as a length attribute.
if ((mKey.mAttributeName == nsGkAtoms::width ||
mKey.mAttributeName == nsGkAtoms::height) &&
- mKey.mElement->GetNameSpaceID() == kNameSpaceID_SVG &&
- !mKey.mElement->IsAttributeMapped(mKey.mAttributeName)) {
- return eCSSProperty_UNKNOWN;
+ mKey.mElement->GetNameSpaceID() == kNameSpaceID_SVG) {
+ // Not an element.
+ if (!mKey.mElement->IsSVGElement(nsGkAtoms::svg)) {
+ return eCSSProperty_UNKNOWN;
+ }
+
+ // An inner element
+ if (static_cast(*mKey.mElement).IsInner()) {
+ return eCSSProperty_UNKNOWN;
+ }
+
+ // Indeed an outer element, fall through.
}
return propID;
diff --git a/dom/svg/SVGCircleElement.cpp b/dom/svg/SVGCircleElement.cpp
index 014de7545b6f..d8dc354b2bbd 100644
--- a/dom/svg/SVGCircleElement.cpp
+++ b/dom/svg/SVGCircleElement.cpp
@@ -4,11 +4,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "ComputedStyle.h"
#include "mozilla/dom/SVGCircleElement.h"
#include "mozilla/gfx/2D.h"
#include "nsGkAtoms.h"
#include "mozilla/dom/SVGCircleElementBinding.h"
#include "mozilla/dom/SVGLengthBinding.h"
+#include "SVGGeometryProperty.h"
NS_IMPL_NS_NEW_SVG_ELEMENT(Circle)
@@ -37,6 +39,13 @@ SVGCircleElement::SVGCircleElement(
already_AddRefed&& aNodeInfo)
: SVGCircleElementBase(std::move(aNodeInfo)) {}
+bool SVGCircleElement::IsAttributeMapped(const nsAtom* aAttribute) const {
+ return IsInLengthInfo(aAttribute, sLengthInfo) ||
+ SVGCircleElementBase::IsAttributeMapped(aAttribute);
+}
+
+namespace SVGT = SVGGeometryProperty::Tags;
+
//----------------------------------------------------------------------
// nsINode methods
@@ -61,8 +70,11 @@ already_AddRefed SVGCircleElement::R() {
/* virtual */
bool SVGCircleElement::HasValidDimensions() const {
- return mLengthAttributes[ATTR_R].IsExplicitlySet() &&
- mLengthAttributes[ATTR_R].GetAnimValInSpecifiedUnits() > 0;
+ float r;
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(this, &r);
+ return r > 0;
}
SVGElement::LengthAttributesInfo SVGCircleElement::GetLengthInfo() {
@@ -77,7 +89,10 @@ bool SVGCircleElement::GetGeometryBounds(
Rect* aBounds, const StrokeOptions& aStrokeOptions,
const Matrix& aToBoundsSpace, const Matrix* aToNonScalingStrokeSpace) {
float x, y, r;
- GetAnimatedLengthValues(&x, &y, &r, nullptr);
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(this, &x, &y,
+ &r);
if (r <= 0.f) {
// Rendering of the element is disabled
@@ -112,7 +127,9 @@ bool SVGCircleElement::GetGeometryBounds(
already_AddRefed SVGCircleElement::BuildPath(PathBuilder* aBuilder) {
float x, y, r;
- GetAnimatedLengthValues(&x, &y, &r, nullptr);
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(this, &x, &y,
+ &r);
if (r <= 0.0f) {
return nullptr;
@@ -123,5 +140,30 @@ already_AddRefed SVGCircleElement::BuildPath(PathBuilder* aBuilder) {
return aBuilder->Finish();
}
+bool SVGCircleElement::IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
+ const ComputedStyle& aOldStyle) {
+ auto *newSVGReset = aNewStyle.StyleSVGReset(),
+ *oldSVGReset = aOldStyle.StyleSVGReset();
+
+ return newSVGReset->mCx != oldSVGReset->mCx ||
+ newSVGReset->mCy != oldSVGReset->mCy ||
+ newSVGReset->mR != oldSVGReset->mR;
+}
+
+nsCSSPropertyID SVGCircleElement::GetCSSPropertyIdForAttrEnum(
+ uint8_t aAttrEnum) {
+ switch (aAttrEnum) {
+ case ATTR_CX:
+ return eCSSProperty_cx;
+ case ATTR_CY:
+ return eCSSProperty_cy;
+ case ATTR_R:
+ return eCSSProperty_r;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unknown attr enum");
+ return eCSSProperty_UNKNOWN;
+ }
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/svg/SVGCircleElement.h b/dom/svg/SVGCircleElement.h
index b0be1f8e021d..efd82e5d7f53 100644
--- a/dom/svg/SVGCircleElement.h
+++ b/dom/svg/SVGCircleElement.h
@@ -7,6 +7,7 @@
#ifndef mozilla_dom_SVGCircleElement_h
#define mozilla_dom_SVGCircleElement_h
+#include "nsCSSPropertyID.h"
#include "SVGGeometryElement.h"
#include "SVGAnimatedLength.h"
@@ -14,6 +15,8 @@ nsresult NS_NewSVGCircleElement(
nsIContent** aResult, already_AddRefed&& aNodeInfo);
namespace mozilla {
+class ComputedStyle;
+
namespace dom {
typedef SVGGeometryElement SVGCircleElementBase;
@@ -29,6 +32,8 @@ class SVGCircleElement final : public SVGCircleElementBase {
already_AddRefed&& aNodeInfo));
public:
+ NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
+
// nsSVGSVGElement methods:
virtual bool HasValidDimensions() const override;
@@ -41,6 +46,10 @@ class SVGCircleElement final : public SVGCircleElementBase {
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
+ static bool IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
+ const ComputedStyle& aOldStyle);
+ static nsCSSPropertyID GetCSSPropertyIdForAttrEnum(uint8_t aAttrEnum);
+
// WebIDL
already_AddRefed Cx();
already_AddRefed Cy();
diff --git a/dom/svg/SVGElement.cpp b/dom/svg/SVGElement.cpp
index 9c023336f356..7635ff0e6c22 100644
--- a/dom/svg/SVGElement.cpp
+++ b/dom/svg/SVGElement.cpp
@@ -30,6 +30,7 @@
#include "nsAttrValueOrString.h"
#include "nsCSSProps.h"
#include "nsContentUtils.h"
+#include "nsDOMCSSAttrDeclaration.h"
#include "nsICSSDeclaration.h"
#include "nsIContentInlines.h"
#include "mozilla/dom/Document.h"
@@ -53,6 +54,7 @@
#include "SVGAnimatedOrient.h"
#include "SVGAnimatedString.h"
#include "SVGAnimatedViewBox.h"
+#include "SVGGeometryProperty.h"
#include "SVGMotionSMILAttr.h"
#include
@@ -1020,6 +1022,41 @@ already_AddRefed SVGElement::ClassName() {
return mClassAttribute.ToDOMAnimatedString(this);
}
+/* static */
+bool SVGElement::UpdateDeclarationBlockFromLength(
+ DeclarationBlock& aBlock, nsCSSPropertyID aPropId,
+ const SVGAnimatedLength& aLength, ValToUse aValToUse) {
+ aBlock.AssertMutable();
+
+ float value;
+ if (aValToUse == ValToUse::Anim) {
+ value = aLength.GetAnimValInSpecifiedUnits();
+ } else {
+ MOZ_ASSERT(aValToUse == ValToUse::Base);
+ value = aLength.GetBaseValInSpecifiedUnits();
+ }
+
+ // SVG parser doesn't check non-negativity of some parsed value,
+ // we should not pass those to CSS side.
+ if (value < 0 &&
+ SVGGeometryProperty::IsNonNegativeGeometryProperty(aPropId)) {
+ return false;
+ }
+
+ nsCSSUnit cssUnit = SVGGeometryProperty::SpecifiedUnitTypeToCSSUnit(
+ aLength.GetSpecifiedUnitType());
+
+ if (cssUnit == eCSSUnit_Percent) {
+ Servo_DeclarationBlock_SetPercentValue(aBlock.Raw(), aPropId,
+ value / 100.f);
+ } else {
+ Servo_DeclarationBlock_SetLengthValue(aBlock.Raw(), aPropId, value,
+ cssUnit);
+ }
+
+ return true;
+}
+
//------------------------------------------------------------------------
// Helper class: MappedAttrParser, for parsing values of mapped attributes
@@ -1035,6 +1072,9 @@ class MOZ_STACK_CLASS MappedAttrParser {
void ParseMappedAttrValue(nsAtom* aMappedAttrName,
const nsAString& aMappedAttrValue);
+ void TellStyleAlreadyParsedResult(nsAtom const* aAtom,
+ SVGAnimatedLength const& aLength);
+
// If we've parsed any values for mapped attributes, this method returns the
// already_AddRefed css::Declaration that incorporates the parsed
// values. Otherwise, this method returns null.
@@ -1122,6 +1162,18 @@ void MappedAttrParser::ParseMappedAttrValue(nsAtom* aMappedAttrName,
}
}
+void MappedAttrParser::TellStyleAlreadyParsedResult(
+ nsAtom const* aAtom, SVGAnimatedLength const& aLength) {
+ if (!mDecl) {
+ mDecl = new DeclarationBlock();
+ }
+ nsCSSPropertyID propertyID =
+ nsCSSProps::LookupProperty(nsDependentAtomString(aAtom));
+
+ SVGElement::UpdateDeclarationBlockFromLength(*mDecl, propertyID, aLength,
+ SVGElement::ValToUse::Base);
+}
+
already_AddRefed MappedAttrParser::GetDeclarationBlock() {
return mDecl.forget();
}
@@ -1145,6 +1197,9 @@ void SVGElement::UpdateContentDeclarationBlock() {
MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
GetBaseURI(), this);
+ bool lengthAffectsStyle =
+ SVGGeometryProperty::ElementMapsLengthsToStyle(this);
+
for (uint32_t i = 0; i < attrCount; ++i) {
const nsAttrName* attrName = mAttrs.AttrNameAt(i);
if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom())) continue;
@@ -1177,6 +1232,20 @@ void SVGElement::UpdateContentDeclarationBlock() {
}
}
+ if (lengthAffectsStyle) {
+ auto const* length = GetAnimatedLength(attrName->Atom());
+
+ if (length && length->HasBaseVal()) {
+ // This is an element with geometry property set via SVG attribute,
+ // and the attribute is already successfully parsed. We want to go
+ // through the optimized path to tell the style system the result
+ // directly, rather than let it parse the same thing again.
+ mappedAttrParser.TellStyleAlreadyParsedResult(attrName->Atom(),
+ *length);
+ continue;
+ }
+ }
+
nsAutoString value;
mAttrs.AttrAt(i)->ToString(value);
mappedAttrParser.ParseMappedAttrValue(attrName->Atom(), value);
@@ -1391,6 +1460,15 @@ void SVGElement::DidChangeLength(uint8_t aAttrEnum,
}
void SVGElement::DidAnimateLength(uint8_t aAttrEnum) {
+ if (SVGGeometryProperty::ElementMapsLengthsToStyle(this)) {
+ nsCSSPropertyID propId =
+ SVGGeometryProperty::AttrEnumToCSSPropId(this, aAttrEnum);
+
+ SMILOverrideStyle()->SetSMILValue(propId,
+ GetLengthInfo().mLengths[aAttrEnum]);
+ return;
+ }
+
ClearAnyCachedPath();
nsIFrame* frame = GetPrimaryFrame();
@@ -1411,7 +1489,6 @@ SVGAnimatedLength* SVGElement::GetAnimatedLength(const nsAtom* aAttrName) {
return &lengthInfo.mLengths[i];
}
}
- MOZ_ASSERT(false, "no matching length found");
return nullptr;
}
diff --git a/dom/svg/SVGElement.h b/dom/svg/SVGElement.h
index 0a745ecc1fdc..e43546f9af30 100644
--- a/dom/svg/SVGElement.h
+++ b/dom/svg/SVGElement.h
@@ -165,6 +165,12 @@ class SVGElement : public SVGElementBase // nsIContent
virtual bool HasValidDimensions() const { return true; }
void SetLength(nsAtom* aName, const SVGAnimatedLength& aLength);
+ enum class ValToUse { Base, Anim };
+ static bool UpdateDeclarationBlockFromLength(DeclarationBlock& aBlock,
+ nsCSSPropertyID aPropId,
+ const SVGAnimatedLength& aLength,
+ ValToUse aValToUse);
+
nsAttrValue WillChangeLength(uint8_t aAttrEnum);
nsAttrValue WillChangeNumberPair(uint8_t aAttrEnum);
nsAttrValue WillChangeIntegerPair(uint8_t aAttrEnum);
diff --git a/dom/svg/SVGEllipseElement.cpp b/dom/svg/SVGEllipseElement.cpp
index ef88e78566c0..e29b6b08606f 100644
--- a/dom/svg/SVGEllipseElement.cpp
+++ b/dom/svg/SVGEllipseElement.cpp
@@ -4,12 +4,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "ComputedStyle.h"
#include "mozilla/dom/SVGEllipseElement.h"
#include "mozilla/dom/SVGEllipseElementBinding.h"
#include "mozilla/dom/SVGLengthBinding.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/RefPtr.h"
+#include "SVGGeometryProperty.h"
NS_IMPL_NS_NEW_SVG_ELEMENT(Ellipse)
@@ -41,6 +43,13 @@ SVGEllipseElement::SVGEllipseElement(
already_AddRefed&& aNodeInfo)
: SVGEllipseElementBase(std::move(aNodeInfo)) {}
+bool SVGEllipseElement::IsAttributeMapped(const nsAtom* aAttribute) const {
+ return IsInLengthInfo(aAttribute, sLengthInfo) ||
+ SVGEllipseElementBase::IsAttributeMapped(aAttribute);
+}
+
+namespace SVGT = SVGGeometryProperty::Tags;
+
//----------------------------------------------------------------------
// nsINode methods
@@ -70,10 +79,12 @@ already_AddRefed SVGEllipseElement::Ry() {
/* virtual */
bool SVGEllipseElement::HasValidDimensions() const {
- return mLengthAttributes[RX].IsExplicitlySet() &&
- mLengthAttributes[RX].GetAnimValInSpecifiedUnits() > 0 &&
- mLengthAttributes[RY].IsExplicitlySet() &&
- mLengthAttributes[RY].GetAnimValInSpecifiedUnits() > 0;
+ float rx, ry;
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(this, &rx, &ry);
+
+ return rx > 0 && ry > 0;
}
SVGElement::LengthAttributesInfo SVGEllipseElement::GetLengthInfo() {
@@ -88,7 +99,10 @@ bool SVGEllipseElement::GetGeometryBounds(
Rect* aBounds, const StrokeOptions& aStrokeOptions,
const Matrix& aToBoundsSpace, const Matrix* aToNonScalingStrokeSpace) {
float x, y, rx, ry;
- GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(
+ this, &x, &y, &rx, &ry);
if (rx <= 0.f || ry <= 0.f) {
// Rendering of the element is disabled
@@ -124,7 +138,10 @@ bool SVGEllipseElement::GetGeometryBounds(
already_AddRefed SVGEllipseElement::BuildPath(PathBuilder* aBuilder) {
float x, y, rx, ry;
- GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(
+ this, &x, &y, &rx, &ry);
if (rx <= 0.0f || ry <= 0.0f) {
return nullptr;
@@ -135,5 +152,33 @@ already_AddRefed SVGEllipseElement::BuildPath(PathBuilder* aBuilder) {
return aBuilder->Finish();
}
+bool SVGEllipseElement::IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
+ const ComputedStyle& aOldStyle) {
+ auto *newSVGReset = aNewStyle.StyleSVGReset(),
+ *oldSVGReset = aOldStyle.StyleSVGReset();
+
+ return newSVGReset->mCx != oldSVGReset->mCx ||
+ newSVGReset->mCy != oldSVGReset->mCy ||
+ newSVGReset->mRx != oldSVGReset->mRx ||
+ newSVGReset->mRy != oldSVGReset->mRy;
+}
+
+nsCSSPropertyID SVGEllipseElement::GetCSSPropertyIdForAttrEnum(
+ uint8_t aAttrEnum) {
+ switch (aAttrEnum) {
+ case CX:
+ return eCSSProperty_cx;
+ case CY:
+ return eCSSProperty_cy;
+ case RX:
+ return eCSSProperty_rx;
+ case RY:
+ return eCSSProperty_ry;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unknown attr enum");
+ return eCSSProperty_UNKNOWN;
+ }
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/svg/SVGEllipseElement.h b/dom/svg/SVGEllipseElement.h
index 26601919c29b..3e91c83c4afd 100644
--- a/dom/svg/SVGEllipseElement.h
+++ b/dom/svg/SVGEllipseElement.h
@@ -7,6 +7,7 @@
#ifndef mozilla_dom_SVGEllipseElement_h
#define mozilla_dom_SVGEllipseElement_h
+#include "nsCSSPropertyID.h"
#include "SVGAnimatedLength.h"
#include "SVGGeometryElement.h"
@@ -14,6 +15,8 @@ nsresult NS_NewSVGEllipseElement(
nsIContent** aResult, already_AddRefed&& aNodeInfo);
namespace mozilla {
+class ComputedStyle;
+
namespace dom {
typedef SVGGeometryElement SVGEllipseElementBase;
@@ -29,6 +32,8 @@ class SVGEllipseElement final : public SVGEllipseElementBase {
already_AddRefed&& aNodeInfo));
public:
+ NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
+
// nsSVGSVGElement methods:
virtual bool HasValidDimensions() const override;
@@ -41,6 +46,10 @@ class SVGEllipseElement final : public SVGEllipseElementBase {
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
+ static bool IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
+ const ComputedStyle& aOldStyle);
+ static nsCSSPropertyID GetCSSPropertyIdForAttrEnum(uint8_t aAttrEnum);
+
// WebIDL
already_AddRefed Cx();
already_AddRefed Cy();
diff --git a/dom/svg/SVGForeignObjectElement.cpp b/dom/svg/SVGForeignObjectElement.cpp
index d52fb5f318da..cc9b800fb81c 100644
--- a/dom/svg/SVGForeignObjectElement.cpp
+++ b/dom/svg/SVGForeignObjectElement.cpp
@@ -11,6 +11,7 @@
#include "mozilla/dom/SVGDocument.h"
#include "mozilla/dom/SVGForeignObjectElementBinding.h"
#include "mozilla/dom/SVGLengthBinding.h"
+#include "SVGGeometryProperty.h"
NS_IMPL_NS_NEW_SVG_ELEMENT(ForeignObject)
@@ -40,6 +41,8 @@ SVGForeignObjectElement::SVGForeignObjectElement(
already_AddRefed&& aNodeInfo)
: SVGGraphicsElement(std::move(aNodeInfo)) {}
+namespace SVGT = SVGGeometryProperty::Tags;
+
//----------------------------------------------------------------------
// nsINode methods
@@ -77,8 +80,16 @@ gfxMatrix SVGForeignObjectElement::PrependLocalTransformsTo(
}
// our 'x' and 'y' attributes:
float x, y;
- const_cast(this)->GetAnimatedLengthValues(&x, &y,
- nullptr);
+
+ if (GetPrimaryFrame()) {
+ SVGGeometryProperty::ResolveAll(this, &x, &y);
+ } else {
+ // This function might be called for element in display:none subtree
+ // (e.g. getScreenCTM), we fall back to use SVG attributes.
+ const_cast(this)->GetAnimatedLengthValues(
+ &x, &y, nullptr);
+ }
+
gfxMatrix toUserSpace = gfxMatrix::Translation(x, y);
if (aWhich == eChildToUserSpace) {
return toUserSpace * aMatrix;
@@ -89,10 +100,12 @@ gfxMatrix SVGForeignObjectElement::PrependLocalTransformsTo(
/* virtual */
bool SVGForeignObjectElement::HasValidDimensions() const {
- return mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() &&
- mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
- mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() &&
- mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0;
+ float width, height;
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(
+ const_cast(this), &width, &height);
+ return width > 0 && height > 0;
}
//----------------------------------------------------------------------
@@ -109,7 +122,8 @@ SVGForeignObjectElement::IsAttributeMapped(const nsAtom* name) const {
sTextContentElementsMap,
sViewportsMap};
- return FindAttributeDependence(name, map) ||
+ return IsInLengthInfo(name, sLengthInfo) ||
+ FindAttributeDependence(name, map) ||
SVGGraphicsElement::IsAttributeMapped(name);
}
@@ -121,5 +135,22 @@ SVGElement::LengthAttributesInfo SVGForeignObjectElement::GetLengthInfo() {
ArrayLength(sLengthInfo));
}
+nsCSSPropertyID SVGForeignObjectElement::GetCSSPropertyIdForAttrEnum(
+ uint8_t aAttrEnum) {
+ switch (aAttrEnum) {
+ case ATTR_X:
+ return eCSSProperty_x;
+ case ATTR_Y:
+ return eCSSProperty_y;
+ case ATTR_WIDTH:
+ return eCSSProperty_width;
+ case ATTR_HEIGHT:
+ return eCSSProperty_height;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unknown attr enum");
+ return eCSSProperty_UNKNOWN;
+ }
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/svg/SVGForeignObjectElement.h b/dom/svg/SVGForeignObjectElement.h
index 8077d783ef46..1e9d1428e6e8 100644
--- a/dom/svg/SVGForeignObjectElement.h
+++ b/dom/svg/SVGForeignObjectElement.h
@@ -8,6 +8,7 @@
#define mozilla_dom_SVGForeignObjectElement_h
#include "mozilla/dom/SVGGraphicsElement.h"
+#include "nsCSSPropertyID.h"
#include "SVGAnimatedLength.h"
nsresult NS_NewSVGForeignObjectElement(
@@ -42,6 +43,8 @@ class SVGForeignObjectElement final : public SVGGraphicsElement {
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
+ static nsCSSPropertyID GetCSSPropertyIdForAttrEnum(uint8_t aAttrEnum);
+
// WebIDL
already_AddRefed X();
already_AddRefed Y();
diff --git a/dom/svg/SVGGeometryElement.cpp b/dom/svg/SVGGeometryElement.cpp
index a86f18846dea..5b211bc95570 100644
--- a/dom/svg/SVGGeometryElement.cpp
+++ b/dom/svg/SVGGeometryElement.cpp
@@ -10,8 +10,11 @@
#include "gfxPlatform.h"
#include "nsCOMPtr.h"
#include "nsComputedDOMStyle.h"
-#include "SVGAnimatedLength.h"
#include "nsSVGUtils.h"
+#include "SVGAnimatedLength.h"
+#include "SVGCircleElement.h"
+#include "SVGEllipseElement.h"
+#include "SVGRectElement.h"
#include "mozilla/dom/SVGLengthBinding.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
@@ -111,6 +114,22 @@ already_AddRefed SVGGeometryElement::GetOrBuildPathForMeasuring() {
return GetOrBuildPath(drawTarget, fillRule);
}
+bool SVGGeometryElement::IsGeometryChangedViaCSS(
+ ComputedStyle const& aNewStyle, ComputedStyle const& aOldStyle) const {
+ if (IsSVGElement(nsGkAtoms::rect)) {
+ return SVGRectElement::IsLengthChangedViaCSS(aNewStyle, aOldStyle);
+ }
+
+ if (IsSVGElement(nsGkAtoms::circle)) {
+ return SVGCircleElement::IsLengthChangedViaCSS(aNewStyle, aOldStyle);
+ }
+
+ if (IsSVGElement(nsGkAtoms::ellipse)) {
+ return SVGEllipseElement::IsLengthChangedViaCSS(aNewStyle, aOldStyle);
+ }
+ return false;
+}
+
FillRule SVGGeometryElement::GetFillRule() {
FillRule fillRule =
FillRule::FILL_WINDING; // Equivalent to StyleFillRule::Nonzero
diff --git a/dom/svg/SVGGeometryElement.h b/dom/svg/SVGGeometryElement.h
index cc35e6264c5d..d7aa0a048e9b 100644
--- a/dom/svg/SVGGeometryElement.h
+++ b/dom/svg/SVGGeometryElement.h
@@ -191,6 +191,13 @@ class SVGGeometryElement : public SVGGeometryElementBase {
*/
virtual already_AddRefed GetOrBuildPathForMeasuring();
+ /**
+ * Return |true| if some geometry properties (|x|, |y|, etc) are changed
+ * because of CSS change.
+ */
+ bool IsGeometryChangedViaCSS(ComputedStyle const& aNewStyle,
+ ComputedStyle const& aOldStyle) const;
+
/**
* Returns the current computed value of the CSS property 'fill-rule' for
* this element.
diff --git a/dom/svg/SVGGeometryProperty.cpp b/dom/svg/SVGGeometryProperty.cpp
new file mode 100644
index 000000000000..62e1e87006b6
--- /dev/null
+++ b/dom/svg/SVGGeometryProperty.cpp
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SVGGeometryProperty.h"
+#include "SVGCircleElement.h"
+#include "SVGEllipseElement.h"
+#include "SVGForeignObjectElement.h"
+#include "SVGRectElement.h"
+
+namespace mozilla {
+namespace dom {
+namespace SVGGeometryProperty {
+
+nsCSSUnit SpecifiedUnitTypeToCSSUnit(uint8_t aSpecifiedUnit) {
+ switch (aSpecifiedUnit) {
+ case SVGLength_Binding::SVG_LENGTHTYPE_NUMBER:
+ case SVGLength_Binding::SVG_LENGTHTYPE_PX:
+ return nsCSSUnit::eCSSUnit_Pixel;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_MM:
+ return nsCSSUnit::eCSSUnit_Millimeter;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_CM:
+ return nsCSSUnit::eCSSUnit_Centimeter;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_IN:
+ return nsCSSUnit::eCSSUnit_Inch;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_PT:
+ return nsCSSUnit::eCSSUnit_Point;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_PC:
+ return nsCSSUnit::eCSSUnit_Pica;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE:
+ return nsCSSUnit::eCSSUnit_Percent;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_EMS:
+ return nsCSSUnit::eCSSUnit_EM;
+
+ case SVGLength_Binding::SVG_LENGTHTYPE_EXS:
+ return nsCSSUnit::eCSSUnit_XHeight;
+
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unknown unit type");
+ return nsCSSUnit::eCSSUnit_Pixel;
+ }
+}
+
+nsCSSPropertyID AttrEnumToCSSPropId(const SVGElement* aElement,
+ uint8_t aAttrEnum) {
+ // This is a very trivial function only applied to a few elements,
+ // so we want to avoid making it virtual.
+ if (aElement->IsSVGElement(nsGkAtoms::rect)) {
+ return SVGRectElement::GetCSSPropertyIdForAttrEnum(aAttrEnum);
+ }
+ if (aElement->IsSVGElement(nsGkAtoms::circle)) {
+ return SVGCircleElement::GetCSSPropertyIdForAttrEnum(aAttrEnum);
+ }
+ if (aElement->IsSVGElement(nsGkAtoms::ellipse)) {
+ return SVGEllipseElement::GetCSSPropertyIdForAttrEnum(aAttrEnum);
+ }
+ if (aElement->IsSVGElement(nsGkAtoms::foreignObject)) {
+ return SVGForeignObjectElement::GetCSSPropertyIdForAttrEnum(aAttrEnum);
+ }
+ return eCSSProperty_UNKNOWN;
+}
+
+bool IsNonNegativeGeometryProperty(nsCSSPropertyID aProp) {
+ return aProp == eCSSProperty_r || aProp == eCSSProperty_rx ||
+ aProp == eCSSProperty_ry || aProp == eCSSProperty_width ||
+ aProp == eCSSProperty_height;
+}
+
+bool ElementMapsLengthsToStyle(SVGElement const* aElement) {
+ return aElement->IsSVGElement(nsGkAtoms::rect) ||
+ aElement->IsSVGElement(nsGkAtoms::circle) ||
+ aElement->IsSVGElement(nsGkAtoms::ellipse) ||
+ aElement->IsSVGElement(nsGkAtoms::foreignObject);
+}
+
+} // namespace SVGGeometryProperty
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/svg/SVGGeometryProperty.h b/dom/svg/SVGGeometryProperty.h
new file mode 100644
index 000000000000..b28ec64335fe
--- /dev/null
+++ b/dom/svg/SVGGeometryProperty.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SVGGeometryProperty_SVGGeometryProperty_h
+#define mozilla_dom_SVGGeometryProperty_SVGGeometryProperty_h
+
+#include "mozilla/dom/SVGElement.h"
+#include "SVGAnimatedLength.h"
+#include "ComputedStyle.h"
+#include "nsIFrame.h"
+#include
+
+namespace mozilla {
+namespace dom {
+
+namespace SVGGeometryProperty {
+namespace ResolverTypes {
+struct LengthPercentNoAuto {};
+struct LengthPercentRXY {};
+struct LengthPercentWidthHeight {};
+} // namespace ResolverTypes
+
+namespace Tags {
+
+#define SVGGEOMETRYPROPERTY_GENERATETAG(tagName, resolver, direction, \
+ styleStruct) \
+ struct tagName { \
+ using ResolverType = ResolverTypes::resolver; \
+ constexpr static auto CtxDirection = SVGContentUtils::direction; \
+ constexpr static auto Getter = &styleStruct::m##tagName; \
+ }
+
+SVGGEOMETRYPROPERTY_GENERATETAG(X, LengthPercentNoAuto, X, nsStyleSVGReset);
+SVGGEOMETRYPROPERTY_GENERATETAG(Y, LengthPercentNoAuto, Y, nsStyleSVGReset);
+SVGGEOMETRYPROPERTY_GENERATETAG(Cx, LengthPercentNoAuto, X, nsStyleSVGReset);
+SVGGEOMETRYPROPERTY_GENERATETAG(Cy, LengthPercentNoAuto, Y, nsStyleSVGReset);
+SVGGEOMETRYPROPERTY_GENERATETAG(R, LengthPercentNoAuto, XY, nsStyleSVGReset);
+SVGGEOMETRYPROPERTY_GENERATETAG(Width, LengthPercentWidthHeight, X,
+ nsStylePosition);
+SVGGEOMETRYPROPERTY_GENERATETAG(Height, LengthPercentWidthHeight, Y,
+ nsStylePosition);
+
+#undef SVGGEOMETRYPROPERTY_GENERATETAG
+
+struct Ry;
+struct Rx {
+ using ResolverType = ResolverTypes::LengthPercentRXY;
+ constexpr static auto CtxDirection = SVGContentUtils::X;
+ constexpr static auto Getter = &nsStyleSVGReset::mRx;
+ using CounterPart = Ry;
+};
+struct Ry {
+ using ResolverType = ResolverTypes::LengthPercentRXY;
+ constexpr static auto CtxDirection = SVGContentUtils::Y;
+ constexpr static auto Getter = &nsStyleSVGReset::mRy;
+ using CounterPart = Rx;
+};
+
+} // namespace Tags
+
+namespace details {
+template
+using AlwaysFloat = float;
+
+using CtxDirectionType = decltype(SVGContentUtils::X);
+
+template
+float ResolvePureLengthPercentage(SVGElement* aElement,
+ const LengthPercentage& aLP) {
+ return aLP.ResolveToCSSPixelsWith(
+ [&] { return CSSCoord{SVGElementMetrics(aElement).GetAxisLength(CTD)}; });
+}
+
+template
+float ResolveImpl(ComputedStyle const& aStyle, SVGElement* aElement,
+ ResolverTypes::LengthPercentNoAuto) {
+ auto const& value = aStyle.StyleSVGReset()->*Tag::Getter;
+ return ResolvePureLengthPercentage(aElement, value);
+}
+
+template
+float ResolveImpl(ComputedStyle const& aStyle, SVGElement* aElement,
+ ResolverTypes::LengthPercentWidthHeight) {
+ static_assert(
+ std::is_same{} || std::is_same{},
+ "Wrong tag");
+
+ auto const& value = aStyle.StylePosition()->*Tag::Getter;
+ if (value.IsLengthPercentage()) {
+ return ResolvePureLengthPercentage(
+ aElement, value.AsLengthPercentage());
+ }
+
+ // |auto| and |max-content| etc. are treated as 0.
+ return 0.f;
+}
+
+template
+float ResolveImpl(ComputedStyle const& aStyle, SVGElement* aElement,
+ ResolverTypes::LengthPercentRXY) {
+ static_assert(std::is_same{} || std::is_same{},
+ "Wrong tag");
+
+ auto const& value = aStyle.StyleSVGReset()->*Tag::Getter;
+ if (value.IsLengthPercentage()) {
+ return ResolvePureLengthPercentage(
+ aElement, value.AsLengthPercentage());
+ }
+
+ MOZ_ASSERT(value.IsAuto());
+ using Rother = typename Tag::CounterPart;
+ auto const& valueOther = aStyle.StyleSVGReset()->*Rother::Getter;
+
+ if (valueOther.IsAuto()) {
+ // Per SVG2, |Rx|, |Ry| resolve to 0 if both are |auto|
+ return 0.f;
+ }
+
+ // If |Rx| is auto while |Ry| not, |Rx| gets the value of |Ry|.
+ return ResolvePureLengthPercentage(
+ aElement, valueOther.AsLengthPercentage());
+}
+
+} // namespace details
+
+template
+float ResolveWith(const ComputedStyle& aStyle, const SVGElement* aElement) {
+ // TODO: There are a lot of utilities lacking const-ness in dom/svg.
+ // We should fix that problem and remove this `const_cast`.
+ return details::ResolveImpl(aStyle, const_cast(aElement),
+ typename Tag::ResolverType{});
+}
+
+// To add support for new properties, or to handle special cases for
+// existing properties, you can add a new tag in |Tags| and |ResolverTypes|
+// namespace, then implement the behavior in |details::ResolveImpl|.
+template
+bool ResolveAll(const SVGElement* aElement,
+ details::AlwaysFloat*... aRes) {
+ if (nsIFrame const* f = aElement->GetPrimaryFrame()) {
+ using dummy = int[];
+ (void)dummy{0, (*aRes = ResolveWith(*f->Style(), aElement), 0)...};
+ return true;
+ }
+ return false;
+}
+
+nsCSSUnit SpecifiedUnitTypeToCSSUnit(uint8_t aSpecifiedUnit);
+nsCSSPropertyID AttrEnumToCSSPropId(const SVGElement* aElement,
+ uint8_t aAttrEnum);
+
+bool IsNonNegativeGeometryProperty(nsCSSPropertyID aProp);
+bool ElementMapsLengthsToStyle(SVGElement const* aElement);
+
+} // namespace SVGGeometryProperty
+} // namespace dom
+} // namespace mozilla
+
+#endif
diff --git a/dom/svg/SVGGraphicsElement.h b/dom/svg/SVGGraphicsElement.h
index 19399e8ef6a6..4ff220a702a3 100644
--- a/dom/svg/SVGGraphicsElement.h
+++ b/dom/svg/SVGGraphicsElement.h
@@ -32,6 +32,16 @@ class SVGGraphicsElement : public SVGGraphicsElementBase, public SVGTests {
// returns true if focusability has been definitively determined otherwise
// false
bool IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex);
+
+ template
+ bool IsInLengthInfo(const nsAtom* aAttribute, const T& aLengthInfos) const {
+ for (auto const& e : aLengthInfos) {
+ if (e.mName == aAttribute) {
+ return true;
+ }
+ }
+ return false;
+ }
};
} // namespace dom
diff --git a/dom/svg/SVGImageElement.cpp b/dom/svg/SVGImageElement.cpp
index 0bbab6cb3049..9c939c337e1f 100644
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -218,7 +218,8 @@ SVGImageElement::IsAttributeMapped(const nsAtom* name) const {
sViewportsMap,
};
- return FindAttributeDependence(name, map) ||
+ return IsInLengthInfo(name, sLengthInfo) ||
+ FindAttributeDependence(name, map) ||
SVGImageElementBase::IsAttributeMapped(name);
}
diff --git a/dom/svg/SVGRectElement.cpp b/dom/svg/SVGRectElement.cpp
index 3f1da44b66df..37309e8d7aaa 100644
--- a/dom/svg/SVGRectElement.cpp
+++ b/dom/svg/SVGRectElement.cpp
@@ -5,13 +5,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/SVGRectElement.h"
-#include "nsGkAtoms.h"
#include "mozilla/dom/SVGLengthBinding.h"
#include "mozilla/dom/SVGRectElementBinding.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/gfx/PathHelpers.h"
+#include "nsGkAtoms.h"
+#include "SVGGeometryProperty.h"
#include
NS_IMPL_NS_NEW_SVG_ELEMENT(Rect)
@@ -49,6 +50,13 @@ SVGRectElement::SVGRectElement(
already_AddRefed&& aNodeInfo)
: SVGRectElementBase(std::move(aNodeInfo)) {}
+bool SVGRectElement::IsAttributeMapped(const nsAtom* aAttribute) const {
+ return IsInLengthInfo(aAttribute, sLengthInfo) ||
+ SVGRectElementBase::IsAttributeMapped(aAttribute);
+}
+
+namespace SVGT = SVGGeometryProperty::Tags;
+
//----------------------------------------------------------------------
// nsINode methods
@@ -85,10 +93,13 @@ already_AddRefed SVGRectElement::Ry() {
/* virtual */
bool SVGRectElement::HasValidDimensions() const {
- return mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() &&
- mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
- mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() &&
- mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0;
+ float width, height;
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(this, &width,
+ &height);
+
+ return width > 0 && height > 0;
}
SVGElement::LengthAttributesInfo SVGRectElement::GetLengthInfo() {
@@ -105,8 +116,11 @@ bool SVGRectElement::GetGeometryBounds(Rect* aBounds,
const Matrix* aToNonScalingStrokeSpace) {
Rect rect;
Float rx, ry;
- GetAnimatedLengthValues(&rect.x, &rect.y, &rect.width, &rect.height, &rx, &ry,
- nullptr);
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(
+ this, &rect.x, &rect.y, &rect.width, &rect.height, &rx, &ry);
if (rect.IsEmpty()) {
// Rendering of the element disabled
@@ -155,7 +169,11 @@ bool SVGRectElement::GetGeometryBounds(Rect* aBounds,
void SVGRectElement::GetAsSimplePath(SimplePath* aSimplePath) {
float x, y, width, height, rx, ry;
- GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(this, &x, &y, &width,
+ &height, &rx, &ry);
if (width <= 0 || height <= 0) {
aSimplePath->Reset();
@@ -175,7 +193,11 @@ void SVGRectElement::GetAsSimplePath(SimplePath* aSimplePath) {
already_AddRefed SVGRectElement::BuildPath(PathBuilder* aBuilder) {
float x, y, width, height, rx, ry;
- GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
+
+ MOZ_ASSERT(GetPrimaryFrame());
+ SVGGeometryProperty::ResolveAll(this, &x, &y, &width,
+ &height, &rx, &ry);
if (width <= 0 || height <= 0) {
return nullptr;
@@ -193,18 +215,6 @@ already_AddRefed SVGRectElement::BuildPath(PathBuilder* aBuilder) {
aBuilder->LineTo(r.BottomLeft());
aBuilder->Close();
} else {
- // If either the 'rx' or the 'ry' attribute isn't set, then we have to
- // set it to the value of the other:
- bool hasRx = mLengthAttributes[ATTR_RX].IsExplicitlySet();
- bool hasRy = mLengthAttributes[ATTR_RY].IsExplicitlySet();
- MOZ_ASSERT(hasRx || hasRy);
-
- if (hasRx && !hasRy) {
- ry = rx;
- } else if (hasRy && !hasRx) {
- rx = ry;
- }
-
// Clamp rx and ry to half the rect's width and height respectively:
rx = std::min(rx, width / 2);
ry = std::min(ry, height / 2);
@@ -216,5 +226,40 @@ already_AddRefed SVGRectElement::BuildPath(PathBuilder* aBuilder) {
return aBuilder->Finish();
}
+bool SVGRectElement::IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
+ const ComputedStyle& aOldStyle) {
+ auto *newSVGReset = aNewStyle.StyleSVGReset(),
+ *oldSVGReset = aOldStyle.StyleSVGReset();
+ auto *newPosition = aNewStyle.StylePosition(),
+ *oldPosition = aOldStyle.StylePosition();
+
+ return newSVGReset->mX != oldSVGReset->mX ||
+ newSVGReset->mY != oldSVGReset->mY ||
+ newPosition->mWidth != oldPosition->mWidth ||
+ newPosition->mHeight != oldPosition->mHeight ||
+ newSVGReset->mRx != oldSVGReset->mRx ||
+ newSVGReset->mRy != oldSVGReset->mRy;
+}
+
+nsCSSPropertyID SVGRectElement::GetCSSPropertyIdForAttrEnum(uint8_t aAttrEnum) {
+ switch (aAttrEnum) {
+ case ATTR_X:
+ return eCSSProperty_x;
+ case ATTR_Y:
+ return eCSSProperty_y;
+ case ATTR_WIDTH:
+ return eCSSProperty_width;
+ case ATTR_HEIGHT:
+ return eCSSProperty_height;
+ case ATTR_RX:
+ return eCSSProperty_rx;
+ case ATTR_RY:
+ return eCSSProperty_ry;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unknown attr enum");
+ return eCSSProperty_UNKNOWN;
+ }
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/svg/SVGRectElement.h b/dom/svg/SVGRectElement.h
index 0a395f69c8fd..ba5843a052d2 100644
--- a/dom/svg/SVGRectElement.h
+++ b/dom/svg/SVGRectElement.h
@@ -7,6 +7,7 @@
#ifndef mozilla_dom_SVGRectElement_h
#define mozilla_dom_SVGRectElement_h
+#include "nsCSSPropertyID.h"
#include "SVGAnimatedLength.h"
#include "SVGGeometryElement.h"
@@ -14,6 +15,8 @@ nsresult NS_NewSVGRectElement(
nsIContent** aResult, already_AddRefed&& aNodeInfo);
namespace mozilla {
+class ComputedStyle;
+
namespace dom {
typedef SVGGeometryElement SVGRectElementBase;
@@ -28,6 +31,8 @@ class SVGRectElement final : public SVGRectElementBase {
already_AddRefed&& aNodeInfo));
public:
+ NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
+
// nsSVGSVGElement methods:
virtual bool HasValidDimensions() const override;
@@ -42,6 +47,10 @@ class SVGRectElement final : public SVGRectElementBase {
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
+ static bool IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
+ const ComputedStyle& aOldStyle);
+ static nsCSSPropertyID GetCSSPropertyIdForAttrEnum(uint8_t aAttrEnum);
+
// WebIDL
already_AddRefed X();
already_AddRefed Y();
diff --git a/dom/svg/SVGViewportElement.h b/dom/svg/SVGViewportElement.h
index 60f34ee11fe5..2419ad577e13 100644
--- a/dom/svg/SVGViewportElement.h
+++ b/dom/svg/SVGViewportElement.h
@@ -124,6 +124,17 @@ class SVGViewportElement : public SVGGraphicsElement {
mViewportHeight = aSize.height;
}
+ /**
+ * Returns true if either this is an SVG element that is the child of
+ * another non-foreignObject SVG element, or this is a SVG element
+ * this is the root of a use-element shadow tree.
+ */
+ bool IsInner() const {
+ const nsIContent* parent = GetFlattenedTreeParent();
+ return parent && parent->IsSVGElement() &&
+ !parent->IsSVGElement(nsGkAtoms::foreignObject);
+ }
+
// WebIDL
already_AddRefed ViewBox();
already_AddRefed PreserveAspectRatio();
@@ -139,17 +150,6 @@ class SVGViewportElement : public SVGGraphicsElement {
return IsInUncomposedDoc() && !GetParent();
}
- /**
- * Returns true if either this is an SVG element that is the child of
- * another non-foreignObject SVG element, or this is a SVG element
- * this is the root of a use-element shadow tree.
- */
- bool IsInner() const {
- const nsIContent* parent = GetFlattenedTreeParent();
- return parent && parent->IsSVGElement() &&
- !parent->IsSVGElement(nsGkAtoms::foreignObject);
- }
-
/**
* Returns the explicit or default preserveAspectRatio, unless we're
* synthesizing a viewBox, in which case it returns the "none" value.
diff --git a/dom/svg/moz.build b/dom/svg/moz.build
index f4a9b1086335..e55c39a28419 100644
--- a/dom/svg/moz.build
+++ b/dom/svg/moz.build
@@ -181,6 +181,7 @@ UNIFIED_SOURCES += [
'SVGFragmentIdentifier.cpp',
'SVGGElement.cpp',
'SVGGeometryElement.cpp',
+ 'SVGGeometryProperty.cpp',
'SVGGradientElement.cpp',
'SVGGraphicsElement.cpp',
'SVGImageElement.cpp',
diff --git a/dom/u2f/tests/browser/browser_abort_visibility.js b/dom/u2f/tests/browser/browser_abort_visibility.js
index 469d687b59e7..449da4d95561 100644
--- a/dom/u2f/tests/browser/browser_abort_visibility.js
+++ b/dom/u2f/tests/browser/browser_abort_visibility.js
@@ -70,6 +70,7 @@ add_task(async function test_abort() {
Services.prefs.setBoolPref("security.webauth.u2f", true);
Services.prefs.setBoolPref("security.webauth.webauthn_enable_softtoken", false);
Services.prefs.setBoolPref("security.webauth.webauthn_enable_usbtoken", true);
+ Services.prefs.setBoolPref("security.webauth.webauthn_enable_android_fido2", false);
// Create a new tab for the MakeCredential() request.
let tab_create = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
diff --git a/dom/u2f/tests/browser/browser_appid_localhost.js b/dom/u2f/tests/browser/browser_appid_localhost.js
index cc7a35a0e745..cf2f08fdd6f2 100644
--- a/dom/u2f/tests/browser/browser_appid_localhost.js
+++ b/dom/u2f/tests/browser/browser_appid_localhost.js
@@ -25,6 +25,7 @@ add_task(async function () {
Services.prefs.setBoolPref("security.webauth.u2f", true);
Services.prefs.setBoolPref("security.webauth.webauthn_enable_softtoken", true);
Services.prefs.setBoolPref("security.webauth.webauthn_enable_usbtoken", false);
+ Services.prefs.setBoolPref("security.webauth.webauthn_enable_android_fido2", false);
// Open a new tab.
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
diff --git a/dom/u2f/tests/test_appid_facet.html b/dom/u2f/tests/test_appid_facet.html
index 0940244d4dfd..94f09a12e561 100644
--- a/dom/u2f/tests/test_appid_facet.html
+++ b/dom/u2f/tests/test_appid_facet.html
@@ -33,6 +33,7 @@ SimpleTest.waitForExplicitFinish();
window.addEventListener("message", handleEventMessage);
SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function(){
document.getElementById('testing_frame').src = "https://example.com/tests/dom/u2f/tests/frame_appid_facet.html";
diff --git a/dom/u2f/tests/test_appid_facet_insecure.html b/dom/u2f/tests/test_appid_facet_insecure.html
index 1c0fddd2ba93..6c35e7501548 100644
--- a/dom/u2f/tests/test_appid_facet_insecure.html
+++ b/dom/u2f/tests/test_appid_facet_insecure.html
@@ -33,6 +33,7 @@ SimpleTest.waitForExplicitFinish();
window.addEventListener("message", handleEventMessage);
SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function(){
document.getElementById('testing_frame').src = "http://test2.example.com/tests/dom/u2f/tests/frame_appid_facet_insecure.html";
diff --git a/dom/u2f/tests/test_appid_facet_subdomain.html b/dom/u2f/tests/test_appid_facet_subdomain.html
index d94007b688e1..6c9f019d4721 100644
--- a/dom/u2f/tests/test_appid_facet_subdomain.html
+++ b/dom/u2f/tests/test_appid_facet_subdomain.html
@@ -33,6 +33,7 @@ SimpleTest.waitForExplicitFinish();
window.addEventListener("message", handleEventMessage);
SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function(){
document.getElementById('testing_frame').src = "https://test1.example.com/tests/dom/u2f/tests/frame_appid_facet_subdomain.html";
diff --git a/dom/u2f/tests/test_multiple_keys.html b/dom/u2f/tests/test_multiple_keys.html
index 97f048cb3e5d..a8ff58a7296d 100644
--- a/dom/u2f/tests/test_multiple_keys.html
+++ b/dom/u2f/tests/test_multiple_keys.html
@@ -33,6 +33,7 @@ SimpleTest.waitForExplicitFinish();
window.addEventListener("message", handleEventMessage);
SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function(){
document.getElementById('testing_frame').src = "https://test2.example.com/tests/dom/u2f/tests/frame_multiple_keys.html";
diff --git a/dom/u2f/tests/test_no_token.html b/dom/u2f/tests/test_no_token.html
index ff7bd20694f8..6b50cbf276ef 100644
--- a/dom/u2f/tests/test_no_token.html
+++ b/dom/u2f/tests/test_no_token.html
@@ -31,6 +31,7 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function() {
// listen for messages from the test harness
diff --git a/dom/u2f/tests/test_override_request.html b/dom/u2f/tests/test_override_request.html
index efd71bf53ebb..76ee3b0e43f2 100644
--- a/dom/u2f/tests/test_override_request.html
+++ b/dom/u2f/tests/test_override_request.html
@@ -23,6 +23,7 @@
SpecialPowers.pushPrefEnv({"set": [
["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", true],
]}, () => {
addEventListener("message", handleEventMessage);
diff --git a/dom/u2f/tests/test_register.html b/dom/u2f/tests/test_register.html
index da2b39f4c298..14ffcbaf9d3a 100644
--- a/dom/u2f/tests/test_register.html
+++ b/dom/u2f/tests/test_register.html
@@ -31,6 +31,7 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function() {
// listen for messages from the test harness
diff --git a/dom/u2f/tests/test_register_sign.html b/dom/u2f/tests/test_register_sign.html
index ccb8dfb057d9..115007ec228d 100644
--- a/dom/u2f/tests/test_register_sign.html
+++ b/dom/u2f/tests/test_register_sign.html
@@ -27,6 +27,7 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.u2f", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function() {
// listen for messages from the test harness
diff --git a/dom/webauthn/tests/browser/browser_abort_visibility.js b/dom/webauthn/tests/browser/browser_abort_visibility.js
index cf88f44fc6e7..7d4499cd726a 100644
--- a/dom/webauthn/tests/browser/browser_abort_visibility.js
+++ b/dom/webauthn/tests/browser/browser_abort_visibility.js
@@ -86,6 +86,7 @@ add_task(async function test_setup() {
"set": [
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", true]
]
});
diff --git a/dom/webauthn/tests/browser/browser_fido_appid_extension.js b/dom/webauthn/tests/browser/browser_fido_appid_extension.js
index 1f783f4b3b8b..ea0b76c7556d 100644
--- a/dom/webauthn/tests/browser/browser_fido_appid_extension.js
+++ b/dom/webauthn/tests/browser/browser_fido_appid_extension.js
@@ -93,6 +93,7 @@ function promiseWebAuthnSign(tab, key_handle, extensions = {}) {
add_task(function test_setup() {
Services.prefs.setBoolPref("security.webauth.u2f", true);
Services.prefs.setBoolPref("security.webauth.webauthn", true);
+ Services.prefs.setBoolPref("security.webauth.webauthn_enable_android_fido2", false);
Services.prefs.setBoolPref("security.webauth.webauthn_enable_softtoken", true);
Services.prefs.setBoolPref("security.webauth.webauthn_enable_usbtoken", false);
});
diff --git a/dom/webauthn/tests/browser/browser_webauthn_prompts.js b/dom/webauthn/tests/browser/browser_webauthn_prompts.js
index 3856bf8a53ac..b1a3a6ea6798 100644
--- a/dom/webauthn/tests/browser/browser_webauthn_prompts.js
+++ b/dom/webauthn/tests/browser/browser_webauthn_prompts.js
@@ -99,6 +99,7 @@ add_task(async function test_setup_usbtoken() {
["security.webauth.u2f", false],
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", true]
]
});
diff --git a/dom/webauthn/tests/browser/browser_webauthn_telemetry.js b/dom/webauthn/tests/browser/browser_webauthn_telemetry.js
index 2ae6dfccb13c..fe1ec41d36ea 100644
--- a/dom/webauthn/tests/browser/browser_webauthn_telemetry.js
+++ b/dom/webauthn/tests/browser/browser_webauthn_telemetry.js
@@ -98,6 +98,7 @@ add_task(async function test_setup() {
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_testing_allow_direct_attestation", true]
]
});
diff --git a/dom/webauthn/tests/test_webauthn_abort_signal.html b/dom/webauthn/tests/test_webauthn_abort_signal.html
index 078a9ca7b6b5..5dc42a13f0ad 100644
--- a/dom/webauthn/tests/test_webauthn_abort_signal.html
+++ b/dom/webauthn/tests/test_webauthn_abort_signal.html
@@ -28,6 +28,7 @@
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", false],
["security.webauth.webauthn_enable_usbtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
]});
});
diff --git a/dom/webauthn/tests/test_webauthn_attestation_conveyance.html b/dom/webauthn/tests/test_webauthn_attestation_conveyance.html
index 058d57c7cd63..bf934a0dfc93 100644
--- a/dom/webauthn/tests/test_webauthn_attestation_conveyance.html
+++ b/dom/webauthn/tests/test_webauthn_attestation_conveyance.html
@@ -62,6 +62,7 @@
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_testing_allow_direct_attestation", true],
]});
});
diff --git a/dom/webauthn/tests/test_webauthn_authenticator_selection.html b/dom/webauthn/tests/test_webauthn_authenticator_selection.html
index b839541249ba..10ba6b643b64 100644
--- a/dom/webauthn/tests/test_webauthn_authenticator_selection.html
+++ b/dom/webauthn/tests/test_webauthn_authenticator_selection.html
@@ -37,6 +37,7 @@
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
]});
});
diff --git a/dom/webauthn/tests/test_webauthn_authenticator_transports.html b/dom/webauthn/tests/test_webauthn_authenticator_transports.html
index a063415dc537..44f99673b34b 100644
--- a/dom/webauthn/tests/test_webauthn_authenticator_transports.html
+++ b/dom/webauthn/tests/test_webauthn_authenticator_transports.html
@@ -40,6 +40,7 @@
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
]});
});
diff --git a/dom/webauthn/tests/test_webauthn_get_assertion.html b/dom/webauthn/tests/test_webauthn_get_assertion.html
index 82974a987b59..c49155fb6fe9 100644
--- a/dom/webauthn/tests/test_webauthn_get_assertion.html
+++ b/dom/webauthn/tests/test_webauthn_get_assertion.html
@@ -62,7 +62,8 @@
return SpecialPowers.pushPrefEnv({"set": [
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
- ["security.webauth.webauthn_enable_usbtoken", false]
+ ["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
]});
});
diff --git a/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html b/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html
index 7fd406d2ab76..b22d44387560 100644
--- a/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html
+++ b/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html
@@ -23,7 +23,9 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
- ["security.webauth.webauthn_enable_usbtoken", false]]},
+ ["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
+ ]},
function() {
PublicKeyCredential.isExternalCTAP2SecurityKeySupported()
.then(aResult => ok(true, `Should always return either true or false: ${aResult}`))
diff --git a/dom/webauthn/tests/test_webauthn_isplatformauthenticatoravailable.html b/dom/webauthn/tests/test_webauthn_isplatformauthenticatoravailable.html
index b76aba4e0655..3fd9d70e1a67 100644
--- a/dom/webauthn/tests/test_webauthn_isplatformauthenticatoravailable.html
+++ b/dom/webauthn/tests/test_webauthn_isplatformauthenticatoravailable.html
@@ -23,7 +23,9 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
- ["security.webauth.webauthn_enable_usbtoken", false]]},
+ ["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
+ ]},
async function() {
// This test ensures that isUserVerifyingPlatformAuthenticatorAvailable()
// is a callable method, but with the softtoken enabled, it's not useful to
diff --git a/dom/webauthn/tests/test_webauthn_loopback.html b/dom/webauthn/tests/test_webauthn_loopback.html
index 7cbfb2fa7a35..764dc54ef297 100644
--- a/dom/webauthn/tests/test_webauthn_loopback.html
+++ b/dom/webauthn/tests/test_webauthn_loopback.html
@@ -25,6 +25,7 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_testing_allow_direct_attestation", true]]},
function() {
is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
diff --git a/dom/webauthn/tests/test_webauthn_make_credential.html b/dom/webauthn/tests/test_webauthn_make_credential.html
index ecb5b08a11f2..3ddd688590a5 100644
--- a/dom/webauthn/tests/test_webauthn_make_credential.html
+++ b/dom/webauthn/tests/test_webauthn_make_credential.html
@@ -48,6 +48,7 @@
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]}, runTests);
function runTests() {
is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
diff --git a/dom/webauthn/tests/test_webauthn_no_token.html b/dom/webauthn/tests/test_webauthn_no_token.html
index e0af8a80849c..75bd57d645b6 100644
--- a/dom/webauthn/tests/test_webauthn_no_token.html
+++ b/dom/webauthn/tests/test_webauthn_no_token.html
@@ -24,6 +24,7 @@ SimpleTest.waitForExplicitFinish();
// Turn off all tokens. This should result in "not allowed" failures
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function() {
is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
diff --git a/dom/webauthn/tests/test_webauthn_override_request.html b/dom/webauthn/tests/test_webauthn_override_request.html
index b4021c9dd577..4c65af4226d3 100644
--- a/dom/webauthn/tests/test_webauthn_override_request.html
+++ b/dom/webauthn/tests/test_webauthn_override_request.html
@@ -22,6 +22,7 @@
return SpecialPowers.pushPrefEnv({"set": [
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", false],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", true],
]});
});
diff --git a/dom/webauthn/tests/test_webauthn_sameorigin.html b/dom/webauthn/tests/test_webauthn_sameorigin.html
index bebf26fac668..00c6e3edb4ae 100644
--- a/dom/webauthn/tests/test_webauthn_sameorigin.html
+++ b/dom/webauthn/tests/test_webauthn_sameorigin.html
@@ -299,6 +299,7 @@
};
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
runTests);
diff --git a/dom/webauthn/tests/test_webauthn_store_credential.html b/dom/webauthn/tests/test_webauthn_store_credential.html
index 94d9cf7330ca..c23f1929da4c 100644
--- a/dom/webauthn/tests/test_webauthn_store_credential.html
+++ b/dom/webauthn/tests/test_webauthn_store_credential.html
@@ -26,6 +26,7 @@
add_task(async function(){
await SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_android_fido2", false],
["security.webauth.webauthn_enable_usbtoken", false]]});
isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
diff --git a/gfx/skia/skia/src/ports/SkScalerContext_win_dw.cpp b/gfx/skia/skia/src/ports/SkScalerContext_win_dw.cpp
index 96293436d7b1..8515a9cb63cf 100644
--- a/gfx/skia/skia/src/ports/SkScalerContext_win_dw.cpp
+++ b/gfx/skia/skia/src/ports/SkScalerContext_win_dw.cpp
@@ -42,17 +42,46 @@
/* Note:
* In versions 8 and 8.1 of Windows, some calls in DWrite are not thread safe.
* The DWriteFactoryMutex protects the calls that are problematic.
+ *
+ * On DWrite 3 or above, which is only available on Windows 10, we don't enable
+ * the locking to avoid thread contention.
*/
static SkSharedMutex DWriteFactoryMutex;
-typedef SkAutoSharedMutexShared Shared;
+struct MaybeExclusive {
+ MaybeExclusive(SkScalerContext_DW* ctx) : fEnabled(!ctx->isDWrite3()) {
+ if (fEnabled) {
+ DWriteFactoryMutex.acquire();
+ }
+ }
+ ~MaybeExclusive() {
+ if (fEnabled) {
+ DWriteFactoryMutex.release();
+ }
+ }
+ bool fEnabled;
+};
+
+struct MaybeShared {
+ MaybeShared(SkScalerContext_DW* ctx) : fEnabled(!ctx->isDWrite3()) {
+ if (fEnabled) {
+ DWriteFactoryMutex.acquireShared();
+ }
+ }
+ ~MaybeShared() {
+ if (fEnabled) {
+ DWriteFactoryMutex.releaseShared();
+ }
+ }
+ bool fEnabled;
+};
static bool isLCD(const SkScalerContextRec& rec) {
return SkMask::kLCD16_Format == rec.fMaskFormat;
}
-static bool is_hinted(DWriteFontTypeface* typeface) {
- SkAutoExclusive l(DWriteFactoryMutex);
+static bool is_hinted(SkScalerContext_DW* ctx, DWriteFontTypeface* typeface) {
+ MaybeExclusive l(ctx);
AutoTDWriteTable maxp(typeface->fDWriteFontFace.get());
if (!maxp.fExists) {
return false;
@@ -122,8 +151,8 @@ static bool is_gridfit_only(GaspRange::Behavior flags) {
return flags.raw.value == GaspRange::Behavior::Raw::GridfitMask;
}
-static bool has_bitmap_strike(DWriteFontTypeface* typeface, GaspRange range) {
- SkAutoExclusive l(DWriteFactoryMutex);
+static bool has_bitmap_strike(SkScalerContext_DW* ctx, DWriteFontTypeface* typeface, GaspRange range) {
+ MaybeExclusive l(ctx);
{
AutoTDWriteTable eblc(typeface->fDWriteFontFace.get());
if (!eblc.fExists) {
@@ -268,7 +297,7 @@ SkScalerContext_DW::SkScalerContext_DW(sk_sp typefaceRef,
range = GaspRange(bitmapPPEM, bitmapPPEM, 0, GaspRange::Behavior());
}
}
- treatLikeBitmap = has_bitmap_strike(typeface, range);
+ treatLikeBitmap = has_bitmap_strike(this, typeface, range);
axisAlignedBitmap = is_axis_aligned(fRec);
}
@@ -304,7 +333,7 @@ SkScalerContext_DW::SkScalerContext_DW(sk_sp typefaceRef,
// If the font has a gasp table version 1, use it to determine symmetric rendering.
} else if ((get_gasp_range(typeface, SkScalarRoundToInt(gdiTextSize), &range) &&
range.fVersion >= 1) ||
- realTextSize > SkIntToScalar(20) || !is_hinted(typeface)) {
+ realTextSize > SkIntToScalar(20) || !is_hinted(this, typeface)) {
fTextSizeRender = realTextSize;
fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
fTextSizeMeasure = realTextSize;
@@ -397,7 +426,7 @@ bool SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
{
- SkAutoExclusive l(DWriteFactoryMutex);
+ MaybeExclusive l(this);
HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
fTextSizeMeasure,
1.0f, // pixelsPerDip
@@ -409,14 +438,14 @@ bool SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
&gm),
"Could not get gdi compatible glyph metrics.");
} else {
- SkAutoExclusive l(DWriteFactoryMutex);
+ MaybeExclusive l(this);
HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
"Could not get design metrics.");
}
DWRITE_FONT_METRICS dwfm;
{
- Shared l(DWriteFactoryMutex);
+ MaybeShared l(this);
this->getDWriteTypeface()->fDWriteFontFace->GetMetrics(&dwfm);
}
SkScalar advanceX = fTextSizeMeasure * gm.advanceWidth / dwfm.designUnitsPerEm;
@@ -465,7 +494,7 @@ HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
SkTScopedComPtr glyphRunAnalysis;
{
- SkAutoExclusive l(DWriteFactoryMutex);
+ MaybeExclusive l(this);
// IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
if (this->getDWriteTypeface()->fFactory2 &&
(fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
@@ -495,7 +524,7 @@ HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
}
}
{
- Shared l(DWriteFactoryMutex);
+ MaybeShared l(this);
HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
"Could not get texture bounds.");
}
@@ -588,7 +617,7 @@ void SkScalerContext_DW::generateColorMetrics(SkGlyph* glyph) {
HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
"Could not create geometry to path converter.");
{
- SkAutoExclusive l(DWriteFactoryMutex);
+ MaybeExclusive l(this);
HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
colorGlyph->glyphRun.fontEmSize,
colorGlyph->glyphRun.glyphIndices,
@@ -947,7 +976,7 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
{
SkTScopedComPtr glyphRunAnalysis;
{
- SkAutoExclusive l(DWriteFactoryMutex);
+ MaybeExclusive l(this);
// IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
if (this->getDWriteTypeface()->fFactory2 &&
(fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
@@ -983,7 +1012,7 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
bbox.right = glyph.fLeft + glyph.fWidth;
bbox.bottom = glyph.fTop + glyph.fHeight;
{
- Shared l(DWriteFactoryMutex);
+ MaybeShared l(this);
HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
&bbox,
fBits.begin(),
@@ -1047,7 +1076,7 @@ void SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) {
HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
"Could not create geometry to path converter.");
{
- SkAutoExclusive l(DWriteFactoryMutex);
+ MaybeExclusive l(this);
HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
colorGlyph->glyphRun.fontEmSize,
colorGlyph->glyphRun.glyphIndices,
@@ -1186,7 +1215,7 @@ bool SkScalerContext_DW::generatePath(SkGlyphID glyph, SkPath* path) {
"Could not create geometry to path converter.");
UINT16 glyphId = SkTo(glyph);
{
- SkAutoExclusive l(DWriteFactoryMutex);
+ MaybeExclusive l(this);
//TODO: convert to<->from DIUs? This would make a difference if hinting.
//It may not be needed, it appears that DirectWrite only hints at em size.
HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetGlyphRunOutline(
diff --git a/gfx/skia/skia/src/ports/SkScalerContext_win_dw.h b/gfx/skia/skia/src/ports/SkScalerContext_win_dw.h
index a462d98de009..30d4bf3232d6 100644
--- a/gfx/skia/skia/src/ports/SkScalerContext_win_dw.h
+++ b/gfx/skia/skia/src/ports/SkScalerContext_win_dw.h
@@ -26,6 +26,10 @@ public:
const SkDescriptor*);
~SkScalerContext_DW() override;
+ // The IDWriteFontFace4 interface is only available in DWrite 3,
+ // so checking if it was found is sufficient to detect DWrite 3.
+ bool isDWrite3() { return bool(getDWriteTypeface()->fDWriteFontFace4); }
+
protected:
unsigned generateGlyphCount() override;
uint16_t generateCharToGlyph(SkUnichar uni) override;
diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h
index 7196aedd646b..a536e4ba2887 100644
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -724,7 +724,7 @@ class gfxPrefs final {
DECL_GFX_PREF(Once, "layout.paint_rects_separately", LayoutPaintRectsSeparately, bool, true);
// This and code dependent on it should be removed once containerless scrolling looks stable.
- DECL_OVERRIDE_PREF(Live, "layout.scroll.root-frame-containers", LayoutUseContainersForRootFrames, !OverrideBase_WebRender());
+ DECL_GFX_PREF(Live, "layout.scroll.root-frame-containers", LayoutUseContainersForRootFrames, bool, false);
// This pref is to be set by test code only.
DECL_GFX_PREF(Live, "layout.scrollbars.always-layerize-track", AlwaysLayerizeScrollbarTrackTestOnly, bool, false);
DECL_GFX_PREF(Live, "layout.smaller-painted-layers", LayoutSmallerPaintedLayers, bool, false);
diff --git a/gfx/webrender_bindings/RenderCompositorANGLE.h b/gfx/webrender_bindings/RenderCompositorANGLE.h
index f66acbd3c67b..86fb77b98ce0 100644
--- a/gfx/webrender_bindings/RenderCompositorANGLE.h
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.h
@@ -50,7 +50,7 @@ class RenderCompositorANGLE : public RenderCompositor {
bool UseDComp() const override { return !!mCompositionDevice; }
- bool UseTripleBuffering() const { return mUseTripleBuffering; }
+ bool UseTripleBuffering() const override { return mUseTripleBuffering; }
LayoutDeviceIntSize GetBufferSize() override;
diff --git a/layout/reftests/svg/geometry-properties-in-css-ref.html b/layout/reftests/svg/geometry-properties-in-css-ref.html
new file mode 100644
index 000000000000..7998b7b86f41
--- /dev/null
+++ b/layout/reftests/svg/geometry-properties-in-css-ref.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/svg/geometry-properties-in-css.html b/layout/reftests/svg/geometry-properties-in-css.html
new file mode 100644
index 000000000000..4204fc41ae9b
--- /dev/null
+++ b/layout/reftests/svg/geometry-properties-in-css.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list
index d76646bfe9aa..40b10acd8608 100644
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -244,6 +244,7 @@ fuzzy-if(Android,0-18,0-600) == foreignObject-fixedpos-01.html foreignObject-dyn
== g-transform-01.svg pass.svg
== getElementById-a-element-01.svg pass.svg
+== geometry-properties-in-css.html geometry-properties-in-css-ref.html
fuzzy-if(Android,0-9,0-980) fuzzy-if(skiaContent,0-3,0-32000) == gradient-live-01a.svg gradient-live-01-ref.svg
fuzzy-if(Android,0-9,0-980) fuzzy-if(skiaContent,0-3,0-32000) == gradient-live-01b.svg gradient-live-01-ref.svg
diff --git a/layout/style/nsDOMCSSAttrDeclaration.cpp b/layout/style/nsDOMCSSAttrDeclaration.cpp
index 8da15e47db47..3ed24764e1c3 100644
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -10,10 +10,12 @@
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Element.h"
+#include "mozilla/dom/SVGElement.h"
#include "mozilla/dom/MutationEventBinding.h"
#include "mozilla/DeclarationBlock.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/SMILCSSValueType.h"
+#include "mozilla/SMILValue.h"
#include "mozAutoDocUpdate.h"
#include "nsIURI.h"
#include "nsNodeUtils.h"
@@ -133,9 +135,10 @@ nsDOMCSSAttributeDeclaration::GetParsingEnvironment(
};
}
-nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
- const nsCSSPropertyID aPropID, const SMILValue& aValue) {
+template
+nsresult nsDOMCSSAttributeDeclaration::SetSMILValueHelper(SetterFunc aFunc) {
MOZ_ASSERT(mIsSMILOverride);
+
// No need to do the ActiveLayerTracker / ScrollLinkedEffectDetector bits,
// since we're in a SMIL animation anyway, no need to try to detect we're a
// scripted animation.
@@ -147,7 +150,9 @@ nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
}
mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
RefPtr decl = olddecl->EnsureMutable();
- bool changed = SMILCSSValueType::SetPropertyValues(aValue, *decl);
+
+ bool changed = aFunc(*decl);
+
if (changed) {
// We can pass nullptr as the latter param, since this is
// mIsSMILOverride == true case.
@@ -156,6 +161,23 @@ nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
return NS_OK;
}
+nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
+ const nsCSSPropertyID /*aPropID*/, const SMILValue& aValue) {
+ MOZ_ASSERT(aValue.mType == &SMILCSSValueType::sSingleton,
+ "We should only try setting a CSS value type");
+ return SetSMILValueHelper([&aValue](DeclarationBlock& aDecl) {
+ return SMILCSSValueType::SetPropertyValues(aValue, aDecl);
+ });
+}
+
+nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
+ const nsCSSPropertyID aPropID, const SVGAnimatedLength& aLength) {
+ return SetSMILValueHelper([aPropID, &aLength](DeclarationBlock& aDecl) {
+ return SVGElement::UpdateDeclarationBlockFromLength(
+ aDecl, aPropID, aLength, SVGElement::ValToUse::Anim);
+ });
+}
+
nsresult nsDOMCSSAttributeDeclaration::SetPropertyValue(
const nsCSSPropertyID aPropID, const nsAString& aValue,
nsIPrincipal* aSubjectPrincipal) {
diff --git a/layout/style/nsDOMCSSAttrDeclaration.h b/layout/style/nsDOMCSSAttrDeclaration.h
index 53d2451bce3e..3790df92e56b 100644
--- a/layout/style/nsDOMCSSAttrDeclaration.h
+++ b/layout/style/nsDOMCSSAttrDeclaration.h
@@ -18,6 +18,7 @@ struct RawServoUnlockedDeclarationBlock;
namespace mozilla {
class SMILValue;
+class SVGAnimatedLength;
namespace dom {
class DomGroup;
@@ -29,6 +30,7 @@ class nsDOMCSSAttributeDeclaration final : public nsDOMCSSDeclaration {
public:
typedef mozilla::dom::Element Element;
typedef mozilla::SMILValue SMILValue;
+ typedef mozilla::SVGAnimatedLength SVGAnimatedLength;
nsDOMCSSAttributeDeclaration(Element* aContent, bool aIsSMILOverride);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -45,7 +47,9 @@ class nsDOMCSSAttributeDeclaration final : public nsDOMCSSDeclaration {
nsINode* GetParentObject() override { return mElement; }
- nsresult SetSMILValue(const nsCSSPropertyID aPropID, const SMILValue&);
+ nsresult SetSMILValue(const nsCSSPropertyID aPropID, const SMILValue& aValue);
+ nsresult SetSMILValue(const nsCSSPropertyID aPropID,
+ const SVGAnimatedLength& aLength);
nsresult SetPropertyValue(const nsCSSPropertyID aPropID,
const nsAString& aValue,
@@ -79,6 +83,10 @@ class nsDOMCSSAttributeDeclaration final : public nsDOMCSSDeclaration {
* than the inline style rule).
*/
const bool mIsSMILOverride;
+
+ private:
+ template
+ nsresult SetSMILValueHelper(SetterFunc aFunc);
};
#endif /* nsDOMCSSAttributeDeclaration_h */
diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp
index b03bdf5030ff..160307afaacc 100644
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1069,7 +1069,14 @@ void nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow) {
// nsStyleSVGReset
//
nsStyleSVGReset::nsStyleSVGReset(const Document& aDocument)
- : mMask(nsStyleImageLayers::LayerType::Mask),
+ : mX(LengthPercentage::Zero()),
+ mY(LengthPercentage::Zero()),
+ mCx(LengthPercentage::Zero()),
+ mCy(LengthPercentage::Zero()),
+ mRx(NonNegativeLengthPercentageOrAuto::Auto()),
+ mRy(NonNegativeLengthPercentageOrAuto::Auto()),
+ mR(NonNegativeLengthPercentage::Zero()),
+ mMask(nsStyleImageLayers::LayerType::Mask),
mStopColor(StyleColor::Black()),
mFloodColor(StyleColor::Black()),
mLightingColor(StyleColor::White()),
@@ -1084,7 +1091,14 @@ nsStyleSVGReset::nsStyleSVGReset(const Document& aDocument)
nsStyleSVGReset::~nsStyleSVGReset() { MOZ_COUNT_DTOR(nsStyleSVGReset); }
nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
- : mMask(aSource.mMask),
+ : mX(aSource.mX),
+ mY(aSource.mY),
+ mCx(aSource.mCx),
+ mCy(aSource.mCy),
+ mRx(aSource.mRx),
+ mRy(aSource.mRy),
+ mR(aSource.mR),
+ mMask(aSource.mMask),
mClipPath(aSource.mClipPath),
mStopColor(aSource.mStopColor),
mFloodColor(aSource.mFloodColor),
@@ -1136,6 +1150,12 @@ nsChangeHint nsStyleSVGReset::CalcDifference(
const nsStyleSVGReset& aNewData) const {
nsChangeHint hint = nsChangeHint(0);
+ if (mX != aNewData.mX || mY != aNewData.mY || mCx != aNewData.mCx ||
+ mCy != aNewData.mCy || mR != aNewData.mR || mRx != aNewData.mRx ||
+ mRy != aNewData.mRy) {
+ hint |= nsChangeHint_InvalidateRenderingObservers | nsChangeHint_NeedReflow;
+ }
+
if (mClipPath != aNewData.mClipPath) {
hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
}
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
index 8d8486d7b6b5..17e33b5280d2 100644
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2859,6 +2859,15 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset {
return mVectorEffect == NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE;
}
+ // geometry properties
+ mozilla::LengthPercentage mX;
+ mozilla::LengthPercentage mY;
+ mozilla::LengthPercentage mCx;
+ mozilla::LengthPercentage mCy;
+ mozilla::NonNegativeLengthPercentageOrAuto mRx;
+ mozilla::NonNegativeLengthPercentageOrAuto mRy;
+ mozilla::NonNegativeLengthPercentage mR;
+
nsStyleImageLayers mMask;
mozilla::StyleShapeSource mClipPath;
mozilla::StyleColor mStopColor;
diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js
index 8e4ada7ab803..e75199f53494 100644
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -5632,6 +5632,62 @@ var gCSSProperties = {
other_values: [ "0", "0px", "-0em", "17px", "0.2em", "0.0002", "context-value" ],
invalid_values: [ "-0.1px", "-3px" ]
},
+ "x": {
+ domProp: "x",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "0px" ],
+ other_values: [ "-1em", "17px", "0.2em", "23.4%" ],
+ invalid_values: [ "auto", "context-value", "0.0002" ]
+ },
+ "y": {
+ domProp: "y",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "0px" ],
+ other_values: [ "-1em", "17px", "0.2em", "23.4%" ],
+ invalid_values: [ "auto", "context-value", "0.0002" ]
+ },
+ "cx": {
+ domProp: "cx",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "0px" ],
+ other_values: [ "-1em", "17px", "0.2em", "23.4%" ],
+ invalid_values: [ "auto", "context-value", "0.0002" ]
+ },
+ "cy": {
+ domProp: "cy",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "0px" ],
+ other_values: [ "-1em", "17px", "0.2em", "23.4%" ],
+ invalid_values: [ "auto", "context-value", "0.0002" ]
+ },
+ "r": {
+ domProp: "r",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "0px" ],
+ other_values: [ "17px", "0.2em", "23.4%" ],
+ invalid_values: [ "auto", "-1", "-1.5px", "0.0002" ]
+ },
+ "rx": {
+ domProp: "rx",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "auto" ],
+ other_values: [ "17px", "0.2em", "23.4%" ],
+ invalid_values: [ "hello", "-12px", "0.0002" ]
+ },
+ "ry": {
+ domProp: "ry",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "auto" ],
+ other_values: [ "17px", "0.2em", "23.4%" ],
+ invalid_values: [ "hello", "-1.3px", "0.0002" ]
+ },
"text-anchor": {
domProp: "textAnchor",
inherited: true,
diff --git a/layout/style/test/test_transitions_per_property.html b/layout/style/test/test_transitions_per_property.html
index 09ecbbb687b9..faf62f7079ff 100644
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -80,6 +80,10 @@ var supported_properties = {
test_length_clamped ],
"column-width": [ test_length_transition,
test_length_clamped ],
+ "cx": [ test_length_transition, test_percent_transition,
+ test_length_unclamped, test_percent_unclamped ],
+ "cy": [ test_length_transition, test_percent_transition,
+ test_length_unclamped, test_percent_unclamped ],
"-moz-image-region": [ test_rect_transition ],
"-moz-outline-radius-bottomleft": [ test_radius_transition ],
"-moz-outline-radius-bottomright": [ test_radius_transition ],
@@ -244,6 +248,12 @@ var supported_properties = {
"right": [ test_length_transition, test_percent_transition,
test_length_percent_calc_transition,
test_length_unclamped, test_percent_unclamped ],
+ "r": [ test_length_transition, test_percent_transition,
+ test_length_clamped, test_percent_clamped ],
+ "rx": [ test_length_transition, test_percent_transition,
+ test_length_clamped, test_percent_clamped ],
+ "ry": [ test_length_transition, test_percent_transition,
+ test_length_clamped, test_percent_clamped ],
"shape-image-threshold": [ test_float_zeroToOne_transition,
// shape-image-threshold (like opacity) is
// clamped in computed style
@@ -297,6 +307,10 @@ var supported_properties = {
test_length_percent_calc_transition,
test_length_clamped, test_percent_clamped ],
"word-spacing": [ test_length_transition, test_length_unclamped ],
+ "x": [ test_length_transition, test_percent_transition,
+ test_length_unclamped, test_percent_unclamped ],
+ "y": [ test_length_transition, test_percent_transition,
+ test_length_unclamped, test_percent_unclamped ],
"z-index": [ test_integer_transition, test_pos_integer_or_auto_transition ],
"-webkit-line-clamp": [ test_pos_integer_or_none_transition ],
"-webkit-text-fill-color": [ test_color_transition,
diff --git a/layout/svg/SVGGeometryFrame.cpp b/layout/svg/SVGGeometryFrame.cpp
index 584a8739f9f0..faad162d106d 100644
--- a/layout/svg/SVGGeometryFrame.cpp
+++ b/layout/svg/SVGGeometryFrame.cpp
@@ -197,6 +197,10 @@ void SVGGeometryFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
}
}
}
+
+ if (element->IsGeometryChangedViaCSS(*Style(), *aOldComputedStyle)) {
+ element->ClearAnyCachedPath();
+ }
}
}
diff --git a/layout/svg/nsSVGForeignObjectFrame.cpp b/layout/svg/nsSVGForeignObjectFrame.cpp
index 7e3822b3bb4d..c4b2b138828b 100644
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -19,6 +19,7 @@
#include "nsLayoutUtils.h"
#include "nsRegion.h"
#include "nsSVGContainerFrame.h"
+#include "SVGGeometryProperty.h"
#include "SVGObserverUtils.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGOuterSVGFrame.h"
@@ -27,6 +28,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::image;
+namespace SVGT = SVGGeometryProperty::Tags;
//----------------------------------------------------------------------
// Implementation
@@ -242,8 +244,9 @@ void nsSVGForeignObjectFrame::PaintSVG(gfxContext& aContext,
if (StyleDisplay()->IsScrollableOverflow()) {
float x, y, width, height;
- static_cast(GetContent())
- ->GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
+ SVGGeometryProperty::ResolveAll(
+ static_cast(GetContent()), &x, &y, &width, &height);
gfxRect clipRect =
nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height);
@@ -291,8 +294,8 @@ nsIFrame* nsSVGForeignObjectFrame::GetFrameForPoint(const gfxPoint& aPoint) {
}
float x, y, width, height;
- static_cast(GetContent())
- ->GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
+ SVGGeometryProperty::ResolveAll(
+ static_cast(GetContent()), &x, &y, &width, &height);
if (!gfxRect(x, y, width, height).Contains(aPoint) ||
!nsSVGUtils::HitTestClip(this, aPoint)) {
@@ -323,8 +326,8 @@ void nsSVGForeignObjectFrame::ReflowSVG() {
// correct dimensions:
float x, y, w, h;
- static_cast(GetContent())
- ->GetAnimatedLengthValues(&x, &y, &w, &h, nullptr);
+ SVGGeometryProperty::ResolveAll(
+ static_cast(GetContent()), &x, &y, &w, &h);
// If mRect's width or height are negative, reflow blows up! We must clamp!
if (w < 0.0f) w = 0.0f;
@@ -376,21 +379,17 @@ void nsSVGForeignObjectFrame::NotifySVGChanged(uint32_t aFlags) {
bool needNewCanvasTM = false;
if (aFlags & COORD_CONTEXT_CHANGED) {
- SVGForeignObjectElement* fO =
- static_cast(GetContent());
// Coordinate context changes affect mCanvasTM if we have a
// percentage 'x' or 'y'
- if (fO->mLengthAttributes[SVGForeignObjectElement::ATTR_X].IsPercentage() ||
- fO->mLengthAttributes[SVGForeignObjectElement::ATTR_Y].IsPercentage()) {
+ if (StyleSVGReset()->mX.HasPercent() || StyleSVGReset()->mY.HasPercent()) {
needNewBounds = true;
needNewCanvasTM = true;
}
+
// Our coordinate context's width/height has changed. If we have a
// percentage width/height our dimensions will change so we must reflow.
- if (fO->mLengthAttributes[SVGForeignObjectElement::ATTR_WIDTH]
- .IsPercentage() ||
- fO->mLengthAttributes[SVGForeignObjectElement::ATTR_HEIGHT]
- .IsPercentage()) {
+ if (StylePosition()->mWidth.HasPercent() ||
+ StylePosition()->mHeight.HasPercent()) {
needNewBounds = true;
needReflow = true;
}
@@ -443,7 +442,8 @@ SVGBBox nsSVGForeignObjectFrame::GetBBoxContribution(
static_cast(GetContent());
float x, y, w, h;
- content->GetAnimatedLengthValues(&x, &y, &w, &h, nullptr);
+ SVGGeometryProperty::ResolveAll(
+ content, &x, &y, &w, &h);
if (w < 0.0f) w = 0.0f;
if (h < 0.0f) h = 0.0f;
diff --git a/layout/tools/reftest/remotereftest.py b/layout/tools/reftest/remotereftest.py
index ee20f4eaa774..fed96888747f 100644
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -432,7 +432,7 @@ def run_test_harness(parser, options):
reftest.stopWebServer(options)
if options.printDeviceInfo and not options.verify:
- reftest.printDeviceInfo(printLogcat=True)
+ reftest.printDeviceInfo(printLogcat=(retVal != 0))
return retVal
diff --git a/mobile/android/app/geckoview-prefs.js b/mobile/android/app/geckoview-prefs.js
index dd41dcfec90f..610ccc035eec 100644
--- a/mobile/android/app/geckoview-prefs.js
+++ b/mobile/android/app/geckoview-prefs.js
@@ -36,7 +36,7 @@ pref("dom.storageManager.enabled", true);
pref("dom.visualviewport.enabled", true);
// Use containerless scrolling.
-pref("layout.scroll.root-frame-containers", 0);
+pref("layout.scroll.root-frame-containers", false);
// Inherit locale from the OS, used for multi-locale builds
pref("intl.locale.requested", "");
diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js
index 7739b60d8596..7690555458f4 100644
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -542,7 +542,7 @@ pref("layers.low-precision-opacity", "1.0");
pref("layers.max-active", 20);
// Use containerless scrolling on Fennec.
-pref("layout.scroll.root-frame-containers", 0);
+pref("layout.scroll.root-frame-containers", false);
pref("notification.feature.enabled", true);
pref("dom.webnotifications.enabled", true);
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ActivityResultHandler.java b/mobile/android/base/java/org/mozilla/gecko/util/ActivityResultHandler.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ActivityResultHandler.java
rename to mobile/android/base/java/org/mozilla/gecko/util/ActivityResultHandler.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ActivityResultHandlerMap.java b/mobile/android/base/java/org/mozilla/gecko/util/ActivityResultHandlerMap.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ActivityResultHandlerMap.java
rename to mobile/android/base/java/org/mozilla/gecko/util/ActivityResultHandlerMap.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/InputOptionsUtils.java b/mobile/android/base/java/org/mozilla/gecko/util/InputOptionsUtils.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/InputOptionsUtils.java
rename to mobile/android/base/java/org/mozilla/gecko/util/InputOptionsUtils.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/JSONUtils.java b/mobile/android/base/java/org/mozilla/gecko/util/JSONUtils.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/JSONUtils.java
rename to mobile/android/base/java/org/mozilla/gecko/util/JSONUtils.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/MapUtils.java b/mobile/android/base/java/org/mozilla/gecko/util/MapUtils.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/MapUtils.java
rename to mobile/android/base/java/org/mozilla/gecko/util/MapUtils.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/MenuUtils.java b/mobile/android/base/java/org/mozilla/gecko/util/MenuUtils.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/MenuUtils.java
rename to mobile/android/base/java/org/mozilla/gecko/util/MenuUtils.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/PrefUtils.java b/mobile/android/base/java/org/mozilla/gecko/util/PrefUtils.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/PrefUtils.java
rename to mobile/android/base/java/org/mozilla/gecko/util/PrefUtils.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/WindowUtils.java b/mobile/android/base/java/org/mozilla/gecko/util/WindowUtils.java
similarity index 100%
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/WindowUtils.java
rename to mobile/android/base/java/org/mozilla/gecko/util/WindowUtils.java
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/SpeechSynthesisService.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/SpeechSynthesisService.java
index 9eae1fda68a6..57c8be31dd18 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/SpeechSynthesisService.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/SpeechSynthesisService.java
@@ -20,13 +20,20 @@ import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
public class SpeechSynthesisService {
private static final String LOGTAG = "GeckoSpeechSynthesis";
- private static TextToSpeech sTTS;
+ // Object type is used to make it easier to remove android.speech dependencies using Proguard.
+ private static Object sTTS;
@WrapForJNI(calledFrom = "gecko")
public static void initSynth() {
+ initSynthInternal();
+ }
+
+ // Extra internal method to make it easier to remove android.speech dependencies using Proguard.
+ private static void initSynthInternal() {
if (sTTS != null) {
return;
}
@@ -47,15 +54,20 @@ public class SpeechSynthesisService {
});
}
+ private static TextToSpeech getTTS() {
+ return (TextToSpeech) sTTS;
+ }
+
private static void registerVoicesByLocale() {
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
+ TextToSpeech tss = getTTS();
Locale defaultLocale = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
- ? sTTS.getDefaultLanguage()
- : sTTS.getLanguage();
+ ? tss.getDefaultLanguage()
+ : tss.getLanguage();
for (Locale locale : getAvailableLanguages()) {
- final Set features = sTTS.getFeatures(locale);
+ final Set features = tss.getFeatures(locale);
boolean isLocal = features != null && features.contains(TextToSpeech.Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS);
String localeStr = locale.toString();
registerVoice("moz-tts:android:" + localeStr, locale.getDisplayName(), localeStr.replace("_", "-"), !isLocal, defaultLocale == locale);
@@ -69,11 +81,11 @@ public class SpeechSynthesisService {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// While this method was introduced in 21, it seems that it
// has not been implemented in the speech service side until 23.
- return sTTS.getAvailableLanguages();
+ return getTTS().getAvailableLanguages();
}
Set locales = new HashSet();
for (Locale locale : Locale.getAvailableLocales()) {
- if (locale.getVariant().isEmpty() && sTTS.isLanguageAvailable(locale) > 0) {
+ if (locale.getVariant().isEmpty() && getTTS().isLanguageAvailable(locale) > 0) {
locales.add(locale);
}
}
@@ -90,24 +102,29 @@ public class SpeechSynthesisService {
@WrapForJNI(calledFrom = "gecko")
public static String speak(final String uri, final String text, final float rate,
final float pitch, final float volume) {
+ AtomicBoolean result = new AtomicBoolean(false);
+ final String utteranceId = UUID.randomUUID().toString();
+ speakInternal(uri, text, rate, pitch, volume, utteranceId, result);
+ return result.get() ? utteranceId : null;
+ }
+
+ // Extra internal method to make it easier to remove android.speech dependencies using Proguard.
+ private static void speakInternal(final String uri, final String text, final float rate,
+ final float pitch, final float volume, final String utteranceId, final AtomicBoolean result) {
if (sTTS == null) {
Log.w(LOGTAG, "TextToSpeech is not initialized");
- return null;
+ return;
}
HashMap params = new HashMap();
- final String utteranceId = UUID.randomUUID().toString();
params.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, Float.toString(volume));
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);
- sTTS.setLanguage(new Locale(uri.substring("moz-tts:android:".length())));
- sTTS.setSpeechRate(rate);
- sTTS.setPitch(pitch);
- int result = sTTS.speak(text, TextToSpeech.QUEUE_FLUSH, params);
- if (result != TextToSpeech.SUCCESS) {
- return null;
- }
-
- return utteranceId;
+ TextToSpeech tss = (TextToSpeech) sTTS;
+ tss.setLanguage(new Locale(uri.substring("moz-tts:android:".length())));
+ tss.setSpeechRate(rate);
+ tss.setPitch(pitch);
+ int speakRes = tss.speak(text, TextToSpeech.QUEUE_FLUSH, params);
+ result.set(speakRes == TextToSpeech.SUCCESS);
}
private static void setUtteranceListener() {
@@ -116,7 +133,7 @@ public class SpeechSynthesisService {
return;
}
- sTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
+ getTTS().setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onDone(final String utteranceId) {
dispatchEnd(utteranceId);
@@ -163,12 +180,17 @@ public class SpeechSynthesisService {
@WrapForJNI(calledFrom = "gecko")
public static void stop() {
+ stopInternal();
+ }
+
+ // Extra internal method to make it easier to remove android.speech dependencies using Proguard.
+ private static void stopInternal() {
if (sTTS == null) {
Log.w(LOGTAG, "TextToSpeech is not initialized");
return;
}
- sTTS.stop();
+ getTTS().stop();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Android M has onStop method. If Android L or above, dispatch
// event
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/NonEvictingLruCache.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/NonEvictingLruCache.java
deleted file mode 100644
index b859bcf6d2a3..000000000000
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/NonEvictingLruCache.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.util;
-
-import android.util.LruCache;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * An LruCache that also supports a set of items that will never be evicted.
- *
- * Alas, LruCache is final, so we compose rather than inherit.
- */
-public class NonEvictingLruCache {
- private final ConcurrentHashMap mPermanent = new ConcurrentHashMap();
- private final LruCache mEvitable;
-
- public NonEvictingLruCache(final int evictableSize) {
- mEvitable = new LruCache(evictableSize);
- }
-
- public V get(final K key) {
- V val = mPermanent.get(key);
- if (val == null) {
- return mEvitable.get(key);
- }
- return val;
- }
-
- public void putWithoutEviction(final K key, final V value) {
- mPermanent.put(key, value);
- }
-
- public void put(final K key, final V value) {
- mEvitable.put(key, value);
- }
-
- public void evictAll() {
- mEvitable.evictAll();
- }
-}
diff --git a/modules/libpref/init/StaticPrefList.h b/modules/libpref/init/StaticPrefList.h
index 9c1ef692ca0a..e50dde3d8ae7 100644
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -2588,6 +2588,13 @@ VARCACHE_PREF(
bool, true
)
+// Maximum size for an array to store the safebrowsing prefixset.
+VARCACHE_PREF(
+ "browser.safebrowsing.prefixset_max_array_size",
+ browser_safebrowsing_prefixset_max_array_size,
+ RelaxedAtomicUint32, 512*1024
+)
+
// When this pref is enabled document loads with a mismatched
// Cross-Origin header will fail to load
VARCACHE_PREF("browser.tabs.remote.useCrossOriginPolicy",
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 9092bd4932a8..23d32e588169 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -777,7 +777,7 @@ pref("gfx.hidpi.enabled", 2);
#endif
// Default to containerless scrolling
-pref("layout.scroll.root-frame-containers", 0);
+pref("layout.scroll.root-frame-containers", false);
pref("layout.scrollbars.always-layerize-track", false);
@@ -6037,8 +6037,9 @@ pref("dom.datatransfer.mozAtAPIs", true);
// cycles.
pref("dom.sidebar.enabled", true);
-// Turn on fission frameloader swapping
-pref("fission.rebuild_frameloaders_on_remoteness_change", true);
+// Turn off fission frameloader swapping while regressions are being fixed.
+// Should be turned back on to resolve bug 1551993.
+pref("fission.rebuild_frameloaders_on_remoteness_change", false);
// If true, preserve browsing contexts between process swaps. Should be set to
// true in bug 1550571.
diff --git a/mozglue/linker/moz.build b/mozglue/linker/moz.build
index 4dc6ac0dd1d5..5204347c3bd1 100644
--- a/mozglue/linker/moz.build
+++ b/mozglue/linker/moz.build
@@ -21,17 +21,7 @@ DEFINES['IMPL_MFBT'] = True
DisableStlWrapping()
-# Avoid building the linker tests if building with icecc since it doesn't deal
-# well with .incbin.
-#
-# A better solution would be to set ICECC=no in the environment before building
-# these objects to force the local build, but moz.build lacks such a capability
-# at the moment.
-#
-# TODO: Remove this when https://github.com/icecc/icecream/pull/463 is merged
-# and in a release.
-if not CONFIG['CXX_IS_ICECREAM']:
- TEST_DIRS += ['tests']
+TEST_DIRS += ['tests']
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']
diff --git a/mozglue/linker/tests/TestZip.cpp b/mozglue/linker/tests/TestZip.cpp
index ac5372a11365..a2d2b10bdd5d 100644
--- a/mozglue/linker/tests/TestZip.cpp
+++ b/mozglue/linker/tests/TestZip.cpp
@@ -11,37 +11,14 @@
Logging Logging::Singleton;
-/**
- * ZIP_DATA(FOO, "foo") defines the variables FOO and FOO_SIZE.
- * The former contains the content of the "foo" file in the same directory
- * as this file, and FOO_SIZE its size.
- */
-/* clang-format off */
-#define ZIP_DATA(name, file) \
- __asm__(".global " #name "\n" \
- ".data\n" \
- ".balign 16\n" \
- #name ":\n" \
- " .incbin \"" SRCDIR "/" file "\"\n" \
- ".L" #name "_END:\n" \
- " .size " #name ", .L" #name "_END-" #name \
- "\n" \
- ".global " #name "_SIZE\n" \
- ".data\n" \
- ".balign 4\n" \
- #name "_SIZE:\n" \
- " .int .L" #name "_END-" #name "\n"); \
- extern const unsigned char name[]; \
- extern const unsigned int name##_SIZE
-/* clang-format on */
-
/**
* test.zip is a basic test zip file with a central directory. It contains
* four entries, in the following order:
* "foo", "bar", "baz", "qux".
* The entries are going to be read out of order.
*/
-ZIP_DATA(TEST_ZIP, "test.zip");
+extern const unsigned char TEST_ZIP[];
+extern const unsigned int TEST_ZIP_SIZE;
const char* test_entries[] = {"baz", "foo", "bar", "qux"};
/**
@@ -58,7 +35,8 @@ const char* test_entries[] = {"baz", "foo", "bar", "qux"};
* zipalign if it had a data descriptor originally.
* - Fourth entry is a file "d", STOREd.
*/
-ZIP_DATA(NO_CENTRAL_DIR_ZIP, "no_central_dir.zip");
+extern const unsigned char NO_CENTRAL_DIR_ZIP[];
+extern const unsigned int NO_CENTRAL_DIR_ZIP_SIZE;
const char* no_central_dir_entries[] = {"a", "b", "c", "d"};
TEST(Zip, TestZip)
diff --git a/mozglue/linker/tests/TestZipData.S b/mozglue/linker/tests/TestZipData.S
new file mode 100644
index 000000000000..5fbb82545197
--- /dev/null
+++ b/mozglue/linker/tests/TestZipData.S
@@ -0,0 +1,17 @@
+.macro zip_data name, path
+ .global \name
+ .data
+ .balign 16
+ \name:
+ .incbin "\path"
+ .L\name\()_END:
+ .size \name, .L\name\()_END-\name
+ .global \name\()_SIZE
+ .data
+ .balign 4
+ \name\()_SIZE:
+ .int .L\name\()_END-\name
+.endm
+
+zip_data TEST_ZIP, "test.zip"
+zip_data NO_CENTRAL_DIR_ZIP, "no_central_dir.zip"
diff --git a/mozglue/linker/tests/moz.build b/mozglue/linker/tests/moz.build
index 29b0e6e428ce..f2470dbbbeb0 100644
--- a/mozglue/linker/tests/moz.build
+++ b/mozglue/linker/tests/moz.build
@@ -11,9 +11,13 @@ UNIFIED_SOURCES += [
'TestZip.cpp',
]
+SOURCES += [
+ 'TestZipData.S',
+]
+
LOCAL_INCLUDES += ['..']
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']
-DEFINES['SRCDIR'] = '"%s"' % SRCDIR
+ASFLAGS += ['-I', SRCDIR]
diff --git a/old-configure.in b/old-configure.in
index 48fbff7383be..62e6e1e2eeb0 100644
--- a/old-configure.in
+++ b/old-configure.in
@@ -1691,6 +1691,13 @@ elif test "$EARLY_BETA_OR_EARLIER"; then
fi
AC_SUBST(EARLY_BETA_OR_EARLIER)
+
+if test "$EARLY_BETA_OR_EARLIER"; then
+ MOZ_NEW_CERT_STORAGE=1
+ AC_DEFINE(MOZ_NEW_CERT_STORAGE)
+fi
+AC_SUBST(MOZ_NEW_CERT_STORAGE)
+
# Allow someone to change MOZ_APP_NAME and MOZ_APP_BASENAME in mozconfig
MOZ_ARG_WITH_STRING(app-name,
[--with-app-name=APPNAME sets MOZ_APP_NAME to APPNAME],
diff --git a/security/manager/ssl/RemoteSecuritySettings.jsm b/security/manager/ssl/RemoteSecuritySettings.jsm
index 4e36c165d88f..7cc3081e4490 100644
--- a/security/manager/ssl/RemoteSecuritySettings.jsm
+++ b/security/manager/ssl/RemoteSecuritySettings.jsm
@@ -83,6 +83,15 @@ function bytesToString(bytes) {
return String.fromCharCode.apply(null, bytes);
}
+class CertInfo {
+ constructor(cert, subject) {
+ this.cert = cert;
+ this.subject = subject;
+ this.trust = Ci.nsICertStorage.TRUST_INHERIT;
+ }
+}
+CertInfo.prototype.QueryInterface = ChromeUtils.generateQI([Ci.nsICertInfo]);
+
this.RemoteSecuritySettings = class RemoteSecuritySettings {
constructor() {
this.client = RemoteSettings(Services.prefs.getCharPref(INTERMEDIATES_COLLECTION_PREF), {
@@ -148,22 +157,42 @@ this.RemoteSecuritySettings = class RemoteSecuritySettings {
TelemetryStopwatch.start(INTERMEDIATES_UPDATE_MS_TELEMETRY);
- Promise.all(waiting.slice(0, maxDownloadsPerRun)
- .map(record => this.maybeDownloadAttachment(record, col, certStorage))
- ).then(async () => {
- const finalCurrent = await this.client.get();
- const finalWaiting = finalCurrent.filter(record => !record.cert_import_complete);
- const countPreloaded = finalCurrent.length - finalWaiting.length;
+ let toDownload = waiting.slice(0, maxDownloadsPerRun);
+ let recordsCertsAndSubjects = await Promise.all(
+ toDownload.map(record => this.maybeDownloadAttachment(record)));
+ let certInfos = [];
+ let recordsToUpdate = [];
+ for (let {record, cert, subject} of recordsCertsAndSubjects) {
+ if (cert && subject) {
+ certInfos.push(new CertInfo(cert, subject));
+ recordsToUpdate.push(record);
+ }
+ }
+ let result = await new Promise((resolve) => {
+ certStorage.addCerts(certInfos, resolve);
+ }).catch((err) => err);
+ if (result != Cr.NS_OK) {
+ Cu.reportError(`certStorage.addCerts failed: ${result}`);
+ Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
+ .add("failedToUpdateDB");
+ return;
+ }
+ await Promise.all(recordsToUpdate.map((record) => {
+ record.cert_import_complete = true;
+ return col.update(record);
+ }));
+ const finalCurrent = await this.client.get();
+ const finalWaiting = finalCurrent.filter(record => !record.cert_import_complete);
+ const countPreloaded = finalCurrent.length - finalWaiting.length;
- TelemetryStopwatch.finish(INTERMEDIATES_UPDATE_MS_TELEMETRY);
- Services.telemetry.scalarSet(INTERMEDIATES_PRELOADED_TELEMETRY,
- countPreloaded);
- Services.telemetry.scalarSet(INTERMEDIATES_PENDING_TELEMETRY,
- finalWaiting.length);
+ TelemetryStopwatch.finish(INTERMEDIATES_UPDATE_MS_TELEMETRY);
+ Services.telemetry.scalarSet(INTERMEDIATES_PRELOADED_TELEMETRY,
+ countPreloaded);
+ Services.telemetry.scalarSet(INTERMEDIATES_PENDING_TELEMETRY,
+ finalWaiting.length);
- Services.obs.notifyObservers(null, "remote-security-settings:intermediates-updated",
- "success");
- });
+ Services.obs.notifyObservers(null, "remote-security-settings:intermediates-updated",
+ "success");
}
async onObservePollEnd(subject, topic, data) {
@@ -227,98 +256,87 @@ this.RemoteSecuritySettings = class RemoteSecuritySettings {
/**
* Attempts to download the attachment, assuming it's not been processed
* already. Does not retry, and always resolves (e.g., does not reject upon
- * failure.) Errors are reported via Cu.reportError; If you need to know
- * success/failure, check record.cert_import_complete.
+ * failure.) Errors are reported via Cu.reportError.
* @param {AttachmentRecord} record defines which data to obtain
- * @param {KintoCollection} col The kinto collection to update
- * @param {nsICertStorage} certStorage The certificate storage to update
- * @return {Promise} a Promise representing the transaction
+ * @return {Promise} a Promise that will resolve to an object with the properties
+ * record, cert, and subject. record is the original record.
+ * cert is the base64-encoded bytes of the downloaded certificate (if
+ * downloading was successful), and null otherwise.
+ * subject is the base64-encoded bytes of the subject distinguished
+ * name of the same.
*/
- async maybeDownloadAttachment(record, col, certStorage) {
+ async maybeDownloadAttachment(record) {
const {attachment: {hash, size}} = record;
+ let result = { record, cert: null, subject: null };
- return this._downloadAttachmentBytes(record)
- .then(async function(attachmentData) {
- if (!attachmentData || attachmentData.length == 0) {
- // Bug 1519273 - Log telemetry for these rejections
- log.debug(`Empty attachment. Hash=${hash}`);
-
- Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
- .add("emptyAttachment");
-
- return;
- }
-
- // check the length
- if (attachmentData.length !== size) {
- log.debug(`Unexpected attachment length. Hash=${hash} Lengths ${attachmentData.length} != ${size}`);
-
- Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
- .add("unexpectedLength");
-
- return;
- }
-
- // check the hash
- let dataAsString = gTextDecoder.decode(attachmentData);
- let calculatedHash = getHash(dataAsString);
- if (calculatedHash !== hash) {
- log.warn(`Invalid hash. CalculatedHash=${calculatedHash}, Hash=${hash}, data=${dataAsString}`);
-
- Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
- .add("unexpectedHash");
-
- return;
- }
-
- let certBase64;
- let subjectBase64;
- try {
- // split off the header and footer
- certBase64 = dataAsString.split("-----")[2].replace(/\s/g, "");
- // get an array of bytes so we can use X509.jsm
- let certBytes = stringToBytes(atob(certBase64));
- let cert = new X509.Certificate();
- cert.parse(certBytes);
- // get the DER-encoded subject and get a base64-encoded string from it
- // TODO(bug 1542028): add getters for _der and _bytes
- subjectBase64 = btoa(bytesToString(cert.tbsCertificate.subject._der._bytes));
- } catch (err) {
- Cu.reportError(`Failed to decode cert: ${err}`);
-
- // Re-purpose the "failedToUpdateNSS" telemetry tag as "failed to
- // decode preloaded intermediate certificate"
- Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
- .add("failedToUpdateNSS");
-
- return;
- }
- log.debug(`Adding cert. Hash=${hash}. Size=${size}`);
- // We can assume that certs obtained from remote-settings are part of
- // the root program. If they aren't, they won't be used for path-
- // building anyway, so just add it to the DB with trust set to
- // "inherit".
- let result = await new Promise((resolve) => {
- certStorage.addCertBySubject(certBase64, subjectBase64,
- Ci.nsICertStorage.TRUST_INHERIT,
- resolve);
- });
- if (result != Cr.NS_OK) {
- Cu.reportError(`Failed to add to cert storage: ${result}`);
- Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
- .add("failedToUpdateDB");
- return;
- }
-
- record.cert_import_complete = true;
- await col.update(record);
- })
- .catch(() => {
- // Don't abort the outer Promise.all because of an error. Errors were
- // sent using Cu.reportError()
+ let attachmentData;
+ try {
+ attachmentData = await this._downloadAttachmentBytes(record);
+ } catch (err) {
+ Cu.reportError(`Failed to download attachment: ${err}`);
Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
.add("failedToDownloadMisc");
- });
+ return result;
+ }
+
+ if (!attachmentData || attachmentData.length == 0) {
+ // Bug 1519273 - Log telemetry for these rejections
+ log.debug(`Empty attachment. Hash=${hash}`);
+
+ Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
+ .add("emptyAttachment");
+
+ return result;
+ }
+
+ // check the length
+ if (attachmentData.length !== size) {
+ log.debug(`Unexpected attachment length. Hash=${hash} Lengths ${attachmentData.length} != ${size}`);
+
+ Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
+ .add("unexpectedLength");
+
+ return result;
+ }
+
+ // check the hash
+ let dataAsString = gTextDecoder.decode(attachmentData);
+ let calculatedHash = getHash(dataAsString);
+ if (calculatedHash !== hash) {
+ log.warn(`Invalid hash. CalculatedHash=${calculatedHash}, Hash=${hash}, data=${dataAsString}`);
+
+ Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
+ .add("unexpectedHash");
+
+ return result;
+ }
+ log.debug(`downloaded cert with hash=${hash}, size=${size}`);
+
+ let certBase64;
+ let subjectBase64;
+ try {
+ // split off the header and footer
+ certBase64 = dataAsString.split("-----")[2].replace(/\s/g, "");
+ // get an array of bytes so we can use X509.jsm
+ let certBytes = stringToBytes(atob(certBase64));
+ let cert = new X509.Certificate();
+ cert.parse(certBytes);
+ // get the DER-encoded subject and get a base64-encoded string from it
+ // TODO(bug 1542028): add getters for _der and _bytes
+ subjectBase64 = btoa(bytesToString(cert.tbsCertificate.subject._der._bytes));
+ } catch (err) {
+ Cu.reportError(`Failed to decode cert: ${err}`);
+
+ // Re-purpose the "failedToUpdateNSS" telemetry tag as "failed to
+ // decode preloaded intermediate certificate"
+ Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
+ .add("failedToUpdateNSS");
+
+ return result;
+ }
+ result.cert = certBase64;
+ result.subject = subjectBase64;
+ return result;
}
async maybeSync(expectedTimestamp, options) {
@@ -327,19 +345,12 @@ this.RemoteSecuritySettings = class RemoteSecuritySettings {
async removeCerts(recordsToRemove) {
let certStorage = Cc["@mozilla.org/security/certstorage;1"].getService(Ci.nsICertStorage);
- let failures = 0;
- for (let record of recordsToRemove) {
- let result = await new Promise((resolve) => {
- certStorage.removeCertByHash(record.pubKeyHash, resolve);
- });
- if (result != Cr.NS_OK) {
- Cu.reportError(`Failed to remove intermediate certificate Hash=${record.pubKeyHash}: ${result}`);
- failures++;
- }
- }
-
- if (failures > 0) {
- Cu.reportError(`Failed to remove ${failures} intermediate certificates`);
+ let hashes = recordsToRemove.map(record => record.pubKeyHash);
+ let result = await new Promise((resolve) => {
+ certStorage.removeCertsByHashes(hashes, resolve);
+ }).catch((err) => err);
+ if (result != Cr.NS_OK) {
+ Cu.reportError(`Failed to remove some intermediate certificates`);
Services.telemetry.getHistogramById(INTERMEDIATES_ERRORS_TELEMETRY)
.add("failedToRemove");
}
diff --git a/security/manager/ssl/cert_storage/src/lib.rs b/security/manager/ssl/cert_storage/src/lib.rs
index 2136d78f3203..3aaed181843f 100644
--- a/security/manager/ssl/cert_storage/src/lib.rs
+++ b/security/manager/ssl/cert_storage/src/lib.rs
@@ -26,7 +26,7 @@ use lmdb::EnvironmentFlags;
use moz_task::{create_thread, is_main_thread, Task, TaskRunnable};
use nserror::{
nsresult, NS_ERROR_FAILURE, NS_ERROR_NOT_SAME_THREAD, NS_ERROR_NO_AGGREGATION,
- NS_ERROR_UNEXPECTED, NS_OK,
+ NS_ERROR_NULL_POINTER, NS_ERROR_UNEXPECTED, NS_OK,
};
use nsstring::{nsACString, nsAString, nsCStr, nsCString, nsString};
use rkv::error::StoreError;
@@ -47,9 +47,9 @@ use std::time::{Duration, SystemTime};
use storage_variant::VariantType;
use thin_vec::ThinVec;
use xpcom::interfaces::{
- nsICertStorage, nsICertStorageCallback, nsIFile, nsIIssuerAndSerialRevocationState,
- nsIObserver, nsIPrefBranch, nsIRevocationState, nsISubjectAndPubKeyRevocationState,
- nsISupports, nsIThread,
+ nsICertInfo, nsICertStorage, nsICertStorageCallback, nsIFile,
+ nsIIssuerAndSerialRevocationState, nsIObserver, nsIPrefBranch, nsIRevocationState,
+ nsISubjectAndPubKeyRevocationState, nsISupports, nsIThread,
};
use xpcom::{nsIID, GetterAddrefs, RefPtr, ThreadBoundRefPtr, XpCom};
@@ -395,21 +395,19 @@ impl SecurityState {
self.int_prefs.insert(name.to_owned(), value);
}
- // To store a certificate by subject, we first create a Cert out of the given cert, subject, and
- // trust. We hash the certificate with sha-256 to obtain a unique* key for that certificate, and
- // we store the Cert in the database. We also look up or create a CertHashList for the given
- // subject and add the new certificate's hash if it isn't present in the list. If it wasn't
- // present, we write out the updated CertHashList.
+ // To store certificates, we create a Cert out of each given cert, subject, and trust tuple. We
+ // hash each certificate with sha-256 to obtain a unique* key for that certificate, and we store
+ // the Cert in the database. We also look up or create a CertHashList for the given subject and
+ // add the new certificate's hash if it isn't present in the list. If it wasn't present, we
+ // write out the updated CertHashList.
// *By the pigeon-hole principle, there exist collisions for sha-256, so this key is not
// actually unique. We rely on the assumption that sha-256 is a cryptographically strong hash.
// If an adversary can find two different certificates with the same sha-256 hash, they can
// probably forge a sha-256-based signature, so assuming the keys we create here are unique is
// not a security issue.
- pub fn add_cert_by_subject(
+ pub fn add_certs(
&mut self,
- cert_der: &[u8],
- subject: &[u8],
- trust: i16,
+ certs: &[(Vec, Vec, i16)],
) -> Result<(), SecurityStateError> {
self.reopen_store_read_write()?;
{
@@ -428,32 +426,30 @@ impl SecurityState {
&Value::Bool(true),
)?;
- let mut digest = Sha256::default();
- digest.input(cert_der);
- let cert_hash = digest.result();
- let cert_key = make_key!(PREFIX_CERT, &cert_hash);
- let cert = Cert::new(cert_der, subject, trust)?;
- env_and_store
- .store
- .put(&mut writer, &cert_key, &Value::Blob(&cert.to_bytes()?))?;
- let subject_key = make_key!(PREFIX_SUBJECT, subject);
- // This reader will only be able to "see" data outside the current transaction. This is
- // fine, though, because what we're reading has not yet been touched by this
- // transaction.
- let reader = env_and_store.env.read()?;
- let empty_vec = Vec::new();
- let old_cert_hash_list = match env_and_store.store.get(&reader, &subject_key)? {
- Some(Value::Blob(hashes)) => hashes,
- Some(_) => &empty_vec,
- None => &empty_vec,
- };
- let new_cert_hash_list = CertHashList::add(old_cert_hash_list, &cert_hash)?;
- if new_cert_hash_list.len() != old_cert_hash_list.len() {
- env_and_store.store.put(
- &mut writer,
- &subject_key,
- &Value::Blob(&new_cert_hash_list),
- )?;
+ for (cert_der, subject, trust) in certs {
+ let mut digest = Sha256::default();
+ digest.input(cert_der);
+ let cert_hash = digest.result();
+ let cert_key = make_key!(PREFIX_CERT, &cert_hash);
+ let cert = Cert::new(cert_der, subject, *trust)?;
+ env_and_store
+ .store
+ .put(&mut writer, &cert_key, &Value::Blob(&cert.to_bytes()?))?;
+ let subject_key = make_key!(PREFIX_SUBJECT, subject);
+ let empty_vec = Vec::new();
+ let old_cert_hash_list = match env_and_store.store.get(&writer, &subject_key)? {
+ Some(Value::Blob(hashes)) => hashes.to_owned(),
+ Some(_) => empty_vec,
+ None => empty_vec,
+ };
+ let new_cert_hash_list = CertHashList::add(&old_cert_hash_list, &cert_hash)?;
+ if new_cert_hash_list.len() != old_cert_hash_list.len() {
+ env_and_store.store.put(
+ &mut writer,
+ &subject_key,
+ &Value::Blob(&new_cert_hash_list),
+ )?;
+ }
}
writer.commit()?;
@@ -462,11 +458,11 @@ impl SecurityState {
Ok(())
}
- // Given a certificate's sha-256 hash, we can look up its Cert entry in the database. We use
- // this to find its subject so we can look up the CertHashList it should appear in. If that list
- // contains the given hash, we remove it and update the CertHashList. Finally we delete the Cert
- // entry.
- pub fn remove_cert_by_hash(&mut self, hash: &[u8]) -> Result<(), SecurityStateError> {
+ // Given a list of certificate sha-256 hashes, we can look up each Cert entry in the database.
+ // We use this to find the corresponding subject so we can look up the CertHashList it should
+ // appear in. If that list contains the given hash, we remove it and update the CertHashList.
+ // Finally we delete the Cert entry.
+ pub fn remove_certs_by_hashes(&mut self, hashes: &[Vec]) -> Result<(), SecurityStateError> {
self.reopen_store_read_write()?;
{
let env_and_store = match self.env_and_store.as_mut() {
@@ -474,33 +470,40 @@ impl SecurityState {
None => return Err(SecurityStateError::from("env and store not initialized?")),
};
let mut writer = env_and_store.env.write()?;
-
let reader = env_and_store.env.read()?;
- let cert_key = make_key!(PREFIX_CERT, hash);
- if let Some(Value::Blob(cert_bytes)) = env_and_store.store.get(&reader, &cert_key)? {
- if let Ok(cert) = Cert::from_bytes(cert_bytes) {
- let subject_key = make_key!(PREFIX_SUBJECT, &cert.subject);
- let empty_vec = Vec::new();
- let old_cert_hash_list = match env_and_store.store.get(&reader, &subject_key)? {
- Some(Value::Blob(hashes)) => hashes,
- Some(_) => &empty_vec,
- None => &empty_vec,
- };
- let new_cert_hash_list = CertHashList::remove(old_cert_hash_list, hash)?;
- if new_cert_hash_list.len() != old_cert_hash_list.len() {
- env_and_store.store.put(
- &mut writer,
- &subject_key,
- &Value::Blob(&new_cert_hash_list),
- )?;
+
+ for hash in hashes {
+ let cert_key = make_key!(PREFIX_CERT, hash);
+ if let Some(Value::Blob(cert_bytes)) =
+ env_and_store.store.get(&reader, &cert_key)?
+ {
+ if let Ok(cert) = Cert::from_bytes(cert_bytes) {
+ let subject_key = make_key!(PREFIX_SUBJECT, &cert.subject);
+ let empty_vec = Vec::new();
+ // We have to use the writer here to make sure we have an up-to-date view of
+ // the cert hash list.
+ let old_cert_hash_list =
+ match env_and_store.store.get(&writer, &subject_key)? {
+ Some(Value::Blob(hashes)) => hashes.to_owned(),
+ Some(_) => empty_vec,
+ None => empty_vec,
+ };
+ let new_cert_hash_list = CertHashList::remove(&old_cert_hash_list, hash)?;
+ if new_cert_hash_list.len() != old_cert_hash_list.len() {
+ env_and_store.store.put(
+ &mut writer,
+ &subject_key,
+ &Value::Blob(&new_cert_hash_list),
+ )?;
+ }
}
}
+ match env_and_store.store.delete(&mut writer, &cert_key) {
+ Ok(()) => {}
+ Err(StoreError::LmdbError(lmdb::Error::NotFound)) => {}
+ Err(e) => return Err(SecurityStateError::from(e)),
+ };
}
- match env_and_store.store.delete(&mut writer, &cert_key) {
- Ok(()) => {}
- Err(StoreError::LmdbError(lmdb::Error::NotFound)) => {}
- Err(e) => return Err(SecurityStateError::from(e)),
- };
writer.commit()?;
}
self.reopen_store_read_only()?;
@@ -1029,7 +1032,7 @@ impl CertStorage {
return NS_ERROR_NOT_SAME_THREAD;
}
if callback.is_null() {
- return NS_ERROR_FAILURE;
+ return NS_ERROR_NULL_POINTER;
}
let task = Box::new(SecurityStateTask::new(
&*callback,
@@ -1051,7 +1054,7 @@ impl CertStorage {
return NS_ERROR_NOT_SAME_THREAD;
}
if revocations.is_null() || callback.is_null() {
- return NS_ERROR_FAILURE;
+ return NS_ERROR_NULL_POINTER;
}
let revocations = &*revocations;
@@ -1115,7 +1118,7 @@ impl CertStorage {
// TODO (bug 1541212): We really want to restrict this to non-main-threads only, but we
// can't do so until bug 1406854 and bug 1534600 are fixed.
if issuer.is_null() || serial.is_null() || subject.is_null() || pub_key.is_null() {
- return NS_ERROR_FAILURE;
+ return NS_ERROR_NULL_POINTER;
}
*state = nsICertStorage::STATE_UNSET as i16;
let ss = get_security_state!(self);
@@ -1140,51 +1143,65 @@ impl CertStorage {
NS_OK
}
- unsafe fn AddCertBySubject(
+ unsafe fn AddCerts(
&self,
- cert: *const nsACString,
- subject: *const nsACString,
- trust: i16,
+ certs: *const ThinVec>,
callback: *const nsICertStorageCallback,
) -> nserror::nsresult {
if !is_main_thread() {
return NS_ERROR_NOT_SAME_THREAD;
}
- if cert.is_null() || subject.is_null() || callback.is_null() {
- return NS_ERROR_FAILURE;
+ if certs.is_null() || callback.is_null() {
+ return NS_ERROR_NULL_POINTER;
+ }
+ let certs = &*certs;
+ let mut cert_entries = Vec::with_capacity(certs.len());
+ for cert in certs {
+ let mut der = nsCString::new();
+ try_ns!((*cert).GetCert(&mut *der).to_result(), or continue);
+ let der = try_ns!(base64::decode(&der), or continue);
+ let mut subject = nsCString::new();
+ try_ns!((*cert).GetSubject(&mut *subject).to_result(), or continue);
+ let subject = try_ns!(base64::decode(&subject), or continue);
+ let mut trust: i16 = 0;
+ try_ns!((*cert).GetTrust(&mut trust).to_result(), or continue);
+ cert_entries.push((der, subject, trust));
}
- let cert_decoded = try_ns!(base64::decode(&*cert));
- let subject_decoded = try_ns!(base64::decode(&*subject));
let task = Box::new(SecurityStateTask::new(
&*callback,
&self.security_state,
- move |ss| ss.add_cert_by_subject(&cert_decoded, &subject_decoded, trust),
+ move |ss| ss.add_certs(&cert_entries),
));
let thread = try_ns!(self.thread.lock());
- let runnable = try_ns!(TaskRunnable::new("AddCertBySubject", task));
+ let runnable = try_ns!(TaskRunnable::new("AddCerts", task));
try_ns!(runnable.dispatch(&*thread));
NS_OK
}
- unsafe fn RemoveCertByHash(
+ unsafe fn RemoveCertsByHashes(
&self,
- hash: *const nsACString,
+ hashes: *const ThinVec,
callback: *const nsICertStorageCallback,
) -> nserror::nsresult {
if !is_main_thread() {
return NS_ERROR_NOT_SAME_THREAD;
}
- if hash.is_null() || callback.is_null() {
- return NS_ERROR_FAILURE;
+ if hashes.is_null() || callback.is_null() {
+ return NS_ERROR_NULL_POINTER;
+ }
+ let hashes = &*hashes;
+ let mut hash_entries = Vec::with_capacity(hashes.len());
+ for hash in hashes {
+ let hash_decoded = try_ns!(base64::decode(&*hash), or continue);
+ hash_entries.push(hash_decoded);
}
- let hash_decoded = try_ns!(base64::decode(&*hash));
let task = Box::new(SecurityStateTask::new(
&*callback,
&self.security_state,
- move |ss| ss.remove_cert_by_hash(&hash_decoded),
+ move |ss| ss.remove_certs_by_hashes(&hash_entries),
));
let thread = try_ns!(self.thread.lock());
- let runnable = try_ns!(TaskRunnable::new("RemoveCertByHash", task));
+ let runnable = try_ns!(TaskRunnable::new("RemoveCertsByHashes", task));
try_ns!(runnable.dispatch(&*thread));
NS_OK
}
@@ -1197,7 +1214,7 @@ impl CertStorage {
// TODO (bug 1541212): We really want to restrict this to non-main-threads only, but we
// can't do so until bug 1406854 and bug 1534600 are fixed.
if subject.is_null() || certs.is_null() {
- return NS_ERROR_FAILURE;
+ return NS_ERROR_NULL_POINTER;
}
let ss = get_security_state!(self);
match ss.find_certs_by_subject(&*subject, &mut *certs) {
diff --git a/security/manager/ssl/nsICertStorage.idl b/security/manager/ssl/nsICertStorage.idl
index 98eb50190b35..74f516bdc4df 100644
--- a/security/manager/ssl/nsICertStorage.idl
+++ b/security/manager/ssl/nsICertStorage.idl
@@ -55,6 +55,22 @@ interface nsISubjectAndPubKeyRevocationState : nsIRevocationState {
readonly attribute ACString pubKey;
};
+/**
+ * An interface representing a certificate to add to storage. Consists of the
+ * base64-encoded DER bytes of the certificate (cert), the base64-encoded DER
+ * bytes of the subject distinguished name of the certificate (subject), and the
+ * trust of the certificate (one of the nsICertStorage.TRUST_* constants).
+ * (Note that this implementation does not validate that the given subject DN
+ * actually matches the subject DN of the certificate, nor that the given cert
+ * is a valid DER X.509 certificate.)
+ */
+[scriptable, uuid(27b66f5e-0faf-403b-95b4-bc11691ac50d)]
+interface nsICertInfo : nsISupports {
+ readonly attribute ACString cert;
+ readonly attribute ACString subject;
+ readonly attribute short trust;
+};
+
[scriptable, uuid(327100a7-3401-45ef-b160-bf880f1016fd)]
interface nsICertStorage : nsISupports {
const octet DATA_TYPE_REVOCATION = 1;
@@ -118,34 +134,27 @@ interface nsICertStorage : nsISupports {
const short TRUST_ANCHOR = 1;
/**
- * Asynchronously add a certificate to the backing storage.
- * cert is the bytes of the certificate as base64-encoded DER.
- * subject is the subject distinguished name of the certificate as
- * base64-encoded DER (although we don't actually validate that the given
- * certificate has the indicated subject).
- * trust is one of the TRUST_* constants in this interface.
+ * Asynchronously add a list of certificates to the backing storage.
+ * See the documentation for nsICertInfo.
* The given callback is called with the result of the operation when it
* completes.
* Must only be called from the main thread.
*/
[must_use]
- void addCertBySubject(in ACString cert,
- in ACString subject,
- in short trust,
- in nsICertStorageCallback callback);
+ void addCerts(in Array certs, in nsICertStorageCallback callback);
/**
- * Asynchronously remove the certificate with the given sha-256 hash from the
- * backing storage.
- * hash is the base64-encoded bytes of the sha-256 hash of the certificate's
- * bytes (DER-encoded).
+ * Asynchronously remove the certificates with the given sha-256 hashes from
+ * the backing storage.
+ * hashes is an array of base64-encoded bytes of the sha-256 hashes of each
+ * certificate's bytes (DER-encoded).
* The given callback is called with the result of the operation when it
* completes.
* Must only be called from the main thread.
*/
[must_use]
- void removeCertByHash(in ACString hash,
- in nsICertStorageCallback callback);
+ void removeCertsByHashes(in Array hashes,
+ in nsICertStorageCallback callback);
/**
* Find all certificates in the backing storage with the given subject
diff --git a/security/manager/ssl/nsNSSCallbacks.cpp b/security/manager/ssl/nsNSSCallbacks.cpp
index 0ff9202a3fbb..2c9c041e8c4e 100644
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -1271,10 +1271,12 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
bool renegotiationUnsafe = !siteSupportsSafeRenego &&
ioLayerHelpers.treatUnsafeNegotiationAsBroken();
+ bool deprecatedTlsVer =
+ (channelInfo.protocolVersion < SSL_LIBRARY_VERSION_TLS_1_2);
RememberCertErrorsTable::GetInstance().LookupCertErrorBits(infoObject);
uint32_t state;
- if (renegotiationUnsafe) {
+ if (renegotiationUnsafe || deprecatedTlsVer) {
state = nsIWebProgressListener::STATE_IS_BROKEN;
} else {
state = nsIWebProgressListener::STATE_IS_SECURE;
diff --git a/security/manager/ssl/security-prefs.js b/security/manager/ssl/security-prefs.js
index 3fc1686ebeae..eb2376efb0b9 100644
--- a/security/manager/ssl/security-prefs.js
+++ b/security/manager/ssl/security-prefs.js
@@ -164,10 +164,10 @@ pref("security.pki.mitm_canary_issuer.enabled", true);
pref("security.pki.mitm_detected", false);
// Intermediate CA Preloading settings
-#if defined(RELEASE_OR_BETA) || defined(MOZ_WIDGET_ANDROID)
-pref("security.remote_settings.intermediates.enabled", false);
-#else
+#if defined(MOZ_NEW_CERT_STORAGE) && !defined(MOZ_WIDGET_ANDROID)
pref("security.remote_settings.intermediates.enabled", true);
+#else
+pref("security.remote_settings.intermediates.enabled", false);
#endif
pref("security.remote_settings.intermediates.bucket", "security-state");
pref("security.remote_settings.intermediates.collection", "intermediates");
diff --git a/security/manager/ssl/tests/unit/test_cert_storage_broken_db.js b/security/manager/ssl/tests/unit/test_cert_storage_broken_db.js
index 5f8ffeb400e2..35dd10630a78 100644
--- a/security/manager/ssl/tests/unit/test_cert_storage_broken_db.js
+++ b/security/manager/ssl/tests/unit/test_cert_storage_broken_db.js
@@ -54,10 +54,9 @@ add_task({
check_has_prior_cert_data(certStorage, false);
result = await new Promise((resolve) => {
- certStorage.addCertBySubject(btoa("some cert"), btoa("some subject"),
- Ci.nsICertStorage.TRUST_INHERIT, resolve);
+ certStorage.addCerts([], resolve);
});
- Assert.equal(result, Cr.NS_OK, "addCertBySubject should succeed");
+ Assert.equal(result, Cr.NS_OK, "addCerts should succeed");
check_has_prior_revocation_data(certStorage, true);
check_has_prior_cert_data(certStorage, true);
diff --git a/security/manager/ssl/tests/unit/test_cert_storage_direct.js b/security/manager/ssl/tests/unit/test_cert_storage_direct.js
index 040827d60600..c6d95c92a372 100644
--- a/security/manager/ssl/tests/unit/test_cert_storage_direct.js
+++ b/security/manager/ssl/tests/unit/test_cert_storage_direct.js
@@ -13,19 +13,18 @@ if (AppConstants.MOZ_NEW_CERT_STORAGE) {
this.certStorage = Cc["@mozilla.org/security/certstorage;1"].getService(Ci.nsICertStorage);
}
-async function addCertBySubject(cert, subject) {
+async function addCerts(certInfos) {
let result = await new Promise((resolve) => {
- certStorage.addCertBySubject(btoa(cert), btoa(subject), Ci.nsICertStorage.TRUST_INHERIT,
- resolve);
+ certStorage.addCerts(certInfos, resolve);
});
- Assert.equal(result, Cr.NS_OK, "addCertBySubject should succeed");
+ Assert.equal(result, Cr.NS_OK, "addCerts should succeed");
}
-async function removeCertByHash(hashBase64) {
+async function removeCertsByHashes(hashesBase64) {
let result = await new Promise((resolve) => {
- certStorage.removeCertByHash(hashBase64, resolve);
+ certStorage.removeCertsByHashes(hashesBase64, resolve);
});
- Assert.equal(result, Cr.NS_OK, "removeCertByHash should succeed");
+ Assert.equal(result, Cr.NS_OK, "removeCertsByHashes should succeed");
}
function stringToArray(s) {
@@ -48,19 +47,31 @@ function getLongString(uniquePart, length) {
return String(uniquePart).padStart(length, "0");
}
+class CertInfo {
+ constructor(cert, subject) {
+ this.cert = btoa(cert);
+ this.subject = btoa(subject);
+ this.trust = Ci.nsICertStorage.TRUST_INHERIT;
+ }
+}
+if (AppConstants.MOZ_NEW_CERT_STORAGE) {
+ CertInfo.prototype.QueryInterface = ChromeUtils.generateQI([Ci.nsICertInfo]);
+}
+
add_task({
skip_if: () => !AppConstants.MOZ_NEW_CERT_STORAGE,
}, async function test_common_subject() {
- await addCertBySubject("some certificate bytes 1", "some common subject");
- await addCertBySubject("some certificate bytes 2", "some common subject");
- await addCertBySubject("some certificate bytes 3", "some common subject");
+ let someCert1 = new CertInfo("some certificate bytes 1", "some common subject");
+ let someCert2 = new CertInfo("some certificate bytes 2", "some common subject");
+ let someCert3 = new CertInfo("some certificate bytes 3", "some common subject");
+ await addCerts([someCert1, someCert2, someCert3]);
let storedCerts = certStorage.findCertsBySubject(stringToArray("some common subject"));
let storedCertsAsStrings = storedCerts.map(arrayToString);
let expectedCerts = ["some certificate bytes 1", "some certificate bytes 2",
"some certificate bytes 3"];
Assert.deepEqual(storedCertsAsStrings.sort(), expectedCerts.sort(), "should find expected certs");
- await addCertBySubject("some other certificate bytes", "some other subject");
+ await addCerts([new CertInfo("some other certificate bytes", "some other subject")]);
storedCerts = certStorage.findCertsBySubject(stringToArray("some common subject"));
storedCertsAsStrings = storedCerts.map(arrayToString);
Assert.deepEqual(storedCertsAsStrings.sort(), expectedCerts.sort(),
@@ -78,9 +89,11 @@ add_task({
const NUM_CERTS = 500;
const CERT_LENGTH = 3000;
const SUBJECT_LENGTH = 40;
+ let certs = [];
for (let i = 0; i < NUM_CERTS; i++) {
- await addCertBySubject(getLongString(i, CERT_LENGTH), getLongString(i, SUBJECT_LENGTH));
+ certs.push(new CertInfo(getLongString(i, CERT_LENGTH), getLongString(i, SUBJECT_LENGTH)));
}
+ await addCerts(certs);
for (let i = 0; i < NUM_CERTS; i++) {
let subject = stringToArray(getLongString(i, SUBJECT_LENGTH));
let storedCerts = certStorage.findCertsBySubject(subject);
@@ -96,11 +109,12 @@ add_task({
}, async function test_removal() {
// As long as cert_storage is given valid base64, attempting to delete some nonexistent
// certificate will "succeed" (it'll do nothing).
- await removeCertByHash(btoa("thishashisthewrongsize"));
+ await removeCertsByHashes([btoa("thishashisthewrongsize")]);
- await addCertBySubject("removal certificate bytes 1", "common subject to remove");
- await addCertBySubject("removal certificate bytes 2", "common subject to remove");
- await addCertBySubject("removal certificate bytes 3", "common subject to remove");
+ let removalCert1 = new CertInfo("removal certificate bytes 1", "common subject to remove");
+ let removalCert2 = new CertInfo("removal certificate bytes 2", "common subject to remove");
+ let removalCert3 = new CertInfo("removal certificate bytes 3", "common subject to remove");
+ await addCerts([removalCert1, removalCert2, removalCert3]);
let storedCerts = certStorage.findCertsBySubject(stringToArray("common subject to remove"));
let storedCertsAsStrings = storedCerts.map(arrayToString);
@@ -110,7 +124,7 @@ add_task({
"should find expected certs before removing them");
// echo -n "removal certificate bytes 2" | sha256sum | xxd -r -p | base64
- await removeCertByHash("2nUPHwl5TVr1mAD1FU9FivLTlTb0BAdnVUhsYgBccN4=");
+ await removeCertsByHashes(["2nUPHwl5TVr1mAD1FU9FivLTlTb0BAdnVUhsYgBccN4="]);
storedCerts = certStorage.findCertsBySubject(stringToArray("common subject to remove"));
storedCertsAsStrings = storedCerts.map(arrayToString);
expectedCerts = ["removal certificate bytes 1", "removal certificate bytes 3"];
@@ -118,7 +132,7 @@ add_task({
"should only have first and third certificates now");
// echo -n "removal certificate bytes 1" | sha256sum | xxd -r -p | base64
- await removeCertByHash("8zoRqHYrklr7Zx6UWpzrPuL+ol8KL1Ml6XHBQmXiaTY=");
+ await removeCertsByHashes(["8zoRqHYrklr7Zx6UWpzrPuL+ol8KL1Ml6XHBQmXiaTY="]);
storedCerts = certStorage.findCertsBySubject(stringToArray("common subject to remove"));
storedCertsAsStrings = storedCerts.map(arrayToString);
expectedCerts = ["removal certificate bytes 3"];
@@ -126,11 +140,34 @@ add_task({
"should only have third certificate now");
// echo -n "removal certificate bytes 3" | sha256sum | xxd -r -p | base64
- await removeCertByHash("vZn7GwDSabB/AVo0T+N26nUsfSXIIx4NgQtSi7/0p/w=");
+ await removeCertsByHashes(["vZn7GwDSabB/AVo0T+N26nUsfSXIIx4NgQtSi7/0p/w="]);
storedCerts = certStorage.findCertsBySubject(stringToArray("common subject to remove"));
Assert.equal(storedCerts.length, 0, "shouldn't have any certificates now");
// echo -n "removal certificate bytes 3" | sha256sum | xxd -r -p | base64
// Again, removing a nonexistent certificate should "succeed".
- await removeCertByHash("vZn7GwDSabB/AVo0T+N26nUsfSXIIx4NgQtSi7/0p/w=");
+ await removeCertsByHashes(["vZn7GwDSabB/AVo0T+N26nUsfSXIIx4NgQtSi7/0p/w="]);
+});
+
+add_task({
+ skip_if: () => !AppConstants.MOZ_NEW_CERT_STORAGE,
+}, async function test_batched_removal() {
+ let removalCert1 = new CertInfo("batch removal certificate bytes 1", "batch subject to remove");
+ let removalCert2 = new CertInfo("batch removal certificate bytes 2", "batch subject to remove");
+ let removalCert3 = new CertInfo("batch removal certificate bytes 3", "batch subject to remove");
+ await addCerts([removalCert1, removalCert2, removalCert3]);
+ let storedCerts = certStorage.findCertsBySubject(stringToArray("batch subject to remove"));
+ let storedCertsAsStrings = storedCerts.map(arrayToString);
+ let expectedCerts = ["batch removal certificate bytes 1", "batch removal certificate bytes 2",
+ "batch removal certificate bytes 3"];
+ Assert.deepEqual(storedCertsAsStrings.sort(), expectedCerts.sort(),
+ "should find expected certs before removing them");
+ // echo -n "batch removal certificate bytes 1" | sha256sum | xxd -r -p | base64
+ // echo -n "batch removal certificate bytes 2" | sha256sum | xxd -r -p | base64
+ // echo -n "batch removal certificate bytes 3" | sha256sum | xxd -r -p | base64
+ await removeCertsByHashes(["EOEEUTuanHZX9NFVCoMKVT22puIJC6g+ZuNPpJgvaa8=",
+ "Xz6h/Kvn35cCLJEZXkjPqk1GG36b56sreLyAXpO+0zg=",
+ "Jr7XdiTT8ZONUL+ogNNMW2oxKxanvYOLQPKBPgH/has="]);
+ storedCerts = certStorage.findCertsBySubject(stringToArray("batch subject to remove"));
+ Assert.equal(storedCerts.length, 0, "shouldn't have any certificates now");
});
diff --git a/services/common/blocklist-clients.js b/services/common/blocklist-clients.js
index 80c850847df8..12a70171f4f1 100644
--- a/services/common/blocklist-clients.js
+++ b/services/common/blocklist-clients.js
@@ -182,71 +182,6 @@ async function updatePinningList({ data: { current: records } }) {
}
}
-/**
- * This custom filter function is used to limit the entries returned
- * by `RemoteSettings("...").get()` depending on the target app information
- * defined on entries.
- *
- * Note that this is async because `jexlFilterFunc` is async.
- */
-async function targetAppFilter(entry, environment) {
- // If the entry has a JEXL filter expression, it should prevail.
- // The legacy target app mechanism will be kept in place for old entries.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=1463377
- const { filter_expression } = entry;
- if (filter_expression) {
- return jexlFilterFunc(entry, environment);
- }
-
- // Keep entries without target information.
- if (!("versionRange" in entry)) {
- return entry;
- }
-
- const { appID, version: appVersion, toolkitVersion } = environment;
- const { versionRange } = entry;
-
- // Everywhere in this method, we avoid checking the minVersion, because
- // we want to retain items whose minVersion is higher than the current
- // app version, so that we have the items around for app updates.
-
- // Gfx blocklist has a specific versionRange object, which is not a list.
- if (!Array.isArray(versionRange)) {
- const { maxVersion = "*" } = versionRange;
- const matchesRange = (Services.vc.compare(appVersion, maxVersion) <= 0);
- return matchesRange ? entry : null;
- }
-
- // Iterate the targeted applications, at least one of them must match.
- // If no target application, keep the entry.
- if (versionRange.length == 0) {
- return entry;
- }
- for (const vr of versionRange) {
- const { targetApplication = [] } = vr;
- if (targetApplication.length == 0) {
- return entry;
- }
- for (const ta of targetApplication) {
- const { guid } = ta;
- if (!guid) {
- return entry;
- }
- const { maxVersion = "*" } = ta;
- if (guid == appID &&
- Services.vc.compare(appVersion, maxVersion) <= 0) {
- return entry;
- }
- if (guid == "toolkit@mozilla.org" &&
- Services.vc.compare(toolkitVersion, maxVersion) <= 0) {
- return entry;
- }
- }
- }
- // Skip this entry.
- return null;
-}
-
var OneCRLBlocklistClient;
var PinningBlocklistClient;
var RemoteSecuritySettingsClient;
@@ -291,5 +226,5 @@ function initialize(options = {}) {
};
}
-let BlocklistClients = {initialize, targetAppFilter};
+let BlocklistClients = {initialize};
diff --git a/servo/components/style/properties/data.py b/servo/components/style/properties/data.py
index ae3070776903..82a98d60d7bd 100644
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -172,7 +172,7 @@ class Longhand(object):
gecko_ffi_name=None,
allowed_in_keyframe_block=True, cast_type='u8',
logical=False, logical_group=None, alias=None, extra_prefixes=None, boxed=False,
- flags=None, allowed_in_page_rule=False, allow_quirks=False,
+ flags=None, allowed_in_page_rule=False, allow_quirks="No",
ignored_when_colors_disabled=False,
vector=False, servo_restyle_damage="repaint"):
self.name = name
diff --git a/servo/components/style/properties/helpers.mako.rs b/servo/components/style/properties/helpers.mako.rs
index 8310d537f36d..9b63ca8465cf 100644
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -10,7 +10,7 @@
<%def name="predefined_type(name, type, initial_value, parse_method='parse',
needs_context=True, vector=False,
computed_type=None, initial_specified_value=None,
- allow_quirks=False, allow_empty=False, **kwargs)">
+ allow_quirks='No', allow_empty=False, **kwargs)">
<%def name="predefined_type_inner(name, type, initial_value, parse_method)">
#[allow(unused_imports)]
use app_units::Au;
@@ -42,8 +42,8 @@
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result> {
- % if allow_quirks:
- specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::Yes)
+ % if allow_quirks != "No":
+ specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::${allow_quirks})
% elif needs_context:
specified::${type}::${parse_method}(context, input)
% else:
@@ -405,8 +405,8 @@
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result> {
- % if property.allow_quirks:
- parse_quirky(context, input, specified::AllowQuirks::Yes)
+ % if property.allow_quirks != "No":
+ parse_quirky(context, input, specified::AllowQuirks::${property.allow_quirks})
% else:
parse(context, input)
% endif
@@ -868,7 +868,7 @@
%def>
<%def name="four_sides_shorthand(name, sub_property_pattern, parser_function,
- needs_context=True, allow_quirks=False, **kwargs)">
+ needs_context=True, allow_quirks='No', **kwargs)">
<% sub_properties=' '.join(sub_property_pattern % side for side in PHYSICAL_SIDES) %>
<%call expr="self.shorthand(name, sub_properties=sub_properties, **kwargs)">
#[allow(unused_imports)]
@@ -881,8 +881,8 @@
input: &mut Parser<'i, 't>,
) -> Result> {
let rect = Rect::parse_with(context, input, |_c, i| {
- % if allow_quirks:
- ${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
+ % if allow_quirks != "No":
+ ${parser_function}_quirky(_c, i, specified::AllowQuirks::${allow_quirks})
% elif needs_context:
${parser_function}(_c, i)
% else:
diff --git a/servo/components/style/properties/longhands/background.mako.rs b/servo/components/style/properties/longhands/background.mako.rs
index 42344a18cb9c..9c66e4676f96 100644
--- a/servo/components/style/properties/longhands/background.mako.rs
+++ b/servo/components/style/properties/longhands/background.mako.rs
@@ -14,7 +14,7 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-backgrounds/#background-color",
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
- allow_quirks=True,
+ allow_quirks="Yes",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
CAN_ANIMATE_ON_COMPOSITOR",
)}
diff --git a/servo/components/style/properties/longhands/border.mako.rs b/servo/components/style/properties/longhands/border.mako.rs
index 13a7f2373501..7ea8b8dd0eb3 100644
--- a/servo/components/style/properties/longhands/border.mako.rs
+++ b/servo/components/style/properties/longhands/border.mako.rs
@@ -28,7 +28,7 @@
animation_value_type="AnimatedColor",
logical=is_logical,
logical_group="border-color",
- allow_quirks=not is_logical,
+ allow_quirks="No" if is_logical else "Yes",
flags="APPLIES_TO_FIRST_LETTER",
ignored_when_colors_disabled=True,
)}
@@ -56,7 +56,7 @@
logical=is_logical,
logical_group="border-width",
flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH",
- allow_quirks=not is_logical,
+ allow_quirks="No" if is_logical else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
% endfor
diff --git a/servo/components/style/properties/longhands/effects.mako.rs b/servo/components/style/properties/longhands/effects.mako.rs
index 0b3f96f0dde3..63db3a64348c 100644
--- a/servo/components/style/properties/longhands/effects.mako.rs
+++ b/servo/components/style/properties/longhands/effects.mako.rs
@@ -37,7 +37,7 @@ ${helpers.predefined_type(
"computed::ClipRectOrAuto::auto()",
animation_value_type="ComputedValue",
boxed=True,
- allow_quirks=True,
+ allow_quirks="Yes",
spec="https://drafts.fxtf.org/css-masking/#clip-property",
)}
diff --git a/servo/components/style/properties/longhands/font.mako.rs b/servo/components/style/properties/longhands/font.mako.rs
index c1d3d8fcc6c3..8d84ef34cb3c 100644
--- a/servo/components/style/properties/longhands/font.mako.rs
+++ b/servo/components/style/properties/longhands/font.mako.rs
@@ -64,7 +64,7 @@ ${helpers.predefined_type(
initial_value="computed::FontSize::medium()",
initial_specified_value="specified::FontSize::medium()",
animation_value_type="NonNegativeLength",
- allow_quirks=True,
+ allow_quirks="Yes",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size",
servo_restyle_damage="rebuild_and_reflow",
diff --git a/servo/components/style/properties/longhands/inherited_text.mako.rs b/servo/components/style/properties/longhands/inherited_text.mako.rs
index cdd7df932560..8a3803045046 100644
--- a/servo/components/style/properties/longhands/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhands/inherited_text.mako.rs
@@ -56,7 +56,7 @@ ${helpers.predefined_type(
"computed::LengthPercentage::zero()",
animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-text/#propdef-text-indent",
- allow_quirks=True,
+ allow_quirks="Yes",
servo_restyle_damage = "reflow",
)}
diff --git a/servo/components/style/properties/longhands/margin.mako.rs b/servo/components/style/properties/longhands/margin.mako.rs
index d2a3be11d1d2..c3289c34b7cb 100644
--- a/servo/components/style/properties/longhands/margin.mako.rs
+++ b/servo/components/style/properties/longhands/margin.mako.rs
@@ -17,7 +17,7 @@
"LengthPercentageOrAuto",
"computed::LengthPercentageOrAuto::zero()",
alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"),
- allow_quirks=not side[1],
+ allow_quirks="No" if side[1] else "Yes",
animation_value_type="ComputedValue",
logical=side[1],
logical_group="margin",
diff --git a/servo/components/style/properties/longhands/padding.mako.rs b/servo/components/style/properties/longhands/padding.mako.rs
index a1262aee0fce..6142bbf901ec 100644
--- a/servo/components/style/properties/longhands/padding.mako.rs
+++ b/servo/components/style/properties/longhands/padding.mako.rs
@@ -24,7 +24,7 @@
logical_group="padding",
spec=spec,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH",
- allow_quirks=not side[1],
+ allow_quirks="No" if side[1] else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
% endfor
diff --git a/servo/components/style/properties/longhands/position.mako.rs b/servo/components/style/properties/longhands/position.mako.rs
index 096349f4b1cf..34216385feda 100644
--- a/servo/components/style/properties/longhands/position.mako.rs
+++ b/servo/components/style/properties/longhands/position.mako.rs
@@ -17,7 +17,7 @@
spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side,
flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue",
- allow_quirks=True,
+ allow_quirks="Yes",
servo_restyle_damage="reflow_out_of_flow",
logical_group="inset",
)}
@@ -253,7 +253,7 @@ ${helpers.predefined_type(
"computed::Size::auto()",
logical=logical,
logical_group="size",
- allow_quirks=not logical,
+ allow_quirks="No" if logical else "Yes",
spec=spec % size,
animation_value_type="Size",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
@@ -266,7 +266,7 @@ ${helpers.predefined_type(
"computed::Size::auto()",
logical=logical,
logical_group="min-size",
- allow_quirks=not logical,
+ allow_quirks="No" if logical else "Yes",
spec=spec % size,
animation_value_type="Size",
servo_restyle_damage="reflow",
@@ -277,7 +277,7 @@ ${helpers.predefined_type(
"computed::MaxSize::none()",
logical=logical,
logical_group="max-size",
- allow_quirks=not logical,
+ allow_quirks="No" if logical else "Yes",
spec=spec % size,
animation_value_type="MaxSize",
servo_restyle_damage="reflow",
diff --git a/servo/components/style/properties/longhands/svg.mako.rs b/servo/components/style/properties/longhands/svg.mako.rs
index 3e4d207397ac..8e93d03dbb1b 100644
--- a/servo/components/style/properties/longhands/svg.mako.rs
+++ b/servo/components/style/properties/longhands/svg.mako.rs
@@ -191,3 +191,66 @@ ${helpers.predefined_type(
animation_value_type="discrete",
flags="CREATES_STACKING_CONTEXT",
)}
+
+${helpers.predefined_type(
+ "x",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#X",
+)}
+
+${helpers.predefined_type(
+ "y",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#Y",
+)}
+
+${helpers.predefined_type(
+ "cx",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#CX",
+)}
+
+${helpers.predefined_type(
+ "cy",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#CY",
+)}
+
+${helpers.predefined_type(
+ "rx",
+ "NonNegativeLengthPercentageOrAuto",
+ "computed::NonNegativeLengthPercentageOrAuto::auto()",
+ products="gecko",
+ animation_value_type="LengthPercentageOrAuto",
+ spec="https://svgwg.org/svg2-draft/geometry.html#RX",
+)}
+
+${helpers.predefined_type(
+ "ry",
+ "NonNegativeLengthPercentageOrAuto",
+ "computed::NonNegativeLengthPercentageOrAuto::auto()",
+ products="gecko",
+ animation_value_type="LengthPercentageOrAuto",
+ spec="https://svgwg.org/svg2-draft/geometry.html#RY",
+)}
+
+${helpers.predefined_type(
+ "r",
+ "NonNegativeLengthPercentage",
+ "computed::NonNegativeLengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="LengthPercentage",
+ spec="https://svgwg.org/svg2-draft/geometry.html#R",
+)}
diff --git a/servo/components/style/properties/shorthands/border.mako.rs b/servo/components/style/properties/shorthands/border.mako.rs
index cd4720687935..1f8df0df6a12 100644
--- a/servo/components/style/properties/shorthands/border.mako.rs
+++ b/servo/components/style/properties/shorthands/border.mako.rs
@@ -7,7 +7,7 @@
${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::Color::parse",
spec="https://drafts.csswg.org/css-backgrounds/#border-color",
- allow_quirks=True)}
+ allow_quirks="Yes")}
${helpers.four_sides_shorthand(
"border-style",
diff --git a/servo/components/style/properties/shorthands/margin.mako.rs b/servo/components/style/properties/shorthands/margin.mako.rs
index fd3124a6ae15..9b996abbe86b 100644
--- a/servo/components/style/properties/shorthands/margin.mako.rs
+++ b/servo/components/style/properties/shorthands/margin.mako.rs
@@ -10,7 +10,7 @@ ${helpers.four_sides_shorthand(
"specified::LengthPercentageOrAuto::parse",
spec="https://drafts.csswg.org/css-box/#propdef-margin",
allowed_in_page_rule=True,
- allow_quirks=True,
+ allow_quirks="Yes",
)}
${helpers.two_properties_shorthand(
diff --git a/servo/components/style/properties/shorthands/padding.mako.rs b/servo/components/style/properties/shorthands/padding.mako.rs
index a4e013caabc3..8d50c3b9e38d 100644
--- a/servo/components/style/properties/shorthands/padding.mako.rs
+++ b/servo/components/style/properties/shorthands/padding.mako.rs
@@ -9,7 +9,7 @@ ${helpers.four_sides_shorthand(
"padding-%s",
"specified::NonNegativeLengthPercentage::parse",
spec="https://drafts.csswg.org/css-box-3/#propdef-padding",
- allow_quirks=True,
+ allow_quirks="Yes",
)}
${helpers.two_properties_shorthand(
diff --git a/servo/components/style/properties/shorthands/position.mako.rs b/servo/components/style/properties/shorthands/position.mako.rs
index 6fdbe1235cff..63298b86ba12 100644
--- a/servo/components/style/properties/shorthands/position.mako.rs
+++ b/servo/components/style/properties/shorthands/position.mako.rs
@@ -768,7 +768,7 @@ ${helpers.four_sides_shorthand(
"%s",
"specified::LengthPercentageOrAuto::parse",
spec="https://drafts.csswg.org/css-logical/#propdef-inset",
- allow_quirks=False,
+ allow_quirks="No",
)}
${helpers.two_properties_shorthand(
diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs
index bda1dd711003..e995731aeccd 100644
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -4513,7 +4513,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
use style::properties::longhands::_moz_script_min_size::SpecifiedValue as MozScriptMinSize;
use style::properties::PropertyDeclaration;
use style::values::generics::NonNegative;
- use style::values::generics::length::Size;
+ use style::values::generics::length::{Size, LengthPercentageOrAuto};
use style::values::specified::length::NoCalcLength;
use style::values::specified::length::{AbsoluteLength, FontRelativeLength};
use style::values::specified::length::LengthPercentage;
@@ -4542,6 +4542,14 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
let prop = match_wrap_declared! { long,
Width => Size::LengthPercentage(NonNegative(LengthPercentage::Length(nocalc))),
+ Height => Size::LengthPercentage(NonNegative(LengthPercentage::Length(nocalc))),
+ X => LengthPercentage::Length(nocalc),
+ Y => LengthPercentage::Length(nocalc),
+ Cx => LengthPercentage::Length(nocalc),
+ Cy => LengthPercentage::Length(nocalc),
+ R => NonNegative(LengthPercentage::Length(nocalc)),
+ Rx => LengthPercentageOrAuto::LengthPercentage(NonNegative(LengthPercentage::Length(nocalc))),
+ Ry => LengthPercentageOrAuto::LengthPercentage(NonNegative(LengthPercentage::Length(nocalc))),
FontSize => LengthPercentage::from(nocalc).into(),
MozScriptMinSize => MozScriptMinSize(nocalc),
};
@@ -4592,6 +4600,13 @@ pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(
let prop = match_wrap_declared! { long,
Height => Size::LengthPercentage(NonNegative(lp)),
Width => Size::LengthPercentage(NonNegative(lp)),
+ X => lp,
+ Y => lp,
+ Cx => lp,
+ Cy => lp,
+ R => NonNegative(lp),
+ Rx => LengthPercentageOrAuto::LengthPercentage(NonNegative(lp)),
+ Ry => LengthPercentageOrAuto::LengthPercentage(NonNegative(lp)),
MarginTop => lp_or_auto,
MarginRight => lp_or_auto,
MarginBottom => lp_or_auto,
diff --git a/taskcluster/ci/build/windows.yml b/taskcluster/ci/build/windows.yml
index 6827a32e8992..cc211ab81c0f 100755
--- a/taskcluster/ci/build/windows.yml
+++ b/taskcluster/ci/build/windows.yml
@@ -270,6 +270,7 @@ win32-shippable/opt:
nightly: true
beta: true
release: true
+ esr.*: false
default:
by-project:
# browser/confvars.sh looks for nightly-try
diff --git a/taskcluster/ci/config.yml b/taskcluster/ci/config.yml
index 2b8a2826f79a..3e0119785044 100755
--- a/taskcluster/ci/config.yml
+++ b/taskcluster/ci/config.yml
@@ -264,7 +264,7 @@ partner-urls:
task-priority:
by-project:
'mozilla-release': 'highest'
- 'mozilla-esr60': 'very-high'
+ 'mozilla-esr.*': 'very-high'
'mozilla-beta': 'high'
'mozilla-central': 'medium'
'autoland': 'low'
diff --git a/taskcluster/ci/release-early-tagging/kind.yml b/taskcluster/ci/release-early-tagging/kind.yml
index 64de0ebae547..6e7622a2f8cc 100644
--- a/taskcluster/ci/release-early-tagging/kind.yml
+++ b/taskcluster/ci/release-early-tagging/kind.yml
@@ -27,10 +27,7 @@ job-defaults:
dontbuild: true
push:
by-project:
- mozilla-beta: true
- mozilla-release: true
- mozilla-esr52: true
- mozilla-esr60: true
+ mozilla-(beta|release|esr.*): true
maple: true
birch: true
default: false
diff --git a/taskcluster/ci/release-notify-promote/kind.yml b/taskcluster/ci/release-notify-promote/kind.yml
index 37058f14fb72..c7a29b98e559 100644
--- a/taskcluster/ci/release-notify-promote/kind.yml
+++ b/taskcluster/ci/release-notify-promote/kind.yml
@@ -34,9 +34,7 @@ job-defaults:
message: "{task[shipping-product]} {release_config[version]} build{release_config[build_number]}/{config[params][project]} is in the candidates directory"
emails:
by-project:
- mozilla-beta: ["release-signoff@mozilla.org"]
- mozilla-release: ["release-signoff@mozilla.org"]
- mozilla-esr60: ["release-signoff@mozilla.org"]
+ mozilla-(beta|release|esr.*): ["release-signoff@mozilla.org"]
try: ["{config[params][owner]}"]
default: []
diff --git a/taskcluster/ci/release-notify-push/kind.yml b/taskcluster/ci/release-notify-push/kind.yml
index 28e09e6b6d39..8e050ae2450c 100644
--- a/taskcluster/ci/release-notify-push/kind.yml
+++ b/taskcluster/ci/release-notify-push/kind.yml
@@ -32,9 +32,7 @@ job-defaults:
message: "{task[shipping-product]} {release_config[version]} build{release_config[build_number]}/{config[params][project]} has been pushed to cdntest"
emails:
by-project:
- mozilla-beta: ["release-signoff@mozilla.org"]
- mozilla-release: ["release-signoff@mozilla.org"]
- mozilla-esr60: ["release-signoff@mozilla.org"]
+ mozilla-(beta|release|esr.*): ["release-signoff@mozilla.org"]
try: ["{config[params][owner]}"]
default: []
diff --git a/taskcluster/ci/release-notify-ship/kind.yml b/taskcluster/ci/release-notify-ship/kind.yml
index dbc744e24558..a7cb09ca71dd 100644
--- a/taskcluster/ci/release-notify-ship/kind.yml
+++ b/taskcluster/ci/release-notify-ship/kind.yml
@@ -34,9 +34,7 @@ job-defaults:
notifications:
emails:
by-project:
- mozilla-beta: ["release-signoff@mozilla.org"]
- mozilla-release: ["release-signoff@mozilla.org"]
- mozilla-esr60: ["release-signoff@mozilla.org"]
+ mozilla-(beta|release|esr.*): ["release-signoff@mozilla.org"]
try: ["{config[params][owner]}"]
default: []
diff --git a/taskcluster/ci/release-notify-started/kind.yml b/taskcluster/ci/release-notify-started/kind.yml
index a7be076eed13..f2c772e2e5b8 100644
--- a/taskcluster/ci/release-notify-started/kind.yml
+++ b/taskcluster/ci/release-notify-started/kind.yml
@@ -21,9 +21,7 @@ job-defaults:
max-run-time: 600
emails:
by-project:
- mozilla-beta: ["release-signoff@mozilla.org"]
- mozilla-release: ["release-signoff@mozilla.org"]
- mozilla-esr60: ["release-signoff@mozilla.org"]
+ mozilla-(beta|release|esr.*): ["release-signoff@mozilla.org"]
try: ["{config[params][owner]}"]
default: []
diff --git a/taskcluster/ci/release-secondary-update-verify-config/kind.yml b/taskcluster/ci/release-secondary-update-verify-config/kind.yml
index 5031c8d4fadf..25b68a18eab1 100644
--- a/taskcluster/ci/release-secondary-update-verify-config/kind.yml
+++ b/taskcluster/ci/release-secondary-update-verify-config/kind.yml
@@ -57,7 +57,7 @@ jobs:
firefox-secondary-linux:
treeherder:
symbol: UVCS
- platform: linux/opt
+ platform: linux-shippable/opt
kind: test
tier: 1
attributes:
@@ -69,7 +69,7 @@ jobs:
firefox-secondary-linux64:
treeherder:
symbol: UVCS
- platform: linux64/opt
+ platform: linux64-shippable/opt
kind: test
tier: 1
attributes:
@@ -93,7 +93,7 @@ jobs:
firefox-secondary-win32:
treeherder:
symbol: UVCS
- platform: win32/opt
+ platform: windows2012-32-shippable/opt
kind: test
tier: 1
attributes:
@@ -105,7 +105,7 @@ jobs:
firefox-secondary-win64:
treeherder:
symbol: UVCS
- platform: win64/opt
+ platform: windows2012-64-shippable/opt
kind: test
tier: 1
attributes:
@@ -117,7 +117,7 @@ jobs:
firefox-secondary-win64-aarch64:
treeherder:
symbol: UVCS
- platform: win64-aarch64/opt
+ platform: windows2012-aarch64-shippable/opt
kind: test
tier: 1
attributes:
diff --git a/taskcluster/ci/release-secondary-update-verify/kind.yml b/taskcluster/ci/release-secondary-update-verify/kind.yml
index c4b158a4c818..de96ce19de72 100644
--- a/taskcluster/ci/release-secondary-update-verify/kind.yml
+++ b/taskcluster/ci/release-secondary-update-verify/kind.yml
@@ -33,6 +33,9 @@ job-defaults:
- 255
env:
CHANNEL: "beta-localtest"
+ treeherder:
+ symbol: UV(UVS)
+ kind: test
extra:
chunks: 12
@@ -40,65 +43,35 @@ jobs:
firefox-secondary-linux64:
description: linux64 secondary channel update verify
shipping-product: firefox
- treeherder:
- symbol: UV(UVS)
- platform: linux64/opt
- kind: test
- tier: 1
attributes:
build_platform: linux64-shippable
firefox-secondary-linux:
description: linux secondary channel update verify
shipping-product: firefox
- treeherder:
- symbol: UV(UVS)
- platform: linux32/opt
- kind: test
- tier: 1
attributes:
build_platform: linux-shippable
firefox-secondary-win64:
description: win64 secondary channel update verify
shipping-product: firefox
- treeherder:
- symbol: UV(UVS)
- platform: windows2012-64/opt
- kind: test
- tier: 1
attributes:
build_platform: win64-shippable
firefox-secondary-win64-aarch64:
description: win64 secondary channel update verify
shipping-product: firefox
- treeherder:
- symbol: UV(UVS)
- platform: windows2012-aarch6464/opt
- kind: test
- tier: 1
attributes:
build_platform: win64-aarch64-shippable
firefox-secondary-win32:
description: win32 secondary channel update verify
shipping-product: firefox
- treeherder:
- symbol: UV(UVS)
- platform: windows2012-32/opt
- kind: test
- tier: 1
attributes:
build_platform: win32-shippable
firefox-secondary-macosx64:
description: macosx64 secondary channel update verify
shipping-product: firefox
- treeherder:
- symbol: UV(UVS)
- platform: osx-cross/opt
- kind: test
- tier: 1
attributes:
build_platform: macosx64-shippable
diff --git a/taskcluster/ci/release-update-verify-config/kind.yml b/taskcluster/ci/release-update-verify-config/kind.yml
index 5a856951d6d6..be734f98b921 100644
--- a/taskcluster/ci/release-update-verify-config/kind.yml
+++ b/taskcluster/ci/release-update-verify-config/kind.yml
@@ -52,7 +52,7 @@ job-defaults:
by-release-type:
beta: beta
release(-rc)?: nonbeta
- esr60: esr
+ esr.*: esr
default: beta
last-watershed:
by-release-type:
@@ -77,7 +77,7 @@ jobs:
shipping-product: firefox
treeherder:
symbol: UVC
- platform: linux32/opt
+ platform: linux32-shippable/opt
kind: test
tier: 1
attributes:
@@ -90,7 +90,7 @@ jobs:
by-release-type:
beta: "beta-localtest"
release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
+ esr.*: "esr-localtest"
default: "default"
mar-channel-id-override:
by-release-type:
@@ -101,7 +101,7 @@ jobs:
shipping-product: firefox
treeherder:
symbol: UVC
- platform: linux64/opt
+ platform: linux64-shippable/opt
kind: test
tier: 1
attributes:
@@ -114,7 +114,7 @@ jobs:
by-release-type:
beta: "beta-localtest"
release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
+ esr.*: "esr-localtest"
default: "default"
mar-channel-id-override:
by-release-type:
@@ -125,7 +125,7 @@ jobs:
shipping-product: firefox
treeherder:
symbol: UVC
- platform: osx-cross/opt
+ platform: osx-shippable/opt
kind: test
tier: 1
attributes:
@@ -138,7 +138,7 @@ jobs:
by-release-type:
beta: "beta-localtest"
release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
+ esr.*: "esr-localtest"
default: "default"
mar-channel-id-override:
by-release-type:
@@ -149,7 +149,7 @@ jobs:
shipping-product: firefox
treeherder:
symbol: UVC
- platform: windows2012-32/opt
+ platform: windows2012-32-shippable/opt
kind: test
tier: 1
attributes:
@@ -162,7 +162,7 @@ jobs:
by-release-type:
beta: "beta-localtest"
release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
+ esr.*: "esr-localtest"
default: "default"
mar-channel-id-override:
by-release-type:
@@ -173,7 +173,7 @@ jobs:
shipping-product: firefox
treeherder:
symbol: UVC
- platform: windows2012-64/opt
+ platform: windows2012-64-shippable/opt
kind: test
tier: 1
attributes:
@@ -186,7 +186,7 @@ jobs:
by-release-type:
beta: "beta-localtest"
release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
+ esr.*: "esr-localtest"
default: "default"
mar-channel-id-override:
by-release-type:
@@ -197,7 +197,7 @@ jobs:
shipping-product: firefox
treeherder:
symbol: UVC
- platform: windows2012-aarch64/opt
+ platform: windows2012-aarch64-shippable/opt
kind: test
tier: 1
attributes:
@@ -210,7 +210,7 @@ jobs:
by-release-type:
beta: "beta-localtest"
release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
+ esr.*: "esr-localtest"
default: "default"
mar-channel-id-override:
by-release-type:
diff --git a/taskcluster/ci/release-update-verify/kind.yml b/taskcluster/ci/release-update-verify/kind.yml
index 94c8f8d938ce..5c0dee05b112 100644
--- a/taskcluster/ci/release-update-verify/kind.yml
+++ b/taskcluster/ci/release-update-verify/kind.yml
@@ -31,6 +31,9 @@ job-defaults:
max-run-time: 5400
retry-exit-status:
- 255
+ treeherder:
+ symbol: UV(UV)
+ kind: test
extra:
chunks: 16
@@ -38,203 +41,71 @@ jobs:
firefox-linux64:
description: linux64 update verify
shipping-product: firefox
- worker:
- env:
- CHANNEL:
- by-release-type:
- beta: "beta-localtest"
- release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
- nightly: "nightly"
- default: "default"
- treeherder:
- symbol: UV(UV)
- platform: linux64/opt
- kind: test
- tier: 1
attributes:
build_platform: linux64-shippable
firefox-linux:
description: linux update verify
shipping-product: firefox
- worker:
- env:
- CHANNEL:
- by-release-type:
- beta: "beta-localtest"
- release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
- nightly: "nightly"
- default: "default"
- treeherder:
- symbol: UV(UV)
- platform: linux32/opt
- kind: test
- tier: 1
attributes:
build_platform: linux-shippable
firefox-win64:
description: win64 update verify
shipping-product: firefox
- worker:
- env:
- CHANNEL:
- by-release-type:
- beta: "beta-localtest"
- release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
- nightly: "nightly"
- default: "default"
- treeherder:
- symbol: UV(UV)
- platform: windows2012-64/opt
- kind: test
- tier: 1
attributes:
build_platform: win64-shippable
firefox-win64-aarch64:
description: win64-aarch64 update verify
shipping-product: firefox
- worker:
- env:
- CHANNEL:
- by-release-type:
- beta: "beta-localtest"
- release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
- nightly: "nightly"
- default: "default"
- treeherder:
- symbol: UV(UV)
- platform: windows2012-aarch64/opt
- kind: test
- tier: 1
attributes:
build_platform: win64-aarch64-shippable
firefox-win32:
description: win32 update verify
shipping-product: firefox
- worker:
- env:
- CHANNEL:
- by-release-type:
- beta: "beta-localtest"
- release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
- nightly: "nightly"
- default: "default"
- treeherder:
- symbol: UV(UV)
- platform: windows2012-32/opt
- kind: test
- tier: 1
attributes:
build_platform: win32-shippable
firefox-macosx64:
description: macosx64 update verify
shipping-product: firefox
- worker:
- env:
- CHANNEL:
- by-release-type:
- beta: "beta-localtest"
- release(-rc)?: "release-localtest"
- esr60: "esr-localtest"
- nightly: "nightly"
- default: "default"
- treeherder:
- symbol: UV(UV)
- platform: osx-cross/opt
- kind: test
- tier: 1
attributes:
build_platform: macosx64-shippable
devedition-linux64:
description: linux64 update verify
shipping-product: devedition
- worker:
- env:
- CHANNEL: "aurora-localtest"
- treeherder:
- symbol: UV(UV)
- platform: linux64-devedition/opt
- kind: test
- tier: 1
attributes:
build_platform: linux64-devedition-nightly
devedition-linux:
description: linux update verify
shipping-product: devedition
- worker:
- env:
- CHANNEL: "aurora-localtest"
- treeherder:
- symbol: UV(UV)
- platform: linux32-devedition/opt
- kind: test
- tier: 1
attributes:
build_platform: linux-devedition-nightly
devedition-win64:
description: win64 update verify
shipping-product: devedition
- worker:
- env:
- CHANNEL: "aurora-localtest"
- treeherder:
- symbol: UV(UV)
- platform: windows2012-64-devedition/opt
- kind: test
- tier: 1
attributes:
build_platform: win64-devedition-nightly
devedition-win64-aarch64:
description: win64-aarch64 update verify
shipping-product: devedition
- worker:
- env:
- CHANNEL: "aurora-localtest"
- treeherder:
- symbol: UV(UV)
- platform: windows2012-aarch64-devedition/opt
- kind: test
- tier: 1
attributes:
build_platform: win64-aarch64-devedition-nightly
devedition-win32:
description: win32 update verify
shipping-product: devedition
- worker:
- env:
- CHANNEL: "aurora-localtest"
- treeherder:
- symbol: UV(UV)
- platform: windows2012-32-devedition/opt
- kind: test
- tier: 1
attributes:
build_platform: win32-devedition-nightly
devedition-macosx64:
description: macosx64 update verify
shipping-product: devedition
- worker:
- env:
- CHANNEL: "aurora-localtest"
- treeherder:
- symbol: UV(UV)
- platform: osx-cross-devedition/opt
- kind: test
- tier: 1
attributes:
build_platform: macosx64-devedition-nightly
diff --git a/taskcluster/ci/release-version-bump/kind.yml b/taskcluster/ci/release-version-bump/kind.yml
index e1463748f46d..ce6d0c13a00c 100644
--- a/taskcluster/ci/release-version-bump/kind.yml
+++ b/taskcluster/ci/release-version-bump/kind.yml
@@ -31,15 +31,7 @@ job-defaults:
bump-files:
by-project:
default: ["browser/config/version_display.txt"]
- mozilla-release:
- - "browser/config/version.txt"
- - "browser/config/version_display.txt"
- - "config/milestone.txt"
- mozilla-esr52:
- - "browser/config/version.txt"
- - "browser/config/version_display.txt"
- - "config/milestone.txt"
- mozilla-esr60:
+ mozilla-(release|esr.*):
- "browser/config/version.txt"
- "browser/config/version_display.txt"
- "config/milestone.txt"
@@ -49,10 +41,7 @@ job-defaults:
- "config/milestone.txt"
push:
by-project:
- mozilla-beta: true
- mozilla-release: true
- mozilla-esr52: true
- mozilla-esr60: true
+ mozilla-(beta|release|esr.*): true
maple: true
birch: true
jamun: true
diff --git a/taskcluster/ci/repo-update/kind.yml b/taskcluster/ci/repo-update/kind.yml
index 5b6a097b1be4..2d7846b634b4 100644
--- a/taskcluster/ci/repo-update/kind.yml
+++ b/taskcluster/ci/repo-update/kind.yml
@@ -14,35 +14,23 @@ job-defaults:
env:
DO_HSTS:
by-project:
- mozilla-central: "1"
- mozilla-esr60: "1"
- mozilla-beta: "1"
+ mozilla-(central|beta|esr.*): "1"
default: ""
DO_HPKP:
by-project:
- mozilla-central: "1"
- mozilla-esr60: "1"
- mozilla-beta: "1"
+ mozilla-(central|beta|esr.*): "1"
default: ""
DO_BLOCKLIST:
by-project:
- mozilla-central: "1"
- mozilla-esr60: "1"
- mozilla-beta: "1"
- mozilla-release: "1"
+ mozilla-(central|beta|release|esr.*): "1"
default: ""
DO_REMOTE_SETTINGS:
by-project:
- mozilla-central: "1"
- mozilla-esr60: "1"
- mozilla-beta: "1"
- mozilla-release: "1"
+ mozilla-(central|beta|release|esr.*): "1"
default: ""
DO_SUFFIX_LIST:
by-project:
- mozilla-central: "1"
- mozilla-esr60: "1"
- mozilla-beta: "1"
+ mozilla-(central|beta|esr.*): "1"
default: ""
USE_MOZILLA_CENTRAL:
by-project:
diff --git a/taskcluster/docs/parameters.rst b/taskcluster/docs/parameters.rst
index 10120432b2bf..fa9d16678468 100644
--- a/taskcluster/docs/parameters.rst
+++ b/taskcluster/docs/parameters.rst
@@ -156,7 +156,7 @@ Release Promotion
Specify the next version for version bump tasks.
``release_type``
- The type of release being promoted. One of "nightly", "beta", "esr60", "release-rc", or "release".
+ The type of release being promoted. One of "nightly", "beta", "esr60", "esr68", "release-rc", or "release".
``release_eta``
The time and date when a release is scheduled to live. This value is passed to Balrog.
diff --git a/taskcluster/scripts/run-task b/taskcluster/scripts/run-task
index 0f8d7007f069..98c57bdebdcc 100755
--- a/taskcluster/scripts/run-task
+++ b/taskcluster/scripts/run-task
@@ -27,6 +27,7 @@ import errno
import io
import json
import os
+import platform
import random
import re
import shutil
@@ -37,7 +38,6 @@ import subprocess
import urllib.error
import urllib.request
-
FINGERPRINT_URL = 'http://taskcluster/secrets/v1/secret/project/taskcluster/gecko/hgfingerprint'
FALLBACK_FINGERPRINT = {
'fingerprints':
@@ -405,7 +405,12 @@ def vcs_checkout(source_repo, dest, store_path,
sys.exit(1)
if IS_MACOSX:
+ release = platform.mac_ver()
+ versionNums = release[0].split('.')[:2]
+ os_version = "%s.%s" % (versionNums[0], versionNums[1])
hg_bin = '/tools/python27-mercurial/bin/hg'
+ if os_version == "10.14":
+ hg_bin = 'hg'
elif IS_POSIX:
hg_bin = 'hg'
elif IS_WINDOWS:
diff --git a/taskcluster/taskgraph/decision.py b/taskcluster/taskgraph/decision.py
index 8fec64cd0794..6dc3dc50fed6 100644
--- a/taskcluster/taskgraph/decision.py
+++ b/taskcluster/taskgraph/decision.py
@@ -82,6 +82,11 @@ PER_PROJECT_PARAMETERS = {
'release_type': 'esr60',
},
+ 'mozilla-esr68': {
+ 'target_tasks_method': 'mozilla_esr68_tasks',
+ 'release_type': 'esr68',
+ },
+
'comm-central': {
'target_tasks_method': 'default',
'release_type': 'nightly',
@@ -97,6 +102,11 @@ PER_PROJECT_PARAMETERS = {
'release_type': 'release',
},
+ 'comm-esr68': {
+ 'target_tasks_method': 'mozilla_esr68_tasks',
+ 'release_type': 'release',
+ },
+
'pine': {
'target_tasks_method': 'pine_tasks',
},
diff --git a/taskcluster/taskgraph/task.py b/taskcluster/taskgraph/task.py
index 74c12c16dc0e..3bdd81667d5f 100644
--- a/taskcluster/taskgraph/task.py
+++ b/taskcluster/taskgraph/task.py
@@ -46,6 +46,15 @@ class Task(object):
def __attrs_post_init__(self):
self.attributes['kind'] = self.kind
+ @property
+ def name(self):
+ if self.label.startswith(self.kind + "-"):
+ return self.label[len(self.kind)+1:]
+ elif self.label.startswith("build-docker-image-"):
+ return self.label[len("build-docker-image-"):]
+ else:
+ raise AttributeError("Task {} does not have a name.".format(self.label))
+
def to_json(self):
rv = {
'kind': self.kind,
diff --git a/taskcluster/taskgraph/test/python.ini b/taskcluster/taskgraph/test/python.ini
index 135961b73a11..f994526162a9 100644
--- a/taskcluster/taskgraph/test/python.ini
+++ b/taskcluster/taskgraph/test/python.ini
@@ -14,6 +14,7 @@ skip-if = python == 3
[test_parameters.py]
[test_target_tasks.py]
[test_taskgraph.py]
+[test_taskcluster_yml.py]
[test_transforms_base.py]
[test_transforms_job.py]
[test_try_option_syntax.py]
diff --git a/taskcluster/taskgraph/test/test_taskcluster_yml.py b/taskcluster/taskgraph/test/test_taskcluster_yml.py
new file mode 100644
index 000000000000..a2e5c6d95147
--- /dev/null
+++ b/taskcluster/taskgraph/test/test_taskcluster_yml.py
@@ -0,0 +1,118 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import, unicode_literals
+
+import jsone
+import pprint
+import slugid
+import unittest
+
+from mozunit import main
+
+from taskgraph.util.yaml import load_yaml
+from taskgraph.util.time import current_json_time
+from taskgraph import GECKO
+
+
+class TestTaskclusterYml(unittest.TestCase):
+
+ taskcluster_yml = load_yaml(GECKO, ".taskcluster.yml")
+
+ def test_push(self):
+ context = {
+ "tasks_for": "hg-push",
+ "push": {
+ "revision": "e8d2d9aff5026ef1f1777b781b47fdcbdb9d8f20",
+ "owner": "dustin@mozilla.com",
+ "pushlog_id": 1556565286,
+ "pushdate": 112957,
+ },
+ "repository": {
+ "url": "https://hg.mozilla.org/mozilla-central",
+ "project": "mozilla-central",
+ "level": "3",
+ },
+ "ownTaskId": slugid.nice().encode("ascii"),
+ }
+ rendered = jsone.render(self.taskcluster_yml, context)
+ pprint.pprint(rendered)
+ self.assertEqual(
+ rendered["tasks"][0]["metadata"]["name"], "Gecko Decision Task"
+ )
+
+ def test_cron(self):
+ context = {
+ "tasks_for": "cron",
+ "repository": {
+ "url": "https://hg.mozilla.org/mozilla-central",
+ "project": "mozilla-central",
+ "level": 3,
+ },
+ "push": {
+ "revision": "e8aebe488b2f2e567940577de25013d00e818f7c",
+ "pushlog_id": -1,
+ "pushdate": 0,
+ "owner": "cron",
+ },
+ "cron": {
+ "task_id": "",
+ "job_name": "test",
+ "job_symbol": "T",
+ "quoted_args": "abc def",
+ },
+ "now": current_json_time(),
+ "ownTaskId": slugid.nice().encode("ascii"),
+ }
+ rendered = jsone.render(self.taskcluster_yml, context)
+ pprint.pprint(rendered)
+ self.assertEqual(
+ rendered["tasks"][0]["metadata"]["name"], "Decision Task for cron job test"
+ )
+
+ def test_action(self):
+ context = {
+ "tasks_for": "action",
+ "repository": {
+ "url": "https://hg.mozilla.org/mozilla-central",
+ "project": "mozilla-central",
+ "level": 3,
+ },
+ "push": {
+ "revision": "e8d2d9aff5026ef1f1777b781b47fdcbdb9d8f20",
+ "owner": "dustin@mozilla.com",
+ "pushlog_id": 1556565286,
+ "pushdate": 112957,
+ },
+ "action": {
+ "name": "test-action",
+ "title": "Test Action",
+ "description": "Just testing",
+ "taskGroupId": slugid.nice().encode("ascii"),
+ "symbol": "t",
+ "repo_scope": "assume:repo:hg.mozilla.org/try:action:generic",
+ "cb_name": "test_action",
+ },
+ "input": {},
+ "parameters": {},
+ "now": current_json_time(),
+ "taskId": slugid.nice().encode("ascii"),
+ "ownTaskId": slugid.nice().encode("ascii"),
+ "clientId": "testing/testing/testing",
+ }
+ rendered = jsone.render(self.taskcluster_yml, context)
+ pprint.pprint(rendered)
+ self.assertEqual(
+ rendered["tasks"][0]["metadata"]["name"], "Action: Test Action"
+ )
+
+ def test_unknown(self):
+ context = {"tasks_for": "bitkeeper-push"}
+ rendered = jsone.render(self.taskcluster_yml, context)
+ pprint.pprint(rendered)
+ self.assertEqual(rendered["tasks"], [])
+
+
+if __name__ == "__main__":
+ main()
diff --git a/taskcluster/taskgraph/transforms/beetmover_langpack_checksums.py b/taskcluster/taskgraph/transforms/beetmover_langpack_checksums.py
index 68d087a7adab..d5f4b7f7c709 100644
--- a/taskcluster/taskgraph/transforms/beetmover_langpack_checksums.py
+++ b/taskcluster/taskgraph/transforms/beetmover_langpack_checksums.py
@@ -17,6 +17,7 @@ from taskgraph.util.scriptworker import (generate_beetmover_artifact_map,
get_beetmover_bucket_scope,
get_worker_type_for_scope,
should_use_artifact_map)
+from taskgraph.util.treeherder import inherit_treeherder_from_dep
from taskgraph.transforms.task import task_description_schema
from voluptuous import Required, Optional
@@ -40,17 +41,11 @@ def make_beetmover_checksums_description(config, jobs):
dep_job = job['primary-dependency']
attributes = dep_job.attributes
- treeherder = job.get('treeherder', {})
+ treeherder = inherit_treeherder_from_dep(job, dep_job)
treeherder.setdefault(
'symbol',
'BMcslang(N{})'.format(attributes.get('l10n_chunk', ''))
)
- dep_th_platform = dep_job.task.get('extra', {}).get(
- 'treeherder', {}).get('machine', {}).get('platform', '')
- treeherder.setdefault('platform',
- "{}/opt".format(dep_th_platform))
- treeherder.setdefault('tier', 1)
- treeherder.setdefault('kind', 'build')
label = job['label']
build_platform = attributes.get('build_platform')
diff --git a/taskcluster/taskgraph/transforms/job/mach.py b/taskcluster/taskgraph/transforms/job/mach.py
index 8b8f92d98631..0ae0624346d8 100644
--- a/taskcluster/taskgraph/transforms/job/mach.py
+++ b/taskcluster/taskgraph/transforms/job/mach.py
@@ -44,6 +44,9 @@ def configure_mach(config, job, taskdesc):
run = job['run']
command_prefix = 'cd $GECKO_PATH && ./mach '
+ if job['worker-type'].endswith('1014'):
+ command_prefix = 'cd $GECKO_PATH && LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 ./mach '
+
mach = run['mach']
if isinstance(mach, dict):
ref, pattern = next(iter(mach.items()))
diff --git a/taskcluster/taskgraph/transforms/job/python_test.py b/taskcluster/taskgraph/transforms/job/python_test.py
index 23395475371b..8c9828118720 100644
--- a/taskcluster/taskgraph/transforms/job/python_test.py
+++ b/taskcluster/taskgraph/transforms/job/python_test.py
@@ -40,6 +40,8 @@ def configure_python_test(config, job, taskdesc):
if worker['os'] == 'macosx' and run['python-version'] == 3:
# OSX hosts can't seem to find python 3 on their own
run['python-version'] = '/tools/python36/bin/python3.6'
+ if job['worker-type'].endswith('1014'):
+ run['python-version'] = '/usr/local/bin/python3'
# defer to the mach implementation
run['mach'] = 'python-test --python {python-version} --subsuite {subsuite}'.format(**run)
diff --git a/taskcluster/taskgraph/transforms/job/run_task.py b/taskcluster/taskgraph/transforms/job/run_task.py
index a2fa4227b857..46ca7483e4f4 100644
--- a/taskcluster/taskgraph/transforms/job/run_task.py
+++ b/taskcluster/taskgraph/transforms/job/run_task.py
@@ -130,6 +130,8 @@ def generic_worker_run_task(config, job, taskdesc):
command = ['C:/mozilla-build/python3/python3.exe', 'run-task']
elif is_mac:
command = ['/tools/python36/bin/python3.6', 'run-task']
+ if job['worker-type'].endswith('1014'):
+ command = ['/usr/local/bin/python3', 'run-task']
else:
command = ['./run-task']
diff --git a/taskcluster/taskgraph/transforms/l10n.py b/taskcluster/taskgraph/transforms/l10n.py
index 8c1391c846a2..a7d0bbda5bf9 100644
--- a/taskcluster/taskgraph/transforms/l10n.py
+++ b/taskcluster/taskgraph/transforms/l10n.py
@@ -187,8 +187,7 @@ def setup_name(config, jobs):
dep = job['primary-dependency']
# Set the name to the same as the dep task, without kind name.
# Label will get set automatically with this kinds name.
- job['name'] = job.get('name',
- dep.task['metadata']['name'][len(dep.kind) + 1:])
+ job['name'] = job.get('name', dep.name)
yield job
diff --git a/taskcluster/taskgraph/transforms/release_beetmover_signed_addons.py b/taskcluster/taskgraph/transforms/release_beetmover_signed_addons.py
index 5d167a5e64e5..7b50aaa48cd9 100644
--- a/taskcluster/taskgraph/transforms/release_beetmover_signed_addons.py
+++ b/taskcluster/taskgraph/transforms/release_beetmover_signed_addons.py
@@ -17,6 +17,7 @@ from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
generate_beetmover_upstream_artifacts,
generate_beetmover_artifact_map,
should_use_artifact_map)
+from taskgraph.util.treeherder import inherit_treeherder_from_dep
from taskgraph.transforms.task import task_description_schema
from taskgraph.transforms.release_sign_and_push_langpacks import get_upstream_task_ref
from voluptuous import Required, Optional
@@ -89,14 +90,8 @@ def make_task_description(config, jobs):
dep_job = job['primary-dependency']
attributes = dep_job.attributes
- treeherder = job.get('treeherder', {})
+ treeherder = inherit_treeherder_from_dep(job, dep_job)
treeherder.setdefault('symbol', 'langpack(BM{})'.format(attributes.get('l10n_chunk', '')))
- dep_th_platform = dep_job.task.get('extra', {}).get(
- 'treeherder', {}).get('machine', {}).get('platform', '')
- treeherder.setdefault('platform',
- "{}/opt".format(dep_th_platform))
- treeherder.setdefault('tier', 1)
- treeherder.setdefault('kind', 'build')
job['attributes'].update(copy_attributes_from_dependent_job(dep_job))
job['attributes']['chunk_locales'] = dep_job.attributes['chunk_locales']
diff --git a/taskcluster/taskgraph/transforms/release_sign_and_push_langpacks.py b/taskcluster/taskgraph/transforms/release_sign_and_push_langpacks.py
index 89de71106cb4..9a5b358d1ed4 100644
--- a/taskcluster/taskgraph/transforms/release_sign_and_push_langpacks.py
+++ b/taskcluster/taskgraph/transforms/release_sign_and_push_langpacks.py
@@ -11,6 +11,7 @@ from taskgraph.loader.single_dep import schema
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.attributes import copy_attributes_from_dependent_job
from taskgraph.util.schema import resolve_keyed_by, optionally_keyed_by
+from taskgraph.util.treeherder import inherit_treeherder_from_dep
from taskgraph.transforms.task import task_description_schema
from voluptuous import Any, Required
@@ -103,15 +104,10 @@ def make_task_description(config, jobs):
for job in jobs:
dep_job = job['primary-dependency']
- treeherder = job.get('treeherder', {})
+ treeherder = inherit_treeherder_from_dep(job, dep_job)
treeherder.setdefault('symbol', 'langpack(SnP{})'.format(
job['attributes'].get('l10n_chunk', '')
))
- dep_th_platform = dep_job.task.get('extra', {}).get(
- 'treeherder', {}).get('machine', {}).get('platform', '')
- treeherder.setdefault('platform', '{}/opt'.format(dep_th_platform))
- treeherder.setdefault('tier', 1)
- treeherder.setdefault('kind', 'build')
job['description'] = job['description'].format(
locales='/'.join(job['attributes']['chunk_locales']),
diff --git a/taskcluster/taskgraph/transforms/update_verify.py b/taskcluster/taskgraph/transforms/update_verify.py
index 9940b27aa3b4..5080f543719a 100644
--- a/taskcluster/taskgraph/transforms/update_verify.py
+++ b/taskcluster/taskgraph/transforms/update_verify.py
@@ -10,16 +10,28 @@ from __future__ import absolute_import, print_function, unicode_literals
from copy import deepcopy
from taskgraph.transforms.base import TransformSequence
-from taskgraph.util.schema import resolve_keyed_by
-from taskgraph.util.treeherder import add_suffix
+from taskgraph.util.treeherder import add_suffix, inherit_treeherder_from_dep
transforms = TransformSequence()
@transforms.add
def add_command(config, tasks):
+ config_tasks = {}
+ for dep in config.kind_dependencies_tasks:
+ if 'update-verify-config' in dep.kind:
+ config_tasks[dep.name] = dep
+
for task in tasks:
+ config_task = config_tasks[task['name']]
total_chunks = task["extra"]["chunks"]
+ task['worker'].setdefault('env', {}).update(
+ CHANNEL=config_task.task['extra']['channel'],
+ )
+ task.setdefault('fetches', {})[config_task.label] = [
+ "update-verify.cfg",
+ ]
+ task['treeherder'] = inherit_treeherder_from_dep(task, config_task)
for this_chunk in range(1, total_chunks+1):
chunked = deepcopy(task)
@@ -40,23 +52,5 @@ def add_command(config, tasks):
),
'sparse-profile': 'update-verify',
}
- for thing in ("CHANNEL", "VERIFY_CONFIG"):
- thing = "worker.env.{}".format(thing)
- resolve_keyed_by(
- chunked, thing, thing,
- **{
- 'project': config.params['project'],
- 'release-type': config.params['release_type'],
- }
- )
-
- for upstream in chunked.get("dependencies", {}).keys():
- if 'update-verify-config' in upstream:
- chunked.setdefault('fetches', {})[upstream] = [
- "update-verify.cfg",
- ]
- break
- else:
- raise Exception("Couldn't find upate verify config")
yield chunked
diff --git a/taskcluster/taskgraph/util/attributes.py b/taskcluster/taskgraph/util/attributes.py
index 1196e1658a6f..6691d4b8bf68 100644
--- a/taskcluster/taskgraph/util/attributes.py
+++ b/taskcluster/taskgraph/util/attributes.py
@@ -19,9 +19,11 @@ RELEASE_PROJECTS = {
'mozilla-beta',
'mozilla-release',
'mozilla-esr60',
+ 'mozilla-esr68',
'comm-central',
'comm-beta',
'comm-esr60',
+ 'comm-esr68',
'oak',
}
diff --git a/taskcluster/taskgraph/util/scriptworker.py b/taskcluster/taskgraph/util/scriptworker.py
index 04899ddbb840..4236bcc76fc1 100644
--- a/taskcluster/taskgraph/util/scriptworker.py
+++ b/taskcluster/taskgraph/util/scriptworker.py
@@ -58,6 +58,7 @@ SIGNING_SCOPE_ALIAS_TO_PROJECT = [[
'mozilla-beta',
'mozilla-release',
'mozilla-esr60',
+ 'mozilla-esr68',
'comm-beta',
'comm-esr60',
])
@@ -95,8 +96,10 @@ BEETMOVER_SCOPE_ALIAS_TO_PROJECT = [[
'mozilla-beta',
'mozilla-release',
'mozilla-esr60',
+ 'mozilla-esr68',
'comm-beta',
'comm-esr60',
+ 'comm-esr68',
])
]]
@@ -145,8 +148,9 @@ BALROG_SCOPE_ALIAS_TO_PROJECT = [[
'comm-esr60',
])
], [
- 'esr', set([
- 'mozilla-esr52',
+ 'esr68', set([
+ 'mozilla-esr68',
+ 'comm-esr68',
])
]]
@@ -157,8 +161,8 @@ BALROG_SERVER_SCOPES = {
'aurora': 'balrog:server:aurora',
'beta': 'balrog:server:beta',
'release': 'balrog:server:release',
- 'esr': 'balrog:server:esr',
'esr60': 'balrog:server:esr',
+ 'esr68': 'balrog:server:esr',
'default': 'balrog:server:dep',
}
diff --git a/taskcluster/taskgraph/util/workertypes.py b/taskcluster/taskgraph/util/workertypes.py
index 957011ccc34e..635f68833796 100644
--- a/taskcluster/taskgraph/util/workertypes.py
+++ b/taskcluster/taskgraph/util/workertypes.py
@@ -6,7 +6,9 @@ from __future__ import absolute_import, print_function, unicode_literals
from mozbuild.util import memoize
+from .taskcluster import get_root_url
from .keyed_by import evaluate_keyed_by
+from .attributes import keymatch
WORKER_TYPES = {
'gce/gecko-1-b-linux': ('docker-worker', 'linux'),
@@ -30,41 +32,69 @@ WORKER_TYPES = {
}
+@memoize
+def _get(graph_config, alias, level):
+ """Get the configuration for this worker_type alias: {provisioner,
+ worker-type, implementation, os}"""
+ level = str(level)
+
+ # handle the legacy (non-alias) format
+ if '/' in alias:
+ alias = alias.format(level=level)
+ provisioner, worker_type = alias.split("/", 1)
+ try:
+ implementation, os = WORKER_TYPES[alias]
+ return {
+ 'provisioner': provisioner,
+ 'worker-type': worker_type,
+ 'implementation': implementation,
+ 'os': os,
+ }
+ except KeyError:
+ return {
+ 'provisioner': provisioner,
+ 'worker-type': worker_type,
+ }
+
+ matches = keymatch(graph_config['workers']['aliases'], alias)
+ if len(matches) > 1:
+ raise KeyError("Multiple matches for worker-type alias " + alias)
+ elif not matches:
+ raise KeyError("No matches for worker-type alias " + alias)
+ worker_config = matches[0].copy()
+
+ worker_config['worker-type'] = evaluate_keyed_by(
+ worker_config['worker-type'],
+ "worker-type alias {} field worker-type".format(alias),
+ {"level": level}).format(level=level, alias=alias)
+
+ return worker_config
+
+
@memoize
def worker_type_implementation(graph_config, worker_type):
"""Get the worker implementation and OS for the given workerType, where the
OS represents the host system, not the target OS, in the case of
cross-compiles."""
- if '/' in worker_type:
- worker_type = worker_type.replace('{level}', '1')
- return WORKER_TYPES[worker_type]
- else:
- worker_config = evaluate_keyed_by(
- {"by-worker-type": graph_config["workers"]["aliases"]},
- "worker-types.yml",
- {'worker-type': worker_type},
- )
- return worker_config['implementation'], worker_config['os']
+ worker_config = _get(graph_config, worker_type, '1')
+ return worker_config['implementation'], worker_config['os']
@memoize
def get_worker_type(graph_config, worker_type, level):
"""
- Get the worker type based, evaluating aliases from the graph config.
+ Get the worker type provisioner and worker-type, optionally evaluating
+ aliases from the graph config.
"""
- level = str(level)
- if '/' in worker_type:
- worker_type = worker_type.format(level=level)
- return worker_type.split("/", 1)
- else:
- worker_config = evaluate_keyed_by(
- {"by-worker-type": graph_config["workers"]["aliases"]},
- "worker-types.yml",
- {"worker-type": worker_type},
- )
- worker_type = evaluate_keyed_by(
- worker_config["worker-type"],
- worker_type,
- {"level": level},
- ).format(level=level, alias=worker_type)
- return worker_config["provisioner"], worker_type
+ worker_config = _get(graph_config, worker_type, level)
+
+ # translate the provisionerId to 'ec2' everywhere but the original
+ # https://taskcluster.net deployment. Once that deployment is no longer in
+ # use, this can be removed and all corresponding provisioners changed to
+ # `ec2`
+ root_url = get_root_url(False)
+ provisioner = worker_config["provisioner"]
+ if root_url != 'https://taskcluster.net' and provisioner == 'aws-provisioner-v1':
+ provisioner = 'ec2'
+
+ return provisioner, worker_config['worker-type']
diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py
index 84edc6d006ba..9745de592496 100644
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -622,6 +622,9 @@ class SSLTunnel:
if option in (
'tls1',
+ 'tls1_1',
+ 'tls1_2',
+ 'tls1_3',
'ssl3',
'rc4',
'failHandshake'):
diff --git a/testing/mochitest/runtestsremote.py b/testing/mochitest/runtestsremote.py
index 2251eed8f5fd..ac117153abca 100644
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -382,7 +382,7 @@ def run_test_harness(parser, options):
retVal = 1
if not device_exception and options.log_mach is None and not options.verify:
- mochitest.printDeviceInfo(printLogcat=True)
+ mochitest.printDeviceInfo(printLogcat=(retVal != 0))
mochitest.archiveMozLogs()
mochitest.message_logger.finish()
diff --git a/testing/mochitest/ssltunnel/ssltunnel.cpp b/testing/mochitest/ssltunnel/ssltunnel.cpp
index a224ac98a9d9..b8ce759de541 100644
--- a/testing/mochitest/ssltunnel/ssltunnel.cpp
+++ b/testing/mochitest/ssltunnel/ssltunnel.cpp
@@ -142,6 +142,9 @@ typedef struct {
PLHashTable* host_redir_table;
PLHashTable* host_ssl3_table;
PLHashTable* host_tls1_table;
+ PLHashTable* host_tls11_table;
+ PLHashTable* host_tls12_table;
+ PLHashTable* host_tls13_table;
PLHashTable* host_rc4_table;
PLHashTable* host_failhandshake_table;
} server_info_t;
@@ -243,7 +246,10 @@ enum {
USE_SSL3 = 1 << 0,
USE_RC4 = 1 << 1,
FAIL_HANDSHAKE = 1 << 2,
- USE_TLS1 = 1 << 4
+ USE_TLS1 = 1 << 3,
+ USE_TLS1_1 = 1 << 4,
+ USE_TLS1_2 = 1 << 5,
+ USE_TLS1_3 = 1 << 6
};
bool ReadConnectRequest(server_info_t* server_info, relayBuffer& buffer,
@@ -307,6 +313,18 @@ bool ReadConnectRequest(server_info_t* server_info, relayBuffer& buffer,
*flags |= USE_TLS1;
}
+ if (PL_HashTableLookup(server_info->host_tls11_table, token)) {
+ *flags |= USE_TLS1_1;
+ }
+
+ if (PL_HashTableLookup(server_info->host_tls12_table, token)) {
+ *flags |= USE_TLS1_2;
+ }
+
+ if (PL_HashTableLookup(server_info->host_tls13_table, token)) {
+ *flags |= USE_TLS1_3;
+ }
+
if (PL_HashTableLookup(server_info->host_failhandshake_table, token)) {
*flags |= FAIL_HANDSHAKE;
}
@@ -368,15 +386,34 @@ bool ConfigureSSLServerSocket(PRFileDesc* socket, server_info_t* si,
SSL_OptionSet(ssl_socket, SSL_REQUIRE_CERTIFICATE, clientAuth == caRequire);
}
+ SSLVersionRange range = {SSL_LIBRARY_VERSION_TLS_1_3,
+ SSL_LIBRARY_VERSION_3_0};
if (flags & USE_SSL3) {
- SSLVersionRange range = {SSL_LIBRARY_VERSION_3_0, SSL_LIBRARY_VERSION_3_0};
- SSL_VersionRangeSet(ssl_socket, &range);
+ range.min = PR_MIN(range.min, SSL_LIBRARY_VERSION_3_0);
+ range.max = PR_MAX(range.max, SSL_LIBRARY_VERSION_3_0);
}
-
if (flags & USE_TLS1) {
- SSLVersionRange range = {SSL_LIBRARY_VERSION_TLS_1_0,
- SSL_LIBRARY_VERSION_TLS_1_0};
- SSL_VersionRangeSet(ssl_socket, &range);
+ range.min = PR_MIN(range.min, SSL_LIBRARY_VERSION_TLS_1_0);
+ range.max = PR_MAX(range.max, SSL_LIBRARY_VERSION_TLS_1_0);
+ }
+ if (flags & USE_TLS1_1) {
+ range.min = PR_MIN(range.min, SSL_LIBRARY_VERSION_TLS_1_1);
+ range.max = PR_MAX(range.max, SSL_LIBRARY_VERSION_TLS_1_1);
+ }
+ if (flags & USE_TLS1_2) {
+ range.min = PR_MIN(range.min, SSL_LIBRARY_VERSION_TLS_1_2);
+ range.max = PR_MAX(range.max, SSL_LIBRARY_VERSION_TLS_1_2);
+ }
+ if (flags & USE_TLS1_3) {
+ range.min = PR_MIN(range.min, SSL_LIBRARY_VERSION_TLS_1_3);
+ range.max = PR_MAX(range.max, SSL_LIBRARY_VERSION_TLS_1_3);
+ }
+ // Set the valid range, if any were specified (if not, skip
+ // when the default range is invalid, i.e. max > min)
+ if (range.min <= range.max &&
+ SSL_VersionRangeSet(ssl_socket, &range) != SECSuccess) {
+ LOG_ERROR(("Error configuring SSL socket version range\n"));
+ return false;
}
if (flags & USE_RC4) {
@@ -701,6 +738,12 @@ void HandleConnection(void* data) {
match_hostname, &match);
PL_HashTableEnumerateEntries(ci->server_info->host_tls1_table,
match_hostname, &match);
+ PL_HashTableEnumerateEntries(ci->server_info->host_tls11_table,
+ match_hostname, &match);
+ PL_HashTableEnumerateEntries(ci->server_info->host_tls12_table,
+ match_hostname, &match);
+ PL_HashTableEnumerateEntries(ci->server_info->host_tls13_table,
+ match_hostname, &match);
PL_HashTableEnumerateEntries(ci->server_info->host_rc4_table,
match_hostname, &match);
PL_HashTableEnumerateEntries(
@@ -960,6 +1003,18 @@ PLHashTable* get_tls1_table(server_info_t* server) {
return server->host_tls1_table;
}
+PLHashTable* get_tls11_table(server_info_t* server) {
+ return server->host_tls11_table;
+}
+
+PLHashTable* get_tls12_table(server_info_t* server) {
+ return server->host_tls12_table;
+}
+
+PLHashTable* get_tls13_table(server_info_t* server) {
+ return server->host_tls13_table;
+}
+
PLHashTable* get_rc4_table(server_info_t* server) {
return server->host_rc4_table;
}
@@ -1016,7 +1071,6 @@ int processConfigLine(char* configLine) {
char* _caret;
char* keyword = strtok2(configLine, ":", &_caret);
-
// Configure usage of http/ssl tunneling proxy behavior
if (!strcmp(keyword, "httpproxy")) {
char* value = strtok2(_caret, ":", &_caret);
@@ -1136,7 +1190,7 @@ int processConfigLine(char* configLine) {
server.host_ssl3_table =
PL_NewHashTable(0, PL_HashString, PL_CompareStrings,
PL_CompareStrings, nullptr, nullptr);
- ;
+
if (!server.host_ssl3_table) {
LOG_ERROR(("Internal, could not create hash table\n"));
return 1;
@@ -1145,12 +1199,39 @@ int processConfigLine(char* configLine) {
server.host_tls1_table =
PL_NewHashTable(0, PL_HashString, PL_CompareStrings,
PL_CompareStrings, nullptr, nullptr);
- ;
+
if (!server.host_tls1_table) {
LOG_ERROR(("Internal, could not create hash table\n"));
return 1;
}
+ server.host_tls11_table =
+ PL_NewHashTable(0, PL_HashString, PL_CompareStrings,
+ PL_CompareStrings, nullptr, nullptr);
+
+ if (!server.host_tls11_table) {
+ LOG_ERROR(("Internal, could not create hash table\n"));
+ return 1;
+ }
+
+ server.host_tls12_table =
+ PL_NewHashTable(0, PL_HashString, PL_CompareStrings,
+ PL_CompareStrings, nullptr, nullptr);
+
+ if (!server.host_tls12_table) {
+ LOG_ERROR(("Internal, could not create hash table\n"));
+ return 1;
+ }
+
+ server.host_tls13_table =
+ PL_NewHashTable(0, PL_HashString, PL_CompareStrings,
+ PL_CompareStrings, nullptr, nullptr);
+
+ if (!server.host_tls13_table) {
+ LOG_ERROR(("Internal, could not create hash table\n"));
+ return 1;
+ }
+
server.host_rc4_table =
PL_NewHashTable(0, PL_HashString, PL_CompareStrings,
PL_CompareStrings, nullptr, nullptr);
@@ -1293,6 +1374,15 @@ int processConfigLine(char* configLine) {
if (!strcmp(keyword, "tls1")) {
return parseWeakCryptoConfig(keyword, _caret, get_tls1_table);
}
+ if (!strcmp(keyword, "tls1_1")) {
+ return parseWeakCryptoConfig(keyword, _caret, get_tls11_table);
+ }
+ if (!strcmp(keyword, "tls1_2")) {
+ return parseWeakCryptoConfig(keyword, _caret, get_tls12_table);
+ }
+ if (!strcmp(keyword, "tls1_3")) {
+ return parseWeakCryptoConfig(keyword, _caret, get_tls13_table);
+ }
if (!strcmp(keyword, "rc4")) {
return parseWeakCryptoConfig(keyword, _caret, get_rc4_table);
@@ -1384,7 +1474,7 @@ int freeSSL3HashItems(PLHashEntry* he, int i, void* arg) {
return HT_ENUMERATE_REMOVE;
}
-int freeTLS1HashItems(PLHashEntry* he, int i, void* arg) {
+int freeTLSHashItems(PLHashEntry* he, int i, void* arg) {
delete[](char*) he->key;
return HT_ENUMERATE_REMOVE;
}
@@ -1536,7 +1626,13 @@ int main(int argc, char** argv) {
freeHostRedirHashItems, nullptr);
PL_HashTableEnumerateEntries(server.host_ssl3_table, freeSSL3HashItems,
nullptr);
- PL_HashTableEnumerateEntries(server.host_tls1_table, freeTLS1HashItems,
+ PL_HashTableEnumerateEntries(server.host_tls1_table, freeTLSHashItems,
+ nullptr);
+ PL_HashTableEnumerateEntries(server.host_tls11_table, freeTLSHashItems,
+ nullptr);
+ PL_HashTableEnumerateEntries(server.host_tls12_table, freeTLSHashItems,
+ nullptr);
+ PL_HashTableEnumerateEntries(server.host_tls13_table, freeTLSHashItems,
nullptr);
PL_HashTableEnumerateEntries(server.host_rc4_table, freeRC4HashItems,
nullptr);
@@ -1547,6 +1643,9 @@ int main(int argc, char** argv) {
PL_HashTableDestroy(server.host_redir_table);
PL_HashTableDestroy(server.host_ssl3_table);
PL_HashTableDestroy(server.host_tls1_table);
+ PL_HashTableDestroy(server.host_tls11_table);
+ PL_HashTableDestroy(server.host_tls12_table);
+ PL_HashTableDestroy(server.host_tls13_table);
PL_HashTableDestroy(server.host_rc4_table);
PL_HashTableDestroy(server.host_failhandshake_table);
}
diff --git a/testing/web-platform/meta/css/CSS2/linebox/vertical-align-109.xht.ini b/testing/web-platform/meta/css/CSS2/linebox/vertical-align-109.xht.ini
new file mode 100644
index 000000000000..58cf8577092f
--- /dev/null
+++ b/testing/web-platform/meta/css/CSS2/linebox/vertical-align-109.xht.ini
@@ -0,0 +1,3 @@
+[vertical-align-109.xht]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/css/css-backgrounds/background-size/background-size-cover-svg.html.ini b/testing/web-platform/meta/css/css-backgrounds/background-size/background-size-cover-svg.html.ini
new file mode 100644
index 000000000000..da48a868e781
--- /dev/null
+++ b/testing/web-platform/meta/css/css-backgrounds/background-size/background-size-cover-svg.html.ini
@@ -0,0 +1,3 @@
+[background-size-cover-svg.html]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/css/css-grid/grid-model/grid-areas-overflowing-grid-container-001.html.ini b/testing/web-platform/meta/css/css-grid/grid-model/grid-areas-overflowing-grid-container-001.html.ini
new file mode 100644
index 000000000000..ff87ce929851
--- /dev/null
+++ b/testing/web-platform/meta/css/css-grid/grid-model/grid-areas-overflowing-grid-container-001.html.ini
@@ -0,0 +1,3 @@
+[grid-areas-overflowing-grid-container-001.html]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/css/css-text-decor/text-emphasis-style-006.html.ini b/testing/web-platform/meta/css/css-text-decor/text-emphasis-style-006.html.ini
new file mode 100644
index 000000000000..793080fd905b
--- /dev/null
+++ b/testing/web-platform/meta/css/css-text-decor/text-emphasis-style-006.html.ini
@@ -0,0 +1,3 @@
+[text-emphasis-style-006.html]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/background-repeat-round-3.html.ini b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/background-repeat-round-3.html.ini
new file mode 100644
index 000000000000..5cfa81cc2694
--- /dev/null
+++ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/background-repeat-round-3.html.ini
@@ -0,0 +1,3 @@
+[background-repeat-round-3.html]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/background-repeat-round-4.html.ini b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/background-repeat-round-4.html.ini
new file mode 100644
index 000000000000..85f251745195
--- /dev/null
+++ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/background-repeat-round-4.html.ini
@@ -0,0 +1,3 @@
+[background-repeat-round-4.html]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/text3/segment-break-transformation-rules-007.html.ini b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/text3/segment-break-transformation-rules-007.html.ini
new file mode 100644
index 000000000000..c474c3d66de1
--- /dev/null
+++ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/text3/segment-break-transformation-rules-007.html.ini
@@ -0,0 +1,3 @@
+[segment-break-transformation-rules-007.html]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/html/browsers/history/the-location-interface/security_location_0.htm.ini b/testing/web-platform/meta/html/browsers/history/the-location-interface/security_location_0.htm.ini
new file mode 100644
index 000000000000..057e26f96631
--- /dev/null
+++ b/testing/web-platform/meta/html/browsers/history/the-location-interface/security_location_0.htm.ini
@@ -0,0 +1,3 @@
+[security_location_0.htm]
+ disabled:
+ if (os == "android") and e10s: bug 1550895 (frequently fails on geckoview)
diff --git a/testing/web-platform/meta/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg.ini b/testing/web-platform/meta/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg.ini
deleted file mode 100644
index 597c4b8fd589..000000000000
--- a/testing/web-platform/meta/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[image-embedding-svg-with-viewport-units-inline-style.svg]
- expected: FAIL
diff --git a/testing/web-platform/meta/svg/embedded/image-embedding-svg-with-viewport-units.svg.ini b/testing/web-platform/meta/svg/embedded/image-embedding-svg-with-viewport-units.svg.ini
deleted file mode 100644
index e9ec81d339af..000000000000
--- a/testing/web-platform/meta/svg/embedded/image-embedding-svg-with-viewport-units.svg.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[image-embedding-svg-with-viewport-units.svg]
- expected: FAIL
diff --git a/testing/web-platform/meta/svg/extensibility/foreignObject/properties.svg.ini b/testing/web-platform/meta/svg/extensibility/foreignObject/properties.svg.ini
index dbd21b3c2daa..47e87e6c5a27 100644
--- a/testing/web-platform/meta/svg/extensibility/foreignObject/properties.svg.ini
+++ b/testing/web-platform/meta/svg/extensibility/foreignObject/properties.svg.ini
@@ -1,19 +1,6 @@
[properties.svg]
- [Untitled]
- expected: FAIL
-
[width and height default to auto]
expected: FAIL
- [style rules are applied]
- expected: FAIL
-
- [attributes set properties]
- expected: FAIL
-
- [style rules override attributes]
- expected: FAIL
-
[width and height default to auto (which computes to "0px")]
expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/cx-valid.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/cx-valid.svg.ini
deleted file mode 100644
index 5b58d8e37e7c..000000000000
--- a/testing/web-platform/meta/svg/geometry/parsing/cx-valid.svg.ini
+++ /dev/null
@@ -1,16 +0,0 @@
-[cx-valid.svg]
- [e.style['cx'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['cx'\] = "-1px" should set the property value]
- expected: FAIL
-
- [e.style['cx'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['cx'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['cx'\] = "5ch" should set the property value]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/cy-valid.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/cy-valid.svg.ini
deleted file mode 100644
index c4744a1488a0..000000000000
--- a/testing/web-platform/meta/svg/geometry/parsing/cy-valid.svg.ini
+++ /dev/null
@@ -1,16 +0,0 @@
-[cy-valid.svg]
- [e.style['cy'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['cy'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['cy'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['cy'\] = "-1px" should set the property value]
- expected: FAIL
-
- [e.style['cy'\] = "5rem" should set the property value]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/height-computed.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/height-computed.svg.ini
index 4848d99c6fd0..842862002126 100644
--- a/testing/web-platform/meta/svg/geometry/parsing/height-computed.svg.ini
+++ b/testing/web-platform/meta/svg/geometry/parsing/height-computed.svg.ini
@@ -5,15 +5,9 @@
[SVG Geometry Properties: getComputedStyle().height, initial]
expected: FAIL
- [SVG Geometry Properties: getComputedStyle().height, presentation attribute]
- expected: FAIL
-
[SVG Geometry Properties: getComputedStyle().height, inline style (auto)]
expected: FAIL
- [SVG Geometry Properties: getComputedStyle().height, presentation attribute]
- expected: FAIL
-
[SVG Geometry Properties: getComputedStyle().height, initial]
expected: FAIL
@@ -44,6 +38,3 @@
[SVG Geometry Properties: getComputedStyle().height, inline style (percentage)]
expected: FAIL
- [SVG Geometry Properties: getComputedStyle().height, presentation attribute]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/r-valid.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/r-valid.svg.ini
deleted file mode 100644
index cd8adc55faf5..000000000000
--- a/testing/web-platform/meta/svg/geometry/parsing/r-valid.svg.ini
+++ /dev/null
@@ -1,16 +0,0 @@
-[r-valid.svg]
- [e.style['r'\] = "1px" should set the property value]
- expected: FAIL
-
- [e.style['r'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['r'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['r'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['r'\] = "5vmin" should set the property value]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/rx-valid.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/rx-valid.svg.ini
deleted file mode 100644
index 58135a0a4aaa..000000000000
--- a/testing/web-platform/meta/svg/geometry/parsing/rx-valid.svg.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-[rx-valid.svg]
- [e.style['rx'\] = "auto" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "1px" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "5vw" should set the property value]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/ry-valid.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/ry-valid.svg.ini
deleted file mode 100644
index 89f5671cddc7..000000000000
--- a/testing/web-platform/meta/svg/geometry/parsing/ry-valid.svg.ini
+++ /dev/null
@@ -1,37 +0,0 @@
-[ry-valid.svg]
- [e.style['rx'\] = "auto" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "1px" should set the property value]
- expected: FAIL
-
- [e.style['rx'\] = "5vh" should set the property value]
- expected: FAIL
-
- [e.style['ry'\] = "auto" should set the property value]
- expected: FAIL
-
- [e.style['ry'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['ry'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['ry'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['ry'\] = "1px" should set the property value]
- expected: FAIL
-
- [e.style['ry'\] = "5vh" should set the property value]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/width-computed.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/width-computed.svg.ini
index 80daaebbd629..a7b3f5b1ce8d 100644
--- a/testing/web-platform/meta/svg/geometry/parsing/width-computed.svg.ini
+++ b/testing/web-platform/meta/svg/geometry/parsing/width-computed.svg.ini
@@ -14,18 +14,12 @@
[SVG Geometry Properties: getComputedStyle().width, initial]
expected: FAIL
- [SVG Geometry Properties: getComputedStyle().width, presentation attribute]
- expected: FAIL
-
[SVG Geometry Properties: getComputedStyle().width, inline style (percentage)]
expected: FAIL
[SVG Geometry Properties: getComputedStyle().width, presentation attribute]
expected: FAIL
- [SVG Geometry Properties: getComputedStyle().width, presentation attribute]
- expected: FAIL
-
[SVG Geometry Properties: getComputedStyle().width, inline style (percentage)]
expected: FAIL
@@ -44,6 +38,3 @@
[SVG Geometry Properties: getComputedStyle().width, inline style (auto)]
expected: FAIL
- [SVG Geometry Properties: getComputedStyle().width, presentation attribute]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/x-valid.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/x-valid.svg.ini
deleted file mode 100644
index 3e60baf71b36..000000000000
--- a/testing/web-platform/meta/svg/geometry/parsing/x-valid.svg.ini
+++ /dev/null
@@ -1,16 +0,0 @@
-[x-valid.svg]
- [e.style['x'\] = "-1px" should set the property value]
- expected: FAIL
-
- [e.style['x'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['x'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['x'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['x'\] = "5cm" should set the property value]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/parsing/y-valid.svg.ini b/testing/web-platform/meta/svg/geometry/parsing/y-valid.svg.ini
deleted file mode 100644
index ee1d0181cdd1..000000000000
--- a/testing/web-platform/meta/svg/geometry/parsing/y-valid.svg.ini
+++ /dev/null
@@ -1,16 +0,0 @@
-[y-valid.svg]
- [e.style['y'\] = "-1px" should set the property value]
- expected: FAIL
-
- [e.style['y'\] = "4%" should set the property value]
- expected: FAIL
-
- [e.style['y'\] = "0" should set the property value]
- expected: FAIL
-
- [e.style['y'\] = "calc(2em + 3ex)" should set the property value]
- expected: FAIL
-
- [e.style['y'\] = "5mm" should set the property value]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/svg/geometry/reftests/percentage.svg.ini b/testing/web-platform/meta/svg/geometry/reftests/percentage.svg.ini
deleted file mode 100644
index 70f9924f1d4a..000000000000
--- a/testing/web-platform/meta/svg/geometry/reftests/percentage.svg.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[percentage.svg]
- expected: FAIL
diff --git a/testing/web-platform/meta/svg/shapes/ellipse-01.svg.ini b/testing/web-platform/meta/svg/shapes/ellipse-01.svg.ini
deleted file mode 100644
index 3cc588394397..000000000000
--- a/testing/web-platform/meta/svg/shapes/ellipse-01.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ellipse-01.svg]
- expected:
- if (not (os == "win")): FAIL
- if (os == "win"): FAIL
diff --git a/testing/web-platform/meta/svg/shapes/ellipse-02.svg.ini b/testing/web-platform/meta/svg/shapes/ellipse-02.svg.ini
deleted file mode 100644
index 8f9286256f01..000000000000
--- a/testing/web-platform/meta/svg/shapes/ellipse-02.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ellipse-02.svg]
- expected:
- if (not (os == "win")): FAIL
- if (os == "win"): FAIL
diff --git a/testing/web-platform/meta/svg/shapes/ellipse-03.svg.ini b/testing/web-platform/meta/svg/shapes/ellipse-03.svg.ini
deleted file mode 100644
index 00e80ac64424..000000000000
--- a/testing/web-platform/meta/svg/shapes/ellipse-03.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ellipse-03.svg]
- expected:
- if (not (os == "win")): FAIL
- if (os == "win"): FAIL
diff --git a/testing/web-platform/meta/svg/shapes/ellipse-05.svg.ini b/testing/web-platform/meta/svg/shapes/ellipse-05.svg.ini
deleted file mode 100644
index 3d59eb300620..000000000000
--- a/testing/web-platform/meta/svg/shapes/ellipse-05.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ellipse-05.svg]
- expected:
- if (not (os == "win")): FAIL
- if (os == "win"): FAIL
diff --git a/testing/web-platform/meta/svg/shapes/ellipse-06.svg.ini b/testing/web-platform/meta/svg/shapes/ellipse-06.svg.ini
deleted file mode 100644
index 55bef13351e4..000000000000
--- a/testing/web-platform/meta/svg/shapes/ellipse-06.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ellipse-06.svg]
- expected:
- if (not (os == "win")): FAIL
- if (os == "win"): FAIL
diff --git a/testing/web-platform/meta/svg/shapes/ellipse-07.svg.ini b/testing/web-platform/meta/svg/shapes/ellipse-07.svg.ini
deleted file mode 100644
index 92151b2c10b3..000000000000
--- a/testing/web-platform/meta/svg/shapes/ellipse-07.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ellipse-07.svg]
- expected:
- if (not (os == "win")): FAIL
- if (os == "win"): FAIL
diff --git a/testing/web-platform/meta/svg/shapes/ellipse-08.svg.ini b/testing/web-platform/meta/svg/shapes/ellipse-08.svg.ini
deleted file mode 100644
index b3895ab52c14..000000000000
--- a/testing/web-platform/meta/svg/shapes/ellipse-08.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[ellipse-08.svg]
- expected:
- if (not (os == "win")): FAIL
- if (os == "win"): FAIL
diff --git a/testing/web-platform/meta/svg/shapes/rx-ry-not-inherited.svg.ini b/testing/web-platform/meta/svg/shapes/rx-ry-not-inherited.svg.ini
deleted file mode 100644
index ee42613f47b7..000000000000
--- a/testing/web-platform/meta/svg/shapes/rx-ry-not-inherited.svg.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[rx-ry-not-inherited.svg]
- [Untitled]
- expected: FAIL
-
- [rx-ry-not-inherited]
- expected: FAIL
-
diff --git a/testing/web-platform/meta/webrtc/RTCPeerConnection-ondatachannel.html.ini b/testing/web-platform/meta/webrtc/RTCPeerConnection-ondatachannel.html.ini
index 7a8cf2dc68c0..0db9ade5a016 100644
--- a/testing/web-platform/meta/webrtc/RTCPeerConnection-ondatachannel.html.ini
+++ b/testing/web-platform/meta/webrtc/RTCPeerConnection-ondatachannel.html.ini
@@ -5,16 +5,21 @@
[Data channel event should fire when new data channel is announced to the remote peer]
expected: FAIL
+ bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
[In-band negotiated channel created on remote peer should match the same (default) configuration as local peer]
expected: FAIL
+ bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1529695
[Open event should not be raised when sending and immediately closing the channel in the datachannel event]
expected: FAIL
+ bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
[Should be able to send data in a datachannel event handler]
expected: FAIL
+ bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
[In-band negotiated channel created on remote peer should match the same configuration as local peer]
expected: FAIL
+ bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1551589
diff --git a/testing/web-platform/tests/intersection-observer/iframe-no-root-with-wrapping-scroller.html b/testing/web-platform/tests/intersection-observer/iframe-no-root-with-wrapping-scroller.html
new file mode 100644
index 000000000000..f219ba39c147
--- /dev/null
+++ b/testing/web-platform/tests/intersection-observer/iframe-no-root-with-wrapping-scroller.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/svg/shapes/reftests/disabled-shapes-01.svg b/testing/web-platform/tests/svg/shapes/reftests/disabled-shapes-01.svg
index 3091ca7b0152..65364dc08ff5 100644
--- a/testing/web-platform/tests/svg/shapes/reftests/disabled-shapes-01.svg
+++ b/testing/web-platform/tests/svg/shapes/reftests/disabled-shapes-01.svg
@@ -21,6 +21,7 @@
+
@@ -29,22 +30,22 @@
+
-
-
+
diff --git a/testing/web-platform/tests/svg/shapes/scripted/disabled-shapes-not-hit.svg b/testing/web-platform/tests/svg/shapes/scripted/disabled-shapes-not-hit.svg
index 5a621d9f21dc..21ea9078785e 100644
--- a/testing/web-platform/tests/svg/shapes/scripted/disabled-shapes-not-hit.svg
+++ b/testing/web-platform/tests/svg/shapes/scripted/disabled-shapes-not-hit.svg
@@ -22,6 +22,7 @@
+
@@ -30,22 +31,22 @@
+
-
-
+
-