Commit Graph
481 Commits
Author SHA1 Message Date
ZacharyZhang-NY 303a3aa926 fix: sync website color scheme 2026-07-10 17:31:10 -04:00
ZacharyZhang-NY 37eb0a7825 fix: coalesce queued scroll input 2026-07-10 17:17:34 -04:00
ZacharyZhang-NY c772e8ee46 feat(splits): activate the split-pane reload button 2026-07-10 16:56:50 -04:00
ZacharyZhang-NY c5890058db feat(reload): reload the active tab with Cmd/Ctrl+R 2026-07-10 16:55:25 -04:00
ZacharyZhang-NY a12b8c8bd8 fix(command): close the command overlay on Escape 2026-07-10 16:35:53 -04:00
ZacharyZhang-NY 18fe57ddc6 fix(servo): reconcile the loading state through redirects and pushState 2026-07-10 16:28:06 -04:00
ZacharyZhang-NY 650196e4e9 fix(downloads): open and reveal files on every platform 2026-07-10 16:17:34 -04:00
ZacharyZhang-NY 2cdad7461d fix(permissions): show only the site permissions Servo enforces 2026-07-10 16:11:57 -04:00
ZacharyZhang-NY d271670906 feat(settings): persist scalar settings across launches 2026-07-10 16:08:13 -04:00
ZacharyZhang-NY 324b0f1a6e fix(profiles): scope the sidebar to the active profile 2026-07-10 16:00:30 -04:00
ZacharyZhang-NY 4e460a51d7 fix(sync): keep sync owner first-claim-wins on Windows 2026-07-10 12:16:15 -04:00
ZacharyZhang-NY fd7f8c3ef0 feat(tabs): run the idle archive policy on a periodic sweep 2026-07-10 12:15:20 -04:00
ZacharyZhang-NY 175702e55a refactor(appearance): remove the decorative accent color row 2026-07-10 12:11:56 -04:00
ZacharyZhang-NY 7c5766137b fix(shortcuts): bind only the current platform's keys 2026-07-10 12:11:06 -04:00
ZacharyZhang-NY bfab49106d fix(tabs): keep the remembered active tab when closing a background tab 2026-07-10 12:09:30 -04:00
ZacharyZhang-NY bb16ed6fb3 feat(core): persist and restore browser state across launches 2026-07-10 12:01:43 -04:00
ZacharyZhang-NY dd0f84600d feat(spaces): make the Space accent real end to end 2026-07-10 11:45:08 -04:00
ZacharyZhang-NY e95177b3e6 refactor(settings): fold the read-only Advanced page into its owning sections 2026-07-10 11:40:09 -04:00
ZacharyZhang-NY b87f9ae2d4 refactor(privacy): drop the diagnostics reporting toggle until a reporter exists 2026-07-10 11:38:47 -04:00
ZacharyZhang-NY 07cd598f75 refactor(settings): remove the Updates page until an updater exists 2026-07-10 11:34:26 -04:00
ZacharyZhang-NY 73f52cdcb1 fix(sync): bound response reads to the snapshot wire limit 2026-07-10 11:21:10 -04:00
ZacharyZhang-NY c5c622f1b8 fix(tests): read complete requests in the snapshot conflict server 2026-07-10 10:48:41 -04:00
ZacharyZhang-NY 3be13ca295 fix(sync): bind browser data to one account owner 2026-07-10 10:46:52 -04:00
ZacharyZhang-NY 46eac43326 fix(auth): reconcile expired desktop sessions 2026-07-10 09:46:55 -04:00
ZacharyZhang-NY 2f346abaea fix(auth): revoke desktop sessions safely 2026-07-10 08:57:00 -04:00
ZacharyZhang-NY 94afa23a69 fix(auth): store bearer tokens in native credentials 2026-07-10 07:57:44 -04:00
ZacharyZhang-NY 540b901fd6 fix(sync): secure encrypted snapshot lifecycle 2026-07-10 06:24:53 -04:00
ZacharyZhang-NY 556c5ff624 fix(sync): enforce private profile boundaries 2026-07-10 03:02:10 -04:00
ZacharyZhang-NY e085174b89 fix(servo): gate vulnerable RSA private operations 2026-07-10 01:06:48 -04:00
ZacharyZhang-NY 58e9bd7d38 fix(servo): bound live request frames 2026-07-09 23:44:27 -04:00
ZacharyZhang-NY 83badaea81 fix(servo): bound live protocol metadata 2026-07-09 23:32:17 -04:00
ZacharyZhang-NY a6e3aeaf46 fix(navigation): classify HTTP schemes case-insensitively 2026-07-09 23:08:15 -04:00
ZacharyZhang-NY 755a6aabd8 fix(servo): lease persistent profile data 2026-07-09 23:05:10 -04:00
ZacharyZhang-NY 7d70db6da9 fix(sync): preserve private profile boundaries 2026-07-09 22:48:44 -04:00
ZacharyZhang-NY 31fc1acf17 fix(servo): retire sessions on internal navigation 2026-07-09 22:37:17 -04:00
ZacharyZhang-NY b422ac1631 fix(permissions): make profile snapshots authoritative 2026-07-09 21:56:36 -04:00
ZacharyZhang-NY c28ec2bee8 feat(servo): isolate profiles with hardware sidecars 2026-07-09 20:27:22 -04:00
ZacharyZhang-NY 78dc86b18e feat(servo): upgrade to latest secure upstream snapshot 2026-07-09 16:00:50 -04:00
ZacharyZhang-NYandClaude Opus 4.8 d150da5bd0 fix(servo): enable variable fonts so weight/width axes render
Like CSS Grid, Servo's `Preferences::default()` ships
`layout_variable_fonts_enabled: false`. `Servo::new` forwards it to Stylo
(`layout.variable_fonts.enabled`), and with the gate off Stylo ignores
`font-variation-settings` and variable weight/width axes: a variable font
renders only its default instance, so every requested weight looks
identical. Modern sites lean on variable fonts (Inter, Roboto Flex,
system New York/SF), so text rendered at the wrong weight versus Chrome.

servo-fonts already drives variations through HarfBuzz, so enabling the
pref is the real fix. Verified with a `@font-face` page using a variable
font at `font-variation-settings: "wght" 200` vs `"wght" 900`: identical
weight before, distinctly light vs black after.

runtime.rs 473 lines (<500). fmt/audit/clippy clean; software_host real-
Servo test passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 14:08:41 -04:00
ZacharyZhang-NYandClaude Opus 4.8 585cb25fe3 fix(domain): drop unwrap/panic from command tests for clippy gate
The workspace lints deny `clippy::unwrap_used` and `clippy::panic`, but
`command.rs`'s two unit tests used `.unwrap()` and `panic!`, so
`cargo clippy --workspace --all-targets -- -D warnings` (a CI gate)
failed on them. Convert both to the crate's Result-returning test
convention: `CommandIntent::parse(...)?` instead of `.unwrap()`, and a
`return Err(...)` in the let-else instead of `panic!`. Same assertions;
`DomainError` is `thiserror::Error`, so `?` flows into `Box<dyn Error>`.

Workspace clippy --all-targets now reports 0 errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:56:35 -04:00
ZacharyZhang-NYandClaude Opus 4.8 207eeaf54c style: drop stray blank lines left by the test-file splits
The `sed`-based extractions in the preceding three split commits each
left one extra blank line at the cut boundary, which `cargo fmt --all
--check` (a CI gate) rejects. Whitespace only — no code change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:53:41 -04:00
ZacharyZhang-NYandClaude Opus 4.8 7fc73e6ac8 refactor(shell): split web_surface_live_site_tests under 500-line audit
`web_surface_live_site_tests.rs` (648, behind the `live-site-smoke`
feature) was the last file over the audit ceiling. Its helpers split
cleanly one-directionally: drivers/waiters call the leaf
validators/builders, never the reverse.

Keep imports, consts, the 6 tests, `run_isolated_live_site_test`, the
`assert_*` drivers, `render_web_surface_frame`, and the `wait_for_*`
helpers in the parent; move the leaf validators + pure fixtures
(`ExpectedCssViewport`, `validate_prd_frame*`, `log_prd_frame`,
`require*`, `*_bounds`, `live_scroll_point`, `web_tab`, `normalized_url`)
into `web_surface_live_site_support.rs` as `pub(super)` items, opened
with `use super::*;`. Parent pulls them back via `use ...support::*`.

470 / 184 lines. `cargo build/clippy -p ely_app --tests --features
live-site-smoke -- -D warnings` clean. scripts/audit_source_lines.sh now
exits 0 (every source file <= 500).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:51:42 -04:00
ZacharyZhang-NYandClaude Opus 4.8 de413f8f46 refactor(shell): split 1062-line gpui_harness_tests god-component
`gpui_harness_tests.rs` was the repo's largest file (1062 lines) and the
worst violator of the 500-line / no-god-component audit. Its 13
`#[gpui::test]`s each build their own local fixtures and share only a
pair of type aliases, an `impl super::ElyShell` test helper, and two free
fns (`active_tab_overlay_state`, `example_url`).

