feat(browser): redesigned interface, tabs, settings and saved bookmarks #164

Open
nonos-sync wants to merge 16 commits from nonos-sync/gh-621 into main AGit
Member

Summary

A redesign of the browser's interface (userland/capsule_browser), plus the persistence and small fixes it needed. The network stack is not changed.

Interface

  • Light and dark themes, dark by default. Switchable in Settings and saved.
  • Rounded address pill, vector icons with anti-aliased edges, and a route badge (Mixnet / Anyone / Direct).
  • Titlebar tabs. Every tab keeps loading in the background (Vec<Box<State>>; per-tab process globals are swapped in tab_scope.rs).
  • Sidebar (full or rail), start page, and pages for history, bookmarks, downloads and tabs. Named tab groups and a reader view.
  • Full Settings page: appearance, network route, SOCKS5 proxy, search engine (DuckDuckGo or a custom %s template), privacy and data, downloads, reader, about.

Storage

  • The browser now requires FileSystem: CAPSULE_REQUIRED_CAPS goes from 0x183d to 0x187d, in both Capsule.mk and spawn.rs. The README and docs/using/browser.md are updated to match.
  • Bookmarks, groups, reader settings, the theme and the search template are kept in /home/.browser/state.bin (NBR1 v1 record; new sections are appended). History stays in RAM only.
  • Downloads are saved to /home/Downloads.
  • The record is written at a fixed 32 KiB. The disk store only overwrites a kept file with bytes of the same length, so a record that grows would otherwise never be saved again.
  • The file is unlinked before each write, so it is recreated as the browser's own. Files restored at boot have owner 0, and the vfs refuses to persist them otherwise.

Fixes

  • fix(qjs): event listeners are scoped to the JS context that registered them and released when it is freed, since each tab runs its own context.
  • The page is painted into the content rect; the stale 28 px titlebar offset is removed.
  • A page that fails to load no longer keeps the previous page's title, so a bookmark of it isn't filed under the wrong name.
  • A leading www. is skipped when picking a site's tile letter.

Testing

  • Host proofs (capsule_browser_proofs): 703 tests pass, and the library clippy (the CI gate for this crate) is clean. New tests cover the record format, fixed-size padding and dropping the oldest bookmarks when full.
  • Capsule cargo check for the user target is at its baseline of 2 warnings.
  • check_allows, check_stubs, check_mirror_caps and tools/nix/inputs.py --check pass.
  • Booted on 0.9.2 dev images under QEMU (TCG), with 0 kernel faults:
    • Checked on screen: themes, Settings, routes, tabs and groups, bookmarks, history, reader, and a background-tab download.
    • Over Mixnet, Anyone and Direct, sites loaded or returned a server response.
    • Install mode: a bookmark and the Light theme survived two reboots, including a bookmark added after a reboot.
  • The last two commits (the failed-load title and the smooth icons) are covered by host tests and a host render of every icon, old and new side by side. They have not been booted yet.

Notes

  • On the boot where setup finishes in Install mode, vfs refuses persists as "amnesic boot" while the policy service is slow to answer under TCG. Later boots are clean. This is outside the browser.
  • Google may show its robot check over the Nym mixnet, because many users share its exit addresses.
  • main is frozen for the 0.9.2 tag. Please don't merge until it reopens.

Opened on GitHub by senseix21 as pull request 621. Review and merge happen there while this repository is kept in step from GitHub; this copy follows it, and is marked merged or closed when it is.

