Closed Bug 1848958 Opened 2 years ago Closed 4 months ago

Send async "mouse" events at the widget level instead of synthesized DOM events

Categories

(Remote Protocol :: Marionette, task, P2)

task
Points:
5

Tracking

(firefox147 fixed)

RESOLVED FIXED
147 Branch
Tracking Status
firefox147 --- fixed

People

(Reporter: whimboo, Assigned: whimboo)

References

(Blocks 12 open bugs)

Details

(Whiteboard: [webdriver:m18], [wptsync upstream])

Attachments

(4 files)

See more details on bug 1773393. We need widget level events to send mouse events closer to what an actual user would do.

Depends on: 1834306
No longer depends on: 1834306
Depends on: 1848957
Depends on: 1853120
Depends on: 1851812
Summary: Consider sending widget input events for mouse instead of synthesized DOM events → Send async "mouse" events at the widget level instead of synthesized DOM events

Please note that with bug 1852243 we have a temporary workaround available that will work fine for layout folks to work towards the interop 2023 goals. As such we do not have to work on this feature in M8 anymore.

Whiteboard: [webdriver:m8] → [webdriver:backlog]
No longer depends on: 1851812
Blocks: 1866500
No longer blocks: 1866500

I realized that InputData which is used by APZ instead of Widget*Event does not have a flag whether the input is caused by a native event or synthesized for tests. This is currently a problem for synthesized mouse events. PresShell::HandleEvent needs to ignore unexpected events coming from OS during tests. So, we need to fix this like this experimental patch. It does not have automated tests, so, if you want, feel free to reuse the patch.

Thanks for the information Masayuki! I haven't started all the work yet but it's planned for next week. Nevertheless it will take a bit until I've everything in place to get started with this bug. So when you filed a bug for your fix please mark it blocking this bug and bug 1885073.

Flags: needinfo?(masayuki)

No, I don't work on it because of not enough time for this. Feel free to use my patch.

Flags: needinfo?(masayuki)
Depends on: 1918806
Whiteboard: [webdriver:backlog] → [webdriver:m16]
Depends on: 1955284
Whiteboard: [webdriver:m16] → [webdriver:m17]
Depends on: 1968855
Depends on: 1968859
Blocks: 1965673
Blocks: 1904859
Blocks: 1894654
Blocks: 1983780
Assignee: nobody → hskupin
Status: NEW → ASSIGNED

While implementing this new feature I noticed that there is a subtle race between when the callback is called and when the event is actually emitted on the page in the content process. It's just some milliseconds off but this can cause tests like the following to fail:

def test_move_to_fractional_position2(session, inline, mouse_chain):
    chain_temp = session.actions.sequence(
        "pointer",
        "pointer_id2",
        {"pointerType": "mouse"})
    chain_temp \
        .pointer_move(100, 100) \
        .perform()

    session.url = inline("""
        <script>
          var allEvents = { events: [] };
          window.addEventListener("pointermove", ev => {
            dump(`\n*** ${Date.now()} event: ${ev.type}\n`);
            allEvents.events.push({
                "type": event.type,
                "pageX": event.pageX,
                "pageY": event.pageY,
            });
          });
        </script>
        """)

    target_point = {
        "x": 5.75,
        "y": 10.25,
    }

    mouse_chain \
        .pointer_move(target_point["x"], target_point["y"]) \
        .perform()

    events = get_events(session)
    assert len(events) == 1

    # For now we are allowing any of floor, ceil, or precise values, because
    # it's unclear what the actual spec requirements really are
    assert events[3]["type"] == "pointermove"
    assert events[3]["pageX"] == pytest.approx(target_point["x"], abs=1.0)
    assert events[3]["pageY"] == pytest.approx(target_point["y"], abs=1.0)

Here the mousemove from the mouse_chain doesn't produce mousemove event in time, so that no event is seen. When I move the chain_temp action after the page load it works all fine. Also when it is removed completely.

Here is the output:

 0:07.47 pid:38892 1758121608042	RemoteAgent	TRACE	PointerMoveAction.performPointerMoveStep [5.75,95.25]
 0:07.48 pid:38892 1758121608043	Marionette	DEBUG	0 <- [1,9,null,{"value":null}]
 0:07.48 pid:38892 1758121608043	webdriver::server	DEBUG	<- 200 OK {"value":null}
 0:07.48 pid:38892 1758121608043	webdriver::server	DEBUG	-> POST /session/0fa3350a-2c86-4aae-85ef-372410357a76/execute/sync {"script": "return allEvents.events;", "args": []}
 0:07.48 pid:38892 1758121608044	Marionette	DEBUG	0 -> [0,10,"WebDriver:ExecuteScript",{"args":[],"script":"return allEvents.events;"}]
 0:07.48 pid:38892 1758121608044	Marionette	DEBUG	0 <- [1,10,null,{"value":[]}]
 0:07.48 pid:38892 1758121608045	webdriver::server	DEBUG	<- 200 OK {"value":[]}
 0:07.48 pid:38892 *** 1758121608046 event: pointermove

