зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1564993 - Create simulator actor and front, r=yzen,nchevobbe
Differential Revision: https://phabricator.services.mozilla.com/D38884 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
2b2064b0e4
Коммит
deacf348f4
|
@ -16,7 +16,19 @@ loader.lazyRequireGetter(
|
|||
"devtools/server/actors/accessibility/walker",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"SimulatorActor",
|
||||
"devtools/server/actors/accessibility/simulator",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(this, "events", "devtools/shared/event-emitter");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"isWebRenderEnabled",
|
||||
"devtools/server/actors/utils/accessibility",
|
||||
true
|
||||
);
|
||||
|
||||
const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
|
||||
|
||||
|
@ -262,6 +274,29 @@ const AccessibilityActor = ActorClassWithSpec(accessibilitySpec, {
|
|||
return this.walker;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get or create Simulator actor, managed by AccessibilityActor,
|
||||
* only if webrender is enabled. Simulator applies color filters on an entire viewport.
|
||||
* This needs to be done using webrender and not an SVG <feColorMatrix> since it is
|
||||
* accelerated and scrolling with filter applied needs to be smooth (Bug1431466).
|
||||
*
|
||||
* @return {Object|null}
|
||||
* SimulatorActor for the current tab.
|
||||
*/
|
||||
getSimulator() {
|
||||
// TODO: Remove this check after Bug1570667
|
||||
if (!isWebRenderEnabled(this.targetActor.window)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.simulator) {
|
||||
this.simulator = new SimulatorActor(this.conn, this.targetActor);
|
||||
this.manage(this.simulator);
|
||||
}
|
||||
|
||||
return this.simulator;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy accessibility service actor. This method also shutsdown
|
||||
* accessibility service if possible.
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
accessibility: {
|
||||
SIMULATION_TYPE: {
|
||||
DEUTERANOMALY,
|
||||
PROTANOMALY,
|
||||
TRITANOMALY,
|
||||
DEUTERANOPIA,
|
||||
PROTANOPIA,
|
||||
TRITANOPIA,
|
||||
CONTRAST_LOSS,
|
||||
},
|
||||
},
|
||||
} = require("devtools/shared/constants");
|
||||
|
||||
/**
|
||||
* Constants used in accessibility actors.
|
||||
*/
|
||||
|
||||
// Color blindness matrix values taken from https://github.com/eeejay/NoCoffee/blob/master/popup.js#L5-L10
|
||||
// Contrast loss matrix values are for 50% contrast (see https://docs.rainmeter.net/tips/colormatrix-guide/,
|
||||
// and https://stackoverflow.com/questions/23865511/contrast-with-color-matrix). The matrices are flattened
|
||||
// 4x5 matrices, needed for docShell setColorMatrix method. i.e. A 4x5 matrix of the form:
|
||||
// 1 2 3 4 5
|
||||
// 6 7 8 9 10
|
||||
// 11 12 13 14 15
|
||||
// 16 17 18 19 20
|
||||
// will be need to be set in docShell as:
|
||||
// [1, 6, 11, 16, 2, 7, 12, 17, 3, 8, 13, 18, 4, 9, 14, 19, 5, 10, 15, 20]
|
||||
const COLOR_TRANSFORMATION_MATRICES = {
|
||||
NONE: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
|
||||
[PROTANOMALY]: [
|
||||
0.817,
|
||||
0.333,
|
||||
0,
|
||||
0,
|
||||
0.183,
|
||||
0.667,
|
||||
0.125,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.875,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[DEUTERANOMALY]: [
|
||||
0.8,
|
||||
0.258,
|
||||
0,
|
||||
0,
|
||||
0.2,
|
||||
0.742,
|
||||
0.142,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.858,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[TRITANOMALY]: [
|
||||
0.967,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.033,
|
||||
0.733,
|
||||
0.183,
|
||||
0,
|
||||
0,
|
||||
0.267,
|
||||
0.817,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[PROTANOPIA]: [
|
||||
0.567,
|
||||
0.558,
|
||||
0,
|
||||
0,
|
||||
0.433,
|
||||
0.442,
|
||||
0.242,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.758,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[DEUTERANOPIA]: [
|
||||
0.625,
|
||||
0.7,
|
||||
0,
|
||||
0,
|
||||
0.375,
|
||||
0.3,
|
||||
0.3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.7,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[TRITANOPIA]: [
|
||||
0.95,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.05,
|
||||
0.433,
|
||||
0.475,
|
||||
0,
|
||||
0,
|
||||
0.567,
|
||||
0.525,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[CONTRAST_LOSS]: [
|
||||
0.5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.5,
|
||||
0.25,
|
||||
0.25,
|
||||
0.25,
|
||||
0,
|
||||
],
|
||||
};
|
||||
|
||||
exports.simulation = {
|
||||
COLOR_TRANSFORMATION_MATRICES,
|
||||
};
|
|
@ -10,6 +10,8 @@ DevToolsModules(
|
|||
'accessibility-parent.js',
|
||||
'accessibility.js',
|
||||
'accessible.js',
|
||||
'constants.js',
|
||||
'simulator.js',
|
||||
'walker.js',
|
||||
'worker.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
|
||||
const { simulatorSpec } = require("devtools/shared/specs/accessibility");
|
||||
const {
|
||||
simulation: { COLOR_TRANSFORMATION_MATRICES },
|
||||
} = require("./constants");
|
||||
|
||||
/**
|
||||
* The SimulatorActor is responsible for setting color matrices
|
||||
* based on the simulation type specified.
|
||||
*/
|
||||
const SimulatorActor = ActorClassWithSpec(simulatorSpec, {
|
||||
initialize(conn, targetActor) {
|
||||
Actor.prototype.initialize.call(this, conn);
|
||||
this.targetActor = targetActor;
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates a type of visual impairment (i.e. color blindness or contrast loss).
|
||||
*
|
||||
* @param {Object} options
|
||||
* Properties: {Array} types
|
||||
* Contains the types of visual impairment(s) to be simulated.
|
||||
* Set default color matrix if array is empty.
|
||||
* @return {Boolean}
|
||||
* True if matrix was successfully applied, false otherwise.
|
||||
*/
|
||||
simulate(options) {
|
||||
if (options.types.length > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.setColorMatrix(
|
||||
COLOR_TRANSFORMATION_MATRICES[
|
||||
options.types.length === 1 ? options.types[0] : "NONE"
|
||||
]
|
||||
);
|
||||
},
|
||||
|
||||
setColorMatrix(colorMatrix) {
|
||||
if (!this.docShell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
this.docShell.setColorMatrix(colorMatrix);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Disables all simulations by setting the default color matrix.
|
||||
*/
|
||||
disable() {
|
||||
this.simulate({ types: [] });
|
||||
},
|
||||
|
||||
destroy() {
|
||||
Actor.prototype.destroy.call(this);
|
||||
|
||||
this.disable();
|
||||
this.targetActor = null;
|
||||
},
|
||||
|
||||
get docShell() {
|
||||
return this.targetActor && this.targetActor.docShell;
|
||||
},
|
||||
});
|
||||
|
||||
exports.SimulatorActor = SimulatorActor;
|
|
@ -83,6 +83,19 @@ function removeSheetForBackgroundCalculation(win) {
|
|||
removeSheet(win, HIGHLIGHTER_STYLES_SHEET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that determines if web render is enabled.
|
||||
*
|
||||
* @param {Window} win
|
||||
* Window to be tested.
|
||||
* @return {Boolean}
|
||||
* True if web render is enabled, false otherwise.
|
||||
*/
|
||||
function isWebRenderEnabled(win) {
|
||||
return win.windowUtils && win.windowUtils.layerManagerType === "WebRender";
|
||||
}
|
||||
|
||||
exports.isDefunct = isDefunct;
|
||||
exports.loadSheetForBackgroundCalculation = loadSheetForBackgroundCalculation;
|
||||
exports.removeSheetForBackgroundCalculation = removeSheetForBackgroundCalculation;
|
||||
exports.isWebRenderEnabled = isWebRenderEnabled;
|
||||
|
|
|
@ -64,6 +64,7 @@ skip-if = (os == 'win' && processor == 'aarch64') # bug 1533184
|
|||
skip-if = (os == 'win' && processor == 'aarch64') # bug 1533184
|
||||
[browser_accessibility_simple.js]
|
||||
skip-if = (os == 'win' && processor == 'aarch64') # bug 1533184
|
||||
[browser_accessibility_simulator.js]
|
||||
[browser_accessibility_text_label_audit_frame.js]
|
||||
skip-if =
|
||||
(os == 'win' && processor == 'aarch64') || # bug 1533184
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"isWebRenderEnabled",
|
||||
"devtools/server/actors/utils/accessibility",
|
||||
true
|
||||
);
|
||||
|
||||
const PREF_ACCESSIBILITY_FORCE_DISABLED = "accessibility.force_disabled";
|
||||
|
||||
function checkAccessibilityState(accessibility, expected) {
|
||||
|
@ -26,10 +33,19 @@ add_task(async function() {
|
|||
|
||||
ok(accessibility, "The AccessibilityFront was created");
|
||||
ok(accessibility.getWalker, "The getWalker method exists");
|
||||
ok(accessibility.getSimulator, "The getSimulator method exists");
|
||||
|
||||
let a11yWalker = await accessibility.getWalker();
|
||||
ok(a11yWalker, "The AccessibleWalkerFront was returned");
|
||||
|
||||
const a11ySimulator = await accessibility.getSimulator();
|
||||
const webRenderEnabled = isWebRenderEnabled(window);
|
||||
is(
|
||||
!!a11ySimulator,
|
||||
webRenderEnabled,
|
||||
`The SimulatorFront was${webRenderEnabled ? "" : " not"} returned.`
|
||||
);
|
||||
|
||||
checkAccessibilityState(accessibility, {
|
||||
enabled: false,
|
||||
canBeDisabled: true,
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"isWebRenderEnabled",
|
||||
"devtools/server/actors/utils/accessibility",
|
||||
true
|
||||
);
|
||||
|
||||
const {
|
||||
accessibility: {
|
||||
SIMULATION_TYPE: { PROTANOPIA },
|
||||
},
|
||||
} = require("devtools/shared/constants");
|
||||
const {
|
||||
simulation: {
|
||||
COLOR_TRANSFORMATION_MATRICES: {
|
||||
PROTANOPIA: PROTANOPIA_MATRIX,
|
||||
NONE: DEFAULT_MATRIX,
|
||||
},
|
||||
},
|
||||
} = require("devtools/server/actors/accessibility/constants");
|
||||
|
||||
// Checks for the SimulatorActor
|
||||
|
||||
async function setup() {
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
|
||||
content.window.testColorMatrix = function(actual, expected) {
|
||||
for (const idx in actual) {
|
||||
is(
|
||||
actual[idx].toFixed(3),
|
||||
expected[idx].toFixed(3),
|
||||
"Color matrix value is set correctly."
|
||||
);
|
||||
}
|
||||
};
|
||||
});
|
||||
SimpleTest.registerCleanupFunction(async function() {
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
|
||||
content.window.testColorMatrix = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function testSimulate(simulator, matrix, type = null) {
|
||||
const matrixApplied = await simulator.simulate({ types: type ? [type] : [] });
|
||||
ok(matrixApplied, "Simulation color matrix is successfully applied.");
|
||||
|
||||
await ContentTask.spawn(
|
||||
gBrowser.selectedBrowser,
|
||||
[type, matrix],
|
||||
([simulationType, simulationMatrix]) => {
|
||||
const { window } = content;
|
||||
info(
|
||||
`Test that color matrix is set to ${simulationType ||
|
||||
"default"} simulation values.`
|
||||
);
|
||||
window.testColorMatrix(
|
||||
window.docShell.getColorMatrix(),
|
||||
simulationMatrix
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const { target, accessibility } = await initAccessibilityFrontForUrl(
|
||||
MAIN_DOMAIN + "doc_accessibility.html"
|
||||
);
|
||||
|
||||
const simulator = await accessibility.getSimulator();
|
||||
|
||||
if (!simulator) {
|
||||
ok(!isWebRenderEnabled(window), "Web render is disabled.");
|
||||
|
||||
// If web render is disabled, we can't test the simulator actor, so return early
|
||||
return;
|
||||
}
|
||||
|
||||
await setup();
|
||||
|
||||
info("Test that protanopia is successfully simulated.");
|
||||
await testSimulate(simulator, PROTANOPIA_MATRIX, PROTANOPIA);
|
||||
|
||||
info(
|
||||
"Test that simulations are successfully removed by setting default color matrix."
|
||||
);
|
||||
await testSimulate(simulator, DEFAULT_MATRIX);
|
||||
|
||||
await target.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
|
@ -85,8 +85,27 @@ const SCORES = {
|
|||
WARNING: "WARNING",
|
||||
};
|
||||
|
||||
// List of simulation types.
|
||||
const SIMULATION_TYPE = {
|
||||
// Low red color blindness
|
||||
PROTANOMALY: "PROTANOMALY",
|
||||
// Low green color blindness
|
||||
DEUTERANOMALY: "DEUTERANOMALY",
|
||||
// Low blue color blindness
|
||||
TRITANOMALY: "TRITANOMALY",
|
||||
// No red color blindness
|
||||
PROTANOPIA: "PROTANOPIA",
|
||||
// No green color blindness
|
||||
DEUTERANOPIA: "DEUTERANOPIA",
|
||||
// No blue color blindness
|
||||
TRITANOPIA: "TRITANOPIA",
|
||||
// Low contrast
|
||||
CONTRAST_LOSS: "CONTRAST_LOSS",
|
||||
};
|
||||
|
||||
exports.accessibility = {
|
||||
AUDIT_TYPE,
|
||||
ISSUE_TYPE,
|
||||
SCORES,
|
||||
SIMULATION_TYPE,
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ const {
|
|||
accessibleSpec,
|
||||
accessibleWalkerSpec,
|
||||
accessibilitySpec,
|
||||
simulatorSpec,
|
||||
} = require("devtools/shared/specs/accessibility");
|
||||
const events = require("devtools/shared/event-emitter");
|
||||
|
||||
|
@ -217,9 +218,13 @@ class AccessibilityFront extends FrontClassWithSpec(accessibilitySpec) {
|
|||
}
|
||||
}
|
||||
|
||||
const SimulatorFront = FrontClassWithSpec(simulatorSpec);
|
||||
|
||||
exports.AccessibleFront = AccessibleFront;
|
||||
registerFront(AccessibleFront);
|
||||
exports.AccessibleWalkerFront = AccessibleWalkerFront;
|
||||
registerFront(AccessibleWalkerFront);
|
||||
exports.AccessibilityFront = AccessibilityFront;
|
||||
registerFront(AccessibilityFront);
|
||||
exports.SimulatorFront = SimulatorFront;
|
||||
registerFront(SimulatorFront);
|
||||
|
|
|
@ -206,6 +206,19 @@ const accessibleWalkerSpec = generateActorSpec({
|
|||
},
|
||||
});
|
||||
|
||||
const simulatorSpec = generateActorSpec({
|
||||
typeName: "simulator",
|
||||
|
||||
methods: {
|
||||
simulate: {
|
||||
request: { options: Arg(0, "nullable:json") },
|
||||
response: {
|
||||
value: RetVal("boolean"),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const accessibilitySpec = generateActorSpec({
|
||||
typeName: "accessibility",
|
||||
|
||||
|
@ -239,6 +252,12 @@ const accessibilitySpec = generateActorSpec({
|
|||
walker: RetVal("accessiblewalker"),
|
||||
},
|
||||
},
|
||||
getSimulator: {
|
||||
request: {},
|
||||
response: {
|
||||
simulator: RetVal("nullable:simulator"),
|
||||
},
|
||||
},
|
||||
enable: {
|
||||
request: {},
|
||||
response: {},
|
||||
|
@ -253,3 +272,4 @@ const accessibilitySpec = generateActorSpec({
|
|||
exports.accessibleSpec = accessibleSpec;
|
||||
exports.accessibleWalkerSpec = accessibleWalkerSpec;
|
||||
exports.accessibilitySpec = accessibilitySpec;
|
||||
exports.simulatorSpec = simulatorSpec;
|
||||
|
|
Загрузка…
Ссылка в новой задаче