Commit Graph
346 Commits
Author SHA1 Message Date
ZacharyZhang-NY 2cdad7461d fix(permissions): show only the site permissions Servo enforces 2026-07-10 16:11:57 -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 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 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 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 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 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-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 3678db60b9 fix(shell): clip native_surface overlay to its panel's corner radius
The web canvas is a GPUI `native_surface` element, which on macOS
attaches an `NSView` (with a Metal-backed `CALayer`) as an AppKit
overlay on top of the GPUI render layer. GPUI's `overflow: hidden`
clips its own children but cannot reach into AppKit, so the canvas
painted square corners on top of the main panel's rounded edge —
the white surface visibly overshot the panel's rounded bottom.

Thread a per-corner radius through the GPUI patch:

- `Window::sync_native_surface` and the `PlatformWindow` trait carry
  a `Corners<Pixels>`.
- The macOS implementation sets `CALayer.cornerRadius` to the maximum
  requested radius and `maskedCorners` to the bitmask of corners that
  actually requested rounding (GPUI is Y-down while NSView is Y-up,
  so a GPUI "top" maps to a CALayer "MaxY" corner — comment locks
  the mapping). `setMasksToBounds: YES` lets Core Animation actually
  honor the corner radius for layered content.
- The `NativeSurface` element resolves all four corner radii from its
  own `StyleRefinement` (so callers attach `.rounded_bl(...)` /
  `.rounded_br(...)` exactly as on any other GPUI element).

Application side wires the right radius per context:

- The main canvas asks for `RADIUS_CARD` (18 px) on its bottom corners
  so it follows the surrounding panel's rounded bottom edge while
  the top stays flush against the toolbar.
- A split pane's canvas asks for the pane's own `SPLIT_PANE_RADIUS`
  (10 px) so the canvas hugs the rounded frame the pane already paints.

`render_failed_web_surface` doesn't need rounding wiring — the error
page is a GPUI div and is clipped normally by the surrounding
`overflow: hidden`.
2026-05-18 15:07:53 -04:00
ZacharyZhang-NY 8aa9ddaeb2 fix(shell): debounce viewport resize so animations stop flashing
Sidebar / window-edge animations emit a new viewport bounds on every
GPUI paint. The previous flow fired `runtime.ensure_tab` synchronously
on every change, which reached down into Servo's surfman backend and
destroyed + reallocated the rendering framebuffer 50+ times per second
— each cycle leaving the NSView with an empty surface until Servo's
next paint completed. The user saw the page strobe blank-then-content
on every gesture, plus a one-time Metal driver warning about an
unloadable texture (the previous framebuffer caught mid-recreate).

Track `viewport_size_changed_at` on `PerTabSurface` and propagate the
debounce on two seams:

- `record_viewport_size` returns `Buffered` for a transition that
  arrives inside the 80 ms window of the previous one, so the
  synchronous `flush_external_web_surface_tick` from the GPUI paint
  callback skips the resize altogether. The very first measurement
  and the first transition after a quiet period still return `Applied`
  so a single drag step or page-load is not delayed.
- `ensure_surface` skips while the viewport is settling, but only
  *after* the initial ensure has installed `last_ensure_key`. The
  first ensure must fire even mid-gesture or the page never loads.
- `next_tick_delay` clamps the poll cadence to `ACTIVE_POLL_INTERVAL`
  while any visible tab is settling, so the trailing-edge resize
  fires within a frame of the gesture stopping instead of waiting
  for an 80 ms idle tick.

The synchronous `record + ensure` pattern in
`failed_surface_ensure_waits_for_a_new_key_before_retrying` can't
advance an `Instant`, so it now calls a `#[cfg(test)]`
`clear_viewport_resize_debounce_for_test` to simulate the
trailing edge and exercise the retry-on-new-key business rule in
isolation. Adds `rapid_viewport_changes_buffer_until_gesture_settles`
to lock the new behaviour.
2026-05-18 14:53:56 -04:00
ZacharyZhang-NY fc1c0ed8d3 refactor(shell): peel session + wire helpers off WebSurfaceRuntime
web_surface_runtime.rs hit 628 lines because it carried four unrelated
concerns:

- session domain types (`WebSurfaceRuntimeScope`, `WebSurfaceSession`,
  `WebSurfaceUrlChange`, …) and their config-dir / `session_for_scope`
  helpers — these are the runtime's input vocabulary, not its control
  flow.
- wire-side glue (scroll-input field marshalling, `pending_input_kind`
  classifier, the latency tracing call, and the `From<&Site...>` impl
  that lowers permissions to the Servo client) — these are the runtime's
  output vocabulary.
- the runtime itself, plus its tests harness.

Split into:
- `web_surface_runtime.rs` (441 lines): WebSurfaceRuntime + Drop.
- `web_surface_runtime_session.rs`: the session types + helpers, with
  `pub(super)`-exposed methods so the runtime can drive them.
