Merge mozilla-central to mozilla-inbound. a=merge on a CLOSED TREE

This commit is contained in:
Razvan Maries 2019-04-28 00:51:21 +03:00
Родитель 0e926d34f6 a85880b516
Коммит 8ed4c0a1dd
49 изменённых файлов: 354 добавлений и 248 удалений

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

@ -37,6 +37,8 @@
iframe.src = `data:text/html,<html><body>hey</body></html>`;
iframe.onload = () => resolve(iframe.contentDocument);
document.body.appendChild(iframe);
document.body.offsetTop; // We rely on the a11y tree being created
// already, and it's created off layout.
});
}
@ -118,7 +120,7 @@
];
break;
default:
ok(false, "Unexpected amount of states");
ok(false, "Unexpected amount of states: " + JSON.stringify(anode.states));
}
if (states) {
for (let i = 0; i < states.length; i++) {

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

@ -18,10 +18,11 @@
"chrome_settings_overrides": {
"search_provider": {
"name": "Prisjakt",
"search_url": "https://www.prisjakt.nu/#rparams=ss={searchTerms}",
"search_form": "https://www.prisjakt.nu/#rparams=ss={searchTerms}",
"search_url": "https://www.prisjakt.nu/search",
"search_url_get_params": "search={searchTerms}",
"search_form": "https://www.prisjakt.nu/search?search={searchTerms}",
"suggest_url": "https://www.prisjakt.nu/plugins/opensearch/suggestions.php",
"suggest_url_get_params": "search={searchTerms}"
}
}
}
}

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

@ -56,10 +56,12 @@ class AccessibilityStartup {
this._supports.relations,
this._supports.snapshot,
this._supports.audit,
this._supports.hydration,
] = await Promise.all([
this.target.actorHasMethod("accessible", "getRelations"),
this.target.actorHasMethod("accessible", "snapshot"),
this.target.actorHasMethod("accessible", "audit"),
this.target.actorHasMethod("accessible", "hydrate"),
]));
await this._accessibility.bootstrap();

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

