Bug 1888756, part 5 - Text Fragments: Implemented user activation. r=edgar,dom-core

This commit implements the rules given in the spec [0]
to determine if a text directive is allowed to be scrolled to.

This includes checking and consuming the text directive user activation
which was introduced in the previous parts of this patch set.

Additionally, a number of checks given in [1] are implemented.
The newly added method is injected into our scroll-to-fragment
algorithms in `Document::ScrollToRef()` and `nsDocShell::ScrollToAnchor()`.

[0] https://wicg.github.io/scroll-to-text-fragment/#restricting-the-text-fragment
[1] https://wicg.github.io/scroll-to-text-fragment/#check-if-a-text-directive-can-be-scrolled

Differential Revision: https://phabricator.services.mozilla.com/D212820
This commit is contained in:
Jan-Niklas Jaeschke
2024-06-26 14:24:33 +00:00
parent 7ace8811e4
commit 86e1256748
8 changed files with 195 additions and 107 deletions

View File

@@ -10763,23 +10763,28 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
// https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
const nsTArray<RefPtr<nsRange>> textDirectives =
const nsTArray<RefPtr<nsRange>> textDirectiveRanges =
fragmentDirective->FindTextFragmentsInDocument();
const bool hasTextDirectives = !textDirectives.IsEmpty();
fragmentDirective->HighlightTextDirectives(textDirectives);
fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
const bool scrollToTextDirective =
!textDirectiveRanges.IsEmpty() &&
fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
const RefPtr<nsRange> textDirectiveToScroll =
scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
// If we have no new anchor, we do not want to scroll, unless there is a
// current anchor and we are doing a history load. So return if we have no
// new anchor, and there is no current anchor or the load is not a history
// load.
if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef) {
if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
!scrollToTextDirective) {
return NS_OK;
}
// Both the new and current URIs refer to the same page. We can now
// browse to the hash stored in the new URI.
if (aNewHash.IsEmpty() && !hasTextDirectives) {
if (aNewHash.IsEmpty() && !scrollToTextDirective) {
// 2. If fragment is the empty string, then return the special value top of
// the document.
//
@@ -10799,10 +10804,11 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
// 3. Let potentialIndicatedElement be the result of finding a potential
// indicated element given document and fragment.
NS_ConvertUTF8toUTF16 uStr(aNewHash);
RefPtr<nsRange> range =
!textDirectives.IsEmpty() ? textDirectives[0] : nullptr;
auto rv =
presShell->GoToAnchor(uStr, range, scroll, ScrollFlags::ScrollSmoothAuto);
MOZ_ASSERT(!uStr.IsEmpty() || scrollToTextDirective);
auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
ScrollFlags::ScrollSmoothAuto);
// 4. If potentialIndicatedElement is not null, then return
// potentialIndicatedElement.