diff --git a/main.js b/main.js index 4b77b9d..b5de314 100644 --- a/main.js +++ b/main.js @@ -149,44 +149,39 @@ app.whenReady().then(async () => { }); // Optimize session settings for performance and OAuth compatibility - const ses = session.defaultSession; - + const sessionsToConfigure = [session.fromPartition('persist:main'), session.defaultSession]; try { - // Configure session for OAuth compatibility (Google, etc.) - ses.setPermissionRequestHandler((webContents, permission, callback) => { - // Allow necessary permissions for OAuth flows - if (['notifications', 'geolocation', 'camera', 'microphone'].includes(permission)) { - callback(false); // Deny by default for privacy - } else { - callback(true); // Allow others like storage access - } - }); + for (const ses of sessionsToConfigure) { + // Configure session for OAuth compatibility (Google, etc.) + ses.setPermissionRequestHandler((webContents, permission, callback) => { + // Allow necessary permissions for OAuth flows + if (['notifications', 'geolocation', 'camera', 'microphone'].includes(permission)) { + callback(false); // Deny by default for privacy + } else { + callback(true); // Allow others like storage access + } + }); - // Configure user agent for better compatibility - ses.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Nebula/1.0.0'); - - // Configure cookies for OAuth compatibility - ses.cookies.on('changed', (event, cookie, cause, removed) => { - // Log cookie changes for debugging OAuth issues - if (cookie.domain.includes('google') || cookie.domain.includes('accounts')) { - console.log(`Cookie ${removed ? 'removed' : 'added'}: ${cookie.name} for ${cookie.domain}`); - } - }); - - // Enable request/response caching - ses.webRequest.onBeforeSendHeaders((details, callback) => { - // Add headers for better OAuth compatibility - details.requestHeaders['Cache-Control'] = 'max-age=3600'; - // Ensure we accept third-party cookies for OAuth flows - details.requestHeaders['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'; - // Add referrer policy for OAuth compatibility - if (details.url.includes('accounts.google.com') || details.url.includes('oauth')) { - details.requestHeaders['Referrer-Policy'] = 'strict-origin-when-cross-origin'; - } - callback({ requestHeaders: details.requestHeaders }); - }); - - // Skip preload registration as it's handled in window options + // Configure user agent for better compatibility + ses.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Nebula/1.0.0'); + + // Configure cookies for OAuth compatibility + ses.cookies.on('changed', (event, cookie, cause, removed) => { + // Log cookie changes for debugging OAuth issues + if (cookie.domain && (cookie.domain.includes('google') || cookie.domain.includes('accounts'))) { + console.log(`Cookie ${removed ? 'removed' : 'added'}: ${cookie.name} for ${cookie.domain}`); + } + }); + + // Optional: add headers only for OAuth flows; avoid forcing cache headers globally + ses.webRequest.onBeforeSendHeaders((details, callback) => { + if (details.url.includes('accounts.google.com') || details.url.includes('oauth')) { + details.requestHeaders['Referrer-Policy'] = 'strict-origin-when-cross-origin'; + details.requestHeaders['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'; + } + callback({ requestHeaders: details.requestHeaders }); + }); + } console.log('Session configured successfully for OAuth compatibility'); } catch (err) { console.error('Session setup error:', err); @@ -330,26 +325,35 @@ ipcMain.handle('save-bookmarks', async (event, bookmarks) => { ipcMain.handle('clear-browser-data', async () => { try { - const ses = session.defaultSession; + const sessionsToClear = [session.defaultSession, session.fromPartition('persist:main')]; - // Clear cookies - await ses.clearStorageData({ storages: ['cookies'] }); - - // Clear local storage and other storage data - await ses.clearStorageData({ storages: ['localstorage', 'indexdb', 'filesystem', 'websql'] }); - - // Clear cache - await ses.clearCache(); - - // Clear HTTP authentication cache - await ses.clearAuthCache(); - - // Clear all cookies explicitly to ensure logged-in accounts are logged out - const cookies = await ses.cookies.get({}); - for (const cookie of cookies) { - await ses.cookies.remove(cookie.url, cookie.name); + for (const ses of sessionsToClear) { + if (!ses) continue; + // Clear all common site storage types + await ses.clearStorageData({ + storages: [ + 'cookies', + 'localstorage', + 'indexdb', + 'filesystem', + 'websql', + 'serviceworkers', + 'caches', + 'shadercache', + 'appcache' + ], + }); + // Clear caches and auth + await ses.clearCache(); + await ses.clearAuthCache(); } + // Also reset on-disk history JSON files managed by the app + const siteHistoryPath = path.join(__dirname, 'site-history.json'); + const searchHistoryPath = path.join(__dirname, 'search-history.json'); + try { await fs.promises.writeFile(siteHistoryPath, JSON.stringify([], null, 2)); } catch {} + try { await fs.promises.writeFile(searchHistoryPath, JSON.stringify([], null, 2)); } catch {} + return true; // Indicate success } catch (error) { console.error('Failed to clear browser data:', error); @@ -357,6 +361,17 @@ ipcMain.handle('clear-browser-data', async () => { } }); +// Optional: standalone clear for search history JSON +ipcMain.handle('clear-search-history', async () => { + const filePath = path.join(__dirname, 'search-history.json'); + try { + await fs.promises.writeFile(filePath, JSON.stringify([], null, 2)); + return true; + } catch (err) { + return false; + } +}); + ipcMain.handle('get-zoom-factor', event => { const wc = BrowserWindow.fromWebContents(event.sender).webContents; return wc.getZoomFactor(); diff --git a/renderer/index.html b/renderer/index.html index b0a552d..ea4a628 100644 --- a/renderer/index.html +++ b/renderer/index.html @@ -51,6 +51,8 @@ 100% + + diff --git a/renderer/script.js b/renderer/script.js index 53ec068..92fbe76 100644 --- a/renderer/script.js +++ b/renderer/script.js @@ -674,6 +674,30 @@ function reload() { } } +function hardReload() { + const webview = document.getElementById(`tab-${activeTabId}`); + if (webview && typeof webview.reloadIgnoringCache === 'function') { + webview.reloadIgnoringCache(); + scheduleUpdateNavButtons(); + } else if (webview) { + // Fallback + webview.reload(); + } +} + +function freshReload() { + const webview = document.getElementById(`tab-${activeTabId}`); + if (!webview) return; + try { + const u = new URL(webview.getURL()); + u.searchParams.set('_bust', Date.now().toString()); + webview.src = u.toString(); + } catch { + // If URL parsing fails (e.g., internal pages), fall back to hard reload + hardReload(); + } +} + // Function to open the Settings page function openSettings() { createTab('browser://settings'); @@ -776,6 +800,10 @@ window.addEventListener('DOMContentLoaded', () => { // only now bind the reload button (guaranteed to exist) const reloadBtn = document.getElementById('reload-btn'); reloadBtn.addEventListener('click', reload); + const hardReloadBtn = document.getElementById('hard-reload-btn'); + if (hardReloadBtn) hardReloadBtn.addEventListener('click', hardReload); + const freshReloadBtn = document.getElementById('fresh-reload-btn'); + if (freshReloadBtn) freshReloadBtn.addEventListener('click', freshReload); // bind zoom buttons (single binding) const zoomInBtn = document.getElementById('zoom-in-btn'); diff --git a/renderer/settings.js b/renderer/settings.js index 9ab0647..50984a7 100644 --- a/renderer/settings.js +++ b/renderer/settings.js @@ -1,13 +1,7 @@ -// Try to get ipcRenderer, but don't fail if it's not available -let ipcRenderer = null; -try { - if (typeof require !== 'undefined') { - const electron = require('electron'); - ipcRenderer = electron.ipcRenderer; - } -} catch (e) { - console.log('[SETTINGS] Electron IPC not available, some features may be limited'); -} +// Prefer contextBridge-exposed API +const ipc = (window.electronAPI && typeof window.electronAPI.invoke === 'function') + ? window.electronAPI + : null; let clearBtn = document.getElementById('clear-data-btn'); const statusDiv = document.getElementById('status'); @@ -39,14 +33,18 @@ function attachClearHandler(btn) { btn.onclick = async () => { if (statusDiv && statusText) { statusDiv.classList.remove('hidden'); - statusText.textContent = 'Clearing all browser data...'; + statusText.textContent = 'Clearing cookies, storage, cache, and history...'; } try { - if (ipcRenderer) { - const ok = await ipcRenderer.invoke('clear-browser-data'); + if (ipc) { + const ok = await ipc.invoke('clear-browser-data'); + // Also clear localStorage site history in this context + try { localStorage.removeItem('siteHistory'); } catch {} + // Try to refresh lists if present + try { if (typeof loadHistories === 'function') await loadHistories(); } catch {} showStatus(ok - ? 'All browser data and bookmarks cleared!' + ? 'All browser data cleared.' : 'Failed to clear browser data.'); } else { showStatus('Clear data feature not available in this context.'); @@ -70,6 +68,36 @@ window.addEventListener('DOMContentLoaded', () => { clearBtn = document.getElementById('clear-data-btn'); attachClearHandler(clearBtn); } + + // Wire per-section clear buttons to main when possible + const clearSiteBtn = document.getElementById('clear-site-history-btn'); + if (clearSiteBtn) { + clearSiteBtn.addEventListener('click', async () => { + try { + // Clear localStorage copy + try { localStorage.removeItem('siteHistory'); } catch {} + // Ask main to clear file-based history for consistency + if (ipc) { await ipc.invoke('clear-site-history'); } + showStatus('Site history cleared'); + try { if (typeof loadHistories === 'function') await loadHistories(); } catch {} + } catch (e) { + console.error('Clear site history error:', e); + showStatus('Failed clearing site history'); + } + }); + } + const clearSearchBtn = document.getElementById('clear-search-history-btn'); + if (clearSearchBtn) { + clearSearchBtn.addEventListener('click', async () => { + try { + if (ipc) { await ipc.invoke('clear-search-history'); } + showStatus('Search history cleared'); + } catch (e) { + console.error('Clear search history error:', e); + showStatus('Failed clearing search history'); + } + }); + } }); // Tabs: simple controller diff --git a/search-history.json b/search-history.json index c44dc44..0637a08 100644 --- a/search-history.json +++ b/search-history.json @@ -1,3 +1 @@ -[ - -] \ No newline at end of file +[] \ No newline at end of file