Bug 1590493 - remove unnecessary calls to actorHasMethod and update supports state across the panel. r=mtigley

Differential Revision: https://phabricator.services.mozilla.com/D54569

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Yura Zenevich 2019-11-28 15:37:18 +00:00
Родитель 215a319521
Коммит 9eb54b9950
15 изменённых файлов: 57 добавлений и 236 удалений

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

@ -47,29 +47,12 @@ class AccessibilityStartup {
try { try {
this._walker = await this._accessibility.getWalker(); this._walker = await this._accessibility.getWalker();
this._supports = {}; this._supports = {};
// Only works with FF61+ targets [this._supports.simulation] = await Promise.all([
this._supports.enableDisable = await this.target.actorHasMethod( // Added in Firefox 70.
"accessibility", this.target.actorHasMethod("accessibility", "getSimulator"),
"enable" ]);
);
if (this._supports.enableDisable) { await this._accessibility.bootstrap();
[
this._supports.relations,
this._supports.snapshot,
this._supports.audit,
this._supports.hydration,
this._supports.simulation,
] = await Promise.all([
this.target.actorHasMethod("accessible", "getRelations"),
this.target.actorHasMethod("accessible", "snapshot"),
this.target.actorHasMethod("accessible", "audit"),
this.target.actorHasMethod("accessible", "hydrate"),
this.target.actorHasMethod("accessibility", "getSimulator"),
]);
await this._accessibility.bootstrap();
}
return true; return true;
} catch (e) { } catch (e) {

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

@ -17,9 +17,6 @@ const { Provider } = require("devtools/client/shared/vendor/react-redux");
// Accessibility Panel // Accessibility Panel
const MainFrame = createFactory(require("./components/MainFrame")); const MainFrame = createFactory(require("./components/MainFrame"));
const OldVersionDescription = createFactory(
require("./components/Description").OldVersionDescription
);
// Store // Store
const createStore = require("devtools/client/shared/redux/create-store"); const createStore = require("devtools/client/shared/redux/create-store");
@ -79,12 +76,6 @@ AccessibilityView.prototype = {
// Make sure state is reset every time accessibility panel is initialized. // Make sure state is reset every time accessibility panel is initialized.
await this.store.dispatch(reset(front, supports)); await this.store.dispatch(reset(front, supports));
const container = document.getElementById("content"); const container = document.getElementById("content");
if (!supports.enableDisable) {
ReactDOM.render(OldVersionDescription(), container);
return;
}
const mainFrame = MainFrame({ const mainFrame = MainFrame({
accessibility: front, accessibility: front,
accessibilityWalker: walker, accessibilityWalker: walker,
@ -107,9 +98,9 @@ AccessibilityView.prototype = {
window.emit(EVENTS.NEW_ACCESSIBLE_FRONT_HIGHLIGHTED); window.emit(EVENTS.NEW_ACCESSIBLE_FRONT_HIGHLIGHTED);
}, },
async selectNodeAccessible(walker, node, supports) { async selectNodeAccessible(walker, node) {
let accessible = await walker.getAccessibleFor(node); let accessible = await walker.getAccessibleFor(node);
if (accessible && supports.hydration) { if (accessible) {
await accessible.hydrate(); await accessible.hydrate();
} }
@ -124,7 +115,7 @@ AccessibilityView.prototype = {
accessible = await walker.getAccessibleFor(child); accessible = await walker.getAccessibleFor(child);
// indexInParent property is only available with additional request // indexInParent property is only available with additional request
// for data (hydration) about the accessible object. // for data (hydration) about the accessible object.
if (accessible && supports.hydration) { if (accessible) {
await accessible.hydrate(); await accessible.hydrate();
} }

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

@ -10,17 +10,16 @@ const { UPDATE_DETAILS } = require("../constants");
* *
* @param {Object} dom walker front * @param {Object} dom walker front
* @param {Object} accessible front * @param {Object} accessible front
* @param {Object} list of supported serverside features.
*/ */
exports.updateDetails = (domWalker, accessible, supports) => dispatch => exports.updateDetails = (domWalker, accessible) => dispatch =>
Promise.all([ Promise.all([
domWalker.getNodeFromActor(accessible.actorID, [ domWalker.getNodeFromActor(accessible.actorID, [
"rawAccessible", "rawAccessible",
"DOMNode", "DOMNode",
]), ]),
supports.relations ? accessible.getRelations() : [], accessible.getRelations(),
supports.audit ? accessible.audit() : {}, accessible.audit(),
supports.hydration ? accessible.hydrate() : null, accessible.hydrate(),
]) ])
.then(response => dispatch({ accessible, type: UPDATE_DETAILS, response })) .then(response => dispatch({ accessible, type: UPDATE_DETAILS, response }))
.catch(error => dispatch({ accessible, type: UPDATE_DETAILS, error })); .catch(error => dispatch({ accessible, type: UPDATE_DETAILS, error }));

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

@ -80,10 +80,8 @@ class AccessibilityRow extends Component {
static get propTypes() { static get propTypes() {
return { return {
...TreeRow.propTypes, ...TreeRow.propTypes,
hasContextMenu: PropTypes.bool.isRequired,
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
scrollContentNodeIntoView: PropTypes.bool.isRequired, scrollContentNodeIntoView: PropTypes.bool.isRequired,
supports: PropTypes.object,
}; };
} }
@ -151,14 +149,13 @@ class AccessibilityRow extends Component {
const { const {
dispatch, dispatch,
member: { object }, member: { object },
supports,
} = this.props; } = this.props;
if (!object.actorID) { if (!object.actorID) {
return; return;
} }
const domWalker = (await object.targetFront.getFront("inspector")).walker; const domWalker = (await object.targetFront.getFront("inspector")).walker;
dispatch(updateDetails(domWalker, object, supports)); dispatch(updateDetails(domWalker, object));
window.emit(EVENTS.NEW_ACCESSIBLE_FRONT_SELECTED, object); window.emit(EVENTS.NEW_ACCESSIBLE_FRONT_SELECTED, object);
} }
@ -253,12 +250,6 @@ class AccessibilityRow extends Component {
} }
async printToJSON() { async printToJSON() {
const { member, supports } = this.props;
if (!supports.snapshot) {
// Debugger server does not support Accessible actor snapshots.
return;
}
if (gTelemetry) { if (gTelemetry) {
gTelemetry.keyedScalarAdd( gTelemetry.keyedScalarAdd(
TELEMETRY_ACCESSIBLE_CONTEXT_MENU_ITEM_ACTIVATED, TELEMETRY_ACCESSIBLE_CONTEXT_MENU_ITEM_ACTIVATED,
@ -267,7 +258,7 @@ class AccessibilityRow extends Component {
); );
} }
const snapshot = await member.object.snapshot(); const snapshot = await this.props.member.object.snapshot();
openDocLink( openDocLink(
`${JSON_URL_PREFIX}${encodeURIComponent(JSON.stringify(snapshot))}` `${JSON_URL_PREFIX}${encodeURIComponent(JSON.stringify(snapshot))}`
); );
@ -282,17 +273,13 @@ class AccessibilityRow extends Component {
} }
const menu = new Menu({ id: "accessibility-row-contextmenu" }); const menu = new Menu({ id: "accessibility-row-contextmenu" });
const { supports } = this.props; menu.append(
new MenuItem({
if (supports.snapshot) { id: "menu-printtojson",
menu.append( label: L10N.getStr("accessibility.tree.menu.printToJSON"),
new MenuItem({ click: () => this.printToJSON(),
id: "menu-printtojson", })
label: L10N.getStr("accessibility.tree.menu.printToJSON"), );
click: () => this.printToJSON(),
})
);
}
menu.popup(e.screenX, e.screenY, gToolbox.doc); menu.popup(e.screenX, e.screenY, gToolbox.doc);
@ -309,7 +296,7 @@ class AccessibilityRow extends Component {
const { member } = this.props; const { member } = this.props;
const props = { const props = {
...this.props, ...this.props,
onContextMenu: this.props.hasContextMenu && (e => this.onContextMenu(e)), onContextMenu: e => this.onContextMenu(e),
onMouseOver: () => this.highlight(member.object), onMouseOver: () => this.highlight(member.object),
onMouseOut: () => this.unhighlight(member.object), onMouseOut: () => this.unhighlight(member.object),
key: `${member.path}-${member.active ? "active" : "inactive"}`, key: `${member.path}-${member.active ? "active" : "inactive"}`,
@ -325,9 +312,8 @@ class AccessibilityRow extends Component {
} }
const mapStateToProps = ({ const mapStateToProps = ({
ui: { supports, [PREFS.SCROLL_INTO_VIEW]: scrollContentNodeIntoView }, ui: { [PREFS.SCROLL_INTO_VIEW]: scrollContentNodeIntoView },
}) => ({ }) => ({
supports,
scrollContentNodeIntoView, scrollContentNodeIntoView,
}); });

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

@ -11,8 +11,6 @@ const {
const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { span } = require("devtools/client/shared/vendor/react-dom-factories"); const { span } = require("devtools/client/shared/vendor/react-dom-factories");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const Badges = createFactory(require("./Badges")); const Badges = createFactory(require("./Badges"));
const AuditController = createFactory(require("./AuditController")); const AuditController = createFactory(require("./AuditController"));
@ -26,16 +24,10 @@ class AccessibilityRowValue extends Component {
member: PropTypes.shape({ member: PropTypes.shape({
object: PropTypes.object, object: PropTypes.object,
}).isRequired, }).isRequired,
supports: PropTypes.object.isRequired,
}; };
} }
render() { render() {
const {
member,
supports: { audit },
} = this.props;
return span( return span(
{ {
role: "presentation", role: "presentation",
@ -45,19 +37,14 @@ class AccessibilityRowValue extends Component {
defaultRep: Grip, defaultRep: Grip,
cropLimit: 50, cropLimit: 50,
}), }),
audit && AuditController(
AuditController( {
{ accessibleFront: this.props.member.object,
accessibleFront: member.object, },
}, Badges()
Badges() )
)
); );
} }
} }
const mapStateToProps = ({ ui: { supports } }) => { module.exports = AccessibilityRowValue;
return { supports };
};
module.exports = connect(mapStateToProps)(AccessibilityRowValue);

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

@ -41,7 +41,6 @@ class AccessibilityTree extends Component {
expanded: PropTypes.object, expanded: PropTypes.object,
selected: PropTypes.string, selected: PropTypes.string,
highlighted: PropTypes.object, highlighted: PropTypes.object,
supports: PropTypes.object,
filtered: PropTypes.bool, filtered: PropTypes.bool,
}; };
} }
@ -167,21 +166,15 @@ class AccessibilityTree extends Component {
expanded, expanded,
selected, selected,
highlighted: highlightedItem, highlighted: highlightedItem,
supports,
accessibilityWalker, accessibilityWalker,
filtered, filtered,
} = this.props; } = this.props;
// Historically, the first context menu item is snapshot function and it is available
// for all accessible object.
const hasContextMenu = supports.snapshot;
const renderRow = rowProps => { const renderRow = rowProps => {
const { object } = rowProps.member; const { object } = rowProps.member;
const highlighted = object === highlightedItem; const highlighted = object === highlightedItem;
return AccessibilityRow( return AccessibilityRow(
Object.assign({}, rowProps, { Object.assign({}, rowProps, {
hasContextMenu,
highlighted, highlighted,
decorator: { decorator: {
getRowClass: function() { getRowClass: function() {
@ -217,32 +210,29 @@ class AccessibilityTree extends Component {
return true; return true;
}, },
onContextMenuTree: onContextMenuTree: function(e) {
hasContextMenu && // If context menu event is triggered on (or bubbled to) the TreeView, it was
function(e) { // done via keyboard. Open context menu for currently selected row.
// If context menu event is triggered on (or bubbled to) the TreeView, it was let row = this.getSelectedRow();
// done via keyboard. Open context menu for currently selected row. if (!row) {
let row = this.getSelectedRow(); return;
if (!row) { }
return;
}
row = row.getWrappedInstance(); row = row.getWrappedInstance();
row.onContextMenu(e); row.onContextMenu(e);
}, },
}); });
} }
} }
const mapStateToProps = ({ const mapStateToProps = ({
accessibles, accessibles,
ui: { expanded, selected, supports, highlighted }, ui: { expanded, selected, highlighted },
audit: { filters }, audit: { filters },
}) => ({ }) => ({
accessibles, accessibles,
expanded, expanded,
selected, selected,
supports,
highlighted, highlighted,
filtered: isFiltered(filters), filtered: isFiltered(filters),
}); });

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

@ -112,7 +112,6 @@ class Accessible extends Component {
labelledby: PropTypes.string.isRequired, labelledby: PropTypes.string.isRequired,
parents: PropTypes.object, parents: PropTypes.object,
relations: PropTypes.object, relations: PropTypes.object,
supports: PropTypes.object,
}; };
} }
@ -181,7 +180,7 @@ class Accessible extends Component {
} }
async update() { async update() {
const { dispatch, accessibleFront, supports } = this.props; const { dispatch, accessibleFront } = this.props;
if (!accessibleFront.actorID) { if (!accessibleFront.actorID) {
return; return;
} }
@ -189,7 +188,7 @@ class Accessible extends Component {
const domWalker = (await accessibleFront.targetFront.getFront("inspector")) const domWalker = (await accessibleFront.targetFront.getFront("inspector"))
.walker; .walker;
dispatch(updateDetails(domWalker, accessibleFront, supports)); dispatch(updateDetails(domWalker, accessibleFront));
} }
setExpanded(item, isExpanded) { setExpanded(item, isExpanded) {
@ -540,13 +539,12 @@ const makeParentMap = items => {
return map; return map;
}; };
const mapStateToProps = ({ details, ui }) => { const mapStateToProps = ({ details }) => {
const { const {
accessible: accessibleFront, accessible: accessibleFront,
DOMNode: nodeFront, DOMNode: nodeFront,
relations, relations,
} = details; } = details;
const { supports } = ui;
if (!accessibleFront || !nodeFront) { if (!accessibleFront || !nodeFront) {
return {}; return {};
} }
@ -556,9 +554,7 @@ const mapStateToProps = ({ details, ui }) => {
if (key === "DOMNode") { if (key === "DOMNode") {
props.nodeFront = nodeFront; props.nodeFront = nodeFront;
} else if (key === "relations") { } else if (key === "relations") {
if (supports.relations) { props.relations = relations;
props.relations = relations;
}
} else { } else {
props[key] = accessibleFront[key]; props[key] = accessibleFront[key];
} }
@ -569,7 +565,7 @@ const mapStateToProps = ({ details, ui }) => {
); );
const parents = makeParentMap(items); const parents = makeParentMap(items);
return { accessibleFront, nodeFront, items, parents, relations, supports }; return { accessibleFront, nodeFront, items, parents, relations };
}; };
module.exports = connect(mapStateToProps)(Accessible); module.exports = connect(mapStateToProps)(Accessible);

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

@ -93,10 +93,6 @@ class Checks extends Component {
} }
const mapStateToProps = ({ details, ui }) => { const mapStateToProps = ({ details, ui }) => {
if (!ui.supports.audit) {
return {};
}
const { audit } = details; const { audit } = details;
if (!audit) { if (!audit) {
return {}; return {};

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

@ -30,22 +30,6 @@ const {
A11Y_SERVICE_ENABLED_COUNT, A11Y_SERVICE_ENABLED_COUNT,
} = require("../constants"); } = require("../constants");
class OldVersionDescription extends Component {
render() {
return div(
{ className: "description" },
p(
{ className: "general" },
img({
src: "chrome://devtools/skin/images/accessibility.svg",
alt: L10N.getStr("accessibility.logo"),
}),
L10N.getStr("accessibility.description.oldVersion")
)
);
}
}
/** /**
* Landing UI for the accessibility panel when Accessibility features are * Landing UI for the accessibility panel when Accessibility features are
* deactivated. * deactivated.
@ -160,4 +144,3 @@ const mapStateToProps = ({ ui }) => ({
// Exports from this module // Exports from this module
exports.Description = connect(mapStateToProps)(Description); exports.Description = connect(mapStateToProps)(Description);
exports.OldVersionDescription = OldVersionDescription;

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

@ -89,14 +89,8 @@ AccessibilityPanel.prototype = {
this.panelWin.gToolbox = this._toolbox; this.panelWin.gToolbox = this._toolbox;
await this.startup.initAccessibility(); await this.startup.initAccessibility();
if (this.supports.enableDisable) { this.picker = new Picker(this);
this.picker = new Picker(this); this.simulator = await this.front.getSimulator();
}
if (this.supports.simulation) {
this.simulator = await this.front.getSimulator();
}
this.fluentBundles = await this.createFluentBundles(); this.fluentBundles = await this.createFluentBundles();
this.updateA11YServiceDurationTimer(); this.updateA11YServiceDurationTimer();
@ -202,12 +196,7 @@ AccessibilityPanel.prototype = {
); );
} }
this.postContentMessage( this.postContentMessage("selectNodeAccessible", this.walker, nodeFront);
"selectNodeAccessible",
this.walker,
nodeFront,
this.supports
);
}, },
highlightAccessible(accessibleFront) { highlightAccessible(accessibleFront) {

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

@ -185,10 +185,8 @@ function onReset(state, { accessibility, supports }) {
enabled, enabled,
canBeDisabled, canBeDisabled,
canBeEnabled, canBeEnabled,
supports,
}; };
if (supports) {
newState.supports = supports;
}
return newState; return newState;
} }

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

@ -43,9 +43,7 @@ window.onload = async function() {
off: () => {}, off: () => {},
}, },
}, },
ui: { ui: { supports: {} }
supports: {},
},
}; };
const mockStore = createStore((state, action) => const mockStore = createStore((state, action) =>
@ -53,28 +51,13 @@ window.onload = async function() {
const provider = createElement(Provider, { store: mockStore }, a); const provider = createElement(Provider, { store: mockStore }, a);
const accessible = ReactDOM.render(provider, window.document.body); const accessible = ReactDOM.render(provider, window.document.body);
ok(accessible, "Should be able to mount Accessible instances"); ok(accessible, "Should be able to mount Accessible instances");
info("Render accessible object when relations are not supported.");
let relationsNode = document.getElementById("/relations"); let relationsNode = document.getElementById("/relations");
ok(!relationsNode, "Relations are not rendered when not supported.");
info("Render accessible object when relations are supported but are empty.");
let state = {
...mockState,
ui: {
supports: {
relations: true,
},
},
};
await mockStore.dispatch({ type: "update", ...state });
relationsNode = document.getElementById("/relations");
ok(relationsNode, "Relations are rendered when supported."); ok(relationsNode, "Relations are rendered when supported.");
let arrow = relationsNode.querySelector(".arrow.theme-twisty"); let arrow = relationsNode.querySelector(".arrow.theme-twisty");
is(arrow.style.visibility, "hidden", "Relations are empty."); is(arrow.style.visibility, "hidden", "Relations are empty.");
info("Render accessible object with relations."); info("Render accessible object with relations.");
state = { const state = {
details: { details: {
...mockState.details, ...mockState.details,
relations: { relations: {
@ -86,11 +69,6 @@ window.onload = async function() {
}, },
}, },
}, },
ui: {
supports: {
relations: true,
},
},
}; };
await mockStore.dispatch({ type: "update", ...state }); await mockStore.dispatch({ type: "update", ...state });
relationsNode = document.getElementById("/relations"); relationsNode = document.getElementById("/relations");

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

@ -90,25 +90,16 @@ window.onload = async function() {
hasContextMenu: true, hasContextMenu: true,
}; };
const mockProps = {
...defaultProps,
hasContextMenu: null,
};
const auditState = { audit: { filters: { [FILTERS.CONTRAST]: false }}}; const auditState = { audit: { filters: { [FILTERS.CONTRAST]: false }}};
const defaultState = { const defaultState = {
ui: { supports: { snapshot: true }}, ui: { supports: {} },
...auditState,
};
const mockState = {
ui: { supports: {}},
...auditState, ...auditState,
}; };
info("Check contextmenu default behaviour."); info("Check contextmenu default behaviour.");
renderAccessibilityRow(defaultProps, defaultState); renderAccessibilityRow(defaultProps, defaultState);
let row = document.getElementById(ROW_ID); const row = document.getElementById(ROW_ID);
info("Get topmost document where the context meny will be rendered"); info("Get topmost document where the context meny will be rendered");
const menuDoc = document.defaultView.windowRoot.ownerGlobal.document; const menuDoc = document.defaultView.windowRoot.ownerGlobal.document;
@ -144,23 +135,6 @@ window.onload = async function() {
browserWindow.openWebLinkIn = defaultOpenWebLinkIn; browserWindow.openWebLinkIn = defaultOpenWebLinkIn;
menu.remove(); menu.remove();
}); });
info("Check accessibility row when context menu is not supported.");
renderAccessibilityRow(defaultProps, mockState);
row = document.getElementById(ROW_ID);
info("Check contextmenu listener is not called when context menu is not supported.");
Simulate.contextMenu(row);
let menu = menuDoc.getElementById("accessibility-row-contextmenu");
ok(!menu, "contextmenu event handler was never called.");
info("Check accessibility row when no context menu is available.");
renderAccessibilityRow(mockProps, defaultState);
row = document.getElementById(ROW_ID);
Simulate.contextMenu(row);
menu = menuDoc.getElementById("accessibility-row-contextmenu");
ok(!menu, "contextmenu event handler was never called.");
} catch (e) { } catch (e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e)); ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally { } finally {

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

@ -1,5 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AccessibilityRowValue component: audit not supported 1`] = `"<span role=\\"presentation\\"><span class=\\"objectBox objectBox-undefined\\">undefined</span></span>"`;
exports[`AccessibilityRowValue component: basic render 1`] = `"<span role=\\"presentation\\"><span class=\\"objectBox objectBox-undefined\\">undefined</span></span>"`; exports[`AccessibilityRowValue component: basic render 1`] = `"<span role=\\"presentation\\"><span class=\\"objectBox objectBox-undefined\\">undefined</span></span>"`;

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

@ -21,40 +21,13 @@ const {
} = require("devtools/client/shared/components/reps/reps"); } = require("devtools/client/shared/components/reps/reps");
const AuditController = require("devtools/client/accessibility/components/AuditController"); const AuditController = require("devtools/client/accessibility/components/AuditController");
const ConnectedAccessibilityRowValueClass = require("devtools/client/accessibility/components/AccessibilityRowValue"); const AccessibilityRowValueClass = require("devtools/client/accessibility/components/AccessibilityRowValue");
const AccessibilityRowValueClass = const AccessibilityRowValue = createFactory(AccessibilityRowValueClass);
ConnectedAccessibilityRowValueClass.WrappedComponent;
const AccessibilityRowValue = createFactory(
ConnectedAccessibilityRowValueClass
);
describe("AccessibilityRowValue component:", () => { describe("AccessibilityRowValue component:", () => {
it("audit not supported", () => {
const store = setupStore({
preloadedState: { ui: { supports: {} } },
});
const wrapper = mount(
Provider(
{ store },
AccessibilityRowValue({
member: { object: mockAccessible() },
})
)
);
expect(wrapper.html()).toMatchSnapshot();
const rowValue = wrapper.find(AccessibilityRowValueClass);
expect(rowValue.children().length).toBe(1);
const container = rowValue.childAt(0);
expect(container.type()).toBe("span");
expect(container.prop("role")).toBe("presentation");
expect(container.children().length).toBe(1);
expect(container.childAt(0).type()).toBe(Rep);
});
it("basic render", () => { it("basic render", () => {
const store = setupStore({ const store = setupStore({
preloadedState: { ui: { supports: { audit: true } } }, preloadedState: { ui: { supports: {} } },
}); });
const wrapper = mount( const wrapper = mount(
Provider( Provider(