Implementing Download Interception, Search, Tab Management, and Drag‑Drop Features in an Electron‑Based Browser
This article details how to build a lightweight Electron browser by assembling webview components, covering download interception, in‑page search, custom tab handling, address‑bar logic, and draggable desktop icons, with full code examples and implementation notes.
Using Electron combined with a webview allows rapid assembly of a custom browser where the primary goal is to produce a functional product for personal use.
Download Interception Feature
The download logic replaces the typical web popup with a native‑like downloader by listening to the will-download event on the BrowserWindow's session and forwarding progress updates to the renderer process.
global.WIN.webContents.session.on('will-download', (evt, item) => {
// other logic
item.on('updated', (evt, state) => {
// send real‑time progress to renderer
})
})Page Search Feature
Electron's webview provides built‑in find‑in‑page capabilities; the UI simply triggers the search box and leverages findInPage and stopFindInPage for keyword highlighting and navigation.
function toSearch() {
let timer
return () => {
if (timer) { clearTimeout(timer) }
timer = setTimeout(() => {
if (keyword.value) {
webviewRef.value.findInPage(keyword.value, { findNext: true })
} else {
webviewRef.value.stopFindInPage('clearSelection')
}
}, 200)
}
}
function closeSearch() { showSearch.value = false; webviewRef.value.stopFindInPage('clearSelection') }
function installFindPage(webview) { /* attach found‑in‑page listener */ }Current Tab Opening Feature
To prevent new windows from opening, the app intercepts the new-window disposition, sends the URL to the existing webview, and denies the default action.
app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(info => {
global.WIN?.webContents.send('webview-url-is-change')
if (info.disposition === 'new-window') {
return { action: 'allow' }
} else {
global.WIN?.webContents.send('webview-open-url', info.url)
return { action: 'deny' }
}
})
})
ipcRenderer.on('webview-open-url', (event, url) => {
try {
const reg = /http|https/g
if (webviewRef.value && reg.test(url)) { webviewRef.value.src = url }
} catch (err) { console.log(err) }
})Tab Switching Feature
Tab switching is achieved by toggling CSS visibility and leveraging Vue Router to manage the displayed component.
Address Bar Functionality
The address bar supports direct URL navigation, quick access to bookmarked sites, and keyword search, prioritizing bookmarks, then URLs, then search queries.
function toSearch(keyword) {
if (`${keyword}`.length === 0) return false
// app search
if (`${keyword}`.length < 20) {
// lookup in bookmark lists
}
// URL navigation
if (isUrl(keyword)) {
let url = /^https?:\/\//i.test(keyword) ? keyword : 'http://' + keyword
goAppNewTab(url)
return false
}
// keyword search
let searchEngine = localStorage.getItem('searchEngine') || CONFIG.searchEngine
url = searchEngine + keyword
if (!router.hasRoute('search')) {
router.addRoute({ name: 'search', path: '/search', meta: { title: '搜索', icon: 'search.svg' }, component: WebView })
keepAliveInclude.value.push('search')
}
router.push({ path: '/search', query: { url } })
setTimeout(() => Bus.$emit('toSearch', url), 20)
}Desktop Icon Drag‑and‑Drop
Because the browser window can be resized, a fixed‑size central area is used for desktop icons; drag‑enter, drag‑over, drag‑leave, and drop events update icon coordinates.
// background grid
// drag logic (Vue composition API)
import { ref, computed } from 'vue'
export default function useDrag() {
const dragging = ref(null)
const currentTarget = ref()
const desk = useDesk()
const { deskList } = storeToRefs(desk)
const { setDeskList, updateDeskData } = desk
function start(e, item) { e.target.classList.add('dragging'); e.dataTransfer.effectAllowed = 'move'; dragging.value = item; currentTarget.value = e }
function end(e) { dragging.value = null; e.target.classList.remove('dragging'); setDeskList(deskList.value); clearTimeout(timer2); timer2 = setTimeout(() => updateDeskData(), 2000) }
// ...enter, leave, over, drop implementations
return { start, end, over, enter, leave, drop }
}Installation Package
The source code is available at https://github.com/jddk/aweb-browser.git ; binaries can be downloaded from the official site or Microsoft Store, with the macOS build pending due to size constraints.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.