зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1669996 - Do not expose chromeonly nodes via Selection API r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D93258
This commit is contained in:
Родитель
a22b90ec8c
Коммит
5a12264fb1
|
@ -248,22 +248,42 @@ class Selection final : public nsSupportsWeakReference,
|
|||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// WebIDL methods
|
||||
nsINode* GetAnchorNode() const {
|
||||
nsINode* GetAnchorNode(CallerType aCallerType = CallerType::System) const {
|
||||
const RangeBoundary& anchor = AnchorRef();
|
||||
return anchor.IsSet() ? anchor.Container() : nullptr;
|
||||
nsINode* anchorNode = anchor.IsSet() ? anchor.Container() : nullptr;
|
||||
if (!anchorNode || aCallerType == CallerType::System ||
|
||||
!anchorNode->ChromeOnlyAccess()) {
|
||||
return anchorNode;
|
||||
}
|
||||
// anchor is nsIContent as ChromeOnlyAccess is nsIContent-only
|
||||
return anchorNode->AsContent()->FindFirstNonChromeOnlyAccessContent();
|
||||
}
|
||||
uint32_t AnchorOffset() const {
|
||||
uint32_t AnchorOffset(CallerType aCallerType = CallerType::System) const {
|
||||
const RangeBoundary& anchor = AnchorRef();
|
||||
if (aCallerType != CallerType::System && anchor.IsSet() &&
|
||||
anchor.Container()->ChromeOnlyAccess()) {
|
||||
return 0;
|
||||
}
|
||||
const Maybe<uint32_t> offset =
|
||||
anchor.Offset(RangeBoundary::OffsetFilter::kValidOffsets);
|
||||
return offset ? *offset : 0;
|
||||
}
|
||||
nsINode* GetFocusNode() const {
|
||||
nsINode* GetFocusNode(CallerType aCallerType = CallerType::System) const {
|
||||
const RangeBoundary& focus = FocusRef();
|
||||
return focus.IsSet() ? focus.Container() : nullptr;
|
||||
nsINode* focusNode = focus.IsSet() ? focus.Container() : nullptr;
|
||||
if (!focusNode || aCallerType == CallerType::System ||
|
||||
!focusNode->ChromeOnlyAccess()) {
|
||||
return focusNode;
|
||||
}
|
||||
// focus is nsIContent as ChromeOnlyAccess is nsIContent-only
|
||||
return focusNode->AsContent()->FindFirstNonChromeOnlyAccessContent();
|
||||
}
|
||||
uint32_t FocusOffset() const {
|
||||
uint32_t FocusOffset(CallerType aCallerType = CallerType::System) const {
|
||||
const RangeBoundary& focus = FocusRef();
|
||||
if (aCallerType != CallerType::System && focus.IsSet() &&
|
||||
focus.Container()->ChromeOnlyAccess()) {
|
||||
return 0;
|
||||
}
|
||||
const Maybe<uint32_t> offset =
|
||||
focus.Offset(RangeBoundary::OffsetFilter::kValidOffsets);
|
||||
return offset ? *offset : 0;
|
||||
|
|
|
@ -1363,6 +1363,7 @@ class nsINode : public mozilla::dom::EventTarget {
|
|||
bool HasBeenInUAWidget() const { return HasFlag(NODE_HAS_BEEN_IN_UA_WIDGET); }
|
||||
|
||||
// True for native anonymous content and for content in UA widgets.
|
||||
// Only nsIContent can fulfill this condition.
|
||||
bool ChromeOnlyAccess() const {
|
||||
return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
|
||||
NODE_HAS_BEEN_IN_UA_WIDGET);
|
||||
|
|
|
@ -12,9 +12,13 @@
|
|||
|
||||
[Exposed=Window]
|
||||
interface Selection {
|
||||
[NeedsCallerType]
|
||||
readonly attribute Node? anchorNode;
|
||||
[NeedsCallerType]
|
||||
readonly attribute unsigned long anchorOffset;
|
||||
[NeedsCallerType]
|
||||
readonly attribute Node? focusNode;
|
||||
[NeedsCallerType]
|
||||
readonly attribute unsigned long focusOffset;
|
||||
readonly attribute boolean isCollapsed;
|
||||
/**
|
||||
|
@ -102,7 +106,7 @@ partial interface Selection {
|
|||
|
||||
/**
|
||||
* Return array of ranges intersecting with the given DOM interval.
|
||||
*/
|
||||
*/
|
||||
[ChromeOnly,Throws,Pref="dom.testing.selection.GetRangesForInterval"]
|
||||
sequence<Range> GetRangesForInterval(Node beginNode, long beginOffset, Node endNode, long endOffset,
|
||||
boolean allowAdjacent);
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Selecting internal node</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<link rel="stylesheet" href="/fonts/ahem.css">
|
||||
<style>
|
||||
details {
|
||||
font: 16px/1 Ahem;
|
||||
}
|
||||
</style>
|
||||
<details id="details"></details>
|
||||
<script>
|
||||
promise_test(async () => {
|
||||
await new test_driver.Actions()
|
||||
.pointerMove(5, 5, {origin: details})
|
||||
.pointerDown()
|
||||
.pointerMove(50, 50)
|
||||
.pointerUp()
|
||||
.send();
|
||||
const selection = getSelection();
|
||||
// Gecko throws when accessing any property from DOM-invisible node
|
||||
// so check we can access something
|
||||
assert_equals(selection.anchorNode.constructor.name, "HTMLDetailsElement");
|
||||
assert_equals(selection.anchorOffset, 0);
|
||||
// Gecko limits the selection inside <details> while Blink does not
|
||||
// so check something general
|
||||
assert_equals(selection.focusNode.nodeType, Node.ELEMENT_NODE);
|
||||
assert_equals(selection.focusOffset, 0);
|
||||
}, "Selecting the default summary of <details> should report a DOM-visible ancestor");
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче