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(); |
} |