Keep those shared items plus tests 1-4 in the root module; move tests 5-8
to `gpui_harness_tests_b.rs` and tests 9-13 to `gpui_harness_tests_c.rs`,
each opening with `use super::*;` so they inherit the parent's imports
and shared items with no per-item churn. Declared via `#[path]` mod, the
established sibling-test pattern in this crate.

475 / 319 / 276 lines. No tests added, removed, or renamed (paths gain a
`gpui_harness_tests_{b,c}::` segment). clippy --all-targets -D warnings
clean; `cargo test -p ely_app` 167 passed / 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:47:51 -04:00
ZacharyZhang-NYandClaude Opus 4.8 66e5b266e9 refactor(core): split oversized integration-test files under 500-line audit
`scripts/audit_source_lines.sh` (a CI gate) flagged `tests/commands.rs`
(527) and `tests/splits.rs` (524) over the 500-line ceiling. Both are
flat lists of independent `#[test]` fns with no shared helpers, so each
splits cleanly into a sibling integration-test binary (the crate already
uses a topical file-per-concern layout under `tests/`).

- commands.rs (29 tests) -> commands.rs (20: tab/space/profile/search)
  + command_pages.rs (9: internal-page-opening commands). 527 -> 389.
- splits.rs (25 tests) -> splits.rs (13: layout/axis/detach mechanics)
  + saved_split_lifecycle.rs (12: close/archive/restore/group). 524 -> 266.

No tests added or removed; each new file carries only the imports it
uses. `cargo clippy -p ely_browser_core --tests -- -D warnings` clean;
all ely_browser_core tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:34:56 -04:00
ZacharyZhang-NYandClaude Opus 4.8 b1fd8ab3f8 refactor(servo): extract paint coordination into runtime_paint
`runtime.rs` had grown past the 500-line ceiling enforced by
`scripts/audit_source_lines.sh` once the grid-pref comment landed (522
lines). Peel the repaint/present pair — `paint_without_readback`,
`paint_without_readback_with_completion`, the private `paint_webview`,
and `paint_with_readback` — into a sibling `runtime_paint.rs`, exactly
the `paint.rs` boundary the embedding architecture doc prescribes.

`runtime_paint` is a child module of `runtime` (declared via `#[path]`,
mirroring `runtime_context`), so it keeps access to the private
`SoftwareServoHost` fields and the `webview()` / `wait_for_paint_completion`
/ `read_rendered_frame` helpers without widening any visibility. No
behaviour change: public API and call sites are identical.

runtime.rs 522 -> 469 lines. Build + clippy clean; full workspace test
suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:17:00 -04:00
ZacharyZhang-NYandClaude Opus 4.8 3d36cb25bf fix(servo): enable CSS Grid so grid layouts stop collapsing
`Preferences::default()` is Servo's conservative library default and
ships `layout_grid_enabled: false`. `Servo::new` forwards prefs to Stylo
(`prefs::set` -> `stylo_static_prefs::set_pref!("layout.grid.enabled")`),
so with the gate off Stylo blockifies `display: grid`: every grid
container collapses to `display: block` and grid-based page layouts
stack into a single column — the "broken" rendering reported on modern
sites.

`ely_servo_preferences()` only flipped `dom_intersection_observer_enabled`
and inherited the grid default, so ELY rendered grid pages collapsed
while Servo's own servoshell (which enables the pref) renders them
correctly. The layout path is implemented — servo-layout drives
`DisplayInside::Grid` through Taffy — so enabling the pref is the real
fix, not a workaround.

