Implement scroll into view steps for all WebDriver command that requires
it (element click, element send keys, element clear, and take element
screenshot).
Testing: `element_send_keys/scroll_into_view.py`,
`element_click/scroll_into_view.py`, `element_clear/clear.py`
---------
Signed-off-by: PotatoCP <Kenzie.Raditya.Tirtarahardja@huawei.com>
This should be the final PR for the Hash Function series that is
trivial.
Of note: I decided to transform `HashMapTracedValues<Atom,..>` to use
FxBuildHasher. This is likely not going to improve performance as Atom's
already have a unique u32 that is used as the Hash but it safes a few
bytes for the RandomState that is normally in the HashMap.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Testing: Hash function changes should not change functionality, we
slightly decrease the size and unit tests still work.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
- Add `ShadowRoot` to `JSValue` to avoid
`WebDriverJSError::UnknownType`, and
`JavaScriptEvaluationError::SerializationError` when execute JS from
embedder.
- Add unit test.
- Move [is_detached](https://w3c.github.io/webdriver/#dfn-is-detached)
to `fn is_detached` to be reused.
- Other random simplification.
Testing: WebDriver conformance tests.
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
Ports the channel for WebDriverLoadStatus to GenericChannel.
Testing: No functional changes - Covered by existing webdriver tests
Part of #38912
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
Previously we immediately passed the KeyboardEvent to embedder. Now we
make element send keys go through the dispatch action which required by
spec. CompositionEvent still immediately passed through embedder
Testing: Should make
`./tests/wpt/tests/webdriver/tests/classic/element_send_keys/` more
stable.
Fixes: https://github.com/servo/servo/issues/38354
Fixes: https://github.com/servo/servo/issues/38442
---------
Signed-off-by: PotatoCP <Kenzie.Raditya.Tirtarahardja@huawei.com>
Co-authored-by: Euclid Ye <euclid.ye@huawei.com>
This PR contains 2 parts:
1. Refactor webdriver session.
2. Improve webdriver window handles:
- Webdriver always get window handles from script thread by default.
- If script thread is blocked by user prompt, embedder stores the window
handle before user prompt appears, then webdriver can get window handle
from embedder.
Testing: Clear timeout cause by user prompt blocking script thread:
https://github.com/longvatrong111/servo/actions/runs/17033900026
---------
Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
Signed-off-by: batu_hoang <longvatrong111@gmail.com>
Co-authored-by: Euclid Ye <euclid.ye@huawei.com>
After #38748, `WebDriverJSValue` is almost same as `JSValue`. Now we
turn "potentially merge into one in the future" into reality. The only
thing we should be cautious is to properly serialize `WebFrame`,
`WebWindow`, `WebElement` for WebDriver.
Testing: No regression. Some error is fixed previously by #38709 which
didn't update test :)
Binary size reduced by 134KB.
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
Implment get window handles according to
[spec](https://w3c.github.io/webdriver/#dfn-window-handles).
- Window handles are supposed to identify `browsing context`. However,
based on `get window handle command` and `get window handles command`,
we only need to care about top level browsing context.
- Back then, we use a random generated uuid for eacch webview id, it is
not correct but still work because all commands depend on `webview id`
and `browsing context id`. The only case we need window handle is is
when webdriver gets window object with js script. Since the object is
converted to the id of window's document node, `get window handle`
should return the same thing.
Action run (with updated expectation):
https://github.com/longvatrong111/servo/actions/runs/16957610535https://github.com/longvatrong111/servo/actions/runs/16957612027
Some tests may sporadically timeout due to unstable hit test.
cc: @xiaochengh
---------
Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
1. Synchronize [Close
Window](https://w3c.github.io/webdriver/#dfn-close-window) command to
reduce intermittency
2. There was a update last month exposing that we are not returning
correct error type for Session getter.
https://github.com/web-platform-tests/wpt/pull/53735
3. Other trivial fix
Testing:
- `/webdriver/tests/classic/close_window/close.py` can now fully pass.
- `/webdriver/tests/classic/delete_session/*` can now fully pass.
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
Adding basic webdriver support to servoshell on ohos and basic
communication between the ohos device and script.
Testing: Manual testing and tracing logs
Signed-off-by: abdelrahman1234567 <abdelrahman.hossameldin.awadalla@huawei.com>
For current implementation, when a command may trigger a navigation,
webdriver only waits for document readiness state.
However, not all navigations make change in document.
This PR handles more cases for waiting for a navigation, and apply to
`element_click`.
- Before sending a command which may trigger a navigation, `webdriver`
sets `load status send` to `embedder`, `constelltation` and `script
thread` to listen to `navigation events`.
- Webdriver check if there is a navigation with `script thread`.
- If the navigation is loading a new url, webdriver checks if the
request is approved with `constellation`, then waits for document
readiness state.
- If the navigation is a hashchange, webdriver waits untill all new
generated dom events have been processed.
Testing:
`tests/wpt/tests/webdriver/tests/classic/element_click/navigate.py`
`tests/wpt/tests/webdriver/tests/classic/element_click/user_prompts.py`
https://github.com/longvatrong111/servo/actions/runs/16488690749
cc: @xiaochengh
---------
Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
Keep Constellation alive even when all browsing context closed in
WebDriver mode. In this case, when creating a new session, we would open
a new top-level browsing context.
Fixes: #37408
Testing: `./mach test-wpt -r
.\tests\wpt\tests\webdriver\tests\classic\close_window\close.py
--product servodriver`
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
- Implement [Maximize
Window](https://w3c.github.io/webdriver/#maximize-window)
- Previously, headless window screen size is same as inner size if not
specified in preference. We make it double as required by the test to
not have max window initially.
- Some other random cleanup.
Testing: webdriver Stress test for maximize window (headed + headless).
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
Cleaning up some dead code which has been here for 9 years. They are
never detected by Lint because we still initialize them as `None` but
never change afterwards.
Testing: No regression.
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Previously, we pretend we are able to set position in response. Now we
can really do it.
Testing: Able to set position accurately when tested locally.
Fixes: Task 5 of #37804.
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
`WebDriverCommandMsg::TakeScreenshot` was the last thing blocking us
from removing constellation access in webdriver server. Now we can
happily remove it.
Surprisingly, this reduces binary size by 185KB for release profile in
Windows. #37737 removes a net total of 300 lines, but only reduced 98KB.
Testing: No regression after testing.
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
Previously the webdriver do not wait for focus to complete, which can
cause some instability.
No matter interact as human or webdriver, the focus chain always goes
as: Embedder forwards -> Constellation (do some updates) -> Embedder (do
some updates).
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
- Add `handler any user prompt` step for all commands.
- Enable webdriver tests which were blocked by `handle any user prompt`
step.
---------
Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
1. Create `get_origin_relative_coordinates` according to
[spec](https://w3c.github.io/webdriver/#dfn-get-coordinates-relative-to-an-origin)
to be reused
2. Add previously missing offset for PointerOrigin::Element
3. Refactor code for perform pointermove/wheel to be closer to spec.
4. Handle some issues with spec:
https://github.com/w3c/webdriver/issues/1758
Testing: Several new passing cases as we are more precise with
coordinates now.
Fixes: Part of #38042.
---------
Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
After sending `GoBack` or `GoForward` command, webdriver wait for the
navigation complete.
It can be achieved by waiting for
`WebViewDelegate::notify_history_changed`
Testing:
`tests/wpt/meta/webdriver/tests/classic/back/back.py`
`tests/wpt/meta/webdriver/tests/classic/forward/forward.py`
---------
Signed-off-by: batu_hoang <longvatrong111@gmail.com>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Previously, we SendKeys will be forwarded to constellation by the
embedder. Now we use webview.notify_input_event, which will send
WebDriverCommandMsg::ForwardInputEvent for the KeyboardEvent and
CompositionEvent.
Fixes: part of https://github.com/servo/servo/issues/37370
---------
Signed-off-by: PotatoCP <kenzieradityatirtarahardja18@gmail.com>
Previously, we KeyboardAction will be forwarded to constellation by the
embedder. Now we use `webview.notify_input_event`, which will send
`WebDriverCommandMsg::ForwardInputEvent` for KeyboardAction
Fixes: part of https://github.com/servo/servo/issues/37370
---------
Signed-off-by: PotatoCP <kenzieradityatirtarahardja18@gmail.com>
1. Rename `GetWindowSize` to `GetWindowRect`
2. Return the WindowRect in device pixels correctly. Previously, it
returns `(0, 0, ScreenWidth, ScreenHeight)` which is a static value.
3. Add `fn window_rect` to `WindowPortsMethods`. Implement it for both
Headless Window and Headed Window.
Testing: Tested manually with powershell script. Result is now dynamic
and reflects the truth.
Fixes: Task 1 & 2 of https://github.com/servo/servo/issues/37804
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
1. Implement XPath Locator Strategy
2. Use it for "Find Element(s)", "Find Element(s) from Element", "Find
Element(s) from Shadow Root"
Testing: `tests\wpt\tests\webdriver\tests\classic\find_element*\find.py`
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
All "Find Element ..." in
[spec](https://w3c.github.io/webdriver/#find-element-from-element) has
exactly same step has "Find Elements ...", except they extract the first
element if there is any. We now reuse the handler instead of running
numerous repetitive steps, same as what we did for ["Find Element from
Shadow
Root"](https://w3c.github.io/webdriver/#find-element-from-shadow-root)
in #37578.
This reduces binary size by 98KB for Release profile in Windows and
improves maintainability.
Testing: `./mach test-wpt -r
.\tests\wpt\tests\webdriver\tests\classic\find_element* --product
servodriver`
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
1. Separate the handling of ["switch to parent
frame"](https://w3c.github.io/webdriver/#switch-to-parent-frame) from
the rest as the processing is a bit different
2. Implement "Select frame by 16-bits numbered ID" for ["switch to
frame"](https://w3c.github.io/webdriver/#switch-to-frame)
3. Implement other missing steps
Testing: All WebDriver Conformance test with new passing cases
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
- Move webdriver `GetViewportSize`, `LoadURL` and `Refresh` to
servoshell.
- Add `GoBack` and `GoFoward` commands.
Testing: Need to finish moving webdriver to servoshell then evaluate
again
Fixes: https://github.com/servo/servo/issues/37370
Signed-off-by: batu_hoang <longvatrong111@gmail.com>
Also renamed all "CSS" selector variants of `WebDriverScriptCommand` to
avoid confusion.
Testing: Mostly `./mach test-wpt -r
tests\wpt\tests\webdriver\tests\classic\find_*_from_shadow_root\find.py
--product servodriver`
But many other test also relies on finding element(s) from shadow root,
so I ran the entire test.
All deleted lines are from test expectations.
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
Implement action synchronization for wheel event. Previously only done
for pointer here https://github.com/servo/servo/pull/36932.
Testing:
`tests/wpt/meta/webdriver/tests/classic/perform_actions/wheel.py`
---------
Signed-off-by: PotatoCP <kenzieradityatirtarahardja18@gmail.com>
For WebDriver, return "No Such Window" properly according to spec.
Testing: `./mach test-wpt -r --log-raw "D:\servo test log\all.txt"
.\tests\wpt\tests\webdriver\tests\classic\ --product servodriver`
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
Remove `embedder/webdriver.rs::WebDriverCookieError` and use universal
`ErrorStatus` from webdriver crate. This is needed as we might need to
send back more universal error such as `NoSuchWindow`.
Testing: No behaviour change.
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
Implement Get Element Shadow Root
https://www.w3.org/TR/webdriver2/#dfn-get-element-shadow-root
cc: @xiaochengh, @yezhizhen, @PotatoCP
Testing:
`\tests\wpt\tests\webdriver\tests\classic\get_element_shadow_root\get.py`
is blocked by `no_browsing_context` and `closed_window`
pass for other sub-tests.
Signed-off-by: batu_hoang <longvatrong111@gmail.com>
We can now send keys to file input, which results in uploading file with
given filename. Needs
`pref=dom_testing_html_input_element_select_files_enabled` flag to work.
https://w3c.github.io/webdriver/#element-send-keys
Testing:
`tests/wpt/meta/webdriver/tests/classic/element_send_keys/{events,
file_upload}.py.`
Signed-off-by: PotatoCP <kenzieradityatirtarahardja18@gmail.com>
This change adds support for rendering static SVG images using the
`resvg` crate, allowing svg sources in the `img` tag and in CSS
`background` and `content` properties. There are some limitations in
using resvg:
1. There is no support for animations or interactivity as these would
require implementing the full DOM layer of SVG specification.
2. Only system fonts can be used for text rendering. There is some
mechanism to provide a custom font resolver to usvg, but that is not
explored in this change.
3. resvg's handling of certain edge cases involving lack of explicit
`width` and `height` on the root svg element deviates from what the
specification expects from browsers. For example, resvg uses the values
in `viewBox` to derive the missing width or height dimension, but
without scaling that dimension to preserve the aspect ratio. It also
doesn't allow overriding this behavior.
Demo screenshot:

<details>
<summary>Source</summary>
```
<style>
#svg1 {
border: 1px solid red;
}
#svg2 {
border: 1px solid red;
width: 300px;
}
#svg3 {
border: 1px solid red;
width: 300px;
height: 200px;
object-fit: contain;
}
#svg4 {
border: 1px solid red;
width: 300px;
height: 200px;
object-fit: cover;
}
#svg5 {
border: 1px solid red;
width: 300px;
height: 200px;
object-fit: fill;
}
#svg6 {
border: 1px solid red;
width: 300px;
height: 200px;
object-fit: none;
}
</style>
</head>
<body>
<div>
<img id="svg1" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
</div>
<div>
<img id="svg2" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
<img id="svg3" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
<img id="svg4" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
</div>
<div>
<img id="svg5" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
<img id="svg6" src="https://raw.githubusercontent.com/servo/servo/refs/heads/main/resources/servo.svg" alt="Servo logo">
</div>
</body>
```
</details>
---------
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Implement missing synchronization in `dispatch_actions` of `WebDriver`.
https://w3c.github.io/webdriver/#dispatching-actions
> The user agent event loop has spun enough times to process the DOM
events generated by the last invocation of the >[dispatch tick
actions](https://w3c.github.io/webdriver/#dfn-dispatch-tick-actions)
steps.
- Add a way for `ScriptThread` to notify `WebDriver` about the
completion of input commands.
- Add a `webdriver_id` field for `InputEvent`. `ScriptThread` uses it to
distinguish WebDriver events and sends notification.
Tests:
`./mach test-wpt --product servodriver -r
tests\wpt\tests\webdriver\tests\classic\element_click\events.py` pass if
`hit_testing` pass. Check
[issue](https://github.com/servo/servo/issues/36676#issuecomment-2882917136)
cc: @xiaochengh
---------
Signed-off-by: batu_hoang <longvatrong111@gmail.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>