Wire browser cookies, storage, tabs, scripts, styles, highlight#27
Draft
mvbmir wants to merge 4 commits into
Draft
Wire browser cookies, storage, tabs, scripts, styles, highlight#27mvbmir wants to merge 4 commits into
mvbmir wants to merge 4 commits into
Conversation
Adds tier 3 of the browser dispatcher: login persistence via a
persistent cookie store plus programmatic session export/import.
Persistent cookies:
The NetworkSession's CookieManager is now backed by a sqlite file at
$XDG_DATA_HOME/limux/cookies.sqlite. All cookies (including HttpOnly)
are persisted automatically, so logins survive limux relaunches
without any explicit save/load — open a site, log in, relaunch,
you're still logged in.
New methods wired via build_browser_script:
browser.cookies.get — list same-origin script-visible cookies
browser.cookies.clear — expire by name or all
browser.storage.local.get — fetch one key or all items
browser.storage.local.set
browser.storage.local.clear
browser.storage.session.{get, set, clear}
browser.state.save — bundle visible cookies + localStorage +
sessionStorage as JSON for export
browser.state.load — apply a bundle back to the current page
HttpOnly cookies are intentionally invisible to document.cookie (that's
the point of the flag), so cookies.get and state.save only surface
script-visible cookies. This is fine for the intended use case: the
sqlite store handles the authentication tokens transparently, while
save/load covers programmatic session setup for testing scenarios.
Adds tier 4 of the browser dispatcher: tab management, persistent
script/style injection, and visual highlight.
Tab management:
browser.tab.list — list every surface in a pane
browser.tab.new — open a browser tab inside an existing pane
browser.tab.switch — activate a specific surface by id
browser.tab.close — close a specific surface by id
Where browser.open_split creates the browser in a sibling pane (or
splits to make one), browser.tab.new stays in the caller's pane —
useful for stacking multiple browser tabs in one workspace slot.
Injection:
browser.addscript — run arbitrary JS in the current page (alias
for browser.eval without the JSON-reply
wrapping contract)
browser.addinitscript — install a UserScript that webkit re-injects
on every top-frame navigation; use for
ref taggers, console shims, auth bootstraps
that must survive SPA route changes
browser.addstyle — install a UserStyleSheet that persists
across navigations
Both injection variants use webkit6::UserContentManager with
InjectedFrames::TopFrame so iframes stay untouched (consistent with
the built-in limux init script's scope).
Visual:
browser.highlight — pulse a 3px magenta outline on the target
element for N ms; used for debugging ref
resolution ("is @e7 really the button I
think it is?")
Iframe scope methods (browser.frame.main / browser.frame.select) are
deferred — they require per-surface scope tracking that isn't needed
by any current workflow.
evaluate_javascript can't await Promise return values — it returns "Unsupported result type" for any async IIFE. Switching to call_async_javascript_function makes webkit auto-await the script before returning the jsc::Value, so async helpers are now viable. Trailing semicolons on expression-style scripts are stripped before wrapping, otherwise `(() => ...)();` would become `return (...;);` and SyntaxError at the JS side. Result conversion falls back to to_json when to_str yields an empty string or "[object Promise]", so non-string return values surface through the bridge cleanly. No user-facing methods change in this commit. This is infra for the upcoming navigate_and_wait / click_and_await_nav / fill_and_submit primitives, which will arrive once they're reimplemented as Rust-side orchestrators (location.href and el.click() both destroy the async JS context mid-await, so those flows have to coordinate via the load-changed signal rather than a single evaluate roundtrip).
a544268 to
399dd40
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #25 (Wire pane/browser control dispatcher). Adds tiers 3, 4, and evaluate_javascript infra on top of the snapshot/action/console baseline.
T3: cookies, storage, state (login persistence)
Persistent cookie store enabled by default. `NetworkSession::cookie_manager` now writes to `$XDG_DATA_HOME/limux/cookies.sqlite`, so logins survive limux relaunches without any explicit save/load — all cookies including HttpOnly persist transparently.
New methods:
T4: tabs, scripts, styles, highlight
Tab management (fills the gap between `browser.open_split` which creates sibling-pane surfaces and the tab-strip inside each pane):
Persistent injection via webkit's `UserContentManager`:
Debug helper:
T5: async-eval infra
`evaluate_javascript` doesn't await Promise returns and surfaces "Unsupported result type" for async IIFEs. Switched to `call_async_javascript_function` so webkit awaits the script before returning the jsc::Value. Trailing semicolons stripped before wrapping as `return (...);` to avoid spurious SyntaxErrors.
This is infra only — it unblocks future high-level primitives (`navigate_and_wait`, `click_and_await_nav`, `fill_and_submit`). Those flows can't complete inside a single evaluate roundtrip because `location.href` and `el.click()` both destroy the async JS context mid-await, so they'll arrive as Rust-side orchestrators using webkit's `load-changed` signal.
Test plan