| Index: content/renderer/render_frame_impl.cc | 
| diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc | 
| index 6d279fe3fdb9fc05d2fec083b84e0b2317cf816d..8ba1664b9db0ca131d399b5ddaadad79ebac02af 100644 | 
| --- a/content/renderer/render_frame_impl.cc | 
| +++ b/content/renderer/render_frame_impl.cc | 
| @@ -1377,7 +1377,9 @@ void RenderFrameImpl::PepperSelectionChanged( | 
| PepperPluginInstanceImpl* instance) { | 
| if (instance != focused_pepper_plugin_) | 
| return; | 
| -  SyncSelectionIfRequired(); | 
| +  // Keep the original behavior for pepper plugins and handle all selection | 
| +  // change as user initiated. | 
| +  SyncSelectionIfRequired(true); | 
| } | 
|  | 
| RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( | 
| @@ -1961,7 +1963,9 @@ void RenderFrameImpl::OnReplace(const base::string16& text) { | 
| frame_->SelectWordAroundCaret(); | 
|  | 
| frame_->ReplaceSelection(WebString::FromUTF16(text)); | 
| -  SyncSelectionIfRequired(); | 
| +  // Handle this selection change as user initiated since typically triggered | 
| +  // from context menu. | 
| +  SyncSelectionIfRequired(true); | 
| } | 
|  | 
| void RenderFrameImpl::OnReplaceMisspelling(const base::string16& text) { | 
| @@ -2640,9 +2644,11 @@ void RenderFrameImpl::DetachGuest(int element_instance_id) { | 
|  | 
| void RenderFrameImpl::SetSelectedText(const base::string16& selection_text, | 
| size_t offset, | 
| -                                      const gfx::Range& range) { | 
| +                                      const gfx::Range& range, | 
| +                                      bool user_initiated) { | 
| Send(new FrameHostMsg_SelectionChanged(routing_id_, selection_text, | 
| -                                         static_cast<uint32_t>(offset), range)); | 
| +                                         static_cast<uint32_t>(offset), range, | 
| +                                         user_initiated)); | 
| } | 
|  | 
| void RenderFrameImpl::EnsureMojoBuiltinsAreAvailable( | 
| @@ -4173,9 +4179,9 @@ void RenderFrameImpl::AbortClientNavigation() { | 
| } | 
|  | 
| void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) { | 
| -  if (!GetRenderWidget()->input_handler().handling_input_event() && | 
| -      !handling_select_range_) | 
| -    return; | 
| +  bool user_initiated = | 
| +      GetRenderWidget()->input_handler().handling_input_event() || | 
| +      handling_select_range_; | 
|  | 
| if (is_empty_selection) | 
| selection_text_.clear(); | 
| @@ -4186,7 +4192,7 @@ void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) { | 
| // to notify the selection was changed.  Focus change should be notified | 
| // before selection change. | 
| GetRenderWidget()->UpdateTextInputState(); | 
| -  SyncSelectionIfRequired(); | 
| +  SyncSelectionIfRequired(user_initiated); | 
| } | 
|  | 
| bool RenderFrameImpl::HandleCurrentKeyboardEvent() { | 
| @@ -6277,10 +6283,10 @@ void RenderFrameImpl::UpdateEncoding(WebFrame* frame, | 
| Send(new FrameHostMsg_UpdateEncoding(routing_id_, encoding_name)); | 
| } | 
|  | 
| -void RenderFrameImpl::SyncSelectionIfRequired() { | 
| +void RenderFrameImpl::SyncSelectionIfRequired(bool user_initiated) { | 
| base::string16 text; | 
| -  size_t offset; | 
| -  gfx::Range range; | 
| +  size_t offset = 0; | 
| +  gfx::Range range = gfx::Range::InvalidRange(); | 
| #if BUILDFLAG(ENABLE_PLUGINS) | 
| if (focused_pepper_plugin_) { | 
| focused_pepper_plugin_->GetSurroundingText(&text, &range); | 
| @@ -6291,32 +6297,37 @@ void RenderFrameImpl::SyncSelectionIfRequired() { | 
| { | 
| WebRange selection = | 
| GetRenderWidget()->GetWebWidget()->CaretOrSelectionRange(); | 
| -    if (selection.IsNull()) | 
| -      return; | 
|  | 
| -    range = gfx::Range(selection.StartOffset(), selection.EndOffset()); | 
| - | 
| -    if (frame_->GetInputMethodController()->TextInputType() != | 
| -        blink::kWebTextInputTypeNone) { | 
| -      // If current focused element is editable, we will send 100 more chars | 
| -      // before and after selection. It is for input method surrounding text | 
| -      // feature. | 
| -      if (selection.StartOffset() > kExtraCharsBeforeAndAfterSelection) | 
| -        offset = selection.StartOffset() - kExtraCharsBeforeAndAfterSelection; | 
| -      else | 
| -        offset = 0; | 
| -      size_t length = | 
| -          selection.EndOffset() - offset + kExtraCharsBeforeAndAfterSelection; | 
| -      text = frame_->RangeAsText(WebRange(offset, length)).Utf16(); | 
| -    } else { | 
| -      offset = selection.StartOffset(); | 
| -      text = frame_->SelectionAsText().Utf16(); | 
| -      // http://crbug.com/101435 | 
| -      // In some case, frame->selectionAsText() returned text's length is not | 
| -      // equal to the length returned from | 
| -      // GetWebWidget()->caretOrSelectionRange(). | 
| -      // So we have to set the range according to text.length(). | 
| -      range.set_end(range.start() + text.length()); | 
| +    // When clearing text selection from JavaScript the selection range | 
| +    // might be null but the selected text still have to be updated. | 
| +    // Do not cancel sync selection if the clear was not user initiated. | 
| +    if (!selection.IsNull()) { | 
| +      range = gfx::Range(selection.StartOffset(), selection.EndOffset()); | 
| + | 
| +      if (frame_->GetInputMethodController()->TextInputType() != | 
| +          blink::kWebTextInputTypeNone) { | 
| +        // If current focused element is editable, we will send 100 more chars | 
| +        // before and after selection. It is for input method surrounding text | 
| +        // feature. | 
| +        if (selection.StartOffset() > kExtraCharsBeforeAndAfterSelection) | 
| +          offset = selection.StartOffset() - kExtraCharsBeforeAndAfterSelection; | 
| +        else | 
| +          offset = 0; | 
| +        size_t length = | 
| +            selection.EndOffset() - offset + kExtraCharsBeforeAndAfterSelection; | 
| +        text = frame_->RangeAsText(WebRange(offset, length)).Utf16(); | 
| +      } else { | 
| +        offset = selection.StartOffset(); | 
| +        text = frame_->SelectionAsText().Utf16(); | 
| +        // http://crbug.com/101435 | 
| +        // In some case, frame->selectionAsText() returned text's length is not | 
| +        // equal to the length returned from | 
| +        // GetWebWidget()->caretOrSelectionRange(). | 
| +        // So we have to set the range according to text.length(). | 
| +        range.set_end(range.start() + text.length()); | 
| +      } | 
| +    } else if (user_initiated) { | 
| +      return; | 
| } | 
| } | 
|  | 
| @@ -6332,7 +6343,7 @@ void RenderFrameImpl::SyncSelectionIfRequired() { | 
| selection_text_ = text; | 
| selection_text_offset_ = offset; | 
| selection_range_ = range; | 
| -    SetSelectedText(text, offset, range); | 
| +    SetSelectedText(text, offset, range, user_initiated); | 
| } | 
| GetRenderWidget()->UpdateSelectionBounds(); | 
| } | 
|  |