зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1696718 - Propagate popup window position update to descendants documents. r=kmag
Differential Revision: https://phabricator.services.mozilla.com/D108559
This commit is contained in:
Родитель
73695d66b4
Коммит
9a4563134c
|
@ -172,6 +172,8 @@ disabled = bug 1438663
|
|||
[browser_ext_popup_requestPermission.js]
|
||||
[browser_ext_popup_select.js]
|
||||
skip-if = debug || os != 'win' # FIXME: re-enable on debug build (bug 1442822)
|
||||
[browser_ext_popup_select_in_oopif.js]
|
||||
skip-if = tsan # bug 1699341
|
||||
[browser_ext_popup_sendMessage.js]
|
||||
[browser_ext_popup_shutdown.js]
|
||||
[browser_ext_port_disconnect_on_crash.js]
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
// This test is based on browser_ext_popup_select.js.
|
||||
|
||||
const iframeSrc = encodeURIComponent(`
|
||||
<html>
|
||||
<style>
|
||||
html,body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<select>
|
||||
<option>Foo</option>
|
||||
<option>Bar</option>
|
||||
<option>Baz</option>
|
||||
</select>
|
||||
</html>`);
|
||||
|
||||
add_task(async function testPopupSelectPopup() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
browser_action: {
|
||||
default_popup: "popup.html",
|
||||
browser_style: false,
|
||||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
"popup.html": `<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"></head>
|
||||
<style>
|
||||
html,body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
iframe {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<iframe src="https://example.com/document-builder.sjs?html=${iframeSrc}">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>`,
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
const browserForPopup = await openBrowserActionPanel(
|
||||
extension,
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
|
||||
const iframe = await SpecialPowers.spawn(browserForPopup, [], async () => {
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return content.document && content.document.querySelector("iframe");
|
||||
});
|
||||
const iframeElement = content.document.querySelector("iframe");
|
||||
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return iframeElement.browsingContext;
|
||||
});
|
||||
return iframeElement.browsingContext;
|
||||
});
|
||||
|
||||
const selectRect = await SpecialPowers.spawn(iframe, [], async () => {
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return content.document.querySelector("select");
|
||||
});
|
||||
const select = content.document.querySelector("select");
|
||||
const focusPromise = new Promise(resolve => {
|
||||
select.addEventListener("focus", resolve, { once: true });
|
||||
});
|
||||
select.focus();
|
||||
await focusPromise;
|
||||
|
||||
const r = select.getBoundingClientRect();
|
||||
|
||||
return { left: r.left, bottom: r.bottom };
|
||||
});
|
||||
|
||||
const selectPopup = document.getElementById("ContentSelectDropdown")
|
||||
.firstElementChild;
|
||||
const popupPromise = promisePopupShown(selectPopup);
|
||||
|
||||
BrowserTestUtils.synthesizeMouseAtCenter("select", {}, iframe);
|
||||
|
||||
await popupPromise;
|
||||
|
||||
let popupRect = selectPopup.getOuterScreenRect();
|
||||
|
||||
is(
|
||||
Math.floor(browserForPopup.screenX + selectRect.left),
|
||||
popupRect.left,
|
||||
"Select popup has the correct x origin"
|
||||
);
|
||||
|
||||
// On Mac select popup window appears on the target select element.
|
||||
let expectedY = navigator.platform.includes("Mac")
|
||||
? Math.floor(browserForPopup.screenY)
|
||||
: Math.floor(browserForPopup.screenY + selectRect.bottom);
|
||||
is(expectedY, popupRect.top, "Select popup has the correct y origin");
|
||||
|
||||
const onPopupHidden = BrowserTestUtils.waitForEvent(
|
||||
selectPopup,
|
||||
"popuphidden"
|
||||
);
|
||||
selectPopup.hidePopup();
|
||||
await onPopupHidden;
|
||||
|
||||
await closeBrowserAction(extension);
|
||||
|
||||
await extension.unload();
|
||||
});
|
|
@ -1065,6 +1065,20 @@ nsresult BrowserParent::UpdatePosition() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void BrowserParent::NotifyPositionUpdatedForContentsInPopup() {
|
||||
if (CanonicalBrowsingContext* bc = GetBrowsingContext()) {
|
||||
bc->PreOrderWalk([](BrowsingContext* aContext) {
|
||||
if (WindowGlobalParent* windowGlobalParent =
|
||||
aContext->Canonical()->GetCurrentWindowGlobal()) {
|
||||
if (RefPtr<BrowserParent> browserParent =
|
||||
windowGlobalParent->GetBrowserParent()) {
|
||||
browserParent->UpdatePosition();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserParent::UpdateDimensions(const nsIntRect& rect,
|
||||
const ScreenIntSize& size) {
|
||||
if (mIsDestroyed) {
|
||||
|
|
|
@ -474,6 +474,11 @@ class BrowserParent final : public PBrowserParent,
|
|||
|
||||
nsresult UpdatePosition();
|
||||
|
||||
// Notify position update to all descendant documents in this browser parent.
|
||||
// NOTE: This should use only for browsers in popup windows attached to the
|
||||
// main browser window.
|
||||
void NotifyPositionUpdatedForContentsInPopup();
|
||||
|
||||
void SizeModeChanged(const nsSizeMode& aSizeMode);
|
||||
|
||||
void HandleAccessKey(const WidgetKeyboardEvent& aEvent,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/StaticPrefs_xul.h"
|
||||
#include "mozilla/dom/BrowserParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/KeyboardEvent.h"
|
||||
|
@ -1339,6 +1340,22 @@ nsRect nsMenuPopupFrame::ComputeAnchorRect(nsPresContext* aRootPresContext,
|
|||
PresContext()->AppUnitsPerDevPixel());
|
||||
}
|
||||
|
||||
static void NotifyPositionUpdatedForRemoteContents(nsIContent* aContent) {
|
||||
for (nsIContent* content = aContent->GetFirstChild(); content;
|
||||
content = content->GetNextSibling()) {
|
||||
if (content->IsXULElement(nsGkAtoms::browser) &&
|
||||
content->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::remote,
|
||||
nsGkAtoms::_true, eIgnoreCase)) {
|
||||
if (dom::BrowserParent* browserParent =
|
||||
dom::BrowserParent::GetFrom(content)) {
|
||||
browserParent->NotifyPositionUpdatedForContentsInPopup();
|
||||
}
|
||||
} else {
|
||||
NotifyPositionUpdatedForRemoteContents(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame,
|
||||
bool aIsMove, bool aSizedToPopup) {
|
||||
if (!mShouldAutoPosition) return NS_OK;
|
||||
|
@ -1695,6 +1712,14 @@ nsresult nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame,
|
|||
}
|
||||
}
|
||||
|
||||
// In the case this popup has remote contents having OOP iframes, it's
|
||||
// possible that OOP iframe's nsSubDocumentFrame has been already reflowed
|
||||
// thus, we will never have a chance to tell this parent browser's position
|
||||
// update to the OOP documents without notifying it explicitly.
|
||||
if (HasRemoteContent()) {
|
||||
NotifyPositionUpdatedForRemoteContents(mContent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче