blob: ec3f18cb0ca0ad0de2efc938bbbf7d1e0ebef294 [file] [log] [blame]
dtapuska9d46ef7d2017-05-26 19:06:061// 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"
Ryan Landay69ac1e42017-09-14 02:17:3812#include "content/common/input/ime_text_span_conversions.h"
Sadrul Habib Chowdhury31c98712018-12-11 04:15:1313#include "content/renderer/compositor/layer_tree_view.h"
dtapuska9d46ef7d2017-05-26 19:06:0614#include "content/renderer/ime_event_guard.h"
Dave Tapuska525eb15e2017-08-17 21:05:5015#include "content/renderer/input/widget_input_handler_manager.h"
dtapuska9d46ef7d2017-05-26 19:06:0616#include "content/renderer/render_thread_impl.h"
17#include "content/renderer/render_view_impl.h"
18#include "content/renderer/render_widget.h"
Blink Reformata30d4232018-04-07 15:31:0619#include "third_party/blink/public/web/web_input_method_controller.h"
20#include "third_party/blink/public/web/web_local_frame.h"
dtapuska9d46ef7d2017-05-26 19:06:0621
22namespace content {
23
24FrameInputHandlerImpl::FrameInputHandlerImpl(
25 base::WeakPtr<RenderFrameImpl> render_frame,
26 mojom::FrameInputHandlerRequest request)
27 : binding_(this),
28 render_frame_(render_frame),
Albert J. Wong7bbf22d2018-12-20 00:27:2729 input_event_queue_(
30 render_frame->GetLocalRootRenderWidget()->GetInputEventQueue()),
dtapuska9d46ef7d2017-05-26 19:06:0631 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
Albert J. Wong7bbf22d2018-12-20 00:27:2732 weak_ptr_factory_(this) {
dtapuska9d46ef7d2017-05-26 19:06:0633 weak_this_ = weak_ptr_factory_.GetWeakPtr();
34 // If we have created an input event queue move the mojo request over to the
35 // compositor thread.
Dave Tapuska04bc5ee92018-04-17 19:03:3136 if (RenderThreadImpl::current() &&
37 RenderThreadImpl::current()->compositor_task_runner() &&
Dave Tapuska9db80842017-07-24 17:24:2638 input_event_queue_) {
dtapuska9d46ef7d2017-05-26 19:06:0639 // Mojo channel bound on compositor thread.
40 RenderThreadImpl::current()->compositor_task_runner()->PostTask(
41 FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::BindNow,
42 base::Unretained(this), std::move(request)));
43 } else {
44 // Mojo channel bound on main thread.
45 BindNow(std::move(request));
46 }
47}
48
49FrameInputHandlerImpl::~FrameInputHandlerImpl() {}
50
51// static
52void FrameInputHandlerImpl::CreateMojoService(
53 base::WeakPtr<RenderFrameImpl> render_frame,
dtapuska9d46ef7d2017-05-26 19:06:0654 mojom::FrameInputHandlerRequest request) {
55 DCHECK(render_frame);
56
57 // Owns itself. Will be deleted when message pipe is destroyed.
58 new FrameInputHandlerImpl(render_frame, std::move(request));
59}
60
Shimi Zhange697c832018-10-04 23:19:1761void FrameInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) {
dtapuska9d46ef7d2017-05-26 19:06:0662 if (input_event_queue_) {
Shimi Zhange697c832018-10-04 23:19:1763 input_event_queue_->QueueClosure(std::move(closure));
dtapuska9d46ef7d2017-05-26 19:06:0664 } else {
Shimi Zhange697c832018-10-04 23:19:1765 std::move(closure).Run();
dtapuska9d46ef7d2017-05-26 19:06:0666 }
67}
68
69void FrameInputHandlerImpl::SetCompositionFromExistingText(
70 int32_t start,
71 int32_t end,
Ryan Landay9e42fd742017-08-12 01:59:1172 const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
dtapuska9d46ef7d2017-05-26 19:06:0673 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
74 RunOnMainThread(
tzik37afd2a2018-10-17 06:40:1875 base::BindOnce(&FrameInputHandlerImpl::SetCompositionFromExistingText,
76 weak_this_, start, end, ui_ime_text_spans));
dtapuska9d46ef7d2017-05-26 19:06:0677 return;
78 }
79
80 if (!render_frame_)
81 return;
82
Albert J. Wong7bbf22d2018-12-20 00:27:2783 ImeEventGuard guard(render_frame_->GetLocalRootRenderWidget());
dtapuska9d46ef7d2017-05-26 19:06:0684
Manuel Rego Casasnovas6743b452018-03-22 20:42:3985 render_frame_->GetWebFrame()->SetCompositionFromExistingText(
86 start, end, ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans));
dtapuska9d46ef7d2017-05-26 19:06:0687}
88
89void FrameInputHandlerImpl::ExtendSelectionAndDelete(int32_t before,
90 int32_t after) {
91 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
tzik37afd2a2018-10-17 06:40:1892 RunOnMainThread(
93 base::BindOnce(&FrameInputHandlerImpl::ExtendSelectionAndDelete,
94 weak_this_, before, after));
dtapuska9d46ef7d2017-05-26 19:06:0695 return;
96 }
97 if (!render_frame_)
98 return;
99 render_frame_->GetWebFrame()->ExtendSelectionAndDelete(before, after);
100}
101
102void FrameInputHandlerImpl::DeleteSurroundingText(int32_t before,
103 int32_t after) {
104 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
tzik37afd2a2018-10-17 06:40:18105 RunOnMainThread(
106 base::BindOnce(&FrameInputHandlerImpl::DeleteSurroundingText,
107 weak_this_, before, after));
dtapuska9d46ef7d2017-05-26 19:06:06108 return;
109 }
110 if (!render_frame_)
111 return;
112 render_frame_->GetWebFrame()->DeleteSurroundingText(before, after);
113}
114
115void FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints(int32_t before,
116 int32_t after) {
117 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
tzik37afd2a2018-10-17 06:40:18118 RunOnMainThread(base::BindOnce(
119 &FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints, weak_this_,
120 before, after));
dtapuska9d46ef7d2017-05-26 19:06:06121 return;
122 }
123 if (!render_frame_)
124 return;
125 render_frame_->GetWebFrame()->DeleteSurroundingTextInCodePoints(before,
126 after);
127}
128
129void FrameInputHandlerImpl::SetEditableSelectionOffsets(int32_t start,
130 int32_t end) {
131 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
132 RunOnMainThread(
tzik37afd2a2018-10-17 06:40:18133 base::BindOnce(&FrameInputHandlerImpl::SetEditableSelectionOffsets,
134 weak_this_, start, end));
dtapuska9d46ef7d2017-05-26 19:06:06135 return;
136 }
137 if (!render_frame_)
138 return;
Dave Tapuska8e304aa2017-11-15 17:29:46139 HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
dtapuska9d46ef7d2017-05-26 19:06:06140 render_frame_->GetWebFrame()->SetEditableSelectionOffsets(start, end);
141}
142
143void FrameInputHandlerImpl::ExecuteEditCommand(
144 const std::string& command,
145 const base::Optional<base::string16>& value) {
146 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
tzik37afd2a2018-10-17 06:40:18147 RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ExecuteEditCommand,
148 weak_this_, command, value));
dtapuska9d46ef7d2017-05-26 19:06:06149 return;
150 }
151 if (!render_frame_)
152 return;
153 if (value) {
154 render_frame_->GetWebFrame()->ExecuteCommand(
155 blink::WebString::FromUTF8(command),
156 blink::WebString::FromUTF16(value.value()));
157 return;
158 }
159
160 render_frame_->GetWebFrame()->ExecuteCommand(
161 blink::WebString::FromUTF8(command));
162}
163
164void FrameInputHandlerImpl::Undo() {
tzik37afd2a2018-10-17 06:40:18165 RunOnMainThread(
166 base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
167 weak_this_, "Undo", UpdateState::kNone));
dtapuska9d46ef7d2017-05-26 19:06:06168}
169
170void FrameInputHandlerImpl::Redo() {
tzik37afd2a2018-10-17 06:40:18171 RunOnMainThread(
172 base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
173 weak_this_, "Redo", UpdateState::kNone));
dtapuska9d46ef7d2017-05-26 19:06:06174}
175
176void FrameInputHandlerImpl::Cut() {
tzik37afd2a2018-10-17 06:40:18177 RunOnMainThread(
178 base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
179 weak_this_, "Cut", UpdateState::kIsSelectingRange));
dtapuska9d46ef7d2017-05-26 19:06:06180}
181
182void FrameInputHandlerImpl::Copy() {
tzik37afd2a2018-10-17 06:40:18183 RunOnMainThread(
184 base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
185 weak_this_, "Copy", UpdateState::kIsSelectingRange));
dtapuska9d46ef7d2017-05-26 19:06:06186}
187
188void FrameInputHandlerImpl::CopyToFindPboard() {
189#if defined(OS_MACOSX)
190 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
191 RunOnMainThread(
192 base::Bind(&FrameInputHandlerImpl::CopyToFindPboard, weak_this_));
193 return;
194 }
195 if (!render_frame_)
196 return;
197 render_frame_->OnCopyToFindPboard();
198#endif
199}
200
201void FrameInputHandlerImpl::Paste() {
tzik37afd2a2018-10-17 06:40:18202 RunOnMainThread(
203 base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
204 weak_this_, "Paste", UpdateState::kIsPasting));
dtapuska9d46ef7d2017-05-26 19:06:06205}
206
207void FrameInputHandlerImpl::PasteAndMatchStyle() {
tzik37afd2a2018-10-17 06:40:18208 RunOnMainThread(base::BindOnce(
209 &FrameInputHandlerImpl::ExecuteCommandOnMainThread, weak_this_,
210 "PasteAndMatchStyle", UpdateState::kIsPasting));
dtapuska9d46ef7d2017-05-26 19:06:06211}
212
213void FrameInputHandlerImpl::Replace(const base::string16& word) {
214 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
215 RunOnMainThread(
tzik37afd2a2018-10-17 06:40:18216 base::BindOnce(&FrameInputHandlerImpl::Replace, weak_this_, word));
dtapuska9d46ef7d2017-05-26 19:06:06217 return;
218 }
219 if (!render_frame_)
220 return;
221 blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
Tessa Nijssencb4583b2018-07-31 20:09:17222 if (!frame->HasSelection())
dtapuska9d46ef7d2017-05-26 19:06:06223 frame->SelectWordAroundCaret();
224 frame->ReplaceSelection(blink::WebString::FromUTF16(word));
225 render_frame_->SyncSelectionIfRequired();
226}
227
228void FrameInputHandlerImpl::ReplaceMisspelling(const base::string16& word) {
229 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
tzik37afd2a2018-10-17 06:40:18230 RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ReplaceMisspelling,
231 weak_this_, word));
dtapuska9d46ef7d2017-05-26 19:06:06232 return;
233 }
234 if (!render_frame_)
235 return;
236 blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
237 if (!frame->HasSelection())
238 return;
239 frame->ReplaceMisspelledRange(blink::WebString::FromUTF16(word));
240}
241
242void FrameInputHandlerImpl::Delete() {
tzik37afd2a2018-10-17 06:40:18243 RunOnMainThread(
244 base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
245 weak_this_, "Delete", UpdateState::kNone));
dtapuska9d46ef7d2017-05-26 19:06:06246}
247
248void FrameInputHandlerImpl::SelectAll() {
tzik37afd2a2018-10-17 06:40:18249 RunOnMainThread(
250 base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
251 weak_this_, "SelectAll", UpdateState::kIsSelectingRange));
dtapuska9d46ef7d2017-05-26 19:06:06252}
253
254void FrameInputHandlerImpl::CollapseSelection() {
255 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
256 RunOnMainThread(
tzik37afd2a2018-10-17 06:40:18257 base::BindOnce(&FrameInputHandlerImpl::CollapseSelection, weak_this_));
dtapuska9d46ef7d2017-05-26 19:06:06258 return;
259 }
260
261 if (!render_frame_)
262 return;
ekaramadd503ac62017-07-19 23:26:06263 const blink::WebRange& range = render_frame_->GetWebFrame()
264 ->GetInputMethodController()
265 ->GetSelectionOffsets();
dtapuska9d46ef7d2017-05-26 19:06:06266 if (range.IsNull())
267 return;
268
Dave Tapuskaf02060a2017-10-27 16:47:40269 HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
dtapuska9d46ef7d2017-05-26 19:06:06270 render_frame_->GetWebFrame()->SelectRange(
Shimi Zhang37deeb22017-09-28 00:59:01271 blink::WebRange(range.EndOffset(), 0),
272 blink::WebLocalFrame::kHideSelectionHandle,
273 blink::mojom::SelectionMenuBehavior::kHide);
dtapuska9d46ef7d2017-05-26 19:06:06274}
275
276void FrameInputHandlerImpl::SelectRange(const gfx::Point& base,
277 const gfx::Point& extent) {
278 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
279 // TODO(dtapuska): This event should be coalesced. Chrome IPC uses
280 // one outstanding event and an ACK to handle coalescing on the browser
281 // side. We should be able to clobber them in the main thread event queue.
tzik37afd2a2018-10-17 06:40:18282 RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::SelectRange,
283 weak_this_, base, extent));
dtapuska9d46ef7d2017-05-26 19:06:06284 return;
285 }
286
287 if (!render_frame_)
288 return;
Albert J. Wong7fcddfa2018-05-29 22:13:21289 RenderWidget* window_widget = render_frame_->render_view()->GetWidget();
Dave Tapuskaf02060a2017-10-27 16:47:40290 HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
dtapuska9d46ef7d2017-05-26 19:06:06291 render_frame_->GetWebFrame()->SelectRange(
Albert J. Wong7fcddfa2018-05-29 22:13:21292 window_widget->ConvertWindowPointToViewport(base),
293 window_widget->ConvertWindowPointToViewport(extent));
dtapuska9d46ef7d2017-05-26 19:06:06294}
295
Shimi Zhange697c832018-10-04 23:19:17296#if defined(OS_ANDROID)
297void FrameInputHandlerImpl::SelectWordAroundCaret(
298 SelectWordAroundCaretCallback callback) {
299 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
300 RunOnMainThread(
301 base::BindOnce(&FrameInputHandlerImpl::SelectWordAroundCaret,
302 weak_this_, std::move(callback)));
303 return;
304 }
305
306 bool did_select = false;
307 int start_adjust = 0;
308 int end_adjust = 0;
309 if (render_frame_) {
310 blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
311 blink::WebRange initial_range = frame->SelectionRange();
Albert J. Wong7bbf22d2018-12-20 00:27:27312 render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(true);
Shimi Zhange697c832018-10-04 23:19:17313 if (!initial_range.IsNull())
314 did_select = frame->SelectWordAroundCaret();
315 if (did_select) {
316 blink::WebRange adjusted_range = frame->SelectionRange();
317 DCHECK(!adjusted_range.IsNull());
318 start_adjust = adjusted_range.StartOffset() - initial_range.StartOffset();
319 end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
320 }
Albert J. Wong7bbf22d2018-12-20 00:27:27321 render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(false);
Shimi Zhange697c832018-10-04 23:19:17322 }
323
324 // If the mojom channel is registered with compositor thread, we have to run
325 // the callback on compositor thread. Otherwise run it on main thread. Mojom
326 // requires the callback runs on the same thread.
327 if (RenderThreadImpl::current() &&
328 RenderThreadImpl::current()->compositor_task_runner() &&
329 input_event_queue_) {
330 RenderThreadImpl::current()->compositor_task_runner()->PostTask(
331 FROM_HERE, base::BindOnce(std::move(callback), did_select, start_adjust,
332 end_adjust));
333 } else {
334 std::move(callback).Run(did_select, start_adjust, end_adjust);
335 }
336}
337#endif // defined(OS_ANDROID)
338
Shimi Zhang37deeb22017-09-28 00:59:01339void FrameInputHandlerImpl::AdjustSelectionByCharacterOffset(
340 int32_t start,
341 int32_t end,
342 blink::mojom::SelectionMenuBehavior selection_menu_behavior) {
dtapuska9d46ef7d2017-05-26 19:06:06343 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
344 RunOnMainThread(
tzik37afd2a2018-10-17 06:40:18345 base::BindOnce(&FrameInputHandlerImpl::AdjustSelectionByCharacterOffset,
346 weak_this_, start, end, selection_menu_behavior));
dtapuska9d46ef7d2017-05-26 19:06:06347 return;
348 }
349
350 if (!render_frame_)
351 return;
ekaramadd503ac62017-07-19 23:26:06352 blink::WebRange range = render_frame_->GetWebFrame()
353 ->GetInputMethodController()
354 ->GetSelectionOffsets();
dtapuska9d46ef7d2017-05-26 19:06:06355 if (range.IsNull())
356 return;
357
358 // Sanity checks to disallow empty and out of range selections.
359 if (start - end > range.length() || range.StartOffset() + start < 0)
360 return;
361
Dave Tapuskaf02060a2017-10-27 16:47:40362 HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
dtapuska9d46ef7d2017-05-26 19:06:06363 // A negative adjust amount moves the selection towards the beginning of
364 // the document, a positive amount moves the selection towards the end of
365 // the document.
366 render_frame_->GetWebFrame()->SelectRange(
367 blink::WebRange(range.StartOffset() + start,
368 range.length() + end - start),
Shimi Zhang37deeb22017-09-28 00:59:01369 blink::WebLocalFrame::kPreserveHandleVisibility, selection_menu_behavior);
dtapuska9d46ef7d2017-05-26 19:06:06370}
371
372void FrameInputHandlerImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
373 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
374 // TODO(dtapuska): This event should be coalesced. Chrome IPC uses
375 // one outstanding event and an ACK to handle coalescing on the browser
376 // side. We should be able to clobber them in the main thread event queue.
tzik37afd2a2018-10-17 06:40:18377 RunOnMainThread(base::BindOnce(
378 &FrameInputHandlerImpl::MoveRangeSelectionExtent, weak_this_, extent));
dtapuska9d46ef7d2017-05-26 19:06:06379 return;
380 }
381
382 if (!render_frame_)
383 return;
Dave Tapuskaf02060a2017-10-27 16:47:40384 HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
dtapuska9d46ef7d2017-05-26 19:06:06385 render_frame_->GetWebFrame()->MoveRangeSelectionExtent(
Albert J. Wong7fcddfa2018-05-29 22:13:21386 render_frame_->render_view()->GetWidget()->ConvertWindowPointToViewport(
387 extent));
dtapuska9d46ef7d2017-05-26 19:06:06388}
389
Dave Tapuskab336b922017-07-06 19:24:05390void FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect(
391 const gfx::Rect& rect) {
392 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
tzik37afd2a2018-10-17 06:40:18393 RunOnMainThread(base::BindOnce(
394 &FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect, weak_this_,
395 rect));
Dave Tapuskab336b922017-07-06 19:24:05396 return;
397 }
398
399 if (!render_frame_)
400 return;
401
EhsanKbd2cea992017-11-23 18:49:08402 render_frame_->ScrollFocusedEditableElementIntoRect(rect);
Dave Tapuskab336b922017-07-06 19:24:05403}
404
405void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) {
406 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
407 RunOnMainThread(
tzik37afd2a2018-10-17 06:40:18408 base::BindOnce(&FrameInputHandlerImpl::MoveCaret, weak_this_, point));
Dave Tapuskab336b922017-07-06 19:24:05409 return;
410 }
411
412 if (!render_frame_)
413 return;
414
Dave Tapuskab336b922017-07-06 19:24:05415 render_frame_->GetWebFrame()->MoveCaretSelection(
Albert J. Wong7fcddfa2018-05-29 22:13:21416 render_frame_->render_view()->GetWidget()->ConvertWindowPointToViewport(
417 point));
Dave Tapuskab336b922017-07-06 19:24:05418}
419
Dave Tapuska525eb15e2017-08-17 21:05:50420void FrameInputHandlerImpl::GetWidgetInputHandler(
Dave Tapuskab66c28f2017-11-15 17:18:47421 mojom::WidgetInputHandlerAssociatedRequest interface_request,
422 mojom::WidgetInputHandlerHostPtr host) {
Dave Tapuska525eb15e2017-08-17 21:05:50423 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
424 main_thread_task_runner_->PostTask(
425 FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::GetWidgetInputHandler,
Dave Tapuskab66c28f2017-11-15 17:18:47426 weak_this_, std::move(interface_request),
427 std::move(host)));
Dave Tapuska525eb15e2017-08-17 21:05:50428 return;
429 }
430 if (!render_frame_)
431 return;
Albert J. Wong7bbf22d2018-12-20 00:27:27432 render_frame_->GetLocalRootRenderWidget()
Dave Tapuska525eb15e2017-08-17 21:05:50433 ->widget_input_handler_manager()
Dave Tapuskab66c28f2017-11-15 17:18:47434 ->AddAssociatedInterface(std::move(interface_request), std::move(host));
Dave Tapuska525eb15e2017-08-17 21:05:50435}
436
dtapuska9d46ef7d2017-05-26 19:06:06437void FrameInputHandlerImpl::ExecuteCommandOnMainThread(
438 const std::string& command,
439 UpdateState update_state) {
440 if (!render_frame_)
441 return;
442
Dave Tapuskaf02060a2017-10-27 16:47:40443 HandlingState handling_state(render_frame_, update_state);
dtapuska9d46ef7d2017-05-26 19:06:06444 render_frame_->GetWebFrame()->ExecuteCommand(
445 blink::WebString::FromUTF8(command));
446}
447
448void FrameInputHandlerImpl::Release() {
449 if (!main_thread_task_runner_->BelongsToCurrentThread()) {
450 // Close the binding on the compositor thread first before telling the main
451 // thread to delete this object.
452 binding_.Close();
453 main_thread_task_runner_->PostTask(
tzik1076ee22017-08-25 04:03:57454 FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::Release, weak_this_));
dtapuska9d46ef7d2017-05-26 19:06:06455 return;
456 }
457 delete this;
458}
459
460void FrameInputHandlerImpl::BindNow(mojom::FrameInputHandlerRequest request) {
461 binding_.Bind(std::move(request));
462 binding_.set_connection_error_handler(
tzik1076ee22017-08-25 04:03:57463 base::BindOnce(&FrameInputHandlerImpl::Release, base::Unretained(this)));
dtapuska9d46ef7d2017-05-26 19:06:06464}
465
466FrameInputHandlerImpl::HandlingState::HandlingState(
Dave Tapuskaf02060a2017-10-27 16:47:40467 const base::WeakPtr<RenderFrameImpl>& render_frame,
dtapuska9d46ef7d2017-05-26 19:06:06468 UpdateState state)
469 : render_frame_(render_frame),
470 original_select_range_value_(render_frame->handling_select_range()),
471 original_pasting_value_(render_frame->IsPasting()) {
472 switch (state) {
473 case UpdateState::kIsPasting:
474 render_frame->set_is_pasting(true);
Nico Weber39f9c292018-01-29 18:51:12475 FALLTHROUGH; // Matches RenderFrameImpl::OnPaste() which sets both.
dtapuska9d46ef7d2017-05-26 19:06:06476 case UpdateState::kIsSelectingRange:
477 render_frame->set_handling_select_range(true);
478 break;
479 case UpdateState::kNone:
480 break;
481 }
482}
483
484FrameInputHandlerImpl::HandlingState::~HandlingState() {
Dave Tapuskaf02060a2017-10-27 16:47:40485 // RenderFrame may have been destroyed while this object was on the stack.
486 if (!render_frame_)
487 return;
dtapuska9d46ef7d2017-05-26 19:06:06488 render_frame_->set_handling_select_range(original_select_range_value_);
489 render_frame_->set_is_pasting(original_pasting_value_);
490}
491
492} // namespace content