Exemplo n.º 1
0
int TextFinder::selectFindMatch(unsigned index, WebRect* selectionRect) {
  SECURITY_DCHECK(index < m_findMatchesCache.size());

  Range* range = m_findMatchesCache[index].m_range;
  if (!range->boundaryPointsValid() || !range->startContainer()->isConnected())
    return -1;

  // Check if the match is already selected.
  if (!m_currentActiveMatchFrame || !m_activeMatch ||
      !areRangesEqual(m_activeMatch.get(), range)) {
    m_activeMatchIndex = m_findMatchesCache[index].m_ordinal - 1;

    // Set this frame as the active frame (the one with the active highlight).
    m_currentActiveMatchFrame = true;
    ownerFrame().viewImpl()->setFocusedFrame(&ownerFrame());

    if (m_activeMatch)
      setMarkerActive(m_activeMatch.get(), false);
    m_activeMatch = range;
    setMarkerActive(m_activeMatch.get(), true);

    // Clear any user selection, to make sure Find Next continues on from the
    // match we just activated.
    ownerFrame().frame()->selection().clear();

    // Make sure no node is focused. See http://crbug.com/38700.
    ownerFrame().frame()->document()->clearFocusedElement();
  }

  IntRect activeMatchRect;
  IntRect activeMatchBoundingBox = enclosingIntRect(
      LayoutObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()));

  if (!activeMatchBoundingBox.isEmpty()) {
    if (m_activeMatch->firstNode() &&
        m_activeMatch->firstNode()->layoutObject()) {
      m_activeMatch->firstNode()->layoutObject()->scrollRectToVisible(
          LayoutRect(activeMatchBoundingBox),
          ScrollAlignment::alignCenterIfNeeded,
          ScrollAlignment::alignCenterIfNeeded, UserScroll);
    }

    // Zoom to the active match.
    activeMatchRect =
        ownerFrame().frameView()->contentsToRootFrame(activeMatchBoundingBox);
    ownerFrame().viewImpl()->zoomToFindInPageRect(activeMatchRect);
  }

  if (selectionRect)
    *selectionRect = activeMatchRect;

  return m_activeMatchIndex + 1;
}
Exemplo n.º 2
0
bool InPageSearchManager::findAndMarkText(const String& text, Range* range, Frame* frame, const FindOptions& options, bool isNewSearch)
{
    m_activeMatch = frame->editor()->findStringAndScrollToVisible(text, range, options);
    if (m_activeMatch) {
        setMarkerActive(m_activeMatch.get(), true /* active */);
        if (isNewSearch) {
            scopeStringMatches(text, true /* reset */);
            // FIXME: If it is a not new search, we need to calculate activeMatchIndex and notify client.
        }
        return true;
    }
    return false;
}
Exemplo n.º 3
0
int TextFinder::selectFindMatch(unsigned index, WebRect* selectionRect)
{
    ASSERT_WITH_SECURITY_IMPLICATION(index < m_findMatchesCache.size());

    RefPtrWillBeRawPtr<Range> range = m_findMatchesCache[index].m_range;
    if (!range->boundaryPointsValid() || !range->startContainer()->inDocument())
        return -1;

    // Check if the match is already selected.
    TextFinder& mainFrameTextFinder = m_ownerFrame.viewImpl()->mainFrameImpl()->ensureTextFinder();
    WebLocalFrameImpl* activeMatchFrame = mainFrameTextFinder.m_currentActiveMatchFrame;
    if (&m_ownerFrame != activeMatchFrame || !m_activeMatch || !areRangesEqual(m_activeMatch.get(), range.get())) {
        if (isActiveMatchFrameValid())
            activeMatchFrame->ensureTextFinder().setMatchMarkerActive(false);

        m_activeMatchIndexInCurrentFrame = m_findMatchesCache[index].m_ordinal - 1;

        // Set this frame as the active frame (the one with the active highlight).
        mainFrameTextFinder.m_currentActiveMatchFrame = &m_ownerFrame;
        m_ownerFrame.viewImpl()->setFocusedFrame(&m_ownerFrame);

        m_activeMatch = range.release();
        setMarkerActive(m_activeMatch.get(), true);

        // Clear any user selection, to make sure Find Next continues on from the match we just activated.
        m_ownerFrame.frame()->selection().clear();

        // Make sure no node is focused. See http://crbug.com/38700.
        m_ownerFrame.frame()->document()->setFocusedElement(nullptr);
    }

    IntRect activeMatchRect;
    IntRect activeMatchBoundingBox = enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()));

    if (!activeMatchBoundingBox.isEmpty()) {
        if (m_activeMatch->firstNode() && m_activeMatch->firstNode()->renderer()) {
            m_activeMatch->firstNode()->renderer()->scrollRectToVisible(
                activeMatchBoundingBox, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
        }

        // Zoom to the active match.
        activeMatchRect = m_ownerFrame.frameView()->contentsToWindow(activeMatchBoundingBox);
        m_ownerFrame.viewImpl()->zoomToFindInPageRect(activeMatchRect);
    }

    if (selectionRect)
        *selectionRect = activeMatchRect;

    return ordinalOfFirstMatch() + m_activeMatchIndexInCurrentFrame + 1;
}
Exemplo n.º 4
0
void TextFinder::clearActiveFindMatch() {
  m_currentActiveMatchFrame = false;
  setMarkerActive(m_activeMatch.get(), false);
  resetActiveMatch();
}
Exemplo n.º 5
0
bool TextFinder::find(int identifier,
                      const WebString& searchText,
                      const WebFindOptions& options,
                      bool wrapWithinFrame,
                      bool* activeNow) {
  if (!options.findNext)
    unmarkAllTextMatches();
  else
    setMarkerActive(m_activeMatch.get(), false);

  if (m_activeMatch &&
      &m_activeMatch->ownerDocument() != ownerFrame().frame()->document())
    m_activeMatch = nullptr;

  // If the user has selected something since the last Find operation we want
  // to start from there. Otherwise, we start searching from where the last Find
  // operation left off (either a Find or a FindNext operation).
  VisibleSelection selection(ownerFrame().frame()->selection().selection());
  bool activeSelection = !selection.isNone();
  if (activeSelection) {
    m_activeMatch = firstRangeOf(selection);
    ownerFrame().frame()->selection().clear();
  }

  DCHECK(ownerFrame().frame());
  DCHECK(ownerFrame().frame()->view());
  const FindOptions findOptions =
      (options.forward ? 0 : Backwards) |
      (options.matchCase ? 0 : CaseInsensitive) |
      (wrapWithinFrame ? WrapAround : 0) |
      (options.wordStart ? AtWordStarts : 0) |
      (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0) |
      (options.findNext ? 0 : StartInSelection);
  m_activeMatch = ownerFrame().frame()->editor().findStringAndScrollToVisible(
      searchText, m_activeMatch.get(), findOptions);

  if (!m_activeMatch) {
    // If we're finding next the next active match might not be in the current
    // frame.  In this case we don't want to clear the matches cache.
    if (!options.findNext)
      clearFindMatchesCache();

    ownerFrame().frameView()->invalidatePaintForTickmarks();
    return false;
  }

  // If the user is browsing a page with autosizing, adjust the zoom to the
  // column where the next hit has been found. Doing this when autosizing is
  // not set will result in a zoom reset on small devices.
  if (ownerFrame()
          .frame()
          ->document()
          ->textAutosizer()
          ->pageNeedsAutosizing()) {
    ownerFrame().viewImpl()->zoomToFindInPageRect(
        ownerFrame().frameView()->contentsToRootFrame(
            enclosingIntRect(LayoutObject::absoluteBoundingBoxRectForRange(
                m_activeMatch.get()))));
  }

  bool wasActiveFrame = m_currentActiveMatchFrame;
  m_currentActiveMatchFrame = true;

  bool isActive = setMarkerActive(m_activeMatch.get(), true);
  if (activeNow)
    *activeNow = isActive;

  // Make sure no node is focused. See http://crbug.com/38700.
  ownerFrame().frame()->document()->clearFocusedElement();

  // Set this frame as focused.
  ownerFrame().viewImpl()->setFocusedFrame(&ownerFrame());

  if (!options.findNext || activeSelection || !isActive) {
    // This is either an initial Find operation, a Find-next from a new
    // start point due to a selection, or new matches were found during
    // Find-next due to DOM alteration (that couldn't be set as active), so
    // we set the flag to ask the scoping effort to find the active rect for
    // us and report it back to the UI.
    m_locatingActiveRect = true;
  } else {
    if (!wasActiveFrame) {
      if (options.forward)
        m_activeMatchIndex = 0;
      else
        m_activeMatchIndex = m_lastMatchCount - 1;
    } else {
      if (options.forward)
        ++m_activeMatchIndex;
      else
        --m_activeMatchIndex;

      if (m_activeMatchIndex + 1 > m_lastMatchCount)
        m_activeMatchIndex = 0;
      else if (m_activeMatchIndex < 0)
        m_activeMatchIndex = m_lastMatchCount - 1;
    }
    WebRect selectionRect = ownerFrame().frameView()->contentsToRootFrame(
        m_activeMatch->boundingBox());
    reportFindInPageSelection(selectionRect, m_activeMatchIndex + 1,
                              identifier);
  }

  return true;
}
Exemplo n.º 6
0
bool TextFinder::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect)
{
    if (!m_ownerFrame.frame() || !m_ownerFrame.frame()->page())
        return false;

    WebLocalFrameImpl* mainFrameImpl = m_ownerFrame.viewImpl()->mainFrameImpl();

    if (!options.findNext)
        m_ownerFrame.frame()->page()->unmarkAllTextMatches();
    else
        setMarkerActive(m_activeMatch.get(), false);

    if (m_activeMatch && &m_activeMatch->ownerDocument() != m_ownerFrame.frame()->document())
        m_activeMatch = nullptr;

    // If the user has selected something since the last Find operation we want
    // to start from there. Otherwise, we start searching from where the last Find
    // operation left off (either a Find or a FindNext operation).
    VisibleSelection selection(m_ownerFrame.frame()->selection().selection());
    bool activeSelection = !selection.isNone();
    if (activeSelection) {
        m_activeMatch = selection.firstRange().get();
        m_ownerFrame.frame()->selection().clear();
    }

    ASSERT(m_ownerFrame.frame() && m_ownerFrame.frame()->view());
    const FindOptions findOptions = (options.forward ? 0 : Backwards)
        | (options.matchCase ? 0 : CaseInsensitive)
        | (wrapWithinFrame ? WrapAround : 0)
        | (options.wordStart ? AtWordStarts : 0)
        | (options.medialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0)
        | (options.findNext ? 0 : StartInSelection);
    m_activeMatch = m_ownerFrame.frame()->editor().findStringAndScrollToVisible(searchText, m_activeMatch.get(), findOptions);

    if (!m_activeMatch) {
        // If we're finding next the next active match might not be in the current frame.
        // In this case we don't want to clear the matches cache.
        if (!options.findNext)
            clearFindMatchesCache();

        m_ownerFrame.invalidateAll();
        return false;
    }

#if OS(ANDROID)
    m_ownerFrame.viewImpl()->zoomToFindInPageRect(m_ownerFrame.frameView()->contentsToWindow(enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(m_activeMatch.get()))));
