Home | History | Annotate | Download | only in editing
      1 /*
      2  * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/editing/FrameSelection.h"
     28 
     29 #include "bindings/core/v8/ExceptionState.h"
     30 #include "core/HTMLNames.h"
     31 #include "core/InputTypeNames.h"
     32 #include "core/accessibility/AXObjectCache.h"
     33 #include "core/css/StylePropertySet.h"
     34 #include "core/dom/CharacterData.h"
     35 #include "core/dom/Document.h"
     36 #include "core/dom/Element.h"
     37 #include "core/dom/ElementTraversal.h"
     38 #include "core/dom/NodeTraversal.h"
     39 #include "core/dom/Text.h"
     40 #include "core/editing/Editor.h"
     41 #include "core/editing/InputMethodController.h"
     42 #include "core/editing/RenderedPosition.h"
     43 #include "core/editing/SpellChecker.h"
     44 #include "core/editing/TextIterator.h"
     45 #include "core/editing/TypingCommand.h"
     46 #include "core/editing/VisibleUnits.h"
     47 #include "core/editing/htmlediting.h"
     48 #include "core/events/Event.h"
     49 #include "core/frame/LocalDOMWindow.h"
     50 #include "core/frame/LocalFrame.h"
     51 #include "core/html/HTMLBodyElement.h"
     52 #include "core/html/HTMLFormElement.h"
     53 #include "core/html/HTMLFrameElementBase.h"
     54 #include "core/html/HTMLInputElement.h"
     55 #include "core/html/HTMLSelectElement.h"
     56 #include "core/page/EditorClient.h"
     57 #include "core/page/EventHandler.h"
     58 #include "core/page/FocusController.h"
     59 #include "core/page/FrameTree.h"
     60 #include "core/frame/FrameView.h"
     61 #include "core/page/Page.h"
     62 #include "core/frame/Settings.h"
     63 #include "core/page/SpatialNavigation.h"
     64 #include "core/rendering/HitTestRequest.h"
     65 #include "core/rendering/HitTestResult.h"
     66 #include "core/rendering/InlineTextBox.h"
     67 #include "core/rendering/RenderLayer.h"
     68 #include "core/rendering/RenderText.h"
     69 #include "core/rendering/RenderTheme.h"
     70 #include "core/rendering/RenderView.h"
     71 #include "core/rendering/RenderWidget.h"
     72 #include "platform/SecureTextInput.h"
     73 #include "platform/geometry/FloatQuad.h"
     74 #include "platform/graphics/GraphicsContext.h"
     75 #include "wtf/text/CString.h"
     76 #include <stdio.h>
     77 
     78 #define EDIT_DEBUG 0
     79 
     80 namespace blink {
     81 
     82 using namespace HTMLNames;
     83 
     84 static inline LayoutUnit NoXPosForVerticalArrowNavigation()
     85 {
     86     return LayoutUnit::min();
     87 }
     88 
     89 static inline bool shouldAlwaysUseDirectionalSelection(LocalFrame* frame)
     90 {
     91     return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirectional();
     92 }
     93 
     94 FrameSelection::FrameSelection(LocalFrame* frame)
     95     : m_frame(frame)
     96     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
     97     , m_observingVisibleSelection(false)
     98     , m_granularity(CharacterGranularity)
     99     , m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired)
    100     , m_caretRectDirty(true)
    101     , m_shouldPaintCaret(true)
    102     , m_isCaretBlinkingSuspended(false)
    103     , m_focused(frame && frame->page() && frame->page()->focusController().focusedFrame() == frame)
    104     , m_shouldShowBlockCursor(false)
    105 {
    106     if (shouldAlwaysUseDirectionalSelection(m_frame))
    107         m_selection.setIsDirectional(true);
    108 }
    109 
    110 FrameSelection::~FrameSelection()
    111 {
    112 #if !ENABLE(OILPAN)
    113     // Oilpan: No need to clear out VisibleSelection observer;
    114     // it is finalized as a part object of FrameSelection.
    115     stopObservingVisibleSelectionChangeIfNecessary();
    116 #endif
    117 }
    118 
    119 Element* FrameSelection::rootEditableElementOrDocumentElement() const
    120 {
    121     Element* selectionRoot = m_selection.rootEditableElement();
    122     return selectionRoot ? selectionRoot : m_frame->document()->documentElement();
    123 }
    124 
    125 ContainerNode* FrameSelection::rootEditableElementOrTreeScopeRootNode() const
    126 {
    127     Element* selectionRoot = m_selection.rootEditableElement();
    128     if (selectionRoot)
    129         return selectionRoot;
    130 
    131     Node* node = m_selection.base().containerNode();
    132     return node ? &node->treeScope().rootNode() : 0;
    133 }
    134 
    135 void FrameSelection::moveTo(const VisiblePosition &pos, EUserTriggered userTriggered, CursorAlignOnScroll align)
    136 {
    137     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
    138     setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity(), m_selection.isDirectional()), options, align);
    139 }
    140 
    141 void FrameSelection::moveTo(const VisiblePosition &base, const VisiblePosition &extent, EUserTriggered userTriggered)
    142 {
    143     const bool selectionHasDirection = true;
    144     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
    145     setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity(), selectionHasDirection), options);
    146 }
    147 
    148 void FrameSelection::moveTo(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
    149 {
    150     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
    151     setSelection(VisibleSelection(pos, affinity, m_selection.isDirectional()), options);
    152 }
    153 
    154 static void adjustEndpointsAtBidiBoundary(VisiblePosition& visibleBase, VisiblePosition& visibleExtent)
    155 {
    156     RenderedPosition base(visibleBase);
    157     RenderedPosition extent(visibleExtent);
    158 
    159     if (base.isNull() || extent.isNull() || base.isEquivalent(extent))
    160         return;
    161 
    162     if (base.atLeftBoundaryOfBidiRun()) {
    163         if (!extent.atRightBoundaryOfBidiRun(base.bidiLevelOnRight())
    164             && base.isEquivalent(extent.leftBoundaryOfBidiRun(base.bidiLevelOnRight()))) {
    165             visibleBase = VisiblePosition(base.positionAtLeftBoundaryOfBiDiRun());
    166             return;
    167         }
    168         return;
    169     }
    170 
    171     if (base.atRightBoundaryOfBidiRun()) {
    172         if (!extent.atLeftBoundaryOfBidiRun(base.bidiLevelOnLeft())
    173             && base.isEquivalent(extent.rightBoundaryOfBidiRun(base.bidiLevelOnLeft()))) {
    174             visibleBase = VisiblePosition(base.positionAtRightBoundaryOfBiDiRun());
    175             return;
    176         }
    177         return;
    178     }
    179 
    180     if (extent.atLeftBoundaryOfBidiRun() && extent.isEquivalent(base.leftBoundaryOfBidiRun(extent.bidiLevelOnRight()))) {
    181         visibleExtent = VisiblePosition(extent.positionAtLeftBoundaryOfBiDiRun());
    182         return;
    183     }
    184 
    185     if (extent.atRightBoundaryOfBidiRun() && extent.isEquivalent(base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) {
    186         visibleExtent = VisiblePosition(extent.positionAtRightBoundaryOfBiDiRun());
    187         return;
    188     }
    189 }
    190 
    191 void FrameSelection::setNonDirectionalSelectionIfNeeded(const VisibleSelection& passedNewSelection, TextGranularity granularity,
    192     EndPointsAdjustmentMode endpointsAdjustmentMode)
    193 {
    194     VisibleSelection newSelection = passedNewSelection;
    195     bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || newSelection.isDirectional();
    196 
    197     VisiblePosition base = m_originalBase.isNotNull() ? m_originalBase : newSelection.visibleBase();
    198     VisiblePosition newBase = base;
    199     VisiblePosition extent = newSelection.visibleExtent();
    200     VisiblePosition newExtent = extent;
    201     if (endpointsAdjustmentMode == AdjustEndpointsAtBidiBoundary)
    202         adjustEndpointsAtBidiBoundary(newBase, newExtent);
    203 
    204     if (newBase != base || newExtent != extent) {
    205         m_originalBase = base;
    206         newSelection.setBase(newBase);
    207         newSelection.setExtent(newExtent);
    208     } else if (m_originalBase.isNotNull()) {
    209         if (m_selection.base() == newSelection.base())
    210             newSelection.setBase(m_originalBase);
    211         m_originalBase.clear();
    212     }
    213 
    214     newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
    215     if (m_selection == newSelection)
    216         return;
    217 
    218     setSelection(newSelection, granularity);
    219 }
    220 
    221 void FrameSelection::setSelection(const VisibleSelection& newSelection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity)
    222 {
    223     bool closeTyping = options & CloseTyping;
    224     bool shouldClearTypingStyle = options & ClearTypingStyle;
    225     EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
    226 
    227     VisibleSelection s = validateSelection(newSelection);
    228     if (shouldAlwaysUseDirectionalSelection(m_frame))
    229         s.setIsDirectional(true);
    230 
    231     if (!m_frame) {
    232         m_selection = s;
    233         return;
    234     }
    235 
    236     // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at FrameSelection::setSelection
    237     // if document->frame() == m_frame we can get into an infinite loop
    238     if (s.base().anchorNode()) {
    239         Document& document = *s.base().document();
    240         if (document.frame() && document.frame() != m_frame && document != m_frame->document()) {
    241             RefPtrWillBeRawPtr<LocalFrame> guard(document.frame());
    242             document.frame()->selection().setSelection(s, options, align, granularity);
    243             // It's possible that during the above set selection, this FrameSelection has been modified by
    244             // selectFrameElementInParentIfFullySelected, but that the selection is no longer valid since
    245             // the frame is about to be destroyed. If this is the case, clear our selection.
    246             if (!guard->host() && !m_selection.isNonOrphanedCaretOrRange())
    247                 clear();
    248             return;
    249         }
    250     }
    251 
    252     m_granularity = granularity;
    253 
    254     if (closeTyping)
    255         TypingCommand::closeTyping(m_frame);
    256 
    257     if (shouldClearTypingStyle)
    258         clearTypingStyle();
    259 
    260     if (m_selection == s) {
    261         // Even if selection was not changed, selection offsets may have been changed.
    262         m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid();
    263         notifyRendererOfSelectionChange(userTriggered);
    264         return;
    265     }
    266 
    267     VisibleSelection oldSelection = m_selection;
    268 
    269     m_selection = s;
    270     setCaretRectNeedsUpdate();
    271 
    272     if (!s.isNone() && !(options & DoNotSetFocus))
    273         setFocusedNodeIfNeeded();
    274 
    275     if (!(options & DoNotUpdateAppearance)) {
    276         // Hits in compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html
    277         DisableCompositingQueryAsserts disabler;
    278         updateAppearance(ResetCaretBlink);
    279     }
    280 
    281     // Always clear the x position used for vertical arrow navigation.
    282     // It will be restored by the vertical arrow navigation code if necessary.
    283     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
    284     selectFrameElementInParentIfFullySelected();
    285     notifyRendererOfSelectionChange(userTriggered);
    286     m_frame->editor().respondToChangedSelection(oldSelection, options);
    287     if (userTriggered == UserTriggered) {
    288         ScrollAlignment alignment;
    289 
    290         if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
    291             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignCenterAlways : ScrollAlignment::alignCenterIfNeeded;
    292         else
    293             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
    294 
    295         revealSelection(alignment, RevealExtent);
    296     }
    297 
    298     notifyAccessibilityForSelectionChange();
    299     notifyCompositorForSelectionChange();
    300     notifyEventHandlerForSelectionChange();
    301     m_frame->domWindow()->enqueueDocumentEvent(Event::create(EventTypeNames::selectionchange));
    302 }
    303 
    304 static bool removingNodeRemovesPosition(Node& node, const Position& position)
    305 {
    306     if (!position.anchorNode())
    307         return false;
    308 
    309     if (position.anchorNode() == node)
    310         return true;
    311 
    312     if (!node.isElementNode())
    313         return false;
    314 
    315     Element& element = toElement(node);
    316     return element.containsIncludingShadowDOM(position.anchorNode());
    317 }
    318 
    319 void FrameSelection::nodeWillBeRemoved(Node& node)
    320 {
    321     // There can't be a selection inside a fragment, so if a fragment's node is being removed,
    322     // the selection in the document that created the fragment needs no adjustment.
    323     if (isNone() || !node.inActiveDocument())
    324         return;
    325 
    326     respondToNodeModification(node, removingNodeRemovesPosition(node, m_selection.base()), removingNodeRemovesPosition(node, m_selection.extent()),
    327         removingNodeRemovesPosition(node, m_selection.start()), removingNodeRemovesPosition(node, m_selection.end()));
    328 }
    329 
    330 void FrameSelection::respondToNodeModification(Node& node, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved)
    331 {
    332     ASSERT(node.document().isActive());
    333 
    334     bool clearRenderTreeSelection = false;
    335     bool clearDOMTreeSelection = false;
    336 
    337     if (startRemoved || endRemoved) {
    338         Position start = m_selection.start();
    339         Position end = m_selection.end();
    340         if (startRemoved)
    341             updatePositionForNodeRemoval(start, node);
    342         if (endRemoved)
    343             updatePositionForNodeRemoval(end, node);
    344 
    345         if (start.isNotNull() && end.isNotNull()) {
    346             if (m_selection.isBaseFirst())
    347                 m_selection.setWithoutValidation(start, end);
    348             else
    349                 m_selection.setWithoutValidation(end, start);
    350         } else
    351             clearDOMTreeSelection = true;
    352 
    353         clearRenderTreeSelection = true;
    354     } else if (baseRemoved || extentRemoved) {
    355         // The base and/or extent are about to be removed, but the start and end aren't.
    356         // Change the base and extent to the start and end, but don't re-validate the
    357         // selection, since doing so could move the start and end into the node
    358         // that is about to be removed.
    359         if (m_selection.isBaseFirst())
    360             m_selection.setWithoutValidation(m_selection.start(), m_selection.end());
    361         else
    362             m_selection.setWithoutValidation(m_selection.end(), m_selection.start());
    363     } else if (m_selection.intersectsNode(&node)) {
    364         // If we did nothing here, when this node's renderer was destroyed, the rect that it
    365         // occupied would be invalidated, but, selection gaps that change as a result of
    366         // the removal wouldn't be invalidated.
    367         // FIXME: Don't do so much unnecessary invalidation.
    368         clearRenderTreeSelection = true;
    369     }
    370 
    371     if (clearRenderTreeSelection)
    372         m_selection.start().document()->renderView()->clearSelection();
    373 
    374     if (clearDOMTreeSelection)
    375         setSelection(VisibleSelection(), DoNotSetFocus);
    376 }
    377 
    378 static Position updatePositionAfterAdoptingTextReplacement(const Position& position, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
    379 {
    380     if (!position.anchorNode() || position.anchorNode() != node || position.anchorType() != Position::PositionIsOffsetInAnchor)
    381         return position;
    382 
    383     // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation
    384     ASSERT(position.offsetInContainerNode() >= 0);
    385     unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
    386     // Replacing text can be viewed as a deletion followed by insertion.
    387     if (positionOffset >= offset && positionOffset <= offset + oldLength)
    388         positionOffset = offset;
    389 
    390     // Adjust the offset if the position is after the end of the deleted contents
    391     // (positionOffset > offset + oldLength) to avoid having a stale offset.
    392     if (positionOffset > offset + oldLength)
    393         positionOffset = positionOffset - oldLength + newLength;
    394 
    395     ASSERT_WITH_SECURITY_IMPLICATION(positionOffset <= node->length());
    396     // CharacterNode in VisibleSelection must be Text node, because Comment
    397     // and ProcessingInstruction node aren't visible.
    398     return Position(toText(node), positionOffset);
    399 }
    400 
    401 void FrameSelection::didUpdateCharacterData(CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
    402 {
    403     // The fragment check is a performance optimization. See http://trac.webkit.org/changeset/30062.
    404     if (isNone() || !node || !node->inDocument())
    405         return;
    406 
    407     Position base = updatePositionAfterAdoptingTextReplacement(m_selection.base(), node, offset, oldLength, newLength);
    408     Position extent = updatePositionAfterAdoptingTextReplacement(m_selection.extent(), node, offset, oldLength, newLength);
    409     Position start = updatePositionAfterAdoptingTextReplacement(m_selection.start(), node, offset, oldLength, newLength);
    410     Position end = updatePositionAfterAdoptingTextReplacement(m_selection.end(), node, offset, oldLength, newLength);
    411     updateSelectionIfNeeded(base, extent, start, end);
    412 }
    413 
    414 static Position updatePostionAfterAdoptingTextNodesMerged(const Position& position, const Text& oldNode, unsigned offset)
    415 {
    416     if (!position.anchorNode() || position.anchorType() != Position::PositionIsOffsetInAnchor)
    417         return position;
    418 
    419     ASSERT(position.offsetInContainerNode() >= 0);
    420     unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
    421 
    422     if (position.anchorNode() == &oldNode)
    423         return Position(toText(oldNode.previousSibling()), positionOffset + offset);
    424 
    425     if (position.anchorNode() == oldNode.parentNode() && positionOffset == offset)
    426         return Position(toText(oldNode.previousSibling()), offset);
    427 
    428     return position;
    429 }
    430 
    431 void FrameSelection::didMergeTextNodes(const Text& oldNode, unsigned offset)
    432 {
    433     if (isNone() || !oldNode.inDocument())
    434         return;
    435     Position base = updatePostionAfterAdoptingTextNodesMerged(m_selection.base(), oldNode, offset);
    436     Position extent = updatePostionAfterAdoptingTextNodesMerged(m_selection.extent(), oldNode, offset);
    437     Position start = updatePostionAfterAdoptingTextNodesMerged(m_selection.start(), oldNode, offset);
    438     Position end = updatePostionAfterAdoptingTextNodesMerged(m_selection.end(), oldNode, offset);
    439     updateSelectionIfNeeded(base, extent, start, end);
    440 }
    441 
    442 static Position updatePostionAfterAdoptingTextNodeSplit(const Position& position, const Text& oldNode)
    443 {
    444     if (!position.anchorNode() || position.anchorNode() != &oldNode || position.anchorType() != Position::PositionIsOffsetInAnchor)
    445         return position;
    446     // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation
    447     ASSERT(position.offsetInContainerNode() >= 0);
    448     unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
    449     unsigned oldLength = oldNode.length();
    450     if (positionOffset <= oldLength)
    451         return position;
    452     return Position(toText(oldNode.nextSibling()), positionOffset - oldLength);
    453 }
    454 
    455 void FrameSelection::didSplitTextNode(const Text& oldNode)
    456 {
    457     if (isNone() || !oldNode.inDocument())
    458         return;
    459     Position base = updatePostionAfterAdoptingTextNodeSplit(m_selection.base(), oldNode);
    460     Position extent = updatePostionAfterAdoptingTextNodeSplit(m_selection.extent(), oldNode);
    461     Position start = updatePostionAfterAdoptingTextNodeSplit(m_selection.start(), oldNode);
    462     Position end = updatePostionAfterAdoptingTextNodeSplit(m_selection.end(), oldNode);
    463     updateSelectionIfNeeded(base, extent, start, end);
    464 }
    465 
    466 void FrameSelection::updateSelectionIfNeeded(const Position& base, const Position& extent, const Position& start, const Position& end)
    467 {
    468     if (base == m_selection.base() && extent == m_selection.extent() && start == m_selection.start() && end == m_selection.end())
    469         return;
    470     VisibleSelection newSelection;
    471     if (m_selection.isBaseFirst())
    472         newSelection.setWithoutValidation(start, end);
    473     else
    474         newSelection.setWithoutValidation(end, start);
    475     setSelection(newSelection, DoNotSetFocus);
    476 }
    477 
    478 TextDirection FrameSelection::directionOfEnclosingBlock()
    479 {
    480     return blink::directionOfEnclosingBlock(m_selection.extent());
    481 }
    482 
    483 TextDirection FrameSelection::directionOfSelection()
    484 {
    485     InlineBox* startBox = 0;
    486     InlineBox* endBox = 0;
    487     int unusedOffset;
    488     // Cache the VisiblePositions because visibleStart() and visibleEnd()
    489     // can cause layout, which has the potential to invalidate lineboxes.
    490     VisiblePosition startPosition = m_selection.visibleStart();
    491     VisiblePosition endPosition = m_selection.visibleEnd();
    492     if (startPosition.isNotNull())
    493         startPosition.getInlineBoxAndOffset(startBox, unusedOffset);
    494     if (endPosition.isNotNull())
    495         endPosition.getInlineBoxAndOffset(endBox, unusedOffset);
    496     if (startBox && endBox && startBox->direction() == endBox->direction())
    497         return startBox->direction();
    498 
    499     return directionOfEnclosingBlock();
    500 }
    501 
    502 void FrameSelection::didChangeFocus()
    503 {
    504     // Hits in virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disabled.html
    505     DisableCompositingQueryAsserts disabler;
    506     updateAppearance();
    507 }
    508 
    509 void FrameSelection::willBeModified(EAlteration alter, SelectionDirection direction)
    510 {
    511     if (alter != AlterationExtend)
    512         return;
    513 
    514     Position start = m_selection.start();
    515     Position end = m_selection.end();
    516 
    517     bool baseIsStart = true;
    518 
    519     if (m_selection.isDirectional()) {
    520         // Make base and extent match start and end so we extend the user-visible selection.
    521         // This only matters for cases where base and extend point to different positions than
    522         // start and end (e.g. after a double-click to select a word).
    523         if (m_selection.isBaseFirst())
    524             baseIsStart = true;
    525         else
    526             baseIsStart = false;
    527     } else {
    528         switch (direction) {
    529         case DirectionRight:
    530             if (directionOfSelection() == LTR)
    531                 baseIsStart = true;
    532             else
    533                 baseIsStart = false;
    534             break;
    535         case DirectionForward:
    536             baseIsStart = true;
    537             break;
    538         case DirectionLeft:
    539             if (directionOfSelection() == LTR)
    540                 baseIsStart = false;
    541             else
    542                 baseIsStart = true;
    543             break;
    544         case DirectionBackward:
    545             baseIsStart = false;
    546             break;
    547         }
    548     }
    549     if (baseIsStart) {
    550         m_selection.setBase(start);
    551         m_selection.setExtent(end);
    552     } else {
    553         m_selection.setBase(end);
    554         m_selection.setExtent(start);
    555     }
    556 }
    557 
    558 VisiblePosition FrameSelection::positionForPlatform(bool isGetStart) const
    559 {
    560     Settings* settings = m_frame ? m_frame->settings() : 0;
    561     if (settings && settings->editingBehaviorType() == EditingMacBehavior)
    562         return isGetStart ? m_selection.visibleStart() : m_selection.visibleEnd();
    563     // Linux and Windows always extend selections from the extent endpoint.
    564     // FIXME: VisibleSelection should be fixed to ensure as an invariant that
    565     // base/extent always point to the same nodes as start/end, but which points
    566     // to which depends on the value of isBaseFirst. Then this can be changed
    567     // to just return m_sel.extent().
    568     return m_selection.isBaseFirst() ? m_selection.visibleEnd() : m_selection.visibleStart();
    569 }
    570 
    571 VisiblePosition FrameSelection::startForPlatform() const
    572 {
    573     return positionForPlatform(true);
    574 }
    575 
    576 VisiblePosition FrameSelection::endForPlatform() const
    577 {
    578     return positionForPlatform(false);
    579 }
    580 
    581 VisiblePosition FrameSelection::nextWordPositionForPlatform(const VisiblePosition &originalPosition)
    582 {
    583     VisiblePosition positionAfterCurrentWord = nextWordPosition(originalPosition);
    584 
    585     if (m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight()) {
    586         // In order to skip spaces when moving right, we advance one
    587         // word further and then move one word back. Given the
    588         // semantics of previousWordPosition() this will put us at the
    589         // beginning of the word following.
    590         VisiblePosition positionAfterSpacingAndFollowingWord = nextWordPosition(positionAfterCurrentWord);
    591         if (positionAfterSpacingAndFollowingWord.isNotNull() && positionAfterSpacingAndFollowingWord != positionAfterCurrentWord)
    592             positionAfterCurrentWord = previousWordPosition(positionAfterSpacingAndFollowingWord);
    593 
    594         bool movingBackwardsMovedPositionToStartOfCurrentWord = positionAfterCurrentWord == previousWordPosition(nextWordPosition(originalPosition));
    595         if (movingBackwardsMovedPositionToStartOfCurrentWord)
    596             positionAfterCurrentWord = positionAfterSpacingAndFollowingWord;
    597     }
    598     return positionAfterCurrentWord;
    599 }
    600 
    601 static void adjustPositionForUserSelectAll(VisiblePosition& pos, bool isForward)
    602 {
    603     if (Node* rootUserSelectAll = Position::rootUserSelectAllForNode(pos.deepEquivalent().anchorNode()))
    604         pos = VisiblePosition(isForward ? positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary) : positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary));
    605 }
    606 
    607 VisiblePosition FrameSelection::modifyExtendingRight(TextGranularity granularity)
    608 {
    609     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    610 
    611     // The difference between modifyExtendingRight and modifyExtendingForward is:
    612     // modifyExtendingForward always extends forward logically.
    613     // modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
    614     // it extends forward logically if the enclosing block is LTR direction,
    615     // but it extends backward logically if the enclosing block is RTL direction.
    616     switch (granularity) {
    617     case CharacterGranularity:
    618         if (directionOfEnclosingBlock() == LTR)
    619             pos = pos.next(CanSkipOverEditingBoundary);
    620         else
    621             pos = pos.previous(CanSkipOverEditingBoundary);
    622         break;
    623     case WordGranularity:
    624         if (directionOfEnclosingBlock() == LTR)
    625             pos = nextWordPositionForPlatform(pos);
    626         else
    627             pos = previousWordPosition(pos);
    628         break;
    629     case LineBoundary:
    630         if (directionOfEnclosingBlock() == LTR)
    631             pos = modifyExtendingForward(granularity);
    632         else
    633             pos = modifyExtendingBackward(granularity);
    634         break;
    635     case SentenceGranularity:
    636     case LineGranularity:
    637     case ParagraphGranularity:
    638     case SentenceBoundary:
    639     case ParagraphBoundary:
    640     case DocumentBoundary:
    641         // FIXME: implement all of the above?
    642         pos = modifyExtendingForward(granularity);
    643         break;
    644     }
    645     adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
    646     return pos;
    647 }
    648 
    649 VisiblePosition FrameSelection::modifyExtendingForward(TextGranularity granularity)
    650 {
    651     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    652     switch (granularity) {
    653     case CharacterGranularity:
    654         pos = pos.next(CanSkipOverEditingBoundary);
    655         break;
    656     case WordGranularity:
    657         pos = nextWordPositionForPlatform(pos);
    658         break;
    659     case SentenceGranularity:
    660         pos = nextSentencePosition(pos);
    661         break;
    662     case LineGranularity:
    663         pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
    664         break;
    665     case ParagraphGranularity:
    666         pos = nextParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
    667         break;
    668     case SentenceBoundary:
    669         pos = endOfSentence(endForPlatform());
    670         break;
    671     case LineBoundary:
    672         pos = logicalEndOfLine(endForPlatform());
    673         break;
    674     case ParagraphBoundary:
    675         pos = endOfParagraph(endForPlatform());
    676         break;
    677     case DocumentBoundary:
    678         pos = endForPlatform();
    679         if (isEditablePosition(pos.deepEquivalent()))
    680             pos = endOfEditableContent(pos);
    681         else
    682             pos = endOfDocument(pos);
    683         break;
    684     }
    685     adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
    686     return pos;
    687 }
    688 
    689 VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
    690 {
    691     VisiblePosition pos;
    692     switch (granularity) {
    693     case CharacterGranularity:
    694         if (isRange()) {
    695             if (directionOfSelection() == LTR)
    696                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    697             else
    698                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
    699         } else
    700             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
    701         break;
    702     case WordGranularity: {
    703         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
    704         pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
    705         break;
    706     }
    707     case SentenceGranularity:
    708     case LineGranularity:
    709     case ParagraphGranularity:
    710     case SentenceBoundary:
    711     case ParagraphBoundary:
    712     case DocumentBoundary:
    713         // FIXME: Implement all of the above.
    714         pos = modifyMovingForward(granularity);
    715         break;
    716     case LineBoundary:
    717         pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
    718         break;
    719     }
    720     return pos;
    721 }
    722 
    723 VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity)
    724 {
    725     VisiblePosition pos;
    726     // FIXME: Stay in editable content for the less common granularities.
    727     switch (granularity) {
    728     case CharacterGranularity:
    729         if (isRange())
    730             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    731         else
    732             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CanSkipOverEditingBoundary);
    733         break;
    734     case WordGranularity:
    735         pos = nextWordPositionForPlatform(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    736         break;
    737     case SentenceGranularity:
    738         pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    739         break;
    740     case LineGranularity: {
    741         // down-arrowing from a range selection that ends at the start of a line needs
    742         // to leave the selection at that line start (no need to call nextLinePosition!)
    743         pos = endForPlatform();
    744         if (!isRange() || !isStartOfLine(pos))
    745             pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(START));
    746         break;
    747     }
    748     case ParagraphGranularity:
    749         pos = nextParagraphPosition(endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
    750         break;
    751     case SentenceBoundary:
    752         pos = endOfSentence(endForPlatform());
    753         break;
    754     case LineBoundary:
    755         pos = logicalEndOfLine(endForPlatform());
    756         break;
    757     case ParagraphBoundary:
    758         pos = endOfParagraph(endForPlatform());
    759         break;
    760     case DocumentBoundary:
    761         pos = endForPlatform();
    762         if (isEditablePosition(pos.deepEquivalent()))
    763             pos = endOfEditableContent(pos);
    764         else
    765             pos = endOfDocument(pos);
    766         break;
    767     }
    768     return pos;
    769 }
    770 
    771 VisiblePosition FrameSelection::modifyExtendingLeft(TextGranularity granularity)
    772 {
    773     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    774 
    775     // The difference between modifyExtendingLeft and modifyExtendingBackward is:
    776     // modifyExtendingBackward always extends backward logically.
    777     // modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
    778     // it extends backward logically if the enclosing block is LTR direction,
    779     // but it extends forward logically if the enclosing block is RTL direction.
    780     switch (granularity) {
    781     case CharacterGranularity:
    782         if (directionOfEnclosingBlock() == LTR)
    783             pos = pos.previous(CanSkipOverEditingBoundary);
    784         else
    785             pos = pos.next(CanSkipOverEditingBoundary);
    786         break;
    787     case WordGranularity:
    788         if (directionOfEnclosingBlock() == LTR)
    789             pos = previousWordPosition(pos);
    790         else
    791             pos = nextWordPositionForPlatform(pos);
    792         break;
    793     case LineBoundary:
    794         if (directionOfEnclosingBlock() == LTR)
    795             pos = modifyExtendingBackward(granularity);
    796         else
    797             pos = modifyExtendingForward(granularity);
    798         break;
    799     case SentenceGranularity:
    800     case LineGranularity:
    801     case ParagraphGranularity:
    802     case SentenceBoundary:
    803     case ParagraphBoundary:
    804     case DocumentBoundary:
    805         pos = modifyExtendingBackward(granularity);
    806         break;
    807     }
    808     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
    809     return pos;
    810 }
    811 
    812 VisiblePosition FrameSelection::modifyExtendingBackward(TextGranularity granularity)
    813 {
    814     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
    815 
    816     // Extending a selection backward by word or character from just after a table selects
    817     // the table.  This "makes sense" from the user perspective, esp. when deleting.
    818     // It was done here instead of in VisiblePosition because we want VPs to iterate
    819     // over everything.
    820     switch (granularity) {
    821     case CharacterGranularity:
    822         pos = pos.previous(CanSkipOverEditingBoundary);
    823         break;
    824     case WordGranularity:
    825         pos = previousWordPosition(pos);
    826         break;
    827     case SentenceGranularity:
    828         pos = previousSentencePosition(pos);
    829         break;
    830     case LineGranularity:
    831         pos = previousLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
    832         break;
    833     case ParagraphGranularity:
    834         pos = previousParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
    835         break;
    836     case SentenceBoundary:
    837         pos = startOfSentence(startForPlatform());
    838         break;
    839     case LineBoundary:
    840         pos = logicalStartOfLine(startForPlatform());
    841         break;
    842     case ParagraphBoundary:
    843         pos = startOfParagraph(startForPlatform());
    844         break;
    845     case DocumentBoundary:
    846         pos = startForPlatform();
    847         if (isEditablePosition(pos.deepEquivalent()))
    848             pos = startOfEditableContent(pos);
    849         else
    850             pos = startOfDocument(pos);
    851         break;
    852     }
    853     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
    854     return pos;
    855 }
    856 
    857 VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
    858 {
    859     VisiblePosition pos;
    860     switch (granularity) {
    861     case CharacterGranularity:
    862         if (isRange())
    863             if (directionOfSelection() == LTR)
    864                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
    865             else
    866                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
    867         else
    868             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
    869         break;
    870     case WordGranularity: {
    871         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
    872         pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
    873         break;
    874     }
    875     case SentenceGranularity:
    876     case LineGranularity:
    877     case ParagraphGranularity:
    878     case SentenceBoundary:
    879     case ParagraphBoundary:
    880     case DocumentBoundary:
    881         // FIXME: Implement all of the above.
    882         pos = modifyMovingBackward(granularity);
    883         break;
    884     case LineBoundary:
    885         pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
    886         break;
    887     }
    888     return pos;
    889 }
    890 
    891 VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity)
    892 {
    893     VisiblePosition pos;
    894     switch (granularity) {
    895     case CharacterGranularity:
    896         if (isRange())
    897             pos = VisiblePosition(m_selection.start(), m_selection.affinity());
    898         else
    899             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CanSkipOverEditingBoundary);
    900         break;
    901     case WordGranularity:
    902         pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    903         break;
    904     case SentenceGranularity:
    905         pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
    906         break;
    907     case LineGranularity:
    908         pos = previousLinePosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
    909         break;
    910     case ParagraphGranularity:
    911         pos = previousParagraphPosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
    912         break;
    913     case SentenceBoundary:
    914         pos = startOfSentence(startForPlatform());
    915         break;
    916     case LineBoundary:
    917         pos = logicalStartOfLine(startForPlatform());
    918         break;
    919     case ParagraphBoundary:
    920         pos = startOfParagraph(startForPlatform());
    921         break;
    922     case DocumentBoundary:
    923         pos = startForPlatform();
    924         if (isEditablePosition(pos.deepEquivalent()))
    925             pos = startOfEditableContent(pos);
    926         else
    927             pos = startOfDocument(pos);
    928         break;
    929     }
    930     return pos;
    931 }
    932 
    933 static bool isBoundary(TextGranularity granularity)
    934 {
    935     return granularity == LineBoundary || granularity == ParagraphBoundary || granularity == DocumentBoundary;
    936 }
    937 
    938 bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered userTriggered)
    939 {
    940     if (userTriggered == UserTriggered) {
    941         OwnPtrWillBeRawPtr<FrameSelection> trialFrameSelection = FrameSelection::create();
    942         trialFrameSelection->setSelection(m_selection);
    943         trialFrameSelection->modify(alter, direction, granularity, NotUserTriggered);
    944 
    945         if (trialFrameSelection->selection().isRange() && m_selection.isCaret() && !dispatchSelectStart())
    946             return false;
    947     }
    948 
    949     willBeModified(alter, direction);
    950 
    951     bool wasRange = m_selection.isRange();
    952     VisiblePosition originalStartPosition = m_selection.visibleStart();
    953     VisiblePosition position;
    954     switch (direction) {
    955     case DirectionRight:
    956         if (alter == AlterationMove)
    957             position = modifyMovingRight(granularity);
    958         else
    959             position = modifyExtendingRight(granularity);
    960         break;
    961     case DirectionForward:
    962         if (alter == AlterationExtend)
    963             position = modifyExtendingForward(granularity);
    964         else
    965             position = modifyMovingForward(granularity);
    966         break;
    967     case DirectionLeft:
    968         if (alter == AlterationMove)
    969             position = modifyMovingLeft(granularity);
    970         else
    971             position = modifyExtendingLeft(granularity);
    972         break;
    973     case DirectionBackward:
    974         if (alter == AlterationExtend)
    975             position = modifyExtendingBackward(granularity);
    976         else
    977             position = modifyMovingBackward(granularity);
    978         break;
    979     }
    980 
    981     if (position.isNull())
    982         return false;
    983 
    984     if (isSpatialNavigationEnabled(m_frame))
    985         if (!wasRange && alter == AlterationMove && position == originalStartPosition)
    986             return false;
    987 
    988     // Some of the above operations set an xPosForVerticalArrowNavigation.
    989     // Setting a selection will clear it, so save it to possibly restore later.
    990     // Note: the START position type is arbitrary because it is unused, it would be
    991     // the requested position type if there were no xPosForVerticalArrowNavigation set.
    992     LayoutUnit x = lineDirectionPointForBlockDirectionNavigation(START);
    993     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
    994 
    995     switch (alter) {
    996     case AlterationMove:
    997         moveTo(position, userTriggered);
    998         break;
    999     case AlterationExtend:
   1000 
   1001         if (!m_selection.isCaret()
   1002             && (granularity == WordGranularity || granularity == ParagraphGranularity || granularity == LineGranularity)
   1003             && m_frame && !m_frame->editor().behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
   1004             // Don't let the selection go across the base position directly. Needed to match mac
   1005             // behavior when, for instance, word-selecting backwards starting with the caret in
   1006             // the middle of a word and then word-selecting forward, leaving the caret in the
   1007             // same place where it was, instead of directly selecting to the end of the word.
   1008             VisibleSelection newSelection = m_selection;
   1009             newSelection.setExtent(position);
   1010             if (m_selection.isBaseFirst() != newSelection.isBaseFirst())
   1011                 position = m_selection.visibleBase();
   1012         }
   1013 
   1014         // Standard Mac behavior when extending to a boundary is grow the selection rather than leaving the
   1015         // base in place and moving the extent. Matches NSTextView.
   1016         if (!m_frame || !m_frame->editor().behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
   1017             setExtent(position, userTriggered);
   1018         else {
   1019             TextDirection textDirection = directionOfEnclosingBlock();
   1020             if (direction == DirectionForward || (textDirection == LTR && direction == DirectionRight) || (textDirection == RTL && direction == DirectionLeft))
   1021                 setEnd(position, userTriggered);
   1022             else
   1023                 setStart(position, userTriggered);
   1024         }
   1025         break;
   1026     }
   1027 
   1028     if (granularity == LineGranularity || granularity == ParagraphGranularity)
   1029         m_xPosForVerticalArrowNavigation = x;
   1030 
   1031     if (userTriggered == UserTriggered)
   1032         m_granularity = CharacterGranularity;
   1033 
   1034     setCaretRectNeedsUpdate();
   1035 
   1036     return true;
   1037 }
   1038 
   1039 // FIXME: Maybe baseline would be better?
   1040 static bool absoluteCaretY(const VisiblePosition &c, int &y)
   1041 {
   1042     IntRect rect = c.absoluteCaretBounds();
   1043     if (rect.isEmpty())
   1044         return false;
   1045     y = rect.y() + rect.height() / 2;
   1046     return true;
   1047 }
   1048 
   1049 bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, VerticalDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align)
   1050 {
   1051     if (!verticalDistance)
   1052         return false;
   1053 
   1054     if (userTriggered == UserTriggered) {
   1055         OwnPtrWillBeRawPtr<FrameSelection> trialFrameSelection = FrameSelection::create();
   1056         trialFrameSelection->setSelection(m_selection);
   1057         trialFrameSelection->modify(alter, verticalDistance, direction, NotUserTriggered);
   1058     }
   1059 
   1060     willBeModified(alter, direction == DirectionUp ? DirectionBackward : DirectionForward);
   1061 
   1062     VisiblePosition pos;
   1063     LayoutUnit xPos = 0;
   1064     switch (alter) {
   1065     case AlterationMove:
   1066         pos = VisiblePosition(direction == DirectionUp ? m_selection.start() : m_selection.end(), m_selection.affinity());
   1067         xPos = lineDirectionPointForBlockDirectionNavigation(direction == DirectionUp ? START : END);
   1068         m_selection.setAffinity(direction == DirectionUp ? UPSTREAM : DOWNSTREAM);
   1069         break;
   1070     case AlterationExtend:
   1071         pos = VisiblePosition(m_selection.extent(), m_selection.affinity());
   1072         xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
   1073         m_selection.setAffinity(DOWNSTREAM);
   1074         break;
   1075     }
   1076 
   1077     int startY;
   1078     if (!absoluteCaretY(pos, startY))
   1079         return false;
   1080     if (direction == DirectionUp)
   1081         startY = -startY;
   1082     int lastY = startY;
   1083 
   1084     VisiblePosition result;
   1085     VisiblePosition next;
   1086     for (VisiblePosition p = pos; ; p = next) {
   1087         if (direction == DirectionUp)
   1088             next = previousLinePosition(p, xPos);
   1089         else
   1090             next = nextLinePosition(p, xPos);
   1091 
   1092         if (next.isNull() || next == p)
   1093             break;
   1094         int nextY;
   1095         if (!absoluteCaretY(next, nextY))
   1096             break;
   1097         if (direction == DirectionUp)
   1098             nextY = -nextY;
   1099         if (nextY - startY > static_cast<int>(verticalDistance))
   1100             break;
   1101         if (nextY >= lastY) {
   1102             lastY = nextY;
   1103             result = next;
   1104         }
   1105     }
   1106 
   1107     if (result.isNull())
   1108         return false;
   1109 
   1110     switch (alter) {
   1111     case AlterationMove:
   1112         moveTo(result, userTriggered, align);
   1113         break;
   1114     case AlterationExtend:
   1115         setExtent(result, userTriggered);
   1116         break;
   1117     }
   1118 
   1119     if (userTriggered == UserTriggered)
   1120         m_granularity = CharacterGranularity;
   1121 
   1122     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
   1123 
   1124     return true;
   1125 }
   1126 
   1127 LayoutUnit FrameSelection::lineDirectionPointForBlockDirectionNavigation(EPositionType type)
   1128 {
   1129     LayoutUnit x = 0;
   1130 
   1131     if (isNone())
   1132         return x;
   1133 
   1134     Position pos;
   1135     switch (type) {
   1136     case START:
   1137         pos = m_selection.start();
   1138         break;
   1139     case END:
   1140         pos = m_selection.end();
   1141         break;
   1142     case BASE:
   1143         pos = m_selection.base();
   1144         break;
   1145     case EXTENT:
   1146         pos = m_selection.extent();
   1147         break;
   1148     }
   1149 
   1150     LocalFrame* frame = pos.document()->frame();
   1151     if (!frame)
   1152         return x;
   1153 
   1154     if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation()) {
   1155         VisiblePosition visiblePosition(pos, m_selection.affinity());
   1156         // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
   1157         // after the selection is created and before this function is called.
   1158         x = visiblePosition.isNotNull() ? visiblePosition.lineDirectionPointForBlockDirectionNavigation() : 0;
   1159         m_xPosForVerticalArrowNavigation = x;
   1160     } else
   1161         x = m_xPosForVerticalArrowNavigation;
   1162 
   1163     return x;
   1164 }
   1165 
   1166 void FrameSelection::clear()
   1167 {
   1168     m_granularity = CharacterGranularity;
   1169     setSelection(VisibleSelection());
   1170 }
   1171 
   1172 void FrameSelection::prepareForDestruction()
   1173 {
   1174     m_granularity = CharacterGranularity;
   1175 
   1176     m_caretBlinkTimer.stop();
   1177 
   1178     RenderView* view = m_frame->contentRenderer();
   1179     if (view)
   1180         view->clearSelection();
   1181 
   1182     setSelection(VisibleSelection(), CloseTyping | ClearTypingStyle | DoNotUpdateAppearance);
   1183     m_previousCaretNode.clear();
   1184 }
   1185 
   1186 void FrameSelection::setStart(const VisiblePosition &pos, EUserTriggered trigger)
   1187 {
   1188     if (m_selection.isBaseFirst())
   1189         setBase(pos, trigger);
   1190     else
   1191         setExtent(pos, trigger);
   1192 }
   1193 
   1194 void FrameSelection::setEnd(const VisiblePosition &pos, EUserTriggered trigger)
   1195 {
   1196     if (m_selection.isBaseFirst())
   1197         setExtent(pos, trigger);
   1198     else
   1199         setBase(pos, trigger);
   1200 }
   1201 
   1202 void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTriggered)
   1203 {
   1204     const bool selectionHasDirection = true;
   1205     setSelection(VisibleSelection(pos.deepEquivalent(), m_selection.extent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
   1206 }
   1207 
   1208 void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTriggered)
   1209 {
   1210     const bool selectionHasDirection = true;
   1211     setSelection(VisibleSelection(m_selection.base(), pos.deepEquivalent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
   1212 }
   1213 
   1214 RenderBlock* FrameSelection::caretRenderer() const
   1215 {
   1216     return CaretBase::caretRenderer(m_selection.start().deprecatedNode());
   1217 }
   1218 
   1219 static bool isNonOrphanedCaret(const VisibleSelection& selection)
   1220 {
   1221     return selection.isCaret() && !selection.start().isOrphan() && !selection.end().isOrphan();
   1222 }
   1223 
   1224 static bool isTextFormControl(const VisibleSelection& selection)
   1225 {
   1226     return enclosingTextFormControl(selection.start());
   1227 }
   1228 
   1229 IntRect FrameSelection::absoluteCaretBounds()
   1230 {
   1231     ASSERT(m_frame->document()->lifecycle().state() != DocumentLifecycle::InPaintInvalidation);
   1232     m_frame->document()->updateLayoutIgnorePendingStylesheets();
   1233     if (!isNonOrphanedCaret(m_selection)) {
   1234         clearCaretRect();
   1235     } else {
   1236         if (isTextFormControl(m_selection))
   1237             updateCaretRect(m_frame->document(), PositionWithAffinity(m_selection.start().isCandidate() ? m_selection.start() : Position(), m_selection.affinity()));
   1238         else
   1239             updateCaretRect(m_frame->document(), VisiblePosition(m_selection.start(), m_selection.affinity()));
   1240     }
   1241     return absoluteBoundsForLocalRect(m_selection.start().deprecatedNode(), localCaretRectWithoutUpdate());
   1242 }
   1243 
   1244 static LayoutRect localCaretRect(const VisibleSelection& m_selection, const PositionWithAffinity& caretPosition, RenderObject*& renderer)
   1245 {
   1246     renderer = nullptr;
   1247     if (!isNonOrphanedCaret(m_selection))
   1248         return LayoutRect();
   1249 
   1250     return localCaretRectOfPosition(caretPosition, renderer);
   1251 }
   1252 
   1253 void FrameSelection::invalidateCaretRect()
   1254 {
   1255     if (!m_caretRectDirty)
   1256         return;
   1257     m_caretRectDirty = false;
   1258 
   1259     RenderObject* renderer = nullptr;
   1260     LayoutRect newRect = localCaretRect(m_selection, PositionWithAffinity(m_selection.start(), m_selection.affinity()), renderer);
   1261     Node* newNode = renderer ? renderer->node() : nullptr;
   1262 
   1263     if (!m_caretBlinkTimer.isActive() && newNode == m_previousCaretNode && newRect == m_previousCaretRect)
   1264         return;
   1265 
   1266     RenderView* view = m_frame->document()->renderView();
   1267     if (m_previousCaretNode && shouldRepaintCaret(view, m_previousCaretNode->isContentEditable()))
   1268         invalidateLocalCaretRect(m_previousCaretNode.get(), m_previousCaretRect);
   1269     if (newNode && shouldRepaintCaret(view, newNode->isContentEditable()))
   1270         invalidateLocalCaretRect(newNode, newRect);
   1271 
   1272     m_previousCaretNode = newNode;
   1273     m_previousCaretRect = newRect;
   1274 }
   1275 
   1276 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
   1277 {
   1278     if (m_selection.isCaret() && m_shouldPaintCaret) {
   1279         updateCaretRect(m_frame->document(), PositionWithAffinity(m_selection.start(), m_selection.affinity()));
   1280         CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
   1281     }
   1282 }
   1283 
   1284 bool FrameSelection::contains(const LayoutPoint& point)
   1285 {
   1286     Document* document = m_frame->document();
   1287 
   1288     // Treat a collapsed selection like no selection.
   1289     if (!isRange())
   1290         return false;
   1291     if (!document->renderView())
   1292         return false;
   1293 
   1294     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
   1295     HitTestResult result(point);
   1296     document->renderView()->hitTest(request, result);
   1297     Node* innerNode = result.innerNode();
   1298     if (!innerNode || !innerNode->renderer())
   1299         return false;
   1300 
   1301     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));
   1302     if (visiblePos.isNull())
   1303         return false;
   1304 
   1305     if (m_selection.visibleStart().isNull() || m_selection.visibleEnd().isNull())
   1306         return false;
   1307 
   1308     Position start(m_selection.visibleStart().deepEquivalent());
   1309     Position end(m_selection.visibleEnd().deepEquivalent());
   1310     Position p(visiblePos.deepEquivalent());
   1311 
   1312     return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
   1313 }
   1314 
   1315 // Workaround for the fact that it's hard to delete a frame.
   1316 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
   1317 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
   1318 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
   1319 // mouse or the keyboard after setting the selection.
   1320 void FrameSelection::selectFrameElementInParentIfFullySelected()
   1321 {
   1322     // Find the parent frame; if there is none, then we have nothing to do.
   1323     Frame* parent = m_frame->tree().parent();
   1324     if (!parent)
   1325         return;
   1326     Page* page = m_frame->page();
   1327     if (!page)
   1328         return;
   1329 
   1330     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
   1331     if (!isRange())
   1332         return;
   1333     if (!isStartOfDocument(selection().visibleStart()))
   1334         return;
   1335     if (!isEndOfDocument(selection().visibleEnd()))
   1336         return;
   1337 
   1338     // FIXME: This is not yet implemented for cross-process frame relationships.
   1339     if (!parent->isLocalFrame())
   1340         return;
   1341 
   1342     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
   1343     // FIXME: Doesn't work for OOPI.
   1344     HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
   1345     if (!ownerElement)
   1346         return;
   1347     ContainerNode* ownerElementParent = ownerElement->parentNode();
   1348     if (!ownerElementParent)
   1349         return;
   1350 
   1351     // 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.
   1352     if (!ownerElementParent->hasEditableStyle())
   1353         return;
   1354 
   1355     // Create compute positions before and after the element.
   1356     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
   1357     VisiblePosition beforeOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex, Position::PositionIsOffsetInAnchor)));
   1358     VisiblePosition afterOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex + 1, Position::PositionIsOffsetInAnchor), VP_UPSTREAM_IF_POSSIBLE));
   1359 
   1360     // Focus on the parent frame, and then select from before this element to after.
   1361     VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
   1362     page->focusController().setFocusedFrame(parent);
   1363     toLocalFrame(parent)->selection().setSelection(newSelection);
   1364 }
   1365 
   1366 void FrameSelection::selectAll()
   1367 {
   1368     Document* document = m_frame->document();
   1369 
   1370     if (isHTMLSelectElement(document->focusedElement())) {
   1371         HTMLSelectElement* selectElement = toHTMLSelectElement(document->focusedElement());
   1372         if (selectElement->canSelectAll()) {
   1373             selectElement->selectAll();
   1374             return;
   1375         }
   1376     }
   1377 
   1378     RefPtrWillBeRawPtr<Node> root = nullptr;
   1379     Node* selectStartTarget = 0;
   1380     if (isContentEditable()) {
   1381         root = highestEditableRoot(m_selection.start());
   1382         if (Node* shadowRoot = m_selection.nonBoundaryShadowTreeRootNode())
   1383             selectStartTarget = shadowRoot->shadowHost();
   1384         else
   1385             selectStartTarget = root.get();
   1386     } else {
   1387         root = m_selection.nonBoundaryShadowTreeRootNode();
   1388         if (root)
   1389             selectStartTarget = root->shadowHost();
   1390         else {
   1391             root = document->documentElement();
   1392             selectStartTarget = document->body();
   1393         }
   1394     }
   1395     if (!root)
   1396         return;
   1397 
   1398     if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::createCancelableBubble(EventTypeNames::selectstart)))
   1399         return;
   1400 
   1401     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root.get()));
   1402     setSelection(newSelection);
   1403     selectFrameElementInParentIfFullySelected();
   1404     notifyRendererOfSelectionChange(UserTriggered);
   1405 }
   1406 
   1407 bool FrameSelection::setSelectedRange(Range* range, EAffinity affinity, DirectoinalOption directional, SetSelectionOptions options)
   1408 {
   1409     if (!range || !range->startContainer() || !range->endContainer())
   1410         return false;
   1411     ASSERT(range->startContainer()->document() == range->endContainer()->document());
   1412 
   1413     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
   1414     // they start at the beginning of the next line instead
   1415     m_logicalRange = nullptr;
   1416     stopObservingVisibleSelectionChangeIfNecessary();
   1417 
   1418     VisibleSelection newSelection(range, affinity, directional == Directional);
   1419     setSelection(newSelection, options);
   1420 
   1421     m_logicalRange = range->cloneRange();
   1422     startObservingVisibleSelectionChange();
   1423 
   1424     return true;
   1425 }
   1426 
   1427 PassRefPtrWillBeRawPtr<Range> FrameSelection::firstRange() const
   1428 {
   1429     if (m_logicalRange)
   1430         return m_logicalRange->cloneRange();
   1431     return m_selection.firstRange();
   1432 }
   1433 
   1434 bool FrameSelection::isInPasswordField() const
   1435 {
   1436     HTMLTextFormControlElement* textControl = enclosingTextFormControl(start());
   1437     return isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->type() == InputTypeNames::password;
   1438 }
   1439 
   1440 void FrameSelection::notifyAccessibilityForSelectionChange()
   1441 {
   1442     if (m_selection.start().isNotNull() && m_selection.end().isNotNull()) {
   1443         if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
   1444             cache->selectionChanged(m_selection.start().containerNode());
   1445     }
   1446 }
   1447 
   1448 void FrameSelection::notifyCompositorForSelectionChange()
   1449 {
   1450     if (!RuntimeEnabledFeatures::compositedSelectionUpdateEnabled())
   1451         return;
   1452 
   1453     scheduleVisualUpdate();
   1454 }
   1455 
   1456 void FrameSelection::notifyEventHandlerForSelectionChange()
   1457 {
   1458     m_frame->eventHandler().notifySelectionChanged();
   1459 }
   1460 
   1461 void FrameSelection::focusedOrActiveStateChanged()
   1462 {
   1463     bool activeAndFocused = isFocusedAndActive();
   1464 
   1465     RefPtrWillBeRawPtr<Document> document = m_frame->document();
   1466     document->updateRenderTreeIfNeeded();
   1467 
   1468     // Because RenderObject::selectionBackgroundColor() and
   1469     // RenderObject::selectionForegroundColor() check if the frame is active,
   1470     // we have to update places those colors were painted.
   1471     if (RenderView* view = document->renderView())
   1472         view->invalidatePaintForSelection();
   1473 
   1474     // Caret appears in the active frame.
   1475     if (activeAndFocused)
   1476         setSelectionFromNone();
   1477     else
   1478         m_frame->spellChecker().spellCheckAfterBlur();
   1479     setCaretVisibility(activeAndFocused ? Visible : Hidden);
   1480 
   1481     // Update for caps lock state
   1482     m_frame->eventHandler().capsLockStateMayHaveChanged();
   1483 
   1484     // We may have lost active status even though the focusElement hasn't changed
   1485     // give the element a chance to recalc style if its affected by focus.
   1486     if (Element* element = document->focusedElement())
   1487         element->focusStateChanged();
   1488 
   1489     // Secure keyboard entry is set by the active frame.
   1490     if (document->useSecureKeyboardEntryWhenActive())
   1491         setUseSecureKeyboardEntry(activeAndFocused);
   1492 }
   1493 
   1494 void FrameSelection::pageActivationChanged()
   1495 {
   1496     focusedOrActiveStateChanged();
   1497 }
   1498 
   1499 void FrameSelection::updateSecureKeyboardEntryIfActive()
   1500 {
   1501     if (m_frame->document() && isFocusedAndActive())
   1502         setUseSecureKeyboardEntry(m_frame->document()->useSecureKeyboardEntryWhenActive());
   1503 }
   1504 
   1505 void FrameSelection::setUseSecureKeyboardEntry(bool enable)
   1506 {
   1507     if (enable)
   1508         enableSecureTextInput();
   1509     else
   1510         disableSecureTextInput();
   1511 }
   1512 
   1513 void FrameSelection::setFocused(bool flag)
   1514 {
   1515     if (m_focused == flag)
   1516         return;
   1517     m_focused = flag;
   1518 
   1519     focusedOrActiveStateChanged();
   1520 }
   1521 
   1522 bool FrameSelection::isFocusedAndActive() const
   1523 {
   1524     return m_focused && m_frame->page() && m_frame->page()->focusController().isActive();
   1525 }
   1526 
   1527 inline static bool shouldStopBlinkingDueToTypingCommand(LocalFrame* frame)
   1528 {
   1529     return frame->editor().lastEditCommand() && frame->editor().lastEditCommand()->shouldStopCaretBlinking();
   1530 }
   1531 
   1532 void FrameSelection::updateAppearance(ResetCaretBlinkOption option)
   1533 {
   1534     // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case
   1535     // the FrameSelection will paint a blinking caret as usual).
   1536     bool paintBlockCursor = m_shouldShowBlockCursor && m_selection.isCaret() && !isLogicalEndOfLine(m_selection.visibleEnd());
   1537 
   1538     bool shouldBlink = !paintBlockCursor && shouldBlinkCaret();
   1539 
   1540     bool willNeedCaretRectUpdate = false;
   1541 
   1542     // If the caret moved, stop the blink timer so we can restart with a
   1543     // black caret in the new location.
   1544     if (option == ResetCaretBlink || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame)) {
   1545         m_caretBlinkTimer.stop();
   1546 
   1547         m_shouldPaintCaret = false;
   1548         willNeedCaretRectUpdate = true;
   1549     }
   1550 
   1551     // Start blinking with a black caret. Be sure not to restart if we're
   1552     // already blinking in the right location.
   1553     if (shouldBlink && !m_caretBlinkTimer.isActive()) {
   1554         if (double blinkInterval = RenderTheme::theme().caretBlinkInterval())
   1555             m_caretBlinkTimer.startRepeating(blinkInterval, FROM_HERE);
   1556 
   1557         m_shouldPaintCaret = true;
   1558         willNeedCaretRectUpdate = true;
   1559     }
   1560 
   1561     if (willNeedCaretRectUpdate)
   1562         setCaretRectNeedsUpdate();
   1563 
   1564     RenderView* view = m_frame->contentRenderer();
   1565     if (!view)
   1566         return;
   1567 
   1568     // Construct a new VisibleSolution, since m_selection is not necessarily valid, and the following steps
   1569     // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69563> and <rdar://problem/10232866>.
   1570 
   1571     VisibleSelection selection;
   1572     if (isTextFormControl(m_selection)) {
   1573         Position endPosition = paintBlockCursor ? m_selection.extent().next() : m_selection.end();
   1574         selection.setWithoutValidation(m_selection.start(), endPosition);
   1575     } else {
   1576         VisiblePosition endVisiblePosition = paintBlockCursor ? modifyExtendingForward(CharacterGranularity) : m_selection.visibleEnd();
   1577         selection = VisibleSelection(m_selection.visibleStart(), endVisiblePosition);
   1578     }
   1579 
   1580     if (!selection.isRange()) {
   1581         view->clearSelection();
   1582         return;
   1583     }
   1584 
   1585     m_frame->document()->updateLayoutIgnorePendingStylesheets();
   1586 
   1587     // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
   1588     // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
   1589     // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
   1590     // and will fill the gap before 'bar'.
   1591     Position startPos = selection.start();
   1592     Position candidate = startPos.downstream();
   1593     if (candidate.isCandidate())
   1594         startPos = candidate;
   1595     Position endPos = selection.end();
   1596     candidate = endPos.upstream();
   1597     if (candidate.isCandidate())
   1598         endPos = candidate;
   1599 
   1600     // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
   1601     // because we don't yet notify the FrameSelection of text removal.
   1602     if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
   1603         RenderObject* startRenderer = startPos.deprecatedNode()->renderer();
   1604         RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
   1605         if (startRenderer && endRenderer && startRenderer->view() == view && endRenderer->view() == view)
   1606             view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset());
   1607     }
   1608 }
   1609 
   1610 void FrameSelection::setCaretVisibility(CaretVisibility visibility)
   1611 {
   1612     if (caretVisibility() == visibility)
   1613         return;
   1614 
   1615     CaretBase::setCaretVisibility(visibility);
   1616 
   1617     updateAppearance();
   1618 }
   1619 
   1620 bool FrameSelection::shouldBlinkCaret() const
   1621 {
   1622     if (!caretIsVisible() || !isCaret())
   1623         return false;
   1624 
   1625     if (m_frame->settings() && m_frame->settings()->caretBrowsingEnabled())
   1626         return false;
   1627 
   1628     Element* root = rootEditableElement();
   1629     if (!root)
   1630         return false;
   1631 
   1632     Element* focusedElement = root->document().focusedElement();
   1633     if (!focusedElement)
   1634         return false;
   1635 
   1636     return focusedElement->containsIncludingShadowDOM(m_selection.start().anchorNode());
   1637 }
   1638 
   1639 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*)
   1640 {
   1641     ASSERT(caretIsVisible());
   1642     ASSERT(isCaret());
   1643     if (isCaretBlinkingSuspended() && m_shouldPaintCaret)
   1644         return;
   1645     m_shouldPaintCaret = !m_shouldPaintCaret;
   1646     setCaretRectNeedsUpdate();
   1647 }
   1648 
   1649 void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggered)
   1650 {
   1651     if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start()))
   1652         textControl->selectionChanged(userTriggered == UserTriggered);
   1653 }
   1654 
   1655 // Helper function that tells whether a particular node is an element that has an entire
   1656 // LocalFrame and FrameView, a <frame>, <iframe>, or <object>.
   1657 static bool isFrameElement(const Node* n)
   1658 {
   1659     if (!n)
   1660         return false;
   1661     RenderObject* renderer = n->renderer();
   1662     if (!renderer || !renderer->isWidget())
   1663         return false;
   1664     Widget* widget = toRenderWidget(renderer)->widget();
   1665     return widget && widget->isFrameView();
   1666 }
   1667 
   1668 void FrameSelection::setFocusedNodeIfNeeded()
   1669 {
   1670     if (isNone() || !isFocused())
   1671         return;
   1672 
   1673     bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
   1674     if (caretBrowsing) {
   1675         if (Element* anchor = enclosingAnchorElement(base())) {
   1676             m_frame->page()->focusController().setFocusedElement(anchor, m_frame);
   1677             return;
   1678         }
   1679     }
   1680 
   1681     if (Element* target = rootEditableElement()) {
   1682         // Walk up the DOM tree to search for a node to focus.
   1683         while (target) {
   1684             // We don't want to set focus on a subframe when selecting in a parent frame,
   1685             // so add the !isFrameElement check here. There's probably a better way to make this
   1686             // work in the long term, but this is the safest fix at this time.
   1687             if (target->isMouseFocusable() && !isFrameElement(target)) {
   1688                 m_frame->page()->focusController().setFocusedElement(target, m_frame);
   1689                 return;
   1690             }
   1691             target = target->parentOrShadowHostElement();
   1692         }
   1693         m_frame->document()->setFocusedElement(nullptr);
   1694     }
   1695 
   1696     if (caretBrowsing)
   1697         m_frame->page()->focusController().setFocusedElement(0, m_frame);
   1698 }
   1699 
   1700 static String extractSelectedText(const FrameSelection& selection, TextIteratorBehavior behavior)
   1701 {
   1702     // We remove '\0' characters because they are not visibly rendered to the user.
   1703     return plainText(selection.toNormalizedRange().get(), behavior).replace(0, "");
   1704 }
   1705 
   1706 String FrameSelection::selectedText() const
   1707 {
   1708     return extractSelectedText(*this, TextIteratorDefaultBehavior);
   1709 }
   1710 
   1711 String FrameSelection::selectedTextForClipboard() const
   1712 {
   1713     if (m_frame->settings() && m_frame->settings()->selectionIncludesAltImageText())
   1714         return extractSelectedText(*this, TextIteratorEmitsImageAltText);
   1715     return selectedText();
   1716 }
   1717 
   1718 FloatRect FrameSelection::bounds() const
   1719 {
   1720     m_frame->document()->updateRenderTreeIfNeeded();
   1721 
   1722     FrameView* view = m_frame->view();
   1723     RenderView* renderView = m_frame->contentRenderer();
   1724 
   1725     if (!view || !renderView)
   1726         return FloatRect();
   1727 
   1728     LayoutRect selectionRect = renderView->selectionBounds();
   1729     return selectionRect;
   1730 }
   1731 
   1732 static inline HTMLFormElement* associatedFormElement(HTMLElement& element)
   1733 {
   1734     if (isHTMLFormElement(element))
   1735         return &toHTMLFormElement(element);
   1736     return element.formOwner();
   1737 }
   1738 
   1739 // Scans logically forward from "start", including any child frames.
   1740 static HTMLFormElement* scanForForm(Node* start)
   1741 {
   1742     if (!start)
   1743         return 0;
   1744 
   1745     HTMLElement* element = start->isHTMLElement() ? toHTMLElement(start) : Traversal<HTMLElement>::next(*start);
   1746     for (; element; element = Traversal<HTMLElement>::next(*element)) {
   1747         if (HTMLFormElement* form = associatedFormElement(*element))
   1748             return form;
   1749 
   1750         if (isHTMLFrameElementBase(*element)) {
   1751             Node* childDocument = toHTMLFrameElementBase(*element).contentDocument();
   1752             if (HTMLFormElement* frameResult = scanForForm(childDocument))
   1753                 return frameResult;
   1754         }
   1755     }
   1756     return 0;
   1757 }
   1758 
   1759 // We look for either the form containing the current focus, or for one immediately after it
   1760 HTMLFormElement* FrameSelection::currentForm() const
   1761 {
   1762     // Start looking either at the active (first responder) node, or where the selection is.
   1763     Node* start = m_frame->document()->focusedElement();
   1764     if (!start)
   1765         start = this->start().deprecatedNode();
   1766     if (!start)
   1767         return 0;
   1768 
   1769     // Try walking up the node tree to find a form element.
   1770     for (HTMLElement* element = Traversal<HTMLElement>::firstAncestorOrSelf(*start); element; element = Traversal<HTMLElement>::firstAncestor(*element)) {
   1771         if (HTMLFormElement* form = associatedFormElement(*element))
   1772             return form;
   1773     }
   1774 
   1775     // Try walking forward in the node tree to find a form element.
   1776     return scanForForm(start);
   1777 }
   1778 
   1779 void FrameSelection::revealSelection(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
   1780 {
   1781     LayoutRect rect;
   1782 
   1783     switch (selectionType()) {
   1784     case NoSelection:
   1785         return;
   1786     case CaretSelection:
   1787         rect = absoluteCaretBounds();
   1788         break;
   1789     case RangeSelection:
   1790         rect = revealExtentOption == RevealExtent ? VisiblePosition(extent()).absoluteCaretBounds() : enclosingIntRect(bounds());
   1791         break;
   1792     }
   1793 
   1794     Position start = this->start();
   1795     ASSERT(start.deprecatedNode());
   1796     if (start.deprecatedNode() && start.deprecatedNode()->renderer()) {
   1797         // FIXME: This code only handles scrolling the startContainer's layer, but
   1798         // the selection rect could intersect more than just that.
   1799         // See <rdar://problem/4799899>.
   1800         if (start.deprecatedNode()->renderer()->scrollRectToVisible(rect, alignment, alignment))
   1801             updateAppearance();
   1802     }
   1803 }
   1804 
   1805 void FrameSelection::setSelectionFromNone()
   1806 {
   1807     // Put a caret inside the body if the entire frame is editable (either the
   1808     // entire WebView is editable or designMode is on for this document).
   1809 
   1810     Document* document = m_frame->document();
   1811     bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
   1812     if (!isNone() || !(document->hasEditableStyle() || caretBrowsing))
   1813         return;
   1814 
   1815     Element* documentElement = document->documentElement();
   1816     if (!documentElement)
   1817         return;
   1818     if (HTMLBodyElement* body = Traversal<HTMLBodyElement>::firstChild(*documentElement))
   1819         setSelection(VisibleSelection(firstPositionInOrBeforeNode(body), DOWNSTREAM));
   1820 }
   1821 
   1822 bool FrameSelection::dispatchSelectStart()
   1823 {
   1824     Node* selectStartTarget = m_selection.extent().containerNode();
   1825     if (!selectStartTarget)
   1826         return true;
   1827 
   1828     return selectStartTarget->dispatchEvent(Event::createCancelableBubble(EventTypeNames::selectstart));
   1829 }
   1830 
   1831 void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor)
   1832 {
   1833     m_shouldShowBlockCursor = shouldShowBlockCursor;
   1834 
   1835     m_frame->document()->updateLayoutIgnorePendingStylesheets();
   1836 
   1837     updateAppearance();
   1838 }
   1839 
   1840 void FrameSelection::didChangeVisibleSelection()
   1841 {
   1842     ASSERT(m_observingVisibleSelection);
   1843     // Invalidate the logical range when the underlying VisibleSelection has changed.
   1844     m_logicalRange = nullptr;
   1845     m_selection.clearChangeObserver();
   1846     m_observingVisibleSelection = false;
   1847 }
   1848 
   1849 VisibleSelection FrameSelection::validateSelection(const VisibleSelection& selection)
   1850 {
   1851     if (!m_frame || selection.isNone())
   1852         return selection;
   1853 
   1854     Position base = selection.base();
   1855     Position extent = selection.extent();
   1856     bool isBaseValid = base.document() == m_frame->document();
   1857     bool isExtentValid = extent.document() == m_frame->document();
   1858 
   1859     if (isBaseValid && isExtentValid)
   1860         return selection;
   1861 
   1862     VisibleSelection newSelection;
   1863     if (isBaseValid) {
   1864         newSelection.setWithoutValidation(base, base);
   1865     } else if (isExtentValid) {
   1866         newSelection.setWithoutValidation(extent, extent);
   1867     }
   1868     return newSelection;
   1869 }
   1870 
   1871 void FrameSelection::startObservingVisibleSelectionChange()
   1872 {
   1873     ASSERT(!m_observingVisibleSelection);
   1874     m_selection.setChangeObserver(*this);
   1875     m_observingVisibleSelection = true;
   1876 }
   1877 
   1878 void FrameSelection::stopObservingVisibleSelectionChangeIfNecessary()
   1879 {
   1880     if (m_observingVisibleSelection) {
   1881         m_selection.clearChangeObserver();
   1882         m_observingVisibleSelection = false;
   1883     }
   1884 }
   1885 
   1886 #ifndef NDEBUG
   1887 
   1888 void FrameSelection::formatForDebugger(char* buffer, unsigned length) const
   1889 {
   1890     m_selection.formatForDebugger(buffer, length);
   1891 }
   1892 
   1893 void FrameSelection::showTreeForThis() const
   1894 {
   1895     m_selection.showTreeForThis();
   1896 }
   1897 
   1898 #endif
   1899 
   1900 void FrameSelection::trace(Visitor* visitor)
   1901 {
   1902     visitor->trace(m_frame);
   1903     visitor->trace(m_selection);
   1904     visitor->trace(m_originalBase);
   1905     visitor->trace(m_logicalRange);
   1906     visitor->trace(m_previousCaretNode);
   1907     visitor->trace(m_typingStyle);
   1908     VisibleSelection::ChangeObserver::trace(visitor);
   1909 }
   1910 
   1911 void FrameSelection::setCaretRectNeedsUpdate()
   1912 {
   1913     m_caretRectDirty = true;
   1914 
   1915     scheduleVisualUpdate();
   1916 }
   1917 
   1918 void FrameSelection::scheduleVisualUpdate() const
   1919 {
   1920     if (!m_frame)
   1921         return;
   1922     if (Page* page = m_frame->page())
   1923         page->animator().scheduleVisualUpdate();
   1924 }
   1925 
   1926 }
   1927 
   1928 #ifndef NDEBUG
   1929 
   1930 void showTree(const blink::FrameSelection& sel)
   1931 {
   1932     sel.showTreeForThis();
   1933 }
   1934 
   1935 void showTree(const blink::FrameSelection* sel)
   1936 {
   1937     if (sel)
   1938         sel->showTreeForThis();
   1939 }
   1940 
   1941 #endif
   1942