OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |