Skip to content

feat: native file and folder picker API#38

Merged
niklabh merged 1 commit into
mainfrom
feat/file-picker-api
Apr 20, 2026
Merged

feat: native file and folder picker API#38
niklabh merged 1 commit into
mainfrom
feat/file-picker-api

Conversation

@niklabh
Copy link
Copy Markdown
Owner

@niklabh niklabh commented Apr 20, 2026

Implements the four Phase 4 System APIs from ROADMAP.md: file_pick, folder_pick, file_read / file_read_range, and file_metadata. Guests receive opaque u32 handles — host paths never cross the sandbox.

Host (oxide-browser)

  • New module file_picker.rs with FilePickerState (HashMap<u32, PathBuf>) and six host functions:
    api_file_pick(title, filters, multiple, out) -> i32
    api_folder_pick(title) -> u32
    api_folder_entries(handle, out) -> i32 (JSON)
    api_file_read(handle, out) -> i64
    api_file_read_range(handle, off, len, out) -> i64
    api_file_metadata(handle, out) -> i32 (JSON)
  • Negative returns communicate required buffer size so guests can
    resize and retry once (avoids fixed 1 MiB caps like api_upload_file).
  • Filter strings are comma-separated extensions ("png,jpg,gif"); empty
    allows all files.
  • folder_entries pre-allocates sub-handles for each child so guests can
    recurse or read files without ever seeing the underlying path.
  • file_metadata emits JSON with name, size, mime (extension-inferred),
    modified_ms, and is_dir.
  • HostState gains file_picker: Arc<Mutex<FilePickerState>>; module
    registered at the tail of register_host_functions.

SDK (oxide-sdk)

  • FFI imports plus safe wrappers: file_pick, folder_pick, folder_entries (-> Vec), file_read, file_read_range, file_metadata (-> FileMetadata).
  • Hand-rolled JSON reader for the strict flat objects the host emits — avoids pulling serde into guest builds.
  • file_read retries once with an exact-sized buffer when the host reports -(required_size), capped at 64 MiB.

