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