-
Notifications
You must be signed in to change notification settings - Fork 32
vaev-webdriver: Intial implementation of webdriver2. #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a complete WebDriver 2 protocol implementation in C++ directly integrated with the Vaev engine, replacing the previous implementation. The new implementation adds support for PDF printing, page source retrieval, and full session handling.
- Adds new C++ WebDriver service with HTTP endpoints for the WebDriver 2 protocol
- Implements core WebDriver functionality including sessions, navigation, window management, and screen capture
- Adds HTML fragment serialization support for retrieving page source
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/vaev-webdriver/service.cpp | Implements HTTP service endpoints for WebDriver 2 protocol (sessions, navigation, contexts, screenshots, printing) |
| src/vaev-webdriver/protocol.cpp | Defines WebDriver protocol types and helper functions for success/error responses |
| src/vaev-webdriver/driver.cpp | Core WebDriver logic handling sessions, windows, navigation, and document operations |
| src/vaev-webdriver/mod.cpp | Module exports for the WebDriver implementation |
| src/vaev-webdriver/manifest.json | Component manifest declaring vaev-engine dependency |
| src/vaev-webdriver/main/manifest.json | Executable manifest for WebDriver server |
| src/vaev-webdriver/main/main.cpp | Entry point for WebDriver server with CLI option parsing |
| src/vaev-engine/style/specified.cpp | Changes opacity field from f16 to f32 for compatibility |
| src/vaev-engine/style/media.cpp | Adds viewportSize() helper method to Media struct |
| src/vaev-engine/dom/window.cpp | Adds refreshAsync() method and refactors viewport size usage |
| src/vaev-engine/dom/serialisation.cpp | Implements HTML fragment serialization per WHATWG spec |
| src/vaev-engine/dom/names.cpp | Adds documentation comment for namespace serialization logic |
| src/vaev-engine/dom/mod.cpp | Exports new serialisation module |
| src/vaev-engine/dom/element.cpp | Adds isVoidElement() method for HTML void element detection |
Louciole
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i let you fishish the TODO's but overall it looks good, I didn't see big loopholes, well done it's great !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 14 out of 15 changed files in this pull request and generated 17 comments.
| 27.94 | ||
| }; | ||
| Math::Insetsf margins = 1.0; | ||
| Vec<urange> pageRanges{}; |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pageRanges field is defined but never used in the toNative() method or populated in service.cpp. Either implement support for page ranges or remove this field if it's not yet supported.
| Vec<urange> pageRanges{}; |
|
|
||
| [[clang::coro_wrapper]] | ||
| Async::Task<> refreshAsync() { | ||
| return loadLocationAsync(document()->url()); |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential null pointer dereference. The upgrade() call on a weak pointer in refreshAsync() (line 68) could return null if the document has been destroyed. Add error handling to check if the upgrade succeeds before calling url() on it.
| return loadLocationAsync(document()->url()); | |
| auto doc = document(); | |
| if (!doc) { | |
| co_return Error::invalidState("No document to refresh"); | |
| } | |
| co_return co_await loadLocationAsync(doc->url()); |
| if (auto isValue = el->getAttribute(Html::IS_ATTR)) { | ||
| e(" is=\""); | ||
| escapeString(e, isValue.unwrap(), true); | ||
| e("\""); | ||
| } | ||
| // - For each attribute: | ||
| for (auto& [name, attr] : el->attributes.iterUnordered()) { | ||
| if (name == Html::IS_ATTR) | ||
| continue; | ||
| // Append space, attribute’s serialized name, "=", quote, escaped value, quote. | ||
| e(" {}=\"", name); | ||
| escapeString(e, attr->value, true); | ||
| e("\""); | ||
| } |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incomplete attribute handling logic. On line 105, the code checks for the is attribute value but then inside the loop on line 112 it skips the is attribute if it's in the attributes map. However, if getAttribute returns a value on line 105, that same attribute should still be in the attributes map, leading to redundant attribute output or skipping. The logic should be clarified to avoid potential duplicate attribute serialization.
| } else { | ||
| co_return Error::invalidInput("unsupported intent"); | ||
| } | ||
|
|
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty line at the beginning of the scope should be removed according to coding guidelines.
| // Let marginRight be the result of getting a property with default named "right" and with a default of 1 from margin. | ||
| auto marginRight = margin.getOr("right", 1); | ||
|
|
||
| // If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less then 0, return error with error code invalid argument. |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment: "then" should be "than". The correct phrase is "less than".
| // If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less then 0, return error with error code invalid argument. | |
| // If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less than 0, return error with error code invalid argument. |
| // TODO | ||
|
|
||
| // Let background be the result of getting a property with default named "background" and with default false from parameters. | ||
| auto background = parameters.getOr("background", false); | ||
|
|
||
| // If background is not a Boolean return error with error code invalid argument. | ||
| // TODO | ||
|
|
||
| // Let page be the result of getting a property with default named "page" and with a default of an empty Object from parameters. | ||
| auto page = parameters.getOr("page", Serde::Object{}); | ||
|
|
||
| // Let pageWidth be the result of getting a property with default named "width" and with a default of 21.59 from page. | ||
| auto pageWidth = page.getOr("width", 21.59); | ||
|
|
||
| // Let pageHeight be the result of getting a property with default named "height" and with a default of 27.94 from page. | ||
| auto pageHeight = page.getOr("height", 27.94); | ||
|
|
||
| // If either of pageWidth or pageHeight is not a Number, or is less than (2.54 / 72), return error with error code invalid argument. | ||
| // TODO | ||
|
|
||
| // Let margin be the result of getting a property with default named "margin" and with a default of an empty Object from parameters. | ||
| auto margin = parameters.getOr("margin", Serde::Object{}); | ||
|
|
||
| // Let marginTop be the result of getting a property with default named "top" and with a default of 1 from margin. | ||
| auto marginTop = margin.getOr("top", 1); | ||
|
|
||
| // Let marginBottom be the result of getting a property with default named "bottom" and with a default of 1 from margin. | ||
| auto marginBottom = margin.getOr("bottom", 1); | ||
|
|
||
| // Let marginLeft be the result of getting a property with default named "left" and with a default of 1 from margin. | ||
| auto marginLeft = margin.getOr("left", 1); | ||
|
|
||
| // Let marginRight be the result of getting a property with default named "right" and with a default of 1 from margin. | ||
| auto marginRight = margin.getOr("right", 1); | ||
|
|
||
| // If any of marginTop, marginBottom, marginLeft, or marginRight is not a Number, or is less then 0, return error with error code invalid argument. | ||
| // TODO | ||
|
|
||
| // Let shrinkToFit be the result of getting a property with default named "shrinkToFit" and with default true from parameters. | ||
| auto shrinkToFit = parameters.getOr("shrinkToFit", true); | ||
|
|
||
| // If shrinkToFit is not a Boolean return error with error code invalid argument. | ||
| // TODO | ||
|
|
||
| // Let pageRanges be the result of getting a property with default named "pageRanges" from parameters with default of an empty Array. | ||
| // TODO | ||
|
|
||
| // If pageRanges is not an Array return error with error code invalid argument. | ||
| // TODO |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple TODO comments mark unimplemented validation checks (lines 462, 468, 480, 498, 504, 510). According to coding guidelines, TODO should only be added if there's a plan to address it in a future PR. Consider either implementing the validation now or converting these to NOTE comments with an explanation of why validation is deferred.
| auto window = try$(session->currentBrowsingContext()); | ||
|
|
||
| // 3. Let title be the session's current top-level browsing context's active document's title. | ||
| return Ok(window->document().upgrade()->title()); |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential null pointer dereference. The upgrade() call on a weak pointer could return null if the document has been destroyed. Add error handling to check if the upgrade succeeds before calling title() on it.
| return Ok(window->document().upgrade()->title()); | |
| auto doc = window->document().upgrade(); | |
| if (not doc) | |
| return Error::invalidInput("document destroyed"); | |
| return Ok(doc->title()); |
| if (eqCi(Str(#VALUE), name)) \ | ||
| return Symbol::from(Str(#VALUE)); | ||
| #include "defs/ns-svg-attr-names.inc" | ||
|
|
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty line added at beginning of scope. According to coding guidelines, empty lines at the beginning of scopes should be removed.
| if (eqCi(Str(#VALUE), name)) \ | ||
| return Symbol::from(Str(#VALUE)); | ||
| #include "defs/ns-svg-tag-names.inc" | ||
|
|
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty line added at beginning of scope. According to coding guidelines, empty lines at the beginning of scopes should be removed.
| } else if (ns == MathMl::NAMESPACE) { | ||
| displayNamespace = "mathml"; | ||
| } | ||
|
|
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty line added at beginning of scope. According to coding guidelines, empty lines at the beginning of scopes should be removed.
d0ae01a to
934a74e
Compare
This rewrites the WebDriver in C++ to integrate it directly with the engine.
It now supports everything the previous implementations did. Plus PDF printing, retrieving the page source, and full session handling.