| Index: third_party/WebKit/Source/core/editing/SelectionController.cpp | 
| diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp | 
| index ed0c5498987322c3de0cf1de759fd8c68caeeec3..ad43105df5bb556d46b4bf365cb9fda12a595293 100644 | 
| --- a/third_party/WebKit/Source/core/editing/SelectionController.cpp | 
| +++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp | 
| @@ -167,16 +167,6 @@ bool SelectionController::handleMousePressEventSingleClick( | 
| // link or image. | 
| bool extendSelection = isExtendingSelection(event); | 
|  | 
| -  // Don't restart the selection when the mouse is pressed on an | 
| -  // existing selection so we can allow for text dragging. | 
| -  if (FrameView* view = m_frame->view()) { | 
| -    LayoutPoint vPoint = view->rootFrameToContents(event.event().position()); | 
| -    if (!extendSelection && selection().contains(vPoint)) { | 
| -      m_mouseDownWasSingleClickInSelection = true; | 
| -      return false; | 
| -    } | 
| -  } | 
| - | 
| const VisiblePositionInFlatTree& visibleHitPos = | 
| visiblePositionOfHitTestResult(event.hitTestResult()); | 
| const VisiblePositionInFlatTree& visiblePos = | 
| @@ -187,6 +177,21 @@ bool SelectionController::handleMousePressEventSingleClick( | 
| const VisibleSelectionInFlatTree& selection = | 
| this->selection().visibleSelection<EditingInFlatTreeStrategy>(); | 
|  | 
| +  // Don't restart the selection when the mouse is pressed on an | 
| +  // existing selection so we can allow for text dragging. | 
| +  if (!extendSelection && this->selection().contains(event.hitTestResult())) { | 
| +    m_mouseDownWasSingleClickInSelection = true; | 
| +    if (!event.event().fromTouch()) | 
| +      return false; | 
| + | 
| +    if (!this->selection().isHandleVisible()) { | 
| +      updateSelectionForMouseDownDispatchingSelectStart( | 
| +          innerNode, selection, CharacterGranularity, | 
| +          HandleVisibility::Visible); | 
| +      return false; | 
| +    } | 
| +  } | 
| + | 
| if (extendSelection && !selection.isNone()) { | 
| // Note: "fast/events/shift-click-user-select-none.html" makes | 
| // |pos.isNull()| true. | 
| @@ -211,22 +216,37 @@ bool SelectionController::handleMousePressEventSingleClick( | 
|  | 
| updateSelectionForMouseDownDispatchingSelectStart( | 
| innerNode, createVisibleSelection(builder.build()), | 
| -        this->selection().granularity()); | 
| +        this->selection().granularity(), HandleVisibility::NotVisible); | 
| return false; | 
| } | 
|  | 
| if (m_selectionState == SelectionState::ExtendedSelection) { | 
| -    updateSelectionForMouseDownDispatchingSelectStart(innerNode, selection, | 
| -                                                      CharacterGranularity); | 
| +    updateSelectionForMouseDownDispatchingSelectStart( | 
| +        innerNode, selection, CharacterGranularity, | 
| +        HandleVisibility::NotVisible); | 
| return false; | 
| } | 
|  | 
| if (visiblePos.isNull()) { | 
| updateSelectionForMouseDownDispatchingSelectStart( | 
| -        innerNode, VisibleSelectionInFlatTree(), CharacterGranularity); | 
| +        innerNode, VisibleSelectionInFlatTree(), CharacterGranularity, | 
| +        HandleVisibility::NotVisible); | 
| return false; | 
| } | 
|  | 
| +  bool isHandleVisible = false; | 
| +  if (hasEditableStyle(*innerNode)) { | 
| +    const bool isTextBoxEmpty = | 
| +        createVisibleSelection(SelectionInFlatTree::Builder() | 
| +                                   .selectAllChildren(*innerNode) | 
| +                                   .build()) | 
| +            .isCaret(); | 
| +    const bool notLeftClick = event.event().pointerProperties().button != | 
| +                              WebPointerProperties::Button::Left; | 
| +    if (!isTextBoxEmpty || notLeftClick) | 
| +      isHandleVisible = event.event().fromTouch(); | 
| +  } | 
| + | 
| updateSelectionForMouseDownDispatchingSelectStart( | 
| innerNode, | 
| expandSelectionToRespectUserSelectAll( | 
| @@ -234,7 +254,8 @@ bool SelectionController::handleMousePressEventSingleClick( | 
| SelectionInFlatTree::Builder() | 
| .collapse(visiblePos.toPositionWithAffinity()) | 
| .build())), | 
| -      CharacterGranularity); | 
| +      CharacterGranularity, isHandleVisible ? HandleVisibility::Visible | 
| +                                            : HandleVisibility::NotVisible); | 
| return false; | 
| } | 
|  | 
| @@ -364,13 +385,15 @@ void SelectionController::updateSelectionForMouseDrag( | 
| } | 
|  | 
| setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(), | 
| -                                     AdjustEndpointsAtBidiBoundary); | 
| +                                     AdjustEndpointsAtBidiBoundary, | 
| +                                     HandleVisibility::NotVisible); | 
| } | 
|  | 
| bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( | 
| Node* targetNode, | 
| const VisibleSelectionInFlatTree& selection, | 
| -    TextGranularity granularity) { | 
| +    TextGranularity granularity, | 
| +    HandleVisibility handleVisibility) { | 
| if (targetNode && targetNode->layoutObject() && | 
| !targetNode->layoutObject()->isSelectable()) | 
| return false; | 
| @@ -393,7 +416,7 @@ bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( | 
| } | 
|  | 
| setNonDirectionalSelectionIfNeeded(selection, granularity, | 
| -                                     DoNotAdjustEndpoints); | 
| +                                     DoNotAdjustEndpoints, handleVisibility); | 
|  | 
| return true; | 
| } | 
| @@ -427,6 +450,7 @@ bool SelectionController::selectClosestWordFromHitTestResult( | 
| .build()); | 
| } | 
|  | 
| +  HandleVisibility visibility = HandleVisibility::NotVisible; | 
| if (selectInputEventType == SelectInputEventType::Touch) { | 
| // If node doesn't have text except space, tab or line break, do not | 
| // select that 'empty' area. | 
| @@ -444,6 +468,8 @@ bool SelectionController::selectClosestWordFromHitTestResult( | 
| newSelection.rootEditableElement()) | 
| .deepEquivalent()) | 
| return false; | 
| + | 
| +    visibility = HandleVisibility::Visible; | 
| } | 
|  | 
| if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) | 
| @@ -451,7 +477,7 @@ bool SelectionController::selectClosestWordFromHitTestResult( | 
|  | 
| return updateSelectionForMouseDownDispatchingSelectStart( | 
| innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 
| -      WordGranularity); | 
| +      WordGranularity, visibility); | 
| } | 
|  | 
| void SelectionController::selectClosestMisspellingFromHitTestResult( | 
| @@ -485,7 +511,7 @@ void SelectionController::selectClosestMisspellingFromHitTestResult( | 
|  | 
| updateSelectionForMouseDownDispatchingSelectStart( | 
| innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 
| -      WordGranularity); | 
| +      WordGranularity, HandleVisibility::NotVisible); | 
| } | 
|  | 
| void SelectionController::selectClosestWordFromMouseEvent( | 
| @@ -542,7 +568,7 @@ void SelectionController::selectClosestWordOrLinkFromMouseEvent( | 
|  | 
| updateSelectionForMouseDownDispatchingSelectStart( | 
| innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 
| -      WordGranularity); | 
| +      WordGranularity, HandleVisibility::NotVisible); | 
| } | 
|  | 
| // TODO(xiaochengh): We should not use reference to return value. | 
| @@ -600,7 +626,8 @@ static void adjustEndpointsAtBidiBoundary( | 
| void SelectionController::setNonDirectionalSelectionIfNeeded( | 
| const VisibleSelectionInFlatTree& passedNewSelection, | 
| TextGranularity granularity, | 
| -    EndPointsAdjustmentMode endpointsAdjustmentMode) { | 
| +    EndPointsAdjustmentMode endpointsAdjustmentMode, | 
| +    HandleVisibility handleVisibility) { | 
| VisibleSelectionInFlatTree newSelection = passedNewSelection; | 
| bool isDirectional = | 
| m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() || | 
| @@ -640,11 +667,16 @@ void SelectionController::setNonDirectionalSelectionIfNeeded( | 
|  | 
| // Adjusting base and extent will make newSelection always directional | 
| newSelection.setIsDirectional(isDirectional); | 
| -  if (selection().visibleSelection<EditingInFlatTreeStrategy>() == newSelection) | 
| +  const bool isHandleVisible = handleVisibility == HandleVisibility::Visible; | 
| +  if (selection().visibleSelection<EditingInFlatTreeStrategy>() == | 
| +          newSelection && | 
| +      selection().isHandleVisible() == isHandleVisible) | 
| return; | 
|  | 
| -  const FrameSelection::SetSelectionOptions options = | 
| +  FrameSelection::SetSelectionOptions options = | 
| FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle; | 
| +  if (isHandleVisible) | 
| +    options |= FrameSelection::HandleVisible; | 
| selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, | 
| granularity); | 
| } | 
| @@ -670,7 +702,7 @@ bool SelectionController::setCaretAtHitTestResult( | 
| SelectionInFlatTree::Builder() | 
| .collapse(visiblePos.toPositionWithAffinity()) | 
| .build())), | 
| -      CharacterGranularity); | 
| +      CharacterGranularity, HandleVisibility::Visible); | 
| } | 
|  | 
| bool SelectionController::handleMousePressEventDoubleClick( | 
| @@ -733,9 +765,12 @@ bool SelectionController::handleMousePressEventTripleClick( | 
| .build()); | 
| } | 
|  | 
| +  bool isHandleVisible = event.event().fromTouch() && newSelection.isRange(); | 
| + | 
| return updateSelectionForMouseDownDispatchingSelectStart( | 
| innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 
| -      ParagraphGranularity); | 
| +      ParagraphGranularity, isHandleVisible ? HandleVisibility::Visible | 
| +                                            : HandleVisibility::NotVisible); | 
| } | 
|  | 
| void SelectionController::handleMousePressEvent( | 
| @@ -945,7 +980,7 @@ void SelectionController::sendContextMenuEvent( | 
| const LayoutPoint& position) { | 
| if (!selection().isAvailable()) | 
| return; | 
| -  if (selection().contains(position) || mev.scrollbar() || | 
| +  if (selection().contains(mev.hitTestResult()) || mev.scrollbar() || | 
| // FIXME: In the editable case, word selection sometimes selects content | 
| // that isn't underneath the mouse. | 
| // If the selection is non-editable, we do word selection to make it | 
| @@ -974,8 +1009,7 @@ void SelectionController::passMousePressEventToSubframe( | 
| // greyed out even though we're clicking on the selection.  This looks | 
| // really strange (having the whole frame be greyed out), so we deselect the | 
| // selection. | 
| -  IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); | 
| -  if (!selection().contains(p)) | 
| +  if (!selection().contains(mev.hitTestResult())) | 
| return; | 
|  | 
| // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 
|  |