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