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

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

Issue 181013007: Introduce TextFinder class for decoupling WebFrameImpl and text finder. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@introduce-textfinder-class-new
Patch Set: Fixed Linux build Created 6 years, 9 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 "CompositionUnderlineVectorBuilder.h" 77 #include "CompositionUnderlineVectorBuilder.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 "WebConsoleMessage.h" 84 #include "WebConsoleMessage.h"
84 #include "WebDOMEvent.h" 85 #include "WebDOMEvent.h"
85 #include "WebDOMEventListener.h" 86 #include "WebDOMEventListener.h"
86 #include "WebDataSourceImpl.h" 87 #include "WebDataSourceImpl.h"
87 #include "WebDevToolsAgentPrivate.h" 88 #include "WebDevToolsAgentPrivate.h"
88 #include "WebDocument.h" 89 #include "WebDocument.h"
89 #include "WebFindOptions.h" 90 #include "WebFindOptions.h"
90 #include "WebFormElement.h" 91 #include "WebFormElement.h"
91 #include "WebFrameClient.h" 92 #include "WebFrameClient.h"
92 #include "WebHistoryItem.h" 93 #include "WebHistoryItem.h"
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 int m_pageCount; 444 int m_pageCount;
444 WebPrintParams m_printParams; 445 WebPrintParams m_printParams;
445 446
446 }; 447 };
447 448
448 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) 449 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader)
449 { 450 {
450 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0; 451 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
451 } 452 }
452 453
453 WebFrameImpl::FindMatch::FindMatch(PassRefPtr<Range> range, int ordinal)
454 : m_range(range)
455 , m_ordinal(ordinal)
456 {
457 }
458
459 class WebFrameImpl::DeferredScopeStringMatches {
460 public:
461 DeferredScopeStringMatches(WebFrameImpl* webFrame, int identifier, const Web String& searchText, const WebFindOptions& options, bool reset)
462 : m_timer(this, &DeferredScopeStringMatches::doTimeout)
463 , m_webFrame(webFrame)
464 , m_identifier(identifier)
465 , m_searchText(searchText)
466 , m_options(options)
467 , m_reset(reset)
468 {
469 m_timer.startOneShot(0.0, FROM_HERE);
470 }
471
472 private:
473 void doTimeout(Timer<DeferredScopeStringMatches>*)
474 {
475 m_webFrame->callScopeStringMatches(this, m_identifier, m_searchText, m_o ptions, m_reset);
476 }
477
478 Timer<DeferredScopeStringMatches> m_timer;
479 RefPtr<WebFrameImpl> m_webFrame;
480 int m_identifier;
481 WebString m_searchText;
482 WebFindOptions m_options;
483 bool m_reset;
484 };
485
486 // WebFrame ------------------------------------------------------------------- 454 // WebFrame -------------------------------------------------------------------
487 455
488 int WebFrame::instanceCount() 456 int WebFrame::instanceCount()
489 { 457 {
490 return frameCount; 458 return frameCount;
491 } 459 }
492 460
493 WebLocalFrame* WebFrame::frameForCurrentContext() 461 WebLocalFrame* WebFrame::frameForCurrentContext()
494 { 462 {
495 v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentConte xt(); 463 v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentConte xt();
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after
1499 } 1467 }
1500 1468
1501 WebString WebFrameImpl::pageProperty(const WebString& propertyName, int pageInde x) 1469 WebString WebFrameImpl::pageProperty(const WebString& propertyName, int pageInde x)
1502 { 1470 {
1503 ASSERT(m_printContext); 1471 ASSERT(m_printContext);
1504 return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pag eIndex); 1472 return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pag eIndex);
1505 } 1473 }
1506 1474
1507 bool WebFrameImpl::find(int identifier, const WebString& searchText, const WebFi ndOptions& options, bool wrapWithinFrame, WebRect* selectionRect) 1475 bool WebFrameImpl::find(int identifier, const WebString& searchText, const WebFi ndOptions& options, bool wrapWithinFrame, WebRect* selectionRect)
1508 { 1476 {
1509 if (!frame() || !frame()->page()) 1477 return ensureTextFinder().find(identifier, searchText, options, wrapWithinFr ame, selectionRect);
1510 return false;
1511
1512 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1513
1514 if (!options.findNext)
1515 frame()->page()->unmarkAllTextMatches();
1516 else
1517 setMarkerActive(m_activeMatch.get(), false);
1518
1519 if (m_activeMatch && &m_activeMatch->ownerDocument() != frame()->document())
1520 m_activeMatch = nullptr;
1521
1522 // If the user has selected something since the last Find operation we want
1523 // to start from there. Otherwise, we start searching from where the last Fi nd
1524 // operation left off (either a Find or a FindNext operation).
1525 VisibleSelection selection(frame()->selection().selection());
1526 bool activeSelection = !selection.isNone();
1527 if (activeSelection) {
1528 m_activeMatch = selection.firstRange().get();
1529 frame()->selection().clear();
1530 }
1531
1532 ASSERT(frame() && frame()->view());
1533 const FindOptions findOptions = (options.forward ? 0 : Backwards)
1534 | (options.matchCase ? 0 : CaseInsensitive)
1535 | (wrapWithinFrame ? WrapAround : 0)
1536 | (options.wordStart ? AtWordStarts : 0)
1537 | (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0)
1538 | (options.findNext ? 0 : StartInSelection);
1539 m_activeMatch = frame()->editor().findStringAndScrollToVisible(searchText, m _activeMatch.get(), findOptions);
1540
1541 if (!m_activeMatch) {
1542 // If we're finding next the next active match might not be in the curre nt frame.
1543 // In this case we don't want to clear the matches cache.
1544 if (!options.findNext)
1545 clearFindMatchesCache();
1546 invalidateArea(InvalidateAll);
1547 return false;
1548 }
1549
1550 #if OS(ANDROID)
1551 viewImpl()->zoomToFindInPageRect(frameView()->contentsToWindow(enclosingIntR ect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()))));
1552 #endif
1553
1554 setMarkerActive(m_activeMatch.get(), true);
1555 WebFrameImpl* oldActiveFrame = mainFrameImpl->m_currentActiveMatchFrame;
1556 mainFrameImpl->m_currentActiveMatchFrame = this;
1557
1558 // Make sure no node is focused. See http://crbug.com/38700.
1559 frame()->document()->setFocusedElement(nullptr);
1560
1561 if (!options.findNext || activeSelection) {
1562 // This is either a Find operation or a Find-next from a new start point
1563 // due to a selection, so we set the flag to ask the scoping effort
1564 // to find the active rect for us and report it back to the UI.
1565 m_locatingActiveRect = true;
1566 } else {
1567 if (oldActiveFrame != this) {
1568 if (options.forward)
1569 m_activeMatchIndexInCurrentFrame = 0;
1570 else
1571 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
1572 } else {
1573 if (options.forward)
1574 ++m_activeMatchIndexInCurrentFrame;
1575 else
1576 --m_activeMatchIndexInCurrentFrame;
1577
1578 if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount)
1579 m_activeMatchIndexInCurrentFrame = 0;
1580 if (m_activeMatchIndexInCurrentFrame == -1)
1581 m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
1582 }
1583 if (selectionRect) {
1584 *selectionRect = frameView()->contentsToWindow(m_activeMatch->boundi ngBox());
1585 reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurren tFrame + 1, identifier);
1586 }
1587 }
1588
1589 return true;
1590 } 1478 }
1591 1479
1592 void WebFrameImpl::stopFinding(bool clearSelection) 1480 void WebFrameImpl::stopFinding(bool clearSelection)
1593 { 1481 {
1594 if (!clearSelection) 1482 if (m_textFinder) {
1595 setFindEndstateFocusAndSelection(); 1483 if (!clearSelection)
1596 cancelPendingScopingEffort(); 1484 setFindEndstateFocusAndSelection();
1597 1485 m_textFinder->stopFindingAndClearSelection();
1598 // Remove all markers for matches found and turn off the highlighting. 1486 }
1599 frame()->document()->markers().removeMarkers(DocumentMarker::TextMatch);
1600 frame()->editor().setMarkedTextMatchesAreHighlighted(false);
1601 clearFindMatchesCache();
1602
1603 // Let the frame know that we don't want tickmarks or highlighting anymore.
1604 invalidateArea(InvalidateAll);
1605 } 1487 }
1606 1488
1607 void WebFrameImpl::scopeStringMatches(int identifier, const WebString& searchTex t, const WebFindOptions& options, bool reset) 1489 void WebFrameImpl::scopeStringMatches(int identifier, const WebString& searchTex t, const WebFindOptions& options, bool reset)
1608 { 1490 {
1609 if (reset) { 1491 ensureTextFinder().scopeStringMatches(identifier, searchText, options, reset );
1610 // This is a brand new search, so we need to reset everything.
1611 // Scoping is just about to begin.
1612 m_scopingInProgress = true;
1613
1614 // Need to keep the current identifier locally in order to finish the
1615 // request in case the frame is detached during the process.
1616 m_findRequestIdentifier = identifier;
1617
1618 // Clear highlighting for this frame.
1619 if (frame() && frame()->page() && frame()->editor().markedTextMatchesAre Highlighted())
1620 frame()->page()->unmarkAllTextMatches();
1621
1622 // Clear the tickmarks and results cache.
1623 clearFindMatchesCache();
1624
1625 // Clear the counters from last operation.
1626 m_lastMatchCount = 0;
1627 m_nextInvalidateAfter = 0;
1628
1629 m_resumeScopingFromRange = nullptr;
1630
1631 // The view might be null on detached frames.
1632 if (frame() && frame()->page())
1633 viewImpl()->mainFrameImpl()->m_framesScopingCount++;
1634
1635 // Now, defer scoping until later to allow find operation to finish quic kly.
1636 scopeStringMatchesSoon(identifier, searchText, options, false); // false means just reset, so don't do it again.
1637 return;
1638 }
1639
1640 if (!shouldScopeMatches(searchText)) {
1641 // Note that we want to defer the final update when resetting even if sh ouldScopeMatches returns false.
1642 // This is done in order to prevent sending a final message based only o n the results of the first frame
1643 // since m_framesScopingCount would be 0 as other frames have yet to res et.
1644 finishCurrentScopingEffort(identifier);
1645 return;
1646 }
1647
1648 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1649 RefPtr<Range> searchRange(rangeOfContents(frame()->document()));
1650
1651 Node* originalEndContainer = searchRange->endContainer();
1652 int originalEndOffset = searchRange->endOffset();
1653
1654 TrackExceptionState exceptionState, exceptionState2;
1655 if (m_resumeScopingFromRange) {
1656 // This is a continuation of a scoping operation that timed out and didn 't
1657 // complete last time around, so we should start from where we left off.
1658 searchRange->setStart(m_resumeScopingFromRange->startContainer(), m_resu meScopingFromRange->startOffset(exceptionState2) + 1, exceptionState);
1659 if (exceptionState.hadException() || exceptionState2.hadException()) {
1660 if (exceptionState2.hadException()) // A non-zero |exceptionState| h appens when navigating during search.
1661 ASSERT_NOT_REACHED();
1662 return;
1663 }
1664 }
1665
1666 // This timeout controls how long we scope before releasing control. This
1667 // value does not prevent us from running for longer than this, but it is
1668 // periodically checked to see if we have exceeded our allocated time.
1669 const double maxScopingDuration = 0.1; // seconds
1670
1671 int matchCount = 0;
1672 bool timedOut = false;
1673 double startTime = currentTime();
1674 do {
1675 // Find next occurrence of the search string.
1676 // FIXME: (http://b/1088245) This WebKit operation may run for longer
1677 // than the timeout value, and is not interruptible as it is currently
1678 // written. We may need to rewrite it with interruptibility in mind, or
1679 // find an alternative.
1680 RefPtr<Range> resultRange(findPlainText(searchRange.get(),
1681 searchText,
1682 options.matchCase ? 0 : CaseInse nsitive));
1683 if (resultRange->collapsed(exceptionState)) {
1684 if (!resultRange->startContainer()->isInShadowTree())
1685 break;
1686
1687 searchRange->setStartAfter(
1688 resultRange->startContainer()->deprecatedShadowAncestorNode(), e xceptionState);
1689 searchRange->setEnd(originalEndContainer, originalEndOffset, excepti onState);
1690 continue;
1691 }
1692
1693 ++matchCount;
1694
1695 // Catch a special case where Find found something but doesn't know what
1696 // the bounding box for it is. In this case we set the first match we fi nd
1697 // as the active rect.
1698 IntRect resultBounds = resultRange->boundingBox();
1699 IntRect activeSelectionRect;
1700 if (m_locatingActiveRect) {
1701 activeSelectionRect = m_activeMatch.get() ?
1702 m_activeMatch->boundingBox() : resultBounds;
1703 }
1704
1705 // If the Find function found a match it will have stored where the
1706 // match was found in m_activeSelectionRect on the current frame. If we
1707 // find this rect during scoping it means we have found the active
1708 // tickmark.
1709 bool foundActiveMatch = false;
1710 if (m_locatingActiveRect && (activeSelectionRect == resultBounds)) {
1711 // We have found the active tickmark frame.
1712 mainFrameImpl->m_currentActiveMatchFrame = this;
1713 foundActiveMatch = true;
1714 // We also know which tickmark is active now.
1715 m_activeMatchIndexInCurrentFrame = matchCount - 1;
1716 // To stop looking for the active tickmark, we set this flag.
1717 m_locatingActiveRect = false;
1718
1719 // Notify browser of new location for the selected rectangle.
1720 reportFindInPageSelection(
1721 frameView()->contentsToWindow(resultBounds),
1722 m_activeMatchIndexInCurrentFrame + 1,
1723 identifier);
1724 }
1725
1726 addMarker(resultRange.get(), foundActiveMatch);
1727
1728 m_findMatchesCache.append(FindMatch(resultRange.get(), m_lastMatchCount + matchCount));
1729
1730 // Set the new start for the search range to be the end of the previous
1731 // result range. There is no need to use a VisiblePosition here,
1732 // since findPlainText will use a TextIterator to go over the visible
1733 // text nodes.
1734 searchRange->setStart(resultRange->endContainer(exceptionState), resultR ange->endOffset(exceptionState), exceptionState);
1735
1736 Node* shadowTreeRoot = searchRange->shadowRoot();
1737 if (searchRange->collapsed(exceptionState) && shadowTreeRoot)
1738 searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->countChildren(), exceptionState);
1739
1740 m_resumeScopingFromRange = resultRange;
1741 timedOut = (currentTime() - startTime) >= maxScopingDuration;
1742 } while (!timedOut);
1743
1744 // Remember what we search for last time, so we can skip searching if more
1745 // letters are added to the search string (and last outcome was 0).
1746 m_lastSearchString = searchText;
1747
1748 if (matchCount > 0) {
1749 frame()->editor().setMarkedTextMatchesAreHighlighted(true);
1750
1751 m_lastMatchCount += matchCount;
1752
1753 // Let the mainframe know how much we found during this pass.
1754 mainFrameImpl->increaseMatchCount(matchCount, identifier);
1755 }
1756
1757 if (timedOut) {
1758 // If we found anything during this pass, we should redraw. However, we
1759 // don't want to spam too much if the page is extremely long, so if we
1760 // reach a certain point we start throttling the redraw requests.
1761 if (matchCount > 0)
1762 invalidateIfNecessary();
1763
1764 // Scoping effort ran out of time, lets ask for another time-slice.
1765 scopeStringMatchesSoon(
1766 identifier,
1767 searchText,
1768 options,
1769 false); // don't reset.
1770 return; // Done for now, resume work later.
1771 }
1772
1773 finishCurrentScopingEffort(identifier);
1774 }
1775
1776 void WebFrameImpl::flushCurrentScopingEffort(int identifier)
1777 {
1778 if (!frame() || !frame()->page())
1779 return;
1780
1781 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1782
1783 // This frame has no further scoping left, so it is done. Other frames might ,
1784 // of course, continue to scope matches.
1785 mainFrameImpl->m_framesScopingCount--;
1786
1787 // If this is the last frame to finish scoping we need to trigger the final
1788 // update to be sent.
1789 if (!mainFrameImpl->m_framesScopingCount)
1790 mainFrameImpl->increaseMatchCount(0, identifier);
1791 }
1792
1793 void WebFrameImpl::finishCurrentScopingEffort(int identifier)
1794 {
1795 flushCurrentScopingEffort(identifier);
1796
1797 m_scopingInProgress = false;
1798 m_lastFindRequestCompletedWithNoMatches = !m_lastMatchCount;
1799
1800 // This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
1801 invalidateArea(InvalidateScrollbar);
1802 } 1492 }
1803 1493
1804 void WebFrameImpl::cancelPendingScopingEffort() 1494 void WebFrameImpl::cancelPendingScopingEffort()
1805 { 1495 {
1806 deleteAllValues(m_deferredScopingWork); 1496 if (m_textFinder)
1807 m_deferredScopingWork.clear(); 1497 m_textFinder->cancelPendingScopingEffort();
1808
1809 m_activeMatchIndexInCurrentFrame = -1;
1810
1811 // Last request didn't complete.
1812 if (m_scopingInProgress)
1813 m_lastFindRequestCompletedWithNoMatches = false;
1814
1815 m_scopingInProgress = false;
1816 } 1498 }
1817 1499
1818 void WebFrameImpl::increaseMatchCount(int count, int identifier) 1500 void WebFrameImpl::increaseMatchCount(int count, int identifier)
1819 { 1501 {
1820 // This function should only be called on the mainframe. 1502 // This function should only be called on the mainframe.
1821 ASSERT(!parent()); 1503 ASSERT(!parent());
1822 1504 ASSERT(m_textFinder);
1823 if (count) 1505 m_textFinder->increaseMatchCount(identifier, count);
1824 ++m_findMatchMarkersVersion;
1825
1826 m_totalMatchCount += count;
1827
1828 // Update the UI with the latest findings.
1829 if (client())
1830 client()->reportFindInPageMatchCount(identifier, m_totalMatchCount, !m_f ramesScopingCount);
1831 }
1832
1833 void WebFrameImpl::reportFindInPageSelection(const WebRect& selectionRect, int a ctiveMatchOrdinal, int identifier)
1834 {
1835 // Update the UI with the latest selection rect.
1836 if (client())
1837 client()->reportFindInPageSelection(identifier, ordinalOfFirstMatchForFr ame(this) + activeMatchOrdinal, selectionRect);
1838 } 1506 }
1839 1507
1840 void WebFrameImpl::resetMatchCount() 1508 void WebFrameImpl::resetMatchCount()
1841 { 1509 {
1842 if (m_totalMatchCount > 0) 1510 ASSERT(m_textFinder);
1843 ++m_findMatchMarkersVersion; 1511 m_textFinder->resetMatchCount();
1844
1845 m_totalMatchCount = 0;
1846 m_framesScopingCount = 0;
1847 } 1512 }
1848 1513
1849 void WebFrameImpl::sendOrientationChangeEvent(int orientation) 1514 void WebFrameImpl::sendOrientationChangeEvent(int orientation)
1850 { 1515 {
1851 if (frame()) 1516 if (frame())
1852 frame()->sendOrientationChangeEvent(orientation); 1517 frame()->sendOrientationChangeEvent(orientation);
1853 } 1518 }
1854 1519
1855 void WebFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event) 1520 void WebFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event)
1856 { 1521 {
1857 ASSERT(!event.isNull()); 1522 ASSERT(!event.isNull());
1858 frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrig in.get(), event, nullptr); 1523 frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrig in.get(), event, nullptr);
1859 } 1524 }
1860 1525
1861 int WebFrameImpl::findMatchMarkersVersion() const 1526 int WebFrameImpl::findMatchMarkersVersion() const
1862 { 1527 {
1863 ASSERT(!parent()); 1528 ASSERT(!parent());
1864 return m_findMatchMarkersVersion; 1529
1530 if (m_textFinder)
1531 return m_textFinder->findMatchMarkersVersion();
1532 return 0;
1865 } 1533 }
1866 1534
1867 void WebFrameImpl::clearFindMatchesCache() 1535 int WebFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* se lectionRect)
1868 { 1536 {
1869 if (!m_findMatchesCache.isEmpty()) 1537 ASSERT(!parent());
1870 viewImpl()->mainFrameImpl()->m_findMatchMarkersVersion++; 1538 ASSERT(m_textFinder);
1871 1539 return m_textFinder->selectNearestFindMatch(point, selectionRect);
1872 m_findMatchesCache.clear();
1873 m_findMatchRectsAreValid = false;
1874 }
1875
1876 bool WebFrameImpl::isActiveMatchFrameValid() const
1877 {
1878 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
1879 WebFrameImpl* activeMatchFrame = mainFrameImpl->activeMatchFrame();
1880 return activeMatchFrame && activeMatchFrame->m_activeMatch && activeMatchFra me->frame()->tree().isDescendantOf(mainFrameImpl->frame());
1881 }
1882
1883 void WebFrameImpl::updateFindMatchRects()
1884 {
1885 IntSize currentContentsSize = contentsSize();
1886 if (m_contentsSizeForCurrentFindMatchRects != currentContentsSize) {
1887 m_contentsSizeForCurrentFindMatchRects = currentContentsSize;
1888 m_findMatchRectsAreValid = false;
1889 }
1890
1891 size_t deadMatches = 0;
1892 for (Vector<FindMatch>::iterator it = m_findMatchesCache.begin(); it != m_fi ndMatchesCache.end(); ++it) {
1893 if (!it->m_range->boundaryPointsValid() || !it->m_range->startContainer( )->inDocument())
1894 it->m_rect = FloatRect();
1895 else if (!m_findMatchRectsAreValid)
1896 it->m_rect = findInPageRectFromRange(it->m_range.get());
1897
1898 if (it->m_rect.isEmpty())
1899 ++deadMatches;
1900 }
1901
1902 // Remove any invalid matches from the cache.
1903 if (deadMatches) {
1904 Vector<FindMatch> filteredMatches;
1905 filteredMatches.reserveCapacity(m_findMatchesCache.size() - deadMatches) ;
1906
1907 for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it != m_findMatchesCache.end(); ++it)
1908 if (!it->m_rect.isEmpty())
1909 filteredMatches.append(*it);
1910
1911 m_findMatchesCache.swap(filteredMatches);
1912 }
1913
1914 // Invalidate the rects in child frames. Will be updated later during traver sal.
1915 if (!m_findMatchRectsAreValid)
1916 for (WebFrame* child = firstChild(); child; child = child->nextSibling() )
1917 toWebFrameImpl(child)->m_findMatchRectsAreValid = false;
1918
1919 m_findMatchRectsAreValid = true;
1920 } 1540 }
1921 1541
1922 WebFloatRect WebFrameImpl::activeFindMatchRect() 1542 WebFloatRect WebFrameImpl::activeFindMatchRect()
1923 { 1543 {
1924 ASSERT(!parent()); 1544 ASSERT(!parent());
1925 1545
1926 if (!isActiveMatchFrameValid()) 1546 if (m_textFinder)
1927 return WebFloatRect(); 1547 return m_textFinder->activeFindMatchRect();
1928 1548 return WebFloatRect();
1929 return WebFloatRect(findInPageRectFromRange(m_currentActiveMatchFrame->m_act iveMatch.get()));
1930 } 1549 }
1931 1550
1932 void WebFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects) 1551 void WebFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects)
1933 { 1552 {
1934 ASSERT(!parent()); 1553 ASSERT(!parent());
1935 1554 ASSERT(m_textFinder);
1936 Vector<WebFloatRect> matchRects; 1555 m_textFinder->findMatchRects(outputRects);
1937 for (WebFrameImpl* frame = this; frame; frame = toWebFrameImpl(frame->traver seNext(false)))
1938 frame->appendFindMatchRects(matchRects);
1939
1940 outputRects = matchRects;
1941 }
1942
1943 void WebFrameImpl::appendFindMatchRects(Vector<WebFloatRect>& frameRects)
1944 {
1945 updateFindMatchRects();
1946 frameRects.reserveCapacity(frameRects.size() + m_findMatchesCache.size());
1947 for (Vector<FindMatch>::const_iterator it = m_findMatchesCache.begin(); it ! = m_findMatchesCache.end(); ++it) {
1948 ASSERT(!it->m_rect.isEmpty());
1949 frameRects.append(it->m_rect);
1950 }
1951 }
1952
1953 int WebFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* se lectionRect)
1954 {
1955 ASSERT(!parent());
1956
1957 WebFrameImpl* bestFrame = 0;
1958 int indexInBestFrame = -1;
1959 float distanceInBestFrame = FLT_MAX;
1960
1961 for (WebFrameImpl* frame = this; frame; frame = toWebFrameImpl(frame->traver seNext(false))) {
1962 float distanceInFrame;
1963 int indexInFrame = frame->nearestFindMatch(point, distanceInFrame);
1964 if (distanceInFrame < distanceInBestFrame) {
1965 bestFrame = frame;
1966 indexInBestFrame = indexInFrame;
1967 distanceInBestFrame = distanceInFrame;
1968 }
1969 }
1970
1971 if (indexInBestFrame != -1)
1972 return bestFrame->selectFindMatch(static_cast<unsigned>(indexInBestFrame ), selectionRect);
1973
1974 return -1;
1975 } 1556 }
1976 1557
1977 void WebFrameImpl::setTickmarks(const WebVector<WebRect>& tickmarks) 1558 void WebFrameImpl::setTickmarks(const WebVector<WebRect>& tickmarks)
1978 { 1559 {
1979 if (frameView()) { 1560 if (frameView()) {
1980 Vector<IntRect> tickmarksConverted(tickmarks.size()); 1561 Vector<IntRect> tickmarksConverted(tickmarks.size());
1981 for (size_t i = 0; i < tickmarks.size(); ++i) 1562 for (size_t i = 0; i < tickmarks.size(); ++i)
1982 tickmarksConverted[i] = tickmarks[i]; 1563 tickmarksConverted[i] = tickmarks[i];
1983 frameView()->setTickmarks(tickmarksConverted); 1564 frameView()->setTickmarks(tickmarksConverted);
1984 invalidateArea(InvalidateScrollbar); 1565 invalidateScrollbar();
1985 } 1566 }
1986 } 1567 }
1987 1568
1988 int WebFrameImpl::nearestFindMatch(const FloatPoint& point, float& distanceSquar ed)
1989 {
1990 updateFindMatchRects();
1991
1992 int nearest = -1;
1993 distanceSquared = FLT_MAX;
1994 for (size_t i = 0; i < m_findMatchesCache.size(); ++i) {
1995 ASSERT(!m_findMatchesCache[i].m_rect.isEmpty());
1996 FloatSize offset = point - m_findMatchesCache[i].m_rect.center();
1997 float width = offset.width();
1998 float height = offset.height();
1999 float currentDistanceSquared = width * width + height * height;
2000 if (currentDistanceSquared < distanceSquared) {
2001 nearest = i;
2002 distanceSquared = currentDistanceSquared;
2003 }
2004 }
2005 return nearest;
2006 }
2007
2008 int WebFrameImpl::selectFindMatch(unsigned index, WebRect* selectionRect)
2009 {
2010 ASSERT_WITH_SECURITY_IMPLICATION(index < m_findMatchesCache.size());
2011
2012 RefPtr<Range> range = m_findMatchesCache[index].m_range;
2013 if (!range->boundaryPointsValid() || !range->startContainer()->inDocument())
2014 return -1;
2015
2016 // Check if the match is already selected.
2017 WebFrameImpl* activeMatchFrame = viewImpl()->mainFrameImpl()->m_currentActiv eMatchFrame;
2018 if (this != activeMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMa tch.get(), range.get())) {
2019 if (isActiveMatchFrameValid())
2020 activeMatchFrame->setMarkerActive(activeMatchFrame->m_activeMatch.ge t(), false);
2021
2022 m_activeMatchIndexInCurrentFrame = m_findMatchesCache[index].m_ordinal - 1;
2023
2024 // Set this frame as the active frame (the one with the active highlight ).
2025 viewImpl()->mainFrameImpl()->m_currentActiveMatchFrame = this;
2026 viewImpl()->setFocusedFrame(this);
2027
2028 m_activeMatch = range.release();
2029 setMarkerActive(m_activeMatch.get(), true);
2030
2031 // Clear any user selection, to make sure Find Next continues on from th e match we just activated.
2032 frame()->selection().clear();
2033
2034 // Make sure no node is focused. See http://crbug.com/38700.
2035 frame()->document()->setFocusedElement(nullptr);
2036 }
2037
2038 IntRect activeMatchRect;
2039 IntRect activeMatchBoundingBox = enclosingIntRect(RenderObject::absoluteBoun dingBoxRectForRange(m_activeMatch.get()));
2040
2041 if (!activeMatchBoundingBox.isEmpty()) {
2042 if (m_activeMatch->firstNode() && m_activeMatch->firstNode()->renderer() )
2043 m_activeMatch->firstNode()->renderer()->scrollRectToVisible(activeMa tchBoundingBox,
2044 ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::align CenterIfNeeded);
2045
2046 // Zoom to the active match.
2047 activeMatchRect = frameView()->contentsToWindow(activeMatchBoundingBox);
2048 viewImpl()->zoomToFindInPageRect(activeMatchRect);
2049 }
2050
2051 if (selectionRect)
2052 *selectionRect = activeMatchRect;
2053
2054 return ordinalOfFirstMatchForFrame(this) + m_activeMatchIndexInCurrentFrame + 1;
2055 }
2056
2057 WebString WebFrameImpl::contentAsText(size_t maxChars) const 1569 WebString WebFrameImpl::contentAsText(size_t maxChars) const
2058 { 1570 {
2059 if (!frame()) 1571 if (!frame())
2060 return WebString(); 1572 return WebString();
2061 StringBuilder text; 1573 StringBuilder text;
2062 frameContentAsPlainText(maxChars, frame(), text); 1574 frameContentAsPlainText(maxChars, frame(), text);
2063 return text.toString(); 1575 return text.toString();
2064 } 1576 }
2065 1577
2066 WebString WebFrameImpl::contentAsMarkup() const 1578 WebString WebFrameImpl::contentAsMarkup() const
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2133 WebFrameImpl::WebFrameImpl(WebFrameClient* client) 1645 WebFrameImpl::WebFrameImpl(WebFrameClient* client)
2134 : m_frameLoaderClientImpl(this) 1646 : m_frameLoaderClientImpl(this)
2135 , m_parent(0) 1647 , m_parent(0)
2136 , m_previousSibling(0) 1648 , m_previousSibling(0)
2137 , m_nextSibling(0) 1649 , m_nextSibling(0)
2138 , m_firstChild(0) 1650 , m_firstChild(0)
2139 , m_lastChild(0) 1651 , m_lastChild(0)
2140 , m_opener(0) 1652 , m_opener(0)
2141 , m_client(client) 1653 , m_client(client)
2142 , m_permissionClient(0) 1654 , m_permissionClient(0)
2143 , m_currentActiveMatchFrame(0)
2144 , m_activeMatchIndexInCurrentFrame(-1)
2145 , m_locatingActiveRect(false)
2146 , m_resumeScopingFromRange(nullptr)
2147 , m_lastMatchCount(-1)
2148 , m_totalMatchCount(-1)
2149 , m_framesScopingCount(-1)
2150 , m_findRequestIdentifier(-1)
2151 , m_scopingInProgress(false)
2152 , m_lastFindRequestCompletedWithNoMatches(false)
2153 , m_nextInvalidateAfter(0)
2154 , m_findMatchMarkersVersion(0)
2155 , m_findMatchRectsAreValid(false)
2156 , m_inputEventsScaleFactorForEmulation(1) 1655 , m_inputEventsScaleFactorForEmulation(1)
2157 { 1656 {
2158 blink::Platform::current()->incrementStatsCounter(webFrameActiveCount); 1657 blink::Platform::current()->incrementStatsCounter(webFrameActiveCount);
2159 frameCount++; 1658 frameCount++;
2160 } 1659 }
2161 1660
2162 WebFrameImpl::~WebFrameImpl() 1661 WebFrameImpl::~WebFrameImpl()
2163 { 1662 {
2164 HashSet<WebFrameImpl*>::iterator end = m_openedFrames.end(); 1663 HashSet<WebFrameImpl*>::iterator end = m_openedFrames.end();
2165 for (HashSet<WebFrameImpl*>::iterator it = m_openedFrames.begin(); it != end ; ++it) 1664 for (HashSet<WebFrameImpl*>::iterator it = m_openedFrames.begin(); it != end ; ++it)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2229 // NOTE: m_client will be null if this frame has been detached. 1728 // NOTE: m_client will be null if this frame has been detached.
2230 if (!childFrame->tree().parent()) 1729 if (!childFrame->tree().parent())
2231 return nullptr; 1730 return nullptr;
2232 1731
2233 return childFrame.release(); 1732 return childFrame.release();
2234 } 1733 }
2235 1734
2236 void WebFrameImpl::didChangeContentsSize(const IntSize& size) 1735 void WebFrameImpl::didChangeContentsSize(const IntSize& size)
2237 { 1736 {
2238 // This is only possible on the main frame. 1737 // This is only possible on the main frame.
2239 if (m_totalMatchCount > 0) { 1738 if (m_textFinder && m_textFinder->totalMatchCount() > 0) {
2240 ASSERT(!parent()); 1739 ASSERT(!parent());
2241 ++m_findMatchMarkersVersion; 1740 m_textFinder->increaseMarkerVersion();
2242 } 1741 }
2243 } 1742 }
2244 1743
2245 void WebFrameImpl::createFrameView() 1744 void WebFrameImpl::createFrameView()
2246 { 1745 {
2247 TRACE_EVENT0("webkit", "WebFrameImpl::createFrameView"); 1746 TRACE_EVENT0("webkit", "WebFrameImpl::createFrameView");
2248 1747
2249 ASSERT(frame()); // If frame() doesn't exist, we probably didn't init proper ly. 1748 ASSERT(frame()); // If frame() doesn't exist, we probably didn't init proper ly.
2250 1749
2251 WebViewImpl* webView = viewImpl(); 1750 WebViewImpl* webView = viewImpl();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2295 1794
2296 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const 1795 WebDataSourceImpl* WebFrameImpl::provisionalDataSourceImpl() const
2297 { 1796 {
2298 return static_cast<WebDataSourceImpl*>(provisionalDataSource()); 1797 return static_cast<WebDataSourceImpl*>(provisionalDataSource());
2299 } 1798 }
2300 1799
2301 void WebFrameImpl::setFindEndstateFocusAndSelection() 1800 void WebFrameImpl::setFindEndstateFocusAndSelection()
2302 { 1801 {
2303 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl(); 1802 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
2304 1803
2305 if (this == mainFrameImpl->activeMatchFrame() && m_activeMatch.get()) { 1804 if (this != mainFrameImpl->activeMatchFrame())
1805 return;
1806
1807 if (Range* activeMatch = m_textFinder->activeMatch()) {
2306 // If the user has set the selection since the match was found, we 1808 // If the user has set the selection since the match was found, we
2307 // don't focus anything. 1809 // don't focus anything.
2308 VisibleSelection selection(frame()->selection().selection()); 1810 VisibleSelection selection(frame()->selection().selection());
2309 if (!selection.isNone()) 1811 if (!selection.isNone())
2310 return; 1812 return;
2311 1813
2312 // Try to find the first focusable node up the chain, which will, for 1814 // Try to find the first focusable node up the chain, which will, for
2313 // example, focus links if we have found text within the link. 1815 // example, focus links if we have found text within the link.
2314 Node* node = m_activeMatch->firstNode(); 1816 Node* node = activeMatch->firstNode();
2315 if (node && node->isInShadowTree()) { 1817 if (node && node->isInShadowTree()) {
2316 if (Node* host = node->shadowHost()) { 1818 if (Node* host = node->shadowHost()) {
2317 if (isHTMLInputElement(*host) || isHTMLTextAreaElement(*host)) 1819 if (isHTMLInputElement(*host) || isHTMLTextAreaElement(*host))
2318 node = host; 1820 node = host;
2319 } 1821 }
2320 } 1822 }
2321 for (; node; node = node->parentNode()) { 1823 for (; node; node = node->parentNode()) {
2322 if (!node->isElementNode()) 1824 if (!node->isElementNode())
2323 continue; 1825 continue;
2324 Element* element = toElement(node); 1826 Element* element = toElement(node);
2325 if (element->isFocusable()) { 1827 if (element->isFocusable()) {
2326 // Found a focusable parent node. Set the active match as the 1828 // Found a focusable parent node. Set the active match as the
2327 // selection and focus to the focusable node. 1829 // selection and focus to the focusable node.
2328 frame()->selection().setSelection(VisibleSelection(m_activeMatch .get())); 1830 frame()->selection().setSelection(VisibleSelection(activeMatch)) ;
2329 frame()->document()->setFocusedElement(element); 1831 frame()->document()->setFocusedElement(element);
2330 return; 1832 return;
2331 } 1833 }
2332 } 1834 }
2333 1835
2334 // Iterate over all the nodes in the range until we find a focusable nod e. 1836 // Iterate over all the nodes in the range until we find a focusable nod e.
2335 // This, for example, sets focus to the first link if you search for 1837 // This, for example, sets focus to the first link if you search for
2336 // text and text that is within one or more links. 1838 // text and text that is within one or more links.
2337 node = m_activeMatch->firstNode(); 1839 node = activeMatch->firstNode();
2338 for (; node && node != m_activeMatch->pastLastNode(); node = NodeTravers al::next(*node)) { 1840 for (; node && node != activeMatch->pastLastNode(); node = NodeTraversal ::next(*node)) {
2339 if (!node->isElementNode()) 1841 if (!node->isElementNode())
2340 continue; 1842 continue;
2341 Element* element = toElement(node); 1843 Element* element = toElement(node);
2342 if (element->isFocusable()) { 1844 if (element->isFocusable()) {
2343 frame()->document()->setFocusedElement(element); 1845 frame()->document()->setFocusedElement(element);
2344 return; 1846 return;
2345 } 1847 }
2346 } 1848 }
2347 1849
2348 // No node related to the active match was focusable, so set the 1850 // No node related to the active match was focusable, so set the
2349 // active match as the selection (so that when you end the Find session, 1851 // active match as the selection (so that when you end the Find session,
2350 // you'll have the last thing you found highlighted) and make sure that 1852 // you'll have the last thing you found highlighted) and make sure that
2351 // we have nothing focused (otherwise you might have text selected but 1853 // we have nothing focused (otherwise you might have text selected but
2352 // a link focused, which is weird). 1854 // a link focused, which is weird).
2353 frame()->selection().setSelection(VisibleSelection(m_activeMatch.get())) ; 1855 frame()->selection().setSelection(VisibleSelection(activeMatch));
2354 frame()->document()->setFocusedElement(nullptr); 1856 frame()->document()->setFocusedElement(nullptr);
2355 1857
2356 // Finally clear the active match, for two reasons: 1858 // Finally clear the active match, for two reasons:
2357 // We just finished the find 'session' and we don't want future (potenti ally 1859 // We just finished the find 'session' and we don't want future (potenti ally
2358 // unrelated) find 'sessions' operations to start at the same place. 1860 // unrelated) find 'sessions' operations to start at the same place.
2359 // The WebFrameImpl could get reused and the m_activeMatch could end up pointing 1861 // The WebFrameImpl could get reused and the activeMatch could end up po inting
2360 // to a document that is no longer valid. Keeping an invalid reference a round 1862 // to a document that is no longer valid. Keeping an invalid reference a round
2361 // is just asking for trouble. 1863 // is just asking for trouble.
2362 m_activeMatch = nullptr; 1864 m_textFinder->resetActiveMatch();
2363 } 1865 }
2364 } 1866 }
2365 1867
2366 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional) 1868 void WebFrameImpl::didFail(const ResourceError& error, bool wasProvisional)
2367 { 1869 {
2368 if (!client()) 1870 if (!client())
2369 return; 1871 return;
2370 WebURLError webError = error; 1872 WebURLError webError = error;
2371 if (wasProvisional) 1873 if (wasProvisional)
2372 client()->didFailProvisionalLoad(this, webError); 1874 client()->didFailProvisionalLoad(this, webError);
2373 else 1875 else
2374 client()->didFailLoad(this, webError); 1876 client()->didFailLoad(this, webError);
2375 } 1877 }
2376 1878
2377 void WebFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars) 1879 void WebFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars)
2378 { 1880 {
2379 frame()->view()->setCanHaveScrollbars(canHaveScrollbars); 1881 frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
2380 } 1882 }
2381 1883
2382 void WebFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, fl oat contentScaleFactor) 1884 void WebFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, fl oat contentScaleFactor)
2383 { 1885 {
2384 m_inputEventsOffsetForEmulation = offset; 1886 m_inputEventsOffsetForEmulation = offset;
2385 m_inputEventsScaleFactorForEmulation = contentScaleFactor; 1887 m_inputEventsScaleFactorForEmulation = contentScaleFactor;
2386 if (frame()->view()) 1888 if (frame()->view())
2387 frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffset ForEmulation, m_inputEventsScaleFactorForEmulation); 1889 frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffset ForEmulation, m_inputEventsScaleFactorForEmulation);
2388 } 1890 }
2389 1891
2390 void WebFrameImpl::invalidateArea(AreaToInvalidate area)
2391 {
2392 ASSERT(frame() && frame()->view());
2393 FrameView* view = frame()->view();
2394
2395 if ((area & InvalidateAll) == InvalidateAll)
2396 view->invalidateRect(view->frameRect());
2397 else {
2398 if ((area & InvalidateContentArea) == InvalidateContentArea) {
2399 IntRect contentArea(
2400 view->x(), view->y(), view->visibleWidth(), view->visibleHeight( ));
2401 IntRect frameRect = view->frameRect();
2402 contentArea.move(-frameRect.x(), -frameRect.y());
2403 view->invalidateRect(contentArea);
2404 }
2405 }
2406
2407 if ((area & InvalidateScrollbar) == InvalidateScrollbar) {
2408 // Invalidate the vertical scroll bar region for the view.
2409 Scrollbar* scrollbar = view->verticalScrollbar();
2410 if (scrollbar)
2411 scrollbar->invalidate();
2412 }
2413 }
2414
2415 void WebFrameImpl::addMarker(Range* range, bool activeMatch)
2416 {
2417 frame()->document()->markers().addTextMatchMarker(range, activeMatch);
2418 }
2419
2420 void WebFrameImpl::setMarkerActive(Range* range, bool active)
2421 {
2422 if (!range || range->collapsed(IGNORE_EXCEPTION))
2423 return;
2424 frame()->document()->markers().setMarkersActive(range, active);
2425 }
2426
2427 int WebFrameImpl::ordinalOfFirstMatchForFrame(WebFrameImpl* frame) const
2428 {
2429 int ordinal = 0;
2430 WebFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl();
2431 // Iterate from the main frame up to (but not including) |frame| and
2432 // add up the number of matches found so far.
2433 for (WebFrameImpl* it = mainFrameImpl; it != frame; it = toWebFrameImpl(it-> traverseNext(true))) {
2434 if (it->m_lastMatchCount > 0)
2435 ordinal += it->m_lastMatchCount;
2436 }
2437 return ordinal;
2438 }
2439
2440 bool WebFrameImpl::shouldScopeMatches(const String& searchText)
2441 {
2442 // Don't scope if we can't find a frame or a view.
2443 // The user may have closed the tab/application, so abort.
2444 // Also ignore detached frames, as many find operations report to the main f rame.
2445 if (!frame() || !frame()->view() || !frame()->page() || !hasVisibleContent() )
2446 return false;
2447
2448 ASSERT(frame()->document() && frame()->view());
2449
2450 // If the frame completed the scoping operation and found 0 matches the last
2451 // time it was searched, then we don't have to search it again if the user i s
2452 // just adding to the search string or sending the same search string again.
2453 if (m_lastFindRequestCompletedWithNoMatches && !m_lastSearchString.isEmpty() ) {
2454 // Check to see if the search string prefixes match.
2455 String previousSearchPrefix =
2456 searchText.substring(0, m_lastSearchString.length());
2457
2458 if (previousSearchPrefix == m_lastSearchString)
2459 return false; // Don't search this frame, it will be fruitless.
2460 }
2461
2462 return true;
2463 }
2464
2465 void WebFrameImpl::scopeStringMatchesSoon(int identifier, const WebString& searc hText, const WebFindOptions& options, bool reset)
2466 {
2467 m_deferredScopingWork.append(new DeferredScopeStringMatches(this, identifier , searchText, options, reset));
2468 }
2469
2470 void WebFrameImpl::callScopeStringMatches(DeferredScopeStringMatches* caller, in t identifier, const WebString& searchText, const WebFindOptions& options, bool r eset)
2471 {
2472 m_deferredScopingWork.remove(m_deferredScopingWork.find(caller));
2473 scopeStringMatches(identifier, searchText, options, reset);
2474
2475 // This needs to happen last since searchText is passed by reference.
2476 delete caller;
2477 }
2478
2479 void WebFrameImpl::invalidateIfNecessary()
2480 {
2481 if (m_lastMatchCount <= m_nextInvalidateAfter)
2482 return;
2483
2484 // FIXME: (http://b/1088165) Optimize the drawing of the tickmarks and
2485 // remove this. This calculation sets a milestone for when next to
2486 // invalidate the scrollbar and the content area. We do this so that we
2487 // don't spend too much time drawing the scrollbar over and over again.
2488 // Basically, up until the first 500 matches there is no throttle.
2489 // After the first 500 matches, we set set the milestone further and
2490 // further out (750, 1125, 1688, 2K, 3K).
2491 static const int startSlowingDownAfter = 500;
2492 static const int slowdown = 750;
2493
2494 int i = m_lastMatchCount / startSlowingDownAfter;
2495 m_nextInvalidateAfter += i * slowdown;
2496 invalidateArea(InvalidateScrollbar);
2497 }
2498
2499 void WebFrameImpl::loadJavaScriptURL(const KURL& url) 1892 void WebFrameImpl::loadJavaScriptURL(const KURL& url)
2500 { 1893 {
2501 // This is copied from ScriptController::executeScriptIfJavaScriptURL. 1894 // This is copied from ScriptController::executeScriptIfJavaScriptURL.
2502 // Unfortunately, we cannot just use that method since it is private, and 1895 // Unfortunately, we cannot just use that method since it is private, and
2503 // it also doesn't quite behave as we require it to for bookmarklets. The 1896 // it also doesn't quite behave as we require it to for bookmarklets. The
2504 // key difference is that we need to suppress loading the string result 1897 // key difference is that we need to suppress loading the string result
2505 // from evaluating the JS URL if executing the JS URL resulted in a 1898 // from evaluating the JS URL if executing the JS URL resulted in a
2506 // location change. We also allow a JS URL to be loaded even if scripts on 1899 // location change. We also allow a JS URL to be loaded even if scripts on
2507 // the page are otherwise disabled. 1900 // the page are otherwise disabled.
2508 1901
(...skipping 15 matching lines...) Expand all
2524 return; 1917 return;
2525 1918
2526 if (!frame()->navigationScheduler().locationChangePending()) 1919 if (!frame()->navigationScheduler().locationChangePending())
2527 frame()->document()->loader()->replaceDocument(scriptResult, ownerDocume nt.get()); 1920 frame()->document()->loader()->replaceDocument(scriptResult, ownerDocume nt.get());
2528 } 1921 }
2529 1922
2530 void WebFrameImpl::willDetachParent() 1923 void WebFrameImpl::willDetachParent()
2531 { 1924 {
2532 // Do not expect string scoping results from any frames that got detached 1925 // Do not expect string scoping results from any frames that got detached
2533 // in the middle of the operation. 1926 // in the middle of the operation.
2534 if (m_scopingInProgress) { 1927 if (m_textFinder && m_textFinder->scopingInProgress()) {
2535 1928
2536 // There is a possibility that the frame being detached was the only 1929 // There is a possibility that the frame being detached was the only
2537 // pending one. We need to make sure final replies can be sent. 1930 // pending one. We need to make sure final replies can be sent.
2538 flushCurrentScopingEffort(m_findRequestIdentifier); 1931 m_textFinder->flushCurrentScoping();
2539 1932
2540 cancelPendingScopingEffort(); 1933 m_textFinder->cancelPendingScopingEffort();
2541 } 1934 }
2542 } 1935 }
2543 1936
1937 WebFrameImpl* WebFrameImpl::activeMatchFrame() const
1938 {
1939 ASSERT(!parent());
1940
1941 if (m_textFinder)
1942 return m_textFinder->activeMatchFrame();
1943 return 0;
1944 }
1945
1946 WebCore::Range* WebFrameImpl::activeMatch() const
1947 {
1948 if (m_textFinder)
1949 return m_textFinder->activeMatch();
1950 return 0;
1951 }
1952
1953 TextFinder& WebFrameImpl::ensureTextFinder()
1954 {
1955 if (!m_textFinder)
1956 m_textFinder = TextFinder::create(*this);
1957
1958 return *m_textFinder;
1959 }
1960
1961 void WebFrameImpl::invalidateScrollbar() const
1962 {
1963 ASSERT(frame() && frame()->view());
1964 FrameView* view = frame()->view();
1965 // Invalidate the vertical scroll bar region for the view.
1966 Scrollbar* scrollbar = view->verticalScrollbar();
1967 if (scrollbar)
1968 scrollbar->invalidate();
1969 }
1970
1971 void WebFrameImpl::invalidateAll() const
1972 {
1973 ASSERT(frame() && frame()->view());
1974 FrameView* view = frame()->view();
1975 view->invalidateRect(view->frameRect());
1976 invalidateScrollbar();
1977 }
1978
2544 } // namespace blink 1979 } // 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