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