OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/renderer/input/frame_input_handler_impl.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/debug/stack_trace.h" | |
11 #include "base/logging.h" | |
12 #include "content/renderer/ime_event_guard.h" | |
13 #include "content/renderer/render_thread_impl.h" | |
14 #include "content/renderer/render_view_impl.h" | |
15 #include "content/renderer/render_widget.h" | |
16 #include "third_party/WebKit/public/web/WebLocalFrame.h" | |
17 | |
18 namespace content { | |
19 | |
20 FrameInputHandlerImpl::FrameInputHandlerImpl( | |
21 RenderFrameImpl* render_frame, | |
22 mojom::FrameInputHandlerRequest request) | |
23 : binding_(this), | |
24 render_frame_(render_frame), | |
25 input_event_queue_( | |
26 render_frame->GetRenderWidget()->GetInputEventQueue()) { | |
27 // Once the binding is connected the error handler will be set to | |
28 // Release. | |
29 AddRef(); | |
30 | |
31 // If we have created an input event queue move the mojo request over to the | |
32 // compositor thread. | |
33 if (input_event_queue_) { | |
34 // Mojo channel bound on compositor thread. | |
35 RenderThreadImpl::current()->compositor_task_runner()->PostTask( | |
36 FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::BindOnCompositor, | |
37 this, std::move(request))); | |
38 } else { | |
39 // Mojo channel bound on main thread. | |
40 BindNow(std::move(request)); | |
41 } | |
42 main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | |
43 } | |
44 | |
45 FrameInputHandlerImpl::~FrameInputHandlerImpl() {} | |
46 | |
47 // static | |
48 void FrameInputHandlerImpl::CreateMojoService( | |
49 RenderFrameImpl* render_frame, | |
50 const service_manager::BindSourceInfo& source_info, | |
51 mojom::FrameInputHandlerRequest request) { | |
52 DCHECK(render_frame); | |
53 | |
54 // Owns itself. Will be deleted when message pipe is destroyed or RenderFrame | |
55 // is destructed. | |
56 new FrameInputHandlerImpl(render_frame, std::move(request)); | |
57 } | |
58 | |
59 void FrameInputHandlerImpl::RunOnMainThread(const base::Closure& closure) { | |
60 if (input_event_queue_) { | |
61 input_event_queue_->QueueClosure(closure); | |
62 } else { | |
63 closure.Run(); | |
64 } | |
65 } | |
66 | |
67 void FrameInputHandlerImpl::SetCompositionFromExistingText( | |
68 int32_t start, | |
69 int32_t end, | |
70 const std::vector<ui::CompositionUnderline>& ui_underlines) { | |
71 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
72 RunOnMainThread( | |
73 base::Bind(&FrameInputHandlerImpl::SetCompositionFromExistingText, this, | |
74 start, end, ui_underlines)); | |
75 return; | |
76 } | |
77 | |
78 ImeEventGuard guard(GetRenderFrame()->GetRenderWidget()); | |
79 std::vector<blink::WebCompositionUnderline> underlines; | |
80 for (const auto& underline : ui_underlines) { | |
81 blink::WebCompositionUnderline blink_underline( | |
82 underline.start_offset, underline.end_offset, underline.color, | |
83 underline.thick, underline.background_color); | |
84 underlines.push_back(blink_underline); | |
85 } | |
86 | |
87 GetRenderFrame()->GetWebFrame()->SetCompositionFromExistingText(start, end, | |
88 underlines); | |
89 } | |
90 | |
91 void FrameInputHandlerImpl::ExtendSelectionAndDelete(int32_t before, | |
92 int32_t after) { | |
93 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
94 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExtendSelectionAndDelete, | |
95 this, before, after)); | |
96 return; | |
97 } | |
98 GetRenderFrame()->GetWebFrame()->ExtendSelectionAndDelete(before, after); | |
99 } | |
100 | |
101 void FrameInputHandlerImpl::DeleteSurroundingText(int32_t before, | |
102 int32_t after) { | |
103 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
104 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::DeleteSurroundingText, | |
105 this, before, after)); | |
106 return; | |
107 } | |
108 GetRenderFrame()->GetWebFrame()->DeleteSurroundingText(before, after); | |
109 } | |
110 | |
111 void FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints(int32_t before, | |
112 int32_t after) { | |
113 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
114 RunOnMainThread( | |
115 base::Bind(&FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints, | |
116 this, before, after)); | |
117 return; | |
118 } | |
119 GetRenderFrame()->GetWebFrame()->DeleteSurroundingTextInCodePoints(before, | |
120 after); | |
121 } | |
122 | |
123 void FrameInputHandlerImpl::SetEditableSelectionOffsets(int32_t start, | |
124 int32_t end) { | |
125 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
126 RunOnMainThread(base::Bind( | |
127 &FrameInputHandlerImpl::SetEditableSelectionOffsets, this, start, end)); | |
128 return; | |
129 } | |
130 GetRenderFrame()->GetWebFrame()->SetEditableSelectionOffsets(start, end); | |
131 } | |
132 | |
133 void FrameInputHandlerImpl::ExecuteEditCommand( | |
134 const std::string& command, | |
135 const base::Optional<std::string>& value) {} | |
136 | |
137 void FrameInputHandlerImpl::Undo() { | |
138 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
139 this, "Undo", UpdateState::kNone)); | |
140 } | |
141 | |
142 void FrameInputHandlerImpl::Redo() { | |
143 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
144 this, "Redo", UpdateState::kNone)); | |
145 } | |
146 | |
147 void FrameInputHandlerImpl::Cut() { | |
148 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
149 this, "Cut", UpdateState::kIsSelectingRange)); | |
150 } | |
151 | |
152 void FrameInputHandlerImpl::Copy() { | |
153 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
154 this, "Copy", UpdateState::kIsSelectingRange)); | |
155 } | |
156 | |
157 void FrameInputHandlerImpl::CopyToFindPboard() { | |
158 #if defined(OS_MACOSX) | |
159 GetRenderFrame()->OnCopyToFindPboard(); | |
dcheng
2017/05/17 04:49:06
Does this eventually need to thread-hop too?
(I g
dtapuska
2017/05/17 17:08:08
Yes it does
| |
160 #endif | |
161 } | |
162 | |
163 void FrameInputHandlerImpl::Paste() { | |
164 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
165 this, "Paste", UpdateState::kIsPasting)); | |
166 } | |
167 | |
168 void FrameInputHandlerImpl::PasteAndMatchStyle() { | |
169 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
170 this, "PasteAndMatchStyle", | |
171 UpdateState::kIsPasting)); | |
172 } | |
173 | |
174 void FrameInputHandlerImpl::Replace(const std::string& word) { | |
175 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
176 this, "PasteAndMatchStyle", | |
177 UpdateState::kIsPasting)); | |
178 } | |
179 | |
180 void FrameInputHandlerImpl::ReplaceMisspelling(const std::string& word) { | |
181 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
182 this, "PasteAndMatchStyle", | |
183 UpdateState::kIsPasting)); | |
184 } | |
185 | |
186 void FrameInputHandlerImpl::Delete() { | |
187 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
188 this, "Delete", UpdateState::kNone)); | |
189 } | |
190 | |
191 void FrameInputHandlerImpl::SelectAll() { | |
192 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, | |
193 this, "SelectAll", | |
194 UpdateState::kIsSelectingRange)); | |
195 } | |
196 | |
197 void FrameInputHandlerImpl::CollapseSelection() { | |
198 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
199 RunOnMainThread( | |
200 base::Bind(&FrameInputHandlerImpl::CollapseSelection, this)); | |
201 return; | |
202 } | |
203 | |
204 const blink::WebRange& range = GetRenderFrame() | |
205 ->GetRenderWidget() | |
206 ->GetWebWidget() | |
207 ->CaretOrSelectionRange(); | |
208 if (range.IsNull()) | |
209 return; | |
210 | |
211 HandlingState handling_state(GetRenderFrame(), | |
212 UpdateState::kIsSelectingRange); | |
213 GetRenderFrame()->GetWebFrame()->SelectRange( | |
214 blink::WebRange(range.EndOffset(), 0)); | |
215 } | |
216 | |
217 void FrameInputHandlerImpl::SelectRange(const gfx::Point& base, | |
218 const gfx::Point& extent) { | |
219 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
220 // TODO(dtapuska): This event should be coalesced. Chrome IPC used | |
221 // and ack scheme for this. We should be able to clobber them in the | |
222 // main thread event queue. | |
223 RunOnMainThread( | |
224 base::Bind(&FrameInputHandlerImpl::SelectRange, this, base, extent)); | |
225 return; | |
226 } | |
227 | |
228 RenderFrameImpl* render_frame = GetRenderFrame(); | |
229 RenderViewImpl* render_view = render_frame->render_view(); | |
230 HandlingState handling_state(render_frame, UpdateState::kIsSelectingRange); | |
231 render_frame->GetWebFrame()->SelectRange( | |
232 render_view->ConvertWindowPointToViewport(base), | |
233 render_view->ConvertWindowPointToViewport(extent)); | |
234 } | |
235 | |
236 void FrameInputHandlerImpl::AdjustSelectionByCharacterOffset(int32_t start, | |
237 int32_t end) { | |
238 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
239 RunOnMainThread( | |
240 base::Bind(&FrameInputHandlerImpl::AdjustSelectionByCharacterOffset, | |
241 this, start, end)); | |
242 return; | |
243 } | |
244 | |
245 blink::WebRange range = GetRenderFrame() | |
246 ->GetRenderWidget() | |
247 ->GetWebWidget() | |
248 ->CaretOrSelectionRange(); | |
249 if (range.IsNull()) | |
250 return; | |
251 | |
252 // Sanity checks to disallow empty and out of range selections. | |
253 if (start - end > range.length() || range.StartOffset() + start < 0) | |
254 return; | |
255 | |
256 HandlingState handling_state(GetRenderFrame(), | |
257 UpdateState::kIsSelectingRange); | |
258 // A negative adjust amount moves the selection towards the beginning of | |
259 // the document, a positive amount moves the selection towards the end of | |
260 // the document. | |
261 GetRenderFrame()->GetWebFrame()->SelectRange( | |
262 blink::WebRange(range.StartOffset() + start, | |
263 range.length() + end - start), | |
264 blink::WebLocalFrame::kPreserveHandleVisibility); | |
265 } | |
266 | |
267 void FrameInputHandlerImpl::MoveRangeSelectionExtent(const gfx::Point& extent) { | |
268 if (!main_thread_task_runner_->BelongsToCurrentThread()) { | |
269 // TODO(dtapuska): This event should be coalesced. Chrome IPC used | |
270 // and ack scheme for this. We should be able to clobber them in the | |
271 // main thread event queue. | |
272 RunOnMainThread(base::Bind(&FrameInputHandlerImpl::MoveRangeSelectionExtent, | |
273 this, extent)); | |
274 return; | |
275 } | |
276 | |
277 HandlingState handling_state(GetRenderFrame(), | |
278 UpdateState::kIsSelectingRange); | |
279 GetRenderFrame()->GetWebFrame()->MoveRangeSelectionExtent( | |
280 GetRenderFrame()->render_view()->ConvertWindowPointToViewport(extent)); | |
281 } | |
282 | |
283 void FrameInputHandlerImpl::ExecuteCommandOnMainThread( | |
284 const std::string& command, | |
285 UpdateState update_state) { | |
286 HandlingState handling_state(GetRenderFrame(), update_state); | |
287 GetRenderFrame()->GetWebFrame()->ExecuteCommand( | |
288 blink::WebString::FromUTF8(command)); | |
289 } | |
290 | |
291 void FrameInputHandlerImpl::BindOnCompositor( | |
292 mojom::FrameInputHandlerRequest request) { | |
293 BindNow(std::move(request)); | |
294 } | |
295 | |
296 void FrameInputHandlerImpl::BindNow(mojom::FrameInputHandlerRequest request) { | |
297 binding_.Bind(std::move(request)); | |
298 | |
299 // This will Release the ref-counted AddRef that was added in the constructor. | |
300 binding_.set_connection_error_handler( | |
301 base::Bind(&FrameInputHandlerImpl::Release, this)); | |
302 } | |
303 | |
304 RenderFrameImpl* FrameInputHandlerImpl::GetRenderFrame() { | |
305 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | |
306 return render_frame_; | |
307 } | |
308 | |
309 FrameInputHandlerImpl::HandlingState::HandlingState( | |
310 RenderFrameImpl* render_frame, | |
311 UpdateState state) | |
312 : render_frame_(render_frame), | |
313 original_select_range_value_(render_frame->handling_select_range()), | |
314 original_pasting_value_(render_frame->IsPasting()) { | |
315 switch (state) { | |
316 case UpdateState::kIsPasting: | |
317 render_frame->set_is_pasting(true); | |
318 case UpdateState::kIsSelectingRange: | |
319 render_frame->set_handling_select_range(true); | |
320 break; | |
321 case UpdateState::kNone: | |
322 break; | |
323 } | |
324 } | |
325 | |
326 FrameInputHandlerImpl::HandlingState::~HandlingState() { | |
327 render_frame_->set_handling_select_range(original_select_range_value_); | |
328 render_frame_->set_is_pasting(original_pasting_value_); | |
329 } | |
330 | |
331 } // namespace content | |
OLD | NEW |