Merge mozilla-central to mozilla-inbound. a=merge

This commit is contained in:
Daniel Varga 2019-05-16 07:19:28 +03:00
Родитель 091774e8ae f638ab1178
Коммит 4bf41d68cf
259 изменённых файлов: 3393 добавлений и 1949 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -170,14 +170,6 @@
<p id="badStsCertExplanation" hidden="true">&certerror.whatShouldIDo.badStsCertExplanation1;</p>
</div>
<div id="wrongSystemTimePanel">
&certerror.wrongSystemTime2;
</div>
<div id="wrongSystemTimeWithoutReferencePanel">
&certerror.wrongSystemTimeWithoutReference;
</div>
<!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
<div id="errorLongDesc" />

Просмотреть файл

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

Просмотреть файл

@ -781,7 +781,10 @@ nsContextMenu.prototype = {
},
openPasswordManager() {
LoginHelper.openPasswordManager(window, gContextMenuContentData.documentURIObject.host);
LoginHelper.openPasswordManager(window, {
filterString: gContextMenuContentData.documentURIObject.host,
entryPoint: "contextmenu",
});
},
inspectNode() {

Просмотреть файл

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

Просмотреть файл

@ -114,3 +114,4 @@ support-files =
support-files =
file_mixedPassiveContent.html
file_bug1045809_1.html
[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");
});
});

Просмотреть файл

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

Просмотреть файл

@ -336,7 +336,7 @@
<toolbarbutton id="appMenu-logins-button"
class="subviewbutton subviewbutton-iconic"
label="&logins.label;"
oncommand="LoginHelper.openPasswordManager(window)"
oncommand="LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' })"
/>
<toolbarbutton id="appMenu-addons-button"
class="subviewbutton subviewbutton-iconic"
@ -425,7 +425,7 @@
<toolbarbutton id="appMenuViewHistorySidebar"
label="&appMenuHistory.viewSidebar.label;"
label-checked="&appMenuHistory.hideSidebar.label;"
label-unchecked="&appMenuHistory.viewSidebar.label;"
label-unchecked="&appMenuHistory.viewSidebar.label;"
type="checkbox"
class="subviewbutton subviewbutton-iconic"
key="key_gotoHistory"

Просмотреть файл

