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

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

Powered by Google App Engine
This is Rietveld 408576698