Once the patches are ready I'll upload to Phabricator to make it reproducible for platform folks for further investigation.

I've attached the current version of my local patches to allow platform folks to investigate the delay of mouse events in the web page. Further I've had a chance to simplify the test and gain more details. The following Marionette test can help. Just run it with:

# coding=UTF-8

from urllib.parse import quote

from marionette_harness import (
    MarionetteTestCase,
    WindowManagerMixin,
)

BOILERPLATES = {
    "html": "<!doctype html>\n<meta charset={charset}>\n{src}",
    "xhtml": """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>XHTML might be the future</title>
  </head>

  <body>
    {src}
  </body>
</html>""",
    "xml": """<?xml version="1.0" encoding="{charset}"?>\n{src}""",
}

MIME_TYPES = {
    "html": "text/html",
    "xhtml": "application/xhtml+xml",
    "xml": "text/xml",
}


def inline(doc, doctype="html", charset="UTF-8"):
    content = BOILERPLATES[doctype].format(src=doc, charset=charset)

    return f"data:{MIME_TYPES[doctype]},{quote(content)}"


class TestMinimizedTestCase(WindowManagerMixin, MarionetteTestCase):
    def tearDown(self):
        if (hasattr(self, "close_all_tabs")):
            self.close_all_tabs()

        super(TestMinimizedTestCase, self).tearDown()

    def test_parent_process_events(self):
        self.marionette.set_pref("remote.events.async.mouse.enabled", True)

        new_tab = self.marionette.open("tab")
        self.marionette.switch_to_window(new_tab["handle"], focus=True)

        self.marionette.navigate(inline("""
            <script>
            var allEvents = { events: [] };
            window.addEventListener("mousemove", ev => {
                dump(`\n\n${Date.now()} *** event: ${ev.type}\n\n`);
                allEvents.events.push({
                    "type": event.type,
                    "pageX": event.pageX,
                    "pageY": event.pageY,
                });
            });
            </script>
        """))

        mouse_chain = self.marionette.actions.sequence("pointer", "pointer_id")
        mouse_chain.pointer_move(8, 8)
        mouse_chain.perform()

        events = self.marionette.execute_script("return allEvents.events", new_sandbox=False, sandbox=None)
        assert len(events) == 1

mach marionette-test --gecko-log=- -vv _a/test_minimized.py --run-until-failure

Things I've noticed:

  1. The problem is only present when running the test in a new tab. When I change the test to open a new window the problem is gone.
  2. It's not a timing issue for when we synthesize the events given that it is also present when I add 5s of delay after opening the tab.

Edgar, could you please check why we have that delay?

Flags: needinfo?(echen)

I'm going to add more wdspec tests once that bug is landed.

Blocks: 1955284
No longer depends on: 1955284

Here a try build with the async Wdspec jobs, which shows a crash for MOZ_ASSERT(false) (MOZ_ASSERT_UNREACHABLE: We should always find a saved callback):

https://treeherder.mozilla.org/jobs?repo=try&tier=1%2C2%2C3&revision=981f437aa5f755d843432933138f821cfa12e280&searchStr=wd%2Cdebug

Edgar is taking a look into this and can also reproduce locally.

