Skip to content

Wallpaper from Library: CORP + shell-token wallpaper path, image thumbnails, Set as Desktop Background - #67

Draft
SashaMIT wants to merge 9 commits into
developfrom
feat/library-set-desktop-background
Draft

SashaMIT wants to merge 9 commits into
developfrom
feat/library-set-desktop-background

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Rebased onto feat/0.7.1-models (501b411c1). The 9 wallpaper/Library commits apply with no conflicts; independent of #68.

What a person sees

  • Uploading a wallpaper in System now actually changes the desktop, and System's own preview shows it.
  • The System window no longer jumps when the file picker closes.
  • Library shows image thumbnails instead of the generic icon (lazy, ≤ 4 MB, LRU of object URLs).
  • Library's transient status lives in the footer and never pushes the toolbar controls.
  • Right-click an image in Library → Set as Desktop Background. The wallpaper changes in place; System does not open.

Why the wallpaper was broken

  1. The gateway enforces Cross-Origin-Embedder-Policy: require-corp; the wallpaper response carried no Cross-Origin-Resource-Policy, so the browser dropped it. Now cross-origin + nosniff.
  2. Home GUI and System render from opaque sandboxed frames, so a CSS url() cannot carry the SameSite=Strict session. They now fetch with their launch token and apply an object URL (with caching, no retry storms).
  3. GET /api/apps/home/appearance/background-image only accepted the Home host token; the active shell that renders the desktop was refused. It now uses require_home_active_shell_token_context, the same authority the shell already uses to write preferences. Ordinary app tokens still get 403 (tested).

Set as Desktop Background — authority model

  • Library only expresses intent (home:set-desktop-background) and never gains appearance authority; a Library token calling the route directly gets 403 (tested).
  • The Home host accepts the intent from library only (policy set, exact message keys, localhost://Users/ URI), performs it with its own appearance authority and refreshes the summary.
  • New POST /api/apps/home/appearance/background-image { source_uri } reads the protected object itself under the caller's principal root, sniffs PNG/JPEG/WebP/GIF from the bytes, applies the same 5 MB rule and saves through the same path as the System byte upload. Foreign-principal, missing, non-image and non-localhost:// sources answer 400 (tested). Bytes never traverse a capsule.
  • System's Reset still clears it; System is unchanged for this feature.

Verification

  • cargo test -p elastos-server background_image (new test_home_sets_background_image_from_own_object + existing wallpaper test), fmt, clippy clean in touched files.
  • home-entropy-check, library-menu-smoke, library-product-behavior-smoke, home-shell-bridge-smoke, home-gui-sign-out-smoke, home-shell-regression-smoke, product-ui-source.
  • Headless end to end on a throwaway Home with a virtual passkey: upload in Library → right-click → menu item → host POST 200 → desktop repaints → System preview shows the same image.
  • On feat/0.7.1-models: home-entropy-check passes at every commit, source gate 14/14, cargo clippy --workspace --all-targets -- -D warnings clean, background_image tests 2/2.

Made with Cursor

Part of #93.

SashaMIT and others added 9 commits September 29, 2026 21:58
The gateway enforces Cross-Origin-Embedder-Policy: require-corp and the
Home GUI desktop renders from an opaque sandboxed frame. The background
image route only set Content-Type, so Chrome blocked the uploaded
wallpaper with NotSameOriginAfterDefaultedToSameOriginByCoep even though
the bytes were saved and served. Mirror the capsule asset route and
assert the header in the existing round-trip test.

Co-authored-by: Cursor <cursoragent@cursor.com>
The Home session cookie is SameSite=Strict, so a CSS url() request from
the opaque Home GUI frame cannot be relied on to carry it. Fetch the
image with x-elastos-home-token like every other Home request, apply it
as an object URL keyed by the versioned summary URL, revoke on change,
and fall back to the default wallpaper if the fetch fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
The dialog heading already names the file; writing 'Previewing …' into
the toolbar pushed the search and view controls. Clear the status on
preview and cap #status-text so no transient message can shift layout.

Co-authored-by: Cursor <cursoragent@cursor.com>
Render image files with their own thumbnail instead of the generic icon.
Only on-screen items are fetched (IntersectionObserver), at most three
at a time, capped at 4 MB, through the download authority Library
already holds; object URLs are released past 160 entries. Prefers
thumbnail_uri when the Runtime provides one.

Co-authored-by: Cursor <cursoragent@cursor.com>
The wallpaper GET only accepted the Home host token, yet the desktop is
drawn by the active shell (home-gui) from an opaque frame with its own
launch token, so every fetch returned 403 and the default wallpaper stayed.
Accept the same authority the appearance-preferences POST already grants
the active shell; ordinary app tokens are still refused.

Co-authored-by: Cursor <cursoragent@cursor.com>
…er preview

Chrome refocuses a file input when its picker closes and scrolls every
scrollable ancestor to reveal it, including overflow:hidden
.settings-container, which shifted the whole System window up. Hidden
file inputs are now viewport-anchored so nothing needs to scroll.

The background preview used a CSS url() that cannot carry the session
from an opaque frame; load it through the launch token like other
System requests.

Co-authored-by: Cursor <cursoragent@cursor.com>
Status text in the toolbar displaced the search and view controls
whenever a message appeared. Move it to the statusbar, where it takes the
spare middle space and truncates first, and drop the file name from the
preview loading message.

Co-authored-by: Cursor <cursoragent@cursor.com>
…bjects

POST /api/apps/home/appearance/background-image { source_uri } lets the
appearance authority (Home host, System, active shells) make a stored object
the wallpaper. The Runtime reads the protected object itself under the
caller's principal root, sniffs PNG/JPEG/WebP/GIF from the bytes, applies the
same size rule as the byte upload and saves through the same path. App
tokens are refused; foreign, missing, non-image and non-localhost sources
answer 400.

Co-authored-by: Cursor <cursoragent@cursor.com>
Library expresses the intent (home:set-desktop-background) and never gains
appearance authority. The Home host accepts it from Library only, with exact
message keys and a localhost://Users/ URI, performs the change with its own
authority and refreshes the summary so the desktop repaints. The menu item is
offered for PNG/JPEG/WebP/GIF objects within the wallpaper size limit.

Co-authored-by: Cursor <cursoragent@cursor.com>
@SashaMIT
SashaMIT marked this pull request as draft September 29, 2026 15:08
@SashaMIT
SashaMIT removed this pull request from stack #77 September 29, 2026 15:50
@SashaMIT
SashaMIT changed the base branch from fix/0.7.1-security to feat/0.7.1-models September 29, 2026 15:50
@SashaMIT
SashaMIT force-pushed the feat/library-set-desktop-background branch from b60ace8 to c3ac261 Compare September 29, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants