/*
 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/editing/FrameSelection.h"

#include <stdio.h>
#include "bindings/core/v8/ExceptionState.h"
#include "core/HTMLNames.h"
#include "core/css/StylePropertySet.h"
#include "core/dom/AXObjectCache.h"
#include "core/dom/CharacterData.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/NodeWithIndex.h"
#include "core/dom/Text.h"
#include "core/editing/CaretDisplayItemClient.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/FrameCaret.h"
#include "core/editing/GranularityStrategy.h"
#include "core/editing/InputMethodController.h"
#include "core/editing/LayoutSelection.h"
#include "core/editing/SelectionController.h"
#include "core/editing/SelectionEditor.h"
#include "core/editing/SelectionModifier.h"
#include "core/editing/TextAffinity.h"
#include "core/editing/VisibleUnits.h"
#include "core/editing/commands/TypingCommand.h"
#include "core/editing/iterators/TextIterator.h"
#include "core/editing/serializers/Serialization.h"
#include "core/editing/spellcheck/SpellChecker.h"
#include "core/events/Event.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLBodyElement.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/input/EventHandler.h"
#include "core/layout/HitTestRequest.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/loader/DocumentLoader.h"
#include "core/page/EditorClient.h"
#include "core/page/FocusController.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "core/page/SpatialNavigation.h"
#include "core/paint/PaintLayer.h"
#include "platform/SecureTextInput.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/text/UnicodeUtilities.h"
#include "wtf/PtrUtil.h"
#include "wtf/text/CString.h"

#define EDIT_DEBUG 0

namespace blink {

using namespace HTMLNames;

static inline bool shouldAlwaysUseDirectionalSelection(LocalFrame* frame) {
  return frame->editor().behavior().shouldConsiderSelectionAsDirectional();
}

FrameSelection::FrameSelection(LocalFrame& frame)
    : m_frame(frame),
      m_layoutSelection(LayoutSelection::create(*this)),
      m_selectionEditor(SelectionEditor::create(frame)),
      m_granularity(CharacterGranularity),
      m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation()),
      m_focused(frame.page() &&
                frame.page()->focusController().focusedFrame() == frame),
      m_frameCaret(new FrameCaret(frame, *m_selectionEditor)) {}

FrameSelection::~FrameSelection() {}

const DisplayItemClient& FrameSelection::caretDisplayItemClientForTesting()
    const {
  return m_frameCaret->displayItemClient();
}

Document& FrameSelection::document() const {
  DCHECK(lifecycleContext());
  return *lifecycleContext();
}

bool FrameSelection::isHandleVisible() const {
  return selectionInDOMTree().isHandleVisible();
}

const VisibleSelection& FrameSelection::computeVisibleSelectionInDOMTree()
    const {
  return m_selectionEditor->computeVisibleSelectionInDOMTree();
}

const VisibleSelectionInFlatTree&
FrameSelection::computeVisibleSelectionInFlatTree() const {
  return m_selectionEditor->computeVisibleSelectionInFlatTree();
}

const SelectionInDOMTree& FrameSelection::selectionInDOMTree() const {
  return m_selectionEditor->selectionInDOMTree();
}

Element* FrameSelection::rootEditableElementOrDocumentElement() const {
  Element* selectionRoot =
      computeVisibleSelectionInDOMTreeDeprecated().rootEditableElement();
  return selectionRoot ? selectionRoot : document().documentElement();
}

// TODO(yosin): We should move |rootEditableElementOrTreeScopeRootNodeOf()| to
// "EditingUtilities.cpp"
ContainerNode* rootEditableElementOrTreeScopeRootNodeOf(
    const Position& position) {
  Element* selectionRoot = rootEditableElementOf(position);
  if (selectionRoot)
    return selectionRoot;

  Node* const node = position.computeContainerNode();
  return node ? &node->treeScope().rootNode() : 0;
}

const VisibleSelection&
FrameSelection::computeVisibleSelectionInDOMTreeDeprecated() const {
  // TODO(yosin): We should hoist updateStyleAndLayoutIgnorePendingStylesheets
  // to caller. See http://crbug.com/590369 for more details.
  document().updateStyleAndLayoutIgnorePendingStylesheets();
  return computeVisibleSelectionInDOMTree();
}

const VisibleSelectionInFlatTree& FrameSelection::selectionInFlatTree() const {
  return computeVisibleSelectionInFlatTree();
}

void FrameSelection::moveCaretSelection(const IntPoint& point) {
  DCHECK(!document().needsLayoutTreeUpdate());

  Element* const editable =
      computeVisibleSelectionInDOMTree().rootEditableElement();
  if (!editable)
    return;

  const VisiblePosition position =
      visiblePositionForContentsPoint(point, frame());
  SelectionInDOMTree::Builder builder;
  builder.setIsDirectional(selectionInDOMTree().isDirectional());
  builder.setIsHandleVisible(true);
  if (position.isNotNull())
    builder.collapse(position.toPositionWithAffinity());
  setSelection(builder.build(), CloseTyping | ClearTypingStyle | UserTriggered);
}

void FrameSelection::setSelection(const SelectionInDOMTree& passedSelection,
                                  SetSelectionOptions options,
                                  CursorAlignOnScroll align,
                                  TextGranularity granularity) {
  if (setSelectionDeprecated(passedSelection, options, granularity))
    didSetSelectionDeprecated(options, align);
}

bool FrameSelection::setSelectionDeprecated(
    const SelectionInDOMTree& passedSelection,
    SetSelectionOptions options,
    TextGranularity granularity) {
  DCHECK(isAvailable());
  passedSelection.assertValidFor(document());

  SelectionInDOMTree::Builder builder(passedSelection);
  if (shouldAlwaysUseDirectionalSelection(m_frame))
    builder.setIsDirectional(true);
  SelectionInDOMTree newSelection = builder.build();
  if (m_granularityStrategy &&
      (options & FrameSelection::DoNotClearStrategy) == 0)
    m_granularityStrategy->Clear();
  bool closeTyping = options & CloseTyping;
  bool shouldClearTypingStyle = options & ClearTypingStyle;
  m_granularity = granularity;

  // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
  // |Editor| class.
  if (closeTyping)
    TypingCommand::closeTyping(m_frame);

  if (shouldClearTypingStyle)
    m_frame->editor().clearTypingStyle();

  const SelectionInDOMTree oldSelectionInDOMTree =
      m_selectionEditor->selectionInDOMTree();
  if (oldSelectionInDOMTree == newSelection)
    return false;
  m_selectionEditor->setSelection(newSelection);
  scheduleVisualUpdateForPaintInvalidationIfNeeded();

  const Document& currentDocument = document();
  // TODO(yosin): We should get rid of unsued |options| for
  // |Editor::respondToChangedSelection()|.
  // Note: Since, setting focus can modify DOM tree, we should use
  // |oldSelection| before setting focus
  m_frame->editor().respondToChangedSelection(
      oldSelectionInDOMTree.computeStartPosition(), options);
  DCHECK_EQ(currentDocument, document());
  return true;
}

void FrameSelection::didSetSelectionDeprecated(SetSelectionOptions options,
                                               CursorAlignOnScroll align) {
  const Document& currentDocument = document();
  if (!selectionInDOMTree().isNone() && !(options & DoNotSetFocus)) {
    setFocusedNodeIfNeeded();
    // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and
    // "FocusIn", |m_frame| may associate to another document.
    if (!isAvailable() || document() != currentDocument) {
      // Once we get test case to reach here, we should change this
      // if-statement to |DCHECK()|.
      NOTREACHED();
      return;
    }
  }

  m_frameCaret->stopCaretBlinkTimer();
  updateAppearance();

  // Always clear the x position used for vertical arrow navigation.
  // It will be restored by the vertical arrow navigation code if necessary.
  m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();

  // TODO(yosin): Can we move this to at end of this function?
  // This may dispatch a synchronous focus-related events.
  if (!(options & DoNotSetFocus)) {
    selectFrameElementInParentIfFullySelected();
    if (!isAvailable() || document() != currentDocument) {
      // editing/selection/selectallchildren-crash.html and
      // editing/selection/longpress-selection-in-iframe-removed-crash.html
      // reach here.
      return;
    }
  }

  EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
  notifyLayoutObjectOfSelectionChange(userTriggered);
  if (userTriggered == UserTriggered) {
    ScrollAlignment alignment;

    if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
      alignment = (align == CursorAlignOnScroll::Always)
                      ? ScrollAlignment::alignCenterAlways
                      : ScrollAlignment::alignCenterIfNeeded;
    else
      alignment = (align == CursorAlignOnScroll::Always)
                      ? ScrollAlignment::alignTopAlways
                      : ScrollAlignment::alignToEdgeIfNeeded;

    revealSelection(alignment, RevealExtent);
  }

  notifyAccessibilityForSelectionChange();
  notifyCompositorForSelectionChange();
  notifyEventHandlerForSelectionChange();
  m_frame->domWindow()->enqueueDocumentEvent(
      Event::create(EventTypeNames::selectionchange));
}

void FrameSelection::setSelection(const SelectionInFlatTree& newSelection,
                                  SetSelectionOptions options,
                                  CursorAlignOnScroll align,
                                  TextGranularity granularity) {
  newSelection.assertValidFor(document());
  SelectionInDOMTree::Builder builder;
  builder.setAffinity(newSelection.affinity())
      .setBaseAndExtent(toPositionInDOMTree(newSelection.base()),
                        toPositionInDOMTree(newSelection.extent()))
      .setGranularity(newSelection.granularity())
      .setIsDirectional(newSelection.isDirectional())
      .setIsHandleVisible(newSelection.isHandleVisible())
      .setHasTrailingWhitespace(newSelection.hasTrailingWhitespace());
  return setSelection(builder.build(), options, align, granularity);
}

void FrameSelection::nodeChildrenWillBeRemoved(ContainerNode& container) {
  if (!container.inActiveDocument())
    return;
  // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
  // |Editor| class.
  if (!document().isRunningExecCommand())
    TypingCommand::closeTyping(m_frame);
}

void FrameSelection::nodeWillBeRemoved(Node& node) {
  // There can't be a selection inside a fragment, so if a fragment's node is
  // being removed, the selection in the document that created the fragment
  // needs no adjustment.
  if (!node.inActiveDocument())
    return;
  // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
  // |Editor| class.
  if (!document().isRunningExecCommand())
    TypingCommand::closeTyping(m_frame);
}

void FrameSelection::didChangeFocus() {
  // Hits in
  // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disabled.html
  DisableCompositingQueryAsserts disabler;
  updateAppearance();
}

static DispatchEventResult dispatchSelectStart(
    const VisibleSelection& selection) {
  Node* selectStartTarget = selection.extent().computeContainerNode();
  if (!selectStartTarget)
    return DispatchEventResult::NotCanceled;

  return selectStartTarget->dispatchEvent(
      Event::createCancelableBubble(EventTypeNames::selectstart));
}

// The return value of |FrameSelection::modify()| is different based on
// value of |userTriggered| parameter.
// When |userTriggered| is |userTriggered|, |modify()| returns false if
// "selectstart" event is dispatched and canceled, otherwise returns true.
// When |userTriggered| is |NotUserTrigged|, return value specifies whether
// selection is modified or not.
bool FrameSelection::modify(EAlteration alter,
                            SelectionDirection direction,
                            TextGranularity granularity,
                            EUserTriggered userTriggered) {
  SelectionModifier selectionModifier(
      *frame(), computeVisibleSelectionInDOMTreeDeprecated(),
      m_xPosForVerticalArrowNavigation);
  const bool modified = selectionModifier.modify(alter, direction, granularity);
  if (userTriggered == UserTriggered &&
      selectionModifier.selection().isRange() &&
      computeVisibleSelectionInDOMTreeDeprecated().isCaret() &&
      dispatchSelectStart(computeVisibleSelectionInDOMTreeDeprecated()) !=
          DispatchEventResult::NotCanceled) {
    return false;
  }
  if (!modified) {
    if (userTriggered == NotUserTriggered)
      return false;
    // If spatial navigation enabled, focus navigator will move focus to
    // another element. See snav-input.html and snav-textarea.html
    if (isSpatialNavigationEnabled(m_frame))
      return false;
    // Even if selection isn't changed, we prevent to default action, e.g.
    // scroll window when caret is at end of content editable.
    return true;
  }

  const SetSelectionOptions options =
      CloseTyping | ClearTypingStyle | userTriggered;
  setSelection(selectionModifier.selection().asSelection(), options);

  if (granularity == LineGranularity || granularity == ParagraphGranularity)
    m_xPosForVerticalArrowNavigation =
        selectionModifier.xPosForVerticalArrowNavigation();

  if (userTriggered == UserTriggered)
    m_granularity = CharacterGranularity;

  scheduleVisualUpdateForPaintInvalidationIfNeeded();

  return true;
}

bool FrameSelection::modify(EAlteration alter,
                            unsigned verticalDistance,
                            VerticalDirection direction) {
  SelectionModifier selectionModifier(
      *frame(), computeVisibleSelectionInDOMTreeDeprecated());
  if (!selectionModifier.modifyWithPageGranularity(alter, verticalDistance,
                                                   direction)) {
    return false;
  }

  setSelection(selectionModifier.selection().asSelection(),
               CloseTyping | ClearTypingStyle | UserTriggered,
               alter == AlterationMove ? CursorAlignOnScroll::Always
                                       : CursorAlignOnScroll::IfNeeded);

  m_granularity = CharacterGranularity;

  return true;
}

void FrameSelection::clear() {
  m_granularity = CharacterGranularity;
  if (m_granularityStrategy)
    m_granularityStrategy->Clear();
  setSelection(SelectionInDOMTree());
}

void FrameSelection::documentAttached(Document* document) {
  DCHECK(document);
  m_useSecureKeyboardEntryWhenActive = false;
  m_selectionEditor->documentAttached(document);
  setContext(document);
}

void FrameSelection::contextDestroyed(Document* document) {
  m_granularity = CharacterGranularity;

  LayoutViewItem view = m_frame->contentLayoutItem();
  if (!view.isNull())
    view.clearSelection();

  m_frame->editor().clearTypingStyle();
}

void FrameSelection::clearPreviousCaretVisualRect(const LayoutBlock& block) {
  m_frameCaret->clearPreviousVisualRect(block);
}

void FrameSelection::layoutBlockWillBeDestroyed(const LayoutBlock& block) {
  m_frameCaret->layoutBlockWillBeDestroyed(block);
}

void FrameSelection::updateStyleAndLayoutIfNeeded() {
  m_frameCaret->updateStyleAndLayoutIfNeeded();
}

void FrameSelection::invalidatePaintIfNeeded(
    const LayoutBlock& block,
    const PaintInvalidatorContext& context) {
  m_frameCaret->invalidatePaintIfNeeded(block, context);
}

bool FrameSelection::shouldPaintCaret(const LayoutBlock& block) const {
  DCHECK_GE(document().lifecycle().state(), DocumentLifecycle::LayoutClean);
  bool result = m_frameCaret->shouldPaintCaret(block);
  DCHECK(!result ||
         (computeVisibleSelectionInDOMTreeDeprecated().isCaret() &&
          computeVisibleSelectionInDOMTree().hasEditableStyle()));
  return result;
}

IntRect FrameSelection::absoluteCaretBounds() {
  DCHECK(computeVisibleSelectionInDOMTree().isValidFor(*m_frame->document()));
  return m_frameCaret->absoluteCaretBounds();
}

void FrameSelection::paintCaret(GraphicsContext& context,
                                const LayoutPoint& paintOffset) {
  m_frameCaret->paintCaret(context, paintOffset);
}

bool FrameSelection::contains(const LayoutPoint& point) {
  if (document().layoutViewItem().isNull())
    return false;

  // Treat a collapsed selection like no selection.
  const VisibleSelectionInFlatTree& visibleSelection =
      computeVisibleSelectionInFlatTree();
  if (!visibleSelection.isRange())
    return false;

  HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
  HitTestResult result(request, point);
  document().layoutViewItem().hitTest(result);
  Node* innerNode = result.innerNode();
  if (!innerNode || !innerNode->layoutObject())
    return false;

  const VisiblePositionInFlatTree& visiblePos =
      createVisiblePosition(fromPositionInDOMTree<EditingInFlatTreeStrategy>(
          innerNode->layoutObject()->positionForPoint(result.localPoint())));
  if (visiblePos.isNull())
    return false;

  const VisiblePositionInFlatTree& visibleStart =
      visibleSelection.visibleStart();
  const VisiblePositionInFlatTree& visibleEnd = visibleSelection.visibleEnd();
  if (visibleStart.isNull() || visibleEnd.isNull())
    return false;

  const PositionInFlatTree& start = visibleStart.deepEquivalent();
  const PositionInFlatTree& end = visibleEnd.deepEquivalent();
  const PositionInFlatTree& pos = visiblePos.deepEquivalent();
  return start.compareTo(pos) <= 0 && pos.compareTo(end) <= 0;
}

// Workaround for the fact that it's hard to delete a frame.
// Call this after doing user-triggered selections to make it easy to delete the
// frame you entirely selected. Can't do this implicitly as part of every
// setSelection call because in some contexts it might not be good for the focus
// to move to another frame. So instead we call it from places where we are
// selecting with the mouse or the keyboard after setting the selection.
void FrameSelection::selectFrameElementInParentIfFullySelected() {
  // Find the parent frame; if there is none, then we have nothing to do.
  Frame* parent = m_frame->tree().parent();
  if (!parent)
    return;
  Page* page = m_frame->page();
  if (!page)
    return;

  // Check if the selection contains the entire frame contents; if not, then
  // there is nothing to do.
  if (selectionInDOMTree().selectionTypeWithLegacyGranularity() !=
      RangeSelection) {
    return;
  }

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  document().updateStyleAndLayoutIgnorePendingStylesheets();

  if (!isStartOfDocument(computeVisibleSelectionInDOMTree().visibleStart()))
    return;
  if (!isEndOfDocument(computeVisibleSelectionInDOMTree().visibleEnd()))
    return;

  // FIXME: This is not yet implemented for cross-process frame relationships.
  if (!parent->isLocalFrame())
    return;

  // Get to the <iframe> or <frame> (or even <object>) element in the parent
  // frame.
  // FIXME: Doesn't work for OOPI.
  HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
  if (!ownerElement)
    return;
  ContainerNode* ownerElementParent = ownerElement->parentNode();
  if (!ownerElementParent)
    return;

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  ownerElementParent->document().updateStyleAndLayoutIgnorePendingStylesheets();

  // This method's purpose is it to make it easier to select iframes (in order
  // to delete them).  Don't do anything if the iframe isn't deletable.
  if (!blink::hasEditableStyle(*ownerElementParent))
    return;

  // Create compute positions before and after the element.
  unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
  VisiblePosition beforeOwnerElement = createVisiblePosition(
      Position(ownerElementParent, ownerElementNodeIndex));
  VisiblePosition afterOwnerElement = createVisiblePosition(
      Position(ownerElementParent, ownerElementNodeIndex + 1),
      VP_UPSTREAM_IF_POSSIBLE);

  SelectionInDOMTree::Builder builder;
  builder
      .setBaseAndExtentDeprecated(beforeOwnerElement.deepEquivalent(),
                                  afterOwnerElement.deepEquivalent())
      .setAffinity(beforeOwnerElement.affinity());

  // Focus on the parent frame, and then select from before this element to
  // after.
  VisibleSelection newSelection = createVisibleSelection(builder.build());
  // TODO(yosin): We should call |FocusController::setFocusedFrame()| before
  // |createVisibleSelection()|.
  page->focusController().setFocusedFrame(parent);
  // setFocusedFrame can dispatch synchronous focus/blur events.  The document
  // tree might be modified.
  if (newSelection.isNonOrphanedCaretOrRange())
    toLocalFrame(parent)->selection().setSelection(newSelection.asSelection());
}

// Returns a shadow tree node for legacy shadow trees, a child of the
// ShadowRoot node for new shadow trees, or 0 for non-shadow trees.
static Node* nonBoundaryShadowTreeRootNode(const Position& position) {
  return position.anchorNode() && !position.anchorNode()->isShadowRoot()
             ? position.anchorNode()->nonBoundaryShadowTreeRootNode()
             : nullptr;
}

void FrameSelection::selectAll() {
  if (isHTMLSelectElement(document().focusedElement())) {
    HTMLSelectElement* selectElement =
        toHTMLSelectElement(document().focusedElement());
    if (selectElement->canSelectAll()) {
      selectElement->selectAll();
      return;
    }
  }

  Node* root = nullptr;
  Node* selectStartTarget = nullptr;
  if (computeVisibleSelectionInDOMTreeDeprecated().isContentEditable()) {
    root = highestEditableRoot(
        computeVisibleSelectionInDOMTreeDeprecated().start());
    if (Node* shadowRoot = nonBoundaryShadowTreeRootNode(
            computeVisibleSelectionInDOMTreeDeprecated().start()))
      selectStartTarget = shadowRoot->ownerShadowHost();
    else
      selectStartTarget = root;
  } else {
    root = nonBoundaryShadowTreeRootNode(
        computeVisibleSelectionInDOMTreeDeprecated().start());
    if (root) {
      selectStartTarget = root->ownerShadowHost();
    } else {
      root = document().documentElement();
      selectStartTarget = document().body();
    }
  }
  if (!root || editingIgnoresContent(*root))
    return;

  if (selectStartTarget) {
    const Document& expectedDocument = document();
    if (selectStartTarget->dispatchEvent(Event::createCancelableBubble(
            EventTypeNames::selectstart)) != DispatchEventResult::NotCanceled)
      return;
    // |root| may be detached due to selectstart event.
    if (!root->isConnected() || expectedDocument != root->document())
      return;
  }

  setSelection(SelectionInDOMTree::Builder()
                   .selectAllChildren(*root)
                   .setIsHandleVisible(isHandleVisible())
                   .build());
  selectFrameElementInParentIfFullySelected();
  notifyLayoutObjectOfSelectionChange(UserTriggered);
}

bool FrameSelection::setSelectedRange(const EphemeralRange& range,
                                      TextAffinity affinity,
                                      SelectionDirectionalMode directional,
                                      SetSelectionOptions options) {
  if (range.isNull())
    return false;
  setSelection(SelectionInDOMTree::Builder()
                   .setBaseAndExtent(range)
                   .setAffinity(affinity)
                   .setIsHandleVisible(isHandleVisible())
                   .setIsDirectional(directional ==
                                     SelectionDirectionalMode::Directional)
                   .build(),
               options);
  return true;
}

void FrameSelection::notifyAccessibilityForSelectionChange() {
  if (selectionInDOMTree().isNone())
    return;
  AXObjectCache* cache = document().existingAXObjectCache();
  if (!cache)
    return;
  const Position& start = selectionInDOMTree().computeStartPosition();
  cache->selectionChanged(start.computeContainerNode());
}

void FrameSelection::notifyCompositorForSelectionChange() {
  if (!RuntimeEnabledFeatures::compositedSelectionUpdateEnabled())
    return;

  scheduleVisualUpdate();
}

void FrameSelection::notifyEventHandlerForSelectionChange() {
  m_frame->eventHandler().selectionController().notifySelectionChanged();
}

void FrameSelection::focusedOrActiveStateChanged() {
  bool activeAndFocused = isFocusedAndActive();

  // Trigger style invalidation from the focused element. Even though
  // the focused element hasn't changed, the evaluation of focus pseudo
  // selectors are dependent on whether the frame is focused and active.
  if (Element* element = document().focusedElement())
    element->focusStateChanged();

  document().updateStyleAndLayoutTree();

  // Because LayoutObject::selectionBackgroundColor() and
  // LayoutObject::selectionForegroundColor() check if the frame is active,
  // we have to update places those colors were painted.
  LayoutViewItem view = document().layoutViewItem();
  if (!view.isNull())
    view.invalidatePaintForSelection();

  // Caret appears in the active frame.
  if (activeAndFocused)
    setSelectionFromNone();
  else
    m_frame->spellChecker().spellCheckAfterBlur();
  m_frameCaret->setCaretVisibility(activeAndFocused ? CaretVisibility::Visible
                                                    : CaretVisibility::Hidden);

  // Update for caps lock state
  m_frame->eventHandler().capsLockStateMayHaveChanged();

  // Secure keyboard entry is set by the active frame.
  if (m_useSecureKeyboardEntryWhenActive)
    setUseSecureKeyboardEntry(activeAndFocused);
}

void FrameSelection::pageActivationChanged() {
  focusedOrActiveStateChanged();
}

void FrameSelection::updateSecureKeyboardEntryIfActive() {
  if (!isFocusedAndActive())
    return;
  setUseSecureKeyboardEntry(m_useSecureKeyboardEntryWhenActive);
}

void FrameSelection::setUseSecureKeyboardEntryWhenActive(
    bool usesSecureKeyboard) {
  if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard)
    return;
  m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard;
  updateSecureKeyboardEntryIfActive();
}

void FrameSelection::setUseSecureKeyboardEntry(bool enable) {
  if (enable)
    enableSecureTextInput();
  else
    disableSecureTextInput();
}

void FrameSelection::setFocused(bool flag) {
  if (m_focused == flag)
    return;
  m_focused = flag;

  focusedOrActiveStateChanged();
}

bool FrameSelection::isFocusedAndActive() const {
  return m_focused && m_frame->page() &&
         m_frame->page()->focusController().isActive();
}

bool FrameSelection::isAppearanceDirty() const {
  return m_layoutSelection->hasPendingSelection();
}

void FrameSelection::commitAppearanceIfNeeded(LayoutView& layoutView) {
  return m_layoutSelection->commit(layoutView);
}

void FrameSelection::didLayout() {
  updateAppearance();
}

void FrameSelection::updateAppearance() {
  DCHECK(!m_frame->contentLayoutItem().isNull());
  m_frameCaret->scheduleVisualUpdateForPaintInvalidationIfNeeded();
  m_layoutSelection->setHasPendingSelection();
}

void FrameSelection::notifyLayoutObjectOfSelectionChange(
    EUserTriggered userTriggered) {
  TextControlElement* textControl =
      enclosingTextControl(selectionInDOMTree().base());
  if (!textControl)
    return;
  textControl->selectionChanged(userTriggered == UserTriggered);
}

// Helper function that tells whether a particular node is an element that has
// an entire LocalFrame and FrameView, a <frame>, <iframe>, or <object>.
static bool isFrameElement(const Node* n) {
  if (!n)
    return false;
  LayoutObject* layoutObject = n->layoutObject();
  if (!layoutObject || !layoutObject->isLayoutPart())
    return false;
  FrameViewBase* frameViewBase = toLayoutPart(layoutObject)->frameViewBase();
  return frameViewBase && frameViewBase->isFrameView();
}

void FrameSelection::setFocusedNodeIfNeeded() {
  if (computeVisibleSelectionInDOMTreeDeprecated().isNone() || !isFocused())
    return;

  if (Element* target =
          computeVisibleSelectionInDOMTreeDeprecated().rootEditableElement()) {
    // Walk up the DOM tree to search for a node to focus.
    document().updateStyleAndLayoutTreeIgnorePendingStylesheets();
    while (target) {
      // We don't want to set focus on a subframe when selecting in a parent
      // frame, so add the !isFrameElement check here. There's probably a better
      // way to make this work in the long term, but this is the safest fix at
      // this time.
      if (target->isMouseFocusable() && !isFrameElement(target)) {
        m_frame->page()->focusController().setFocusedElement(target, m_frame);
        return;
      }
      target = target->parentOrShadowHostElement();
    }
    document().clearFocusedElement();
  }
}

static String extractSelectedText(const FrameSelection& selection,
                                  TextIteratorBehavior behavior) {
  const VisibleSelectionInFlatTree& visibleSelection =
      selection.computeVisibleSelectionInFlatTree();
  const EphemeralRangeInFlatTree& range =
      visibleSelection.toNormalizedEphemeralRange();
  // We remove '\0' characters because they are not visibly rendered to the
  // user.
  return plainText(range, behavior).replace(0, "");
}

String FrameSelection::selectedHTMLForClipboard() const {
  const VisibleSelectionInFlatTree& visibleSelection =
      computeVisibleSelectionInFlatTree();
  const EphemeralRangeInFlatTree& range =
      visibleSelection.toNormalizedEphemeralRange();
  return createMarkup(range.startPosition(), range.endPosition(),
                      AnnotateForInterchange,
                      ConvertBlocksToInlines::NotConvert, ResolveNonLocalURLs);
}

String FrameSelection::selectedText(
    const TextIteratorBehavior& behavior) const {
  return extractSelectedText(*this, behavior);
}

String FrameSelection::selectedText() const {
  return selectedText(TextIteratorBehavior());
}

String FrameSelection::selectedTextForClipboard() const {
  return extractSelectedText(
      *this, TextIteratorBehavior::Builder()
                 .setEmitsImageAltText(
                     m_frame->settings() &&
                     m_frame->settings()->getSelectionIncludesAltImageText())
                 .build());
}

LayoutRect FrameSelection::bounds() const {
  FrameView* view = m_frame->view();
  if (!view)
    return LayoutRect();

  return intersection(unclippedBounds(),
                      LayoutRect(view->visibleContentRect()));
}

LayoutRect FrameSelection::unclippedBounds() const {
  FrameView* view = m_frame->view();
  LayoutViewItem layoutView = m_frame->contentLayoutItem();

  if (!view || layoutView.isNull())
    return LayoutRect();

  view->updateLifecycleToLayoutClean();
  return LayoutRect(layoutView.selectionBounds());
}

static inline HTMLFormElement* associatedFormElement(HTMLElement& element) {
  if (isHTMLFormElement(element))
    return &toHTMLFormElement(element);
  return element.formOwner();
}

// Scans logically forward from "start", including any child frames.
static HTMLFormElement* scanForForm(Node* start) {
  if (!start)
    return 0;

  for (HTMLElement& element : Traversal<HTMLElement>::startsAt(
           start->isHTMLElement() ? toHTMLElement(start)
                                  : Traversal<HTMLElement>::next(*start))) {
    if (HTMLFormElement* form = associatedFormElement(element))
      return form;

    if (isHTMLFrameElementBase(element)) {
      Node* childDocument = toHTMLFrameElementBase(element).contentDocument();
      if (HTMLFormElement* frameResult = scanForForm(childDocument))
        return frameResult;
    }
  }
  return 0;
}

// We look for either the form containing the current focus, or for one
// immediately after it
HTMLFormElement* FrameSelection::currentForm() const {
  // Start looking either at the active (first responder) node, or where the
  // selection is.
  Node* start = document().focusedElement();
  if (!start)
    start = computeVisibleSelectionInDOMTreeDeprecated().start().anchorNode();
  if (!start)
    return 0;

  // Try walking up the node tree to find a form element.
  for (HTMLElement* element =
           Traversal<HTMLElement>::firstAncestorOrSelf(*start);
       element; element = Traversal<HTMLElement>::firstAncestor(*element)) {
    if (HTMLFormElement* form = associatedFormElement(*element))
      return form;
  }

  // Try walking forward in the node tree to find a form element.
  return scanForForm(start);
}

void FrameSelection::revealSelection(const ScrollAlignment& alignment,
                                     RevealExtentOption revealExtentOption) {
  DCHECK(isAvailable());

  // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  // Calculation of absolute caret bounds requires clean layout.
  document().updateStyleAndLayoutIgnorePendingStylesheets();

  LayoutRect rect;

  switch (computeVisibleSelectionInDOMTree().getSelectionType()) {
    case NoSelection:
      return;
    case CaretSelection:
      rect = LayoutRect(absoluteCaretBounds());
      break;
    case RangeSelection:
      rect = LayoutRect(revealExtentOption == RevealExtent
                            ? absoluteCaretBoundsOf(createVisiblePosition(
                                  computeVisibleSelectionInDOMTree().extent()))
                            : enclosingIntRect(unclippedBounds()));
      break;
  }

  Position start = computeVisibleSelectionInDOMTreeDeprecated().start();
  DCHECK(start.anchorNode());
  if (start.anchorNode() && start.anchorNode()->layoutObject()) {
    // FIXME: This code only handles scrolling the startContainer's layer, but
    // the selection rect could intersect more than just that.
    if (DocumentLoader* documentLoader = m_frame->loader().documentLoader())
      documentLoader->initialScrollState().wasScrolledByUser = true;
    if (start.anchorNode()->layoutObject()->scrollRectToVisible(rect, alignment,
                                                                alignment))
      updateAppearance();
  }
}

void FrameSelection::setSelectionFromNone() {
  // Put a caret inside the body if the entire frame is editable (either the
  // entire WebView is editable or designMode is on for this document).

  Document* document = m_frame->document();
  if (!computeVisibleSelectionInDOMTreeDeprecated().isNone() ||
      !(blink::hasEditableStyle(*document)))
    return;

  Element* documentElement = document->documentElement();
  if (!documentElement)
    return;
  if (HTMLBodyElement* body =
          Traversal<HTMLBodyElement>::firstChild(*documentElement)) {
    setSelection(SelectionInDOMTree::Builder()
                     .collapse(firstPositionInOrBeforeNode(body))
                     .build());
  }
}

// TODO(yoichio): We should have LocalFrame having FrameCaret,
// Editor and PendingSelection using FrameCaret directly
// and get rid of this.
bool FrameSelection::shouldShowBlockCursor() const {
  return m_frameCaret->shouldShowBlockCursor();
}

// TODO(yoichio): We should have LocalFrame having FrameCaret,
// Editor and PendingSelection using FrameCaret directly
// and get rid of this.
// TODO(yoichio): We should use "caret-shape" in "CSS Basic User Interface
// Module Level 4" https://drafts.csswg.org/css-ui-4/
// To use "caret-shape", we need to expose inserting mode information to CSS;
// https://github.com/w3c/csswg-drafts/issues/133
void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor) {
  m_frameCaret->setShouldShowBlockCursor(shouldShowBlockCursor);
}

#ifndef NDEBUG

void FrameSelection::showTreeForThis() const {
  computeVisibleSelectionInDOMTreeDeprecated().showTreeForThis();
}

#endif

DEFINE_TRACE(FrameSelection) {
  visitor->trace(m_frame);
  visitor->trace(m_layoutSelection);
  visitor->trace(m_selectionEditor);
  visitor->trace(m_frameCaret);
  SynchronousMutationObserver::trace(visitor);
}

void FrameSelection::scheduleVisualUpdate() const {
  if (Page* page = m_frame->page())
    page->animator().scheduleVisualUpdate(m_frame->localFrameRoot());
}

void FrameSelection::scheduleVisualUpdateForPaintInvalidationIfNeeded() const {
  if (FrameView* frameView = m_frame->view())
    frameView->scheduleVisualUpdateForPaintInvalidationIfNeeded();
}

bool FrameSelection::selectWordAroundPosition(const VisiblePosition& position) {
  static const EWordSide wordSideList[2] = {RightWordIfOnBoundary,
                                            LeftWordIfOnBoundary};
  for (EWordSide wordSide : wordSideList) {
    // TODO(yoichio): We should have Position version of |start/endOfWord|
    // for avoiding unnecessary canonicalization.
    VisiblePosition start = startOfWord(position, wordSide);
    VisiblePosition end = endOfWord(position, wordSide);
    String text =
        plainText(EphemeralRange(start.deepEquivalent(), end.deepEquivalent()));
    if (!text.isEmpty() && !isSeparator(text.characterStartingAt(0))) {
      setSelection(SelectionInDOMTree::Builder()
                       .collapse(start.toPositionWithAffinity())
                       .extend(end.deepEquivalent())
                       .build(),
                   CloseTyping | ClearTypingStyle,
                   CursorAlignOnScroll::IfNeeded, WordGranularity);
      return true;
    }
  }

  return false;
}

GranularityStrategy* FrameSelection::granularityStrategy() {
  // We do lazy initalization for m_granularityStrategy, because if we
  // initialize it right in the constructor - the correct settings may not be
  // set yet.
  SelectionStrategy strategyType = SelectionStrategy::Character;
  Settings* settings = m_frame ? m_frame->settings() : 0;
  if (settings &&
      settings->getSelectionStrategy() == SelectionStrategy::Direction)
    strategyType = SelectionStrategy::Direction;

  if (m_granularityStrategy && m_granularityStrategy->GetType() == strategyType)
    return m_granularityStrategy.get();

  if (strategyType == SelectionStrategy::Direction)
    m_granularityStrategy = WTF::makeUnique<DirectionGranularityStrategy>();
  else
    m_granularityStrategy = WTF::makeUnique<CharacterGranularityStrategy>();
  return m_granularityStrategy.get();
}

void FrameSelection::moveRangeSelectionExtent(const IntPoint& contentsPoint) {
  if (computeVisibleSelectionInDOMTreeDeprecated().isNone())
    return;

  const SetSelectionOptions options =
      FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle |
      FrameSelection::DoNotClearStrategy | UserTriggered;
  setSelection(SelectionInDOMTree::Builder(
                   granularityStrategy()->updateExtent(contentsPoint, m_frame))
                   .setIsHandleVisible(true)
                   .build(),
               options);
}

// TODO(yosin): We should make |FrameSelection::moveRangeSelection()| to take
// two |IntPoint| instead of two |VisiblePosition| like
// |moveRangeSelectionExtent()|.
void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition,
                                        const VisiblePosition& extentPosition,
                                        TextGranularity granularity) {
  SelectionInDOMTree newSelection =
      SelectionInDOMTree::Builder()
          .setBaseAndExtentDeprecated(basePosition.deepEquivalent(),
                                      extentPosition.deepEquivalent())
          .setAffinity(basePosition.affinity())
          .setGranularity(granularity)
          .setIsHandleVisible(isHandleVisible())
          .build();

  if (newSelection.isNone())
    return;

  setSelection(newSelection, CloseTyping | ClearTypingStyle,
               CursorAlignOnScroll::IfNeeded, granularity);
}

void FrameSelection::setCaretVisible(bool caretIsVisible) {
  m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible
                                                  : CaretVisibility::Hidden);
}

void FrameSelection::setCaretBlinkingSuspended(bool suspended) {
  m_frameCaret->setCaretBlinkingSuspended(suspended);
}

bool FrameSelection::isCaretBlinkingSuspended() const {
  return m_frameCaret->isCaretBlinkingSuspended();
}

void FrameSelection::cacheRangeOfDocument(Range* range) {
  m_selectionEditor->cacheRangeOfDocument(range);
}

Range* FrameSelection::documentCachedRange() const {
  return m_selectionEditor->documentCachedRange();
}

void FrameSelection::clearDocumentCachedRange() {
  m_selectionEditor->clearDocumentCachedRange();
}

}  // namespace blink

#ifndef NDEBUG

void showTree(const blink::FrameSelection& sel) {
  sel.showTreeForThis();
}

void showTree(const blink::FrameSelection* sel) {
  if (sel)
    sel->showTreeForThis();
  else
    LOG(INFO) << "Cannot showTree for <null> FrameSelection.";
}

#endif