Example (examples/file-picker-demo)

  • Split-panel app exercising every new API:
    • "Pick Image…" — filtered single select
    • "Pick Files…" — unfiltered multi select
    • "Pick Folder…" — folder browser with drill-in
  • Left panel lists picked files or folder_entries children; clicking a folder drills in, clicking a file selects for preview.
  • Right panel shows metadata and either a canvas_image preview (via file_read) for image/* or a 2 KiB text snippet (via file_read_range) for text-ish MIME types.
  • Registered in workspace Cargo.toml.

Security

  • No new linker capabilities beyond the six registered imports.
  • No WASI, no paths exposed to the guest — handles only.
  • Access is read-only and scoped to files the user explicitly picked via the OS dialog.

Verification

  • cargo build -p oxide-browser ok
  • cargo build -p oxide-sdk --target wasm32-unknown-unknown ok
  • cargo build --target wasm32-unknown-unknown --release
    -p file-picker-demo ok (118 KB wasm)
  • cargo fmt --all && cargo clippy --workspace --all-targets
    -- -D warnings ok
  • cargo test --workspace ok

ROADMAP.md: the four Phase 4 file API bullets are now checked off.

Made-with: Cursor

Summary by CodeRabbit

Release Notes

  • New Features

    • Added native file picker dialog with single/multi-select and extension filtering support
    • Added folder picker and directory browsing capabilities
    • Added file reading (full and partial range reads) and metadata inspection (size, MIME type, timestamps)
    • Added example demo app showcasing the file picker UI with preview pane
  • Documentation

    • Updated roadmap marking file picker and metadata APIs as complete

Implements the four Phase 4 System APIs from ROADMAP.md: file_pick,
folder_pick, file_read / file_read_range, and file_metadata. Guests
receive opaque u32 handles — host paths never cross the sandbox.

Host (oxide-browser)
- New module `file_picker.rs` with `FilePickerState` (HashMap<u32,
  PathBuf>) and six host functions:
    api_file_pick(title, filters, multiple, out)   -> i32
    api_folder_pick(title)                         -> u32
    api_folder_entries(handle, out)                -> i32 (JSON)
    api_file_read(handle, out)                     -> i64
    api_file_read_range(handle, off, len, out)     -> i64
    api_file_metadata(handle, out)                 -> i32 (JSON)
- Negative returns communicate required buffer size so guests can
  resize and retry once (avoids fixed 1 MiB caps like api_upload_file).
- Filter strings are comma-separated extensions ("png,jpg,gif"); empty
  allows all files.
- folder_entries pre-allocates sub-handles for each child so guests can
  recurse or read files without ever seeing the underlying path.
- file_metadata emits JSON with name, size, mime (extension-inferred),
  modified_ms, and is_dir.
- HostState gains `file_picker: Arc<Mutex<FilePickerState>>`; module
  registered at the tail of register_host_functions.

SDK (oxide-sdk)
- FFI imports plus safe wrappers: `file_pick`, `folder_pick`,
  `folder_entries` (-> Vec<FolderEntry>), `file_read`, `file_read_range`,
  `file_metadata` (-> FileMetadata).
- Hand-rolled JSON reader for the strict flat objects the host emits —
  avoids pulling serde into guest builds.
- file_read retries once with an exact-sized buffer when the host
  reports -(required_size), capped at 64 MiB.

Example (examples/file-picker-demo)
- Split-panel app exercising every new API:
    * "Pick Image…"  — filtered single select
    * "Pick Files…"  — unfiltered multi select
    * "Pick Folder…" — folder browser with drill-in
- Left panel lists picked files or folder_entries children; clicking a
  folder drills in, clicking a file selects for preview.
- Right panel shows metadata and either a canvas_image preview (via
  file_read) for image/* or a 2 KiB text snippet (via file_read_range)
  for text-ish MIME types.
- Registered in workspace Cargo.toml.

Security
- No new linker capabilities beyond the six registered imports.
- No WASI, no paths exposed to the guest — handles only.
- Access is read-only and scoped to files the user explicitly picked
  via the OS dialog.

Verification
- cargo build -p oxide-browser                                      ok
- cargo build -p oxide-sdk --target wasm32-unknown-unknown          ok
- cargo build --target wasm32-unknown-unknown --release
    -p file-picker-demo                               ok (118 KB wasm)
- cargo fmt --all && cargo clippy --workspace --all-targets
    -- -D warnings                                                  ok
- cargo test --workspace                                            ok

ROADMAP.md: the four Phase 4 file API bullets are now checked off.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Introduces a complete file/folder picker API system spanning host (oxide-browser) and guest (oxide-sdk) layers. Implements native OS dialogs, handle-based file access, metadata queries, and ranged file reads. Adds a new example crate demonstrating the picker UI with image and text preview functionality.

Changes

Cohort / File(s) Summary
Workspace & Configuration
Cargo.toml, ROADMAP.md
Added examples/file-picker-demo to workspace members; marked Phase 4 file picker tasks as completed and refined folder_pick() description.
Host File Picker Module
oxide-browser/src/file_picker.rs
Implements six host APIs (file_pick, folder_pick, folder_entries, file_read, file_read_range, file_metadata) with handle-based file/folder access, OS dialog integration, file metadata extraction, MIME type detection, and error handling with capacity signaling.
Host Integration
oxide-browser/src/capabilities.rs, oxide-browser/src/lib.rs
Extended HostState with file_picker field to store picker state/handles; registered file picker functions in register_host_functions; exported new file_picker module.
Guest SDK API
oxide-sdk/src/lib.rs
Added public types FileMetadata and FolderEntry; exposed six wrapper functions (file_pick, folder_pick, folder_entries, file_read, file_read_range, file_metadata) with dynamic buffer sizing and JSON parsing for guest-side file/folder access.
File Picker Demo Example
examples/file-picker-demo/Cargo.toml, examples/file-picker-demo/src/lib.rs
New WebAssembly example crate demonstrating file picker UI with breadcrumb navigation, selectable row list, and inline previews (images via canvas, text with truncation/wrapping); handles file/folder selection, metadata loading, and conditional content reading.

Sequence Diagram(s)

sequenceDiagram
    participant Guest as Guest App
    participant Host as Host Runtime
    participant Dialog as OS File Dialog
    participant FS as Filesystem

    Note over Guest,FS: File Picking & Reading Workflow

    Guest->>Host: file_pick(title, filters, multiple)
    Host->>Dialog: Open native file dialog
    Dialog-->>Host: User selects files
    Host->>Host: Allocate handles, store paths
    Host-->>Guest: Return handles [u32]

    Guest->>Host: file_metadata(handle)
    Host->>FS: Stat file (size, mtime, extension)
    Host->>Host: Derive MIME from extension
    Host-->>Guest: JSON metadata

    Guest->>Host: file_read(handle)
    Host->>FS: Read entire file
    Host-->>Guest: Raw bytes

    Guest->>Host: file_read_range(handle, offset, len)
    Host->>FS: Read [offset..offset+len)
    Host-->>Guest: Bytes (up to len)
Loading
sequenceDiagram
    participant Guest as Guest App
    participant Host as Host Runtime
    participant Dialog as OS Folder Dialog
    participant FS as Filesystem

    Note over Guest,FS: Folder Browsing Workflow

    Guest->>Host: folder_pick(title)
    Host->>Dialog: Open native folder dialog
    Dialog-->>Host: User selects folder
    Host->>Host: Allocate directory handle
    Host-->>Guest: Return handle (u32)

    Guest->>Host: folder_entries(handle)
    Host->>FS: Enumerate directory contents
    Host->>Host: Allocate handles for each entry
    Host-->>Guest: JSON array [{name,size,is_dir,handle}]

    Guest->>Host: file_metadata(sub_handle)
    Host->>FS: Stat entry
    Host-->>Guest: Metadata (reuse same API)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰✨ Hoppity-hop through files we go,
Dialogs dancing, handles flow,
Folders peek, their contents spill,
Metadata, bytes—we read our fill!
Preview panes in pixels bright,
Picker magic—pure delight! 🎨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: native file and folder picker API' directly and accurately describes the main change—implementing native file and folder picker APIs as the primary feature.
Docstring Coverage ✅ Passed Docstring coverage is 92.86% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/file-picker-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@niklabh niklabh merged commit 36b127e into main Apr 20, 2026
4 of 5 checks passed
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.

1 participant