Ungabunga Browser
A minimal web browser built with Qt6 WebEngine. All persistent data (history, bookmarks, credentials) lives in one portable SQLite file. Website sessions (cookies, localStorage, cache) are not stored between launches — semi-incognito by default.
Build
# Dependencies (Void Linux):
sudo xbps-install -S qt6-base-devel qt6-webengine-devel sqlite-devel libsodium-devel
sudo xbps-install -S hunspell hunspell-en
cmake -B build
cmake --build build
Usage
On first run, the browser prompts you to set a master password for the encrypted credential vault. Subsequent launches require the master password to unlock the vault.
Binary: build/browser
Features
- Tabbed browsing – open/close tabs (Ctrl+T, Ctrl+W), cycle with Ctrl+Tab /
Ctrl+Shift+Tab, close with middle-click.
target="_blank"andwindow.open()open new tabs. - Address bar – type a URL or search query (DuckDuckGo). History-based autocomplete (last 1000 entries). Enter navigates; searches if input contains spaces or lacks a domain pattern.
- Bookmarks – toggle on/off per page with Ctrl+D. Stored in SQLite.
- History – every page visit (URL, title, timestamp) is saved to SQLite.
- Dark mode – toggle via toolbar button. Applies a dark QPalette and
reloads pages so
prefers-color-schemeis re-evaluated. - DevTools – per-tab Chromium DevTools panel, toggled via toolbar button or "Inspect Element" context menu.
- Downloads – downloads go to
~/Downloads. A collapsible download bar shows progress per file; cancel during progress, dismiss when complete/failed. Clears completed downloads in bulk. - Fullscreen – triggered by pages (F11). Exit with Escape. Toolbar/tab bar hidden while fullscreen.
- Permissions – prompts for camera, microphone, geolocation, and notifications on a per-origin basis.
- Zoom – Ctrl+/Ctrl- to zoom, Ctrl+0 to reset. Zoom level is persisted per domain in SQLite and restored on navigation.
- Password vault – encrypted with XChaCha20-Poly1305 AEAD. The data
encryption key (DEK) is wrapped with a key encryption key (KEK) derived from
the master password via Argon2id. The DEK exists only in memory while
unlocked.
- Capture – JavaScript injected via QWebChannel observes login forms. On form submission, the origin, username, and password are forwarded to the C++ backend.
- Save/Update – prompts to save new credentials or update existing ones for the same origin+username. Skips if the password is unchanged.
- Autofill – on page load, if exactly one credential exists for the host, it is filled automatically. Multiple credentials show a popup menu (Ctrl+Shift+L or toolbar button) to pick which to fill.
- Spell check – enabled for en_US. Requires hunspell BDIC files at
~/.local/share/qtwebengine_dictionaries/:sudo xbps-install -S hunspell-en mkdir -p ~/.local/share/qtwebengine_dictionaries cp /usr/share/hunspell-bdic/en_US.bdic ~/.local/share/qtwebengine_dictionaries/
Database
Everything is in one SQLite file — easy to backup, restore, or migrate. Located
at QStandardPaths::AppDataLocation/browser.db:
history– URL, title, last visit timebookmarks– URL, title, created timepasswords– origin, username, encrypted password (ciphertext + nonce), timestampsvault_meta– key-value store for the encrypted DEK, Argon2 salt/cost parametersdomain_settings– key-value store per domain (used for zoom factor persistence)
Dependencies
- Qt6 (Widgets, WebEngineWidgets, Sql, WebChannel)
- libsodium (>= 1.0.18)
- hunspell (runtime only, for spell check dictionaries)
- CMake >= 3.21, C++17 compiler