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