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