1d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)/*
2d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * Copyright (C) 2009 Google Inc. All rights reserved.
3d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *
4d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * modification, are permitted provided that the following conditions are
6d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * met:
7d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *
8d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
9d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
10d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
11d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
12d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * in the documentation and/or other materials provided with the
13d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * distribution.
14d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
15d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
16d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * this software without specific prior written permission.
17d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *
18d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) */
30d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
31d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
32d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "config.h"
33f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "web/TextFinder.h"
34f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
35d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/dom/DocumentMarker.h"
36d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/dom/DocumentMarkerController.h"
3707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "core/dom/Range.h"
38d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/dom/shadow/ShadowRoot.h"
39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/editing/Editor.h"
40d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/editing/TextIterator.h"
4107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "core/editing/VisibleSelection.h"
42d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/FrameView.h"
4307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "platform/Timer.h"
44d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "public/platform/WebVector.h"
45f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "public/web/WebFindOptions.h"
46f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "public/web/WebFrameClient.h"
47f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "public/web/WebViewClient.h"
48f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "web/FindInPageCoordinates.h"
49f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "web/WebLocalFrameImpl.h"
50f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "web/WebViewImpl.h"
51d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "wtf/CurrentTime.h"
52d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
53d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)using namespace WebCore;
54d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
55d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)namespace blink {
56d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
57a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochTextFinder::FindMatch::FindMatch(PassRefPtrWillBeRawPtr<Range> range, int ordinal)
5807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    : m_range(range)
5907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_ordinal(ordinal)
60d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
61d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
62d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
63a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid TextFinder::FindMatch::trace(WebCore::Visitor* visitor)
64a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
65a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    visitor->trace(m_range);
66a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
67a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
6807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochclass TextFinder::DeferredScopeStringMatches {
6907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochpublic:
7007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    DeferredScopeStringMatches(TextFinder* textFinder, int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
7107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        : m_timer(this, &DeferredScopeStringMatches::doTimeout)
7207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        , m_textFinder(textFinder)
7307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        , m_identifier(identifier)
7407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        , m_searchText(searchText)
7507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        , m_options(options)
7607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        , m_reset(reset)
7707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
7807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_timer.startOneShot(0.0, FROM_HERE);
79d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
80d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
8107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochprivate:
8207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    void doTimeout(Timer<DeferredScopeStringMatches>*)
8307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    {
8407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_textFinder->callScopeStringMatches(this, m_identifier, m_searchText, m_options, m_reset);
8507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
86d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
8707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    Timer<DeferredScopeStringMatches> m_timer;
8807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    TextFinder* m_textFinder;
8907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    const int m_identifier;
9007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    const WebString m_searchText;
9107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    const WebFindOptions m_options;
9207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    const bool m_reset;
9307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch};
94d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
9507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochbool TextFinder::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect)
96d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
9707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!m_ownerFrame.frame() || !m_ownerFrame.frame()->page())
98d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
99d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
10010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* mainFrameImpl = m_ownerFrame.viewImpl()->mainFrameImpl();
101d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
102d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!options.findNext)
10307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.frame()->page()->unmarkAllTextMatches();
104d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    else
105d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        setMarkerActive(m_activeMatch.get(), false);
106d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
10707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (m_activeMatch && &m_activeMatch->ownerDocument() != m_ownerFrame.frame()->document())
108d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_activeMatch = nullptr;
109d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
110d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // If the user has selected something since the last Find operation we want
111d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // to start from there. Otherwise, we start searching from where the last Find
112d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // operation left off (either a Find or a FindNext operation).
11307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    VisibleSelection selection(m_ownerFrame.frame()->selection().selection());
114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool activeSelection = !selection.isNone();
115d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (activeSelection) {
116d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_activeMatch = selection.firstRange().get();
11707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.frame()->selection().clear();
118d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
119d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
12007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    ASSERT(m_ownerFrame.frame() && m_ownerFrame.frame()->view());
121d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const FindOptions findOptions = (options.forward ? 0 : Backwards)
122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        | (options.matchCase ? 0 : CaseInsensitive)
123d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        | (wrapWithinFrame ? WrapAround : 0)
124d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        | (options.wordStart ? AtWordStarts : 0)
125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        | (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0)
126d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        | (options.findNext ? 0 : StartInSelection);
12707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_activeMatch = m_ownerFrame.frame()->editor().findStringAndScrollToVisible(searchText, m_activeMatch.get(), findOptions);
128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
129d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!m_activeMatch) {
130d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // If we're finding next the next active match might not be in the current frame.
131d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // In this case we don't want to clear the matches cache.
132d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (!options.findNext)
133d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            clearFindMatchesCache();
13407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
13507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.invalidateAll();
136d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
137d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
138d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
139d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#if OS(ANDROID)
14007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.viewImpl()->zoomToFindInPageRect(m_ownerFrame.frameView()->contentsToWindow(enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()))));
141d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif
142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    setMarkerActive(m_activeMatch.get(), true);
14410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* oldActiveFrame = mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame;
14507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame = &m_ownerFrame;
146d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
147d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Make sure no node is focused. See http://crbug.com/38700.
14807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.frame()->document()->setFocusedElement(nullptr);
149d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
150d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!options.findNext || activeSelection) {
151d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // This is either a Find operation or a Find-next from a new start point
152d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // due to a selection, so we set the flag to ask the scoping effort
153d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // to find the active rect for us and report it back to the UI.
154d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_locatingActiveRect = true;
155d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    } else {
15607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (oldActiveFrame != &m_ownerFrame) {
157d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (options.forward)
158d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                m_activeMatchIndexInCurrentFrame = 0;
159d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            else
160d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
161d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        } else {
162d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (options.forward)
163d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                ++m_activeMatchIndexInCurrentFrame;
164d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            else
165d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                --m_activeMatchIndexInCurrentFrame;
166d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount)
168d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                m_activeMatchIndexInCurrentFrame = 0;
169d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (m_activeMatchIndexInCurrentFrame == -1)
170d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
171d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
172d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (selectionRect) {
17307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            *selectionRect = m_ownerFrame.frameView()->contentsToWindow(m_activeMatch->boundingBox());
174d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurrentFrame + 1, identifier);
175d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
176d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
177d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
178d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return true;
179d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
180d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
18107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::stopFindingAndClearSelection()
182d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
183d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    cancelPendingScopingEffort();
184d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
185d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Remove all markers for matches found and turn off the highlighting.
18607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.frame()->document()->markers().removeMarkers(DocumentMarker::TextMatch);
18707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.frame()->editor().setMarkedTextMatchesAreHighlighted(false);
188d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    clearFindMatchesCache();
189d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
190d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Let the frame know that we don't want tickmarks or highlighting anymore.
19107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.invalidateAll();
192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
193d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
19407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
195d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
196d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (reset) {
197d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // This is a brand new search, so we need to reset everything.
198d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Scoping is just about to begin.
199d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_scopingInProgress = true;
200d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
201d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Need to keep the current identifier locally in order to finish the
202d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // request in case the frame is detached during the process.
203d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_findRequestIdentifier = identifier;
204d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
205d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Clear highlighting for this frame.
20607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        LocalFrame* frame = m_ownerFrame.frame();
20707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (frame && frame->page() && frame->editor().markedTextMatchesAreHighlighted())
20807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            frame->page()->unmarkAllTextMatches();
209d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
210d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Clear the tickmarks and results cache.
211d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        clearFindMatchesCache();
212d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
213d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Clear the counters from last operation.
214d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_lastMatchCount = 0;
215d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_nextInvalidateAfter = 0;
216d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_resumeScopingFromRange = nullptr;
217d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
218d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // The view might be null on detached frames.
21907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (frame && frame->page())
22007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            m_ownerFrame.viewImpl()->mainFrameImpl()->ensureTextFinder().m_framesScopingCount++;
221d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
222d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Now, defer scoping until later to allow find operation to finish quickly.
223d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        scopeStringMatchesSoon(identifier, searchText, options, false); // false means just reset, so don't do it again.
224d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
225d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
226d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
227d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!shouldScopeMatches(searchText)) {
228d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Note that we want to defer the final update when resetting even if shouldScopeMatches returns false.
229d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // This is done in order to prevent sending a final message based only on the results of the first frame
230d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // since m_framesScopingCount would be 0 as other frames have yet to reset.
231d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        finishCurrentScopingEffort(identifier);
232d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
233d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
234d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
23510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* mainFrameImpl = m_ownerFrame.viewImpl()->mainFrameImpl();
236f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    Position searchStart = firstPositionInNode(m_ownerFrame.frame()->document());
237f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    Position searchEnd = lastPositionInNode(m_ownerFrame.frame()->document());
238f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ASSERT(searchStart.document() == searchEnd.document());
239d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
240d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (m_resumeScopingFromRange) {
241d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // This is a continuation of a scoping operation that timed out and didn't
242d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // complete last time around, so we should start from where we left off.
243f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        ASSERT(m_resumeScopingFromRange->collapsed());
244f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        searchStart = m_resumeScopingFromRange->startPosition().next();
245f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (searchStart.document() != searchEnd.document())
246d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return;
247d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
248d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
24907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // This timeout controls how long we scope before releasing control. This
250d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // value does not prevent us from running for longer than this, but it is
251d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // periodically checked to see if we have exceeded our allocated time.
252d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const double maxScopingDuration = 0.1; // seconds
253d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
254d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    int matchCount = 0;
255d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool timedOut = false;
256d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    double startTime = currentTime();
257d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    do {
258d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Find next occurrence of the search string.
259f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        // FIXME: (http://crbug.com/6818) This WebKit operation may run for longer
260d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // than the timeout value, and is not interruptible as it is currently
261d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // written. We may need to rewrite it with interruptibility in mind, or
262d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // find an alternative.
263f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        Position resultStart;
264f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        Position resultEnd;
265f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        findPlainText(searchStart, searchEnd, searchText, options.matchCase ? 0 : CaseInsensitive, resultStart, resultEnd);
266f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (resultStart == resultEnd) {
267f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            // Not found.
268f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            break;
269f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        }
270f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
271f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        RefPtrWillBeRawPtr<Range> resultRange = Range::create(*resultStart.document(), resultStart, resultEnd);
272f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (resultRange->collapsed()) {
273f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            // resultRange will be collapsed if the matched text spans over multiple TreeScopes.
274f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            // FIXME: Show such matches to users.
275f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            searchStart = resultStart.next();
276d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            continue;
277d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
278d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
279d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ++matchCount;
280d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
281d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Catch a special case where Find found something but doesn't know what
282d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // the bounding box for it is. In this case we set the first match we find
283d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // as the active rect.
284d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        IntRect resultBounds = resultRange->boundingBox();
285d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        IntRect activeSelectionRect;
286d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (m_locatingActiveRect) {
287d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            activeSelectionRect = m_activeMatch.get() ?
288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                m_activeMatch->boundingBox() : resultBounds;
289d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
290d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
291d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // If the Find function found a match it will have stored where the
292d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // match was found in m_activeSelectionRect on the current frame. If we
293d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // find this rect during scoping it means we have found the active
294d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // tickmark.
295d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        bool foundActiveMatch = false;
296d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) {
297d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // We have found the active tickmark frame.
29807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame = &m_ownerFrame;
299d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            foundActiveMatch = true;
300d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // We also know which tickmark is active now.
301d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            m_activeMatchIndexInCurrentFrame = matchCount - 1;
302d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // To stop looking for the active tickmark, we set this flag.
303d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            m_locatingActiveRect = false;
304d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
305d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // Notify browser of new location for the selected rectangle.
306d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            reportFindInPageSelection(
30707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                m_ownerFrame.frameView()->contentsToWindow(resultBounds),
308d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                m_activeMatchIndexInCurrentFrame + 1,
309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                identifier);
310d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
311d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
312d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        addMarker(resultRange.get(), foundActiveMatch);
313d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
314d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_findMatchesCache.append(FindMatch(resultRange.get(), m_lastMatchCount + matchCount));
315d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
316d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Set the new start for the search range to be the end of the previous
317d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // result range. There is no need to use a VisiblePosition here,
318d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // since findPlainText will use a TextIterator to go over the visible
319d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // text nodes.
320f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        searchStart = resultStart.next();
321d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
322f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        m_resumeScopingFromRange = Range::create(*resultStart.document(), resultStart, resultStart);
323d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        timedOut = (currentTime() - startTime) >= maxScopingDuration;
324d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    } while (!timedOut);
325d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
326d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Remember what we search for last time, so we can skip searching if more
327d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // letters are added to the search string (and last outcome was 0).
328d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_lastSearchString = searchText;
329d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
330d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (matchCount > 0) {
33107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.frame()->editor().setMarkedTextMatchesAreHighlighted(true);
332d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
333d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_lastMatchCount += matchCount;
334d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
335d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Let the mainframe know how much we found during this pass.
336d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        mainFrameImpl->increaseMatchCount(matchCount, identifier);
337d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
338d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
339d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (timedOut) {
340d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // If we found anything during this pass, we should redraw. However, we
341d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // don't want to spam too much if the page is extremely long, so if we
342d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // reach a certain point we start throttling the redraw requests.
343d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (matchCount > 0)
344d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            invalidateIfNecessary();
345d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
346d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Scoping effort ran out of time, lets ask for another time-slice.
347d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        scopeStringMatchesSoon(
348d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            identifier,
349d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            searchText,
350d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            options,
351d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            false); // don't reset.
352d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return; // Done for now, resume work later.
353d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
354d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
355d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    finishCurrentScopingEffort(identifier);
356d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
357d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
35807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::flushCurrentScopingEffort(int identifier)
359d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
36007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!m_ownerFrame.frame() || !m_ownerFrame.frame()->page())
361d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
362d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
36310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* mainFrameImpl = m_ownerFrame.viewImpl()->mainFrameImpl();
36407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    mainFrameImpl->ensureTextFinder().decrementFramesScopingCount(identifier);
365d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
366d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
36707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::finishCurrentScopingEffort(int identifier)
368d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
369d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    flushCurrentScopingEffort(identifier);
370d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
371d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_scopingInProgress = false;
372d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_lastFindRequestCompletedWithNoMatches = !m_lastMatchCount;
373d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
374d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
37507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.invalidateScrollbar();
376d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
377d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
37807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::cancelPendingScopingEffort()
379d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
380d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    deleteAllValues(m_deferredScopingWork);
381d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_deferredScopingWork.clear();
382d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
383d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_activeMatchIndexInCurrentFrame = -1;
384d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
385d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Last request didn't complete.
386d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (m_scopingInProgress)
387d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_lastFindRequestCompletedWithNoMatches = false;
388d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
389d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_scopingInProgress = false;
390d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
391d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
39207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::increaseMatchCount(int identifier, int count)
393d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
394d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (count)
395d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ++m_findMatchMarkersVersion;
396d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
397d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_totalMatchCount += count;
398d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
399d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Update the UI with the latest findings.
40007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (m_ownerFrame.client())
40107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_framesScopingCount);
402d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
403d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
40407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::reportFindInPageSelection(const WebRect& selectionRect, int activeMatchOrdinal, int identifier)
405d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
406d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Update the UI with the latest selection rect.
40707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (m_ownerFrame.client())
40807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.client()->reportFindInPageSelection(identifier, ordinalOfFirstMatch() + activeMatchOrdinal, selectionRect);
409d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
410d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
41107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::resetMatchCount()
412d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
413d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (m_totalMatchCount > 0)
414d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ++m_findMatchMarkersVersion;
415d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
416d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_totalMatchCount = 0;
417d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_framesScopingCount = 0;
418d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
419d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
42007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::clearFindMatchesCache()
421d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
422d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!m_findMatchesCache.isEmpty())
42307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.viewImpl()->mainFrameImpl()->ensureTextFinder().m_findMatchMarkersVersion++;
424d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
425d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_findMatchesCache.clear();
426d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_findMatchRectsAreValid = false;
427d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
428d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
42907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochbool TextFinder::isActiveMatchFrameValid() const
430d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
43110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* mainFrameImpl = m_ownerFrame.viewImpl()->mainFrameImpl();
43210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* activeMatchFrame = mainFrameImpl->activeMatchFrame();
43307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    return activeMatchFrame && activeMatchFrame->activeMatch() && activeMatchFrame->frame()->tree().isDescendantOf(mainFrameImpl->frame());
434d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
435d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
43607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::updateFindMatchRects()
437d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
43807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    IntSize currentContentsSize = m_ownerFrame.contentsSize();
439d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (m_contentsSizeForCurrentFindMatchRects != currentContentsSize) {
440d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_contentsSizeForCurrentFindMatchRects = currentContentsSize;
441d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_findMatchRectsAreValid = false;
442d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
443d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
444d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    size_t deadMatches = 0;
445d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (Vector<FindMatch>::iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it) {
446d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (!it->m_range->boundaryPointsValid() || !it->m_range->startContainer()->inDocument())
447d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            it->m_rect = FloatRect();
448d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        else if (!m_findMatchRectsAreValid)
449d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            it->m_rect = findInPageRectFromRange(it->m_range.get());
450d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
451d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (it->m_rect.isEmpty())
452d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            ++deadMatches;
453d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
454d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
455d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Remove any invalid matches from the cache.
456d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (deadMatches) {
457a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        WillBeHeapVector<FindMatch> filteredMatches;
458d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        filteredMatches.reserveCapacity(m_findMatchesCache.size() - deadMatches);
459d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
46007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it) {
461d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (!it->m_rect.isEmpty())
462d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                filteredMatches.append(*it);
46307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
464d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
465d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_findMatchesCache.swap(filteredMatches);
466d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
467d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
468d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Invalidate the rects in child frames. Will be updated later during traversal.
469d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!m_findMatchRectsAreValid)
47007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        for (WebFrame* child = m_ownerFrame.firstChild(); child; child = child->nextSibling())
47110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch            toWebLocalFrameImpl(child)->ensureTextFinder().m_findMatchRectsAreValid = false;
472d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
473d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_findMatchRectsAreValid = true;
474d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
475d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
47607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben MurdochWebFloatRect TextFinder::activeFindMatchRect()
477d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
478d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!isActiveMatchFrameValid())
479d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return WebFloatRect();
480d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
48107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    return WebFloatRect(findInPageRectFromRange(m_currentActiveMatchFrame->activeMatch()));
482d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
483d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
48407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::findMatchRects(WebVector<WebFloatRect>& outputRects)
485d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
486d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Vector<WebFloatRect> matchRects;
48710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    for (WebLocalFrameImpl* frame = &m_ownerFrame; frame; frame = toWebLocalFrameImpl(frame->traverseNext(false)))
48807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        frame->ensureTextFinder().appendFindMatchRects(matchRects);
489d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
490d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    outputRects = matchRects;
491d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
492d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
49307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::appendFindMatchRects(Vector<WebFloatRect>& frameRects)
494d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
495d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    updateFindMatchRects();
496d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    frameRects.reserveCapacity(frameRects.size() + m_findMatchesCache.size());
497d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it) {
498d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ASSERT(!it->m_rect.isEmpty());
499d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        frameRects.append(it->m_rect);
500d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
501d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
502d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
50307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochint TextFinder::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect)
504d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
50507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    TextFinder* bestFinder = 0;
506d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    int indexInBestFrame = -1;
507d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float distanceInBestFrame = FLT_MAX;
508d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
50910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    for (WebLocalFrameImpl* frame = &m_ownerFrame; frame; frame = toWebLocalFrameImpl(frame->traverseNext(false))) {
510d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        float distanceInFrame;
51107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        TextFinder& finder = frame->ensureTextFinder();
51207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        int indexInFrame = finder.nearestFindMatch(point, distanceInFrame);
513d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (distanceInFrame < distanceInBestFrame) {
51407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            bestFinder = &finder;
515d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            indexInBestFrame = indexInFrame;
516d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            distanceInBestFrame = distanceInFrame;
517d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
518d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
519d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
520d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (indexInBestFrame != -1)
52107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        return bestFinder->selectFindMatch(static_cast<unsigned>(indexInBestFrame), selectionRect);
522d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
523d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return -1;
524d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
525d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
52607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochint TextFinder::nearestFindMatch(const FloatPoint& point, float& distanceSquared)
527d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
528d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    updateFindMatchRects();
529d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
530d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    int nearest = -1;
531d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    distanceSquared = FLT_MAX;
532d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (size_t i = 0; i < m_findMatchesCache.size(); ++i) {
533d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ASSERT(!m_findMatchesCache[i].m_rect.isEmpty());
534d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        FloatSize offset = point - m_findMatchesCache[i].m_rect.center();
535d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        float width = offset.width();
536d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        float height = offset.height();
537d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        float currentDistanceSquared = width * width + height * height;
538d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (currentDistanceSquared < distanceSquared) {
539d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            nearest = i;
540d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            distanceSquared = currentDistanceSquared;
541d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
542d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
543d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return nearest;
544d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
545d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
54607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochint TextFinder::selectFindMatch(unsigned index, WebRect* selectionRect)
547d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
548d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT_WITH_SECURITY_IMPLICATION(index < m_findMatchesCache.size());
549d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
550a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Range> range = m_findMatchesCache[index].m_range;
551d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!range->boundaryPointsValid() || !range->startContainer()->inDocument())
552d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return -1;
553d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
554d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Check if the match is already selected.
55507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    TextFinder& mainFrameTextFinder = m_ownerFrame.viewImpl()->mainFrameImpl()->ensureTextFinder();
55610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* activeMatchFrame = mainFrameTextFinder.m_currentActiveMatchFrame;
55707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (&m_ownerFrame != activeMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMatch.get(), range.get())) {
558d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isActiveMatchFrameValid())
55907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            activeMatchFrame->ensureTextFinder().setMatchMarkerActive(false);
560d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
561d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_activeMatchIndexInCurrentFrame = m_findMatchesCache[index].m_ordinal - 1;
562d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
563d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Set this frame as the active frame (the one with the active highlight).
56407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        mainFrameTextFinder.m_currentActiveMatchFrame = &m_ownerFrame;
56507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.viewImpl()->setFocusedFrame(&m_ownerFrame);
566d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
567d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_activeMatch = range.release();
568d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        setMarkerActive(m_activeMatch.get(), true);
569d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
570d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Clear any user selection, to make sure Find Next continues on from the match we just activated.
57107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.frame()->selection().clear();
572d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
573d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Make sure no node is focused. See http://crbug.com/38700.
57407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.frame()->document()->setFocusedElement(nullptr);
575d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
576d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
577d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    IntRect activeMatchRect;
578d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    IntRect activeMatchBoundingBox = enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()));
579d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
580d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!activeMatchBoundingBox.isEmpty()) {
58107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (m_activeMatch->firstNode() && m_activeMatch->firstNode()->renderer()) {
58207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            m_activeMatch->firstNode()->renderer()->scrollRectToVisible(
58307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                activeMatchBoundingBox, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
58407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
585d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
586d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Zoom to the active match.
58707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        activeMatchRect = m_ownerFrame.frameView()->contentsToWindow(activeMatchBoundingBox);
58807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.viewImpl()->zoomToFindInPageRect(activeMatchRect);
589d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
590d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
591d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (selectionRect)
592d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        *selectionRect = activeMatchRect;
593d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
59407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    return ordinalOfFirstMatch() + m_activeMatchIndexInCurrentFrame + 1;
595d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
596d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
59710f88d5669dbd969c059d61ba09fa37dd72ac559Ben MurdochPassOwnPtr<TextFinder> TextFinder::create(WebLocalFrameImpl& ownerFrame)
598d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
59907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    return adoptPtr(new TextFinder(ownerFrame));
600d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
601d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
60210f88d5669dbd969c059d61ba09fa37dd72ac559Ben MurdochTextFinder::TextFinder(WebLocalFrameImpl& ownerFrame)
60307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    : m_ownerFrame(ownerFrame)
604d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_currentActiveMatchFrame(0)
605d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_activeMatchIndexInCurrentFrame(-1)
606d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_resumeScopingFromRange(nullptr)
607d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_lastMatchCount(-1)
608d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_totalMatchCount(-1)
609d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_framesScopingCount(-1)
610d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_findRequestIdentifier(-1)
611d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_nextInvalidateAfter(0)
612d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_findMatchMarkersVersion(0)
61307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_locatingActiveRect(false)
61407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_scopingInProgress(false)
61507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_lastFindRequestCompletedWithNoMatches(false)
616d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    , m_findMatchRectsAreValid(false)
617d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
618d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
619d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
62007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben MurdochTextFinder::~TextFinder()
621d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
622d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    cancelPendingScopingEffort();
623d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
624d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
62507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::addMarker(Range* range, bool activeMatch)
626d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
62707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.frame()->document()->markers().addTextMatchMarker(range, activeMatch);
628d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
629d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
63007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::setMarkerActive(Range* range, bool active)
631d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
632f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (!range || range->collapsed())
633d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
63407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.frame()->document()->markers().setMarkersActive(range, active);
635d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
636d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
63710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochint TextFinder::ordinalOfFirstMatchForFrame(WebLocalFrameImpl* frame) const
638d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
639d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    int ordinal = 0;
64010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    WebLocalFrameImpl* mainFrameImpl = m_ownerFrame.viewImpl()->mainFrameImpl();
641d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Iterate from the main frame up to (but not including) |frame| and
642d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // add up the number of matches found so far.
64310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    for (WebLocalFrameImpl* it = mainFrameImpl; it != frame; it = toWebLocalFrameImpl(it->traverseNext(true))) {
64407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        TextFinder& finder = it->ensureTextFinder();
64507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (finder.m_lastMatchCount > 0)
64607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            ordinal += finder.m_lastMatchCount;
647d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
648d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return ordinal;
649d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
650d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
65107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochbool TextFinder::shouldScopeMatches(const String& searchText)
652d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
653d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Don't scope if we can't find a frame or a view.
654d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // The user may have closed the tab/application, so abort.
655d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Also ignore detached frames, as many find operations report to the main frame.
65607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    LocalFrame* frame = m_ownerFrame.frame();
65707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!frame || !frame->view() || !frame->page() || !m_ownerFrame.hasVisibleContent())
658d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return false;
659d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
66007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    ASSERT(frame->document() && frame->view());
661d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
662d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // If the frame completed the scoping operation and found 0 matches the last
663d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // time it was searched, then we don't have to search it again if the user is
664d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // just adding to the search string or sending the same search string again.
665d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (m_lastFindRequestCompletedWithNoMatches && !m_lastSearchString.isEmpty()) {
666d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Check to see if the search string prefixes match.
667d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        String previousSearchPrefix =
668d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            searchText.substring(0, m_lastSearchString.length());
669d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
670d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (previousSearchPrefix == m_lastSearchString)
671d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return false; // Don't search this frame, it will be fruitless.
672d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
673d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
674d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return true;
675d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
676d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
67707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::scopeStringMatchesSoon(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
678d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
679d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_deferredScopingWork.append(new DeferredScopeStringMatches(this, identifier, searchText, options, reset));
680d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
681d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
68207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::callScopeStringMatches(DeferredScopeStringMatches* caller, int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
683d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
684d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_deferredScopingWork.remove(m_deferredScopingWork.find(caller));
685d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    scopeStringMatches(identifier, searchText, options, reset);
686d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
687d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // This needs to happen last since searchText is passed by reference.
688d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    delete caller;
689d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
690d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
69107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::invalidateIfNecessary()
692d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
693d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (m_lastMatchCount <= m_nextInvalidateAfter)
694d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
695d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
696d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // FIXME: (http://b/1088165) Optimize the drawing of the tickmarks and
697d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // remove this. This calculation sets a milestone for when next to
698d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // invalidate the scrollbar and the content area. We do this so that we
699d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // don't spend too much time drawing the scrollbar over and over again.
700d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // Basically, up until the first 500 matches there is no throttle.
701d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // After the first 500 matches, we set set the milestone further and
702d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // further out (750, 1125, 1688, 2K, 3K).
703d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static const int startSlowingDownAfter = 500;
704d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    static const int slowdown = 750;
705d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
706d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    int i = m_lastMatchCount / startSlowingDownAfter;
707d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_nextInvalidateAfter += i * slowdown;
70807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_ownerFrame.invalidateScrollbar();
709d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
710d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
71107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::flushCurrentScoping()
712d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
71307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    flushCurrentScopingEffort(m_findRequestIdentifier);
71407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
715d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
71607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::setMatchMarkerActive(bool active)
71707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch{
71807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    setMarkerActive(m_activeMatch.get(), active);
719d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
720d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
72107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid TextFinder::decrementFramesScopingCount(int identifier)
722d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
72307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // This frame has no further scoping left, so it is done. Other frames might,
72407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // of course, continue to scope matches.
72507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    --m_framesScopingCount;
726d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
72707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // If this is the last frame to finish scoping we need to trigger the final
72807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    // update to be sent.
72907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!m_framesScopingCount)
73007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        m_ownerFrame.increaseMatchCount(0, identifier);
73107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}
732d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
73307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochint TextFinder::ordinalOfFirstMatch() const
73407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch{
73507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    return ordinalOfFirstMatchForFrame(&m_ownerFrame);
736d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
737d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
738d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} // namespace blink
739