@ -79,8 +79,12 @@ AccessibilityView.prototype = {
window.emit(EVENTS.NEW_ACCESSIBLE_FRONT_HIGHLIGHTED);
},
async selectNodeAccessible(walker, node) {
async selectNodeAccessible(walker, node, supports) {
let accessible = await walker.getAccessibleFor(node);
if (accessible && supports.hydration) {
await accessible.hydrate();
}
// If node does not have an accessible object, try to find node's child text node and
// try to retrieve an accessible object for that child instead. This is the best
// effort approach until there's accessibility API to retrieve accessible object at
@ -90,7 +94,13 @@ AccessibilityView.prototype = {
for (const child of children) {
if (child.nodeType === nodeConstants.TEXT_NODE) {
accessible = await walker.getAccessibleFor(child);
if (accessible && accessible.indexInParent >= 0) {
// indexInParent property is only available with additional request
// for data (hydration) about the accessible object.
if (accessible && supports.hydration) {
await accessible.hydrate();
}
if (accessible.indexInParent >= 0) {
break;
}
}

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

@ -17,5 +17,6 @@ exports.updateDetails = (domWalker, accessible, supports) =>
domWalker.getNodeFromActor(accessible.actorID, ["rawAccessible", "DOMNode"]),
supports.relations ? accessible.getRelations() : [],
supports.audit ? accessible.audit() : {},
supports.hydration ? accessible.hydrate() : null,
]).then(response => dispatch({ accessible, type: UPDATE_DETAILS, response }))
.catch(error => dispatch({ accessible, type: UPDATE_DETAILS, error }));

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

@ -8,19 +8,12 @@ const React = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { getContrastRatioScore } = require("./ColorContrastAccessibility");
const { isFiltered } = require("../utils/audit");
const { FILTERS } = require("../constants");
const { accessibility: { AUDIT_TYPE, ColorContrastScores } } =
require("devtools/shared/constants");
const { accessibility: { AUDIT_TYPE, SCORES } } = require("devtools/shared/constants");
function validateContrast({ error, value, min, isLargeText }) {
if (error) {
return false;
}
const score = getContrastRatioScore(value || min, isLargeText);
return score === ColorContrastScores.FAIL;
function validateContrast({ error, score }) {
return !error && score === SCORES.FAIL;
}
const AUDIT_TYPE_TO_FILTER = {

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

@ -11,7 +11,6 @@ const LearnMoreLink = createFactory(require("./LearnMoreLink"));
const { A11Y_CONTRAST_LEARN_MORE_LINK } = require("../constants");
const { L10N } = require("../utils/l10n");
const { accessibility: { ColorContrastScores } } = require("devtools/shared/constants");
/**
* Component that renders a colour contrast value along with a swatch preview of what the
@ -22,8 +21,8 @@ class ContrastValueClass extends Component {
return {
backgroundColor: PropTypes.array.isRequired,
color: PropTypes.array.isRequired,
isLargeText: PropTypes.bool.isRequired,
value: PropTypes.number.isRequired,
score: PropTypes.string,
};
}
@ -31,13 +30,13 @@ class ContrastValueClass extends Component {
const {
backgroundColor,
color,
isLargeText,
value,
score,
} = this.props;
const className = [
"accessibility-contrast-value",
getContrastRatioScore(value, isLargeText),
score,
].join(" ");
return (
@ -71,6 +70,9 @@ class ColorContrastAccessibilityClass extends Component {
backgroundColor: PropTypes.array,
backgroundColorMin: PropTypes.array,
backgroundColorMax: PropTypes.array,
score: PropTypes.string,
scoreMin: PropTypes.string,
scoreMax: PropTypes.string,
};
}
@ -79,9 +81,9 @@ class ColorContrastAccessibilityClass extends Component {
error,
isLargeText,
color,
value, backgroundColor,
min, backgroundColorMin,
max, backgroundColorMax,
value, backgroundColor, score,
min, backgroundColorMin, scoreMin,
max, backgroundColorMax, scoreMax,
} = this.props;
const children = [];
@ -99,17 +101,17 @@ class ColorContrastAccessibilityClass extends Component {
}
if (value) {
children.push(ContrastValue({ isLargeText, color, backgroundColor, value }));
children.push(ContrastValue({ score, color, backgroundColor, value }));
} else {
children.push(
ContrastValue(
{ isLargeText, color, backgroundColor: backgroundColorMin, value: min }),
{ score: scoreMin, color, backgroundColor: backgroundColorMin, value: min }),
div({
role: "presentation",
className: "accessibility-color-contrast-separator",
}),
ContrastValue(
{ isLargeText, color, backgroundColor: backgroundColorMax, value: max }),
{ score: scoreMax, color, backgroundColor: backgroundColorMax, value: max }),
);
}
@ -140,15 +142,12 @@ const ColorContrastAccessibility = createFactory(ColorContrastAccessibilityClass
class ContrastAnnotationClass extends Component {
static get propTypes() {
return {
isLargeText: PropTypes.bool.isRequired,
value: PropTypes.number,
min: PropTypes.number,
score: PropTypes.string,
};
}
render() {
const { isLargeText, min, value } = this.props;
const score = getContrastRatioScore(value || min, isLargeText);
const { score } = this.props;
return (
LearnMoreLink(
@ -191,31 +190,7 @@ class ColorContrastCheck extends Component {
}
}
/**
* Get contrast ratio score.
* ratio.
* @param {Number} value
* Value of the contrast ratio for a given accessible object.
* @param {Boolean} isLargeText
* True if the accessible object contains large text.
* @return {String}
* Represents the appropriate contrast ratio score.
*/
function getContrastRatioScore(value, isLargeText) {
const levels = isLargeText ? { AA: 3, AAA: 4.5 } : { AA: 4.5, AAA: 7 };
let score = ColorContrastScores.FAIL;
if (value >= levels.AAA) {
score = ColorContrastScores.AAA;
} else if (value >= levels.AA) {
score = ColorContrastScores.AA;
}
return score;
}
module.exports = {
ColorContrastAccessibility: ColorContrastAccessibilityClass,
ColorContrastCheck,
getContrastRatioScore,
};

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

@ -9,8 +9,7 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { L10N } = require("../utils/l10n");
const { getContrastRatioScore } = require("./ColorContrastAccessibility");
const { accessibility: { ColorContrastScores } } = require("devtools/shared/constants");
const { accessibility: { SCORES } } = require("devtools/shared/constants");
loader.lazyGetter(this, "Badge", () => createFactory(require("./Badge")));
@ -26,21 +25,18 @@ class ContrastBadge extends Component {
static get propTypes() {
return {
error: PropTypes.string,
isLargeText: PropTypes.bool.isRequired,
value: PropTypes.number,
min: PropTypes.number,
score: PropTypes.string,
walker: PropTypes.object.isRequired,
};
}
render() {
const { error, value, min, isLargeText, walker } = this.props;
const { error, score, walker } = this.props;
if (error) {
return null;
}
const score = getContrastRatioScore(value || min, isLargeText);
if (score !== ColorContrastScores.FAIL) {
if (score !== SCORES.FAIL) {
return null;
}

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

@ -154,7 +154,8 @@ AccessibilityPanel.prototype = {
"devtools.accessibility.select_accessible_for_node", reason, 1);
}
this.postContentMessage("selectNodeAccessible", this.walker, nodeFront);
this.postContentMessage("selectNodeAccessible", this.walker, nodeFront,
this.supports);
},
highlightAccessible(accessibleFront) {

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

@ -43,6 +43,7 @@ const tests = [{
"color": [255, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
"score": "fail",
},
},
},
@ -59,6 +60,7 @@ const tests = [{
"color": [0, 0, 255, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
"score": "AAA",
},
},
},

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

@ -62,6 +62,7 @@ describe("AuditController component:", () => {
"color": [255, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
"score": "AA",
},
},
}, span())));
@ -79,6 +80,7 @@ describe("AuditController component:", () => {
"color": [255, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
"score": "fail",
};
const wrapper = mount(Provider({store}, AuditFilter({
@ -102,6 +104,7 @@ describe("AuditController component:", () => {
"backgroundColorMin": [219, 106, 116, 1],
"backgroundColorMax": [156, 145, 211, 1],
"isLargeText": false,
"score": "fail",
};
const wrapper = mount(Provider({store}, AuditFilter({

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

@ -51,6 +51,7 @@ describe("Badges component:", () => {
"color": [255, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
"score": "AA",
},
},
})));
@ -64,6 +65,7 @@ describe("Badges component:", () => {
"color": [255, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
"score": "fail",
};
const wrapper = mount(Provider({ store }, Badges({ checks: { CONTRAST }})));
@ -81,6 +83,7 @@ describe("Badges component:", () => {
"backgroundColorMin": [219, 106, 116, 1],
"backgroundColorMax": [156, 145, 211, 1],
"isLargeText": false,
"score": "fail",
};
const wrapper = mount(Provider({ store }, Badges({ checks: { CONTRAST }})));

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

@ -29,6 +29,7 @@ describe("ContrastBadge component:", () => {
const wrapper = shallow(ContrastBadge({
value: 5.11,
isLargeText: false,
score: "AA",
}));
expect(wrapper.html()).toMatchSnapshot();
expect(wrapper.isEmptyRender()).toBe(true);
@ -39,6 +40,7 @@ describe("ContrastBadge component:", () => {
min: 5.11,
max: 6.25,
isLargeText: false,
score: "AA",
}));
expect(wrapper.html()).toMatchSnapshot();
expect(wrapper.isEmptyRender()).toBe(true);
@ -48,6 +50,7 @@ describe("ContrastBadge component:", () => {
const wrapper = shallow(ContrastBadge({
value: 3.77,
isLargeText: true,
score: "AA",
}));
expect(wrapper.html()).toMatchSnapshot();
expect(wrapper.isEmptyRender()).toBe(true);
@ -57,6 +60,7 @@ describe("ContrastBadge component:", () => {
const wrapper = mount(Provider({ store }, ContrastBadge({
value: 3.77,
isLargeText: false,
score: "fail",
})));
expect(wrapper.html()).toMatchSnapshot();

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

@ -41,6 +41,7 @@ window.onload = async function() {
"color": [255, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
"score": "fail",
})
);
@ -52,6 +53,9 @@ window.onload = async function() {
"backgroundColorMin": [219, 106, 116, 1],
"backgroundColorMax": [156, 145, 211, 1],
"isLargeText": false,
"score": "fail",
"scoreMin": "fail",
"scoreMax": "fail",
})
);
@ -61,6 +65,7 @@ window.onload = async function() {
"color": [255, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": true,
"score": "AA",
})
);
} catch (e) {

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

@ -150,7 +150,7 @@ async function testClickInInnerIframe(doc) {
const onFrameLoad = new Promise(r => {
iframe.addEventListener("load", r, true);
});
iframe.src = "data:text/html,<div id=test style='height:50px;'></div>";
iframe.srcdoc = "<div id=test style='height:50px;'></div>";
await onFrameLoad;
tooltip.setContentSize({width: 100, height: 50});

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

@ -366,16 +366,29 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
actor: this.actorID,
role: this.role,
name: this.name,
childCount: this.childCount,
checks: this._lastAudit,
};
},
/**
* Provide additional (full) information about the accessible object that is
* otherwise missing from the form.
*
* @return {Object}
* Object that contains accessible object information such as states,
* actions, attributes, etc.
*/
hydrate() {
return {
value: this.value,
description: this.description,
keyboardShortcut: this.keyboardShortcut,
childCount: this.childCount,
domNodeType: this.domNodeType,
indexInParent: this.indexInParent,
states: this.states,
actions: this.actions,
attributes: this.attributes,
checks: this._lastAudit,
};
},

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

@ -11,6 +11,7 @@ loader.lazyRequireGetter(this, "getCurrentZoom", "devtools/shared/layout/utils",
loader.lazyRequireGetter(this, "addPseudoClassLock", "devtools/server/actors/highlighters/utils/markup", true);
loader.lazyRequireGetter(this, "removePseudoClassLock", "devtools/server/actors/highlighters/utils/markup", true);
loader.lazyRequireGetter(this, "DevToolsWorker", "devtools/shared/worker/worker", true);
loader.lazyRequireGetter(this, "accessibility", "devtools/shared/constants", true);
const WORKER_URL = "resource://devtools/server/actors/accessibility/worker.js";
const HIGHLIGHTED_PSEUDO_CLASS = ":-moz-devtools-highlighted";
@ -109,6 +110,29 @@ function getImageCtx(win, bounds, zoom, scale, node) {
return ctx;
}
/**
* Get contrast ratio score based on WCAG criteria.
* @param {Number} ratio
* Value of the contrast ratio for a given accessible object.
* @param {Boolean} isLargeText
* True if the accessible object contains large text.
* @return {String}
* Value that represents calculated contrast ratio score.
*/
function getContrastRatioScore(ratio, isLargeText) {
const { SCORES: { FAIL, AA, AAA } } = accessibility;
const levels = isLargeText ? { AA: 3, AAA: 4.5 } : { AA: 4.5, AAA: 7 };
let score = FAIL;
if (ratio >= levels.AAA) {
score = AAA;
} else if (ratio >= levels.AA) {
score = AA;
}
return score;
}
/**
* Calculates the contrast ratio of the referenced DOM node.
*
@ -177,11 +201,13 @@ async function getContrastRatioFor(node, options = {}) {
}
if (rgba.value) {
const value = colorUtils.calculateContrastRatio(rgba.value, color);
return {
value: colorUtils.calculateContrastRatio(rgba.value, color),
value,
color,
backgroundColor: rgba.value,
isLargeText,
score: getContrastRatioScore(value, isLargeText),
};
}
@ -194,6 +220,8 @@ async function getContrastRatioFor(node, options = {}) {
[rgba.min, rgba.max] = [rgba.max, rgba.min];
}
const score = getContrastRatioScore(min, isLargeText);
return {
min,
max,
@ -201,6 +229,9 @@ async function getContrastRatioFor(node, options = {}) {
backgroundColorMin: rgba.min,
backgroundColorMax: rgba.max,
isLargeText,
score,
scoreMin: score,
scoreMax: getContrastRatioScore(max, isLargeText),
};
}

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

@ -22,6 +22,7 @@ loader.lazyRequireGetter(this, "isXUL", "devtools/server/actors/highlighters/uti
loader.lazyRequireGetter(this, "loadSheet", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "register", "devtools/server/actors/highlighters", true);
loader.lazyRequireGetter(this, "removeSheet", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "accessibility", "devtools/shared/constants", true);
const kStateHover = 0x00000004; // NS_EVENT_STATE_HOVER
@ -405,7 +406,10 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
const ancestries = [];
for (const [acc, audit] of report.entries()) {
if (audit && Object.values(audit).filter(check => check != null).length > 0) {
// Filter out audits that have no failing checks.
if (audit &&
Object.values(audit).some(check => check != null && !check.error &&
check.score === accessibility.SCORES.FAIL)) {
ancestries.push(this.getAncestry(acc));
}
}

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

@ -9,7 +9,7 @@ const { getCurrentZoom, getViewportDimensions } = require("devtools/shared/layou
const { moveInfobar, createNode } = require("./markup");
const { truncateString } = require("devtools/shared/inspector/utils");
const { accessibility: { ColorContrastScores } } = require("devtools/shared/constants");
const { accessibility: { SCORES } } = require("devtools/shared/constants");
const STRINGS_URI = "devtools/shared/locales/accessibility.properties";
loader.lazyRequireGetter(this, "LocalizationHelper", "devtools/shared/l10n", true);
@ -527,11 +527,10 @@ class ContrastRatio extends AuditReport {
});
}
_fillAndStyleContrastValue(el, { value, isLargeText, color, backgroundColor }) {
_fillAndStyleContrastValue(el, { value, className, color, backgroundColor }) {
value = value.toFixed(2);
const style = getContrastRatioScoreStyle(value, isLargeText);
this.setTextContent(el, value);
el.classList.add(style);
el.classList.add(className);
el.setAttribute("style",
`--accessibility-highlighter-contrast-ratio-color: rgba(${color});` +
`--accessibility-highlighter-contrast-ratio-bg: rgba(${backgroundColor});`);
@ -551,7 +550,7 @@ class ContrastRatio extends AuditReport {
for (const key of ["label", "min", "max", "error", "separator"]) {
const el = els[key] = this.getElement(`contrast-ratio-${key}`);
if (["min", "max"].includes(key)) {
Object.values(ColorContrastScores).forEach(
Object.values(SCORES).forEach(
className => el.classList.remove(className));
this.setTextContent(el, "");
}
@ -574,18 +573,20 @@ class ContrastRatio extends AuditReport {
}
if (contrastRatio.value) {
const { value, color, backgroundColor } = contrastRatio;
const { value, color, score, backgroundColor } = contrastRatio;
this._fillAndStyleContrastValue(els.min,
{ value, isLargeText, color, backgroundColor });
{ value, className: score, color, backgroundColor });
return true;
}
const { min, max, color, backgroundColorMin, backgroundColorMax } = contrastRatio;
const {
min, max, color, backgroundColorMin, backgroundColorMax, scoreMin, scoreMax,
} = contrastRatio;
this._fillAndStyleContrastValue(els.min,
{ value: min, isLargeText, color, backgroundColor: backgroundColorMin });
{ value: min, className: scoreMin, color, backgroundColor: backgroundColorMin });
els.separator.removeAttribute("hidden");
this._fillAndStyleContrastValue(els.max,
{ value: max, isLargeText, color, backgroundColor: backgroundColorMax });
{ value: max, className: scoreMax, color, backgroundColor: backgroundColorMax });
return true;
}
@ -646,29 +647,6 @@ function getBounds(win, { x, y, w, h, zoom }) {
return { left, right, top, bottom, width, height };
}
/**
* Get contrast ratio score styling to be applied on the element that renders the contrast
* ratio.
* @param {Number} ratio
* Value of the contrast ratio for a given accessible object.
* @param {Boolean} isLargeText
* True if the accessible object contains large text.
* @return {String}
* CSS class that represents the appropriate contrast ratio score styling.
*/
function getContrastRatioScoreStyle(ratio, isLargeText) {
const levels = isLargeText ? { AA: 3, AAA: 4.5 } : { AA: 4.5, AAA: 7 };
let style = ColorContrastScores.FAIL;
if (ratio >= levels.AAA) {
style = ColorContrastScores.AAA;
} else if (ratio >= levels.AA) {
style = ColorContrastScores.AA;
}
return style;
}
exports.MAX_STRING_LENGTH = MAX_STRING_LENGTH;
exports.getBounds = getBounds;
exports.Infobar = Infobar;

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

@ -16,6 +16,14 @@ add_task(async function() {
const buttonNode = await walker.querySelector(walker.rootNode, "#button");
const accessibleFront = await a11yWalker.getAccessibleFor(buttonNode);
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "pushbutton",
childCount: 1,
});
await accessibleFront.hydrate();
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "pushbutton",

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

@ -37,6 +37,7 @@ add_task(async function() {
"color": [0, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": true,
score: "AAA",
},
});

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

@ -21,6 +21,14 @@ add_task(async function() {
const accessibleSliderFront = await a11yWalker.getAccessibleFor(sliderNode);
const browser = gBrowser.selectedBrowser;
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "pushbutton",
childCount: 1,
});
await accessibleFront.hydrate();
checkA11yFront(accessibleFront, {
name: "Accessible Button",
role: "pushbutton",
@ -92,6 +100,7 @@ add_task(async function() {
content.document.getElementById("button").setAttribute("aria-live", "polite")));
info("Value change event");
await accessibleSliderFront.hydrate();
checkA11yFront(accessibleSliderFront, { value: "5" });
await emitA11yEvent(accessibleSliderFront, "value-change",
() => checkA11yFront(accessibleSliderFront, { value: "6" }),
@ -101,6 +110,7 @@ add_task(async function() {
info("Reorder event");
is(accessibleSliderFront.childCount, 1, "Slider has only 1 child");
const [firstChild ] = await accessibleSliderFront.children();
await firstChild.hydrate();
is(firstChild.indexInParent, 0, "Slider's first child has correct index in parent");
await emitA11yEvent(accessibleSliderFront, "reorder",
childCount => {

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

@ -12,27 +12,7 @@ add_task(async function() {
const accessibles = [{
name: "",
role: "document",
value: "",
description: "",
keyboardShortcut: "",
childCount: 2,
domNodeType: 9,
indexInParent: 0,
states: [
"focused", "readonly", "focusable", "active", "opaque", "enabled", "sensitive",
],
actions: [],
attributes: {
display: "block",
"explicit-name": "true",
"margin-bottom": "8px",
"margin-left": "8px",
"margin-right": "8px",
"margin-top": "8px",
tag: "body",
"text-align": "start",
"text-indent": "0px",
},
checks: {
"CONTRAST": null,
},
@ -40,27 +20,7 @@ add_task(async function() {
name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
"eiusmod tempor incididunt ut labore et dolore magna aliqua.",
role: "heading",
value: "",
description: "",
keyboardShortcut: "",
childCount: 1,
domNodeType: 1,
indexInParent: 0,
states: [ "selectable text", "opaque", "enabled", "sensitive" ],
actions: [],
attributes: {
display: "block",
formatting: "block",
id: "h1",
level: "1",
"margin-bottom": "21.4333px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "21.4333px",
tag: "h1",
"text-align": "start",
"text-indent": "0px",
},
checks: {
"CONTRAST": null,
},
@ -68,15 +28,7 @@ add_task(async function() {
name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
"eiusmod tempor incididunt ut labore et dolore magna aliqua.",
role: "text leaf",
value: "",
description: "",
keyboardShortcut: "",
childCount: 0,
domNodeType: 3,
indexInParent: 0,
states: [ "opaque", "enabled", "sensitive" ],
actions: [],
attributes: { "explicit-name": "true" },
checks: {
"CONTRAST": {
"value": 21,
@ -88,41 +40,14 @@ add_task(async function() {
}, {
name: "",
role: "paragraph",
value: "",
description: "",
keyboardShortcut: "",
childCount: 1,
domNodeType: 1,
indexInParent: 1,
states: [ "selectable text", "opaque", "enabled", "sensitive" ],
actions: [ "Press" ],
attributes: {
display: "block",
formatting: "block",
id: "p",
"margin-bottom": "16px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "16px",
tag: "p",
"text-align": "start",
"text-indent": "0px",
},
checks: {
"CONTRAST": null,
},
}, {
name: "Accessible Paragraph",
role: "text leaf",
value: "",
description: "",
keyboardShortcut: "",
childCount: 0,
domNodeType: 3,
indexInParent: 0,
states: [ "opaque", "enabled", "sensitive" ],
actions: [],
attributes: { "explicit-name": "true" },
checks: {
"CONTRAST": {
"value": 21,

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

@ -17,7 +17,7 @@ exports.accessibility = {
},
// Constants associated with WCAG guidelines score system:
// failing -> AA -> AAA;
ColorContrastScores: {
SCORES: {
FAIL: "fail",
AA: "AA",
AAA: "AAA",

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

@ -85,7 +85,8 @@ class AccessibleFront extends FrontClassWithSpec(accessibleSpec) {
form(form) {
this.actorID = form.actor;
this._form = form;
this._form = this._form || {};
Object.assign(this._form, form);
}
nameChange(name, parent, walker) {
@ -145,6 +146,12 @@ class AccessibleFront extends FrontClassWithSpec(accessibleSpec) {
audited(checks) {
this._form.checks = checks;
}
hydrate() {
return super.hydrate().then(properties => {
Object.assign(this._form, properties);
});
}
}
class AccessibleWalkerFront extends FrontClassWithSpec(accessibleWalkerSpec) {

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

@ -102,6 +102,12 @@ const accessibleSpec = generateActorSpec({
relations: RetVal("array:accessibleRelation"),
},
},
hydrate: {
request: {},
response: {
properties: RetVal("json"),
},
},
snapshot: {
request: {},
response: {

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

@ -117,6 +117,9 @@
l3.detach();
l4.detach();
// swapDocShells reflows asynchronously, ensure layout is
// clean so that the viewport of f1 is the right size.
$("f1").getBoundingClientRect();
var s1_new = snapshotWindow($("f1").contentWindow);
var [same, first, second] = compareSnapshots(s1_new, s2, true);
ok(same, "Should reflow on swap. Expected " + second + " but got " + first);

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

@ -7,14 +7,29 @@
<script src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<script type="application/javascript">
function navigateAway() {
// Anchor clicks are only handled if we have a pres-context, and we may not
// have one yet by the time this runs, and getBoundingClientRect() won't
// construct it after bug 1440537.
//
// So we may need to wait a few frames to make this reliable.
//
// FIXME(emilio, bug 1218456): This dance shouldn't be needed.
let anchor = document.getElementById("anchor");
if (anchor.getBoundingClientRect().width > 0)
anchor.click();
else
requestAnimationFrame(navigateAway);
}
function doTest() {
// this should fail the first time, but work the second
try {
// this should fail the first time, but work the second
window.parent.ok_wrapper(true, "a document that was loaded, navigated to another document, had 'allow-same-origin' added and then was" +
" navigated back should be same-origin with its parent");
}
catch (e) {
sendMouseEvent({type:'click'}, 'anchor');
} catch (e) {
navigateAway();
}
}

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

@ -19,11 +19,13 @@
#include "mozilla/SVGContextPaint.h"
#include "mozilla/TextUtils.h"
#include "nsComputedDOMStyle.h"
#include "nsContainerFrame.h"
#include "nsFontMetrics.h"
#include "nsIFrame.h"
#include "nsIScriptError.h"
#include "nsLayoutUtils.h"
#include "nsMathUtils.h"
#include "nsSVGUtils.h"
#include "nsWhitespaceTokenizer.h"
#include "SVGAnimationElement.h"
#include "SVGAnimatedPreserveAspectRatio.h"
@ -466,15 +468,37 @@ SVGViewportElement* SVGContentUtils::GetNearestViewportElement(
static gfx::Matrix GetCTMInternal(SVGElement* aElement, bool aScreenCTM,
bool aHaveRecursed) {
gfxMatrix matrix = aElement->PrependLocalTransformsTo(
gfxMatrix(), aHaveRecursed ? eAllTransforms : eUserSpaceToParent);
auto getLocalTransformHelper =
[](SVGElement const* e, bool shouldIncludeChildToUserSpace) -> gfxMatrix {
gfxMatrix ret;
if (auto* f = e->GetPrimaryFrame()) {
ret = nsSVGUtils::GetTransformMatrixInUserSpace(f);
} else {
// FIXME: Ideally we should also return the correct matrix
// for display:none, but currently transform related code relies
// heavily on the present of a frame.
// For now we just fall back to |PrependLocalTransformsTo| which
// doesn't account for CSS transform.
ret = e->PrependLocalTransformsTo({}, eUserSpaceToParent);
}
if (shouldIncludeChildToUserSpace) {
ret = e->PrependLocalTransformsTo({}, eChildToUserSpace) * ret;
}
return ret;
};
gfxMatrix matrix = getLocalTransformHelper(aElement, aHaveRecursed);
SVGElement* element = aElement;
nsIContent* ancestor = aElement->GetFlattenedTreeParent();
while (ancestor && ancestor->IsSVGElement() &&
!ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
element = static_cast<SVGElement*>(ancestor);
matrix *= element->PrependLocalTransformsTo(gfxMatrix()); // i.e. *A*ppend
matrix *= getLocalTransformHelper(element, true);
if (!aScreenCTM && SVGContentUtils::EstablishesViewport(element)) {
if (!element->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG) &&
!element->NodeInfo()->Equals(nsGkAtoms::symbol, kNameSpaceID_SVG)) {
@ -501,7 +525,7 @@ static gfx::Matrix GetCTMInternal(SVGElement* aElement, bool aScreenCTM,
// transforms in this case since that's what we've been doing for
// a while, and it keeps us consistent with WebKit and Opera (if not
// really with the ambiguous spec).
matrix = aElement->PrependLocalTransformsTo(gfxMatrix());
matrix = getLocalTransformHelper(aElement, true);
}
if (auto* f = element->GetPrimaryFrame()) {

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

@ -9,6 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366697
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style>
#padsvg1 { padding-left: 27px; padding-top: 43px; }
#transrect1 { transform: scale(2,3); }
</style>
</head>
<body>
@ -19,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366697
<iframe id="svg" src="getCTM-helper.svg"></iframe>
<svg id="padsvg1" width="100" height="100">
<rect width="10" height="10" />
<rect id="transrect1" width="10" height="10" />
</svg>
<pre id="test">
@ -34,6 +35,10 @@ function runTest() {
is(buggy.getCTM().e, 30, "buggy.getCTM().e");
is(buggy.getCTM().f, 40, "buggy.getCTM().f");
var transrect1 = document.getElementById("transrect1");
is(transrect1.getCTM().a, 2, "transrect1.getCTM().a");
is(transrect1.getCTM().d, 3, "transrect1.getCTM().d");
var padsvg1 = document.getElementById("padsvg1");
is(padsvg1.getScreenCTM().e - padsvg1.getBoundingClientRect().x, 27, "padsvg1.getScreenCTM().e");
is(padsvg1.getScreenCTM().f - padsvg1.getBoundingClientRect().y, 43, "padsvg1.getScreenCTM().f");

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

@ -0,0 +1,3 @@
<!doctype html>
<img src="data:image/svg+xml,<svg width='90px' xmlns='http://www.w3.org/2000/svg'></svg>" style="position: absolute;">
<img src="data:image/svg+xml,<svg height='90px' xmlns='http://www.w3.org/2000/svg'></svg>" style="position: absolute;">

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

@ -568,4 +568,4 @@ pref(layout.css.column-span.enabled,true) load 1534146.html
pref(layout.css.column-span.enabled,true) load 1539017.html
load 1539303.html
pref(layout.css.column-span.enabled,true) load 1541679.html
load 1547261.html

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

@ -2410,7 +2410,7 @@ nsIFrame::LogicalSides nsImageFrame::GetLogicalSkipSides(
}
nsresult nsImageFrame::GetIntrinsicImageSize(nsSize& aSize) {
if (mIntrinsicSize.width && mIntrinsicSize.width) {
if (mIntrinsicSize.width && mIntrinsicSize.height) {
aSize.SizeTo(*mIntrinsicSize.width, *mIntrinsicSize.height);
return NS_OK;
}

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

@ -1,7 +1,8 @@
<svg style="width: 500px; height: 500px; border: 1px solid green;">
<defs>
<mask id="mask">
<rect id="square" x="200px" y="250px" width="100px" height="150px" fill="#ffffff" />
<rect x="200px" y="250px" width="100px" height="150px" fill="#ffffff" />
<rect x="50px" y="105px" width="110px" height="195px" fill="blue" />
</mask>
</defs>
<rect mask="url(#mask)" width="500px" height="500px" fill="red" />

До

Ширина:  |  Высота:  |  Размер: 287 B

После

Ширина:  |  Высота:  |  Размер: 350 B

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

@ -1,12 +1,18 @@
<style>
#square{
#square1 {
transform: translate(100px, 100px) scale(2,3);
}
#square2 {
transform: scale(2,3);
}
</style>
<svg style="width: 500px; height: 500px; border: 1px solid green;">
<defs>
<mask id="mask">
<rect id="square" x="50px" y="50px" width="50px" height="50px" fill="#ffffff" />
<rect id="square1" x="50px" y="50px" width="50px" height="50px" fill="#ffffff" />
<svg viewBox="0 0 100 100">
<rect id="square2" x="5" y="7" width="11" height="13" fill="blue" />
</svg>
</mask>
</defs>
<rect mask="url(#mask)" width="500px" height="500px" fill="red" />

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

@ -156,11 +156,9 @@ function run() {
var sheeturl = "data:text/css," + escape(sheet);
var link = "<link rel='stylesheet' href='" + sheeturl + "'>";
var htmldoc = "<!DOCTYPE HTML>" + link + link + "<body>";
var docurl = "data:text/html," + escape(htmldoc);
post_clone_test(docurl, function() {
var wrappedFrame = SpecialPowers.wrap(iframe);
var clonedoc = wrappedFrame.contentDocument;
var clonewin = wrappedFrame.contentWindow;
post_clone_test(htmldoc, function() {
var clonedoc = iframe.contentDocument;
var clonewin = iframe.contentWindow;
var links = clonedoc.getElementsByTagName("link");
// cause a clone
var clonedsheet = links[1].sheet;
@ -891,9 +889,9 @@ function change_state(func)
posted_items.push({state: func});
}
function post_clone_test(docurl, testfunc)
function post_clone_test(srcdoc, testfunc)
{
posted_items.push({docurl: docurl, testfunc: testfunc});
posted_items.push({srcdoc, testfunc});
}
function handle_posted_items()
@ -910,9 +908,9 @@ function handle_posted_items()
return;
}
var docurl = posted_items[0].docurl;
var srcdoc = posted_items[0].srcdoc;
iframe.onload = handle_iframe_onload;
iframe.src = docurl;
iframe.srcdoc = srcdoc;
}
function handle_iframe_onload(event)

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

@ -59,7 +59,7 @@ void nsSVGClipPathFrame::ApplyClipPath(gfxContext& aContext,
static_cast<SVGGeometryElement*>(pathFrame->GetContent());
gfxMatrix toChildsUserSpace =
nsSVGUtils::GetTransformMatrixInUserSpace(pathFrame, this) *
nsSVGUtils::GetTransformMatrixInUserSpace(pathFrame) *
(GetClipPathTransform(aClippedFrame) * aMatrix);
gfxMatrix newMatrix = aContext.CurrentMatrixDouble()
@ -220,8 +220,7 @@ void nsSVGClipPathFrame::PaintFrameIntoMask(nsIFrame* aFrame,
nsIContent* childContent = child->GetContent();
if (childContent->IsSVGElement()) {
toChildsUserSpace =
nsSVGUtils::GetTransformMatrixInUserSpace(child, child->GetParent()) *
mMatrixForChildren;
nsSVGUtils::GetTransformMatrixInUserSpace(child) * mMatrixForChildren;
}
// clipPath does not result in any image rendering, so we just use a dummy
@ -302,7 +301,7 @@ bool nsSVGClipPathFrame::PointIsInsideClipPath(nsIFrame* aClippedFrame,
if (SVGFrame) {
gfxPoint pointForChild = point;
gfxMatrix m = nsSVGUtils::GetTransformMatrixInUserSpace(kid, this);
gfxMatrix m = nsSVGUtils::GetTransformMatrixInUserSpace(kid);
if (!m.IsIdentity()) {
if (!m.Invert()) {
return false;
@ -428,9 +427,8 @@ gfxMatrix nsSVGClipPathFrame::GetCanvasTM() { return mMatrixForChildren; }
gfxMatrix nsSVGClipPathFrame::GetClipPathTransform(nsIFrame* aClippedFrame) {
SVGClipPathElement* content = static_cast<SVGClipPathElement*>(GetContent());
gfxMatrix tm =
content->PrependLocalTransformsTo({}, eChildToUserSpace) *
nsSVGUtils::GetTransformMatrixInUserSpace(this, this->GetParent());
gfxMatrix tm = content->PrependLocalTransformsTo({}, eChildToUserSpace) *
nsSVGUtils::GetTransformMatrixInUserSpace(this);
SVGAnimatedEnumeration* clipPathUnits =
&content->mEnumAttributes[SVGClipPathElement::CLIPPATHUNITS];
@ -464,7 +462,7 @@ SVGBBox nsSVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox& aBBox,
nsSVGDisplayableFrame* svg = do_QueryFrame(frame);
if (svg) {
gfxMatrix matrix =
nsSVGUtils::GetTransformMatrixInUserSpace(frame, this) * aMatrix;
nsSVGUtils::GetTransformMatrixInUserSpace(frame) * aMatrix;
tmpBBox = svg->GetBBoxContribution(mozilla::gfx::ToMatrix(matrix),
nsSVGUtils::eBBoxIncludeFill);
nsSVGClipPathFrame* clipPathFrame;

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

@ -261,7 +261,7 @@ void nsSVGDisplayContainerFrame::PaintSVG(gfxContext& aContext,
continue; // nothing to paint for kid
}
m = nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) * m;
m = nsSVGUtils::GetTransformMatrixInUserSpace(kid) * m;
if (m.IsSingular()) {
continue;
}
@ -392,8 +392,7 @@ SVGBBox nsSVGDisplayContainerFrame::GetBBoxContribution(
if (content->IsSVGElement()) {
transform = static_cast<SVGElement*>(content)->PrependLocalTransformsTo(
{}, eChildToUserSpace) *
nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) *
transform;
nsSVGUtils::GetTransformMatrixInUserSpace(kid) * transform;
}
// We need to include zero width/height vertical/horizontal lines, so we
// have to use UnionEdges.

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

@ -118,7 +118,7 @@ already_AddRefed<SourceSurface> nsSVGMaskFrame::GetMaskForMaskedFrame(
nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
m = nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) * m;
m = nsSVGUtils::GetTransformMatrixInUserSpace(kid) * m;
}
nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, aParams.imgParams);

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

@ -361,9 +361,7 @@ already_AddRefed<SourceSurface> nsSVGPatternFrame::PaintPattern(
nsSVGDisplayableFrame *SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
tm = nsSVGUtils::GetTransformMatrixInUserSpace(kid,
patternWithChildren) *
tm;
tm = nsSVGUtils::GetTransformMatrixInUserSpace(kid) * tm;
}
nsSVGUtils::PaintFrameWithEffects(kid, *ctx, tm, aImgParams);

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

@ -103,7 +103,7 @@ void nsSVGSwitchFrame::PaintSVG(gfxContext& aContext,
if (kid) {
gfxMatrix tm = aTransform;
if (kid->GetContent()->IsSVGElement()) {
tm = nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) * tm;
tm = nsSVGUtils::GetTransformMatrixInUserSpace(kid) * tm;
}
nsSVGUtils::PaintFrameWithEffects(kid, aContext, tm, aImgParams,
aDirtyRect);
@ -255,8 +255,7 @@ SVGBBox nsSVGSwitchFrame::GetBBoxContribution(const Matrix& aToBBoxUserspace,
if (content->IsSVGElement()) {
transform = static_cast<SVGElement*>(content)->PrependLocalTransformsTo(
{}, eChildToUserSpace) *
nsSVGUtils::GetTransformMatrixInUserSpace(kid, this) *
transform;
nsSVGUtils::GetTransformMatrixInUserSpace(kid) * transform;
}
return svgKid->GetBBoxContribution(ToMatrix(transform), aFlags);
}

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

@ -28,6 +28,7 @@
#include "nsPresContext.h"
#include "nsStyleCoord.h"
#include "nsStyleStruct.h"
#include "nsStyleTransformMatrix.h"
#include "SVGAnimatedLength.h"
#include "nsSVGClipPathFrame.h"
#include "nsSVGContainerFrame.h"
@ -1094,9 +1095,8 @@ gfxRect nsSVGUtils::GetBBox(nsIFrame* aFrame, uint32_t aFlags,
matrix = gfxMatrix();
}
matrix = nsSVGUtils::GetTransformMatrixInUserSpace(
clipPathFrame, clipPathFrame->GetParent()) *
matrix;
matrix =
nsSVGUtils::GetTransformMatrixInUserSpace(clipPathFrame) * matrix;
bbox = clipPathFrame->GetBBoxForClipPathFrame(bbox, matrix, aFlags)
.ToThebesRect();
@ -1251,8 +1251,8 @@ bool nsSVGUtils::GetNonScalingStrokeTransform(nsIFrame* aFrame,
MOZ_ASSERT(aFrame->GetContent()->IsSVGElement(), "should be an SVG element");
nsSVGOuterSVGFrame* outer = nsSVGUtils::GetOuterSVGFrame(aFrame);
*aUserToOuterSVG = nsSVGUtils::GetTransformMatrixInUserSpace(aFrame, outer);
*aUserToOuterSVG = ThebesMatrix(SVGContentUtils::GetCTM(
static_cast<SVGElement*>(aFrame->GetContent()), true));
return aUserToOuterSVG->HasNonTranslation();
}
@ -1642,7 +1642,7 @@ void nsSVGUtils::PaintSVGGlyph(Element* aElement, gfxContext* aContext) {
if (frame->GetContent()->IsSVGElement()) {
// PaintSVG() expects the passed transform to be the transform to its own
// SVG user space, so we need to account for any 'transform' attribute:
m = nsSVGUtils::GetTransformMatrixInUserSpace(frame, frame->GetParent());
m = nsSVGUtils::GetTransformMatrixInUserSpace(frame);
}
// SVG-in-OpenType is not allowed to paint external resources, so we can
@ -1696,29 +1696,49 @@ gfxMatrix nsSVGUtils::GetCSSPxToDevPxMatrix(nsIFrame* aNonSVGFrame) {
return gfxMatrix(devPxPerCSSPx, 0.0, 0.0, devPxPerCSSPx, 0.0, 0.0);
}
gfxMatrix nsSVGUtils::GetTransformMatrixInUserSpace(const nsIFrame* aFrame,
const nsIFrame* aAncestor) {
gfxMatrix nsSVGUtils::GetTransformMatrixInUserSpace(const nsIFrame* aFrame) {
// We check element instead of aFrame directly because SVG element
// may have non-SVG frame, <tspan> for example.
MOZ_ASSERT(aFrame->GetContent() && aFrame->GetContent()->IsSVGElement(),
"Only use this wrapper for SVG elements");
if (!aFrame->IsTransformed()) {
return {};
}
nsDisplayTransform::FrameTransformProperties properties{
aFrame, AppUnitsPerCSSPixel(), nullptr};
nsStyleTransformMatrix::TransformReferenceBox refBox;
refBox.Init(aFrame);
// SVG elements can have x/y offset, their default transform origin
// is the origin of user space, not the top left point of the frame.
Point3D svgTransformOrigin{
properties.mToTransformOrigin.x - CSSPixel::FromAppUnits(refBox.X()),
properties.mToTransformOrigin.y - CSSPixel::FromAppUnits(refBox.Y()),
properties.mToTransformOrigin.z};
Matrix svgTransform;
Matrix4x4 trans;
(void)aFrame->IsSVGTransformed(&svgTransform);
if (properties.HasTransform()) {
trans = nsStyleTransformMatrix::ReadTransforms(
properties.mIndividualTransformList
? properties.mIndividualTransformList->mHead
: nullptr,
properties.mMotion,
properties.mTransformList ? properties.mTransformList->mHead : nullptr,
refBox, AppUnitsPerCSSPixel());
} else {
trans = Matrix4x4::From2D(svgTransform);
}
trans.ChangeBasis(svgTransformOrigin);
Matrix mm;
auto trans = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor,
nsIFrame::IN_CSS_UNITS);
trans.ProjectTo2D();
trans.CanDraw2D(&mm);
gfxMatrix ret = ThebesMatrix(mm);
(void)trans.CanDraw2D(&mm);
float initPositionX = NSAppUnitsToFloatPixels(aFrame->GetPosition().x,
AppUnitsPerCSSPixel()),
initPositionY = NSAppUnitsToFloatPixels(aFrame->GetPosition().y,
AppUnitsPerCSSPixel());
// Remove the initial displacement to mimic the behavior
// of SVGElement::PrependLocalTransformsTo().
ret = ret.PreTranslate(-initPositionX, -initPositionY);
return ret;
return ThebesMatrix(mm);
}

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

@ -597,11 +597,13 @@ class nsSVGUtils {
}
/**
* A simple wrapper of nsLayoutUtils::GetTransformToAncestor to avoid
* boilerplate code for changing unit and matrix format.
* It is a replacement of
* SVGElement::PrependLocalTransformsTo(eUserSpaceToParent).
* If no CSS transform is involved, they should behave exactly the same;
* if there are CSS transforms, this one will take them into account
* while SVGElement::PrependLocalTransformsTo won't.
*/
static gfxMatrix GetTransformMatrixInUserSpace(const nsIFrame* aFrame,
const nsIFrame* aAncestor);
static gfxMatrix GetTransformMatrixInUserSpace(const nsIFrame* aFrame);
};
#endif

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

@ -9,6 +9,8 @@
<Url type="application/x-suggestions+json" method="GET" template="https://www.prisjakt.nu/plugins/opensearch/suggestions.php">
<Param name="search" value="{searchTerms}"/>
</Url>
<Url type="text/html" method="GET" template="https://m.prisjakt.nu/search/{searchTerms}"/>
<Url type="text/html" method="GET" template="https://www.prisjakt.nu/search">
<Param name="search" value="{searchTerms}"/>
</Url>
<Url type="application/x-moz-tabletsearch" method="GET" template="https://www.prisjakt.nu/#rparams=ss={searchTerms}"/>
</SearchPlugin>

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

@ -63,6 +63,9 @@ add_task(async function test_target_blank_link() {
let link = win.document.getElementById("link");
{
// Flush layout so that synthesizeMouseAtCenter on a cross-origin iframe
// works as expected.
document.body.getBoundingClientRect();
synthesizeMouseAtCenter(link, {}, iframe.contentWindow);
let {subject: doc} = await promiseObserved("document-element-inserted", doc => doc.documentURI === linkURL);
info("Link opened");

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

@ -2144,6 +2144,36 @@ telemetry:
- 'main'
- 'content'
ecosystem_old_send_time:
bug_numbers:
- 1545365
description: >
The timestamp im milliseconds of the last time we tried to send an Ecosystem ping
expires: "73"
kind: string
notification_emails:
- jrediger@mozilla.com
release_channel_collection: opt-in
record_in_processes:
- 'main'
record_into_store:
- 'pre-account'
ecosystem_new_send_time:
bug_numbers:
- 1545365
description: >
The timestamp im milliseconds of the last time we tried to send an Ecosystem ping
expires: "73"
kind: string
notification_emails:
- jrediger@mozilla.com
release_channel_collection: opt-in
record_in_processes:
- 'main'
record_into_store:
- 'pre-account'
telemetry.discarded:
accumulations:
bug_numbers:

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

@ -216,10 +216,21 @@ var EcosystemTelemetry = {
this._log.trace(`_submitPing, ping type: ${pingType}, reason: ${reason}`);
let now = Policy.monotonicNow();
let new_send_time = now;
let old_send_time = this._lastSendTime;
// Duration in seconds
let duration = Math.round((now - this._lastSendTime) / 1000);
this._lastSendTime = now;
// FIXME(bug 1545365): This is a hack to track the values we see,
// in order to determine where negative durations are coming from.
// Note: These scalars must be set _before_ getting the rest of the payload.
// Note: We don't support signed integer scalars, so we convert these to strings
// in order to also capture the negative values.
Services.telemetry.scalarSet("telemetry.ecosystem_old_send_time", old_send_time.toString());
Services.telemetry.scalarSet("telemetry.ecosystem_new_send_time", new_send_time.toString());
let payload = this._payload(reason, duration);
// Never include the client ID.

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

@ -51,6 +51,9 @@ function checkPingStructure(ping, type, reason) {
Assert.ok("keyedScalars" in payload, "Payload must contain keyed scalars");
Assert.ok("histograms" in payload, "Payload must contain histograms");
Assert.ok("keyedHistograms" in payload, "Payload must contain keyed histograms");
Assert.ok("telemetry.ecosystem_old_send_time" in payload.scalars.parent, "Old send time should be set");
Assert.ok("telemetry.ecosystem_new_send_time" in payload.scalars.parent, "New send time should be set");
}
function sendPing() {

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

@ -6700,6 +6700,11 @@ function runTestOnAnotherContext(aPanelOrFrame, aFocusedEditor, aTestName)
{
aFocusedEditor.value = "";
// The frames and panel are cross-origin, and we no longer
// propagate flushes to parent cross-origin iframes explicitly,
// so flush our own layout here so the positions are correct.
document.documentElement.getBoundingClientRect();
var editorRect = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRect, aTestName + ": editorRect")) {
return;