* feat(web): add chat link opening preference * docs(web): clarify preference-controlled link routing * fix(web): hide link preference without a browser * fix(web): make the built-in browser opt-in * test(web): honor profile-aware browser availability --------- Co-authored-by: Turtle <[email protected]>
description, kind
| description | kind |
|---|---|
| Right-Sidebar browser tabs for sandboxed HTTP(S) pages, including loopback services. | package-reference |
@deepseek-ai/dsh-client-ui-sidebar-browser
English | 中文
Summary
Browse HTTP(S) pages, including loopback services, inside independent right-Sidebar tabs. The current carrier is an iframe with application-managed history in both Web and Desktop. The package never injects Electron or Node access into visited content.
Table of Contents
- Use this package
- Understand the implementation
- Further Exploration
- Model Experience
- Known Limitations and Deferred Work
- Dev Note
Use this package
Browser is disabled by default in Web profiles and enabled on Desktop. Enable the shipped entry through the Web profile patch to use it. Open Browser from the right-Sidebar guide and enter an HTTP(S) URL. Chat HTTP(S) links open here when the link preference selects the built-in browser. A host name without a scheme becomes HTTPS. Public and loopback targets use the same default sandbox. Each guide action or delegated message-link activation creates another Browser tab.
When to choose it
Choose Browser for a Web page that should remain beside the current Session. Choose Document Preview for local files, and use the explicit external-browser action when a site refuses iframe embedding or needs browser capabilities this package withholds.
Minimal configuration
The package has no plugin configuration. A Web profile enables the shipped entry through its profile patch:
- id: ui-sidebar-browser
disabled: false
Client plugins can open a tab through ctx.sidebarRight.openTab('browser', { params: { url } }). The optional URL passes the same validation as address-bar input before navigation.
The toolbar provides Back, Forward, Reload, Go, Open in system browser, and a rightmost per-tab sandbox toggle. Disabling the sandbox is temporary and displays a warning. The external action accepts a known HTTP(S) target. The tab title is the Web host.
Understand the implementation
Implementation internals — click to expand
Protocol policy
The address parser accepts HTTP and HTTPS, including loopback targets. It rejects file: URLs, script/data/blob input, embedded credentials, the DSH application origin, and malformed addresses. Document Preview owns local-file rendering.
Iframe carrier
Web and Desktop use sandbox="allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox" by default. The frame has no direct download or top-navigation flag. Popups leave the sandbox; in Web, an escaped popup retains its opener and can navigate the top-level application. The visited origin can use its own cookies and Web storage but a cross-origin target cannot read DSH DOM, storage, or API responses. The iframe sends no referrer and adds no package-owned Permissions Policy, so browser defaults and user grants apply. The toolbar can remove the sandbox for the current tab occurrence; the choice is not persisted. An unsandboxed page can navigate the top-level application under browser activation rules and use downloads, modal dialogs, and input locks. The package does not proxy or probe remote pages.
Web records toolbar submissions and typed tab opens. A navigation state machine treats the first iframe load for each controlled revision as known and a later load as proof that the page changed to an unreadable URL. In that unknown state the address is marked, Back, Forward, and external-open are disabled, and Reload returns to the last controlled URL. A remounted body reloads the latest application-known URL and uses its optional initial URL only before the first controlled target. History API and fragment changes that emit no iframe load remain invisible. An iframe error event displays a transient load-failure notice until the next controlled load without changing URL history.
Controller
Each tab receives one BrowserController class. Its public commands are loadUrl, goBack, goForward, and reload; address validation and history mutation stay behind that object. Its BrowserNavigation class owns the serializable URL state machine. The BrowserFrame interface owns transient sandbox and document state plus carrier operations, and IframeImpl implements that interface for the current iframe carrier. Slot injection exposes keyed frame state through useBrowserFrame and supplies plain callbacks, so the React body receives neither the controller nor an observable source; it keeps only the editable draft and iframe DOM.
The controller interface does not depend on iframe APIs. A future ElectronWebViewImpl can implement BrowserFrame while owning <webview> attachment and target identity. That deferred carrier is documented in the same Sidebar Browser decision, but is not registered or tested today.
Further Exploration
- Right Sidebar — tab composition, navigation, and lifecycle.
- Document Preview — local source, Markdown, images, HTML, and PDF rendering.
- Sidebar Browser decision — current iframe behavior, controller ownership, and deferred Electron carrier.
Model Experience
None, as Browser tabs are user-facing presentation state and register no tool, prompt section, or Session event.
KV Cache effect
None; browsing does not enter a model request.
Known Limitations and Deferred Work
The isolation policy deliberately gives up some browser compatibility:
- Many sites refuse iframe embedding or need downloads or top-level navigation withheld from the frame by the default sandbox. An HTTPS application can also block public HTTP pages as mixed content. Disabling the sandbox trades its restrictions for compatibility but does not bypass mixed-content or private-network policy. The unsandboxed frame can navigate the top-level application under browser activation rules and use downloads, modal dialogs, and input locks. It does not isolate the visited origin's cookies per Browser tab or prevent an in-frame page from choosing its own next URL.
- In Web, a popup that escapes the sandbox retains its opener and can use that chain to navigate the top-level application. Desktop handles popup creation separately.
- A later iframe load reveals that navigation occurred but not the new cross-origin URL. History API and fragment changes may remain invisible; Web Back and Forward are unavailable after the state becomes unknown.
- Browsers conceal many iframe failures for security: DNS, TLS, mixed-content, CSP, and
X-Frame-Optionsfailures may emitloador no actionable event instead oferror. The load-failure notice is best-effort. - Browser history survives body remounts and ordinary page reloads, but closing the tab or unloading
ui-sidebar-rightaborts its occurrence and removes the stored history bucket. - Local files are rejected and remain owned by Document Preview.
- The proposed Electron
<webview>carrier, per-tab cookie partitions, native history, and target-specific CDP connection are not implemented.
Dev Note
Working context for maintainers — click to expand
None.
Runtime invariant: No companion is published. BrowserNavigation is the sole URL-state writer; the store receives its immutable snapshots, and focused controller and component tests exercise publication and cleanup directly.