| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/devtools/protocol/input_handler.h" | 5 #include "content/browser/devtools/protocol/input_handler.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 11 #include "base/threading/thread_task_runner_handle.h" | 11 #include "base/threading/thread_task_runner_handle.h" |
| 12 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
| 13 #include "cc/output/compositor_frame_metadata.h" | 13 #include "cc/output/compositor_frame_metadata.h" |
| 14 #include "content/browser/frame_host/render_frame_host_impl.h" |
| 14 #include "content/browser/renderer_host/render_widget_host_impl.h" | 15 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 15 #include "content/common/input/synthetic_pinch_gesture_params.h" | 16 #include "content/common/input/synthetic_pinch_gesture_params.h" |
| 16 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" | 17 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" |
| 17 #include "content/common/input/synthetic_tap_gesture_params.h" | 18 #include "content/common/input/synthetic_tap_gesture_params.h" |
| 18 #include "third_party/WebKit/public/platform/WebInputEvent.h" | 19 #include "third_party/WebKit/public/platform/WebInputEvent.h" |
| 19 #include "ui/events/keycodes/dom/keycode_converter.h" | 20 #include "ui/events/keycodes/dom/keycode_converter.h" |
| 20 #include "ui/gfx/geometry/point.h" | 21 #include "ui/gfx/geometry/point.h" |
| 21 | 22 |
| 22 namespace content { | 23 namespace content { |
| 23 namespace devtools { | 24 namespace protocol { |
| 24 namespace input { | |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 gfx::PointF CssPixelsToPointF(int x, int y, float page_scale_factor) { | 28 gfx::PointF CssPixelsToPointF(int x, int y, float page_scale_factor) { |
| 29 return gfx::PointF(x * page_scale_factor, y * page_scale_factor); | 29 return gfx::PointF(x * page_scale_factor, y * page_scale_factor); |
| 30 } | 30 } |
| 31 | 31 |
| 32 gfx::Vector2dF CssPixelsToVector2dF(int x, int y, float page_scale_factor) { | 32 gfx::Vector2dF CssPixelsToVector2dF(int x, int y, float page_scale_factor) { |
| 33 return gfx::Vector2dF(x * page_scale_factor, y * page_scale_factor); | 33 return gfx::Vector2dF(x * page_scale_factor, y * page_scale_factor); |
| 34 } | 34 } |
| 35 | 35 |
| 36 bool StringToGestureSourceType(const std::string& in, | 36 bool StringToGestureSourceType(Maybe<std::string> in, |
| 37 SyntheticGestureParams::GestureSourceType& out) { | 37 SyntheticGestureParams::GestureSourceType& out) { |
| 38 if (in == kGestureSourceTypeDefault) { | 38 if (!in.isJust()) { |
| 39 out = SyntheticGestureParams::GestureSourceType::DEFAULT_INPUT; | 39 out = SyntheticGestureParams::GestureSourceType::DEFAULT_INPUT; |
| 40 return true; | 40 return true; |
| 41 } else if (in == kGestureSourceTypeTouch) { | 41 } |
| 42 if (in.fromJust() == Input::GestureSourceTypeEnum::Default) { |
| 43 out = SyntheticGestureParams::GestureSourceType::DEFAULT_INPUT; |
| 44 return true; |
| 45 } |
| 46 if (in.fromJust() == Input::GestureSourceTypeEnum::Touch) { |
| 42 out = SyntheticGestureParams::GestureSourceType::TOUCH_INPUT; | 47 out = SyntheticGestureParams::GestureSourceType::TOUCH_INPUT; |
| 43 return true; | 48 return true; |
| 44 } else if (in == kGestureSourceTypeMouse) { | 49 } |
| 50 if (in.fromJust() == Input::GestureSourceTypeEnum::Mouse) { |
| 45 out = SyntheticGestureParams::GestureSourceType::MOUSE_INPUT; | 51 out = SyntheticGestureParams::GestureSourceType::MOUSE_INPUT; |
| 46 return true; | 52 return true; |
| 47 } else { | |
| 48 return false; | |
| 49 } | 53 } |
| 54 return false; |
| 50 } | 55 } |
| 51 | 56 |
| 52 } | 57 void SetEventModifiers(blink::WebInputEvent* event, int modifiers) { |
| 53 | 58 if (modifiers & 1) |
| 54 typedef DevToolsProtocolClient::Response Response; | |
| 55 | |
| 56 namespace { | |
| 57 | |
| 58 void SetEventModifiers(blink::WebInputEvent* event, const int* modifiers) { | |
| 59 if (!modifiers) | |
| 60 return; | |
| 61 if (*modifiers & 1) | |
| 62 event->modifiers |= blink::WebInputEvent::AltKey; | 59 event->modifiers |= blink::WebInputEvent::AltKey; |
| 63 if (*modifiers & 2) | 60 if (modifiers & 2) |
| 64 event->modifiers |= blink::WebInputEvent::ControlKey; | 61 event->modifiers |= blink::WebInputEvent::ControlKey; |
| 65 if (*modifiers & 4) | 62 if (modifiers & 4) |
| 66 event->modifiers |= blink::WebInputEvent::MetaKey; | 63 event->modifiers |= blink::WebInputEvent::MetaKey; |
| 67 if (*modifiers & 8) | 64 if (modifiers & 8) |
| 68 event->modifiers |= blink::WebInputEvent::ShiftKey; | 65 event->modifiers |= blink::WebInputEvent::ShiftKey; |
| 69 } | 66 } |
| 70 | 67 |
| 71 void SetEventTimestamp(blink::WebInputEvent* event, const double* timestamp) { | 68 void SetEventTimestamp(blink::WebInputEvent* event, Maybe<double> timestamp) { |
| 72 // Convert timestamp, in seconds since unix epoch, to an event timestamp | 69 // Convert timestamp, in seconds since unix epoch, to an event timestamp |
| 73 // which is time ticks since platform start time. | 70 // which is time ticks since platform start time. |
| 74 base::TimeTicks ticks = timestamp | 71 base::TimeTicks ticks = timestamp.isJust() |
| 75 ? base::TimeDelta::FromSecondsD(*timestamp) + | 72 ? base::TimeDelta::FromSecondsD(timestamp.fromJust()) + |
| 76 base::TimeTicks::UnixEpoch() | 73 base::TimeTicks::UnixEpoch() |
| 77 : base::TimeTicks::Now(); | 74 : base::TimeTicks::Now(); |
| 78 event->timeStampSeconds = (ticks - base::TimeTicks()).InSecondsF(); | 75 event->timeStampSeconds = (ticks - base::TimeTicks()).InSecondsF(); |
| 79 } | 76 } |
| 80 | 77 |
| 81 bool SetKeyboardEventText(blink::WebUChar* to, const std::string* from) { | 78 bool SetKeyboardEventText(blink::WebUChar* to, Maybe<std::string> from) { |
| 82 if (!from) | 79 if (!from.isJust()) |
| 83 return true; | 80 return true; |
| 84 | 81 |
| 85 base::string16 text16 = base::UTF8ToUTF16(*from); | 82 base::string16 text16 = base::UTF8ToUTF16(from.fromJust()); |
| 86 if (text16.size() > blink::WebKeyboardEvent::textLengthCap) | 83 if (text16.size() > blink::WebKeyboardEvent::textLengthCap) |
| 87 return false; | 84 return false; |
| 88 | 85 |
| 89 for (size_t i = 0; i < text16.size(); ++i) | 86 for (size_t i = 0; i < text16.size(); ++i) |
| 90 to[i] = text16[i]; | 87 to[i] = text16[i]; |
| 91 return true; | 88 return true; |
| 92 } | 89 } |
| 93 | 90 |
| 94 bool SetMouseEventButton(blink::WebMouseEvent* event, | 91 bool SetMouseEventButton(blink::WebMouseEvent* event, |
| 95 const std::string* button) { | 92 const std::string& button) { |
| 96 if (!button) | 93 if (button.empty()) |
| 97 return true; | 94 return true; |
| 98 | 95 |
| 99 if (*button == dispatch_mouse_event::kButtonNone) { | 96 if (button == Input::DispatchMouseEvent::ButtonEnum::None) { |
| 100 event->button = blink::WebMouseEvent::Button::NoButton; | 97 event->button = blink::WebMouseEvent::Button::NoButton; |
| 101 } else if (*button == dispatch_mouse_event::kButtonLeft) { | 98 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Left) { |
| 102 event->button = blink::WebMouseEvent::Button::Left; | 99 event->button = blink::WebMouseEvent::Button::Left; |
| 103 event->modifiers |= blink::WebInputEvent::LeftButtonDown; | 100 event->modifiers |= blink::WebInputEvent::LeftButtonDown; |
| 104 } else if (*button == dispatch_mouse_event::kButtonMiddle) { | 101 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Middle) { |
| 105 event->button = blink::WebMouseEvent::Button::Middle; | 102 event->button = blink::WebMouseEvent::Button::Middle; |
| 106 event->modifiers |= blink::WebInputEvent::MiddleButtonDown; | 103 event->modifiers |= blink::WebInputEvent::MiddleButtonDown; |
| 107 } else if (*button == dispatch_mouse_event::kButtonRight) { | 104 } else if (button == Input::DispatchMouseEvent::ButtonEnum::Right) { |
| 108 event->button = blink::WebMouseEvent::Button::Right; | 105 event->button = blink::WebMouseEvent::Button::Right; |
| 109 event->modifiers |= blink::WebInputEvent::RightButtonDown; | 106 event->modifiers |= blink::WebInputEvent::RightButtonDown; |
| 110 } else { | 107 } else { |
| 111 return false; | 108 return false; |
| 112 } | 109 } |
| 113 return true; | 110 return true; |
| 114 } | 111 } |
| 115 | 112 |
| 116 bool SetMouseEventType(blink::WebMouseEvent* event, const std::string& type) { | 113 bool SetMouseEventType(blink::WebMouseEvent* event, const std::string& type) { |
| 117 if (type == dispatch_mouse_event::kTypeMousePressed) { | 114 if (type == Input::DispatchMouseEvent::TypeEnum::MousePressed) { |
| 118 event->type = blink::WebInputEvent::MouseDown; | 115 event->type = blink::WebInputEvent::MouseDown; |
| 119 } else if (type == dispatch_mouse_event::kTypeMouseReleased) { | 116 } else if (type == Input::DispatchMouseEvent::TypeEnum::MouseReleased) { |
| 120 event->type = blink::WebInputEvent::MouseUp; | 117 event->type = blink::WebInputEvent::MouseUp; |
| 121 } else if (type == dispatch_mouse_event::kTypeMouseMoved) { | 118 } else if (type == Input::DispatchMouseEvent::TypeEnum::MouseMoved) { |
| 122 event->type = blink::WebInputEvent::MouseMove; | 119 event->type = blink::WebInputEvent::MouseMove; |
| 123 } else { | 120 } else { |
| 124 return false; | 121 return false; |
| 125 } | 122 } |
| 126 return true; | 123 return true; |
| 127 } | 124 } |
| 128 | 125 |
| 126 void SendSynthesizePinchGestureResponse( |
| 127 std::unique_ptr<Input::Backend::SynthesizePinchGestureCallback> callback, |
| 128 SyntheticGesture::Result result) { |
| 129 if (result == SyntheticGesture::Result::GESTURE_FINISHED) { |
| 130 callback->sendSuccess(); |
| 131 } else { |
| 132 callback->sendFailure(Response::Error( |
| 133 base::StringPrintf("Synthetic pinch failed, result was %d", result))); |
| 134 } |
| 135 } |
| 136 |
| 137 class TapGestureResponse { |
| 138 public: |
| 139 TapGestureResponse( |
| 140 std::unique_ptr<Input::Backend::SynthesizeTapGestureCallback> callback, |
| 141 int count) |
| 142 : callback_(std::move(callback)), |
| 143 count_(count) { |
| 144 } |
| 145 |
| 146 void OnGestureResult(SyntheticGesture::Result result) { |
| 147 --count_; |
| 148 // Still waiting for more taps to finish. |
| 149 if (result == SyntheticGesture::Result::GESTURE_FINISHED && count_) |
| 150 return; |
| 151 if (callback_) { |
| 152 if (result == SyntheticGesture::Result::GESTURE_FINISHED) { |
| 153 callback_->sendSuccess(); |
| 154 } else { |
| 155 callback_->sendFailure(Response::Error( |
| 156 base::StringPrintf("Synthetic tap failed, result was %d", result))); |
| 157 } |
| 158 callback_.reset(); |
| 159 } |
| 160 if (!count_) |
| 161 delete this; |
| 162 } |
| 163 |
| 164 private: |
| 165 std::unique_ptr<Input::Backend::SynthesizeTapGestureCallback> callback_; |
| 166 int count_; |
| 167 }; |
| 168 |
| 169 void SendSynthesizeScrollGestureResponse( |
| 170 std::unique_ptr<Input::Backend::SynthesizeScrollGestureCallback> callback, |
| 171 SyntheticGesture::Result result) { |
| 172 if (result == SyntheticGesture::Result::GESTURE_FINISHED) { |
| 173 callback->sendSuccess(); |
| 174 } else { |
| 175 callback->sendFailure(Response::Error( |
| 176 base::StringPrintf("Synthetic scroll failed, result was %d", result))); |
| 177 } |
| 178 } |
| 179 |
| 129 } // namespace | 180 } // namespace |
| 130 | 181 |
| 131 InputHandler::InputHandler() | 182 InputHandler::InputHandler() |
| 132 : host_(NULL), | 183 : host_(NULL), |
| 133 page_scale_factor_(1.0), | 184 page_scale_factor_(1.0), |
| 185 last_id_(0), |
| 134 weak_factory_(this) { | 186 weak_factory_(this) { |
| 135 } | 187 } |
| 136 | 188 |
| 137 InputHandler::~InputHandler() { | 189 InputHandler::~InputHandler() { |
| 138 } | 190 } |
| 139 | 191 |
| 140 void InputHandler::SetRenderWidgetHost(RenderWidgetHostImpl* host) { | 192 void InputHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { |
| 141 host_ = host; | 193 host_ = host; |
| 142 } | 194 } |
| 143 | 195 |
| 144 void InputHandler::SetClient(std::unique_ptr<Client> client) { | 196 void InputHandler::Wire(UberDispatcher* dispatcher) { |
| 145 client_.swap(client); | 197 Input::Dispatcher::wire(dispatcher, this); |
| 146 } | 198 } |
| 147 | 199 |
| 148 void InputHandler::OnSwapCompositorFrame( | 200 void InputHandler::OnSwapCompositorFrame( |
| 149 const cc::CompositorFrameMetadata& frame_metadata) { | 201 const cc::CompositorFrameMetadata& frame_metadata) { |
| 150 page_scale_factor_ = frame_metadata.page_scale_factor; | 202 page_scale_factor_ = frame_metadata.page_scale_factor; |
| 151 scrollable_viewport_size_ = frame_metadata.scrollable_viewport_size; | 203 scrollable_viewport_size_ = frame_metadata.scrollable_viewport_size; |
| 152 } | 204 } |
| 153 | 205 |
| 206 Response InputHandler::Disable() { |
| 207 return Response::OK(); |
| 208 } |
| 209 |
| 154 Response InputHandler::DispatchKeyEvent( | 210 Response InputHandler::DispatchKeyEvent( |
| 155 const std::string& type, | 211 const std::string& type, |
| 156 const int* modifiers, | 212 Maybe<int> modifiers, |
| 157 const double* timestamp, | 213 Maybe<double> timestamp, |
| 158 const std::string* text, | 214 Maybe<std::string> text, |
| 159 const std::string* unmodified_text, | 215 Maybe<std::string> unmodified_text, |
| 160 const std::string* key_identifier, | 216 Maybe<std::string> key_identifier, |
| 161 const std::string* code, | 217 Maybe<std::string> code, |
| 162 const std::string* key, | 218 Maybe<std::string> key, |
| 163 const int* windows_virtual_key_code, | 219 Maybe<int> windows_virtual_key_code, |
| 164 const int* native_virtual_key_code, | 220 Maybe<int> native_virtual_key_code, |
| 165 const bool* auto_repeat, | 221 Maybe<bool> auto_repeat, |
| 166 const bool* is_keypad, | 222 Maybe<bool> is_keypad, |
| 167 const bool* is_system_key) { | 223 Maybe<bool> is_system_key) { |
| 168 NativeWebKeyboardEvent event; | 224 NativeWebKeyboardEvent event; |
| 169 event.skip_in_browser = true; | 225 event.skip_in_browser = true; |
| 170 | 226 |
| 171 if (type == dispatch_key_event::kTypeKeyDown) { | 227 if (type == Input::DispatchKeyEvent::TypeEnum::KeyDown) { |
| 172 event.type = blink::WebInputEvent::KeyDown; | 228 event.type = blink::WebInputEvent::KeyDown; |
| 173 } else if (type == dispatch_key_event::kTypeKeyUp) { | 229 } else if (type == Input::DispatchKeyEvent::TypeEnum::KeyUp) { |
| 174 event.type = blink::WebInputEvent::KeyUp; | 230 event.type = blink::WebInputEvent::KeyUp; |
| 175 } else if (type == dispatch_key_event::kTypeChar) { | 231 } else if (type == Input::DispatchKeyEvent::TypeEnum::Char) { |
| 176 event.type = blink::WebInputEvent::Char; | 232 event.type = blink::WebInputEvent::Char; |
| 177 } else if (type == dispatch_key_event::kTypeRawKeyDown) { | 233 } else if (type == Input::DispatchKeyEvent::TypeEnum::RawKeyDown) { |
| 178 event.type = blink::WebInputEvent::RawKeyDown; | 234 event.type = blink::WebInputEvent::RawKeyDown; |
| 179 } else { | 235 } else { |
| 180 return Response::InvalidParams( | 236 return Response::InvalidParams( |
| 181 base::StringPrintf("Unexpected event type '%s'", type.c_str())); | 237 base::StringPrintf("Unexpected event type '%s'", type.c_str())); |
| 182 } | 238 } |
| 183 | 239 |
| 184 SetEventModifiers(&event, modifiers); | 240 SetEventModifiers(&event, modifiers.fromMaybe(0)); |
| 185 SetEventTimestamp(&event, timestamp); | 241 SetEventTimestamp(&event, std::move(timestamp)); |
| 186 if (!SetKeyboardEventText(event.text, text)) | 242 if (!SetKeyboardEventText(event.text, std::move(text))) |
| 187 return Response::InvalidParams("Invalid 'text' parameter"); | 243 return Response::InvalidParams("Invalid 'text' parameter"); |
| 188 if (!SetKeyboardEventText(event.unmodifiedText, unmodified_text)) | 244 if (!SetKeyboardEventText(event.unmodifiedText, std::move(unmodified_text))) |
| 189 return Response::InvalidParams("Invalid 'unmodifiedText' parameter"); | 245 return Response::InvalidParams("Invalid 'unmodifiedText' parameter"); |
| 190 | 246 |
| 191 if (windows_virtual_key_code) | 247 if (windows_virtual_key_code.isJust()) |
| 192 event.windowsKeyCode = *windows_virtual_key_code; | 248 event.windowsKeyCode = windows_virtual_key_code.fromJust(); |
| 193 if (native_virtual_key_code) | 249 if (native_virtual_key_code.isJust()) |
| 194 event.nativeKeyCode = *native_virtual_key_code; | 250 event.nativeKeyCode = native_virtual_key_code.fromJust(); |
| 195 if (auto_repeat && *auto_repeat) | 251 if (auto_repeat.fromMaybe(false)) |
| 196 event.modifiers |= blink::WebInputEvent::IsAutoRepeat; | 252 event.modifiers |= blink::WebInputEvent::IsAutoRepeat; |
| 197 if (is_keypad && *is_keypad) | 253 if (is_keypad.fromMaybe(false)) |
| 198 event.modifiers |= blink::WebInputEvent::IsKeyPad; | 254 event.modifiers |= blink::WebInputEvent::IsKeyPad; |
| 199 if (is_system_key) | 255 if (is_system_key.isJust()) |
| 200 event.isSystemKey = *is_system_key; | 256 event.isSystemKey = is_system_key.fromJust(); |
| 201 | 257 |
| 202 if (code) { | 258 if (code.isJust()) { |
| 203 event.domCode = static_cast<int>( | 259 event.domCode = static_cast<int>( |
| 204 ui::KeycodeConverter::CodeStringToDomCode(*code)); | 260 ui::KeycodeConverter::CodeStringToDomCode(code.fromJust())); |
| 205 } | 261 } |
| 206 | 262 |
| 207 if (key) { | 263 if (key.isJust()) { |
| 208 event.domKey = static_cast<int>( | 264 event.domKey = static_cast<int>( |
| 209 ui::KeycodeConverter::KeyStringToDomKey(*key)); | 265 ui::KeycodeConverter::KeyStringToDomKey(key.fromJust())); |
| 210 } | 266 } |
| 211 | 267 |
| 212 if (!host_) | 268 if (!host_ || !host_->GetRenderWidgetHost()) |
| 213 return Response::ServerError("Could not connect to view"); | 269 return Response::InternalError(); |
| 214 | 270 |
| 215 host_->Focus(); | 271 host_->GetRenderWidgetHost()->Focus(); |
| 216 host_->ForwardKeyboardEvent(event); | 272 host_->GetRenderWidgetHost()->ForwardKeyboardEvent(event); |
| 217 return Response::OK(); | 273 return Response::OK(); |
| 218 } | 274 } |
| 219 | 275 |
| 220 Response InputHandler::DispatchMouseEvent( | 276 Response InputHandler::DispatchMouseEvent( |
| 221 const std::string& type, | 277 const std::string& type, |
| 222 int x, | 278 int x, |
| 223 int y, | 279 int y, |
| 224 const int* modifiers, | 280 Maybe<int> modifiers, |
| 225 const double* timestamp, | 281 Maybe<double> timestamp, |
| 226 const std::string* button, | 282 Maybe<std::string> button, |
| 227 const int* click_count) { | 283 Maybe<int> click_count) { |
| 228 blink::WebMouseEvent event; | 284 blink::WebMouseEvent event; |
| 229 | 285 |
| 230 if (!SetMouseEventType(&event, type)) { | 286 if (!SetMouseEventType(&event, type)) { |
| 231 return Response::InvalidParams( | 287 return Response::InvalidParams( |
| 232 base::StringPrintf("Unexpected event type '%s'", type.c_str())); | 288 base::StringPrintf("Unexpected event type '%s'", type.c_str())); |
| 233 } | 289 } |
| 234 SetEventModifiers(&event, modifiers); | 290 SetEventModifiers(&event, modifiers.fromMaybe(0)); |
| 235 SetEventTimestamp(&event, timestamp); | 291 SetEventTimestamp(&event, std::move(timestamp)); |
| 236 if (!SetMouseEventButton(&event, button)) | 292 if (!SetMouseEventButton(&event, button.fromMaybe(""))) |
| 237 return Response::InvalidParams("Invalid mouse button"); | 293 return Response::InvalidParams("Invalid mouse button"); |
| 238 | 294 |
| 239 event.x = x * page_scale_factor_; | 295 event.x = x * page_scale_factor_; |
| 240 event.y = y * page_scale_factor_; | 296 event.y = y * page_scale_factor_; |
| 241 event.windowX = x * page_scale_factor_; | 297 event.windowX = x * page_scale_factor_; |
| 242 event.windowY = y * page_scale_factor_; | 298 event.windowY = y * page_scale_factor_; |
| 243 event.globalX = x * page_scale_factor_; | 299 event.globalX = x * page_scale_factor_; |
| 244 event.globalY = y * page_scale_factor_; | 300 event.globalY = y * page_scale_factor_; |
| 245 event.clickCount = click_count ? *click_count : 0; | 301 event.clickCount = click_count.fromMaybe(0); |
| 246 event.pointerType = blink::WebPointerProperties::PointerType::Mouse; | 302 event.pointerType = blink::WebPointerProperties::PointerType::Mouse; |
| 247 | 303 |
| 248 if (!host_) | 304 if (!host_ || !host_->GetRenderWidgetHost()) |
| 249 return Response::ServerError("Could not connect to view"); | 305 return Response::InternalError(); |
| 250 | 306 |
| 251 host_->Focus(); | 307 host_->GetRenderWidgetHost()->Focus(); |
| 252 host_->ForwardMouseEvent(event); | 308 host_->GetRenderWidgetHost()->ForwardMouseEvent(event); |
| 253 return Response::OK(); | 309 return Response::OK(); |
| 254 } | 310 } |
| 255 | 311 |
| 256 Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type, | 312 Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type, |
| 257 int x, | 313 int x, |
| 258 int y, | 314 int y, |
| 259 double timestamp, | 315 double timestamp, |
| 260 const std::string& button, | 316 const std::string& button, |
| 261 double* delta_x, | 317 Maybe<double> delta_x, |
| 262 double* delta_y, | 318 Maybe<double> delta_y, |
| 263 int* modifiers, | 319 Maybe<int> modifiers, |
| 264 int* click_count) { | 320 Maybe<int> click_count) { |
| 265 blink::WebMouseWheelEvent wheel_event; | 321 blink::WebMouseWheelEvent wheel_event; |
| 266 blink::WebMouseEvent mouse_event; | 322 blink::WebMouseEvent mouse_event; |
| 267 blink::WebMouseEvent* event = &mouse_event; | 323 blink::WebMouseEvent* event = &mouse_event; |
| 268 | 324 |
| 269 if (type == emulate_touch_from_mouse_event::kTypeMouseWheel) { | 325 if (type == Input::EmulateTouchFromMouseEvent::TypeEnum::MouseWheel) { |
| 270 if (!delta_x || !delta_y) { | 326 if (!delta_x.isJust() || !delta_y.isJust()) { |
| 271 return Response::InvalidParams( | 327 return Response::InvalidParams( |
| 272 "'deltaX' and 'deltaY' are expected for mouseWheel event"); | 328 "'deltaX' and 'deltaY' are expected for mouseWheel event"); |
| 273 } | 329 } |
| 274 wheel_event.deltaX = static_cast<float>(*delta_x); | 330 wheel_event.deltaX = static_cast<float>(delta_x.fromJust()); |
| 275 wheel_event.deltaY = static_cast<float>(*delta_y); | 331 wheel_event.deltaY = static_cast<float>(delta_y.fromJust()); |
| 276 event = &wheel_event; | 332 event = &wheel_event; |
| 277 event->type = blink::WebInputEvent::MouseWheel; | 333 event->type = blink::WebInputEvent::MouseWheel; |
| 278 } else if (!SetMouseEventType(event, type)) { | 334 } else if (!SetMouseEventType(event, type)) { |
| 279 return Response::InvalidParams( | 335 return Response::InvalidParams( |
| 280 base::StringPrintf("Unexpected event type '%s'", type.c_str())); | 336 base::StringPrintf("Unexpected event type '%s'", type.c_str())); |
| 281 } | 337 } |
| 282 | 338 |
| 283 SetEventModifiers(event, modifiers); | 339 SetEventModifiers(event, modifiers.fromMaybe(0)); |
| 284 SetEventTimestamp(event, ×tamp); | 340 SetEventTimestamp(event, Maybe<double>(timestamp)); |
| 285 if (!SetMouseEventButton(event, &button)) | 341 if (!SetMouseEventButton(event, button)) |
| 286 return Response::InvalidParams("Invalid mouse button"); | 342 return Response::InvalidParams("Invalid mouse button"); |
| 287 | 343 |
| 288 event->x = x; | 344 event->x = x; |
| 289 event->y = y; | 345 event->y = y; |
| 290 event->windowX = x; | 346 event->windowX = x; |
| 291 event->windowY = y; | 347 event->windowY = y; |
| 292 event->globalX = x; | 348 event->globalX = x; |
| 293 event->globalY = y; | 349 event->globalY = y; |
| 294 event->clickCount = click_count ? *click_count : 0; | 350 event->clickCount = click_count.fromMaybe(0); |
| 295 event->pointerType = blink::WebPointerProperties::PointerType::Touch; | 351 event->pointerType = blink::WebPointerProperties::PointerType::Touch; |
| 296 | 352 |
| 297 if (!host_) | 353 if (!host_ || !host_->GetRenderWidgetHost()) |
| 298 return Response::ServerError("Could not connect to view"); | 354 return Response::InternalError(); |
| 299 | 355 |
| 300 if (event->type == blink::WebInputEvent::MouseWheel) | 356 if (event->type == blink::WebInputEvent::MouseWheel) |
| 301 host_->ForwardWheelEvent(wheel_event); | 357 host_->GetRenderWidgetHost()->ForwardWheelEvent(wheel_event); |
| 302 else | 358 else |
| 303 host_->ForwardMouseEvent(mouse_event); | 359 host_->GetRenderWidgetHost()->ForwardMouseEvent(mouse_event); |
| 304 return Response::OK(); | 360 return Response::OK(); |
| 305 } | 361 } |
| 306 | 362 |
| 307 Response InputHandler::SynthesizePinchGesture( | 363 void InputHandler::SynthesizePinchGesture( |
| 308 DevToolsCommandId command_id, | |
| 309 int x, | 364 int x, |
| 310 int y, | 365 int y, |
| 311 double scale_factor, | 366 double scale_factor, |
| 312 const int* relative_speed, | 367 Maybe<int> relative_speed, |
| 313 const std::string* gesture_source_type) { | 368 Maybe<std::string> gesture_source_type, |
| 314 if (!host_) | 369 std::unique_ptr<SynthesizePinchGestureCallback> callback) { |
| 315 return Response::ServerError("Could not connect to view"); | 370 if (!host_ || !host_->GetRenderWidgetHost()) { |
| 371 callback->sendFailure(Response::InternalError()); |
| 372 return; |
| 373 } |
| 316 | 374 |
| 317 SyntheticPinchGestureParams gesture_params; | 375 SyntheticPinchGestureParams gesture_params; |
| 318 const int kDefaultRelativeSpeed = 800; | 376 const int kDefaultRelativeSpeed = 800; |
| 319 | 377 |
| 320 gesture_params.scale_factor = scale_factor; | 378 gesture_params.scale_factor = scale_factor; |
| 321 gesture_params.anchor = CssPixelsToPointF(x, y, page_scale_factor_); | 379 gesture_params.anchor = CssPixelsToPointF(x, y, page_scale_factor_); |
| 322 gesture_params.relative_pointer_speed_in_pixels_s = | 380 gesture_params.relative_pointer_speed_in_pixels_s = |
| 323 relative_speed ? *relative_speed : kDefaultRelativeSpeed; | 381 relative_speed.fromMaybe(kDefaultRelativeSpeed); |
| 324 | 382 |
| 325 if (!StringToGestureSourceType( | 383 if (!StringToGestureSourceType( |
| 326 gesture_source_type ? *gesture_source_type : kGestureSourceTypeDefault, | 384 std::move(gesture_source_type), |
| 327 gesture_params.gesture_source_type)) { | 385 gesture_params.gesture_source_type)) { |
| 328 return Response::InvalidParams("gestureSourceType"); | 386 callback->sendFailure( |
| 387 Response::InvalidParams("Unknown gestureSourceType")); |
| 388 return; |
| 329 } | 389 } |
| 330 | 390 |
| 331 host_->QueueSyntheticGesture( | 391 host_->GetRenderWidgetHost()->QueueSyntheticGesture( |
| 332 SyntheticGesture::Create(gesture_params), | 392 SyntheticGesture::Create(gesture_params), |
| 333 base::Bind(&InputHandler::SendSynthesizePinchGestureResponse, | 393 base::Bind(&SendSynthesizePinchGestureResponse, |
| 334 weak_factory_.GetWeakPtr(), command_id)); | 394 base::Passed(std::move(callback)))); |
| 335 | |
| 336 return Response::OK(); | |
| 337 } | 395 } |
| 338 | 396 |
| 339 Response InputHandler::SynthesizeScrollGesture( | 397 void InputHandler::SynthesizeScrollGesture( |
| 340 DevToolsCommandId command_id, | |
| 341 int x, | 398 int x, |
| 342 int y, | 399 int y, |
| 343 const int* x_distance, | 400 Maybe<int> x_distance, |
| 344 const int* y_distance, | 401 Maybe<int> y_distance, |
| 345 const int* x_overscroll, | 402 Maybe<int> x_overscroll, |
| 346 const int* y_overscroll, | 403 Maybe<int> y_overscroll, |
| 347 const bool* prevent_fling, | 404 Maybe<bool> prevent_fling, |
| 348 const int* speed, | 405 Maybe<int> speed, |
| 349 const std::string* gesture_source_type, | 406 Maybe<std::string> gesture_source_type, |
| 350 const int* repeat_count, | 407 Maybe<int> repeat_count, |
| 351 const int* repeat_delay_ms, | 408 Maybe<int> repeat_delay_ms, |
| 352 const std::string* interaction_marker_name) { | 409 Maybe<std::string> interaction_marker_name, |
| 353 if (!host_) | 410 std::unique_ptr<SynthesizeScrollGestureCallback> callback) { |
| 354 return Response::ServerError("Could not connect to view"); | 411 if (!host_ || !host_->GetRenderWidgetHost()) { |
| 412 callback->sendFailure(Response::InternalError()); |
| 413 return; |
| 414 } |
| 355 | 415 |
| 356 SyntheticSmoothScrollGestureParams gesture_params; | 416 SyntheticSmoothScrollGestureParams gesture_params; |
| 357 const bool kDefaultPreventFling = true; | 417 const bool kDefaultPreventFling = true; |
| 358 const int kDefaultSpeed = 800; | 418 const int kDefaultSpeed = 800; |
| 359 | 419 |
| 360 gesture_params.anchor = CssPixelsToPointF(x, y, page_scale_factor_); | 420 gesture_params.anchor = CssPixelsToPointF(x, y, page_scale_factor_); |
| 361 gesture_params.prevent_fling = | 421 gesture_params.prevent_fling = |
| 362 prevent_fling ? *prevent_fling : kDefaultPreventFling; | 422 prevent_fling.fromMaybe(kDefaultPreventFling); |
| 363 gesture_params.speed_in_pixels_s = speed ? *speed : kDefaultSpeed; | 423 gesture_params.speed_in_pixels_s = speed.fromMaybe(kDefaultSpeed); |
| 364 | 424 |
| 365 if (x_distance || y_distance) { | 425 if (x_distance.fromJust() || y_distance.fromJust()) { |
| 366 gesture_params.distances.push_back( | 426 gesture_params.distances.push_back( |
| 367 CssPixelsToVector2dF(x_distance ? *x_distance : 0, | 427 CssPixelsToVector2dF(x_distance.fromMaybe(0), |
| 368 y_distance ? *y_distance : 0, page_scale_factor_)); | 428 y_distance.fromMaybe(0), page_scale_factor_)); |
| 369 } | 429 } |
| 370 | 430 |
| 371 if (x_overscroll || y_overscroll) { | 431 if (x_overscroll.isJust() || y_overscroll.isJust()) { |
| 372 gesture_params.distances.push_back(CssPixelsToVector2dF( | 432 gesture_params.distances.push_back(CssPixelsToVector2dF( |
| 373 x_overscroll ? -*x_overscroll : 0, y_overscroll ? -*y_overscroll : 0, | 433 -x_overscroll.fromMaybe(0), -y_overscroll.fromMaybe(0), |
| 374 page_scale_factor_)); | 434 page_scale_factor_)); |
| 375 } | 435 } |
| 376 | 436 |
| 377 if (!StringToGestureSourceType( | 437 if (!StringToGestureSourceType( |
| 378 gesture_source_type ? *gesture_source_type : kGestureSourceTypeDefault, | 438 std::move(gesture_source_type), |
| 379 gesture_params.gesture_source_type)) { | 439 gesture_params.gesture_source_type)) { |
| 380 return Response::InvalidParams("gestureSourceType"); | 440 callback->sendFailure( |
| 441 Response::InvalidParams("Unknown gestureSourceType")); |
| 442 return; |
| 381 } | 443 } |
| 382 | 444 |
| 383 SynthesizeRepeatingScroll( | 445 SynthesizeRepeatingScroll( |
| 384 gesture_params, repeat_count ? *repeat_count : 0, | 446 gesture_params, repeat_count.fromMaybe(0), |
| 385 base::TimeDelta::FromMilliseconds(repeat_delay_ms ? *repeat_delay_ms | 447 base::TimeDelta::FromMilliseconds(repeat_delay_ms.fromMaybe(250)), |
| 386 : 250), | 448 interaction_marker_name.fromMaybe(""), ++last_id_, std::move(callback)); |
| 387 interaction_marker_name ? *interaction_marker_name : "", command_id); | |
| 388 | |
| 389 return Response::OK(); | |
| 390 } | 449 } |
| 391 | 450 |
| 392 void InputHandler::SynthesizeRepeatingScroll( | 451 void InputHandler::SynthesizeRepeatingScroll( |
| 393 SyntheticSmoothScrollGestureParams gesture_params, | 452 SyntheticSmoothScrollGestureParams gesture_params, |
| 394 int repeat_count, | 453 int repeat_count, |
| 395 base::TimeDelta repeat_delay, | 454 base::TimeDelta repeat_delay, |
| 396 std::string interaction_marker_name, | 455 std::string interaction_marker_name, |
| 397 DevToolsCommandId command_id) { | 456 int id, |
| 457 std::unique_ptr<SynthesizeScrollGestureCallback> callback) { |
| 398 if (!interaction_marker_name.empty()) { | 458 if (!interaction_marker_name.empty()) { |
| 399 // TODO(alexclarke): Can we move this elsewhere? It doesn't really fit here. | 459 // TODO(alexclarke): Can we move this elsewhere? It doesn't really fit here. |
| 400 TRACE_EVENT_COPY_ASYNC_BEGIN0("benchmark", interaction_marker_name.c_str(), | 460 TRACE_EVENT_COPY_ASYNC_BEGIN0("benchmark", interaction_marker_name.c_str(), |
| 401 command_id.call_id); | 461 id); |
| 402 } | 462 } |
| 403 | 463 |
| 404 host_->QueueSyntheticGesture( | 464 host_->GetRenderWidgetHost()->QueueSyntheticGesture( |
| 405 SyntheticGesture::Create(gesture_params), | 465 SyntheticGesture::Create(gesture_params), |
| 406 base::Bind(&InputHandler::OnScrollFinished, weak_factory_.GetWeakPtr(), | 466 base::Bind(&InputHandler::OnScrollFinished, weak_factory_.GetWeakPtr(), |
| 407 gesture_params, repeat_count, repeat_delay, | 467 gesture_params, repeat_count, repeat_delay, |
| 408 interaction_marker_name, command_id)); | 468 interaction_marker_name, id, |
| 469 base::Passed(std::move(callback)))); |
| 409 } | 470 } |
| 410 | 471 |
| 411 void InputHandler::OnScrollFinished( | 472 void InputHandler::OnScrollFinished( |
| 412 SyntheticSmoothScrollGestureParams gesture_params, | 473 SyntheticSmoothScrollGestureParams gesture_params, |
| 413 int repeat_count, | 474 int repeat_count, |
| 414 base::TimeDelta repeat_delay, | 475 base::TimeDelta repeat_delay, |
| 415 std::string interaction_marker_name, | 476 std::string interaction_marker_name, |
| 416 DevToolsCommandId command_id, | 477 int id, |
| 478 std::unique_ptr<SynthesizeScrollGestureCallback> callback, |
| 417 SyntheticGesture::Result result) { | 479 SyntheticGesture::Result result) { |
| 418 if (!interaction_marker_name.empty()) { | 480 if (!interaction_marker_name.empty()) { |
| 419 TRACE_EVENT_COPY_ASYNC_END0("benchmark", interaction_marker_name.c_str(), | 481 TRACE_EVENT_COPY_ASYNC_END0("benchmark", interaction_marker_name.c_str(), |
| 420 command_id.call_id); | 482 id); |
| 421 } | 483 } |
| 422 | 484 |
| 423 if (repeat_count > 0) { | 485 if (repeat_count > 0) { |
| 424 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 486 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 425 FROM_HERE, | 487 FROM_HERE, |
| 426 base::Bind(&InputHandler::SynthesizeRepeatingScroll, | 488 base::Bind(&InputHandler::SynthesizeRepeatingScroll, |
| 427 weak_factory_.GetWeakPtr(), gesture_params, repeat_count - 1, | 489 weak_factory_.GetWeakPtr(), gesture_params, repeat_count - 1, |
| 428 repeat_delay, interaction_marker_name, command_id), | 490 repeat_delay, interaction_marker_name, id, |
| 491 base::Passed(std::move(callback))), |
| 429 repeat_delay); | 492 repeat_delay); |
| 430 } else { | 493 } else { |
| 431 SendSynthesizeScrollGestureResponse(command_id, result); | 494 SendSynthesizeScrollGestureResponse(std::move(callback), result); |
| 432 } | 495 } |
| 433 } | 496 } |
| 434 | 497 |
| 435 Response InputHandler::SynthesizeTapGesture( | 498 void InputHandler::SynthesizeTapGesture( |
| 436 DevToolsCommandId command_id, | |
| 437 int x, | 499 int x, |
| 438 int y, | 500 int y, |
| 439 const int* duration, | 501 Maybe<int> duration, |
| 440 const int* tap_count, | 502 Maybe<int> tap_count, |
| 441 const std::string* gesture_source_type) { | 503 Maybe<std::string> gesture_source_type, |
| 442 if (!host_) | 504 std::unique_ptr<SynthesizeTapGestureCallback> callback) { |
| 443 return Response::ServerError("Could not connect to view"); | 505 if (!host_ || !host_->GetRenderWidgetHost()) { |
| 506 callback->sendFailure(Response::InternalError()); |
| 507 return; |
| 508 } |
| 444 | 509 |
| 445 SyntheticTapGestureParams gesture_params; | 510 SyntheticTapGestureParams gesture_params; |
| 446 const int kDefaultDuration = 50; | 511 const int kDefaultDuration = 50; |
| 447 const int kDefaultTapCount = 1; | 512 const int kDefaultTapCount = 1; |
| 448 | 513 |
| 449 gesture_params.position = CssPixelsToPointF(x, y, page_scale_factor_); | 514 gesture_params.position = CssPixelsToPointF(x, y, page_scale_factor_); |
| 450 gesture_params.duration_ms = duration ? *duration : kDefaultDuration; | 515 gesture_params.duration_ms = duration.fromMaybe(kDefaultDuration); |
| 451 | 516 |
| 452 if (!StringToGestureSourceType( | 517 if (!StringToGestureSourceType( |
| 453 gesture_source_type ? *gesture_source_type : kGestureSourceTypeDefault, | 518 std::move(gesture_source_type), |
| 454 gesture_params.gesture_source_type)) { | 519 gesture_params.gesture_source_type)) { |
| 455 return Response::InvalidParams("gestureSourceType"); | 520 callback->sendFailure( |
| 521 Response::InvalidParams("Unknown gestureSourceType")); |
| 522 return; |
| 456 } | 523 } |
| 457 | 524 |
| 458 if (!tap_count) | 525 int count = tap_count.fromMaybe(kDefaultTapCount); |
| 459 tap_count = &kDefaultTapCount; | 526 if (!count) { |
| 460 | 527 callback->sendSuccess(); |
| 461 for (int i = 0; i < *tap_count; i++) { | 528 return; |
| 462 // If we're doing more than one tap, don't send the response to the client | |
| 463 // until we've completed the last tap. | |
| 464 bool is_last_tap = i == *tap_count - 1; | |
| 465 host_->QueueSyntheticGesture( | |
| 466 SyntheticGesture::Create(gesture_params), | |
| 467 base::Bind(&InputHandler::SendSynthesizeTapGestureResponse, | |
| 468 weak_factory_.GetWeakPtr(), command_id, is_last_tap)); | |
| 469 } | 529 } |
| 470 | 530 |
| 471 return Response::OK(); | 531 TapGestureResponse* response = |
| 472 } | 532 new TapGestureResponse(std::move(callback), count); |
| 473 | 533 for (int i = 0; i < count; i++) { |
| 474 Response InputHandler::DispatchTouchEvent( | 534 host_->GetRenderWidgetHost()->QueueSyntheticGesture( |
| 475 const std::string& type, | 535 SyntheticGesture::Create(gesture_params), |
| 476 const std::vector<std::unique_ptr<base::DictionaryValue>>& touch_points, | 536 base::Bind(&TapGestureResponse::OnGestureResult, |
| 477 const int* modifiers, | 537 base::Unretained(response))); |
| 478 const double* timestamp) { | |
| 479 return Response::FallThrough(); | |
| 480 } | |
| 481 | |
| 482 void InputHandler::SendSynthesizePinchGestureResponse( | |
| 483 DevToolsCommandId command_id, | |
| 484 SyntheticGesture::Result result) { | |
| 485 if (result == SyntheticGesture::Result::GESTURE_FINISHED) { | |
| 486 client_->SendSynthesizePinchGestureResponse( | |
| 487 command_id, SynthesizePinchGestureResponse::Create()); | |
| 488 } else { | |
| 489 client_->SendError(command_id, | |
| 490 Response::InternalError(base::StringPrintf( | |
| 491 "Synthetic pinch failed, result was %d", result))); | |
| 492 } | 538 } |
| 493 } | 539 } |
| 494 | 540 |
| 495 void InputHandler::SendSynthesizeScrollGestureResponse( | 541 } // namespace protocol |
| 496 DevToolsCommandId command_id, | |
| 497 SyntheticGesture::Result result) { | |
| 498 if (result == SyntheticGesture::Result::GESTURE_FINISHED) { | |
| 499 client_->SendSynthesizeScrollGestureResponse( | |
| 500 command_id, SynthesizeScrollGestureResponse::Create()); | |
| 501 } else { | |
| 502 client_->SendError(command_id, | |
| 503 Response::InternalError(base::StringPrintf( | |
| 504 "Synthetic scroll failed, result was %d", result))); | |
| 505 } | |
| 506 } | |
| 507 | |
| 508 void InputHandler::SendSynthesizeTapGestureResponse( | |
| 509 DevToolsCommandId command_id, | |
| 510 bool send_success, | |
| 511 SyntheticGesture::Result result) { | |
| 512 if (result == SyntheticGesture::Result::GESTURE_FINISHED) { | |
| 513 if (send_success) { | |
| 514 client_->SendSynthesizeTapGestureResponse( | |
| 515 command_id, SynthesizeTapGestureResponse::Create()); | |
| 516 } | |
| 517 } else { | |
| 518 client_->SendError(command_id, | |
| 519 Response::InternalError(base::StringPrintf( | |
| 520 "Synthetic tap failed, result was %d", result))); | |
| 521 } | |
| 522 } | |
| 523 | |
| 524 } // namespace input | |
| 525 } // namespace devtools | |
| 526 } // namespace content | 542 } // namespace content |
| OLD | NEW |