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); |