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