Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: Source/web/WebFrameImpl.cpp

Issue 69923006: Introduce TextFinder class. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@upload-review-4
Patch Set: Rebase Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/web/WebFrameImpl.h ('k') | Source/web/web.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 #include "WebFrameImpl.h" 73 #include "WebFrameImpl.h"
74 74
75 #include <algorithm> 75 #include <algorithm>
76 #include "AssociatedURLLoader.h" 76 #include "AssociatedURLLoader.h"
77 #include "DOMUtilitiesPrivate.h" 77 #include "DOMUtilitiesPrivate.h"
78 #include "EventListenerWrapper.h" 78 #include "EventListenerWrapper.h"
79 #include "FindInPageCoordinates.h" 79 #include "FindInPageCoordinates.h"
80 #include "HTMLNames.h" 80 #include "HTMLNames.h"
81 #include "PageOverlay.h" 81 #include "PageOverlay.h"
82 #include "SharedWorkerRepositoryClientImpl.h" 82 #include "SharedWorkerRepositoryClientImpl.h"
83 #include "TextFinder.h"
83 #include "V8DOMFileSystem.h" 84 #include "V8DOMFileSystem.h"
84 #include "V8DirectoryEntry.h" 85 #include "V8DirectoryEntry.h"
85 #include "V8FileEntry.h" 86 #include "V8FileEntry.h"
86 #include "WebConsoleMessage.h" 87 #include "WebConsoleMessage.h"
87 #include "WebDOMEvent.h" 88 #include "WebDOMEvent.h"
88 #include "WebDOMEventListener.h" 89 #include "WebDOMEventListener.h"
89 #include "WebDataSourceImpl.h" 90 #include "WebDataSourceImpl.h"
90 #include "WebDevToolsAgentPrivate.h" 91 #include "WebDevToolsAgentPrivate.h"
91 #include "WebDocument.h" 92 #include "WebDocument.h"
92 #include "WebFindOptions.h" 93 #include "WebFindOptions.h"
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 int m_pageCount; 455 int m_pageCount;
455 WebPrintParams m_printParams; 456 WebPrintParams m_printParams;
456 457
457 }; 458 };
458 459
459 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) 460 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader)
460 { 461 {
461 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0; 462 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
462 } 463 }
463 464
464 WebFrameImpl::FindMatch::FindMatch(PassRefPtr<Range> range, int ordinal)
465 : m_range(range)
466 , m_ordinal(ordinal)
467 {
468 }
469
470 class WebFrameImpl::DeferredScopeStringMatches {
471 public:
472 DeferredScopeStringMatches(WebFrameImpl* webFrame, int identifier, const Web String& searchText, const WebFindOptions& options, bool reset)
473 : m_timer(this, &DeferredScopeStringMatches::doTimeout)
474 , m_webFrame(webFrame)
475 , m_identifier(identifier)
476 , m_searchText(searchText)
477 , m_options(options)
478 , m_reset(reset)
479 {
480 m_timer.startOneShot(0.0);
481 }
482
483 private:
484 void doTimeout(Timer<DeferredScopeStringMatches>*)
485 {
486 m_webFrame->callScopeStringMatches(this, m_identifier, m_searchText, m_o ptions, m_reset);
487 }
488
489 Timer<DeferredScopeStringMatches> m_timer;
490 RefPtr<WebFrameImpl> m_webFrame;
491 int m_identifier;
492 WebString m_searchText;
493 WebFindOptions m_options;
494 bool m_reset;
495 };
496
497 // WebFrame ------------------------------------------------------------------- 465 // WebFrame -------------------------------------------------------------------
498 466
499 int WebFrame::instanceCount() 467 int WebFrame::instanceCount()
500 { 468 {
501 return frameCount; 469 return frameCount;
502 } 470 }
503 471
504 WebFrame* WebFrame::frameForCurrentContext() 472 WebFrame* WebFrame::frameForCurrentContext()
505 { 473 {
506 v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentConte xt(); 474 v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentConte xt();
(...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after
1457 } 1425 }
1458 1426
1459 WebString WebFrameImpl::pageProperty(const WebString& propertyName, int pageInde x) 1427 WebString WebFrameImpl::pageProperty(const WebString& propertyName, int pageInde x)
1460 { 1428 {
1461 ASSERT(m_printContext); 1429 ASSERT(m_printContext);
1462 return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pag eIndex); 1430 return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pag eIndex);
1463 } 1431 }
1464 1432
1465 bool WebFrameImpl::find(int identifier, const WebString& searchText, const WebFi ndOptions& options, bool wrapWithinFrame, WebRect* selectionRect) 1433 bool WebFrameImpl::find(int identifier, const WebString& searchText, const WebFi ndOptions& options, bool wrapWithinFrame, WebRect* selectionRect)
1466 { 1434 {
1467 if (!frame() || !frame()->page()) 1435 return getOrCreateTextFinder().find(identifier, searchText, options, wrapWit hinFrame, selectionRect);
1468 return false;
1469
1470 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1471
1472 if (!options.findNext)
1473 frame()->page()->unmarkAllTextMatches();
1474 else
1475 setMarkerActive(m_activeMatch.get(), false);
1476
1477 if (m_activeMatch && &m_activeMatch->ownerDocument() != frame()->document())
1478 m_activeMatch = 0;
1479
1480 // If the user has selected something since the last Find operation we want
1481 // to start from there. Otherwise, we start searching from where the last Fi nd
1482 // operation left off (either a Find or a FindNext operation).
1483 VisibleSelection selection(frame()->selection().selection());
1484 bool activeSelection = !selection.isNone();
1485 if (activeSelection) {
1486 m_activeMatch = selection.firstRange().get();
1487 frame()->selection().clear();
1488 }
1489
1490 ASSERT(frame() && frame()->view());
1491 const FindOptions findOptions = (options.forward ? 0 : Backwards)
1492 | (options.matchCase ? 0 : CaseInsensitive)
1493 | (wrapWithinFrame ? WrapAround : 0)
1494 | (options.wordStart ? AtWordStarts : 0)
1495 | (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0)
1496 | (options.findNext ? 0 : StartInSelection);
1497 m_activeMatch = frame()->editor().findStringAndScrollToVisible(searchText, m _activeMatch.get(), findOptions);
1498
1499 if (!m_activeMatch) {
1500 // If we're finding next the next active match might not be in the curre nt frame.
1501 // In this case we don't want to clear the matches cache.
1502 if (!options.findNext)
1503 clearFindMatchesCache();
1504 invalidateArea(InvalidateAll);
1505 return false;
1506 }
1507
1508 #if OS(ANDROID)
1509 viewImpl()->zoomToFindInPageRect(frameView()->contentsToWindow(enclosingIntR ect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()))));
1510 #endif
1511
1512 setMarkerActive(m_activeMatch.get(), true);
1513 WebFrameImpl* oldActiveFrame = mainFrameImpl->m_currentActiveMatchFrame;
1514 mainFrameImpl->m_currentActiveMatchFrame = this;
1515
1516 // Make sure no node is focused. See http://crbug.com/38700.
1517 frame()->document()->setFocusedElement(0);
1518
1519 if (!options.findNext || activeSelection) {
1520 // This is either a Find operation or a Find-next from a new start point
1521 // due to a selection, so we set the flag to ask the scoping effort
1522 // to find the active rect for us and report it back to the UI.
1523 m_locatingActiveRect = true;
1524 } else {
1525 if (oldActiveFrame != this) {
1526 if (options.forward)
1527 m_activeMatchIndexInCurrentFrame = 0;
1528 else
1529 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
1530 } else {
1531 if (options.forward)
1532 ++m_activeMatchIndexInCurrentFrame;
1533 else
1534 --m_activeMatchIndexInCurrentFrame;
1535
1536 if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount)
1537 m_activeMatchIndexInCurrentFrame = 0;
1538 if (m_activeMatchIndexInCurrentFrame == -1)
1539 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
1540 }
1541 if (selectionRect) {
1542 *selectionRect = frameView()->contentsToWindow(m_activeMatch->boundi ngBox());
1543 reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurren tFrame + 1, identifier);
1544 }
1545 }
1546
1547 return true;
1548 } 1436 }
1549 1437
1550 void WebFrameImpl::stopFinding(bool clearSelection) 1438 void WebFrameImpl::stopFinding(bool clearSelection)
1551 { 1439 {
1440 ASSERT(m_textFinder);
1441
1552 if (!clearSelection) 1442 if (!clearSelection)
1553 setFindEndstateFocusAndSelection(); 1443 setFindEndstateFocusAndSelection();
1554 cancelPendingScopingEffort(); 1444 m_textFinder->stopFindingAndClearSelection();
1555
1556 // Remove all markers for matches found and turn off the highlighting.
1557 frame()->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
1558 frame()->editor().setMarkedTextMatchesAreHighlighted(false);
1559 clearFindMatchesCache();
1560
1561 // Let the frame know that we don't want tickmarks or highlighting anymore.
1562 invalidateArea(InvalidateAll);
1563 } 1445 }
1564 1446
1565 void WebFrameImpl::scopeStringMatches(int identifier, const WebString& searchTex t, const WebFindOptions& options, bool reset) 1447 void WebFrameImpl::scopeStringMatches(int identifier, const WebString& searchTex t, const WebFindOptions& options, bool reset)
1566 { 1448 {
1567 if (reset) { 1449 getOrCreateTextFinder().scopeStringMatches(identifier, searchText, options, reset);
1568 // This is a brand new search, so we need to reset everything.
1569 // Scoping is just about to begin.
1570 m_scopingInProgress = true;
1571
1572 // Need to keep the current identifier locally in order to finish the
1573 // request in case the frame is detached during the process.
1574 m_findRequestIdentifier = identifier;
1575
1576 // Clear highlighting for this frame.
1577 if (frame() && frame()->page() && frame()->editor().markedTextMatchesAre Highlighted())
1578 frame()->page()->unmarkAllTextMatches();
1579
1580 // Clear the tickmarks and results cache.
1581 clearFindMatchesCache();
1582
1583 // Clear the counters from last operation.
1584 m_lastMatchCount = 0;
1585 m_nextInvalidateAfter = 0;
1586
1587 m_resumeScopingFromRange = 0;
1588
1589 // The view might be null on detached frames.
1590 if (frame() && frame()->page())
1591 viewImpl()->mainFrameImpl()->m_framesScopingCount++;
1592
1593 // Now, defer scoping until later to allow find operation to finish quic kly.
1594 scopeStringMatchesSoon(identifier, searchText, options, false); // false means just reset, so don't do it again.
1595 return;
1596 }
1597
1598 if (!shouldScopeMatches(searchText)) {
1599 // Note that we want to defer the final update when resetting even if sh ouldScopeMatches returns false.
1600 // This is done in order to prevent sending a final message based only o n the results of the first frame
1601 // since m_framesScopingCount would be 0 as other frames have yet to res et.
1602 finishCurrentScopingEffort(identifier);
1603 return;
1604 }
1605
1606 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1607 RefPtr<Range> searchRange(rangeOfContents(frame()->document()));
1608
1609 Node* originalEndContainer = searchRange->endContainer();
1610 int originalEndOffset = searchRange->endOffset();
1611
1612 TrackExceptionState exceptionState, exceptionState2;
1613 if (m_resumeScopingFromRange) {
1614 // This is a continuation of a scoping operation that timed out and didn 't
1615 // complete last time around, so we should start from where we left off.
1616 searchRange->setStart(m_resumeScopingFromRange->startContainer(), m_resu meScopingFromRange->startOffset(exceptionState2) + 1, exceptionState);
1617 if (exceptionState.hadException() || exceptionState2.hadException()) {
1618 if (exceptionState2.hadException()) // A non-zero |exceptionState| h appens when navigating during search.
1619 ASSERT_NOT_REACHED();
1620 return;
1621 }
1622 }
1623
1624 // This timeout controls how long we scope before releasing control. This
1625 // value does not prevent us from running for longer than this, but it is
1626 // periodically checked to see if we have exceeded our allocated time.
1627 const double maxScopingDuration = 0.1; // seconds
1628
1629 int matchCount = 0;
1630 bool timedOut = false;
1631 double startTime = currentTime();
1632 do {
1633 // Find next occurrence of the search string.
1634 // FIXME: (http://b/1088245) This WebKit operation may run for longer
1635 // than the timeout value, and is not interruptible as it is currently
1636 // written. We may need to rewrite it with interruptibility in mind, or
1637 // find an alternative.
1638 RefPtr<Range> resultRange(findPlainText(searchRange.get(),
1639 searchText,
1640 options.matchCase ? 0 : CaseInse nsitive));
1641 if (resultRange->collapsed(exceptionState)) {
1642 if (!resultRange->startContainer()->isInShadowTree())
1643 break;
1644
1645 searchRange->setStartAfter(
1646 resultRange->startContainer()->deprecatedShadowAncestorNode(), e xceptionState);
1647 searchRange->setEnd(originalEndContainer, originalEndOffset, excepti onState);
1648 continue;
1649 }
1650
1651 ++matchCount;
1652
1653 // Catch a special case where Find found something but doesn't know what
1654 // the bounding box for it is. In this case we set the first match we fi nd
1655 // as the active rect.
1656 IntRect resultBounds = resultRange->boundingBox();
1657 IntRect activeSelectionRect;
1658 if (m_locatingActiveRect) {
1659 activeSelectionRect = m_activeMatch.get() ?
1660 m_activeMatch->boundingBox() : resultBounds;
1661 }
1662
1663 // If the Find function found a match it will have stored where the
1664 // match was found in m_activeSelectionRect on the current frame. If we
1665 // find this rect during scoping it means we have found the active
1666 // tickmark.
1667 bool foundActiveMatch = false;
1668 if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) {
1669 // We have found the active tickmark frame.
1670 mainFrameImpl->m_currentActiveMatchFrame = this;
1671 foundActiveMatch = true;
1672 // We also know which tickmark is active now.
1673 m_activeMatchIndexInCurrentFrame = matchCount - 1;
1674 // To stop looking for the active tickmark, we set this flag.
1675 m_locatingActiveRect = false;
1676
1677 // Notify browser of new location for the selected rectangle.
1678 reportFindInPageSelection(
1679 frameView()->contentsToWindow(resultBounds),
1680 m_activeMatchIndexInCurrentFrame + 1,
1681 identifier);
1682 }
1683
1684 addMarker(resultRange.get(), foundActiveMatch);
1685
1686 m_findMatchesCache.append(FindMatch(resultRange.get(), m_lastMatchCount + matchCount));
1687
1688 // Set the new start for the search range to be the end of the previous
1689 // result range. There is no need to use a VisiblePosition here,
1690 // since findPlainText will use a TextIterator to go over the visible
1691 // text nodes.
1692 searchRange->setStart(resultRange->endContainer(exceptionState), resultR ange->endOffset(exceptionState), exceptionState);
1693
1694 Node* shadowTreeRoot = searchRange->shadowRoot();
1695 if (searchRange->collapsed(exceptionState) && shadowTreeRoot)
1696 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount() , exceptionState);
1697
1698 m_resumeScopingFromRange = resultRange;
1699 timedOut = (currentTime() - startTime) >= maxScopingDuration;
1700 } while (!timedOut);
1701
1702 // Remember what we search for last time, so we can skip searching if more
1703 // letters are added to the search string (and last outcome was 0).
1704 m_lastSearchString = searchText;
1705
1706 if (matchCount > 0) {
1707 frame()->editor().setMarkedTextMatchesAreHighlighted(true);
1708
1709 m_lastMatchCount += matchCount;
1710
1711 // Let the mainframe know how much we found during this pass.
1712 mainFrameImpl->increaseMatchCount(matchCount, identifier);
1713 }
1714
1715 if (timedOut) {
1716 // If we found anything during this pass, we should redraw. However, we
1717 // don't want to spam too much if the page is extremely long, so if we
1718 // reach a certain point we start throttling the redraw requests.
1719 if (matchCount > 0)
1720 invalidateIfNecessary();
1721
1722 // Scoping effort ran out of time, lets ask for another time-slice.
1723 scopeStringMatchesSoon(
1724 identifier,
1725 searchText,
1726 options,
1727 false); // don't reset.
1728 return; // Done for now, resume work later.
1729 }
1730
1731 finishCurrentScopingEffort(identifier);
1732 }
1733
1734 void WebFrameImpl::flushCurrentScopingEffort(int identifier)
1735 {
1736 if (!frame() || !frame()->page())
1737 return;
1738
1739 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1740
1741 // This frame has no further scoping left, so it is done. Other frames might ,
1742 // of course, continue to scope matches.
1743 mainFrameImpl->m_framesScopingCount--;
1744
1745 // If this is the last frame to finish scoping we need to trigger the final
1746 // update to be sent.
1747 if (!mainFrameImpl->m_framesScopingCount)
1748 mainFrameImpl->increaseMatchCount(0, identifier);
1749 }
1750
1751 void WebFrameImpl::finishCurrentScopingEffort(int identifier)
1752 {
1753 flushCurrentScopingEffort(identifier);
1754
1755 m_scopingInProgress = false;
1756 m_lastFindRequestCompletedWithNoMatches = !m_lastMatchCount;
1757
1758 // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
1759 invalidateArea(InvalidateScrollbar);
1760 } 1450 }
1761 1451
1762 void WebFrameImpl::cancelPendingScopingEffort() 1452 void WebFrameImpl::cancelPendingScopingEffort()
1763 { 1453 {
1764 deleteAllValues(m_deferredScopingWork); 1454 if (m_textFinder)
1765 m_deferredScopingWork.clear(); 1455 m_textFinder->cancelPendingScopingEffort();
1766
1767 m_activeMatchIndexInCurrentFrame = -1;
1768
1769 // Last request didn't complete.
1770 if (m_scopingInProgress)
1771 m_lastFindRequestCompletedWithNoMatches = false;
1772
1773 m_scopingInProgress = false;
1774 } 1456 }
1775 1457
1776 void WebFrameImpl::increaseMatchCount(int count, int identifier) 1458 void WebFrameImpl::increaseMatchCount(int count, int identifier)
1777 { 1459 {
1778 // This function should only be called on the mainframe. 1460 // This function should only be called on the mainframe.
1779 ASSERT(!parent()); 1461 ASSERT(!parent());
1780 1462 ASSERT(m_textFinder);
1781 if (count) 1463 m_textFinder->increaseMatchCount(identifier, count);
1782 ++m_findMatchMarkersVersion;
1783
1784 m_totalMatchCount += count;
1785
1786 // Update the UI with the latest findings.
1787 if (client())
1788 client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_f ramesScopingCount);
1789 }
1790
1791 void WebFrameImpl::reportFindInPageSelection(const WebRect& selectionRect, int a ctiveMatchOrdinal, int identifier)
1792 {
1793 // Update the UI with the latest selection rect.
1794 if (client())
1795 client()->reportFindInPageSelection(identifier, ordinalOfFirstMatchForFr ame(this) + activeMatchOrdinal, selectionRect);
1796 } 1464 }
1797 1465
1798 void WebFrameImpl::resetMatchCount() 1466 void WebFrameImpl::resetMatchCount()
1799 { 1467 {
1800 if (m_totalMatchCount > 0) 1468 ASSERT(m_textFinder);
1801 ++m_findMatchMarkersVersion; 1469 m_textFinder->resetMatchCount();
1802
1803 m_totalMatchCount = 0;
1804 m_framesScopingCount = 0;
1805 } 1470 }
1806 1471
1807 void WebFrameImpl::sendOrientationChangeEvent(int orientation) 1472 void WebFrameImpl::sendOrientationChangeEvent(int orientation)
1808 { 1473 {
1809 #if ENABLE(ORIENTATION_EVENTS) 1474 #if ENABLE(ORIENTATION_EVENTS)
1810 if (frame()) 1475 if (frame())
1811 frame()->sendOrientationChangeEvent(orientation); 1476 frame()->sendOrientationChangeEvent(orientation);
1812 #endif 1477 #endif
1813 } 1478 }
1814 1479
1815 void WebFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event) 1480 void WebFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event)
1816 { 1481 {
1817 ASSERT(!event.isNull()); 1482 ASSERT(!event.isNull());
1818 frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrig in.get(), event, 0); 1483 frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrig in.get(), event, 0);
1819 } 1484 }
1820 1485
1821 int WebFrameImpl::findMatchMarkersVersion() const 1486 int WebFrameImpl::findMatchMarkersVersion() const
1822 { 1487 {
1823 ASSERT(!parent()); 1488 ASSERT(!parent());
1824 return m_findMatchMarkersVersion; 1489
1490 return m_textFinder ? m_textFinder->findMatchMarkersVersion() : 0;
1825 } 1491 }
1826 1492
1827 void WebFrameImpl::clearFindMatchesCache() 1493 int WebFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* se lectionRect)
1828 { 1494 {
1829 if (!m_findMatchesCache.isEmpty()) 1495 ASSERT(!parent());
1830 viewImpl()->mainFrameImpl()->m_findMatchMarkersVersion++; 1496 ASSERT(m_textFinder);
1831 1497 return m_textFinder->selectNearestFindMatch(point, selectionRect);
1832 m_findMatchesCache.clear();
1833 m_findMatchRectsAreValid = false;
1834 }
1835
1836 bool WebFrameImpl::isActiveMatchFrameValid() const
1837 {
1838 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1839 WebFrameImpl* activeMatchFrame = mainFrameImpl->activeMatchFrame();
1840 return activeMatchFrame && activeMatchFrame->m_activeMatch && activeMatchFra me->frame()->tree().isDescendantOf(mainFrameImpl->frame());
1841 }
1842
1843 void WebFrameImpl::updateFindMatchRects()
1844 {
1845 IntSize currentContentsSize = contentsSize();
1846 if (m_contentsSizeForCurrentFindMatchRects != currentContentsSize) {
1847 m_contentsSizeForCurrentFindMatchRects = currentContentsSize;
1848 m_findMatchRectsAreValid = false;
1849 }
1850
1851 size_t deadMatches = 0;
1852 for (Vector<FindMatch>::iterator it = m_findMatchesCache.begin(); it != m_fi ndMatchesCache.end(); ++it) {
1853 if (!it->m_range->boundaryPointsValid() || !it->m_range->startContainer( )->inDocument())
1854 it->m_rect = FloatRect();
1855 else if (!m_findMatchRectsAreValid)
1856 it->m_rect = findInPageRectFromRange(it->m_range.get());
1857
1858 if (it->m_rect.isEmpty())
1859 ++deadMatches;
1860 }
1861
1862 // Remove any invalid matches from the cache.
1863 if (deadMatches) {
1864 Vector<FindMatch> filteredMatches;
1865 filteredMatches.reserveCapacity(m_findMatchesCache.size() - deadMatches) ;
1866
1867 for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it)
1868 if (!it->m_rect.isEmpty())
1869 filteredMatches.append(*it);
1870
1871 m_findMatchesCache.swap(filteredMatches);
1872 }
1873
1874 // Invalidate the rects in child frames. Will be updated later during traver sal.
1875 if (!m_findMatchRectsAreValid)
1876 for (WebFrame* child = firstChild(); child; child = child->nextSibling() )
1877 toWebFrameImpl(child)->m_findMatchRectsAreValid = false;
1878
1879 m_findMatchRectsAreValid = true;
1880 } 1498 }
1881 1499
1882 WebFloatRect WebFrameImpl::activeFindMatchRect() 1500 WebFloatRect WebFrameImpl::activeFindMatchRect()
1883 { 1501 {
1884 ASSERT(!parent()); 1502 ASSERT(!parent());
1503 ASSERT(m_textFinder);
1885 1504
1886 if (!isActiveMatchFrameValid()) 1505 return m_textFinder->activeFindMatchRect();
1887 return WebFloatRect();
1888
1889 return WebFloatRect(findInPageRectFromRange(m_currentActiveMatchFrame->m_act iveMatch.get()));
1890 } 1506 }
1891 1507
1892 void WebFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects) 1508 void WebFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects)
1893 { 1509 {
1894 ASSERT(!parent()); 1510 ASSERT(!parent());
1895 1511 ASSERT(m_textFinder);
1896 Vector<WebFloatRect> matchRects; 1512 m_textFinder->findMatchRects(outputRects);
1897 for (WebFrameImpl* frame = this; frame; frame = toWebFrameImpl(frame->traver seNext(false)))
1898 frame->appendFindMatchRects(matchRects);
1899
1900 outputRects = matchRects;
1901 }
1902
1903 void WebFrameImpl::appendFindMatchRects(Vector<WebFloatRect>& frameRects)
1904 {
1905 updateFindMatchRects();
1906 frameRects.reserveCapacity(frameRects.size() + m_findMatchesCache.size());
1907 for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it ! = m_findMatchesCache.end(); ++it) {
1908 ASSERT(!it->m_rect.isEmpty());
1909 frameRects.append(it->m_rect);
1910 }
1911 }
1912
1913 int WebFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* se lectionRect)
1914 {
1915 ASSERT(!parent());
1916
1917 WebFrameImpl* bestFrame = 0;
1918 int indexInBestFrame = -1;
1919 float distanceInBestFrame = FLT_MAX;
1920
1921 for (WebFrameImpl* frame = this; frame; frame = toWebFrameImpl(frame->traver seNext(false))) {
1922 float distanceInFrame;
1923 int indexInFrame = frame->nearestFindMatch(point, distanceInFrame);
1924 if (distanceInFrame < distanceInBestFrame) {
1925 bestFrame = frame;
1926 indexInBestFrame = indexInFrame;
1927 distanceInBestFrame = distanceInFrame;
1928 }
1929 }
1930
1931 if (indexInBestFrame != -1)
1932 return bestFrame->selectFindMatch(static_cast<unsigned>(indexInBestFrame ), selectionRect);
1933
1934 return -1;
1935 }
1936
1937 int WebFrameImpl::nearestFindMatch(const FloatPoint& point, float& distanceSquar ed)
1938 {
1939 updateFindMatchRects();
1940
1941 int nearest = -1;
1942 distanceSquared = FLT_MAX;
1943 for (size_t i = 0; i < m_findMatchesCache.size(); ++i) {
1944 ASSERT(!m_findMatchesCache[i].m_rect.isEmpty());
1945 FloatSize offset = point - m_findMatchesCache[i].m_rect.center();
1946 float width = offset.width();
1947 float height = offset.height();
1948 float currentDistanceSquared = width * width + height * height;
1949 if (currentDistanceSquared < distanceSquared) {
1950 nearest = i;
1951 distanceSquared = currentDistanceSquared;
1952 }
1953 }
1954 return nearest;
1955 }
1956
1957 int WebFrameImpl::selectFindMatch(unsigned index, WebRect* selectionRect)
1958 {
1959 ASSERT_WITH_SECURITY_IMPLICATION(index < m_findMatchesCache.size());
1960
1961 RefPtr<Range> range = m_findMatchesCache[index].m_range;
1962 if (!range->boundaryPointsValid() || !range->startContainer()->inDocument())
1963 return -1;
1964
1965 // Check if the match is already selected.
1966 WebFrameImpl* activeMatchFrame = viewImpl()->mainFrameImpl()->m_currentActiv eMatchFrame;
1967 if (this != activeMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMa tch.get(), range.get())) {
1968 if (isActiveMatchFrameValid())
1969 activeMatchFrame->setMarkerActive(activeMatchFrame->m_activeMatch.ge t(), false);
1970
1971 m_activeMatchIndexInCurrentFrame = m_findMatchesCache[index].m_ordinal - 1;
1972
1973 // Set this frame as the active frame (the one with the active highlight ).
1974 viewImpl()->mainFrameImpl()->m_currentActiveMatchFrame = this;
1975 viewImpl()->setFocusedFrame(this);
1976
1977 m_activeMatch = range.release();
1978 setMarkerActive(m_activeMatch.get(), true);
1979
1980 // Clear any user selection, to make sure Find Next continues on from th e match we just activated.
1981 frame()->selection().clear();
1982
1983 // Make sure no node is focused. See http://crbug.com/38700.
1984 frame()->document()->setFocusedElement(0);
1985 }
1986
1987 IntRect activeMatchRect;
1988 IntRect activeMatchBoundingBox = enclosingIntRect(RenderObject::absoluteBoun dingBoxRectForRange(m_activeMatch.get()));
1989
1990 if (!activeMatchBoundingBox.isEmpty()) {
1991 if (m_activeMatch->firstNode() && m_activeMatch->firstNode()->renderer() )
1992 m_activeMatch->firstNode()->renderer()->scrollRectToVisible(activeMa tchBoundingBox,
1993 ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::align CenterIfNeeded);
1994
1995 // Zoom to the active match.
1996 activeMatchRect = frameView()->contentsToWindow(activeMatchBoundingBox);
1997 viewImpl()->zoomToFindInPageRect(activeMatchRect);
1998 }
1999
2000 if (selectionRect)
2001 *selectionRect = activeMatchRect;
2002
2003 return ordinalOfFirstMatchForFrame(this) + m_activeMatchIndexInCurrentFrame + 1;
2004 } 1513 }
2005 1514
2006 WebString WebFrameImpl::contentAsText(size_t maxChars) const 1515 WebString WebFrameImpl::contentAsText(size_t maxChars) const
2007 { 1516 {
2008 if (!frame()) 1517 if (!frame())
2009 return WebString(); 1518 return WebString();
2010 StringBuilder text; 1519 StringBuilder text;
2011 frameContentAsPlainText(maxChars, frame(), text); 1520 frameContentAsPlainText(maxChars, frame(), text);
2012 return text.toString(); 1521 return text.toString();
2013 } 1522 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2093 1602
2094 WebFrameImpl* WebFrameImpl::create(WebFrameClient* client, long long embedderIde ntifier) 1603 WebFrameImpl* WebFrameImpl::create(WebFrameClient* client, long long embedderIde ntifier)
2095 { 1604 {
2096 return adoptRef(new WebFrameImpl(client, embedderIdentifier)).leakRef(); 1605 return adoptRef(new WebFrameImpl(client, embedderIdentifier)).leakRef();
2097 } 1606 }
2098 1607
2099 WebFrameImpl::WebFrameImpl(WebFrameClient* client, long long embedderIdentifier) 1608 WebFrameImpl::WebFrameImpl(WebFrameClient* client, long long embedderIdentifier)
2100 : m_frameInit(WebFrameInit::create(this, embedderIdentifier)) 1609 : m_frameInit(WebFrameInit::create(this, embedderIdentifier))
2101 , m_client(client) 1610 , m_client(client)
2102 , m_permissionClient(0) 1611 , m_permissionClient(0)
2103 , m_currentActiveMatchFrame(0)
2104 , m_activeMatchIndexInCurrentFrame(-1)
2105 , m_locatingActiveRect(false)
2106 , m_resumeScopingFromRange(0)
2107 , m_lastMatchCount(-1)
2108 , m_totalMatchCount(-1)
2109 , m_framesScopingCount(-1)
2110 , m_findRequestIdentifier(-1)
2111 , m_scopingInProgress(false)
2112 , m_lastFindRequestCompletedWithNoMatches(false)
2113 , m_nextInvalidateAfter(0)
2114 , m_findMatchMarkersVersion(0)
2115 , m_findMatchRectsAreValid(false)
2116 , m_inputEventsScaleFactorForEmulation(1) 1612 , m_inputEventsScaleFactorForEmulation(1)
2117 { 1613 {
2118 blink::Platform::current()->incrementStatsCounter(webFrameActiveCount); 1614 blink::Platform::current()->incrementStatsCounter(webFrameActiveCount);
2119 frameCount++; 1615 frameCount++;
2120 } 1616 }
2121 1617
2122 WebFrameImpl::~WebFrameImpl() 1618 WebFrameImpl::~WebFrameImpl()
2123 { 1619 {
2124 blink::Platform::current()->decrementStatsCounter(webFrameActiveCount); 1620 blink::Platform::current()->decrementStatsCounter(webFrameActiveCount);
2125 frameCount--; 1621 frameCount--;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2187 // NOTE: m_client will be null if this frame has been detached. 1683 // NOTE: m_client will be null if this frame has been detached.
2188 if (!childFrame->tree().parent()) 1684 if (!childFrame->tree().parent())
2189 return 0; 1685 return 0;
2190 1686
2191 return childFrame.release(); 1687 return childFrame.release();
2192 } 1688 }
2193 1689
2194 void WebFrameImpl::didChangeContentsSize(const IntSize& size) 1690 void WebFrameImpl::didChangeContentsSize(const IntSize& size)
2195 { 1691 {
2196 // This is only possible on the main frame. 1692 // This is only possible on the main frame.
2197 if (m_totalMatchCount > 0) { 1693 if (m_textFinder && m_textFinder->totalMatchCount() > 0) {
2198 ASSERT(!parent()); 1694 ASSERT(!parent());
2199 ++m_findMatchMarkersVersion; 1695 m_textFinder->increaseMarkerVersion();
2200 } 1696 }
2201 } 1697 }
2202 1698
2203 void WebFrameImpl::createFrameView() 1699 void WebFrameImpl::createFrameView()
2204 { 1700 {
2205 TRACE_EVENT0("webkit", "WebFrameImpl::createFrameView"); 1701 TRACE_EVENT0("webkit", "WebFrameImpl::createFrameView");
2206 1702
2207 ASSERT(frame()); // If frame() doesn't exist, we probably didn't init proper ly. 1703 ASSERT(frame()); // If frame() doesn't exist, we probably didn't init proper ly.
2208 1704
2209 WebViewImpl* webView = viewImpl(); 1705 WebViewImpl* webView = viewImpl();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 1746
2251 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const 1747 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const
2252 { 1748 {
2253 return static_cast<WebDataSourceImpl*>(provisionalDataSource()); 1749 return static_cast<WebDataSourceImpl*>(provisionalDataSource());
2254 } 1750 }
2255 1751
2256 void WebFrameImpl::setFindEndstateFocusAndSelection() 1752 void WebFrameImpl::setFindEndstateFocusAndSelection()
2257 { 1753 {
2258 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl(); 1754 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
2259 1755
2260 if (this == mainFrameImpl->activeMatchFrame() && m_activeMatch.get()) { 1756 if (this == mainFrameImpl->activeMatchFrame() && m_textFinder->activeMatch() ) {
1757 Range* activeMatch = m_textFinder->activeMatch();
2261 // If the user has set the selection since the match was found, we 1758 // If the user has set the selection since the match was found, we
2262 // don't focus anything. 1759 // don't focus anything.
2263 VisibleSelection selection(frame()->selection().selection()); 1760 VisibleSelection selection(frame()->selection().selection());
2264 if (!selection.isNone()) 1761 if (!selection.isNone())
2265 return; 1762 return;
2266 1763
2267 // Try to find the first focusable node up the chain, which will, for 1764 // Try to find the first focusable node up the chain, which will, for
2268 // example, focus links if we have found text within the link. 1765 // example, focus links if we have found text within the link.
2269 Node* node = m_activeMatch->firstNode(); 1766 Node* node = activeMatch->firstNode();
2270 if (node && node->isInShadowTree()) { 1767 if (node && node->isInShadowTree()) {
2271 Node* host = node->deprecatedShadowAncestorNode(); 1768 Node* host = node->deprecatedShadowAncestorNode();
2272 if (host->hasTagName(HTMLNames::inputTag) || host->hasTagName(HTMLNa mes::textareaTag)) 1769 if (host->hasTagName(HTMLNames::inputTag) || host->hasTagName(HTMLNa mes::textareaTag))
2273 node = host; 1770 node = host;
2274 } 1771 }
2275 for (; node; node = node->parentNode()) { 1772 for (; node; node = node->parentNode()) {
2276 if (!node->isElementNode()) 1773 if (!node->isElementNode())
2277 continue; 1774 continue;
2278 Element* element = toElement(node); 1775 Element* element = toElement(node);
2279 if (element->isFocusable()) { 1776 if (element->isFocusable()) {
2280 // Found a focusable parent node. Set the active match as the 1777 // Found a focusable parent node. Set the active match as the
2281 // selection and focus to the focusable node. 1778 // selection and focus to the focusable node.
2282 frame()->selection().setSelection(m_activeMatch.get()); 1779 frame()->selection().setSelection(activeMatch);
2283 frame()->document()->setFocusedElement(element); 1780 frame()->document()->setFocusedElement(element);
2284 return; 1781 return;
2285 } 1782 }
2286 } 1783 }
2287 1784
2288 // Iterate over all the nodes in the range until we find a focusable nod e. 1785 // Iterate over all the nodes in the range until we find a focusable nod e.
2289 // This, for example, sets focus to the first link if you search for 1786 // This, for example, sets focus to the first link if you search for
2290 // text and text that is within one or more links. 1787 // text and text that is within one or more links.
2291 node = m_activeMatch->firstNode(); 1788 node = activeMatch->firstNode();
2292 for (; node && node != m_activeMatch->pastLastNode(); node = NodeTravers al::next(*node)) { 1789 for (; node && node != activeMatch->pastLastNode(); node = NodeTraversal ::next(*node)) {
2293 if (!node->isElementNode()) 1790 if (!node->isElementNode())
2294 continue; 1791 continue;
2295 Element* element = toElement(node); 1792 Element* element = toElement(node);
2296 if (element->isFocusable()) { 1793 if (element->isFocusable()) {
2297 frame()->document()->setFocusedElement(element); 1794 frame()->document()->setFocusedElement(element);
2298 return; 1795 return;
2299 } 1796 }
2300 } 1797 }
2301 1798
2302 // No node related to the active match was focusable, so set the 1799 // No node related to the active match was focusable, so set the
2303 // active match as the selection (so that when you end the Find session, 1800 // active match as the selection (so that when you end the Find session,
2304 // you'll have the last thing you found highlighted) and make sure that 1801 // you'll have the last thing you found highlighted) and make sure that
2305 // we have nothing focused (otherwise you might have text selected but 1802 // we have nothing focused (otherwise you might have text selected but
2306 // a link focused, which is weird). 1803 // a link focused, which is weird).
2307 frame()->selection().setSelection(m_activeMatch.get()); 1804 frame()->selection().setSelection(activeMatch);
2308 frame()->document()->setFocusedElement(0); 1805 frame()->document()->setFocusedElement(0);
2309 1806
2310 // Finally clear the active match, for two reasons: 1807 // Finally clear the active match, for two reasons:
2311 // We just finished the find 'session' and we don't want future (potenti ally 1808 // We just finished the find 'session' and we don't want future (potenti ally
2312 // unrelated) find 'sessions' operations to start at the same place. 1809 // unrelated) find 'sessions' operations to start at the same place.
2313 // The WebFrameImpl could get reused and the m_activeMatch could end up pointing 1810 // The WebFrameImpl could get reused and the activeMatch could end up po inting
2314 // to a document that is no longer valid. Keeping an invalid reference a round 1811 // to a document that is no longer valid. Keeping an invalid reference a round
2315 // is just asking for trouble. 1812 // is just asking for trouble.
2316 m_activeMatch = 0; 1813 m_textFinder->resetActiveMatch();
2317 } 1814 }
2318 } 1815 }
2319 1816
2320 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional) 1817 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional)
2321 { 1818 {
2322 if (!client()) 1819 if (!client())
2323 return; 1820 return;
2324 WebURLError webError = error; 1821 WebURLError webError = error;
2325 if (wasProvisional) 1822 if (wasProvisional)
2326 client()->didFailProvisionalLoad(this, webError); 1823 client()->didFailProvisionalLoad(this, webError);
2327 else 1824 else
2328 client()->didFailLoad(this, webError); 1825 client()->didFailLoad(this, webError);
2329 } 1826 }
2330 1827
2331 void WebFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars) 1828 void WebFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
2332 { 1829 {
2333 frame()->view()->setCanHaveScrollbars(canHaveScrollbars); 1830 frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
2334 } 1831 }
2335 1832
2336 void WebFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, fl oat contentScaleFactor) 1833 void WebFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, fl oat contentScaleFactor)
2337 { 1834 {
2338 m_inputEventsOffsetForEmulation = offset; 1835 m_inputEventsOffsetForEmulation = offset;
2339 m_inputEventsScaleFactorForEmulation = contentScaleFactor; 1836 m_inputEventsScaleFactorForEmulation = contentScaleFactor;
2340 if (frame()->view()) 1837 if (frame()->view())
2341 frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffset ForEmulation, m_inputEventsScaleFactorForEmulation); 1838 frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffset ForEmulation, m_inputEventsScaleFactorForEmulation);
2342 } 1839 }
2343 1840
2344 void WebFrameImpl::invalidateArea(AreaToInvalidate area)
2345 {
2346 ASSERT(frame() && frame()->view());
2347 FrameView* view = frame()->view();
2348
2349 if ((area & InvalidateAll) == InvalidateAll)
2350 view->invalidateRect(view->frameRect());
2351 else {
2352 if ((area & InvalidateContentArea) == InvalidateContentArea) {
2353 IntRect contentArea(
2354 view->x(), view->y(), view->visibleWidth(), view->visibleHeight( ));
2355 IntRect frameRect = view->frameRect();
2356 contentArea.move(-frameRect.x(), -frameRect.y());
2357 view->invalidateRect(contentArea);
2358 }
2359 }
2360
2361 if ((area & InvalidateScrollbar) == InvalidateScrollbar) {
2362 // Invalidate the vertical scroll bar region for the view.
2363 Scrollbar* scrollbar = view->verticalScrollbar();
2364 if (scrollbar)
2365 scrollbar->invalidate();
2366 }
2367 }
2368
2369 void WebFrameImpl::addMarker(Range* range, bool activeMatch)
2370 {
2371 frame()->document()->markers()->addTextMatchMarker(range, activeMatch);
2372 }
2373
2374 void WebFrameImpl::setMarkerActive(Range* range, bool active)
2375 {
2376 if (!range || range->collapsed(IGNORE_EXCEPTION))
2377 return;
2378 frame()->document()->markers()->setMarkersActive(range, active);
2379 }
2380
2381 int WebFrameImpl::ordinalOfFirstMatchForFrame(WebFrameImpl* frame) const
2382 {
2383 int ordinal = 0;
2384 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
2385 // Iterate from the main frame up to (but not including) |frame| and
2386 // add up the number of matches found so far.
2387 for (WebFrameImpl* it = mainFrameImpl; it != frame; it = toWebFrameImpl(it-> traverseNext(true))) {
2388 if (it->m_lastMatchCount > 0)
2389 ordinal += it->m_lastMatchCount;
2390 }
2391 return ordinal;
2392 }
2393
2394 bool WebFrameImpl::shouldScopeMatches(const String& searchText)
2395 {
2396 // Don't scope if we can't find a frame or a view.
2397 // The user may have closed the tab/application, so abort.
2398 // Also ignore detached frames, as many find operations report to the main f rame.
2399 if (!frame() || !frame()->view() || !frame()->page() || !hasVisibleContent() )
2400 return false;
2401
2402 ASSERT(frame()->document() && frame()->view());
2403
2404 // If the frame completed the scoping operation and found 0 matches the last
2405 // time it was searched, then we don't have to search it again if the user i s
2406 // just adding to the search string or sending the same search string again.
2407 if (m_lastFindRequestCompletedWithNoMatches && !m_lastSearchString.isEmpty() ) {
2408 // Check to see if the search string prefixes match.
2409 String previousSearchPrefix =
2410 searchText.substring(0, m_lastSearchString.length());
2411
2412 if (previousSearchPrefix == m_lastSearchString)
2413 return false; // Don't search this frame, it will be fruitless.
2414 }
2415
2416 return true;
2417 }
2418
2419 void WebFrameImpl::scopeStringMatchesSoon(int identifier, const WebString& searc hText, const WebFindOptions& options, bool reset)
2420 {
2421 m_deferredScopingWork.append(new DeferredScopeStringMatches(this, identifier , searchText, options, reset));
2422 }
2423
2424 void WebFrameImpl::callScopeStringMatches(DeferredScopeStringMatches* caller, in t identifier, const WebString& searchText, const WebFindOptions& options, bool r eset)
2425 {
2426 m_deferredScopingWork.remove(m_deferredScopingWork.find(caller));
2427 scopeStringMatches(identifier, searchText, options, reset);
2428
2429 // This needs to happen last since searchText is passed by reference.
2430 delete caller;
2431 }
2432
2433 void WebFrameImpl::invalidateIfNecessary()
2434 {
2435 if (m_lastMatchCount <= m_nextInvalidateAfter)
2436 return;
2437
2438 // FIXME: (http://b/1088165) Optimize the drawing of the tickmarks and
2439 // remove this. This calculation sets a milestone for when next to
2440 // invalidate the scrollbar and the content area. We do this so that we
2441 // don't spend too much time drawing the scrollbar over and over again.
2442 // Basically, up until the first 500 matches there is no throttle.
2443 // After the first 500 matches, we set set the milestone further and
2444 // further out (750, 1125, 1688, 2K, 3K).
2445 static const int startSlowingDownAfter = 500;
2446 static const int slowdown = 750;
2447
2448 int i = m_lastMatchCount / startSlowingDownAfter;
2449 m_nextInvalidateAfter += i * slowdown;
2450 invalidateArea(InvalidateScrollbar);
2451 }
2452
2453 void WebFrameImpl::loadJavaScriptURL(const KURL& url) 1841 void WebFrameImpl::loadJavaScriptURL(const KURL& url)
2454 { 1842 {
2455 // This is copied from ScriptController::executeScriptIfJavaScriptURL. 1843 // This is copied from ScriptController::executeScriptIfJavaScriptURL.
2456 // Unfortunately, we cannot just use that method since it is private, and 1844 // Unfortunately, we cannot just use that method since it is private, and
2457 // it also doesn't quite behave as we require it to for bookmarklets. The 1845 // it also doesn't quite behave as we require it to for bookmarklets. The
2458 // key difference is that we need to suppress loading the string result 1846 // key difference is that we need to suppress loading the string result
2459 // from evaluating the JS URL if executing the JS URL resulted in a 1847 // from evaluating the JS URL if executing the JS URL resulted in a
2460 // location change. We also allow a JS URL to be loaded even if scripts on 1848 // location change. We also allow a JS URL to be loaded even if scripts on
2461 // the page are otherwise disabled. 1849 // the page are otherwise disabled.
2462 1850
(...skipping 15 matching lines...) Expand all
2478 return; 1866 return;
2479 1867
2480 if (!frame()->navigationScheduler().locationChangePending()) 1868 if (!frame()->navigationScheduler().locationChangePending())
2481 frame()->document()->loader()->replaceDocument(scriptResult, ownerDocume nt.get()); 1869 frame()->document()->loader()->replaceDocument(scriptResult, ownerDocume nt.get());
2482 } 1870 }
2483 1871
2484 void WebFrameImpl::willDetachParent() 1872 void WebFrameImpl::willDetachParent()
2485 { 1873 {
2486 // Do not expect string scoping results from any frames that got detached 1874 // Do not expect string scoping results from any frames that got detached
2487 // in the middle of the operation. 1875 // in the middle of the operation.
2488 if (m_scopingInProgress) { 1876 if (m_textFinder && m_textFinder->scopingInProgress()) {
2489 1877
2490 // There is a possibility that the frame being detached was the only 1878 // There is a possibility that the frame being detached was the only
2491 // pending one. We need to make sure final replies can be sent. 1879 // pending one. We need to make sure final replies can be sent.
2492 flushCurrentScopingEffort(m_findRequestIdentifier); 1880 m_textFinder->flushCurrentScoping();
2493 1881
2494 cancelPendingScopingEffort(); 1882 m_textFinder->cancelPendingScopingEffort();
2495 } 1883 }
2496 } 1884 }
2497 1885
1886 WebFrameImpl* WebFrameImpl::activeMatchFrame() const
1887 {
1888 ASSERT(!parent());
1889 ASSERT(m_textFinder);
1890 return m_textFinder->activeMatchFrame();
1891 }
1892
1893 WebCore::Range* WebFrameImpl::activeMatch() const
1894 {
1895 ASSERT(m_textFinder);
1896 return m_textFinder->activeMatch();
1897 }
1898
1899 TextFinder& WebFrameImpl::getOrCreateTextFinder()
1900 {
1901 if (!m_textFinder)
1902 m_textFinder = TextFinder::create(*this);
1903
1904 ASSERT(m_textFinder);
1905 return *m_textFinder;
1906 }
1907
2498 } // namespace blink 1908 } // namespace blink
OLDNEW
« no previous file with comments | « Source/web/WebFrameImpl.h ('k') | Source/web/web.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698