blob: 34c79c8b73331e40dc0de7775f6c9dde510f1b68 [file] [log] [blame]
vkuzkokovc985d952014-10-01 12:24:131// Copyright 2014 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/browser/devtools/protocol/input_handler.h"
6
avib7348942015-12-25 20:57:107#include <stddef.h>
8
Lan Weie77c3d22019-03-08 20:38:169#include <vector>
10
Sebastien Marchandf8cbfab2019-01-25 16:02:3011#include "base/bind.h"
vkuzkokovc985d952014-10-01 12:24:1312#include "base/strings/stringprintf.h"
dgozmane20f50c2015-04-06 10:46:3913#include "base/strings/utf_string_conversions.h"
fdoraycaed3832016-06-13 18:15:5314#include "base/threading/thread_task_runner_handle.h"
alexclarke20301011d2015-08-18 10:43:1415#include "base/trace_event/trace_event.h"
Dmitry Gozman08a40e2f2018-10-02 21:16:4116#include "content/browser/devtools/devtools_agent_host_impl.h"
Blaisebcad00c2017-07-25 00:19:4917#include "content/browser/devtools/protocol/native_input_event_builder.h"
dgozman111fdd032016-12-18 00:49:2618#include "content/browser/frame_host/render_frame_host_impl.h"
Lan Wei9c6f1242019-02-11 23:01:3019#include "content/browser/renderer_host/input/synthetic_pointer_action.h"
Dmitry Gozman95bab292017-08-16 22:48:5820#include "content/browser/renderer_host/input/touch_emulator.h"
dgozman0f07a152015-04-13 11:10:4321#include "content/browser/renderer_host/render_widget_host_impl.h"
Dmitry Gozman901b6302018-03-02 02:30:3922#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
Kevin McNee4d843a5c2019-02-19 16:50:3423#include "content/browser/renderer_host/render_widget_host_view_base.h"
samuonged25cba2015-04-30 23:10:5424#include "content/common/input/synthetic_pinch_gesture_params.h"
25#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
26#include "content/common/input/synthetic_tap_gesture_params.h"
Avi Drissmanc2618c042018-08-30 14:12:5727#include "content/public/browser/web_contents.h"
Annie Sullivan35977ad2019-04-30 21:04:2828#include "content/public/common/content_features.h"
Dmitry Gozman95bab292017-08-16 22:48:5829#include "ui/events/base_event_utils.h"
jam013b74c82017-02-10 16:36:1030#include "ui/events/blink/web_input_event_traits.h"
Dmitry Gozman95bab292017-08-16 22:48:5831#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
kpschoedel3b0960a2015-05-11 17:52:1132#include "ui/events/keycodes/dom/keycode_converter.h"
samuonged25cba2015-04-30 23:10:5433#include "ui/gfx/geometry/point.h"
Joel Einbinder7a680362018-07-28 19:44:5334#include "ui/gfx/range/range.h"
vkuzkokovc985d952014-10-01 12:24:1335
36namespace content {
dgozman111fdd032016-12-18 00:49:2637namespace protocol {
vkuzkokovc985d952014-10-01 12:24:1338
samuonged25cba2015-04-30 23:10:5439namespace {
40
Pavel Feldman04e776d72017-07-12 23:52:4041gfx::PointF CssPixelsToPointF(double x, double y, float page_scale_factor) {
danakj2ef31b82015-10-21 18:18:0242 return gfx::PointF(x * page_scale_factor, y * page_scale_factor);
samuonged25cba2015-04-30 23:10:5443}
44
Pavel Feldman04e776d72017-07-12 23:52:4045gfx::Vector2dF CssPixelsToVector2dF(double x,
46 double y,
47 float page_scale_factor) {
danakj2ef31b82015-10-21 18:18:0248 return gfx::Vector2dF(x * page_scale_factor, y * page_scale_factor);
samuonged25cba2015-04-30 23:10:5449}
50
dgozman111fdd032016-12-18 00:49:2651bool StringToGestureSourceType(Maybe<std::string> in,
samuonged25cba2015-04-30 23:10:5452 SyntheticGestureParams::GestureSourceType& out) {
dgozman111fdd032016-12-18 00:49:2653 if (!in.isJust()) {
samuonged25cba2015-04-30 23:10:5454 out = SyntheticGestureParams::GestureSourceType::DEFAULT_INPUT;
55 return true;
dgozman111fdd032016-12-18 00:49:2656 }
57 if (in.fromJust() == Input::GestureSourceTypeEnum::Default) {
58 out = SyntheticGestureParams::GestureSourceType::DEFAULT_INPUT;
59 return true;
60 }
61 if (in.fromJust() == Input::GestureSourceTypeEnum::Touch) {
samuonged25cba2015-04-30 23:10:5462 out = SyntheticGestureParams::GestureSourceType::TOUCH_INPUT;
63 return true;
dgozman111fdd032016-12-18 00:49:2664 }
65 if (in.fromJust() == Input::GestureSourceTypeEnum::Mouse) {
samuonged25cba2015-04-30 23:10:5466 out = SyntheticGestureParams::GestureSourceType::MOUSE_INPUT;
67 return true;
samuonged25cba2015-04-30 23:10:5468 }
dgozman111fdd032016-12-18 00:49:2669 return false;
samuonged25cba2015-04-30 23:10:5470}
71
Joel Einbinderd5b1a0e2017-10-19 03:38:0572int GetEventModifiers(int modifiers,
73 bool auto_repeat,
74 bool is_keypad,
Lan Wei3d5ac6c52018-12-13 21:21:1475 int location,
76 int buttons) {
Dave Tapuska47740512017-12-07 14:31:5577 int result = blink::WebInputEvent::kFromDebugger;
dtapuska899ac222017-01-03 18:09:1678 if (auto_repeat)
Blink Reformat1c4d759e2017-04-09 16:34:5479 result |= blink::WebInputEvent::kIsAutoRepeat;
dtapuska899ac222017-01-03 18:09:1680 if (is_keypad)
Blink Reformat1c4d759e2017-04-09 16:34:5481 result |= blink::WebInputEvent::kIsKeyPad;
dtapuska899ac222017-01-03 18:09:1682
dgozman111fdd032016-12-18 00:49:2683 if (modifiers & 1)
Blink Reformat1c4d759e2017-04-09 16:34:5484 result |= blink::WebInputEvent::kAltKey;
dgozman111fdd032016-12-18 00:49:2685 if (modifiers & 2)
Blink Reformat1c4d759e2017-04-09 16:34:5486 result |= blink::WebInputEvent::kControlKey;
dgozman111fdd032016-12-18 00:49:2687 if (modifiers & 4)
Blink Reformat1c4d759e2017-04-09 16:34:5488 result |= blink::WebInputEvent::kMetaKey;
dgozman111fdd032016-12-18 00:49:2689 if (modifiers & 8)
Blink Reformat1c4d759e2017-04-09 16:34:5490 result |= blink::WebInputEvent::kShiftKey;
Joel Einbinderd5b1a0e2017-10-19 03:38:0591
92 if (location & 1)
93 result |= blink::WebInputEvent::kIsLeft;
94 if (location & 2)
95 result |= blink::WebInputEvent::kIsRight;
Lan Wei3d5ac6c52018-12-13 21:21:1496
97 if (buttons & 1)
98 result |= blink::WebMouseEvent::kLeftButtonDown;
99 if (buttons & 2)
100 result |= blink::WebInputEvent::kRightButtonDown;
101 if (buttons & 4)
102 result |= blink::WebInputEvent::kMiddleButtonDown;
103 if (buttons & 8)
104 result |= blink::WebInputEvent::kBackButtonDown;
105 if (buttons & 16)
106 result |= blink::WebInputEvent::kForwardButtonDown;
dtapuska899ac222017-01-03 18:09:16107 return result;
dgozmane20f50c2015-04-06 10:46:39108}
109
Deepanjan Roy5ba32182018-01-22 19:51:02110base::TimeTicks GetEventTimeTicks(const Maybe<double>& timestamp) {
majidvp9ca5a012016-03-09 20:27:17111 // Convert timestamp, in seconds since unix epoch, to an event timestamp
112 // which is time ticks since platform start time.
dtapuska899ac222017-01-03 18:09:16113 return timestamp.isJust()
114 ? base::TimeDelta::FromSecondsD(timestamp.fromJust()) +
115 base::TimeTicks::UnixEpoch()
116 : base::TimeTicks::Now();
117}
118
dgozman111fdd032016-12-18 00:49:26119bool SetKeyboardEventText(blink::WebUChar* to, Maybe<std::string> from) {
120 if (!from.isJust())
dgozmane20f50c2015-04-06 10:46:39121 return true;
122
dgozman111fdd032016-12-18 00:49:26123 base::string16 text16 = base::UTF8ToUTF16(from.fromJust());
Blink Reformat1c4d759e2017-04-09 16:34:54124 if (text16.size() > blink::WebKeyboardEvent::kTextLengthCap)
dgozmane20f50c2015-04-06 10:46:39125 return false;
126
127 for (size_t i = 0; i < text16.size(); ++i)
128 to[i] = text16[i];
129 return true;
130}
131
dtapuska899ac222017-01-03 18:09:16132bool GetMouseEventButton(const std::string& button,
133 blink::WebPointerProperties::Button* event_button,
134 int* event_modifiers) {
dgozman111fdd032016-12-18 00:49:26135 if (button.empty())
dgozmane20f50c2015-04-06 10:46:39136 return true;
137
dgozman111fdd032016-12-18 00:49:26138 if (button == Input::DispatchMouseEvent::ButtonEnum::None) {
Blink Reformat1c4d759e2017-04-09 16:34:54139 *event_button = blink::WebMouseEvent::Button::kNoButton;
dgozman111fdd032016-12-18 00:49:26140 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Left) {
Blink Reformat1c4d759e2017-04-09 16:34:54141 *event_button = blink::WebMouseEvent::Button::kLeft;
142 *event_modifiers = blink::WebInputEvent::kLeftButtonDown;
dgozman111fdd032016-12-18 00:49:26143 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Middle) {
Blink Reformat1c4d759e2017-04-09 16:34:54144 *event_button = blink::WebMouseEvent::Button::kMiddle;
145 *event_modifiers = blink::WebInputEvent::kMiddleButtonDown;
dgozman111fdd032016-12-18 00:49:26146 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Right) {
Blink Reformat1c4d759e2017-04-09 16:34:54147 *event_button = blink::WebMouseEvent::Button::kRight;
148 *event_modifiers = blink::WebInputEvent::kRightButtonDown;
Lan Wei3d5ac6c52018-12-13 21:21:14149 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Back) {
150 *event_button = blink::WebMouseEvent::Button::kBack;
151 *event_modifiers = blink::WebInputEvent::kBackButtonDown;
152 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Forward) {
153 *event_button = blink::WebMouseEvent::Button::kForward;
154 *event_modifiers = blink::WebInputEvent::kForwardButtonDown;
dgozmane20f50c2015-04-06 10:46:39155 } else {
156 return false;
157 }
158 return true;
159}
160
dtapuska899ac222017-01-03 18:09:16161blink::WebInputEvent::Type GetMouseEventType(const std::string& type) {
162 if (type == Input::DispatchMouseEvent::TypeEnum::MousePressed)
Blink Reformat1c4d759e2017-04-09 16:34:54163 return blink::WebInputEvent::kMouseDown;
dtapuska899ac222017-01-03 18:09:16164 if (type == Input::DispatchMouseEvent::TypeEnum::MouseReleased)
Blink Reformat1c4d759e2017-04-09 16:34:54165 return blink::WebInputEvent::kMouseUp;
dtapuska899ac222017-01-03 18:09:16166 if (type == Input::DispatchMouseEvent::TypeEnum::MouseMoved)
Blink Reformat1c4d759e2017-04-09 16:34:54167 return blink::WebInputEvent::kMouseMove;
Dmitry Gozman1e8fae32017-08-16 00:04:41168 if (type == Input::DispatchMouseEvent::TypeEnum::MouseWheel)
169 return blink::WebInputEvent::kMouseWheel;
Blink Reformat1c4d759e2017-04-09 16:34:54170 return blink::WebInputEvent::kUndefined;
dgozmane20f50c2015-04-06 10:46:39171}
172
Lan Weie77c3d22019-03-08 20:38:16173blink::WebInputEvent::Type GetTouchEventType(const std::string& type) {
174 if (type == Input::DispatchTouchEvent::TypeEnum::TouchStart)
175 return blink::WebInputEvent::kTouchStart;
176 if (type == Input::DispatchTouchEvent::TypeEnum::TouchEnd)
177 return blink::WebInputEvent::kTouchEnd;
178 if (type == Input::DispatchTouchEvent::TypeEnum::TouchMove)
179 return blink::WebInputEvent::kTouchMove;
180 if (type == Input::DispatchTouchEvent::TypeEnum::TouchCancel)
181 return blink::WebInputEvent::kTouchCancel;
182 return blink::WebInputEvent::kUndefined;
183}
184
Lan Weid387faf2019-01-02 20:08:08185blink::WebPointerProperties::PointerType GetPointerType(
186 const std::string& type) {
187 if (type == Input::DispatchMouseEvent::PointerTypeEnum::Mouse)
188 return blink::WebPointerProperties::PointerType::kMouse;
189 if (type == Input::DispatchMouseEvent::PointerTypeEnum::Pen)
190 return blink::WebPointerProperties::PointerType::kPen;
191 return blink::WebPointerProperties::PointerType::kMouse;
192}
193
Lan Wei9c6f1242019-02-11 23:01:30194SyntheticPointerActionParams::PointerActionType GetTouchPointerActionType(
195 const std::string& type) {
196 if (type == Input::DispatchTouchEvent::TypeEnum::TouchStart)
197 return SyntheticPointerActionParams::PointerActionType::PRESS;
198 if (type == Input::DispatchTouchEvent::TypeEnum::TouchEnd)
199 return SyntheticPointerActionParams::PointerActionType::RELEASE;
200 if (type == Input::DispatchTouchEvent::TypeEnum::TouchMove)
201 return SyntheticPointerActionParams::PointerActionType::MOVE;
202 if (type == Input::DispatchTouchEvent::TypeEnum::TouchCancel)
203 return SyntheticPointerActionParams::PointerActionType::CANCEL;
204 return SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED;
205}
206
207SyntheticPointerActionParams::Button GetPointerActionParamsButton(
208 const std::string& button) {
209 if (button == Input::DispatchMouseEvent::ButtonEnum::Left)
210 return SyntheticPointerActionParams::Button::LEFT;
211 if (button == Input::DispatchMouseEvent::ButtonEnum::Middle)
212 return SyntheticPointerActionParams::Button::MIDDLE;
213 if (button == Input::DispatchMouseEvent::ButtonEnum::Right)
214 return SyntheticPointerActionParams::Button::RIGHT;
215 if (button == Input::DispatchMouseEvent::ButtonEnum::Back)
216 return SyntheticPointerActionParams::Button::BACK;
217 if (button == Input::DispatchMouseEvent::ButtonEnum::Forward)
218 return SyntheticPointerActionParams::Button::FORWARD;
219 return SyntheticPointerActionParams::Button::NO_BUTTON;
Dmitry Gozman95bab292017-08-16 22:48:58220}
221
Lan Weie77c3d22019-03-08 20:38:16222bool GenerateTouchPoints(
223 blink::WebTouchEvent* event,
224 blink::WebInputEvent::Type type,
225 const base::flat_map<int, blink::WebTouchPoint>& points,
226 const blink::WebTouchPoint& changing) {
227 event->touches_length = 1;
228 event->touches[0] = changing;
229 for (auto& it : points) {
230 if (it.first == changing.id)
231 continue;
232 if (event->touches_length == blink::WebTouchEvent::kTouchesLengthCap)
233 return false;
234 event->touches[event->touches_length] = it.second;
235 event->touches[event->touches_length].state =
236 blink::WebTouchPoint::kStateStationary;
237 event->touches_length++;
238 }
239 if (type != blink::WebInputEvent::kUndefined) {
240 event->touches[0].state = type == blink::WebInputEvent::kTouchCancel
241 ? blink::WebTouchPoint::kStateCancelled
242 : blink::WebTouchPoint::kStateReleased;
243 event->SetType(type);
244 } else if (points.find(changing.id) == points.end()) {
245 event->touches[0].state = blink::WebTouchPoint::kStatePressed;
246 event->SetType(blink::WebInputEvent::kTouchStart);
247 } else {
248 event->touches[0].state = blink::WebTouchPoint::kStateMoved;
249 event->SetType(blink::WebInputEvent::kTouchMove);
250 }
251 return true;
252}
253
dgozman111fdd032016-12-18 00:49:26254void SendSynthesizePinchGestureResponse(
255 std::unique_ptr<Input::Backend::SynthesizePinchGestureCallback> callback,
256 SyntheticGesture::Result result) {
257 if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
258 callback->sendSuccess();
259 } else {
260 callback->sendFailure(Response::Error(
261 base::StringPrintf("Synthetic pinch failed, result was %d", result)));
262 }
263}
264
265class TapGestureResponse {
266 public:
267 TapGestureResponse(
268 std::unique_ptr<Input::Backend::SynthesizeTapGestureCallback> callback,
269 int count)
270 : callback_(std::move(callback)),
271 count_(count) {
272 }
273
274 void OnGestureResult(SyntheticGesture::Result result) {
275 --count_;
276 // Still waiting for more taps to finish.
277 if (result == SyntheticGesture::Result::GESTURE_FINISHED && count_)
278 return;
279 if (callback_) {
280 if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
281 callback_->sendSuccess();
282 } else {
283 callback_->sendFailure(Response::Error(
284 base::StringPrintf("Synthetic tap failed, result was %d", result)));
285 }
286 callback_.reset();
287 }
288 if (!count_)
289 delete this;
290 }
291
292 private:
293 std::unique_ptr<Input::Backend::SynthesizeTapGestureCallback> callback_;
294 int count_;
295};
296
297void SendSynthesizeScrollGestureResponse(
298 std::unique_ptr<Input::Backend::SynthesizeScrollGestureCallback> callback,
299 SyntheticGesture::Result result) {
300 if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
301 callback->sendSuccess();
302 } else {
303 callback->sendFailure(Response::Error(
304 base::StringPrintf("Synthetic scroll failed, result was %d", result)));
305 }
306}
307
Lan Wei9c6f1242019-02-11 23:01:30308void DispatchPointerActionsResponse(
309 std::unique_ptr<Input::Backend::DispatchTouchEventCallback> callback,
310 SyntheticGesture::Result result) {
311 if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
312 callback->sendSuccess();
313 } else {
314 callback->sendFailure(Response::Error(
315 base::StringPrintf("Action sequence failed, result was %d", result)));
316 }
317}
318
dgozmane20f50c2015-04-06 10:46:39319} // namespace
320
Dmitry Gozman901b6302018-03-02 02:30:39321class InputHandler::InputInjector
322 : public RenderWidgetHost::InputEventObserver {
323 public:
324 InputInjector(InputHandler* owner, RenderWidgetHostImpl* widget_host)
325 : owner_(owner), widget_host_(widget_host->GetWeakPtr()) {
326 widget_host->AddInputEventObserver(this);
327 }
328
329 void Cleanup() {
330 for (auto& callback : pending_key_callbacks_)
331 callback->sendSuccess();
332 pending_key_callbacks_.clear();
333 for (auto& callback : pending_mouse_callbacks_)
334 callback->sendSuccess();
335 pending_mouse_callbacks_.clear();
336 MaybeSelfDestruct();
337 }
338
339 bool HasWidgetHost(RenderWidgetHostImpl* widget_host) {
340 return widget_host == widget_host_.get();
341 }
342
343 void InjectWheelEvent(blink::WebMouseWheelEvent* wheel_event,
344 std::unique_ptr<DispatchMouseEventCallback> callback) {
345 if (!widget_host_) {
346 callback->sendFailure(Response::InternalError());
347 return;
348 }
349
350 widget_host_->Focus();
351 input_queued_ = false;
352 pending_mouse_callbacks_.push_back(std::move(callback));
353 widget_host_->ForwardWheelEvent(*wheel_event);
354 if (!input_queued_) {
355 pending_mouse_callbacks_.back()->sendSuccess();
356 pending_mouse_callbacks_.pop_back();
357 MaybeSelfDestruct();
358 return;
359 }
360
Sahel Sharifye6d81f472018-07-11 20:40:26361 // Send a synthetic wheel event with phaseEnded to finish scrolling.
362 wheel_event->delta_x = 0;
363 wheel_event->delta_y = 0;
364 wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
365 wheel_event->dispatch_type = blink::WebInputEvent::kEventNonBlocking;
366 widget_host_->ForwardWheelEvent(*wheel_event);
Dmitry Gozman901b6302018-03-02 02:30:39367 }
368
369 void InjectMouseEvent(const blink::WebMouseEvent& mouse_event,
370 std::unique_ptr<DispatchMouseEventCallback> callback) {
371 if (!widget_host_) {
372 callback->sendFailure(Response::InternalError());
373 return;
374 }
375
376 widget_host_->Focus();
377 input_queued_ = false;
378 pending_mouse_callbacks_.push_back(std::move(callback));
379 widget_host_->ForwardMouseEvent(mouse_event);
380 if (!input_queued_) {
381 pending_mouse_callbacks_.back()->sendSuccess();
382 pending_mouse_callbacks_.pop_back();
383 MaybeSelfDestruct();
384 }
385 }
386
387 void InjectKeyboardEvent(const NativeWebKeyboardEvent& keyboard_event,
388 std::unique_ptr<DispatchKeyEventCallback> callback) {
389 if (!widget_host_) {
390 callback->sendFailure(Response::InternalError());
391 return;
392 }
393
394 widget_host_->Focus();
395 input_queued_ = false;
396 pending_key_callbacks_.push_back(std::move(callback));
397 widget_host_->ForwardKeyboardEvent(keyboard_event);
398 if (!input_queued_) {
399 pending_key_callbacks_.back()->sendSuccess();
400 pending_key_callbacks_.pop_back();
401 MaybeSelfDestruct();
402 }
403 }
404
405 void InjectTouchEvents(const std::vector<blink::WebTouchEvent>& events,
406 std::unique_ptr<DispatchTouchEventCallback> callback) {
407 if (!widget_host_) {
408 callback->sendFailure(Response::InternalError());
409 return;
410 }
411
412 widget_host_->Focus();
413 widget_host_->GetTouchEmulator()->Enable(
414 TouchEmulator::Mode::kInjectingTouchEvents,
415 ui::GestureProviderConfigType::CURRENT_PLATFORM);
416 base::OnceClosure closure = base::BindOnce(
417 &DispatchTouchEventCallback::sendSuccess, std::move(callback));
418 for (size_t i = 0; i < events.size(); i++) {
419 widget_host_->GetTouchEmulator()->InjectTouchEvent(
W. James MacLeana1403ff2018-06-11 19:28:08420 events[i], widget_host_->GetView(),
Dmitry Gozman901b6302018-03-02 02:30:39421 i == events.size() - 1 ? std::move(closure) : base::OnceClosure());
422 }
423 MaybeSelfDestruct();
424 }
425
426 private:
427 void OnInputEvent(const blink::WebInputEvent& event) override {
428 input_queued_ = true;
429 }
430
431 void OnInputEventAck(InputEventAckSource source,
432 InputEventAckState state,
433 const blink::WebInputEvent& event) override {
434 if ((event.GetModifiers() & blink::WebInputEvent::kFromDebugger) == 0)
435 return;
436
437 if (blink::WebInputEvent::IsKeyboardEventType(event.GetType()) &&
438 !pending_key_callbacks_.empty()) {
439 pending_key_callbacks_.front()->sendSuccess();
440 pending_key_callbacks_.pop_front();
441 MaybeSelfDestruct();
442 return;
443 }
444
445 if ((blink::WebInputEvent::IsMouseEventType(event.GetType()) ||
446 event.GetType() == blink::WebInputEvent::kMouseWheel) &&
447 !pending_mouse_callbacks_.empty()) {
448 pending_mouse_callbacks_.front()->sendSuccess();
449 pending_mouse_callbacks_.pop_front();
450 MaybeSelfDestruct();
451 return;
452 }
453 }
454
455 void MaybeSelfDestruct() {
456 if (!pending_key_callbacks_.empty() || !pending_mouse_callbacks_.empty())
457 return;
458 if (widget_host_)
459 widget_host_->RemoveInputEventObserver(this);
460 owner_->injectors_.erase(this);
461 }
462
463 InputHandler* const owner_;
464 base::WeakPtr<RenderWidgetHostImpl> widget_host_;
465 // Callbacks for calls to Input.dispatchKey/MouseEvent that have been sent to
466 // the renderer, but that we haven't yet received an ack for.
467 bool input_queued_ = false;
468 base::circular_deque<std::unique_ptr<DispatchKeyEventCallback>>
469 pending_key_callbacks_;
470 base::circular_deque<std::unique_ptr<DispatchMouseEventCallback>>
471 pending_mouse_callbacks_;
472
473 DISALLOW_COPY_AND_ASSIGN(InputInjector);
474};
475
vkuzkokovc985d952014-10-01 12:24:13476InputHandler::InputHandler()
dgozman39d9d9a2016-12-28 18:56:30477 : DevToolsDomainHandler(Input::Metainfo::domainName),
478 host_(nullptr),
samuonged25cba2015-04-30 23:10:54479 page_scale_factor_(1.0),
Jeremy Roman3bca4bf2019-07-11 03:41:25480 last_id_(0) {}
vkuzkokovc985d952014-10-01 12:24:13481
482InputHandler::~InputHandler() {
483}
484
dgozman39d9d9a2016-12-28 18:56:30485// static
dgozman9bca3cc2017-05-05 22:35:26486std::vector<InputHandler*> InputHandler::ForAgentHost(
487 DevToolsAgentHostImpl* host) {
Dmitry Gozman08a40e2f2018-10-02 21:16:41488 return host->HandlersByName<InputHandler>(Input::Metainfo::domainName);
dgozman39d9d9a2016-12-28 18:56:30489}
490
Andrey Kosyakov3c8e4852018-01-23 05:20:27491void InputHandler::SetRenderer(int process_host_id,
Andrey Kosyakova1d473a2017-10-12 01:41:26492 RenderFrameHostImpl* frame_host) {
493 if (frame_host == host_)
Dmitry Gozman95bab292017-08-16 22:48:58494 return;
495 ClearInputState();
Avi Drissmanc2618c042018-08-30 14:12:57496
497 WebContents* old_web_contents = WebContents::FromRenderFrameHost(host_);
498 WebContents* new_web_contents = WebContents::FromRenderFrameHost(frame_host);
499
Andrey Kosyakov78fdaec2019-04-06 00:15:57500 // When navigating, the new renderer might have a different page scale.
501 // It emits a changed event iff the new page scale is not 1
502 // (see crbug.com/929806)
503 // If attaching to a new host, we've got OnPageScaleFactorChanged(),
504 // so don't override it.
505 if (host_)
506 page_scale_factor_ = 1.0;
507
Andrey Kosyakova1d473a2017-10-12 01:41:26508 host_ = frame_host;
Avi Drissmanc2618c042018-08-30 14:12:57509
510 if (ignore_input_events_ && old_web_contents != new_web_contents) {
511 if (old_web_contents)
512 old_web_contents->SetIgnoreInputEvents(false);
513 if (new_web_contents)
514 new_web_contents->SetIgnoreInputEvents(true);
515 }
vkuzkokovc985d952014-10-01 12:24:13516}
517
dgozman111fdd032016-12-18 00:49:26518void InputHandler::Wire(UberDispatcher* dispatcher) {
519 Input::Dispatcher::wire(dispatcher, this);
samuonged25cba2015-04-30 23:10:54520}
521
Joel Einbinder89a0720b82018-03-27 03:21:13522void InputHandler::OnPageScaleFactorChanged(float page_scale_factor) {
523 page_scale_factor_ = page_scale_factor;
samuong1b5ccef2015-02-20 19:30:24524}
525
dgozman111fdd032016-12-18 00:49:26526Response InputHandler::Disable() {
Dmitry Gozman95bab292017-08-16 22:48:58527 ClearInputState();
Avi Drissmanc2618c042018-08-30 14:12:57528 WebContents* web_contents = WebContents::FromRenderFrameHost(host_);
529 if (web_contents && ignore_input_events_)
530 web_contents->SetIgnoreInputEvents(false);
pfeldmana26cfa52017-05-23 21:41:39531 ignore_input_events_ = false;
Lan Wei9c6f1242019-02-11 23:01:30532 pointer_ids_.clear();
Lan Weie77c3d22019-03-08 20:38:16533 touch_points_.clear();
dgozman111fdd032016-12-18 00:49:26534 return Response::OK();
535}
536
samuong8db76012017-01-20 06:36:08537void InputHandler::DispatchKeyEvent(
dgozman6d9d8532015-04-03 18:04:51538 const std::string& type,
dgozman111fdd032016-12-18 00:49:26539 Maybe<int> modifiers,
540 Maybe<double> timestamp,
541 Maybe<std::string> text,
542 Maybe<std::string> unmodified_text,
543 Maybe<std::string> key_identifier,
544 Maybe<std::string> code,
545 Maybe<std::string> key,
546 Maybe<int> windows_virtual_key_code,
547 Maybe<int> native_virtual_key_code,
548 Maybe<bool> auto_repeat,
549 Maybe<bool> is_keypad,
samuong8db76012017-01-20 06:36:08550 Maybe<bool> is_system_key,
Joel Einbinderd5b1a0e2017-10-19 03:38:05551 Maybe<int> location,
samuong8db76012017-01-20 06:36:08552 std::unique_ptr<DispatchKeyEventCallback> callback) {
dtapuska899ac222017-01-03 18:09:16553 blink::WebInputEvent::Type web_event_type;
dgozmane20f50c2015-04-06 10:46:39554
dgozman111fdd032016-12-18 00:49:26555 if (type == Input::DispatchKeyEvent::TypeEnum::KeyDown) {
Blink Reformat1c4d759e2017-04-09 16:34:54556 web_event_type = blink::WebInputEvent::kKeyDown;
dgozman111fdd032016-12-18 00:49:26557 } else if (type == Input::DispatchKeyEvent::TypeEnum::KeyUp) {
Blink Reformat1c4d759e2017-04-09 16:34:54558 web_event_type = blink::WebInputEvent::kKeyUp;
dgozman111fdd032016-12-18 00:49:26559 } else if (type == Input::DispatchKeyEvent::TypeEnum::Char) {
Blink Reformat1c4d759e2017-04-09 16:34:54560 web_event_type = blink::WebInputEvent::kChar;
dgozman111fdd032016-12-18 00:49:26561 } else if (type == Input::DispatchKeyEvent::TypeEnum::RawKeyDown) {
Blink Reformat1c4d759e2017-04-09 16:34:54562 web_event_type = blink::WebInputEvent::kRawKeyDown;
dgozmane20f50c2015-04-06 10:46:39563 } else {
samuong8db76012017-01-20 06:36:08564 callback->sendFailure(Response::InvalidParams(
565 base::StringPrintf("Unexpected event type '%s'", type.c_str())));
566 return;
dgozmane20f50c2015-04-06 10:46:39567 }
568
dtapuska899ac222017-01-03 18:09:16569 NativeWebKeyboardEvent event(
570 web_event_type,
Blink Reformat1c4d759e2017-04-09 16:34:54571 GetEventModifiers(modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers),
dtapuska899ac222017-01-03 18:09:16572 auto_repeat.fromMaybe(false),
Lan Wei3d5ac6c52018-12-13 21:21:14573 is_keypad.fromMaybe(false), location.fromMaybe(0), 0),
Daniel Cheng224569ee2018-04-25 05:45:06574 GetEventTimeTicks(timestamp));
Blaisebcad00c2017-07-25 00:19:49575
samuong8db76012017-01-20 06:36:08576 if (!SetKeyboardEventText(event.text, std::move(text))) {
577 callback->sendFailure(Response::InvalidParams("Invalid 'text' parameter"));
578 return;
579 }
Blink Reformat1c4d759e2017-04-09 16:34:54580 if (!SetKeyboardEventText(event.unmodified_text,
581 std::move(unmodified_text))) {
samuong8db76012017-01-20 06:36:08582 callback->sendFailure(
583 Response::InvalidParams("Invalid 'unmodifiedText' parameter"));
584 return;
585 }
dgozmane20f50c2015-04-06 10:46:39586
dgozman111fdd032016-12-18 00:49:26587 if (windows_virtual_key_code.isJust())
Blink Reformat1c4d759e2017-04-09 16:34:54588 event.windows_key_code = windows_virtual_key_code.fromJust();
dgozman111fdd032016-12-18 00:49:26589 if (native_virtual_key_code.isJust())
Blink Reformat1c4d759e2017-04-09 16:34:54590 event.native_key_code = native_virtual_key_code.fromJust();
dgozman111fdd032016-12-18 00:49:26591 if (is_system_key.isJust())
Blink Reformat1c4d759e2017-04-09 16:34:54592 event.is_system_key = is_system_key.fromJust();
dgozmane20f50c2015-04-06 10:46:39593
dgozman111fdd032016-12-18 00:49:26594 if (code.isJust()) {
Blink Reformat1c4d759e2017-04-09 16:34:54595 event.dom_code = static_cast<int>(
dgozman111fdd032016-12-18 00:49:26596 ui::KeycodeConverter::CodeStringToDomCode(code.fromJust()));
mharanczyk38785842015-05-27 07:53:48597 }
598
dgozman111fdd032016-12-18 00:49:26599 if (key.isJust()) {
Blink Reformat1c4d759e2017-04-09 16:34:54600 event.dom_key = static_cast<int>(
dgozman111fdd032016-12-18 00:49:26601 ui::KeycodeConverter::KeyStringToDomKey(key.fromJust()));
habib.virjibb338c92015-06-02 16:32:24602 }
603
samuong8db76012017-01-20 06:36:08604 if (!host_ || !host_->GetRenderWidgetHost()) {
605 callback->sendFailure(Response::InternalError());
606 return;
607 }
thakis3505cba2017-06-10 18:10:52608
Dmitry Gozman901b6302018-03-02 02:30:39609 RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
610 if (!host_->GetParent() && widget_host->delegate()) {
611 RenderWidgetHostImpl* target_host =
612 widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host);
613 if (target_host)
614 widget_host = target_host;
615 }
616
Blaisebcad00c2017-07-25 00:19:49617 // We do not pass events to browser if there is no native key event
618 // due to Mac needing the actual os_event.
619 if (event.native_key_code)
620 event.os_event = NativeInputEventBuilder::CreateEvent(event);
621 else
622 event.skip_in_browser = true;
623
Dmitry Gozman901b6302018-03-02 02:30:39624 EnsureInjector(widget_host)->InjectKeyboardEvent(event, std::move(callback));
dgozman6d9d8532015-04-03 18:04:51625}
626
Joel Einbinder7a680362018-07-28 19:44:53627void InputHandler::InsertText(const std::string& text,
628 std::unique_ptr<InsertTextCallback> callback) {
629 base::string16 text16 = base::UTF8ToUTF16(text);
630 base::OnceClosure closure =
631 base::BindOnce(&InsertTextCallback::sendSuccess, std::move(callback));
632
633 if (!host_ || !host_->GetRenderWidgetHost()) {
634 callback->sendFailure(Response::InternalError());
635 return;
636 }
637
638 RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
639 if (!host_->GetParent() && widget_host->delegate()) {
640 RenderWidgetHostImpl* target_host =
641 widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host);
642 if (target_host)
643 widget_host = target_host;
644 }
645
646 widget_host->Focus();
647 widget_host->GetWidgetInputHandler()->ImeCommitText(
648 text16, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0,
649 std::move(closure));
650}
651
samuong8db76012017-01-20 06:36:08652void InputHandler::DispatchMouseEvent(
Dmitry Gozman1e8fae32017-08-16 00:04:41653 const std::string& event_type,
Pavel Feldman04e776d72017-07-12 23:52:40654 double x,
655 double y,
Dmitry Gozman1e8fae32017-08-16 00:04:41656 Maybe<int> maybe_modifiers,
657 Maybe<double> maybe_timestamp,
658 Maybe<std::string> maybe_button,
Lan Wei3d5ac6c52018-12-13 21:21:14659 Maybe<int> buttons,
samuong8db76012017-01-20 06:36:08660 Maybe<int> click_count,
Dmitry Gozman1e8fae32017-08-16 00:04:41661 Maybe<double> delta_x,
662 Maybe<double> delta_y,
Lan Weid387faf2019-01-02 20:08:08663 Maybe<std::string> pointer_type,
samuong8db76012017-01-20 06:36:08664 std::unique_ptr<DispatchMouseEventCallback> callback) {
Dmitry Gozman1e8fae32017-08-16 00:04:41665 blink::WebInputEvent::Type type = GetMouseEventType(event_type);
666 if (type == blink::WebInputEvent::kUndefined) {
samuong8db76012017-01-20 06:36:08667 callback->sendFailure(Response::InvalidParams(
Dmitry Gozman1e8fae32017-08-16 00:04:41668 base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
samuong8db76012017-01-20 06:36:08669 return;
dgozmane20f50c2015-04-06 10:46:39670 }
Dmitry Gozman1e8fae32017-08-16 00:04:41671
672 blink::WebPointerProperties::Button button =
Blink Reformat1c4d759e2017-04-09 16:34:54673 blink::WebPointerProperties::Button::kNoButton;
dtapuska899ac222017-01-03 18:09:16674 int button_modifiers = 0;
Dmitry Gozman1e8fae32017-08-16 00:04:41675 if (!GetMouseEventButton(maybe_button.fromMaybe(""), &button,
samuong8db76012017-01-20 06:36:08676 &button_modifiers)) {
677 callback->sendFailure(Response::InvalidParams("Invalid mouse button"));
678 return;
679 }
dgozmane20f50c2015-04-06 10:46:39680
Dmitry Gozman1e8fae32017-08-16 00:04:41681 int modifiers = GetEventModifiers(
682 maybe_modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
Lan Wei3d5ac6c52018-12-13 21:21:14683 false, 0, buttons.fromMaybe(0));
Dmitry Gozman1e8fae32017-08-16 00:04:41684 modifiers |= button_modifiers;
Daniel Cheng224569ee2018-04-25 05:45:06685 base::TimeTicks timestamp = GetEventTimeTicks(maybe_timestamp);
dtapuska899ac222017-01-03 18:09:16686
Dmitry Gozman1e8fae32017-08-16 00:04:41687 std::unique_ptr<blink::WebMouseEvent, ui::WebInputEventDeleter> mouse_event;
688 blink::WebMouseWheelEvent* wheel_event = nullptr;
dgozmane20f50c2015-04-06 10:46:39689
Dmitry Gozman1e8fae32017-08-16 00:04:41690 if (type == blink::WebInputEvent::kMouseWheel) {
691 wheel_event = new blink::WebMouseWheelEvent(type, modifiers, timestamp);
692 mouse_event.reset(wheel_event);
693 if (!delta_x.isJust() || !delta_y.isJust()) {
694 callback->sendFailure(Response::InvalidParams(
695 "'deltaX' and 'deltaY' are expected for mouseWheel event"));
696 return;
697 }
698 wheel_event->delta_x = static_cast<float>(-delta_x.fromJust());
699 wheel_event->delta_y = static_cast<float>(-delta_y.fromJust());
Sahel Sharifye6d81f472018-07-11 20:40:26700 wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
701 wheel_event->dispatch_type = blink::WebInputEvent::kBlocking;
Dmitry Gozman1e8fae32017-08-16 00:04:41702 } else {
703 mouse_event.reset(new blink::WebMouseEvent(type, modifiers, timestamp));
704 }
705
706 mouse_event->button = button;
Dmitry Gozman1e8fae32017-08-16 00:04:41707 mouse_event->click_count = click_count.fromMaybe(0);
Lan Weid387faf2019-01-02 20:08:08708 mouse_event->pointer_type = GetPointerType(pointer_type.fromMaybe(""));
Dmitry Gozman1e8fae32017-08-16 00:04:41709
Dmitry Gozman901b6302018-03-02 02:30:39710 gfx::PointF point;
711 RenderWidgetHostImpl* widget_host =
712 FindTargetWidgetHost(CssPixelsToPointF(x, y, page_scale_factor_), &point);
713 if (!widget_host) {
samuong8db76012017-01-20 06:36:08714 callback->sendFailure(Response::InternalError());
Dmitry Gozman1e8fae32017-08-16 00:04:41715 return;
716 }
dgozmane20f50c2015-04-06 10:46:39717
Dmitry Gozman901b6302018-03-02 02:30:39718 mouse_event->SetPositionInWidget(point.x(), point.y());
719 mouse_event->SetPositionInScreen(point.x(), point.y());
720 if (wheel_event) {
721 EnsureInjector(widget_host)
722 ->InjectWheelEvent(wheel_event, std::move(callback));
723 } else {
724 EnsureInjector(widget_host)
725 ->InjectMouseEvent(*mouse_event, std::move(callback));
samuong8db76012017-01-20 06:36:08726 }
dgozman6d9d8532015-04-03 18:04:51727}
728
Dmitry Gozman95bab292017-08-16 22:48:58729void InputHandler::DispatchTouchEvent(
730 const std::string& event_type,
731 std::unique_ptr<Array<Input::TouchPoint>> touch_points,
732 protocol::Maybe<int> maybe_modifiers,
733 protocol::Maybe<double> maybe_timestamp,
734 std::unique_ptr<DispatchTouchEventCallback> callback) {
Lan Weie77c3d22019-03-08 20:38:16735 if (base::FeatureList::IsEnabled(features::kSyntheticPointerActions)) {
736 DispatchSyntheticPointerActionTouch(
737 event_type, std::move(touch_points), std::move(maybe_modifiers),
738 std::move(maybe_timestamp), std::move(callback));
739 return;
740 }
741
742 DispatchWebTouchEvent(event_type, std::move(touch_points),
743 std::move(maybe_modifiers), std::move(maybe_timestamp),
744 std::move(callback));
745}
746
747void InputHandler::DispatchWebTouchEvent(
748 const std::string& event_type,
749 std::unique_ptr<Array<Input::TouchPoint>> touch_points,
750 protocol::Maybe<int> maybe_modifiers,
751 protocol::Maybe<double> maybe_timestamp,
752 std::unique_ptr<DispatchTouchEventCallback> callback) {
753 blink::WebInputEvent::Type type = GetTouchEventType(event_type);
754 if (type == blink::WebInputEvent::kUndefined) {
755 callback->sendFailure(Response::InvalidParams(
756 base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
757 return;
758 }
759
760 int modifiers = GetEventModifiers(
761 maybe_modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
762 false, 0, 0);
763 base::TimeTicks timestamp = GetEventTimeTicks(maybe_timestamp);
764
765 if ((type == blink::WebInputEvent::kTouchStart ||
766 type == blink::WebInputEvent::kTouchMove) &&
Johannes Henkel53d2ce282019-06-18 23:14:27767 touch_points->empty()) {
Lan Weie77c3d22019-03-08 20:38:16768 callback->sendFailure(Response::InvalidParams(
769 "TouchStart and TouchMove must have at least one touch point."));
770 return;
771 }
772 if ((type == blink::WebInputEvent::kTouchEnd ||
773 type == blink::WebInputEvent::kTouchCancel) &&
Johannes Henkel53d2ce282019-06-18 23:14:27774 !touch_points->empty()) {
Lan Weie77c3d22019-03-08 20:38:16775 callback->sendFailure(Response::InvalidParams(
776 "TouchEnd and TouchCancel must not have any touch points."));
777 return;
778 }
779 if (type == blink::WebInputEvent::kTouchStart && !touch_points_.empty()) {
780 callback->sendFailure(Response::InvalidParams(
781 "Must have no prior active touch points to start a new touch."));
782 return;
783 }
784 if (type != blink::WebInputEvent::kTouchStart && touch_points_.empty()) {
785 callback->sendFailure(Response::InvalidParams(
786 "Must send a TouchStart first to start a new touch."));
787 return;
788 }
789
790 base::flat_map<int, blink::WebTouchPoint> points;
791 size_t with_id = 0;
Johannes Henkel53d2ce282019-06-18 23:14:27792 for (size_t i = 0; i < touch_points->size(); ++i) {
793 Input::TouchPoint* point = (*touch_points)[i].get();
794 int id = point->GetId(i); // index |i| is default for the id.
Lan Weie77c3d22019-03-08 20:38:16795 if (point->HasId())
796 with_id++;
797 points[id].id = id;
798 points[id].radius_x = point->GetRadiusX(1.0);
799 points[id].radius_y = point->GetRadiusY(1.0);
800 points[id].rotation_angle = point->GetRotationAngle(0.0);
801 points[id].force = point->GetForce(1.0);
802 points[id].pointer_type = blink::WebPointerProperties::PointerType::kTouch;
803 points[id].SetPositionInWidget(point->GetX() * page_scale_factor_,
804 point->GetY() * page_scale_factor_);
805 points[id].SetPositionInScreen(point->GetX() * page_scale_factor_,
806 point->GetY() * page_scale_factor_);
807 }
Johannes Henkel53d2ce282019-06-18 23:14:27808 if (with_id > 0 && with_id < touch_points->size()) {
Lan Weie77c3d22019-03-08 20:38:16809 callback->sendFailure(Response::InvalidParams(
810 "All or none of the provided TouchPoints must supply ids."));
811 return;
812 }
813
814 std::vector<blink::WebTouchEvent> events;
815 bool ok = true;
816 for (auto& id_point : points) {
817 if (touch_points_.find(id_point.first) != touch_points_.end())
818 continue;
819 events.emplace_back(type, modifiers, timestamp);
820 ok &= GenerateTouchPoints(&events.back(), blink::WebInputEvent::kUndefined,
821 touch_points_, id_point.second);
822 touch_points_.insert(id_point);
823 }
824 for (auto& id_point : points) {
825 DCHECK(touch_points_.find(id_point.first) != touch_points_.end());
826 if (touch_points_[id_point.first].PositionInWidget() ==
827 id_point.second.PositionInWidget()) {
828 continue;
829 }
830 events.emplace_back(type, modifiers, timestamp);
831 ok &= GenerateTouchPoints(&events.back(), blink::WebInputEvent::kUndefined,
832 touch_points_, id_point.second);
833 touch_points_[id_point.first] = id_point.second;
834 }
835 if (type != blink::WebInputEvent::kTouchCancel)
836 type = blink::WebInputEvent::kTouchEnd;
837 for (auto it = touch_points_.begin(); it != touch_points_.end();) {
838 if (points.find(it->first) != points.end()) {
839 it++;
840 continue;
841 }
842 events.emplace_back(type, modifiers, timestamp);
843 ok &= GenerateTouchPoints(&events.back(), type, touch_points_, it->second);
844 it = touch_points_.erase(it);
845 }
846 if (!ok) {
847 callback->sendFailure(Response::Error(
848 base::StringPrintf("Exceeded maximum touch points limit of %d",
849 blink::WebTouchEvent::kTouchesLengthCap)));
850 return;
851 }
852
853 if (events.empty()) {
854 callback->sendSuccess();
855 return;
856 }
857
858 gfx::PointF original(events[0].touches[0].PositionInWidget().x,
859 events[0].touches[0].PositionInWidget().y);
860 gfx::PointF transformed;
861 RenderWidgetHostImpl* widget_host =
862 FindTargetWidgetHost(original, &transformed);
863 if (!widget_host) {
864 callback->sendFailure(Response::InternalError());
865 return;
866 }
867 gfx::Vector2dF delta = transformed - original;
868 for (size_t i = 0; i < events.size(); i++) {
869 events[i].dispatch_type =
870 events[i].GetType() == blink::WebInputEvent::kTouchCancel
871 ? blink::WebInputEvent::kEventNonBlocking
872 : blink::WebInputEvent::kBlocking;
873 events[i].moved_beyond_slop_region = true;
874 events[i].unique_touch_event_id = ui::GetNextTouchEventId();
875 for (unsigned j = 0; j < events[i].touches_length; j++) {
876 blink::WebFloatPoint point = events[i].touches[j].PositionInWidget();
877 events[i].touches[j].SetPositionInWidget(point.x + delta.x(),
878 point.y + delta.y());
879 point = events[i].touches[j].PositionInScreen();
880 events[i].touches[j].SetPositionInScreen(point.x + delta.x(),
881 point.y + delta.y());
882 }
883 }
884 EnsureInjector(widget_host)->InjectTouchEvents(events, std::move(callback));
885}
886
887void InputHandler::DispatchSyntheticPointerActionTouch(
888 const std::string& event_type,
889 std::unique_ptr<Array<Input::TouchPoint>> touch_points,
890 protocol::Maybe<int> maybe_modifiers,
891 protocol::Maybe<double> maybe_timestamp,
892 std::unique_ptr<DispatchTouchEventCallback> callback) {
Lan Wei9c6f1242019-02-11 23:01:30893 if (!host_ || !host_->GetRenderWidgetHost()) {
894 callback->sendFailure(Response::InternalError());
895 return;
896 }
897
898 SyntheticPointerActionParams::PointerActionType pointer_action_type =
899 GetTouchPointerActionType(event_type);
900 if (pointer_action_type ==
901 SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED) {
Dmitry Gozman95bab292017-08-16 22:48:58902 callback->sendFailure(Response::InvalidParams(
903 base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
904 return;
905 }
906
907 int modifiers = GetEventModifiers(
908 maybe_modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
Lan Wei3d5ac6c52018-12-13 21:21:14909 false, 0, 0);
Dmitry Gozman95bab292017-08-16 22:48:58910
Lan Wei9c6f1242019-02-11 23:01:30911 if ((pointer_action_type ==
912 SyntheticPointerActionParams::PointerActionType::PRESS ||
913 pointer_action_type ==
914 SyntheticPointerActionParams::PointerActionType::MOVE) &&
Johannes Henkel53d2ce282019-06-18 23:14:27915 touch_points->empty()) {
Dmitry Gozman95bab292017-08-16 22:48:58916 callback->sendFailure(Response::InvalidParams(
917 "TouchStart and TouchMove must have at least one touch point."));
918 return;
919 }
Lan Wei9c6f1242019-02-11 23:01:30920 if ((pointer_action_type ==
921 SyntheticPointerActionParams::PointerActionType::RELEASE ||
922 pointer_action_type ==
923 SyntheticPointerActionParams::PointerActionType::CANCEL) &&
Johannes Henkel53d2ce282019-06-18 23:14:27924 !touch_points->empty()) {
Dmitry Gozman95bab292017-08-16 22:48:58925 callback->sendFailure(Response::InvalidParams(
926 "TouchEnd and TouchCancel must not have any touch points."));
927 return;
928 }
Lan Wei9c6f1242019-02-11 23:01:30929 if (pointer_action_type ==
930 SyntheticPointerActionParams::PointerActionType::PRESS &&
931 !pointer_ids_.empty()) {
Dmitry Gozman95bab292017-08-16 22:48:58932 callback->sendFailure(Response::InvalidParams(
933 "Must have no prior active touch points to start a new touch."));
934 return;
935 }
Lan Wei9c6f1242019-02-11 23:01:30936 if (pointer_action_type !=
937 SyntheticPointerActionParams::PointerActionType::PRESS &&
938 pointer_ids_.empty()) {
Dmitry Gozman95bab292017-08-16 22:48:58939 callback->sendFailure(Response::InvalidParams(
940 "Must send a TouchStart first to start a new touch."));
941 return;
942 }
943
Lan Wei9c6f1242019-02-11 23:01:30944 SyntheticGestureParams::GestureSourceType gesture_source_type =
945 SyntheticGestureParams::GestureSourceType::TOUCH_INPUT;
946 SyntheticPointerActionListParams action_list_params;
947 SyntheticPointerActionListParams::ParamList param_list;
948 action_list_params.gesture_source_type = gesture_source_type;
949 if (pointer_action_type ==
950 SyntheticPointerActionParams::PointerActionType::RELEASE ||
951 pointer_action_type ==
952 SyntheticPointerActionParams::PointerActionType::CANCEL) {
953 for (auto it = pointer_ids_.begin(); it != pointer_ids_.end();) {
954 SyntheticPointerActionParams action_params =
955 PrepareSyntheticPointerActionParams(pointer_action_type, *it, "", 0,
956 0, modifiers);
957 param_list.push_back(action_params);
958 it = pointer_ids_.erase(it);
959 }
960 }
961
Dmitry Gozman95bab292017-08-16 22:48:58962 size_t with_id = 0;
Lan Wei9c6f1242019-02-11 23:01:30963 gfx::PointF original;
964 std::set<int> current_pointer_ids;
Johannes Henkel53d2ce282019-06-18 23:14:27965 for (size_t i = 0; i < touch_points->size(); ++i) {
966 Input::TouchPoint* point = (*touch_points)[i].get();
967 int id = point->GetId(i); // index |i| is default for the id.
Dmitry Gozman95bab292017-08-16 22:48:58968 if (point->HasId())
969 with_id++;
Lan Wei9c6f1242019-02-11 23:01:30970
971 SyntheticPointerActionParams::PointerActionType action_type =
972 SyntheticPointerActionParams::PointerActionType::MOVE;
973 if (pointer_ids_.find(id) == pointer_ids_.end()) {
974 pointer_ids_.insert(id);
975 action_type = SyntheticPointerActionParams::PointerActionType::PRESS;
976 }
977 SyntheticPointerActionParams action_params =
978 PrepareSyntheticPointerActionParams(
979 action_type, id, "", point->GetX(), point->GetY(), modifiers,
980 point->GetRadiusX(1.0), point->GetRadiusY(1.0),
981 point->GetRotationAngle(0.0), point->GetForce(1.0));
982 param_list.push_back(action_params);
983 original = gfx::PointF(point->GetX(), point->GetY());
984 current_pointer_ids.insert(id);
Dmitry Gozman95bab292017-08-16 22:48:58985 }
Johannes Henkel53d2ce282019-06-18 23:14:27986 if (with_id > 0 && with_id < touch_points->size()) {
Dmitry Gozman95bab292017-08-16 22:48:58987 callback->sendFailure(Response::InvalidParams(
988 "All or none of the provided TouchPoints must supply ids."));
989 return;
990 }
991
Lan Wei9c6f1242019-02-11 23:01:30992 if (pointer_action_type ==
993 SyntheticPointerActionParams::PointerActionType::MOVE &&
994 current_pointer_ids.size() < pointer_ids_.size()) {
995 for (auto it = pointer_ids_.begin(); it != pointer_ids_.end();) {
996 if (current_pointer_ids.find(*it) != current_pointer_ids.end()) {
997 it++;
998 continue;
999 }
1000 SyntheticPointerActionParams action_params =
1001 PrepareSyntheticPointerActionParams(
1002 SyntheticPointerActionParams::PointerActionType::RELEASE, *it, "",
1003 0, 0, modifiers);
1004 param_list.push_back(action_params);
1005 it = pointer_ids_.erase(it);
Dmitry Gozman95bab292017-08-16 22:48:581006 }
Dmitry Gozman95bab292017-08-16 22:48:581007 }
Lan Wei9c6f1242019-02-11 23:01:301008 action_list_params.PushPointerActionParamsList(param_list);
Dmitry Gozman95bab292017-08-16 22:48:581009
Lan Wei9c6f1242019-02-11 23:01:301010 if (!synthetic_pointer_driver_) {
1011 synthetic_pointer_driver_ =
1012 SyntheticPointerDriver::Create(gesture_source_type);
Dmitry Gozman95bab292017-08-16 22:48:581013 }
Lan Wei9c6f1242019-02-11 23:01:301014 std::unique_ptr<SyntheticPointerAction> synthetic_gesture =
1015 std::make_unique<SyntheticPointerAction>(action_list_params);
1016 synthetic_gesture->SetSyntheticPointerDriver(synthetic_pointer_driver_.get());
Dmitry Gozman95bab292017-08-16 22:48:581017
Kevin McNee4d843a5c2019-02-19 16:50:341018 RenderWidgetHostViewBase* root_view = GetRootView();
1019 if (!root_view) {
Dmitry Gozman901b6302018-03-02 02:30:391020 callback->sendFailure(Response::InternalError());
1021 return;
1022 }
Kevin McNee4d843a5c2019-02-19 16:50:341023
1024 root_view->host()->QueueSyntheticGesture(
Lan Wei9c6f1242019-02-11 23:01:301025 std::move(synthetic_gesture),
1026 base::BindOnce(&DispatchPointerActionsResponse, std::move(callback)));
1027}
1028
1029SyntheticPointerActionParams InputHandler::PrepareSyntheticPointerActionParams(
1030 SyntheticPointerActionParams::PointerActionType pointer_action_type,
1031 int id,
1032 const std::string& button_name,
1033 double x,
1034 double y,
1035 int key_modifiers,
1036 float radius_x,
1037 float radius_y,
1038 float rotation_angle,
1039 float force) {
1040 SyntheticPointerActionParams action_params(pointer_action_type);
1041 action_params.set_pointer_id(id);
1042 SyntheticPointerActionParams::Button button =
1043 GetPointerActionParamsButton(button_name);
1044 switch (pointer_action_type) {
1045 case SyntheticPointerActionParams::PointerActionType::PRESS:
1046 action_params.set_position(
1047 gfx::PointF(x * page_scale_factor_, y * page_scale_factor_));
1048 action_params.set_button(button);
1049 action_params.set_key_modifiers(key_modifiers);
1050 action_params.set_width(radius_x * 2.f);
1051 action_params.set_height(radius_y * 2.f);
1052 action_params.set_rotation_angle(rotation_angle);
1053 action_params.set_force(force);
1054 break;
1055 case SyntheticPointerActionParams::PointerActionType::MOVE:
1056 action_params.set_position(
1057 gfx::PointF(x * page_scale_factor_, y * page_scale_factor_));
1058 action_params.set_key_modifiers(key_modifiers);
1059 action_params.set_width(radius_x * 2.f);
1060 action_params.set_height(radius_y * 2.f);
1061 action_params.set_rotation_angle(rotation_angle);
1062 action_params.set_force(force);
1063 break;
1064 case SyntheticPointerActionParams::PointerActionType::RELEASE:
1065 case SyntheticPointerActionParams::PointerActionType::CANCEL:
1066 action_params.set_button(button);
1067 action_params.set_key_modifiers(key_modifiers);
1068 break;
1069 case SyntheticPointerActionParams::PointerActionType::LEAVE:
1070 case SyntheticPointerActionParams::PointerActionType::IDLE:
1071 case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
1072 NOTREACHED();
1073 break;
Dmitry Gozman95bab292017-08-16 22:48:581074 }
Lan Wei9c6f1242019-02-11 23:01:301075 return action_params;
Dmitry Gozman95bab292017-08-16 22:48:581076}
1077
vkuzkokovc985d952014-10-01 12:24:131078Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
1079 int x,
1080 int y,
vkuzkokovc985d952014-10-01 12:24:131081 const std::string& button,
Deepanjan Roy5ba32182018-01-22 19:51:021082 Maybe<double> maybe_timestamp,
dgozman111fdd032016-12-18 00:49:261083 Maybe<double> delta_x,
1084 Maybe<double> delta_y,
1085 Maybe<int> modifiers,
1086 Maybe<int> click_count) {
dtapuska899ac222017-01-03 18:09:161087 blink::WebInputEvent::Type event_type;
dgozman111fdd032016-12-18 00:49:261088 if (type == Input::EmulateTouchFromMouseEvent::TypeEnum::MouseWheel) {
Blink Reformat1c4d759e2017-04-09 16:34:541089 event_type = blink::WebInputEvent::kMouseWheel;
dgozman111fdd032016-12-18 00:49:261090 if (!delta_x.isJust() || !delta_y.isJust()) {
vkuzkokovc985d952014-10-01 12:24:131091 return Response::InvalidParams(
1092 "'deltaX' and 'deltaY' are expected for mouseWheel event");
1093 }
dtapuska899ac222017-01-03 18:09:161094 } else {
1095 event_type = GetMouseEventType(type);
Blink Reformat1c4d759e2017-04-09 16:34:541096 if (event_type == blink::WebInputEvent::kUndefined) {
dtapuska899ac222017-01-03 18:09:161097 return Response::InvalidParams(
1098 base::StringPrintf("Unexpected event type '%s'", type.c_str()));
1099 }
vkuzkokovc985d952014-10-01 12:24:131100 }
1101
dtapuska899ac222017-01-03 18:09:161102 blink::WebPointerProperties::Button event_button =
Blink Reformat1c4d759e2017-04-09 16:34:541103 blink::WebPointerProperties::Button::kNoButton;
dtapuska899ac222017-01-03 18:09:161104 int button_modifiers = 0;
1105 if (!GetMouseEventButton(button, &event_button, &button_modifiers))
dgozmane20f50c2015-04-06 10:46:391106 return Response::InvalidParams("Invalid mouse button");
vkuzkokovc985d952014-10-01 12:24:131107
jam013b74c82017-02-10 16:36:101108 ui::WebScopedInputEvent event;
dtapuska899ac222017-01-03 18:09:161109 blink::WebMouseWheelEvent* wheel_event = nullptr;
1110 blink::WebMouseEvent* mouse_event = nullptr;
1111 if (type == Input::EmulateTouchFromMouseEvent::TypeEnum::MouseWheel) {
1112 wheel_event = new blink::WebMouseWheelEvent(
Blink Reformat1c4d759e2017-04-09 16:34:541113 event_type,
1114 GetEventModifiers(
1115 modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
Lan Wei3d5ac6c52018-12-13 21:21:141116 false, 0, 0) |
Blink Reformat1c4d759e2017-04-09 16:34:541117 button_modifiers,
Daniel Cheng224569ee2018-04-25 05:45:061118 GetEventTimeTicks(maybe_timestamp));
dtapuska899ac222017-01-03 18:09:161119 mouse_event = wheel_event;
1120 event.reset(wheel_event);
Blink Reformat1c4d759e2017-04-09 16:34:541121 wheel_event->delta_x = static_cast<float>(delta_x.fromJust());
1122 wheel_event->delta_y = static_cast<float>(delta_y.fromJust());
Sahel Sharifye6d81f472018-07-11 20:40:261123 wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
dtapuska899ac222017-01-03 18:09:161124 } else {
1125 mouse_event = new blink::WebMouseEvent(
Blink Reformat1c4d759e2017-04-09 16:34:541126 event_type,
1127 GetEventModifiers(
1128 modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
Lan Wei3d5ac6c52018-12-13 21:21:141129 false, 0, 0) |
Blink Reformat1c4d759e2017-04-09 16:34:541130 button_modifiers,
Daniel Cheng224569ee2018-04-25 05:45:061131 GetEventTimeTicks(maybe_timestamp));
dtapuska899ac222017-01-03 18:09:161132 event.reset(mouse_event);
1133 }
1134
Blink Reformat1c4d759e2017-04-09 16:34:541135 mouse_event->SetPositionInWidget(x, y);
dtapuska899ac222017-01-03 18:09:161136 mouse_event->button = event_button;
Blink Reformat1c4d759e2017-04-09 16:34:541137 mouse_event->SetPositionInScreen(x, y);
1138 mouse_event->click_count = click_count.fromMaybe(0);
1139 mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kTouch;
vkuzkokovc985d952014-10-01 12:24:131140
dgozman111fdd032016-12-18 00:49:261141 if (!host_ || !host_->GetRenderWidgetHost())
1142 return Response::InternalError();
vkuzkokovc985d952014-10-01 12:24:131143
Sahel Sharify7f7a3172017-10-24 16:41:571144 if (wheel_event) {
dtapuska899ac222017-01-03 18:09:161145 host_->GetRenderWidgetHost()->ForwardWheelEvent(*wheel_event);
Sahel Sharifye6d81f472018-07-11 20:40:261146 // Send a synthetic wheel event with phaseEnded to finish scrolling.
1147 wheel_event->delta_x = 0;
1148 wheel_event->delta_y = 0;
1149 wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
1150 wheel_event->dispatch_type = blink::WebInputEvent::kEventNonBlocking;
1151 host_->GetRenderWidgetHost()->ForwardWheelEvent(*wheel_event);
Sahel Sharify7f7a3172017-10-24 16:41:571152 } else {
dtapuska899ac222017-01-03 18:09:161153 host_->GetRenderWidgetHost()->ForwardMouseEvent(*mouse_event);
Sahel Sharify7f7a3172017-10-24 16:41:571154 }
vkuzkokovc985d952014-10-01 12:24:131155 return Response::OK();
1156}
1157
pfeldmana26cfa52017-05-23 21:41:391158Response InputHandler::SetIgnoreInputEvents(bool ignore) {
1159 ignore_input_events_ = ignore;
Avi Drissmanc2618c042018-08-30 14:12:571160 WebContents* web_contents = WebContents::FromRenderFrameHost(host_);
1161 if (web_contents)
1162 web_contents->SetIgnoreInputEvents(ignore);
pfeldmana26cfa52017-05-23 21:41:391163 return Response::OK();
1164}
1165
dgozman111fdd032016-12-18 00:49:261166void InputHandler::SynthesizePinchGesture(
Pavel Feldman04e776d72017-07-12 23:52:401167 double x,
1168 double y,
samuong1b5ccef2015-02-20 19:30:241169 double scale_factor,
dgozman111fdd032016-12-18 00:49:261170 Maybe<int> relative_speed,
1171 Maybe<std::string> gesture_source_type,
1172 std::unique_ptr<SynthesizePinchGestureCallback> callback) {
1173 if (!host_ || !host_->GetRenderWidgetHost()) {
1174 callback->sendFailure(Response::InternalError());
1175 return;
1176 }
samuonged25cba2015-04-30 23:10:541177
1178 SyntheticPinchGestureParams gesture_params;
1179 const int kDefaultRelativeSpeed = 800;
1180
1181 gesture_params.scale_factor = scale_factor;
danakj2ef31b82015-10-21 18:18:021182 gesture_params.anchor = CssPixelsToPointF(x, y, page_scale_factor_);
dtapuska694e49d72017-05-10 17:15:121183 if (!PointIsWithinContents(gesture_params.anchor)) {
1184 callback->sendFailure(Response::InvalidParams("Position out of bounds"));
1185 return;
1186 }
1187
samuonged25cba2015-04-30 23:10:541188 gesture_params.relative_pointer_speed_in_pixels_s =
dgozman111fdd032016-12-18 00:49:261189 relative_speed.fromMaybe(kDefaultRelativeSpeed);
samuonged25cba2015-04-30 23:10:541190
1191 if (!StringToGestureSourceType(
dgozman111fdd032016-12-18 00:49:261192 std::move(gesture_source_type),
samuonged25cba2015-04-30 23:10:541193 gesture_params.gesture_source_type)) {
dgozman111fdd032016-12-18 00:49:261194 callback->sendFailure(
1195 Response::InvalidParams("Unknown gestureSourceType"));
1196 return;
samuonged25cba2015-04-30 23:10:541197 }
1198
Kevin McNee4d843a5c2019-02-19 16:50:341199 RenderWidgetHostViewBase* root_view = GetRootView();
1200 if (!root_view) {
Dmitry Gozman690a89e2018-03-06 01:25:311201 callback->sendFailure(Response::InternalError());
1202 return;
1203 }
1204
Kevin McNee4d843a5c2019-02-19 16:50:341205 root_view->host()->QueueSyntheticGesture(
samuonged25cba2015-04-30 23:10:541206 SyntheticGesture::Create(gesture_params),
tzikccf160c2018-02-20 12:43:131207 base::BindOnce(&SendSynthesizePinchGestureResponse, std::move(callback)));
samuong1b5ccef2015-02-20 19:30:241208}
1209
dgozman111fdd032016-12-18 00:49:261210void InputHandler::SynthesizeScrollGesture(
Pavel Feldman04e776d72017-07-12 23:52:401211 double x,
1212 double y,
1213 Maybe<double> x_distance,
1214 Maybe<double> y_distance,
1215 Maybe<double> x_overscroll,
1216 Maybe<double> y_overscroll,
dgozman111fdd032016-12-18 00:49:261217 Maybe<bool> prevent_fling,
1218 Maybe<int> speed,
1219 Maybe<std::string> gesture_source_type,
1220 Maybe<int> repeat_count,
1221 Maybe<int> repeat_delay_ms,
1222 Maybe<std::string> interaction_marker_name,
1223 std::unique_ptr<SynthesizeScrollGestureCallback> callback) {
1224 if (!host_ || !host_->GetRenderWidgetHost()) {
1225 callback->sendFailure(Response::InternalError());
1226 return;
1227 }
samuonged25cba2015-04-30 23:10:541228
1229 SyntheticSmoothScrollGestureParams gesture_params;
1230 const bool kDefaultPreventFling = true;
1231 const int kDefaultSpeed = 800;
1232
danakj2ef31b82015-10-21 18:18:021233 gesture_params.anchor = CssPixelsToPointF(x, y, page_scale_factor_);
dtapuska694e49d72017-05-10 17:15:121234 if (!PointIsWithinContents(gesture_params.anchor)) {
1235 callback->sendFailure(Response::InvalidParams("Position out of bounds"));
1236 return;
1237 }
1238
samuonged25cba2015-04-30 23:10:541239 gesture_params.prevent_fling =
dgozman111fdd032016-12-18 00:49:261240 prevent_fling.fromMaybe(kDefaultPreventFling);
1241 gesture_params.speed_in_pixels_s = speed.fromMaybe(kDefaultSpeed);
samuonged25cba2015-04-30 23:10:541242
dtapuska694e49d72017-05-10 17:15:121243 if (x_distance.isJust() || y_distance.isJust()) {
samuonged25cba2015-04-30 23:10:541244 gesture_params.distances.push_back(
dgozman111fdd032016-12-18 00:49:261245 CssPixelsToVector2dF(x_distance.fromMaybe(0),
1246 y_distance.fromMaybe(0), page_scale_factor_));
samuonged25cba2015-04-30 23:10:541247 }
1248
dgozman111fdd032016-12-18 00:49:261249 if (x_overscroll.isJust() || y_overscroll.isJust()) {
danakj2ef31b82015-10-21 18:18:021250 gesture_params.distances.push_back(CssPixelsToVector2dF(
dgozman111fdd032016-12-18 00:49:261251 -x_overscroll.fromMaybe(0), -y_overscroll.fromMaybe(0),
danakj2ef31b82015-10-21 18:18:021252 page_scale_factor_));
samuonged25cba2015-04-30 23:10:541253 }
1254
1255 if (!StringToGestureSourceType(
dgozman111fdd032016-12-18 00:49:261256 std::move(gesture_source_type),
samuonged25cba2015-04-30 23:10:541257 gesture_params.gesture_source_type)) {
dgozman111fdd032016-12-18 00:49:261258 callback->sendFailure(
1259 Response::InvalidParams("Unknown gestureSourceType"));
1260 return;
samuonged25cba2015-04-30 23:10:541261 }
1262
alexclarke20301011d2015-08-18 10:43:141263 SynthesizeRepeatingScroll(
Kevin McNee4d843a5c2019-02-19 16:50:341264 gesture_params, repeat_count.fromMaybe(0),
dgozman111fdd032016-12-18 00:49:261265 base::TimeDelta::FromMilliseconds(repeat_delay_ms.fromMaybe(250)),
1266 interaction_marker_name.fromMaybe(""), ++last_id_, std::move(callback));
samuong1b5ccef2015-02-20 19:30:241267}
1268
alexclarke20301011d2015-08-18 10:43:141269void InputHandler::SynthesizeRepeatingScroll(
1270 SyntheticSmoothScrollGestureParams gesture_params,
1271 int repeat_count,
1272 base::TimeDelta repeat_delay,
1273 std::string interaction_marker_name,
dgozman111fdd032016-12-18 00:49:261274 int id,
1275 std::unique_ptr<SynthesizeScrollGestureCallback> callback) {
Kevin McNee4d843a5c2019-02-19 16:50:341276 RenderWidgetHostViewBase* root_view = GetRootView();
1277 if (!root_view) {
Dmitry Gozman690a89e2018-03-06 01:25:311278 callback->sendFailure(Response::Error("Frame was detached"));
1279 return;
1280 }
1281
alexclarke20301011d2015-08-18 10:43:141282 if (!interaction_marker_name.empty()) {
alexclarke20301011d2015-08-18 10:43:141283 // TODO(alexclarke): Can we move this elsewhere? It doesn't really fit here.
kozyatinskiy1084bdca2015-11-21 05:40:481284 TRACE_EVENT_COPY_ASYNC_BEGIN0("benchmark", interaction_marker_name.c_str(),
dgozman111fdd032016-12-18 00:49:261285 id);
alexclarke20301011d2015-08-18 10:43:141286 }
1287
Kevin McNee4d843a5c2019-02-19 16:50:341288 root_view->host()->QueueSyntheticGesture(
alexclarke20301011d2015-08-18 10:43:141289 SyntheticGesture::Create(gesture_params),
tzike2aca992017-09-05 08:50:541290 base::BindOnce(&InputHandler::OnScrollFinished,
Kevin McNee4d843a5c2019-02-19 16:50:341291 weak_factory_.GetWeakPtr(), gesture_params, repeat_count,
1292 repeat_delay, interaction_marker_name, id,
tzikccf160c2018-02-20 12:43:131293 std::move(callback)));
alexclarke20301011d2015-08-18 10:43:141294}
1295
1296void InputHandler::OnScrollFinished(
1297 SyntheticSmoothScrollGestureParams gesture_params,
1298 int repeat_count,
1299 base::TimeDelta repeat_delay,
1300 std::string interaction_marker_name,
dgozman111fdd032016-12-18 00:49:261301 int id,
1302 std::unique_ptr<SynthesizeScrollGestureCallback> callback,
alexclarke20301011d2015-08-18 10:43:141303 SyntheticGesture::Result result) {
1304 if (!interaction_marker_name.empty()) {
kozyatinskiy1084bdca2015-11-21 05:40:481305 TRACE_EVENT_COPY_ASYNC_END0("benchmark", interaction_marker_name.c_str(),
dgozman111fdd032016-12-18 00:49:261306 id);
alexclarke20301011d2015-08-18 10:43:141307 }
1308
1309 if (repeat_count > 0) {
fdoraycaed3832016-06-13 18:15:531310 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
alexclarke20301011d2015-08-18 10:43:141311 FROM_HERE,
tzikf50714c2017-08-18 06:14:571312 base::BindOnce(&InputHandler::SynthesizeRepeatingScroll,
Kevin McNee4d843a5c2019-02-19 16:50:341313 weak_factory_.GetWeakPtr(), gesture_params,
tzikf50714c2017-08-18 06:14:571314 repeat_count - 1, repeat_delay, interaction_marker_name,
tzikccf160c2018-02-20 12:43:131315 id, std::move(callback)),
alexclarke20301011d2015-08-18 10:43:141316 repeat_delay);
1317 } else {
dgozman111fdd032016-12-18 00:49:261318 SendSynthesizeScrollGestureResponse(std::move(callback), result);
alexclarke20301011d2015-08-18 10:43:141319 }
1320}
1321
dgozman111fdd032016-12-18 00:49:261322void InputHandler::SynthesizeTapGesture(
Pavel Feldman04e776d72017-07-12 23:52:401323 double x,
1324 double y,
dgozman111fdd032016-12-18 00:49:261325 Maybe<int> duration,
1326 Maybe<int> tap_count,
1327 Maybe<std::string> gesture_source_type,
1328 std::unique_ptr<SynthesizeTapGestureCallback> callback) {
1329 if (!host_ || !host_->GetRenderWidgetHost()) {
1330 callback->sendFailure(Response::InternalError());
1331 return;
1332 }
samuonged25cba2015-04-30 23:10:541333
1334 SyntheticTapGestureParams gesture_params;
1335 const int kDefaultDuration = 50;
1336 const int kDefaultTapCount = 1;
1337
danakj2ef31b82015-10-21 18:18:021338 gesture_params.position = CssPixelsToPointF(x, y, page_scale_factor_);
dtapuska694e49d72017-05-10 17:15:121339 if (!PointIsWithinContents(gesture_params.position)) {
1340 callback->sendFailure(Response::InvalidParams("Position out of bounds"));
1341 return;
1342 }
1343
dgozman111fdd032016-12-18 00:49:261344 gesture_params.duration_ms = duration.fromMaybe(kDefaultDuration);
samuonged25cba2015-04-30 23:10:541345
1346 if (!StringToGestureSourceType(
dgozman111fdd032016-12-18 00:49:261347 std::move(gesture_source_type),
samuonged25cba2015-04-30 23:10:541348 gesture_params.gesture_source_type)) {
dgozman111fdd032016-12-18 00:49:261349 callback->sendFailure(
1350 Response::InvalidParams("Unknown gestureSourceType"));
1351 return;
samuonged25cba2015-04-30 23:10:541352 }
1353
dgozman111fdd032016-12-18 00:49:261354 int count = tap_count.fromMaybe(kDefaultTapCount);
1355 if (!count) {
1356 callback->sendSuccess();
1357 return;
1358 }
samuonged25cba2015-04-30 23:10:541359
Kevin McNee4d843a5c2019-02-19 16:50:341360 RenderWidgetHostViewBase* root_view = GetRootView();
1361 if (!root_view) {
Dmitry Gozman690a89e2018-03-06 01:25:311362 callback->sendFailure(Response::InternalError());
1363 return;
1364 }
1365
dgozman111fdd032016-12-18 00:49:261366 TapGestureResponse* response =
1367 new TapGestureResponse(std::move(callback), count);
1368 for (int i = 0; i < count; i++) {
Kevin McNee4d843a5c2019-02-19 16:50:341369 root_view->host()->QueueSyntheticGesture(
samuonged25cba2015-04-30 23:10:541370 SyntheticGesture::Create(gesture_params),
tzike2aca992017-09-05 08:50:541371 base::BindOnce(&TapGestureResponse::OnGestureResult,
1372 base::Unretained(response)));
samuonged25cba2015-04-30 23:10:541373 }
1374}
1375
Dmitry Gozman95bab292017-08-16 22:48:581376void InputHandler::ClearInputState() {
Dmitry Gozman901b6302018-03-02 02:30:391377 while (!injectors_.empty())
1378 (*injectors_.begin())->Cleanup();
Dmitry Gozman95bab292017-08-16 22:48:581379 // TODO(dgozman): cleanup touch callbacks as well?
Lan Wei9c6f1242019-02-11 23:01:301380 pointer_ids_.clear();
samuong8db76012017-01-20 06:36:081381}
1382
dtapuska694e49d72017-05-10 17:15:121383bool InputHandler::PointIsWithinContents(gfx::PointF point) const {
1384 gfx::Rect bounds = host_->GetView()->GetViewBounds();
1385 bounds -= bounds.OffsetFromOrigin(); // Translate the bounds to (0,0).
1386 return bounds.Contains(point.x(), point.y());
1387}
1388
Dmitry Gozman901b6302018-03-02 02:30:391389InputHandler::InputInjector* InputHandler::EnsureInjector(
1390 RenderWidgetHostImpl* widget_host) {
1391 for (auto& it : injectors_) {
1392 if (it->HasWidgetHost(widget_host))
1393 return it.get();
1394 }
1395 InputInjector* injector = new InputInjector(this, widget_host);
1396 injectors_.emplace(injector);
1397 return injector;
1398}
1399
1400RenderWidgetHostImpl* InputHandler::FindTargetWidgetHost(
1401 const gfx::PointF& point,
1402 gfx::PointF* transformed) {
1403 *transformed = point;
1404
1405 RenderWidgetHostImpl* widget_host =
1406 host_ ? host_->GetRenderWidgetHost() : nullptr;
1407 if (!widget_host)
1408 return nullptr;
1409
1410 if (!host_->GetParent() && widget_host->delegate() &&
1411 widget_host->delegate()->GetInputEventRouter() &&
1412 widget_host->GetView()) {
1413 widget_host = widget_host->delegate()
1414 ->GetInputEventRouter()
1415 ->GetRenderWidgetHostAtPoint(widget_host->GetView(),
1416 point, transformed);
1417 }
1418
1419 return widget_host;
1420}
1421
Kevin McNee4d843a5c2019-02-19 16:50:341422RenderWidgetHostViewBase* InputHandler::GetRootView() {
1423 if (!host_)
1424 return nullptr;
1425
1426 RenderWidgetHostViewBase* view =
1427 static_cast<RenderWidgetHostViewBase*>(host_->GetView());
1428 if (!view)
1429 return nullptr;
1430
1431 return view->GetRootView();
1432}
1433
dgozman111fdd032016-12-18 00:49:261434} // namespace protocol
vkuzkokovc985d952014-10-01 12:24:131435} // namespace content