зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1827516 - Fix retargeting of UAWidget.elementFromPoint(). r=smaug
The continue in GetContentInThisDocument meant that if we call that in a UA widget we'd return null... This breaks the following check: https://searchfox.org/mozilla-central/rev/31f5847a4494b3646edabbdd7ea39cb88509afe2/toolkit/content/widgets/videocontrols.js#1373-1381 Which was introduced in bug 1513600 to fix precisely this bug... Depends on D175714 Differential Revision: https://phabricator.services.mozilla.com/D175715
This commit is contained in:
Родитель
df7453527a
Коммит
452fa41d65
|
@ -11652,7 +11652,9 @@ nsIContent* Document::GetContentInThisDocument(nsIFrame* aFrame) const {
|
||||||
for (nsIFrame* f = aFrame; f;
|
for (nsIFrame* f = aFrame; f;
|
||||||
f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
|
f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
|
||||||
nsIContent* content = f->GetContent();
|
nsIContent* content = f->GetContent();
|
||||||
if (!content || content->IsInNativeAnonymousSubtree()) continue;
|
if (!content) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (content->OwnerDoc() == this) {
|
if (content->OwnerDoc() == this) {
|
||||||
return content;
|
return content;
|
||||||
|
|
|
@ -285,8 +285,8 @@ already_AddRefed<nsContentList> DocumentOrShadowRoot::GetElementsByClassName(
|
||||||
return nsContentUtils::GetElementsByClassName(&AsNode(), aClasses);
|
return nsContentUtils::GetElementsByClassName(&AsNode(), aClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIContent* DocumentOrShadowRoot::Retarget(nsIContent* aContent) const {
|
nsINode* DocumentOrShadowRoot::Retarget(nsINode* aNode) const {
|
||||||
for (nsIContent* cur = aContent; cur; cur = cur->GetContainingShadowHost()) {
|
for (nsINode* cur = aNode; cur; cur = cur->GetContainingShadowHost()) {
|
||||||
if (cur->SubtreeRoot() == &AsNode()) {
|
if (cur->SubtreeRoot() == &AsNode()) {
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ Element* DocumentOrShadowRoot::GetRetargetedFocusedElement() {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (nsIContent* retarget = Retarget(content)) {
|
if (nsINode* retarget = Retarget(content)) {
|
||||||
return retarget->AsElement();
|
return retarget->AsElement();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -308,15 +308,7 @@ Element* DocumentOrShadowRoot::GetRetargetedFocusedElement() {
|
||||||
Element* DocumentOrShadowRoot::GetPointerLockElement() {
|
Element* DocumentOrShadowRoot::GetPointerLockElement() {
|
||||||
nsCOMPtr<Element> pointerLockedElement =
|
nsCOMPtr<Element> pointerLockedElement =
|
||||||
PointerLockManager::GetLockedElement();
|
PointerLockManager::GetLockedElement();
|
||||||
if (!pointerLockedElement) {
|
return Element::FromNodeOrNull(Retarget(pointerLockedElement));
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIContent* retargetedPointerLockedElement = Retarget(pointerLockedElement);
|
|
||||||
return retargetedPointerLockedElement &&
|
|
||||||
retargetedPointerLockedElement->IsElement()
|
|
||||||
? retargetedPointerLockedElement->AsElement()
|
|
||||||
: nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Element* DocumentOrShadowRoot::GetFullscreenElement() const {
|
Element* DocumentOrShadowRoot::GetFullscreenElement() const {
|
||||||
|
@ -327,13 +319,7 @@ Element* DocumentOrShadowRoot::GetFullscreenElement() const {
|
||||||
Element* element = AsNode().OwnerDoc()->GetUnretargetedFullscreenElement();
|
Element* element = AsNode().OwnerDoc()->GetUnretargetedFullscreenElement();
|
||||||
NS_ASSERTION(!element || element->State().HasState(ElementState::FULLSCREEN),
|
NS_ASSERTION(!element || element->State().HasState(ElementState::FULLSCREEN),
|
||||||
"Fullscreen element should have fullscreen styles applied");
|
"Fullscreen element should have fullscreen styles applied");
|
||||||
|
return Element::FromNodeOrNull(Retarget(element));
|
||||||
nsIContent* retargeted = Retarget(element);
|
|
||||||
if (retargeted && retargeted->IsElement()) {
|
|
||||||
return retargeted->AsElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -359,16 +345,16 @@ enum class PerformRetargeting {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename NodeOrElement>
|
template <typename NodeOrElement>
|
||||||
NodeOrElement* CastTo(nsIContent* aContent);
|
NodeOrElement* CastTo(nsINode*);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
Element* CastTo<Element>(nsIContent* aContent) {
|
Element* CastTo<Element>(nsINode* aNode) {
|
||||||
return aContent->AsElement();
|
return aNode->AsElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
nsINode* CastTo<nsINode>(nsIContent* aContent) {
|
nsINode* CastTo<nsINode>(nsINode* aNode) {
|
||||||
return aContent;
|
return aNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename NodeOrElement>
|
template <typename NodeOrElement>
|
||||||
|
@ -413,12 +399,23 @@ static void QueryNodesFromRect(DocumentOrShadowRoot& aRoot, const nsRect& aRect,
|
||||||
aOptions);
|
aOptions);
|
||||||
|
|
||||||
for (nsIFrame* frame : frames) {
|
for (nsIFrame* frame : frames) {
|
||||||
nsIContent* content = doc->GetContentInThisDocument(frame);
|
nsINode* node = doc->GetContentInThisDocument(frame);
|
||||||
if (!content) {
|
while (node && node->IsInNativeAnonymousSubtree()) {
|
||||||
|
nsIContent* root = node->GetClosestNativeAnonymousSubtreeRoot();
|
||||||
|
MOZ_ASSERT(root, "content is connected");
|
||||||
|
MOZ_ASSERT(root->IsRootOfNativeAnonymousSubtree(), "wat");
|
||||||
|
if (root == &aRoot.AsNode()) {
|
||||||
|
// If we're in the anonymous subtree root we care about, don't retarget.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = root->GetParentOrShadowHostNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returningElements && !content->IsElement()) {
|
if (returningElements && !node->IsElement()) {
|
||||||
// If this helper is called via ElementsFromPoint, we need to make sure
|
// If this helper is called via ElementsFromPoint, we need to make sure
|
||||||
// our frame is an element. Otherwise return whatever the top frame is
|
// our frame is an element. Otherwise return whatever the top frame is
|
||||||
// even if it isn't the top-painted element.
|
// even if it isn't the top-painted element.
|
||||||
|
@ -429,9 +426,9 @@ static void QueryNodesFromRect(DocumentOrShadowRoot& aRoot, const nsRect& aRect,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
content = content->GetParent();
|
node = node->GetParent();
|
||||||
if (ShadowRoot* shadow = ShadowRoot::FromNodeOrNull(content)) {
|
if (ShadowRoot* shadow = ShadowRoot::FromNodeOrNull(node)) {
|
||||||
content = shadow->Host();
|
node = shadow->Host();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,11 +436,11 @@ static void QueryNodesFromRect(DocumentOrShadowRoot& aRoot, const nsRect& aRect,
|
||||||
// https://github.com/w3c/webcomponents/issues/735
|
// https://github.com/w3c/webcomponents/issues/735
|
||||||
// https://github.com/w3c/webcomponents/issues/736
|
// https://github.com/w3c/webcomponents/issues/736
|
||||||
if (retargeting) {
|
if (retargeting) {
|
||||||
content = aRoot.Retarget(content);
|
node = aRoot.Retarget(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content && content != aNodes.SafeLastElement(nullptr)) {
|
if (node && node != aNodes.SafeLastElement(nullptr)) {
|
||||||
aNodes.AppendElement(CastTo<NodeOrElement>(content));
|
aNodes.AppendElement(CastTo<NodeOrElement>(node));
|
||||||
if (aMultiple == Multiple::No) {
|
if (aMultiple == Multiple::No) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,7 @@ class DocumentOrShadowRoot : public RadioGroupManager {
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations);
|
void GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations);
|
||||||
|
|
||||||
nsIContent* Retarget(nsIContent* aContent) const;
|
nsINode* Retarget(nsINode*) const;
|
||||||
|
|
||||||
void OnSetAdoptedStyleSheets(StyleSheet&, uint32_t aIndex, ErrorResult&);
|
void OnSetAdoptedStyleSheets(StyleSheet&, uint32_t aIndex, ErrorResult&);
|
||||||
void OnDeleteAdoptedStyleSheets(StyleSheet&, uint32_t aIndex, ErrorResult&);
|
void OnDeleteAdoptedStyleSheets(StyleSheet&, uint32_t aIndex, ErrorResult&);
|
||||||
|
|
|
@ -32,6 +32,7 @@ support-files =
|
||||||
../../widgets/panel-item.css
|
../../widgets/panel-item.css
|
||||||
../../widgets/panel-list.js
|
../../widgets/panel-list.js
|
||||||
../../widgets/panel-list.css
|
../../widgets/panel-list.css
|
||||||
|
[test_ua_widget_elementFromPoint.html]
|
||||||
[test_ua_widget_sandbox.html]
|
[test_ua_widget_sandbox.html]
|
||||||
[test_ua_widget_unbind.html]
|
[test_ua_widget_unbind.html]
|
||||||
[test_videocontrols.html]
|
[test_videocontrols.html]
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>UA Widget getElementFromPoint</title>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
|
||||||
|
<div id="host" style="width: 100px; height: 100px;"></div>
|
||||||
|
<script>
|
||||||
|
const host = document.getElementById("host");
|
||||||
|
SpecialPowers.wrap(host.attachShadow({ mode: "open"})).setIsUAWidget();
|
||||||
|
host.shadowRoot.innerHTML = `
|
||||||
|
<div style="width: 100px; height: 100px; background-color: green;"></div>
|
||||||
|
`;
|
||||||
|
let hostRect = host.getBoundingClientRect();
|
||||||
|
let point = {
|
||||||
|
x: hostRect.x + 50,
|
||||||
|
y: hostRect.y + 50,
|
||||||
|
};
|
||||||
|
is(document.elementFromPoint(point.x, point.y), host,
|
||||||
|
"Host should be found from the document");
|
||||||
|
is(host.shadowRoot.elementFromPoint(point.x, point.y), host.shadowRoot.firstElementChild,
|
||||||
|
"Should not have retargeted UA widget content to host unnecessarily");
|
||||||
|
</script>
|
Загрузка…
Ссылка в новой задаче