Bug 206314 - Use Visible Position to calculate Positions for highlights
Summary: Use Visible Position to calculate Positions for highlights
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Megan Gardner
URL:
Keywords: InRadar
: 205529 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-01-15 13:55 PST by Megan Gardner
Modified: 2020-01-30 13:15 PST (History)
15 users (show)

See Also:


Attachments
Patch (23.64 KB, patch)
2020-01-15 14:14 PST, Megan Gardner
no flags Details | Formatted Diff | Diff
Patch (22.87 KB, patch)
2020-01-15 17:12 PST, Megan Gardner
no flags Details | Formatted Diff | Diff
Patch (13.42 KB, patch)
2020-01-15 18:08 PST, Megan Gardner
no flags Details | Formatted Diff | Diff
Patch (12.84 KB, patch)
2020-01-15 19:40 PST, Megan Gardner
no flags Details | Formatted Diff | Diff
Patch (22.52 KB, patch)
2020-01-16 19:30 PST, Megan Gardner
no flags Details | Formatted Diff | Diff
Patch (23.54 KB, patch)
2020-01-17 15:42 PST, Megan Gardner
no flags Details | Formatted Diff | Diff
Patch for landing (23.33 KB, patch)
2020-01-17 17:30 PST, Megan Gardner
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Megan Gardner 2020-01-15 13:55:17 PST
Use Visible Position to calculate Positions for highlights
Comment 1 Megan Gardner 2020-01-15 14:14:53 PST
Created attachment 387845 [details]
Patch
Comment 2 Ryosuke Niwa 2020-01-15 16:14:11 PST
Comment on attachment 387845 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=387845&action=review

> Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp:85
> +        auto visibleSelection = VisibleSelection(Range::create(*rangeGroup->m_document.get(), data->range));

It makes no sense to create a Range just so that we can create VisibleSelection. r- because of this.
Once again, Range is a very expensive object to create so we should avoid making one.
Just add a new constructor of VisibleSelection which takes StaticRange instead.
Also, what guarantees that boundary points of StaticRange still point to nodes in the same document at this point?

> Source/WebCore/Modules/highlight/HighlightRangeGroup.h:49
> +    HighlightRangeData(StaticRange&& range)

Nit: Please define this before all data members and place a blank line
between member functions & member variables to visually separate them.

> Source/WebCore/Modules/highlight/HighlightRangeGroup.h:71
> +    

Nit: whitespace.

> Source/WebCore/editing/TextManipulationController.cpp:-209
> -

This seems like an unrelated change. Please revert.

> Source/WebCore/rendering/InlineTextBox.cpp:1055
> +                

Ditto. Revert.

> Source/WebCore/rendering/InlineTextBox.cpp:1060
> +                    highlightData.setContext({startRenderer, endRenderer, static_cast<unsigned>(startOffset), static_cast<unsigned>(endOffset)});

Ditto.