@ -294,6 +294,8 @@ var gPrivacyPane = {
this.networkCookieBehaviorReadPrefs();
this._initTrackingProtectionExtensionControl();
Services.telemetry.setEventRecordingEnabled("pwmgr", true);
Preferences.get("media.autoplay.default").on("change",
gPrivacyPane.blockAutoplayReadPrefs.bind(gPrivacyPane));
@ -1422,9 +1424,12 @@ var gPrivacyPane = {
*/
showPasswords() {
if (LoginHelper.managementURI) {
window.docShell.messageManager.sendAsyncMessage("PasswordManager:OpenPreferences", {});
window.docShell.messageManager.sendAsyncMessage("PasswordManager:OpenPreferences", {
entryPoint: "preferences",
});
return;
}
Services.telemetry.recordEvent("pwmgr", "open_management", "preferences");
gSubDialog.open("chrome://passwordmgr/content/passwordManager.xul");
},

Просмотреть файл

@ -1,4 +1,7 @@
"use strict";
ChromeUtils.import("resource://testing-common/TelemetryTestUtils.jsm", this);
const PM_URL = "chrome://passwordmgr/content/passwordManager.xul";
const PREF_MANAGEMENT_URI = "signon.management.overrideURI";
@ -21,6 +24,7 @@ add_task(async function test_setup() {
});
add_task(async function test_openPasswordSubDialog() {
Services.telemetry.clearEvents();
await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true});
let dialogOpened = promiseLoadSubDialog(PM_URL);
@ -37,6 +41,11 @@ add_task(async function test_openPasswordSubDialog() {
});
passwordsDialog = await dialogOpened;
// check telemetry events while we are in here
TelemetryTestUtils.assertEvents(
[["pwmgr", "open_management", "preferences"]],
{category: "pwmgr", method: "open_management"});
});
add_task(async function test_deletePasswordWithKey() {
@ -60,6 +69,7 @@ add_task(async function test_deletePasswordWithKey() {
});
add_task(async function subdialog_cleanup() {
Services.telemetry.clearEvents();
// Undo the save password change.
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
let doc = content.document;

Просмотреть файл

@ -2,22 +2,30 @@
# 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/.
## UI strings for the simplified onboarding modal
### UI strings for the simplified onboarding modal / about:welcome
### Various strings use a non-breaking space to avoid a single dangling /
### widowed word, so test on various window sizes if you also want this.
## These button action text can be split onto multiple lines, so use explicit
## newlines in translations to control where the line break appears (e.g., to
## avoid breaking quoted text).
onboarding-button-label-learn-more = Learn More
onboarding-button-label-try-now = Try It Now
onboarding-button-label-get-started = Get Started
## Welcome modal dialog strings
onboarding-welcome-header = Welcome to { -brand-short-name }
onboarding-welcome-body = Youve got the browser.<br/>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 <a data-l10n-name="terms">Terms of Service</a> and <a data-l10n-name="privacy">Privacy Notice</a>.
onboarding-join-form-legal = By proceeding, you agree to the <a data-l10n-name="terms">Terms of Service</a> and <a data-l10n-name="privacy">Privacy Notice</a>.
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 its convenient for you.
onboarding-pocket-anywhere-text2 = Save your favorite content offline with the { -pocket-brand-name } App and read, listen, and watch whenever its 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

Просмотреть файл

@ -205,12 +205,6 @@ was trying to connect. -->
"SSL_ERROR_UNSUPPORTED_VERSION". -->
<!ENTITY sslv3Used.longDesc2 "Advanced info: SSL_ERROR_UNSUPPORTED_VERSION">
<!-- LOCALIZATION NOTE (certerror.wrongSystemTime2,
certerror.wrongSystemTimeWithoutReference) - The <span id='..' />
tags will be injected with actual values, please leave them unchanged. -->
<!ENTITY certerror.wrongSystemTime2 "<p> &brandShortName; did not connect to <span id='wrongSystemTime_URL'/> because your computers clock appears to show the wrong time and this is preventing a secure connection.</p> <p>Your computer is set to <span id='wrongSystemTime_systemDate'/>, when it should be <span id='wrongSystemTime_actualDate'/>. To fix this problem, change your date and time settings to match the correct time.</p>">
<!ENTITY certerror.wrongSystemTimeWithoutReference "<p>&brandShortName; did not connect to <span id='wrongSystemTimeWithoutReference_URL'/> because your computers clock appears to show the wrong time and this is preventing a secure connection.</p> <p>Your computer is set to <span id='wrongSystemTimeWithoutReference_systemDate'/>. To fix this problem, change your date and time settings to match the correct time.</p>">
<!ENTITY certerror.pagetitle2 "Warning: Potential Security Risk Ahead">
<!ENTITY certerror.sts.pagetitle "Did Not Connect: Potential Security Issue">
<!ENTITY certerror.whatShouldIDo.badStsCertExplanation1 "<span class='hostname'></span> has a security policy called HTTP Strict Transport Security (HSTS), which means that &brandShortName; can only connect to it securely. You cant add an exception to visit this site.">

Просмотреть файл

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

Двоичные данные
build/pgo/certs/cert9.db

Двоичный файл не отображается.

Двоичные данные
build/pgo/certs/key4.db

Двоичный файл не отображается.

Двоичные данные
build/pgo/certs/mochitest.client

Двоичный файл не отображается.

Просмотреть файл

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

Просмотреть файл

@ -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 <http://mozilla.org/MPL/2.0/>. */
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
});
/***/ }),

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -44,6 +44,7 @@ async function mapLocations(
}
const { sourceId } = generatedLocations[0];
const originalLocations = await sourceMaps.getOriginalLocations(
sourceId,
generatedLocations

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -55,7 +55,8 @@ export function mapScopes(
scopes: Promise<Scope>,
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);

Просмотреть файл

@ -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<?Source> {
const epoch = getSourcesEpoch(getState());
await dispatch({

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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<AstLocation[]> {
return this.invoke("findOutOfScopeLocations", sourceId, position);
}
export const findOutOfScopeLocations = async (
sourceId: string,
position: AstPosition
): Promise<AstLocation[]> =>
dispatcher.invoke("findOutOfScopeLocations", sourceId, position);
async getNextStep(
sourceId: SourceId,
pausedPosition: AstPosition
): Promise<?SourceLocation> {
return this.invoke("getNextStep", sourceId, pausedPosition);
}
export const getNextStep = async (
sourceId: SourceId,
pausedPosition: AstPosition
): Promise<?SourceLocation> =>
dispatcher.invoke("getNextStep", sourceId, pausedPosition);
async clearState(): Promise<void> {
return this.invoke("clearState");
}
export const clearASTs = async (): Promise<void> =>
dispatcher.invoke("clearASTs");
async getScopes(location: SourceLocation): Promise<SourceScope[]> {
return this.invoke("getScopes", location);
}
export const getScopes = async (
location: SourceLocation
): Promise<SourceScope[]> => dispatcher.invoke("getScopes", location);
async getSymbols(sourceId: string): Promise<SymbolDeclarations> {
return this.invoke("getSymbols", sourceId);
}
export const clearScopes = async (): Promise<void> =>
dispatcher.invoke("clearScopes");
async setSource(sourceId: SourceId, content: SourceContent): Promise<void> {
const astSource: AstSource = {
id: sourceId,
text: content.type === "wasm" ? "" : content.value,
contentType: content.contentType || null,
isWasm: content.type === "wasm"
};
export const clearSymbols = async (): Promise<void> =>
dispatcher.invoke("clearSymbols");
return this.invoke("setSource", astSource);
}
export const getSymbols = async (
sourceId: string
): Promise<SymbolDeclarations> => dispatcher.invoke("getSymbols", sourceId);
async hasSyntaxError(input: string): Promise<string | false> {
return this.invoke("hasSyntaxError", input);
}
export const setSource = async (
sourceId: SourceId,
content: SourceContent
): Promise<void> => {
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<void> =>
dispatcher.invoke("clearSources");
export const hasSyntaxError = async (input: string): Promise<string | false> =>
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,

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -873,11 +873,9 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
} else if (eventType.EqualsLiteral("drop")) {
nsIWebNavigation* webnav = static_cast<nsIWebNavigation*>(mWebBrowser);
uint32_t linksCount;
nsIDroppedLinkItem** links;
if (webnav && NS_SUCCEEDED(handler->DropLinks(dragEvent, true, &linksCount,
&links))) {
if (linksCount >= 1) {
nsTArray<RefPtr<nsIDroppedLinkItem>> links;
if (webnav && NS_SUCCEEDED(handler->DropLinks(dragEvent, true, links))) {
if (links.Length() >= 1) {
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
handler->GetTriggeringPrincipal(dragEvent,
getter_AddRefs(triggeringPrincipal));
@ -888,11 +886,7 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) {
nsCOMPtr<nsIBrowserChild> 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 {

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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<nsIDroppedLinkItem> 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<AString> 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<nsIDroppedLinkItem> queryLinks(in DataTransfer aDataTransfer);
/**
* Given a drop event aEvent, determines the triggering principal for the

Просмотреть файл

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

Просмотреть файл

@ -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<AString> 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<ACString> enabledCommands,
in Array<ACString> disabledCommands);
readonly attribute nsIPrincipal contentPrincipal;
readonly attribute nsIContentSecurityPolicy csp;

Просмотреть файл

@ -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<nsIDroppedLinkItem> links);
readonly attribute uint64_t tabId;

Просмотреть файл

@ -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<RefPtr<nsIDroppedLinkItem>>& aLinks) {
nsTArray<nsString> 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<DisplayportSetListener> postLayerization =
APZCCallbackHelper::SendSetTargetAPZCNotification(
mPuppetWidget, document, localEvent, aGuid.mLayersId, aInputBlockId);
mPuppetWidget, document, localEvent, aGuid.mLayersId,
aInputBlockId);
if (postLayerization && postLayerization->Register()) {
Unused << postLayerization.release();
}

Просмотреть файл

@ -809,15 +809,12 @@ mozilla::ipc::IPCResult BrowserParent::RecvDropLinks(
if (aLinks.Length() != mVerifyDropLinks.Length()) {
loadUsingSystemPrincipal = false;
}
UniquePtr<const char16_t*[]> links;
links = MakeUnique<const char16_t*[]>(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<nsIPrincipal> 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<RefPtr<nsIDroppedLinkItem>> 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<const char*[]> enabledCommands, disabledCommands;
if (aEnabledCommands.Length()) {
enabledCommands = MakeUnique<const char*[]>(aEnabledCommands.Length());
for (uint32_t c = 0; c < aEnabledCommands.Length(); c++) {
enabledCommands[c] = aEnabledCommands[c].get();
}
}
if (aDisabledCommands.Length()) {
disabledCommands = MakeUnique<const char*[]>(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();

Просмотреть файл

@ -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. <rect>) 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. <rect>) 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 <svg> element.
if (!mKey.mElement->IsSVGElement(nsGkAtoms::svg)) {
return eCSSProperty_UNKNOWN;
}
// An inner <svg> element
if (static_cast<dom::SVGSVGElement const&>(*mKey.mElement).IsInner()) {
return eCSSProperty_UNKNOWN;
}
// Indeed an outer <svg> element, fall through.
}
return propID;

Просмотреть файл

@ -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<mozilla::dom::NodeInfo>&& 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<DOMSVGAnimatedLength> SVGCircleElement::R() {
/* virtual */
bool SVGCircleElement::HasValidDimensions() const {
return mLengthAttributes[ATTR_R].IsExplicitlySet() &&
mLengthAttributes[ATTR_R].GetAnimValInSpecifiedUnits() > 0;
float r;
MOZ_ASSERT(GetPrimaryFrame());
SVGGeometryProperty::ResolveAll<SVGT::R>(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<SVGT::Cx, SVGT::Cy, SVGT::R>(this, &x, &y,
&r);
if (r <= 0.f) {
// Rendering of the element is disabled
@ -112,7 +127,9 @@ bool SVGCircleElement::GetGeometryBounds(
already_AddRefed<Path> SVGCircleElement::BuildPath(PathBuilder* aBuilder) {
float x, y, r;
GetAnimatedLengthValues(&x, &y, &r, nullptr);
MOZ_ASSERT(GetPrimaryFrame());
SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::R>(this, &x, &y,
&r);
if (r <= 0.0f) {
return nullptr;
@ -123,5 +140,30 @@ already_AddRefed<Path> 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

Просмотреть файл

@ -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<mozilla::dom::NodeInfo>&& aNodeInfo);
namespace mozilla {
class ComputedStyle;
namespace dom {
typedef SVGGeometryElement SVGCircleElementBase;
@ -29,6 +32,8 @@ class SVGCircleElement final : public SVGCircleElementBase {
already_AddRefed<mozilla::dom::NodeInfo>&& 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<DOMSVGAnimatedLength> Cx();
already_AddRefed<DOMSVGAnimatedLength> Cy();

Просмотреть файл

@ -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 <stdarg.h>
@ -1020,6 +1022,41 @@ already_AddRefed<DOMSVGAnimatedString> 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<DeclarationBlock> 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;
}

Просмотреть файл

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

Просмотреть файл

@ -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<mozilla::dom::NodeInfo>&& 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<DOMSVGAnimatedLength> 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<SVGT::Rx, SVGT::Ry>(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<SVGT::Cx, SVGT::Cy, SVGT::Rx, SVGT::Ry>(
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<Path> SVGEllipseElement::BuildPath(PathBuilder* aBuilder) {
float x, y, rx, ry;
GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
MOZ_ASSERT(GetPrimaryFrame());
SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::Rx, SVGT::Ry>(
this, &x, &y, &rx, &ry);
if (rx <= 0.0f || ry <= 0.0f) {
return nullptr;
@ -135,5 +152,33 @@ already_AddRefed<Path> 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

Просмотреть файл

@ -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<mozilla::dom::NodeInfo>&& aNodeInfo);
namespace mozilla {
class ComputedStyle;
namespace dom {
typedef SVGGeometryElement SVGEllipseElementBase;
@ -29,6 +32,8 @@ class SVGEllipseElement final : public SVGEllipseElementBase {
already_AddRefed<mozilla::dom::NodeInfo>&& 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<DOMSVGAnimatedLength> Cx();
already_AddRefed<DOMSVGAnimatedLength> Cy();

Просмотреть файл

@ -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<mozilla::dom::NodeInfo>&& 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<SVGForeignObjectElement*>(this)->GetAnimatedLengthValues(&x, &y,
nullptr);
if (GetPrimaryFrame()) {
SVGGeometryProperty::ResolveAll<SVGT::X, SVGT::Y>(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<SVGForeignObjectElement*>(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<SVGT::Width, SVGT::Height>(
const_cast<SVGForeignObjectElement*>(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

Просмотреть файл

@ -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<DOMSVGAnimatedLength> X();
already_AddRefed<DOMSVGAnimatedLength> Y();

Просмотреть файл

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

Просмотреть файл

@ -191,6 +191,13 @@ class SVGGeometryElement : public SVGGeometryElementBase {
*/
virtual already_AddRefed<Path> 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.

Просмотреть файл

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

Просмотреть файл

@ -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 <type_traits>
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 <class T>
using AlwaysFloat = float;
using CtxDirectionType = decltype(SVGContentUtils::X);
template <CtxDirectionType CTD>
float ResolvePureLengthPercentage(SVGElement* aElement,
const LengthPercentage& aLP) {
return aLP.ResolveToCSSPixelsWith(
[&] { return CSSCoord{SVGElementMetrics(aElement).GetAxisLength(CTD)}; });
}
template <class Tag>
float ResolveImpl(ComputedStyle const& aStyle, SVGElement* aElement,
ResolverTypes::LengthPercentNoAuto) {
auto const& value = aStyle.StyleSVGReset()->*Tag::Getter;
return ResolvePureLengthPercentage<Tag::CtxDirection>(aElement, value);
}
template <class Tag>
float ResolveImpl(ComputedStyle const& aStyle, SVGElement* aElement,
ResolverTypes::LengthPercentWidthHeight) {
static_assert(
std::is_same<Tag, Tags::Width>{} || std::is_same<Tag, Tags::Height>{},
"Wrong tag");
auto const& value = aStyle.StylePosition()->*Tag::Getter;
if (value.IsLengthPercentage()) {
return ResolvePureLengthPercentage<Tag::CtxDirection>(
aElement, value.AsLengthPercentage());
}
// |auto| and |max-content| etc. are treated as 0.
return 0.f;
}
template <class Tag>
float ResolveImpl(ComputedStyle const& aStyle, SVGElement* aElement,
ResolverTypes::LengthPercentRXY) {
static_assert(std::is_same<Tag, Tags::Rx>{} || std::is_same<Tag, Tags::Ry>{},
"Wrong tag");
auto const& value = aStyle.StyleSVGReset()->*Tag::Getter;
if (value.IsLengthPercentage()) {
return ResolvePureLengthPercentage<Tag::CtxDirection>(
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<Rother::CtxDirection>(
aElement, valueOther.AsLengthPercentage());
}
} // namespace details
template <class Tag>
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<Tag>(aStyle, const_cast<SVGElement*>(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 <class... Tags>
bool ResolveAll(const SVGElement* aElement,
details::AlwaysFloat<Tags>*... aRes) {
if (nsIFrame const* f = aElement->GetPrimaryFrame()) {
using dummy = int[];
(void)dummy{0, (*aRes = ResolveWith<Tags>(*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

Просмотреть файл

@ -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 <typename T>
bool IsInLengthInfo(const nsAtom* aAttribute, const T& aLengthInfos) const {
for (auto const& e : aLengthInfos) {
if (e.mName == aAttribute) {
return true;
}
}
return false;
}
};
} // namespace dom

Просмотреть файл

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

Просмотреть файл

@ -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 <algorithm>
NS_IMPL_NS_NEW_SVG_ELEMENT(Rect)
@ -49,6 +50,13 @@ SVGRectElement::SVGRectElement(
already_AddRefed<mozilla::dom::NodeInfo>&& 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<DOMSVGAnimatedLength> 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<SVGT::Width, SVGT::Height>(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<SVGT::X, SVGT::Y, SVGT::Width, SVGT::Height,
SVGT::Rx, SVGT::Ry>(
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<SVGT::X, SVGT::Y, SVGT::Width, SVGT::Height,
SVGT::Rx, SVGT::Ry>(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<Path> SVGRectElement::BuildPath(PathBuilder* aBuilder) {
float x, y, width, height, rx, ry;
GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
MOZ_ASSERT(GetPrimaryFrame());
SVGGeometryProperty::ResolveAll<SVGT::X, SVGT::Y, SVGT::Width, SVGT::Height,
SVGT::Rx, SVGT::Ry>(this, &x, &y, &width,
&height, &rx, &ry);
if (width <= 0 || height <= 0) {
return nullptr;
@ -193,18 +215,6 @@ already_AddRefed<Path> 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<Path> 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

Просмотреть файл

@ -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<mozilla::dom::NodeInfo>&& aNodeInfo);
namespace mozilla {
class ComputedStyle;
namespace dom {
typedef SVGGeometryElement SVGRectElementBase;
@ -28,6 +31,8 @@ class SVGRectElement final : public SVGRectElementBase {
already_AddRefed<mozilla::dom::NodeInfo>&& 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<DOMSVGAnimatedLength> X();
already_AddRefed<DOMSVGAnimatedLength> Y();

Просмотреть файл

@ -124,6 +124,17 @@ class SVGViewportElement : public SVGGraphicsElement {
mViewportHeight = aSize.height;
}
/**
* Returns true if either this is an SVG <svg> element that is the child of
* another non-foreignObject SVG element, or this is a SVG <symbol> 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<SVGAnimatedRect> ViewBox();
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
@ -139,17 +150,6 @@ class SVGViewportElement : public SVGGraphicsElement {
return IsInUncomposedDoc() && !GetParent();
}
/**
* Returns true if either this is an SVG <svg> element that is the child of
* another non-foreignObject SVG element, or this is a SVG <symbol> 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.

Просмотреть файл

@ -181,6 +181,7 @@ UNIFIED_SOURCES += [
'SVGFragmentIdentifier.cpp',
'SVGGElement.cpp',
'SVGGeometryElement.cpp',
'SVGGeometryProperty.cpp',
'SVGGradientElement.cpp',
'SVGGraphicsElement.cpp',
'SVGImageElement.cpp',

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше