Index: content/renderer/render_frame_impl.cc |
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc |
index 894e553c9e6d2cce2625127ab2104f832ad14df8..3ac32f9104f1aa6699e533c7e7c382c52c4bc332 100644 |
--- a/content/renderer/render_frame_impl.cc |
+++ b/content/renderer/render_frame_impl.cc |
@@ -1415,7 +1415,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( |
@@ -2021,7 +2023,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) { |
@@ -2723,9 +2727,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( |
@@ -4104,9 +4110,20 @@ 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 (!user_initiated) { |
+ // Do not update text input state unnecessarily when text selection remains |
+ // empty. |
+ if (is_empty_selection && selection_text_.empty()) |
+ return; |
+ |
+ // Ignore selection change of text replacement triggered by IME composition. |
+ if (GetRenderWidget()->input_handler().ime_composition_replacement()) |
+ return; |
+ } |
if (is_empty_selection) |
selection_text_.clear(); |
@@ -4117,7 +4134,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() { |
@@ -6202,10 +6219,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); |
@@ -6216,32 +6233,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; |
} |
} |
@@ -6257,7 +6279,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(); |
} |