- `web_surface_runtime_wire.rs`: the wire helpers and the From impl.

`web_surface_runtime` keeps re-exporting the URL-change / frame /
ensure-result types so existing call sites
(`web_surface_state.rs`, `web_surface.rs`, `web_surface_controller.rs`)
need no rewiring.
2026-05-18 14:28:57 -04:00
ZacharyZhang-NY dabb965afd refactor(shell): peel input recorders off WebSurfaceStore
`web_surface.rs` had crept to 548 lines; six unrelated input-recorder
methods (scroll delta, viewport size, native surface, hover point,
click point, typed text) dominated the file. Move them into a sibling
`web_surface_input.rs` so the store file (now 338 lines) is the
ensure / tick / lifecycle facade and the input file is a flat set of
`record_*` methods on the same struct.

`surfaces`, `keyboard_focus`, and `surface_mut` become `pub(super)` so
the sibling can reach them; everything else stays private.
2026-05-18 14:24:52 -04:00
ZacharyZhang-NY 4cbd1c8870 test(servo): pin DPR-on-first-apply contract with viewport diff
Lift `apply_viewport`'s three-way diff (resize / set_hidpi / set_zoom)
into a `ViewportChange` value so the decision is testable without a
running `SoftwareServoHost`. Four unit cases pin the contract:

- Retina creation (DPR=2.0): only the hidpi push fires (the bug above).
- Standard-DPI creation (DPR=1.0): nothing to push, session already
  matches Servo's defaults.
- Mid-session zoom change: only `set_page_zoom` fires.
- Cross-monitor DPR change: only the hidpi push fires.

This is a regression guard for the previous commit — any future change
that re-initializes a session from request values instead of Servo's
post-build defaults will fail `fresh_retina_session_pushes_hidpi_only`.
2026-05-18 14:14:04 -04:00
ZacharyZhang-NY a067d62ad3 fix(servo): push DPR on first viewport apply
The newly-created session was stamped with the request's hidpi factor,
but `WebViewBuilder` defaults `hidpi_scale_factor` to 1.0 and we never
override it. `apply_viewport`'s diff check then saw
`session.dpr == request.dpr` and skipped `set_hidpi_scale`, leaving Servo
at hidpi=1.0 forever. On Retina that collapses CSS pixels onto device
pixels — the page lays out for a 2× viewport and renders at half size.
Same shape applies to page zoom.

Initialize the session with Servo's actual post-build defaults so the
viewport diff is the source of truth for whether `set_hidpi_scale` and
`set_page_zoom` need to run.
2026-05-18 14:12:18 -04:00
ZacharyZhang-NY 68a4507dbe update 2026-05-18 13:58:36 -04:00
ZacharyZhang-NY d076dad356 Fix shell regressions and reset Servo embedding direction 2026-05-16 11:23:41 -04:00
ZacharyZhang-NY 973fd0a582 feat(app): animate sync toggle motion 2026-05-16 05:27:24 -04:00
ZacharyZhang-NY 0c9bfc2673 perf(sync): avoid snapshot clone when scheduling uploads 2026-05-16 05:19:54 -04:00
ZacharyZhang-NY 51f836f34c feat(sync): auto upload changed browser state 2026-05-16 05:13:19 -04:00
ZacharyZhang-NY 0d755af005 perf(app): suppress repeated web metadata updates 2026-05-16 05:03:43 -04:00
ZacharyZhang-NY df092f285c perf(app): defer web poll after ensure 2026-05-16 04:40:34 -04:00
ZacharyZhang-NY 654f661237 perf(app): skip unchanged software web frames 2026-05-16 04:36:49 -04:00
ZacharyZhang-NY 91df575cf8 perf(app): batch scroll surface flushes 2026-05-16 04:23:49 -04:00
ZacharyZhang-NY 0c733fa006 perf(app): settle web cadence on visible load frames 2026-05-16 04:16:12 -04:00
ZacharyZhang-NY 168c60bf2a perf(app): settle web poll cadence after load 2026-05-16 04:13:20 -04:00
ZacharyZhang-NY 99d54a7089 perf(app): idle repeated terminal web states 2026-05-16 04:06:41 -04:00
ZacharyZhang-NY 372c29f2c3 perf(app): stop extending loading poll bursts 2026-05-16 04:01:43 -04:00
ZacharyZhang-NY 8c2dffddc7 fix(sync): run initial upload for signed-in profiles 2026-05-16 03:50:16 -04:00
ZacharyZhang-NY 93c2b3636c perf(app): skip iosurface scans on ui thread 2026-05-16 03:25:35 -04:00
ZacharyZhang-NY 54fcce29f3 perf(app): gate payloadless surfaces on app imports 2026-05-16 03:17:45 -04:00