> Source/WebCore/rendering/SelectionRangeData.cpp:170
> -    if (&renderer == m_selectionContext.start() || renderer.isDescendantOf(m_selectionContext.start())) {
> +    if (&renderer == m_selectionContext.start() /*|| renderer.isDescendantOf(m_selectionContext.start())*/) {

What's happening with this? We don't commit commented out code like this.

> Source/WebCore/rendering/SelectionRangeData.cpp:176
> -    if (&renderer == m_selectionContext.end() || renderer.isDescendantOf(m_selectionContext.end()))
> +    if (&renderer == m_selectionContext.end() /*|| renderer.isDescendantOf(m_selectionContext.end())*/)

Ditto.
Comment 3 Megan Gardner 2020-01-15 17:12:45 PST
Created attachment 387873 [details]
Patch
Comment 4 Megan Gardner 2020-01-15 18:08:21 PST
Created attachment 387882 [details]
Patch
Comment 5 Ryosuke Niwa 2020-01-15 18:38:39 PST
Comment on attachment 387882 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=387882&action=review

Okay, the new patch looks better but there is one security bug in this patch so we need to fix that before I can r+ it.

> Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp:80
> +    

Nit: whitespace.

> Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp:84
> +        if (!data || !areNodesConnectedInSameTreeScope(data->range->startContainer(), data->range->endContainer()))
> +            return;

Hm... areNodesConnectedInSameTreeScope returns true when both nodes are disconnected. We want to check that.
So we need to exit early when !data->range->startContainer().isConnected().
In fact, it might be simpler to just check that &data->range->startContainer().treeScope() == &data->range->endContainer().treeScope()

> Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp:86
> +        auto visibleSelection = VisibleSelection(data->range);

Why not just: VisibleSelection visibleSelection(data->range);

> Source/WebCore/Modules/highlight/HighlightRangeGroup.cpp:88
> +        data->startPosition = visibleSelection.visibleStart().deepEquivalent();
> +        data->endPosition = visibleSelection.visibleEnd().deepEquivalent();

Let's not safe to access data here.
Construction of VisibleSelection and calls to visibleStart or visibleEnd can easy trigger a sync layout,
execute arbitrary JS and delete this highlight group.

You should either check nullity of weakData after each call, or make a copy of HighightRangeData at the beginning.

> Source/WebCore/Modules/highlight/HighlightRangeGroup.h:47
> +    static Ref<HighlightRangeData> create(Ref<StaticRange>&& range)

Nit: Need a blank line between the constructor & this static member function.

> Source/WebCore/Modules/highlight/HighlightRangeGroup.h:71
> +    Vector<Ref<HighlightRangeData>> m_rangesData; // TODO: use a HashSet instead of a Vector <rdar://problem/57760614>

Nit: Use FIXME instead.

> Source/WebCore/dom/Range.cpp:48
> +#include "StaticRange.h"

Why do we need to include StaticRange.h here?

> Source/WebCore/dom/Range.h:47
> +class StaticRange;

Ditto.

> Source/WebCore/editing/VisibleSelection.cpp:106
> +    validate();

We should assert that the caller has checked both start & end belong to the same document here.
i.e. check that &staticRange.startContainer()->treeScope() == &staticRange.endContainer()->treeScope().
Comment 6 Megan Gardner 2020-01-15 19:40:58 PST
Created attachment 387888 [details]
Patch
Comment 7 Ryosuke Niwa 2020-01-16 11:34:05 PST
Looks like CSS highlight tests are failing?
Comment 8 Megan Gardner 2020-01-16 19:30:11 PST
Created attachment 388005 [details]
Patch
Comment 9 Ryosuke Niwa 2020-01-16 23:21:00 PST
Comment on attachment 388005 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=388005&action=review

> Source/WebCore/dom/Document.cpp:2747
> +        for (auto& highlight : m_highlightMap->map()) {
> +            for (auto& rangeData : highlight.value->rangesData()) {

These iterations aren't safe because you're constructing VisibleSelection inside.
Constructing VisibleSelection can result in layout to be updated and execute arbitrary JS code.
We probably have to make a copy of highlight groups to a Vector instead.
For each highlight group, we also need to make a Vector of WeakPtr to range data or something.

> Source/WebCore/dom/Document.cpp:2748
> +                if ((rangeData->startPosition.isNotNull() && rangeData->endPosition.isNotNull()) || (&rangeData->range->startContainer()->treeScope() != &rangeData->range->endContainer()->treeScope()))

Hm... instead of using positions being null as a way of detecting positions not being set,
can we use Optional like Optional<pair<Position, Position>> or add a dedicated boolean flag?
Comment 10 Megan Gardner 2020-01-17 15:42:57 PST
Created attachment 388101 [details]
Patch
Comment 11 Ryosuke Niwa 2020-01-17 16:29:12 PST
Comment on attachment 388101 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=388101&action=review

> Source/WebCore/dom/Document.cpp:2751
> +                if ((!rangeData->startPosition.hasValue() || !rangeData->endPosition.hasValue())
> +                    && (&rangeData->range->startContainer()->treeScope() == &rangeData->range->endContainer()->treeScope()))
> +                    rangesData.append(makeWeakPtr(rangeData.ptr()));

This is a complicated expression. Can we continue early instead? i.e.
if (!rangeData->startPosition || !rangeData->endPosition)
    continue;
if (rangeData->range->startContainer()->treeScope() != &rangeData->range->endContainer()->treeScope())
    continue;
rangesData.append(makeWeakPtr(rangeData.ptr()));

> Source/WebCore/dom/Document.cpp:2765
> +            if (weakRangeData.get()) {

Continue when !weakRangeData instead?

> Source/WebCore/dom/Document.cpp:2766
> +                if (!rangeData->startPosition.hasValue())

I don't think we need to check this since it's unlikely that Page::updateRendering would have ran by updating the layout.
Even if did, there is no harm in re-setting to the new position value.

> Source/WebCore/dom/Document.cpp:2767
> +                    rangeData->startPosition = visibleSelection.visibleStart().deepEquivalent();

Need to do this instead: rangeData->startPosition = startPosition

> Source/WebCore/dom/Document.cpp:2768
> +                if (!rangeData->endPosition.hasValue())

Ditto.

> Source/WebCore/dom/Document.cpp:2769
> +                    rangeData->endPosition = visibleSelection.visibleEnd().deepEquivalent();

Ditto.

> Source/WebCore/rendering/InlineTextBox.cpp:1047
> +            if (rangeData->startPosition.hasValue() && rangeData->endPosition.hasValue()) {

Nit: It's more succinct to say: rangeData->startPosition && rangeData->endPosition.
Comment 12 Wenson Hsieh 2020-01-17 16:49:32 PST
Comment on attachment 388101 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=388101&action=review

> Source/WebCore/Modules/highlight/HighlightRangeGroup.h:38
> +class Position;

Nit - you don't need the forward declaration here if you also #include "Position.h"
Comment 13 Megan Gardner 2020-01-17 17:30:26 PST
Created attachment 388121 [details]
Patch for landing
Comment 14 WebKit Commit Bot 2020-01-17 18:13:22 PST
Comment on attachment 388121 [details]
Patch for landing

Clearing flags on attachment: 388121

Committed r254785: <https://trac.webkit.org/changeset/254785>
Comment 15 WebKit Commit Bot 2020-01-17 18:13:24 PST
All reviewed patches have been landed.  Closing bug.
Comment 16 Radar WebKit Bug Importer 2020-01-17 18:14:12 PST
<rdar://problem/58703201>
Comment 17 Megan Gardner 2020-01-30 13:15:46 PST
*** Bug 205529 has been marked as a duplicate of this bug. ***