(In reply to Henrik Skupin [:whimboo][⌚️UTC+2] from comment #10)

Edgar, could you please check why we have that delay?

I filed bug 1989416.

Depends on: 1989416
Flags: needinfo?(echen)

There is also a crash in the DragSessionProxy which I filed as bug 1989436. Given that this only happens for async jobs in CI it's not a hard-blocker and I should mark those tests as currently crashing.

Whiteboard: [webdriver:m17] → [webdriver:m18]
Blocks: 1998260

It looks like that I was able to figure out the remaining issues and so far the most recent try build looks fine:
https://treeherder.mozilla.org/jobs?repo=try&tier=1%2C2%2C3&revision=ef54f4e61ef7344b45046423d1e6cadb62a4f0cb

If it stays that way I'll upload an updated series of patches tomorrow.

Attachment #9513928 - Attachment description: WIP: Bug 1848958 - [remote] Ignore error from finalize action if browsing context no longer exists. → Bug 1848958 - [remote] Ignore error from finalize action if browsing context no longer exists.
Attachment #9513929 - Attachment description: WIP: Bug 1848958 - [remote] Add support for mouse widget events to Marionette and WebDriver BiDi. → Bug 1848958 - [remote] Add support for mouse widget events to Marionette and WebDriver BiDi.
Attachment #9513930 - Attachment description: WIP: Bug 1848958 - [remote] Use async (widget) mouse events for async-event-dispatching jobs in CI. → Bug 1848958 - [remote] Use async (widget) mouse events for async-event-dispatching jobs in CI.
Attachment #9513931 - Attachment description: WIP: Bug 1848958 - [wdspec] Update tests for async mouse events. → Bug 1848958 - [wdspec] Update tests for async mouse events.
Blocks: 1998347
Blocks: 1998786
Blocks: 1999380
Attachment #9513931 - Attachment description: Bug 1848958 - [wdspec] Update tests for async mouse events. → Bug 1848958 - [wdspec] Update tests for dispatching mouse events via the parent process.
Pushed by hskupin@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/9e80bc22f216 https://hg.mozilla.org/integration/autoland/rev/41dbafc765a4 [remote] Ignore error from finalize action if browsing context no longer exists. r=jdescottes https://github.com/mozilla-firefox/firefox/commit/2c38d9a85586 https://hg.mozilla.org/integration/autoland/rev/852c5c1290bb [remote] Add support for mouse widget events to Marionette and WebDriver BiDi. r=jdescottes https://github.com/mozilla-firefox/firefox/commit/cc2c0ff3147c https://hg.mozilla.org/integration/autoland/rev/9cc5104f1ac8 [remote] Use async (widget) mouse events for async-event-dispatching jobs in CI. r=jgraham,jdescottes https://github.com/mozilla-firefox/firefox/commit/4a2e13581c2d https://hg.mozilla.org/integration/autoland/rev/0ffad14f5d03 [wdspec] Update tests for dispatching mouse events via the parent process. r=jdescottes
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/55976 for changes under testing/web-platform/tests
Whiteboard: [webdriver:m18] → [webdriver:m18], [wptsync upstream]
Pushed by abutkovits@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/d210ff281f35 https://hg.mozilla.org/integration/autoland/rev/9e063737eb82 Revert "Bug 1848958 - [wdspec] Update tests for dispatching mouse events via the parent process. r=jdescottes" for causing failures at pointer_dblclick.py.
Pushed by archaeopteryx@coole-files.de: https://github.com/mozilla-firefox/firefox/commit/303fbd932715 https://hg.mozilla.org/mozilla-central/rev/11c34bdb25ea [remote] Ignore error from finalize action if browsing context no longer exists. r=jdescottes https://github.com/mozilla-firefox/firefox/commit/bca3fa41d754 https://hg.mozilla.org/mozilla-central/rev/6628ce965840 [remote] Add support for mouse widget events to Marionette and WebDriver BiDi. r=jdescottes https://github.com/mozilla-firefox/firefox/commit/4340c11d3235 https://hg.mozilla.org/mozilla-central/rev/55c404ab4de3 [remote] Use async (widget) mouse events for async-event-dispatching jobs in CI. r=jgraham,jdescottes https://github.com/mozilla-firefox/firefox/commit/5f95d4ad4f06 https://hg.mozilla.org/mozilla-central/rev/8e857ab00473 [wdspec] Update tests for dispatching mouse events via the parent process. r=jdescottes https://github.com/mozilla-firefox/firefox/commit/6abddcb0a507 https://hg.mozilla.org/mozilla-central/rev/88a09a47e50b Revert "Bug 1848958 - [wdspec] Update tests for dispatching mouse events via the parent process. r=jdescottes" for causing failures at pointer_dblclick.py.
Upstream PR merged by moz-wptsync-bot

There is an issue with the meta data for pointer_dblclick.py tests, which I've updated before landing but which assumes the given tests to fail everywhere even for test jobs without async events. I need to fix that.

But there is as well an issue on Android when dispatching the event. There is the following JavaScript error thrown due to different timing causing a silent failure and the command to hang:

11-12 10:18:46.240  5829  5851 E GeckoConsole: [JavaScript Error: "ReferenceError: can't access lexical declaration 'preventDefault' before initialization" {file: "chrome://remote/content/shared/webdriver/Event.sys.mjs" line: 93}]

The linter doesn't show this as error or even not as warning. I'm going to fix that.

Flags: needinfo?(hskupin)
Blocks: 1999714
Pushed by hskupin@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/99a1153fdbea https://hg.mozilla.org/integration/autoland/rev/e26b4b7e0032 [wdspec] Update tests for dispatching mouse events via the parent process. r=jdescottes https://github.com/mozilla-firefox/firefox/commit/a6a9422f1d15 https://hg.mozilla.org/integration/autoland/rev/cdfa56af3094 [remote] Ignore error from finalize action if browsing context no longer exists. r=jdescottes https://github.com/mozilla-firefox/firefox/commit/1b2336856443 https://hg.mozilla.org/integration/autoland/rev/68b77d556f52 [remote] Use async (widget) mouse events for async-event-dispatching jobs in CI. r=jgraham,jdescottes https://github.com/mozilla-firefox/firefox/commit/d382b9ac2ecb https://hg.mozilla.org/integration/autoland/rev/203a0d2dad2a [remote] Add support for mouse widget events to Marionette and WebDriver BiDi. r=jdescottes
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/56013 for changes under testing/web-platform/tests
Upstream PR was closed without merging
Upstream PR was closed without merging
Blocks: 1935324
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: