fix(interactivity-checker): carefully handle frame elements (#9340)

* Browsers like MS Edge throw errors if the frameElement property is being accessed from a different host address. This means that the `frameElement` property should be accessed carefully.

Fixes #3372
This commit is contained in:
Paul Gschwendtner
2018-01-23 16:54:32 +01:00
committed by Jeremy Elbourn
parent 2c192d0a57
commit 6f7332b748
2 changed files with 31 additions and 3 deletions
@@ -337,6 +337,22 @@ describe('InteractivityChecker', () => {
expect(checker.isTabbable(button)).toBe(true);
});
it('should carefully try to access the frame element of an elements window', () => {
const iframe = createFromTemplate('<iframe>', true) as HTMLFrameElement;
const button = createFromTemplate('<button tabindex="1">Not Tabbable</button>');
appendElements([iframe]);
iframe.setAttribute('tabindex', '-1');
iframe.contentDocument.body.appendChild(button);
Object.defineProperty(iframe.contentWindow, 'frameElement', {
get: () => { throw 'Access Denied!'; }
});
expect(() => checker.isTabbable(button)).not.toThrow();
});
it('should mark elements which are contentEditable as tabbable', () => {
let editableEl = createFromTemplate('<div contenteditable="true">', true);
+15 -3
View File
@@ -60,11 +60,10 @@ export class InteractivityChecker {
return false;
}
let frameElement = getWindow(element).frameElement as HTMLElement;
const frameElement = getFrameElement(getWindow(element));
if (frameElement) {
let frameType = frameElement && frameElement.nodeName.toLowerCase();
const frameType = frameElement && frameElement.nodeName.toLowerCase();
// Frame elements inherit their tabindex onto all child elements.
if (getTabIndexValue(frameElement) === -1) {
@@ -143,6 +142,19 @@ export class InteractivityChecker {
}
/**
* Returns the frame element from a window object. Since browsers like MS Edge throw errors if
* the frameElement property is being accessed from a different host address, this property
* should be accessed carefully.
*/
function getFrameElement(window: Window) {
try {
return window.frameElement as HTMLElement;
} catch (e) {
return null;
}
}
/** Checks whether the specified element has any geometry / rectangles. */
function hasGeometry(element: HTMLElement): boolean {
// Use logic from jQuery to check for an invisible element.