[go: up one dir, main page]

[m96] Reland "Set from_devtools_debugger in CDP events handler and use it in aura gesture target to dispatch to the specific view instead of a root window."

This is a reland of 8a8a3311f21bf6e164403df68338549ead56ab03

Original change's description:
> Set from_devtools_debugger in CDP events handler and use it in aura gesture target to dispatch to the specific view instead of a root window.
>
> Bug: 1117173
> Change-Id: I02eaa35b8f4bd961018c5d8d80eb639319baeb8f
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3263968
> Commit-Queue: Danil Somsikov <dsv@chromium.org>
> Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
> Reviewed-by: Keren Zhu <kerenzhu@chromium.org>
> Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#942533}

(cherry picked from commit 42f3de93ec0ae3cd8e855aec1631a26baf66a523)

Bug: 1117173
Change-Id: Ideee602bedfaec59c1077b57e46de29605ac7500
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3289268
Commit-Queue: Danil Somsikov <dsv@chromium.org>
Reviewed-by: Keren Zhu <kerenzhu@chromium.org>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#942994}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3329843
Cr-Commit-Position: refs/branch-heads/4664@{#1302}
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
diff --git a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 1901209..22340ba 100644
--- a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
+#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/test/values_test_util.h"
 #include "base/threading/thread_restrictions.h"
@@ -40,7 +41,10 @@
 #include "third_party/boringssl/src/include/openssl/ssl.h"
 
 using DevToolsProtocolTest = DevToolsProtocolTestBase;
+using testing::AllOf;
 using testing::Eq;
+using testing::Contains;
+using testing::Not;
 
 namespace {
 
@@ -108,6 +112,81 @@
   // Should not crash by this point.
 }
 
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
+                       InputDispatchEventsToCorrectTarget) {
+  Attach();
+
+  std::string setup_logging = R"(
+      window.logs = [];
+      ['dragenter', 'keydown', 'mousedown', 'mouseenter', 'mouseleave',
+       'mousemove', 'mouseout', 'mouseover', 'mouseup', 'click', 'touchcancel',
+       'touchend', 'touchmove', 'touchstart',
+      ].forEach((event) =>
+        window.addEventListener(event, (e) => logs.push(e.type)));)";
+  content::WebContents* target_web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL("about:blank"), WindowOpenDisposition::NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
+  content::WebContents* other_web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_TRUE(
+      content::EvalJs(target_web_contents, setup_logging).error.empty());
+  EXPECT_TRUE(content::EvalJs(other_web_contents, setup_logging).error.empty());
+
+  base::DictionaryValue params;
+  params.SetStringKey("button", "left");
+  params.SetIntKey("clickCount", 1);
+  params.SetIntKey("x", 100);
+  params.SetIntKey("y", 250);
+  params.SetIntKey("clickCount", 1);
+
+  params.SetStringKey("type", "mousePressed");
+  SendCommandSync("Input.dispatchMouseEvent", params.Clone());
+
+  params.SetStringKey("type", "mouseMoved");
+  params.SetIntKey("y", 270);
+  SendCommandSync("Input.dispatchMouseEvent", params.Clone());
+
+  params.SetStringKey("type", "mouseReleased");
+  SendCommandSync("Input.dispatchMouseEvent", std::move(params));
+
+  params = base::DictionaryValue();
+  params.SetIntKey("x", 100);
+  params.SetIntKey("y", 250);
+  params.SetStringPath("type", "dragEnter");
+  params.SetIntPath("data.dragOperationsMask", 1);
+  params.SetPath("data.items", base::ListValue());
+  SendCommandSync("Input.dispatchDragEvent", std::move(params));
+
+  params = base::DictionaryValue();
+  params.SetIntKey("x", 100);
+  params.SetIntKey("y", 250);
+  SendCommandSync("Input.synthesizeTapGesture", std::move(params));
+
+  params = base::DictionaryValue();
+  params.SetStringKey("type", "keyDown");
+  params.SetStringKey("key", "a");
+  SendCommandSync("Input.dispatchKeyEvent", std::move(params));
+
+  content::EvalJsResult main_target_events =
+      content::EvalJs(target_web_contents, "logs.join(' ')");
+  content::EvalJsResult other_target_events =
+      content::EvalJs(other_web_contents, "logs.join(' ')");
+  // mouse events might happen in the other_target if the real mouse pointer
+  // happens to be over the browser window
+  EXPECT_THAT(base::SplitString(main_target_events.ExtractString(), " ",
+                                base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL),
+              AllOf(Contains("mouseover"), Contains("mousedown"), Contains("mousemove"),
+                    Contains("mouseup"), Contains("click"), Contains("dragenter"),
+                    Contains("keydown")));
+  EXPECT_THAT(base::SplitString(other_target_events.ExtractString(), " ",
+                                base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL),
+              AllOf(Not(Contains("click")), Not(Contains("dragenter")),
+                    Not(Contains("keydown"))));
+}
+
 class DevToolsProtocolTest_AppId : public DevToolsProtocolTest {
  public:
   DevToolsProtocolTest_AppId() {
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc
index 65eda39..199f70a 100644
--- a/content/browser/devtools/protocol/input_handler.cc
+++ b/content/browser/devtools/protocol/input_handler.cc
@@ -133,6 +133,7 @@
 bool GetMouseEventButton(const std::string& button,
                          blink::WebPointerProperties::Button* event_button,
                          int* event_modifiers) {
+  *event_modifiers = blink::WebInputEvent::kFromDebugger;
   if (button.empty())
     return true;
 
@@ -140,19 +141,19 @@
     *event_button = blink::WebMouseEvent::Button::kNoButton;
   } else if (button == Input::MouseButtonEnum::Left) {
     *event_button = blink::WebMouseEvent::Button::kLeft;
-    *event_modifiers = blink::WebInputEvent::kLeftButtonDown;
+    *event_modifiers |= blink::WebInputEvent::kLeftButtonDown;
   } else if (button == Input::MouseButtonEnum::Middle) {
     *event_button = blink::WebMouseEvent::Button::kMiddle;
-    *event_modifiers = blink::WebInputEvent::kMiddleButtonDown;
+    *event_modifiers |= blink::WebInputEvent::kMiddleButtonDown;
   } else if (button == Input::MouseButtonEnum::Right) {
     *event_button = blink::WebMouseEvent::Button::kRight;
-    *event_modifiers = blink::WebInputEvent::kRightButtonDown;
+    *event_modifiers |= blink::WebInputEvent::kRightButtonDown;
   } else if (button == Input::MouseButtonEnum::Back) {
     *event_button = blink::WebMouseEvent::Button::kBack;
-    *event_modifiers = blink::WebInputEvent::kBackButtonDown;
+    *event_modifiers |= blink::WebInputEvent::kBackButtonDown;
   } else if (button == Input::MouseButtonEnum::Forward) {
     *event_button = blink::WebMouseEvent::Button::kForward;
-    *event_modifiers = blink::WebInputEvent::kForwardButtonDown;
+    *event_modifiers |= blink::WebInputEvent::kForwardButtonDown;
   } else {
     return false;
   }
@@ -1367,7 +1368,7 @@
 
   if (!synthetic_pointer_driver_) {
     synthetic_pointer_driver_ =
-        SyntheticPointerDriver::Create(gesture_source_type);
+        SyntheticPointerDriver::Create(gesture_source_type, true);
   }
   std::unique_ptr<SyntheticPointerAction> synthetic_gesture =
       std::make_unique<SyntheticPointerAction>(action_list_params);
@@ -1563,6 +1564,7 @@
   SyntheticPinchGestureParams gesture_params;
   const int kDefaultRelativeSpeed = 800;
 
+  gesture_params.from_devtools_debugger = true;
   gesture_params.scale_factor = scale_factor;
   gesture_params.anchor = CssPixelsToPointF(x, y, page_scale_factor_);
   if (!PointIsWithinContents(gesture_params.anchor)) {
@@ -1612,6 +1614,7 @@
   }
 
   SyntheticSmoothScrollGestureParams gesture_params;
+  gesture_params.from_devtools_debugger = true;
   const bool kDefaultPreventFling = true;
   const int kDefaultSpeed = 800;
 
@@ -1723,6 +1726,7 @@
   const int kDefaultTapCount = 1;
 
   gesture_params.position = CssPixelsToPointF(x, y, page_scale_factor_);
+  gesture_params.from_devtools_debugger = true;
   if (!PointIsWithinContents(gesture_params.position)) {
     callback->sendFailure(Response::InvalidParams("Position out of bounds"));
     return;
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
index db6bbafc..c5848f1 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -63,12 +63,19 @@
 
   aura::Window* window = GetWindow();
   aura::WindowTreeHost* host = window->GetHost();
-  for (const auto& event : events) {
-    event->ConvertLocationToTarget(window, host->window());
-    ui::EventDispatchDetails details =
-        event_injector_.Inject(host, event.get());
-    if (details.dispatcher_destroyed)
-      break;
+  for (auto& event : events) {
+    // Synthetic events from devtools debugger need to be dispatched explicitly
+    // to the target window. Otherwise they will end up in the active tab
+    // which might be different from the target.
+    if (web_touch.GetModifiers() & blink::WebInputEvent::kFromDebugger) {
+      window->delegate()->OnEvent(event.get());
+    } else {
+      event->ConvertLocationToTarget(window, host->window());
+      ui::EventDispatchDetails details =
+          event_injector_.Inject(host, event.get());
+      if (details.dispatcher_destroyed)
+        break;
+    }
   }
 }
 
@@ -97,11 +104,18 @@
   wheel_precision_y_ = delta_y - wheel_event.y_offset();
 
   aura::Window* window = GetWindow();
-  wheel_event.ConvertLocationToTarget(window, window->GetRootWindow());
-  ui::EventDispatchDetails details =
-      event_injector_.Inject(window->GetHost(), &wheel_event);
-  if (details.dispatcher_destroyed)
-    return;
+  // Synthetic events from devtools debugger need to be dispatched explicitly
+  // to the target window. Otherwise they will end up in the active tab
+  // which might be different from the target.
+  if (web_wheel.GetModifiers() & blink::WebInputEvent::kFromDebugger) {
+    window->delegate()->OnEvent(&wheel_event);
+  } else {
+    wheel_event.ConvertLocationToTarget(window, window->GetRootWindow());
+    ui::EventDispatchDetails details =
+        event_injector_.Inject(window->GetHost(), &wheel_event);
+    if (details.dispatcher_destroyed)
+      return;
+  }
 }
 
 void SyntheticGestureTargetAura::DispatchWebGestureEventToPlatform(
@@ -123,8 +137,15 @@
                                  web_gesture.PositionInWidget().y(), flags,
                                  web_gesture.TimeStamp(), pinch_details);
 
-    pinch_event.ConvertLocationToTarget(window, window->GetRootWindow());
-    event_injector_.Inject(window->GetHost(), &pinch_event);
+    // Synthetic events from devtools debugger need to be dispatched explicitly
+    // to the target window. Otherwise they will end up in the active tab
+    // which might be different from the target.
+    if (web_gesture.GetModifiers() & blink::WebInputEvent::kFromDebugger) {
+      window->delegate()->OnEvent(&pinch_event);
+    } else {
+      pinch_event.ConvertLocationToTarget(window, window->GetRootWindow());
+      event_injector_.Inject(window->GetHost(), &pinch_event);
+    }
     return;
   }
 
@@ -138,8 +159,15 @@
                                web_gesture.data.fling_start.velocity_x,
                                web_gesture.data.fling_start.velocity_y, 0, 0, 2,
                                momentum_phase, ui::ScrollEventPhase::kNone);