## Summary A redesign of the browser's interface (`userland/capsule_browser`), plus the persistence and small fixes it needed. The network stack is not changed. **Interface** - Light and dark themes, dark by default. Switchable in Settings and saved. - Rounded address pill, vector icons with anti-aliased edges, and a route badge (Mixnet / Anyone / Direct). - Titlebar tabs. Every tab keeps loading in the background (`Vec<Box<State>>`; per-tab process globals are swapped in `tab_scope.rs`). - Sidebar (full or rail), start page, and pages for history, bookmarks, downloads and tabs. Named tab groups and a reader view. - Full Settings page: appearance, network route, SOCKS5 proxy, search engine (DuckDuckGo or a custom `%s` template), privacy and data, downloads, reader, about. **Storage** - The browser now requires FileSystem: `CAPSULE_REQUIRED_CAPS` goes from `0x183d` to `0x187d`, in both `Capsule.mk` and `spawn.rs`. The README and `docs/using/browser.md` are updated to match. - Bookmarks, groups, reader settings, the theme and the search template are kept in `/home/.browser/state.bin` (`NBR1` v1 record; new sections are appended). History stays in RAM only. - Downloads are saved to `/home/Downloads`. - The record is written at a fixed 32 KiB. The disk store only overwrites a kept file with bytes of the same length, so a record that grows would otherwise never be saved again. - The file is unlinked before each write, so it is recreated as the browser's own. Files restored at boot have owner 0, and the vfs refuses to persist them otherwise. **Fixes** - `fix(qjs)`: event listeners are scoped to the JS context that registered them and released when it is freed, since each tab runs its own context. - The page is painted into the content rect; the stale 28 px titlebar offset is removed. - A page that fails to load no longer keeps the previous page's title, so a bookmark of it isn't filed under the wrong name. - A leading `www.` is skipped when picking a site's tile letter. ## Testing - Host proofs (`capsule_browser_proofs`): 703 tests pass, and the library clippy (the CI gate for this crate) is clean. New tests cover the record format, fixed-size padding and dropping the oldest bookmarks when full. - Capsule `cargo check` for the user target is at its baseline of 2 warnings. - `check_allows`, `check_stubs`, `check_mirror_caps` and `tools/nix/inputs.py --check` pass. - Booted on 0.9.2 dev images under QEMU (TCG), with 0 kernel faults: - Checked on screen: themes, Settings, routes, tabs and groups, bookmarks, history, reader, and a background-tab download. - Over Mixnet, Anyone and Direct, sites loaded or returned a server response. - Install mode: a bookmark and the Light theme survived two reboots, including a bookmark added after a reboot. - The last two commits (the failed-load title and the smooth icons) are covered by host tests and a host render of every icon, old and new side by side. They have not been booted yet. ## Notes - On the boot where setup finishes in Install mode, vfs refuses persists as "amnesic boot" while the policy service is slow to answer under TCG. Later boots are clean. This is outside the browser. - Google may show its robot check over the Nym mixnet, because many users share its exit addresses. - `main` is frozen for the 0.9.2 tag. Please don't merge until it reopens. --- Opened on GitHub by senseix21 as [pull request 621](https://github.com/NON-OS/microkernel/pull/621). Review and merge happen there while this repository is kept in step from GitHub; this copy follows it, and is marked merged or closed when it is.
The listener table is process-wide and assumed one page context per
process. Entries carried no context and were never released, so after a
navigation freed a page's context a later dispatch could call a listener
function belonging to the freed context, and with several browser tabs
each running scripts a click in one tab could fire another tab's
handlers.

Each entry now records its context; dispatch and removeEventListener
only touch the calling context's entries, and freeing a context first
releases its entries. Dead slots are reused so the table does not fill
up over a long session.
The toolbar was drawn 28 px down for a titlebar the window frame already
draws above the app surface, so that band was never painted and clicks
there were dropped, and the page, damage rects, blits, overlays and
pointer events each assumed their own fixed offset below the toolbar.

A pure ui::layout::compute now splits the surface into toolbar, sidebar
and content. The toolbar and the page paint into their own regions,
damage rects are placed by the same layout, and pointer events are
translated into region coordinates once.
The toolbar was pixel art on a dark band. It now paints on a light
surface with anti-aliased stroke glyphs, a rounded address field that
shows a lock for https pages, and a badge naming the network route
(Mixnet, Anyone, SOCKS or Direct) that opens the network settings.

The address field keeps its caret, selection, clipboard and scrolling;
only its colours and frame changed. Toolbar geometry is one pure
function, and the painter, the click handler, caret placement, text
fitting and damage rects all read the pill from it.
Adds the window-level Shell and a left sidebar that folds to an icon
rail on narrow windows, laid out by one pure function shared with its
click handler. Settings moves to the sidebar and the network badge.

The dark home page is replaced by a light start page: a greeting by
hour, a search field that mirrors the address bar with its caret and
selection, favourite tiles with bookmarks first, and cards for
frequently visited sites, the network route and the session. It
scrolls with the wheel.

Page titles are read from the committed document. Each finished
navigation is logged for the session, and the toolbar star bookmarks
the current page, filled while it is bookmarked.
The browser held one page per window. It now keeps up to six tabs, each
a boxed page State (the script engine holds a raw pointer into its DOM),
shown as a strip in the window titlebar through the app skeleton's
accessory hook. Ctrl+T, Ctrl+W and Ctrl+Tab open, close and switch.

Every tab with a load in flight keeps loading: each tick steps the tab
in view, then one busy tab out of view in turn, under one budget for
proxy calls. Three things a page sets live in process globals and are
read deep in the engine - its network routes, its cookie jar and its
web fonts - so each tab keeps its own and they are swapped in only while
that tab steps. A tab out of view leaves streams free at each proxy for
the tab in view, and drops its decoded images until it is shown again,
against one image budget shared by every tab.
The browser is to keep bookmarks across reboots and save downloads under
/home/Downloads, which needs the vfs. The capability is added in the
signed manifest, the kernel spawner and the Nix capsule catalogue
together: a spawner granting more than the manifest fails the mirror
check, and a mismatch silently denies the first vfs call.
Bookmarks are written to /home/.browser/state.bin as one versioned,
bounded record and loaded when the window opens; a short or damaged
record falls back to defaults, and a dead file server costs one timeout
before a gate stops further attempts. A save re-reads the file and
merges it, newest bookmark winning and this window's removals dropped,
so two browser windows do not erase each other's bookmarks.

A 2xx response the browser does not display is a download. Every tab
reports its downloads; one is written to /home/Downloads per tick, and
only while the tab in view is idle, under a unique name. The start page
counts what was saved and names the latest. The visit log stays in
memory and clears at shutdown.
The sidebar and toolbar open native pages: History with Mixnet, Anyone
and Direct filters, Bookmarks with relative times and removal, Downloads
with saved and failed filters, and a grid of the open tabs that switches
or closes them. Untitled pages are named by their site everywhere.

Tabs can be gathered into up to eight named, coloured groups, reached
from the sidebar when it has room and always from the Tabs page, where a
group can be renamed in place or deleted. Group names, colours and
reader settings persist with the bookmarks.

Reader mode extracts a page's article and sets it in a column beside its
settings panel, with Light, Sepia and Dark themes, five sizes and three
widths. Keys and the wheel on any page the browser draws scroll that
page and never reach the page hidden behind it.
A live session's file server keeps written files for the session and
refuses to make them permanent, so the browser marked every download
there as failed with access denied although the file was in
/home/Downloads. Making a download permanent is now best effort, as it
already was for the bookmark store; only a failed write fails the save.
Every colour the browser draws around a page now comes from one palette
with a light and a dark instance, chosen by a process-wide setting that
starts dark so the first frame is already dark. The page's own
rendering and the reader's article themes are unchanged; letter tiles
keep white ink on their fixed colours.

The choice is kept with the bookmarks as one byte appended to the
record, so records written before it read as dark. Switching repaints
every tab and the tab strip. A host test holds every text colour to at
least 4.5:1 against its ground in both palettes. Until the settings page
lands, the toggle lives in the settings panel.
The settings overlay is replaced by a settings page, opened from the
sidebar and the network badge, with Appearance (light or dark), Network
(Nym, Anyone or direct, and a SOCKS5 proxy for every tab), Search
(DuckDuckGo or a custom template holding %s, checked before it is
used), Privacy and data (clear history, clear the download list, remove
all bookmarks after a second click), where downloads go, the reader's
defaults, and the browser version.

Its two text fields share the address bar's editing code, so caret,
selection and clipboard behave the same, and take keys ahead of the
address bar while focused. The page's layout is one pure function used
by the painter, the click handler and caret placement. A custom search
template is kept with the bookmarks; older records read DuckDuckGo.
The browser now requires FileSystem (0x187d) to keep bookmarks in
/home/.browser/state.bin and save downloads to /home/Downloads. The
capsule README and the user guide still listed 0x183d with no
filesystem authority, which check_mirror_caps flags against Capsule.mk.
An install-mode boot kept the theme but lost every bookmark. The disk
store overwrites a kept file in place only with bytes of the same
length, so a record that grew by a bookmark was refused; and the vfs
restores kept files at boot with owner 0, so every persist after a
reboot was refused as not the caller's file.

Write the record at one fixed size (32 KiB, zero-padded, oldest
bookmarks dropped when it would not fit), and unlink the RAM copy before
writing it so it is recreated as the browser's own.
A bookmark for www.google.com showed W on its tile, not G.
Three failure paths left the previous page's title in place, so a star
on a page that failed to load filed it under that title: neverssl.com
was bookmarked as "Google". Clear it there as app/nav.rs already does,
so the bookmark falls back to the site name.
Each icon line was a stack of one-pixel anti-aliased lines offset by
whole pixels from endpoints snapped to whole pixels, so ends and joins
stair-stepped, and the reload arc used an aliased ring sweep.

Stroke every line, polyline and arc through one path rasteriser
(glyph/stroke.rs) that blends each pixel once by its centre's distance
to the nearest segment, at 1/16-pixel precision, with round ends and
joins. The reload arc is a 64-to-the-turn chord path, and the filled
polygon samples the same sub-pixel points so it meets the outline.
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin +refs/pull/164/head:nonos-sync/gh-621
git switch nonos-sync/gh-621
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
NON-OS/nonos-micro-kernel!164
No description provided.