Merge branch 'SteamOS' of https://github.com/NebulaZMG/NebulaBrowser into SteamOS
This commit is contained in:
+24
@@ -86,3 +86,27 @@ typings/
|
|||||||
site-history.json
|
site-history.json
|
||||||
bookmarks.json
|
bookmarks.json
|
||||||
bookmarks.backup.json
|
bookmarks.backup.json
|
||||||
|
|
||||||
|
# AppImage / SteamOS
|
||||||
|
squashfs-root/
|
||||||
|
*.AppImage
|
||||||
|
|
||||||
|
# Electron build output
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
release/
|
||||||
|
|
||||||
|
# Native binaries
|
||||||
|
nebula
|
||||||
|
nebula.exe
|
||||||
|
|
||||||
|
# Node/Electron
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
nebula-appdir/
|
||||||
|
*.asar
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
Converting extracted AppImage (`squashfs-root`) into a distributable AppDir for Steam
|
||||||
|
|
||||||
|
If your environment lacks `rsync`, use `cp -a` to copy the extracted AppImage into a clean AppDir and prepare it for upload to Steam.
|
||||||
|
|
||||||
|
1) Copy the extracted AppImage to an AppDir folder
|
||||||
|
```bash
|
||||||
|
cp -a squashfs-root/ nebula-appdir
|
||||||
|
```
|
||||||
|
|
||||||
|
2) Unpack `app.asar` to edit or include app sources (optional; requires `npx asar`)
|
||||||
|
```bash
|
||||||
|
cd nebula-appdir/resources
|
||||||
|
npx asar extract app.asar app
|
||||||
|
# keep a backup if you want
|
||||||
|
mv app app.orig && rm app.asar
|
||||||
|
cd ../../
|
||||||
|
```
|
||||||
|
|
||||||
|
3) Add/verify launcher (we added `nebula-appdir/Nebula`):
|
||||||
|
```bash
|
||||||
|
chmod +x nebula-appdir/Nebula
|
||||||
|
```
|
||||||
|
Run locally:
|
||||||
|
```bash
|
||||||
|
cd nebula-appdir
|
||||||
|
./Nebula
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Ensure binary & permissions are correct
|
||||||
|
```bash
|
||||||
|
chmod +x nebula-appdir/nebula
|
||||||
|
```
|
||||||
|
|
||||||
|
5) Package or upload to Steam
|
||||||
|
- Create a tarball to upload as game files, or upload the AppDir contents as the depot.
|
||||||
|
```bash
|
||||||
|
tar -czf nebula-appdir.tar.gz -C nebula-appdir .
|
||||||
|
```
|
||||||
|
- In Steamworks, set the launch command to `./Nebula` (or `./nebula`).
|
||||||
|
|
||||||
|
Notes
|
||||||
|
- `--no-sandbox` reduces Chromium sandboxing; prefer fixing `chrome-sandbox` and enabling sandboxing when possible.
|
||||||
|
- Using the AppDir avoids AppImage/FUSE dependency on target systems.
|
||||||
|
- Test on a clean SteamOS/Deck image before publishing.
|
||||||
|
|
||||||
|
Big Picture auto-start (SteamOS Gaming Mode)
|
||||||
|
- If Nebula is launched from SteamOS Gaming Mode, it will auto-start in Big Picture Mode.
|
||||||
|
- To force/disable via Steam Launch Options: `--big-picture` or `--no-big-picture`.
|
||||||
@@ -42,6 +42,14 @@ Nebula Browser includes a **Big Picture Mode** - a controller-friendly, console-
|
|||||||
### Automatic Detection
|
### Automatic Detection
|
||||||
If Nebula detects a Steam Deck-sized display (1280x800), it will suggest Big Picture Mode in settings.
|
If Nebula detects a Steam Deck-sized display (1280x800), it will suggest Big Picture Mode in settings.
|
||||||
|
|
||||||
|
### Auto-start in SteamOS Gaming Mode
|
||||||
|
When Nebula is launched from SteamOS **Gaming Mode** (gamescope / Steam gamepad UI), it will automatically start in **Big Picture Mode**.
|
||||||
|
|
||||||
|
You can override this behavior:
|
||||||
|
- Force Big Picture at launch: launch options `--big-picture` (or `--bigpicture`)
|
||||||
|
- Disable Big Picture auto-start: launch options `--no-big-picture` (or `--no-bigpicture`)
|
||||||
|
- Environment overrides: `NEBULA_BIG_PICTURE=1` / `NEBULA_NO_BIG_PICTURE=1`
|
||||||
|
|
||||||
## Navigation Sections
|
## Navigation Sections
|
||||||
|
|
||||||
| Section | Description |
|
| Section | Description |
|
||||||
|
|||||||
+16
-2
@@ -20,6 +20,15 @@ class GPUConfig {
|
|||||||
// Start with conservative settings that usually work
|
// Start with conservative settings that usually work
|
||||||
this.applyConservativeSettings();
|
this.applyConservativeSettings();
|
||||||
|
|
||||||
|
// On Linux/SteamOS, force disable GPU and sandbox to ensure webview stability
|
||||||
|
if (platform === 'linux') {
|
||||||
|
console.log('Linux detected: Disabling GPU and enforcing no-sandbox');
|
||||||
|
app.commandLine.appendSwitch('disable-gpu');
|
||||||
|
app.commandLine.appendSwitch('no-sandbox');
|
||||||
|
this.fallbackApplied = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to enable GPU features progressively
|
// Try to enable GPU features progressively
|
||||||
this.tryEnableGPU();
|
this.tryEnableGPU();
|
||||||
}
|
}
|
||||||
@@ -43,8 +52,13 @@ class GPUConfig {
|
|||||||
// GPU acceleration switches
|
// GPU acceleration switches
|
||||||
app.commandLine.appendSwitch('ignore-gpu-blacklist');
|
app.commandLine.appendSwitch('ignore-gpu-blacklist');
|
||||||
app.commandLine.appendSwitch('ignore-gpu-blocklist');
|
app.commandLine.appendSwitch('ignore-gpu-blocklist');
|
||||||
app.commandLine.appendSwitch('enable-gpu-rasterization');
|
|
||||||
app.commandLine.appendSwitch('enable-zero-copy');
|
// On Linux/SteamOS, these aggressive flags can cause webview rendering issues (black screen)
|
||||||
|
// We disable them for Linux to ensure stability
|
||||||
|
if (process.platform !== 'linux') {
|
||||||
|
app.commandLine.appendSwitch('enable-gpu-rasterization');
|
||||||
|
app.commandLine.appendSwitch('enable-zero-copy');
|
||||||
|
}
|
||||||
|
|
||||||
// Video acceleration (usually safer than full GPU)
|
// Video acceleration (usually safer than full GPU)
|
||||||
app.commandLine.appendSwitch('enable-accelerated-video-decode');
|
app.commandLine.appendSwitch('enable-accelerated-video-decode');
|
||||||
|
|||||||
@@ -72,6 +72,53 @@ ipcMain.removeHandler('window-close');
|
|||||||
// BIG PICTURE MODE - Steam Deck / Console UI
|
// BIG PICTURE MODE - Steam Deck / Console UI
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
function envTruthy(value) {
|
||||||
|
if (value === undefined || value === null) return false;
|
||||||
|
const s = String(value).trim().toLowerCase();
|
||||||
|
return s === '1' || s === 'true' || s === 'yes' || s === 'on';
|
||||||
|
}
|
||||||
|
|
||||||
|
function argvHasFlag(flag) {
|
||||||
|
return process.argv.includes(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Heuristic: detect Steam Deck / SteamOS Gaming Mode (gamescope) launches.
|
||||||
|
*
|
||||||
|
* This is intentionally conservative and only used for picking the *default*
|
||||||
|
* startup UI. Users can override via CLI/env.
|
||||||
|
*/
|
||||||
|
function isGameModeEnvironment() {
|
||||||
|
const env = process.env;
|
||||||
|
|
||||||
|
// Common Steam tenfoot / gamepad UI markers
|
||||||
|
if (envTruthy(env.STEAM_GAMEPADUI)) return true;
|
||||||
|
if (envTruthy(env.SteamTenfoot)) return true;
|
||||||
|
if (envTruthy(env.STEAM_TENFOOT)) return true;
|
||||||
|
|
||||||
|
// SteamOS / gamescope compositor markers
|
||||||
|
const currentDesktop = String(env.XDG_CURRENT_DESKTOP || '').toLowerCase();
|
||||||
|
const sessionDesktop = String(env.XDG_SESSION_DESKTOP || '').toLowerCase();
|
||||||
|
if (currentDesktop.includes('gamescope') || sessionDesktop.includes('gamescope')) return true;
|
||||||
|
|
||||||
|
if (env.GAMESCOPE_WSI || env.GAMESCOPE_SESSION || env.GAMESCOPE_FOCUSED_APP) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldStartInBigPictureMode() {
|
||||||
|
// Explicit CLI overrides first
|
||||||
|
if (argvHasFlag('--no-big-picture') || argvHasFlag('--no-bigpicture')) return false;
|
||||||
|
if (argvHasFlag('--big-picture') || argvHasFlag('--bigpicture') || argvHasFlag('--tenfoot') || argvHasFlag('--game-mode')) return true;
|
||||||
|
|
||||||
|
// Explicit env overrides
|
||||||
|
if (envTruthy(process.env.NEBULA_NO_BIG_PICTURE) || envTruthy(process.env.NEBULA_NO_BIGPICTURE)) return false;
|
||||||
|
if (envTruthy(process.env.NEBULA_BIG_PICTURE) || envTruthy(process.env.NEBULA_BIGPICTURE) || envTruthy(process.env.NEBULA_GAME_MODE)) return true;
|
||||||
|
|
||||||
|
// Auto-detect SteamOS Gaming Mode
|
||||||
|
return isGameModeEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
// Steam Deck screen dimensions: 1280x800
|
// Steam Deck screen dimensions: 1280x800
|
||||||
const STEAM_DECK_WIDTH = 1280;
|
const STEAM_DECK_WIDTH = 1280;
|
||||||
const STEAM_DECK_HEIGHT = 800;
|
const STEAM_DECK_HEIGHT = 800;
|
||||||
@@ -503,7 +550,17 @@ function configureSessionsAsync() {
|
|||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
const t0 = performance.now();
|
const t0 = performance.now();
|
||||||
createWindow();
|
|
||||||
|
// If launched via SteamOS Gaming Mode / gamepad UI, default to Big Picture Mode.
|
||||||
|
// Desktop launches remain unchanged.
|
||||||
|
const startInBigPicture = shouldStartInBigPictureMode();
|
||||||
|
if (startInBigPicture) {
|
||||||
|
console.log('[Startup] Detected game mode launch; starting in Big Picture Mode');
|
||||||
|
createBigPictureWindow();
|
||||||
|
} else {
|
||||||
|
createWindow();
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize user plugins after app ready
|
// Initialize user plugins after app ready
|
||||||
try {
|
try {
|
||||||
pluginManager.ensureUserPluginsDir();
|
pluginManager.ensureUserPluginsDir();
|
||||||
@@ -512,7 +569,7 @@ app.whenReady().then(() => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[Plugins] initialization error:', e);
|
console.error('[Plugins] initialization error:', e);
|
||||||
}
|
}
|
||||||
console.log('[Startup] createWindow invoked in', (performance.now() - t0).toFixed(1), 'ms after app.whenReady');
|
console.log('[Startup] initial window created (', startInBigPicture ? 'bigpicture' : 'desktop', ') in', (performance.now() - t0).toFixed(1), 'ms after app.whenReady');
|
||||||
|
|
||||||
// Handle GPU process crashes (still register early)
|
// Handle GPU process crashes (still register early)
|
||||||
app.on('gpu-process-crashed', (event, killed) => {
|
app.on('gpu-process-crashed', (event, killed) => {
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Assemble nebula-appdir from extracted squashfs-root
|
||||||
|
set -euo pipefail
|
||||||
|
SRC="${1:-squashfs-root}"
|
||||||
|
DEST="${2:-nebula-appdir}"
|
||||||
|
|
||||||
|
if [ ! -d "$SRC" ]; then
|
||||||
|
echo "Source $SRC not found. Extract the AppImage first (./dist/Nebula-*.AppImage --appimage-extract)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy extracted contents into DEST
|
||||||
|
mkdir -p "$DEST"
|
||||||
|
cp -a "$SRC/." "$DEST/"
|
||||||
|
|
||||||
|
# Ensure launcher/binary exist
|
||||||
|
if [ -f "$DEST/run-nebula.sh" ]; then
|
||||||
|
mv "$DEST/run-nebula.sh" "$DEST/Nebula" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
chmod +x "$DEST/Nebula" || true
|
||||||
|
|
||||||
|
# Ensure directories for icons and desktop entries
|
||||||
|
mkdir -p "$DEST/usr/share/icons/hicolor/256x256/apps"
|
||||||
|
mkdir -p "$DEST/usr/share/applications"
|
||||||
|
|
||||||
|
# Copy icon if present at top level of extracted AppImage
|
||||||
|
if [ -f "$SRC/nebula.png" ]; then
|
||||||
|
cp "$SRC/nebula.png" "$DEST/usr/share/icons/hicolor/256x256/apps/nebula.png"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Also embed project icon if present in repo assets
|
||||||
|
PROJECT_ICON="$(cd "$(dirname "$0")" && pwd)/assets/images/Logos/Nebula-Favicon.png"
|
||||||
|
if [ -f "$PROJECT_ICON" ]; then
|
||||||
|
echo "Embedding project icon into AppDir: $PROJECT_ICON"
|
||||||
|
cp "$PROJECT_ICON" "$DEST/usr/share/icons/hicolor/256x256/apps/nebula.png"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install desktop file into AppDir
|
||||||
|
if [ -f "$DEST/nebula.desktop" ]; then
|
||||||
|
cp "$DEST/nebula.desktop" "$DEST/usr/share/applications/nebula.desktop"
|
||||||
|
else
|
||||||
|
cat > "$DEST/usr/share/applications/nebula.desktop" <<'EOF'
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Nebula
|
||||||
|
Comment=Nebula Browser
|
||||||
|
Exec=./Nebula %U
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Icon=nebula
|
||||||
|
Categories=Network;WebBrowser;
|
||||||
|
StartupWMClass=Nebula
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fix permissions
|
||||||
|
chmod -R a+r "$DEST/usr/share/icons/hicolor/256x256/apps" || true
|
||||||
|
chmod +x "$DEST/Nebula" || true
|
||||||
|
|
||||||
|
echo "AppDir assembled at $DEST. Run with: $DEST/Nebula"
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron .",
|
"start": "electron .",
|
||||||
|
"start:dev": "electron . --no-sandbox --disable-gpu",
|
||||||
|
"start:linux": "electron . --no-sandbox",
|
||||||
"dist": "electron-builder",
|
"dist": "electron-builder",
|
||||||
"run": "electron ."
|
"run": "electron ."
|
||||||
},
|
},
|
||||||
|
|||||||
+27
@@ -1,5 +1,11 @@
|
|||||||
// preload.js - Optimized version
|
// preload.js - Optimized version
|
||||||
const { contextBridge, ipcRenderer } = require('electron');
|
const { contextBridge, ipcRenderer } = require('electron');
|
||||||
|
let pathModule;
|
||||||
|
try {
|
||||||
|
pathModule = require('path');
|
||||||
|
} catch (err) {
|
||||||
|
pathModule = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Cache DOM references for performance
|
// Cache DOM references for performance
|
||||||
let domReady = false;
|
let domReady = false;
|
||||||
@@ -75,6 +81,27 @@ const electronAPI = {
|
|||||||
saveImageFromNet: async (url) => ipcRenderer.invoke('save-image-from-url', { url })
|
saveImageFromNet: async (url) => ipcRenderer.invoke('save-image-from-url', { url })
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Provide absolute path to the renderer preload for webview guests so
|
||||||
|
// webview `preload` attributes use an absolute, resolvable path on all platforms.
|
||||||
|
const webviewPreloadAbsolutePath = pathModule ? pathModule.join(__dirname, 'preload.js') : null;
|
||||||
|
electronAPI.getWebviewPreloadPath = () => webviewPreloadAbsolutePath;
|
||||||
|
|
||||||
|
// Fixup any static <webview preload="..."> attributes in the DOM early so
|
||||||
|
// guests receive an absolute path instead of a relative one that may fail
|
||||||
|
// to resolve inside the guest process.
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
try {
|
||||||
|
if (webviewPreloadAbsolutePath) {
|
||||||
|
const els = document.querySelectorAll('webview[preload]');
|
||||||
|
for (const el of els) {
|
||||||
|
try { el.setAttribute('preload', webviewPreloadAbsolutePath); } catch {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// non-fatal
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Cache for bookmarks to reduce IPC calls
|
// Cache for bookmarks to reduce IPC calls
|
||||||
let bookmarksCache = null;
|
let bookmarksCache = null;
|
||||||
let bookmarksCacheTime = 0;
|
let bookmarksCacheTime = 0;
|
||||||
|
|||||||
+73
-14
@@ -594,32 +594,91 @@ function goForward() {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
function initGamepadSupport() {
|
function initGamepadSupport() {
|
||||||
|
if (!navigator.getGamepads) {
|
||||||
|
console.warn('[BigPicture] Gamepad API not available in this environment');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: On Linux (and some controllers like handheld integrated gamepads),
|
||||||
|
// the `gamepadconnected` event may not fire until the first button press,
|
||||||
|
// or at all. We rely on continuous polling for robustness.
|
||||||
window.addEventListener('gamepadconnected', (e) => {
|
window.addEventListener('gamepadconnected', (e) => {
|
||||||
console.log('[BigPicture] Gamepad connected:', e.gamepad.id);
|
console.log('[BigPicture] Gamepad connected:', e.gamepad?.id || 'unknown');
|
||||||
state.gamepadConnected = true;
|
// Prefer the first connected controller as the active one.
|
||||||
state.gamepadIndex = e.gamepad.index;
|
if (state.gamepadIndex === null) {
|
||||||
showToast('Controller connected');
|
state.gamepadConnected = true;
|
||||||
|
state.gamepadIndex = e.gamepad.index;
|
||||||
|
showToast('Controller connected');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('gamepaddisconnected', (e) => {
|
window.addEventListener('gamepaddisconnected', (e) => {
|
||||||
console.log('[BigPicture] Gamepad disconnected');
|
console.log('[BigPicture] Gamepad disconnected:', e.gamepad?.id || 'unknown');
|
||||||
state.gamepadConnected = false;
|
// If the active controller disconnected, clear it; polling will auto-select another.
|
||||||
state.gamepadIndex = null;
|
if (state.gamepadIndex === e.gamepad.index) {
|
||||||
showToast('Controller disconnected');
|
state.gamepadConnected = false;
|
||||||
|
state.gamepadIndex = null;
|
||||||
|
showToast('Controller disconnected');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Initial scan (covers controllers that are already connected at load).
|
||||||
|
refreshActiveGamepad(true);
|
||||||
|
|
||||||
// Start polling for gamepad input
|
// Start polling for gamepad input
|
||||||
requestAnimationFrame(pollGamepad);
|
requestAnimationFrame(pollGamepad);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pollGamepad() {
|
function getFirstConnectedGamepad(gamepads) {
|
||||||
if (state.gamepadConnected && state.gamepadIndex !== null) {
|
if (!gamepads) return null;
|
||||||
const gamepads = navigator.getGamepads();
|
for (let i = 0; i < gamepads.length; i++) {
|
||||||
const gamepad = gamepads[state.gamepadIndex];
|
const gp = gamepads[i];
|
||||||
|
if (gp) return gp;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (gamepad) {
|
function refreshActiveGamepad(isInitial = false) {
|
||||||
handleGamepadInput(gamepad);
|
const gamepads = navigator.getGamepads();
|
||||||
|
|
||||||
|
// If we have an index, verify it still points to a real gamepad.
|
||||||
|
let active = null;
|
||||||
|
if (state.gamepadIndex !== null) {
|
||||||
|
active = gamepads[state.gamepadIndex] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: pick the first connected controller.
|
||||||
|
if (!active) {
|
||||||
|
active = getFirstConnectedGamepad(gamepads);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
const changed = !state.gamepadConnected || state.gamepadIndex !== active.index;
|
||||||
|
state.gamepadConnected = true;
|
||||||
|
state.gamepadIndex = active.index;
|
||||||
|
if (changed && !isInitial) {
|
||||||
|
console.log('[BigPicture] Active gamepad selected:', active.id);
|
||||||
|
showToast('Controller connected');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (state.gamepadConnected) {
|
||||||
|
state.gamepadConnected = false;
|
||||||
|
state.gamepadIndex = null;
|
||||||
|
if (!isInitial) {
|
||||||
|
showToast('Controller disconnected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.gamepadConnected = false;
|
||||||
|
state.gamepadIndex = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { gamepads, active };
|
||||||
|
}
|
||||||
|
|
||||||
|
function pollGamepad() {
|
||||||
|
const { active } = refreshActiveGamepad(false);
|
||||||
|
if (active) {
|
||||||
|
handleGamepadInput(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAnimationFrame(pollGamepad);
|
requestAnimationFrame(pollGamepad);
|
||||||
|
|||||||
+18
-2
@@ -368,7 +368,16 @@ function createTab(inputUrl) {
|
|||||||
webview.src = resolvedUrl;
|
webview.src = resolvedUrl;
|
||||||
webview.setAttribute('allowpopups', '');
|
webview.setAttribute('allowpopups', '');
|
||||||
webview.setAttribute('partition', 'persist:main');
|
webview.setAttribute('partition', 'persist:main');
|
||||||
webview.setAttribute('preload', '../preload.js');
|
// Use absolute preload path provided by the main-window preload to ensure
|
||||||
|
// the guest process can resolve the file (important on Linux/SteamOS).
|
||||||
|
try {
|
||||||
|
const preloadPath = (window.electronAPI && typeof window.electronAPI.getWebviewPreloadPath === 'function')
|
||||||
|
? window.electronAPI.getWebviewPreloadPath()
|
||||||
|
: '../preload.js';
|
||||||
|
webview.setAttribute('preload', preloadPath);
|
||||||
|
} catch (e) {
|
||||||
|
webview.setAttribute('preload', '../preload.js');
|
||||||
|
}
|
||||||
// Add attributes needed for Google OAuth and sign-in flows
|
// Add attributes needed for Google OAuth and sign-in flows
|
||||||
webview.setAttribute('webpreferences', 'allowRunningInsecureContent=false,javascript=true,webSecurity=true');
|
webview.setAttribute('webpreferences', 'allowRunningInsecureContent=false,javascript=true,webSecurity=true');
|
||||||
try {
|
try {
|
||||||
@@ -667,7 +676,14 @@ function convertHomeTabToWebview(tabId, inputUrl, resolvedUrl) {
|
|||||||
webview.src = resolvedUrl;
|
webview.src = resolvedUrl;
|
||||||
webview.setAttribute('allowpopups', '');
|
webview.setAttribute('allowpopups', '');
|
||||||
webview.setAttribute('partition', 'persist:main');
|
webview.setAttribute('partition', 'persist:main');
|
||||||
webview.setAttribute('preload', '../preload.js');
|
try {
|
||||||
|
const preloadPath = (window.electronAPI && typeof window.electronAPI.getWebviewPreloadPath === 'function')
|
||||||
|
? window.electronAPI.getWebviewPreloadPath()
|
||||||
|
: '../preload.js';
|
||||||
|
webview.setAttribute('preload', preloadPath);
|
||||||
|
} catch (e) {
|
||||||
|
webview.setAttribute('preload', '../preload.js');
|
||||||
|
}
|
||||||
// Add attributes needed for Google OAuth and sign-in flows
|
// Add attributes needed for Google OAuth and sign-in flows
|
||||||
webview.setAttribute('webpreferences', 'allowRunningInsecureContent=false,javascript=true,webSecurity=true');
|
webview.setAttribute('webpreferences', 'allowRunningInsecureContent=false,javascript=true,webSecurity=true');
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user