зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1541705 - Try to see whether the target frame is scrolled out of view in out-of-process iframe if we couldn't walk up the frame tree. r=surkov
Differential Revision: https://phabricator.services.mozilla.com/D44423 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
8c9bd09b43
Коммит
6f114d0542
|
@ -362,12 +362,12 @@ uint64_t Accessible::VisibilityState() const {
|
|||
// If contained by scrollable frame then check that at least 12 pixels
|
||||
// around the object is visible, otherwise the object is offscreen.
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(parentFrame);
|
||||
const nscoord kMinPixels = nsPresContext::CSSPixelsToAppUnits(12);
|
||||
if (scrollableFrame) {
|
||||
nsRect scrollPortRect = scrollableFrame->GetScrollPortRect();
|
||||
nsRect frameRect = nsLayoutUtils::TransformFrameRectToAncestor(
|
||||
frame, frame->GetRectRelativeToSelf(), parentFrame);
|
||||
if (!scrollPortRect.Contains(frameRect)) {
|
||||
const nscoord kMinPixels = nsPresContext::CSSPixelsToAppUnits(12);
|
||||
scrollPortRect.Deflate(kMinPixels, kMinPixels);
|
||||
if (!scrollPortRect.Intersects(frameRect)) return states::OFFSCREEN;
|
||||
}
|
||||
|
@ -375,6 +375,14 @@ uint64_t Accessible::VisibilityState() const {
|
|||
|
||||
if (!parentFrame) {
|
||||
parentFrame = nsLayoutUtils::GetCrossDocParentFrame(curFrame);
|
||||
// Even if we couldn't find the parent frame, it might mean we are in an
|
||||
// out-of-process iframe, try to see if |frame| is scrolled out in an
|
||||
// scrollable frame in a cross-process ancestor document.
|
||||
if (!parentFrame &&
|
||||
nsLayoutUtils::FrameIsMostlyScrolledOutOfViewInCrossProcess(
|
||||
frame, kMinPixels)) {
|
||||
return states::OFFSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
curFrame = parentFrame;
|
||||
|
|
|
@ -7,3 +7,5 @@ support-files =
|
|||
[browser_test_link.js]
|
||||
skip-if = verify
|
||||
[browser_test_visibility.js]
|
||||
[browser_offscreen_element_in_out_of_process_iframe.js]
|
||||
skip-if = (webrender && os == 'win') # bug 1580706
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* 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 parentURL =
|
||||
"data:text/html;charset=utf-8," +
|
||||
'<div id="scroller" style="width: 300px; height: 300px; overflow-y: scroll; overflow-x: hidden;">' +
|
||||
' <div style="width: 100%; height: 1000px;"></div>' +
|
||||
' <iframe frameborder="0"/>' +
|
||||
"</div>";
|
||||
const iframeURL =
|
||||
"data:text/html;charset=utf-8," +
|
||||
"<style>" +
|
||||
" html,body {" +
|
||||
" /* Convenient for calculation of element positions */" +
|
||||
" margin: 0;" +
|
||||
" padding: 0;" +
|
||||
" }" +
|
||||
"</style>" +
|
||||
'<div id="target" style="width: 100px; height: 100px;">target</div>';
|
||||
|
||||
add_task(async function() {
|
||||
const win = await BrowserTestUtils.openNewBrowserWindow({
|
||||
fission: true,
|
||||
});
|
||||
|
||||
try {
|
||||
const browser = win.gBrowser.selectedTab.linkedBrowser;
|
||||
|
||||
BrowserTestUtils.loadURI(browser, parentURL);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, parentURL);
|
||||
|
||||
async function setup(url) {
|
||||
const iframe = content.document.querySelector("iframe");
|
||||
|
||||
iframe.contentWindow.location = url;
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener("load", resolve, { once: true });
|
||||
});
|
||||
|
||||
return iframe.browsingContext;
|
||||
}
|
||||
|
||||
async function scrollTo(x, y) {
|
||||
await SpecialPowers.spawn(browser, [x, y], async (scrollX, scrollY) => {
|
||||
const scroller = content.document.getElementById("scroller");
|
||||
scroller.scrollTo(scrollX, scrollY);
|
||||
await new Promise(resolve => {
|
||||
scroller.addEventListener("scroll", resolve, { once: true });
|
||||
});
|
||||
});
|
||||
await waitForIFrameUpdates();
|
||||
}
|
||||
|
||||
// Setup an out-of-process iframe which is initially scrolled out.
|
||||
const iframe = await SpecialPowers.spawn(browser, [iframeURL], setup);
|
||||
|
||||
await waitForIFrameUpdates();
|
||||
await spawnTestStates(
|
||||
iframe,
|
||||
"target",
|
||||
nsIAccessibleStates.STATE_OFFSCREEN
|
||||
);
|
||||
|
||||
// Scroll the iframe into view and the target element is also visible but
|
||||
// the visible area height is 11px.
|
||||
await scrollTo(0, 711);
|
||||
await spawnTestStates(
|
||||
iframe,
|
||||
"target",
|
||||
nsIAccessibleStates.STATE_OFFSCREEN
|
||||
);
|
||||
|
||||
// Scroll to a position where the visible height is 13px.
|
||||
await scrollTo(0, 713);
|
||||
await spawnTestStates(iframe, "target", 0);
|
||||
|
||||
// Scroll the iframe out again.
|
||||
await scrollTo(0, 0);
|
||||
await spawnTestStates(
|
||||
iframe,
|
||||
"target",
|
||||
nsIAccessibleStates.STATE_OFFSCREEN
|
||||
);
|
||||
} finally {
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
}
|
||||
});
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* exported waitForIFrameUpdates, spawnTestStates */
|
||||
|
||||
// Load the shared-head file first.
|
||||
/* import-globals-from ../shared-head.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
|
@ -17,3 +19,35 @@ loadScripts(
|
|||
{ name: "common.js", dir: MOCHITESTS_DIR },
|
||||
{ name: "promisified-events.js", dir: MOCHITESTS_DIR }
|
||||
);
|
||||
|
||||
// A utility function to make sure the information of scroll position or visible
|
||||
// area changes reach to out-of-process iframes.
|
||||
async function waitForIFrameUpdates() {
|
||||
// Wait for two frames since the information is notified via asynchronous IPC
|
||||
// calls.
|
||||
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||
}
|
||||
|
||||
// A utility function to test the state of |elementId| element in out-of-process
|
||||
// |browsingContext|.
|
||||
async function spawnTestStates(browsingContext, elementId, expectedStates) {
|
||||
function testStates(id, expected) {
|
||||
const acc = SpecialPowers.Cc[
|
||||
"@mozilla.org/accessibilityService;1"
|
||||
].getService(SpecialPowers.Ci.nsIAccessibilityService);
|
||||
const target = content.document.getElementById(id);
|
||||
let state = {};
|
||||
acc.getAccessibleFor(target).getState(state, {});
|
||||
if (expected === 0) {
|
||||
Assert.equal(state.value, expected);
|
||||
} else {
|
||||
Assert.ok(state.value & expected);
|
||||
}
|
||||
}
|
||||
await SpecialPowers.spawn(
|
||||
browsingContext,
|
||||
[elementId, expectedStates],
|
||||
testStates
|
||||
);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче