Repository navigation
Downloads and DevTools (downloads lane: DL, DT) - #20
Conversation
Every profile session's will-download saves to the profile's download
folder (the OS Downloads folder; a temp folder in test runs) under a free
name ("report (1).pdf"), written as <name>.crdownload until complete.
OrbitState.downloads holds what the sidebar shows (running, failed, and
finished ones for 4 s); the downloads list (userData/downloads.json) keeps
every download per profile behind downloads.list. A tab opened only for a
download closes and its opener is selected again. Toasts say when a
download starts, finishes or fails. Downloads outlive their page.
Quitting while downloads run asks "N downloads in progress, quit
anyway?": a before-quit guard that runs first, and on Linux/Windows the
last window asks before it closes. The other before-quit listeners
(core, Mini Window) skip a quit that was stopped (event.defaultPrevented).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts: docs/feature-status.json (union: DL-09 from main, DL-01 from this lane); FEATURES.md regenerated with node scripts/features.mjs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lled The archive's before-quit listener closed its store and stopped its timers even when the downloads guard had stopped the quit. It now skips a stopped quit (event.defaultPrevented), like core and Mini Window. The quit test checks that nothing starts winding down after Cancel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DevTools for the selected tab or focused split pane, docked inside the page's own view (or undocked, as chosen in DevTools' dock menu); Peek and Mini Window pages get their own the same way. - Keys: ⌥⌘I / F12 (Ctrl+Shift+I / F12) open, close, and bring undocked DevTools to the front; ⌥⌘J (Ctrl+Shift+J) opens on the Console; ⌥⌘C is the element picker on macOS (no default key on Windows/Linux; command bar "Inspect Element"). ⇧⌘C stays Copy URL. The keys also work while DevTools have the keyboard; a key held down acts once (the keyboard router passes auto-repeat to actions). - View → Developer submenu on macOS. - Right-click → Inspect keeps the engine's inspectElement. - A page shown again takes the docked size last chosen in any DevTools. - Links DevTools open become tabs. - A crashed page hands the keyboard to the window, so ⇧⌘R (the navigation lane's nav.hardReload) brings it back. Shared/other-lane edits (small): actions.ts (devtools.console, devtools.inspect, F12 on macOS), rpc.ts, registry.ts (ActionContext.repeat), windows.ts (pass isAutoRepeat), tabs/commands.ts (devtools.toggle moved to src/main/devtools), peek/page-actions.ts, features.ts, menu.ts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # FEATURES.md
…e, pause/resume/retry - DL-02: a file icon flies from the page's edge into the Library button, which bounces; one flight per download; reduced motion fades instead. With the sidebar hidden, a "Downloading <file>" toast. - DL-03: a row above the bottom bar with the newest download (name truncated in the middle, bar, bytes, time left, cancel) and "+N"; hover or "+N" lists them all; done for 4 s (click opens); failed shows Resume or Retry. - DL-04: Open (Orbit shows PDF, images, text and media in a tab), Show in Finder/Folder, Copy File, Copy Download Link; a moved file shows "File Missing" and Download Again. - DL-08: Remove from List keeps the file; Delete File moves it to the Trash; downloads.clear empties a profile's list but for running downloads. - DL-15: pause/resume, Resume of a cut-off download with a range request (Retry when the server gave no ETag/Last-Modified), and resume after a restart from the partial file, kept under a hidden second name through the engine's shutdown. - DL-16: Peek and Mini Window downloads join the same list; a private session's downloads are kept in memory only and leave when its last page closes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Ctrl+J flyout, drag out, Keep/Discard - DL-10: the Library's Downloads section lists the profile's downloads newest first by day, with a picture or kind icon, size or progress, site and time; search by name; a click previews in a Peek over the Library (Cmd/Ctrl-click: a tab; other files open in their app); hover actions and the full menu; a profile switcher; Clear all. - DL-11: the Media section, a grid of downloaded pictures and videos (videos play muted while on screen, still with reduced motion), plus the OS screenshots when chosen. - DL-05: hovering the Library button shows the recent files; right-click chooses Downloads / Screenshots and Show Screenshots in Library (new settings recentFiles, libraryScreenshots). - DL-06: every download drags out as the real file (sidebar row, popover, Library, flyout). - DL-14: Ctrl+J opens the downloads flyout beside the sidebar on Windows and Linux; on macOS Cmd+Shift+J and Cmd+Alt+L open the Library's Downloads section; a "Downloads" action. - DL-12: programs, installers, scripts and disk images wait under their partial name with Keep / Discard; finished files get the OS "from the internet" mark (macOS quarantine, Windows Zone.Identifier). - DL-08: Clear all keeps running, paused, held and resumable downloads. - DL-09: right after a download, a closed Library opens on Downloads next time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r's download button uses the download flow (DL-13) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Typing orbit://pages or another internal address in the command bar opens it as a normal tab; orbit://pages/ lists the pages and orbit://version/ shows the versions of Orbit, Electron, Chromium, V8, Node and the OS. - A privileged standard, secure scheme, registered once before ready (the app's only registerSchemesAsPrivileged call), served on every profile session from the renderer bundle. - The page is served only to navigations Orbit or an internal page started, and scripts and styles only to requests with an orbit: origin; anything else gets a network error. Web content can't navigate, frame, redirect to or open one (the window-open guard registers last, so it runs before Peek's). - A session preload gives an orbit: page's main frame the same window.orbit bridge as Orbit's UI on channels of its own; main answers only a tab's main frame showing an orbit: page and forwards state patches and broadcasts there. - Pages register by file name (*.internal-page.tsx) for reuse by other lanes (D39: history, extensions, settings pages). Documented at src/main/devtools/internal-pages.ts and src/renderer/src/internal/registry.ts. DT-13 stays partial: the pages other lanes own come with them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts, each kept both sides: - src/shared/rpc.ts: RendererView has both 'onboarding' and 'internal'. - src/main/persist.ts: normalizeDownloads (which already turns running downloads into interrupted ones) and normalizeSettingsPrefs. - src/renderer/src/shell/sidebar/Sidebar.tsx: the update banner and the downloads tray. - FEATURES.md regenerated from the merged docs/feature-status.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…T-13) After the Settings merge, the version page shows what About shows through settings.buildInfo, with its Copy build info, instead of a second command that reported the same versions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (DL-07) Settings → Profiles → [profile] → Download location: the profile's folder, Other… (the OS folder picker) and Ask every time. A new profile starts with the OS Downloads folder. Ask every time shows the OS save dialog for each download, opening in the folder the last one went to, kept across restarts. As in other browsers the file downloads meanwhile under a hidden name where the dialog opens, and moves into place when complete (copied across disks without blocking); it shows in the sidebar and the lists once placed, and Cancel drops it. A chosen folder is always used, never the folder last used with Ask every time; a folder that can't be written to asks with the save dialog and says why. Shared edits: Profile gains downloadFolder, downloadAsk and downloadAskFolder (state.ts, normalized in persist.ts); the Profiles section shows the row (settings lane's profiles.settings.tsx, one import and one row). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e finishing in the background notifies (DL-17) While downloads run or are paused, their overall progress shows on the macOS Dock icon and the windows' taskbar buttons (setProgressBar): bytes received of those with a known size, the can't-tell bar when none is known, Windows' paused colour when all are paused. A download that finishes while no Orbit window has focus bounces the Dock icon once and shows a "Download complete" notification; a private window's download isn't named in it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: c93d7763-4cf8-45aa-addf-c7bd8d942d6d) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 4f78ab43-ef50-4bc7-87be-0eea47e37ce8) |
…state file or its backup (DL-16, review M1) The sidebar's rows of private sessions' downloads stay in OrbitState, as private windows, Spaces and tabs do, and serialize leaves them out. The DL-16 test writes the state file twice while the download runs and twice after it finishes, and reads the file and its .bak each time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ress (DL-16, review F3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…age whose script could read other files (DL-04, DL-13, review M2) D53 (4): a download opens in an Orbit tab only as a type that runs no script there: PDF, raster images, plain text, audio and video. SVG leaves the inline list (HTML, XHTML, XML and MHTML were never on it); it still shows as a picture in thumbnails and Media tiles, where an <img> runs none of its script. The test downloads SVGs whose script reads secret.txt beside them and posts it to the fixture server, opens one with downloads.open and previews the other from the Library: the server gets nothing, and a text file with a script opens as text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ws a hover lists (DL-08) The tray lists every download only while hovered; the test passed only when the pointer happened to rest over it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: bce7b19b-0ec6-4e64-9537-8423645095e6) |
…ne the download put in place (DL-04, DL-08, review M3) A finished download keeps its file's size and date as it went into place (taken again after Windows' zone marker, which can change the date). Another file at its path (one saved over it, a file put there after it was moved away, or a later download saved there with Ask every time, DL-07) is not its file: the download shows "File Missing", Open and Show in Folder do nothing, and Delete File leaves that file alone and keeps the entry. Downloads listed before this go by their path, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: ff82149a-d771-4b29-aa63-ab4da25aa9e7) |
…e of Windows' own types (DL-12, review F1) Everywhere: sh, bash, zsh, py, pl, rb, .desktop launchers, iso, img, vhd, vhdx, jnlp, and the .tool and .terminal files Terminal runs. On Windows also chm, url, scf, settingcontent-ms, library-ms, searchconnector-ms, inf, msc, msp, mst, msu, dll, xll, ClickOnce files, diagcab, rdp and the remaining script types (wsc, sct, msh, PowerShell's other files). DL-12 is yes, with Safe Browsing as the gap the spec allows (D54). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: a710252e-b4fd-4be5-8aca-c0ebb9dc857e) |
…ad keeps its entry (DL-12, DL-15, review F4) The list dropped its oldest entries that weren't running, held or resumable ones included, and their partial files then stayed on disk with nothing to remove them. Now only entries with no partial file go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: dc6ab1d8-cfb8-4bfb-84a6-fdbbe76765c8) |
… sends no events, and is served with script-src 'self' (DT-13, D53, review F7) INTERNAL_PAGE_COMMANDS (src/main/devtools/internal-urls.ts) lists each page's commands by name: the version page's build info and its copy. Main refuses any other command from an internal page, and every event, so a script that got into a page showing text from the web can do no more than the page. The documents' CSP header adds script-src 'self', object-src 'none' and base-uri 'none' to frame-ancestors 'none'; index.html's own meta policy already blocked inline scripts, and the served header now does too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 502c74a8-8289-43b3-97ea-1054598726d0) |
…-06, DL-08, DL-09, DL-11, DL-13, DT-13) SB-09 and DL-11 are yes (DL-11's in-browser captures need OT-03, which has no spec row). The partial rows name the lanes that build what they lack: Open with... (finish-downloads), dropping into a canvas (canvases), the Download history choice and Windows' PDF default (finish-settings), the Library sections of the notes, finish-tabs and tweaks lanes, and the internal pages of their own lanes. DL-04 and DL-08 say how another file at a download's path is treated; DT-13 and ARCHITECTURE.md the pages' command lists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: f8eac90a-9ebb-4ab4-be3a-7a44673d12d4) |
Conflicts resolved keeping both sides: - withoutPrivate (src/shared/private.ts) also leaves out a private session's downloads, and persist.ts's serialize uses it alone (fix check N4: chrome's filter skipped them). - Sidebar: chrome's private and floating sidebars, with the downloads tray in both. - features.ts, rpc.ts, electron.vite.config.ts, ARCHITECTURE.md: both sides' entries. - docs/feature-status.json merged key by key (no key changed on both sides); FEATURES.md regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… preload (D53 (1)) src/preload/internal.ts, a second preload on every profile session, is gone: chrome's web page preload (src/preload/page.ts) gives an orbit: page's main frame the bridge, on its own orbit-page:internal-* channels (PAGE_CHANNEL), and patches nothing there; anywhere else it works as before. Main answers those channels only for a tab's main frame showing an orbit: page, with only the page's listed commands and no events (F7's list and CSP unchanged). The DT-13 test checks a page's session has the one preload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…3 (3)) pageMayOpen refuses an orbit: address to any page but an internal one, as it refuses a local file to a web page (D49), so every route that asks it refuses one: the page menu (link and picture), Split View's link item (now linkSplitMenuItems, which asks it itself), ⌥-click, a dropped link, and through framesMayOpen the new tabs, windows and pop-ups a page asks for, a pop-up's own opens, and blocked pop-ups kept to open later. Such a refusal shows no toast: to a web page, orbit: is a scheme that isn't there. Without the fix, the new nav-links test finds the menu's five open/save items on the link and two on the picture, a blocked pop-up kept, and three orbit: tabs loaded (a pop-up's open and two drops). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntil the last one closes (DL-16) Now that private windows exist, the DL-16 test uses them instead of a profile on an in-memory session: - A private window's sidebar row and Ctrl+J flyout list only its own session's downloads. Before, normal downloads showed there too. - Feedback, toasts and files opened from a private window stay in that private session's windows. Before, a private PDF or text file opened in a tab of a normal window. A private download doesn't change the Library's section, and the Dock's notification gives no file name. - The list ends when the session ends (the last private window closes and its profile goes), not when the session's pages close. On that: a running download is saved and then leaves the list; a paused or stopped one is cancelled; a program held back (DL-12) is discarded. - Removes the "Until Orbit has private windows" page-count tracker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… of showing Since the chrome merge, tests keep the page menu (keepPageMenu) and never pop it up, so recording Menu.popup saw nothing and the DT-02 Inspect test failed at the first right-click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…docked DevTools (F10, DT-03) DevTools report where they put the page in its view (each setInspectedPageBounds, and null once undocked), and the window manager's tabViewBounds is the page's own area: the view less docked DevTools, cut as the engine lays it out. Page tools, link pill, loading indicator and permission prompt follow it on each report. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Reload action (F11) The DT-14 test now records the actions its keys run. NV-04 (Esc in the page and double-clicking Reload stop a load) is on main since the chrome merge; its tests pass here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lete checks the file is the one downloaded (D56) Open, Show in Folder, Copy File, preview, drag and the Library act on whatever file is at a download's path, also one edited since. Delete File moves it to the Trash only while its size and date match the record; otherwise the file and the row stay and a toast says it changed after it was downloaded. A download that finishes at an older one's path marks the older one replaced: "File missing", kept across restarts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: 193db202-df19-4483-8f96-4821bc1525c8) |
Conflicts: src/shared/rpc.ts keeps both new RendererViews, 'import' and 'internal'; FEATURES.md is regenerated. docs/feature-status.json merged by itself: it parses, has no duplicate keys, and matches both sides key by key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts:
- LibraryButton.tsx: downloads' button (recent files on hover, right-click) with the
title from useShortcutLabel('app.library'); the static TITLE and its imports go.
- OverlayApp.tsx: both imports (downloads flyout and the shortcut sheet), in Biome's order.
- feature-status.json: SB-09 from main (the recent-files popover is built); SB-11 keeps
the KS-02 note. FEATURES.md regenerated.
attachShortcuts keeps its order (record, switcher, actionIn, has, leaveToPage, run); the
run line now passes repeat from main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
The downloads lane covers downloads (DL), and DevTools with Orbit's internal
orbit:pages (DT). Chrome (PR #18) is merged in (63e65b3). Import moved to its own lane (PR #22).orbit:pages); ST-20. Each row's note says what's missing.Decisions
.orbit-<id>.crdownloadwhile the save dialog is open, then moves into place. Cancel leaves no file and no entry.orbit:pages.orbit:page's main frame, and each page has a fixed list of commands.script-src 'self'CSP.Review
reviews/lane-downloads.md) asked for changes, with 3 must-fixes:2715613) fixed all three, plus F1, F3, F4, F7 and F9. Each fix has a test that fails without it.63e65b3..80036af):orbit:on every route a web page can use (F8);reviews/lane-downloads-fixcheck2.md). The merge loses nothing from either side. Each fix's test fails without it: F8, DL-16 (c) and (d), D56 (a), D53 (1) and F10. The downloads, devtools, nav, nav-links, nav-page and chrome specs ran 166 passed, 2 skipped (macOS only) and 0 failed. Its follow-ups go to the finish-downloads lane. Among them, N1: a quit with a private window open leaves the partial file of a held program in the download folder.Merge gate (D42), run locally on Linux on
80036afnpm run build,npm run typecheck,npm run lintand./node_modules/.bin/vitest runall exit 0. Unit: 580 passed of 580, in 61 files.xvfb-run -a -s "-screen 0 1440x900x24" ./node_modules/.bin/playwright test --workers 1 --retries 0ran 503 tests in 23.5 min: 499 passed, 4 skipped, 0 failed, and it exited 0.test.fail().80036af's.🤖 Generated with Claude Code
Note
Medium Risk
Large surface area touching filesystem paths, quit lifecycle, private-session data, and a new privileged
orbit://protocol; mitigated by extensive e2e/unit hooks but still core browser behavior.Overview
This PR lands the downloads lane end-to-end and a first DevTools / internal-pages stack, with
FEATURES.mdand architecture docs updated to match.Downloads replace the main-process stub with a full
DownloadManager: per-profile folders and “ask every time” save dialogs, sidebar progress and start animation, Library Downloads and Media sections, recent-files hover on the Library button, Ctrl+J flyout (non-macOS), pause/resume/retry, dangerous-file Keep/Discard, quarantine/Zone.Identifier marking, private-window isolation, dock/taskbar progress and background completion notifications, and quit guards when transfers are active. Archive/main quit handlers now respectbefore-quitwhen downloads block shutdown.DevTools add open/toggle/console/inspect actions, dock-side and page-area tracking so page overlays stay off docked DevTools, and hard reload wiring.
orbit://internal pages register a privileged scheme, session protocol handler, navigation guards, and a restrictedwindow.orbitbridge on the page preload (INTERNAL_PAGE_COMMANDS), starting withorbit://version/and listing infrastructure for more pages.Sidebar SB-09 is marked complete (Library hover popover, drag-out, + menu notes). Renderer work includes the Library downloads section module and related UI (per diff).
Reviewed by Cursor Bugbot for commit 80036af. Bugbot is set up for automated code reviews on this repo. Configure here.