#endif

    setMarkerActive(m_activeMatch.get(), true);
    WebLocalFrameImpl* oldActiveFrame = mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame;
    mainFrameImpl->ensureTextFinder().m_currentActiveMatchFrame = &m_ownerFrame;

    // Make sure no node is focused. See http://crbug.com/38700.
    m_ownerFrame.frame()->document()->setFocusedElement(nullptr);

    if (!options.findNext || activeSelection) {
        // This is either a Find operation or a Find-next from a new start point
        // due to a selection, so we set the flag to ask the scoping effort
        // to find the active rect for us and report it back to the UI.
        m_locatingActiveRect = true;
    } else {
        if (oldActiveFrame != &m_ownerFrame) {
            if (options.forward)
                m_activeMatchIndexInCurrentFrame = 0;
            else
                m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
        } else {
            if (options.forward)
                ++m_activeMatchIndexInCurrentFrame;
            else
                --m_activeMatchIndexInCurrentFrame;

            if (m_activeMatchIndexInCurrentFrame + 1 > m_lastMatchCount)
                m_activeMatchIndexInCurrentFrame = 0;
            if (m_activeMatchIndexInCurrentFrame == -1)
                m_activeMatchIndexInCurrentFrame = m_lastMatchCount - 1;
        }
        if (selectionRect) {
            *selectionRect = m_ownerFrame.frameView()->contentsToWindow(m_activeMatch->boundingBox());
            reportFindInPageSelection(*selectionRect, m_activeMatchIndexInCurrentFrame + 1, identifier);
        }
    }

    return true;
}
Exemplo n.º 7
0
void TextFinder::setMatchMarkerActive(bool active)
{
    setMarkerActive(m_activeMatch.get(), active);
}
Exemplo n.º 8
0
bool InPageSearchManager::findNextString(const String& text, bool forward)
{
    if (!text.length()) {
        clearTextMatches();
        cancelPendingScopingEffort();
        m_activeSearchString = String();
        return false;
    }

    if (!shouldSearchForText(text)) {
        m_activeSearchString = text;
        return false;
    }

    // Validate the range in case any node has been removed since last search.
    if (m_activeMatch && !m_activeMatch->boundaryPointsValid())
        m_activeMatch = 0;

    RefPtr<Range> searchStartingPoint(m_activeMatch);
    bool newSearch = m_activeSearchString != text;
    if (newSearch) { // Start a new search.
        m_activeSearchString = text;
        cancelPendingScopingEffort();
        m_webPage->m_page->unmarkAllTextMatches();
    } else { // Search same string for next occurrence.
        setMarkerActive(m_activeMatch.get(), false /* active */);
        // Searching for same string should start from the end of last match.
        if (m_activeMatch) {
            if (forward)
                searchStartingPoint->setStart(searchStartingPoint->endPosition());
            else
                searchStartingPoint->setEnd(searchStartingPoint->startPosition());
        }
    }

    // If there is any active selection, new search should start from the beginning of it.
    VisibleSelection selection = m_webPage->focusedOrMainFrame()->selection()->selection();
    if (!selection.isNone()) {
        searchStartingPoint = selection.firstRange().get();
        m_webPage->focusedOrMainFrame()->selection()->clear();
    }

    Frame* currentActiveMatchFrame = selection.isNone() && m_activeMatch ? m_activeMatch->ownerDocument()->frame() : m_webPage->focusedOrMainFrame();

    const FindOptions findOptions = (forward ? 0 : Backwards)
        | CaseInsensitive
        | StartInSelection;

    if (findAndMarkText(text, searchStartingPoint.get(), currentActiveMatchFrame, findOptions, newSearch))
        return true;

    Frame* startFrame = currentActiveMatchFrame;
    do {
        currentActiveMatchFrame = DOMSupport::incrementFrame(currentActiveMatchFrame, forward, true /* wrapFlag */);
        if (findAndMarkText(text, 0, currentActiveMatchFrame, findOptions, newSearch))
            return true;
    } while (currentActiveMatchFrame && startFrame != currentActiveMatchFrame);

    clearTextMatches();

    // FIXME: We need to notify client here.
    return false;
}