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