Verified with a deterministic `display: grid; grid-template-columns:
1fr 1fr 1fr` page: 9 stacked full-width bars before, a 3x3 grid after.
Wikipedia/HN/GitHub/google.com re-checked unchanged; full workspace
test suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:07:50 -04:00
ZacharyZhang-NY aa8182bec4 update 2026-05-21 15:44:26 -04:00
ZacharyZhang-NY 7fc2967793 fix(servo): skip WebView::load when Servo already at requested URL
Servo's \`WebView::set_history\` fires \`notify_url_changed\` on **every**
history mutation — full navigations, redirects, in-page link clicks,
and JS-driven \`history.pushState\` / \`history.replaceState\`.

Our pipeline fans that delegate signal back through
\`WebSurfaceUrlChange\` into \`tab.url\`. The next \`ensure_surface\`
observes the new tab URL, hashes a fresh ensure key, and calls
\`ServoLiveClient::ensure\` → \`apply_navigation\`. Until this commit
\`apply_navigation\` compared the request against the local
\`session.requested_url\` cache and, on mismatch, sent Servo a
\`webview.load(url)\` — even when Servo was the one who *just*
told us about that URL.

\`WebView::load\` is a hard navigation: it tells the constellation
to abort the current document, clear the surface, and refetch.
google.com's homepage \`replaceState\`s a fresh \`?zx=<timestamp>\`
roughly once a second to bust caches; with this round-trip we
were turning each of those into a full load-clear-refetch and
producing one visible white flash per second.

Use \`host.snapshot(webview_id).url()\` (which Servo keeps in lock-step
with \`set_history\`) as the source of truth. If Servo's WebView is
already at the requested URL, just sync our \`session.requested_url\`
bookkeeping and return — no \`load\` message, no surface clear, no
flash. Genuine embedder-initiated navigations (chrome URL bar typed,
in-app link click) still take the \`should_navigate\` path because
Servo's URL hasn't caught up to the requested target yet.
2026-05-18 15:46:18 -04:00
ZacharyZhang-NY 0a97c4af13 fix(servo): stop forcing paint+present on every ensure
Servo's reference embedder (\`examples/winit_minimal.rs\`) is reactive:

  - \`user_event\` only calls \`servo.spin_event_loop()\` — never paints
  - \`notify_new_frame_ready\` is what flips the embedder into the
    redraw path (calls \`window.request_redraw()\`)
  - \`RedrawRequested\` is the **single** site that runs
    \`webview.paint() + rendering_context.present()\`

Painting is therefore at-most-once-per-real-frame: a paint happens
only when Servo has actually composited new content.

Our \`ServoLiveClient::ensure\` was forcing
\`paint_without_readback_with_completion\` after every setup pass.
\`ensure\` runs on every \`ensure_surface\` invocation — viewport
debounce settle, URL redirect (google.com → / → /?zx=…), permission
update, native-surface re-attach, page-zoom change. Each invocation
called Servo's painter while it had no new composited frame ready:
WebRender's \`clear_background\` wiped the surface to the configured
shell background colour, the empty scene rendered, \`present\` swapped
that blank surface to the NSView's CALayer — and the user saw a
white flash. A chain of redirects produced a chain of flashes.

Drop the unconditional \`paint\` from \`ensure\`. Keep the
\`host.tick()\` (Servo's spin) so the navigate / viewport / input
messages reach the constellation in this turn, but defer painting to
\`poll\`, which already gates \`paint_without_readback_with_completion\`
on \`snapshot.has_pending_frame()\` — exactly mirroring the
reference embedder's reactive model. \`ServoLiveFrame\` returned from
\`ensure\` only carries snapshot metadata, so callers that depend on
the frame value (worker queue, UI state) are unaffected.
2026-05-18 15:39:14 -04:00
ZacharyZhang-NY d1e811b724 fix(servo): resize through WebView only, never the rendering context
Servo's reference embedder (\`examples/winit_minimal.rs\`) handles
resize with a single call: \`webview.resize(new_size)\`. The Servo
paint pipeline behind that call:

  1. early-returns if \`rendering_context.size() == new_size\`,
  2. otherwise calls \`rendering_context.resize\` itself,
  3. updates \`webview_renderer.rect\` so the compositor relays out
     the page at the new device viewport,
  4. sends \`transaction.set_document_view(...)\` so WebRender's
     document viewport matches the surface,
  5. flags the painter \`needs_repaint(RepaintReason::Resize)\`.

Our \`runtime.rs::resize\` called \`webview.rendering_context.resize\`
*before* \`webview.webview.resize\`. surfman accepted the new size, so
the painter saw \`rendering_context.size() == new_size\` and took the
early-return path — steps 3, 4, and 5 never ran. The compositor
kept the original (creation-time) viewport rect while we presented
a much larger surface. The page ended up laid out for a tiny
viewport and either rendered into the top-left of a sea of cleared
background (StableLance) or never painted any pipeline at all
(google.com appeared totally blank).

Drop the direct \`rendering_context.resize\` call and route through
\`WebView::resize\` exactly as the reference embedder does. The
debounce in \`record_viewport_size\` still collapses a sidebar /
window-edge animation into a single trailing-edge resize, so we
also avoid hammering Servo with per-frame surface mutations.
2026-05-18 15:30:55 -04:00