-  scroll_event.ConvertLocationToTarget(window, window->GetRootWindow());
-  event_injector_.Inject(window->GetHost(), &scroll_event);
+  // Synthetic events from devtools debugger need to be dispatched explicitly
+  // to the target window. Otherwise they will end up in the active tab
+  // which might be different from the target.
+  if (web_gesture.GetModifiers() & blink::WebInputEvent::kFromDebugger) {
+    window->delegate()->OnEvent(&scroll_event);
+  } else {
+    scroll_event.ConvertLocationToTarget(window, window->GetRootWindow());
+    event_injector_.Inject(window->GetHost(), &scroll_event);
+  }
 }
 
 void SyntheticGestureTargetAura::DispatchWebMouseEventToPlatform(
@@ -164,12 +192,19 @@
                              changed_button_flags, pointer_details);
 
   aura::Window* window = GetWindow();
-  mouse_event.ConvertLocationToTarget(window, window->GetRootWindow());
   mouse_event.SetClickCount(web_mouse_event.click_count);
-  ui::EventDispatchDetails details =
-      event_injector_.Inject(window->GetHost(), &mouse_event);
-  if (details.dispatcher_destroyed)
-    return;
+  // Synthetic events from devtools debugger need to be dispatched explicitly
+  // to the target window. Otherwise they will end up in the active tab
+  // which might be different from the target.
+  if (web_mouse_event.GetModifiers() & blink::WebInputEvent::kFromDebugger) {
+    window->delegate()->OnEvent(&mouse_event);
+  } else {
+    mouse_event.ConvertLocationToTarget(window, window->GetRootWindow());
+    ui::EventDispatchDetails details =
+        event_injector_.Inject(window->GetHost(), &mouse_event);
+    if (details.dispatcher_destroyed)
+      return;
+  }
 }
 
 content::mojom::GestureSourceType