| Index: third_party/WebKit/Source/web/TextFinder.cpp
|
| diff --git a/third_party/WebKit/Source/web/TextFinder.cpp b/third_party/WebKit/Source/web/TextFinder.cpp
|
| index 4f6ea4071f41fc591a29e4b1a71e0d3519dde50c..407dc0d75e6b7698703d9de4ac15f24d8a189790 100644
|
| --- a/third_party/WebKit/Source/web/TextFinder.cpp
|
| +++ b/third_party/WebKit/Source/web/TextFinder.cpp
|
| @@ -117,8 +117,6 @@ bool TextFinder::find(int identifier, const WebString& searchText, const WebFind
|
| if (!ownerFrame().frame() || !ownerFrame().frame()->page())
|
| return false;
|
|
|
| - WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl();
|
| -
|
| if (!options.findNext)
|
| unmarkAllTextMatches();
|
| else
|
| @@ -164,49 +162,58 @@ bool TextFinder::find(int identifier, const WebString& searchText, const WebFind
|
| ownerFrame().viewImpl()->zoomToFindInPageRect(ownerFrame().frameView()->contentsToRootFrame(enclosingIntRect(LayoutObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()))));
|
| }
|
|
|
| - WebLocalFrameImpl* oldActiveFrame = mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame;
|
| - mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame = &ownerFrame();
|
| -
|
| - // Make sure no node is focused. See http://crbug.com/38700.
|
| - ownerFrame().frame()->document()->clearFocusedElement();
|
| + bool wasActiveFrame = m_currentActiveMatchFrame;
|
| + m_currentActiveMatchFrame = true;
|
|
|
| bool isActive = setMarkerActive(m_activeMatch.get(), true);
|
| if (activeNow)
|
| *activeNow = isActive;
|
|
|
| + // Make sure no node is focused. See http://crbug.com/38700.
|
| + ownerFrame().frame()->document()->clearFocusedElement();
|
| +
|
| + // Set this frame as focused.
|
| + ownerFrame().viewImpl()->setFocusedFrame(&ownerFrame());
|
| +
|
| if (!options.findNext || activeSelection || !isActive) {
|
| - // This is either a Find operation, a Find-next from a new start point
|
| - // due to a selection, or new matches were found during Find-next due
|
| - // to DOM alteration (that couldn't be set as active), so we set the
|
| - // flag to ask the scoping effort to find the active rect for us and
|
| - // report it back to the UI.
|
| + // This is either an initial Find operation, a Find-next from a new
|
| + // start point due to a selection, or new matches were found during
|
| + // Find-next due to DOM alteration (that couldn't be set as active), so
|
| + // we set the flag to ask the scoping effort to find the active rect for
|
| + // us and report it back to the UI.
|
| m_locatingActiveRect = true;
|
| } else {
|
| - if (oldActiveFrame != &ownerFrame()) {
|
| + if (!wasActiveFrame) {
|
| if (options.forward)
|
| - m_activeMatchIndexInCurrentFrame = 0;
|
| + m_activeMatchIndex = 0;
|
| else
|
| - m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
|
| + m_activeMatchIndex = m_lastMatchCount - 1;
|
| } else {
|
| if (options.forward)
|
| - ++m_activeMatchIndexInCurrentFrame;
|
| + ++m_activeMatchIndex;
|
| else
|
| - --m_activeMatchIndexInCurrentFrame;
|
| + --m_activeMatchIndex;
|
|
|
| - if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount)
|
| - m_activeMatchIndexInCurrentFrame = 0;
|
| - if (m_activeMatchIndexInCurrentFrame == -1)
|
| - m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
|
| + if (m_activeMatchIndex + 1 > m_lastMatchCount)
|
| + m_activeMatchIndex = 0;
|
| + else if (m_activeMatchIndex < 0)
|
| + m_activeMatchIndex = m_lastMatchCount - 1;
|
| }
|
| if (selectionRect) {
|
| *selectionRect = ownerFrame().frameView()->contentsToRootFrame(m_activeMatch->boundingBox());
|
| - reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurrentFrame + 1, identifier);
|
| + reportFindInPageSelection(*selectionRect, m_activeMatchIndex + 1, identifier);
|
| }
|
| }
|
|
|
| return true;
|
| }
|
|
|
| +void TextFinder::clearActiveFindMatch()
|
| +{
|
| + m_currentActiveMatchFrame = false;
|
| + setMarkerActive(m_activeMatch.get(), false);
|
| +}
|
| +
|
| void TextFinder::stopFindingAndClearSelection()
|
| {
|
| cancelPendingScopingEffort();
|
| @@ -232,10 +239,9 @@ void TextFinder::reportFindInPageResultToAccessibility(int identifier)
|
| if (!startObject || !endObject)
|
| return;
|
|
|
| - WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl();
|
| - if (mainFrameImpl && mainFrameImpl->client()) {
|
| - mainFrameImpl->client()->handleAccessibilityFindInPageResult(
|
| - identifier, m_activeMatchIndexInCurrentFrame + 1,
|
| + if (ownerFrame().client()) {
|
| + ownerFrame().client()->handleAccessibilityFindInPageResult(
|
| + identifier, m_activeMatchIndex + 1,
|
| WebAXObject(startObject), m_activeMatch->startOffset(),
|
| WebAXObject(endObject), m_activeMatch->endOffset());
|
| }
|
| @@ -266,7 +272,7 @@ void TextFinder::scopeStringMatches(int identifier, const WebString& searchText,
|
| // The view might be null on detached frames.
|
| LocalFrame* frame = ownerFrame().frame();
|
| if (frame && frame->page())
|
| - ownerFrame().viewImpl()->mainFrameImpl()->ensureTextFinder().m_framesScopingCount++;
|
| + m_frameScoping = true;
|
|
|
| // Now, defer scoping until later to allow find operation to finish quickly.
|
| scopeStringMatchesSoon(identifier, searchText, options, false); // false means just reset, so don't do it again.
|
| @@ -274,14 +280,10 @@ void TextFinder::scopeStringMatches(int identifier, const WebString& searchText,
|
| }
|
|
|
| if (!shouldScopeMatches(searchText)) {
|
| - // Note that we want to defer the final update when resetting even if shouldScopeMatches returns false.
|
| - // This is done in order to prevent sending a final message based only on the results of the first frame
|
| - // since m_framesScopingCount would be 0 as other frames have yet to reset.
|
| finishCurrentScopingEffort(identifier);
|
| return;
|
| }
|
|
|
| - WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl();
|
| PositionInFlatTree searchStart = PositionInFlatTree::firstPositionInNode(ownerFrame().frame()->document());
|
| PositionInFlatTree searchEnd = PositionInFlatTree::lastPositionInNode(ownerFrame().frame()->document());
|
| DCHECK_EQ(searchStart.document(), searchEnd.document());
|
| @@ -341,17 +343,17 @@ void TextFinder::scopeStringMatches(int identifier, const WebString& searchText,
|
| bool foundActiveMatch = false;
|
| if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) {
|
| // We have found the active tickmark frame.
|
| - mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame = &ownerFrame();
|
| + m_currentActiveMatchFrame = true;
|
| foundActiveMatch = true;
|
| // We also know which tickmark is active now.
|
| - m_activeMatchIndexInCurrentFrame = matchCount - 1;
|
| + m_activeMatchIndex = matchCount - 1;
|
| // To stop looking for the active tickmark, we set this flag.
|
| m_locatingActiveRect = false;
|
|
|
| // Notify browser of new location for the selected rectangle.
|
| reportFindInPageSelection(
|
| ownerFrame().frameView()->contentsToRootFrame(resultBounds),
|
| - m_activeMatchIndexInCurrentFrame + 1,
|
| + m_activeMatchIndex + 1,
|
| identifier);
|
| }
|
|
|
| @@ -380,8 +382,8 @@ void TextFinder::scopeStringMatches(int identifier, const WebString& searchText,
|
|
|
| ownerFrame().client()->reportFindInFrameMatchCount(identifier, m_lastMatchCount, false);
|
|
|
| - // Let the mainframe know how much we found during this pass.
|
| - mainFrameImpl->increaseMatchCount(matchCount, identifier);
|
| + // Let the frame know how many matches we found during this pass.
|
| + ownerFrame().increaseMatchCount(matchCount, identifier);
|
| }
|
|
|
| if (timedOut) {
|
| @@ -408,8 +410,8 @@ void TextFinder::flushCurrentScopingEffort(int identifier)
|
| if (!ownerFrame().frame() || !ownerFrame().frame()->page())
|
| return;
|
|
|
| - WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl();
|
| - mainFrameImpl->ensureTextFinder().decrementFramesScopingCount(identifier);
|
| + m_frameScoping = false;
|
| + ownerFrame().increaseMatchCount(0, identifier);
|
| }
|
|
|
| void TextFinder::finishCurrentScopingEffort(int identifier)
|
| @@ -431,7 +433,7 @@ void TextFinder::cancelPendingScopingEffort()
|
| deferredWork->dispose();
|
| m_deferredScopingWork.clear();
|
|
|
| - m_activeMatchIndexInCurrentFrame = -1;
|
| + m_activeMatchIndex = -1;
|
|
|
| // Last request didn't complete.
|
| if (m_scopingInProgress)
|
| @@ -449,14 +451,14 @@ void TextFinder::increaseMatchCount(int identifier, int count)
|
|
|
| // Update the UI with the latest findings.
|
| if (ownerFrame().client())
|
| - ownerFrame().client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_framesScopingCount);
|
| + ownerFrame().client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_frameScoping);
|
| }
|
|
|
| void TextFinder::reportFindInPageSelection(const WebRect& selectionRect, int activeMatchOrdinal, int identifier)
|
| {
|
| // Update the UI with the latest selection rect.
|
| if (ownerFrame().client())
|
| - ownerFrame().client()->reportFindInPageSelection(identifier, ordinalOfFirstMatch() + activeMatchOrdinal, selectionRect);
|
| + ownerFrame().client()->reportFindInPageSelection(identifier, activeMatchOrdinal, selectionRect);
|
|
|
| // Update accessibility too, so if the user commits to this query
|
| // we can move accessibility focus to this result.
|
| @@ -469,29 +471,18 @@ void TextFinder::resetMatchCount()
|
| ++m_findMatchMarkersVersion;
|
|
|
| m_totalMatchCount = 0;
|
| - m_framesScopingCount = 0;
|
| + m_frameScoping = false;
|
| }
|
|
|
| void TextFinder::clearFindMatchesCache()
|
| {
|
| if (!m_findMatchesCache.isEmpty())
|
| - ownerFrame().viewImpl()->mainFrameImpl()->ensureTextFinder().m_findMatchMarkersVersion++;
|
| + ++m_findMatchMarkersVersion;
|
|
|
| m_findMatchesCache.clear();
|
| m_findMatchRectsAreValid = false;
|
| }
|
|
|
| -bool TextFinder::isActiveMatchFrameValid() const
|
| -{
|
| - WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl();
|
| - if (!mainFrameImpl->textFinder())
|
| - return false;
|
| -
|
| - if (WebLocalFrameImpl* activeMatchFrame = mainFrameImpl->textFinder()->activeMatchFrame())
|
| - return activeMatchFrame->textFinder()->activeMatch() && activeMatchFrame->frame()->tree().isDescendantOf(mainFrameImpl->frame());
|
| - return false;
|
| -}
|
| -
|
| void TextFinder::updateFindMatchRects()
|
| {
|
| IntSize currentContentsSize = ownerFrame().contentsSize();
|
| @@ -534,71 +525,56 @@ void TextFinder::updateFindMatchRects()
|
|
|
| WebFloatRect TextFinder::activeFindMatchRect()
|
| {
|
| - if (!isActiveMatchFrameValid())
|
| + if (!m_currentActiveMatchFrame || !m_activeMatch)
|
| return WebFloatRect();
|
|
|
| - return WebFloatRect(findInPageRectFromRange(m_currentActiveMatchFrame->textFinder()->activeMatch()));
|
| + return WebFloatRect(findInPageRectFromRange(activeMatch()));
|
| }
|
|
|
| void TextFinder::findMatchRects(WebVector<WebFloatRect>& outputRects)
|
| {
|
| - Vector<WebFloatRect> matchRects;
|
| - for (WebLocalFrameImpl* frame = &ownerFrame(); frame; frame = toWebLocalFrameImpl(frame->traverseNextLocal(false)))
|
| - frame->ensureTextFinder().appendFindMatchRects(matchRects);
|
| -
|
| - outputRects = matchRects;
|
| -}
|
| -
|
| -void TextFinder::appendFindMatchRects(Vector<WebFloatRect>& frameRects)
|
| -{
|
| updateFindMatchRects();
|
| - frameRects.reserveCapacity(frameRects.size() + m_findMatchesCache.size());
|
| +
|
| + Vector<WebFloatRect> matchRects;
|
| + matchRects.reserveCapacity(matchRects.size() + m_findMatchesCache.size());
|
| for (const FindMatch& match : m_findMatchesCache) {
|
| DCHECK(!match.m_rect.isEmpty());
|
| - frameRects.append(match.m_rect);
|
| + matchRects.append(match.m_rect);
|
| }
|
| +
|
| + outputRects = matchRects;
|
| }
|
|
|
| int TextFinder::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect)
|
| {
|
| - TextFinder* bestFinder = nullptr;
|
| - int indexInBestFrame = -1;
|
| - float distanceInBestFrame = FLT_MAX;
|
| -
|
| - for (WebLocalFrameImpl* frame = &ownerFrame(); frame; frame = toWebLocalFrameImpl(frame->traverseNextLocal(false))) {
|
| - float distanceInFrame;
|
| - TextFinder& finder = frame->ensureTextFinder();
|
| - int indexInFrame = finder.nearestFindMatch(point, distanceInFrame);
|
| - if (distanceInFrame < distanceInBestFrame) {
|
| - bestFinder = &finder;
|
| - indexInBestFrame = indexInFrame;
|
| - distanceInBestFrame = distanceInFrame;
|
| - }
|
| - }
|
| -
|
| - if (indexInBestFrame != -1)
|
| - return bestFinder->selectFindMatch(static_cast<unsigned>(indexInBestFrame), selectionRect);
|
| + int index = nearestFindMatch(point, nullptr);
|
| + if (index != -1)
|
| + return selectFindMatch(static_cast<unsigned>(index), selectionRect);
|
|
|
| return -1;
|
| }
|
|
|
| -int TextFinder::nearestFindMatch(const FloatPoint& point, float& distanceSquared)
|
| +int TextFinder::nearestFindMatch(const FloatPoint& point, float* distanceSquared)
|
| {
|
| updateFindMatchRects();
|
|
|
| int nearest = -1;
|
| - distanceSquared = FLT_MAX;
|
| + float nearestDistanceSquared = FLT_MAX;
|
| for (size_t i = 0; i < m_findMatchesCache.size(); ++i) {
|
| DCHECK(!m_findMatchesCache[i].m_rect.isEmpty());
|
| FloatSize offset = point - m_findMatchesCache[i].m_rect.center();
|
| float width = offset.width();
|
| float height = offset.height();
|
| float currentDistanceSquared = width * width + height * height;
|
| - if (currentDistanceSquared < distanceSquared) {
|
| + if (currentDistanceSquared < nearestDistanceSquared) {
|
| nearest = i;
|
| - distanceSquared = currentDistanceSquared;
|
| + nearestDistanceSquared = currentDistanceSquared;
|
| }
|
| }
|
| +
|
| + if (distanceSquared)
|
| + *distanceSquared = nearestDistanceSquared;
|
| +
|
| return nearest;
|
| }
|
|
|
| @@ -611,18 +587,15 @@ int TextFinder::selectFindMatch(unsigned index, WebRect* selectionRect)
|
| return -1;
|
|
|
| // Check if the match is already selected.
|
| - TextFinder& mainFrameTextFinder = ownerFrame().viewImpl()->mainFrameImpl()->ensureTextFinder();
|
| - WebLocalFrameImpl* activeMatchFrame = mainFrameTextFinder.m_currentActiveMatchFrame;
|
| - if (&ownerFrame() != activeMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMatch.get(), range)) {
|
| - if (isActiveMatchFrameValid())
|
| - activeMatchFrame->ensureTextFinder().setMatchMarkerActive(false);
|
| -
|
| - m_activeMatchIndexInCurrentFrame = m_findMatchesCache[index].m_ordinal - 1;
|
| + if (!m_currentActiveMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMatch.get(), range)) {
|
| + m_activeMatchIndex = m_findMatchesCache[index].m_ordinal - 1;
|
|
|
| // Set this frame as the active frame (the one with the active highlight).
|
| - mainFrameTextFinder.m_currentActiveMatchFrame = &ownerFrame();
|
| + m_currentActiveMatchFrame = true;
|
| ownerFrame().viewImpl()->setFocusedFrame(&ownerFrame());
|
|
|
| + if (m_activeMatch)
|
| + setMarkerActive(m_activeMatch.get(), false);
|
| m_activeMatch = range;
|
| setMarkerActive(m_activeMatch.get(), true);
|
|
|
| @@ -650,7 +623,7 @@ int TextFinder::selectFindMatch(unsigned index, WebRect* selectionRect)
|
| if (selectionRect)
|
| *selectionRect = activeMatchRect;
|
|
|
| - return ordinalOfFirstMatch() + m_activeMatchIndexInCurrentFrame + 1;
|
| + return m_activeMatchIndex + 1;
|
| }
|
|
|
| TextFinder* TextFinder::create(WebLocalFrameImpl& ownerFrame)
|
| @@ -660,12 +633,12 @@ TextFinder* TextFinder::create(WebLocalFrameImpl& ownerFrame)
|
|
|
| TextFinder::TextFinder(WebLocalFrameImpl& ownerFrame)
|
| : m_ownerFrame(&ownerFrame)
|
| - , m_currentActiveMatchFrame(nullptr)
|
| - , m_activeMatchIndexInCurrentFrame(-1)
|
| + , m_currentActiveMatchFrame(false)
|
| + , m_activeMatchIndex(-1)
|
| , m_resumeScopingFromRange(nullptr)
|
| , m_lastMatchCount(-1)
|
| , m_totalMatchCount(-1)
|
| - , m_framesScopingCount(-1)
|
| + , m_frameScoping(false)
|
| , m_findRequestIdentifier(-1)
|
| , m_nextInvalidateAfter(0)
|
| , m_findMatchMarkersVersion(0)
|
| @@ -695,33 +668,14 @@ bool TextFinder::setMarkerActive(Range* range, bool active)
|
| void TextFinder::unmarkAllTextMatches()
|
| {
|
| LocalFrame* frame = ownerFrame().frame();
|
| - if (frame && frame->page() && frame->editor().markedTextMatchesAreHighlighted()) {
|
| - if (ownerFrame().client() && ownerFrame().client()->shouldSearchSingleFrame())
|
| - frame->document()->markers().removeMarkers(DocumentMarker::TextMatch);
|
| - else
|
| - frame->page()->unmarkAllTextMatches();
|
| - }
|
| -}
|
| -
|
| -int TextFinder::ordinalOfFirstMatchForFrame(WebLocalFrameImpl* frame) const
|
| -{
|
| - int ordinal = 0;
|
| - WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl();
|
| - // Iterate from the main frame up to (but not including) |frame| and
|
| - // add up the number of matches found so far.
|
| - for (WebLocalFrameImpl* it = mainFrameImpl; it != frame; it = toWebLocalFrameImpl(it->traverseNextLocal(true))) {
|
| - TextFinder& finder = it->ensureTextFinder();
|
| - if (finder.m_lastMatchCount > 0)
|
| - ordinal += finder.m_lastMatchCount;
|
| - }
|
| - return ordinal;
|
| + if (frame && frame->page() && frame->editor().markedTextMatchesAreHighlighted())
|
| + frame->document()->markers().removeMarkers(DocumentMarker::TextMatch);
|
| }
|
|
|
| bool TextFinder::shouldScopeMatches(const String& searchText)
|
| {
|
| // Don't scope if we can't find a frame or a view.
|
| // The user may have closed the tab/application, so abort.
|
| - // Also ignore detached frames, as many find operations report to the main frame.
|
| LocalFrame* frame = ownerFrame().frame();
|
| if (!frame || !frame->view() || !frame->page() || !ownerFrame().hasVisibleContent())
|
| return false;
|
| @@ -782,32 +736,9 @@ void TextFinder::flushCurrentScoping()
|
| flushCurrentScopingEffort(m_findRequestIdentifier);
|
| }
|
|
|
| -void TextFinder::setMatchMarkerActive(bool active)
|
| -{
|
| - setMarkerActive(m_activeMatch.get(), active);
|
| -}
|
| -
|
| -void TextFinder::decrementFramesScopingCount(int identifier)
|
| -{
|
| - // This frame has no further scoping left, so it is done. Other frames might,
|
| - // of course, continue to scope matches.
|
| - --m_framesScopingCount;
|
| -
|
| - // If this is the last frame to finish scoping we need to trigger the final
|
| - // update to be sent.
|
| - if (!m_framesScopingCount)
|
| - ownerFrame().increaseMatchCount(0, identifier);
|
| -}
|
| -
|
| -int TextFinder::ordinalOfFirstMatch() const
|
| -{
|
| - return ordinalOfFirstMatchForFrame(m_ownerFrame.get());
|
| -}
|
| -
|
| DEFINE_TRACE(TextFinder)
|
| {
|
| visitor->trace(m_ownerFrame);
|
| - visitor->trace(m_currentActiveMatchFrame);
|
| visitor->trace(m_activeMatch);
|
| visitor->trace(m_resumeScopingFromRange);
|
| visitor->trace(m_deferredScopingWork);
|
|
|