From 42aa6f6affac4faacbce5bee0312657fe2c0b0b4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 1 Jul 2026 15:05:59 +0000 Subject: [PATCH 1/2] Modernize Electron app: fix Drive link parsing, harden security - Upgrade Electron 13.6.6 -> 43.x (plus electron-builder/electron-packager/asar) - main.js: remove nodeIntegration/webviewTag, enable contextIsolation+sandbox - preload.js: expose IPC via contextBridge instead of leaving it inert - renderer.js: use the new bridge instead of require('electron'); parse both the legacy open?id= link and the current file/d/ID/view link format (Drive's share UI no longer generates the old format); fix typo to - index.html: drop the module.exports jQuery workaround, now unnecessary without nodeIntegration --- index.html | 14 -------------- main.js | 6 ++---- package.json | 8 ++++---- preload.js | 9 +++++++-- renderer.js | 32 ++++++++++++++++++-------------- 5 files changed, 31 insertions(+), 38 deletions(-) diff --git a/index.html b/index.html index a25aec1..124e59e 100644 --- a/index.html +++ b/index.html @@ -9,21 +9,7 @@ GD Video Player - - - - - - - diff --git a/main.js b/main.js index 2d962b3..bd51bea 100644 --- a/main.js +++ b/main.js @@ -2,8 +2,6 @@ const { app, BrowserWindow } = require('electron') const path = require('path') -app.allowRendererProcessReuse = true - function createWindow() { // Create the browser window. const mainWindow = new BrowserWindow({ @@ -13,8 +11,8 @@ function createWindow() { maximizable: true, resizable: false, webPreferences: { - webviewTag: true, - nodeIntegration: true, + contextIsolation: true, + sandbox: true, preload: path.join(__dirname, 'preload.js') } }) diff --git a/package.json b/package.json index 5bae6e7..7b8659f 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,10 @@ "dist": "electron-builder" }, "devDependencies": { - "asar": "^2.1.0", - "electron": "^13.6.6", - "electron-builder": "^22.4.0", - "electron-packager": "^14.2.1" + "asar": "^3.2.0", + "electron": "^43.0.0", + "electron-builder": "^26.15.3", + "electron-packager": "^17.1.2" }, "dependencies": {}, "license": "MIT", diff --git a/preload.js b/preload.js index f9a6265..27de2f2 100644 --- a/preload.js +++ b/preload.js @@ -1,2 +1,7 @@ -// All of the Node.js APIs are available in the preload process. -// It has the same sandbox as a Chrome extension. \ No newline at end of file +const { contextBridge, ipcRenderer } = require('electron') + +contextBridge.exposeInMainWorld('gdPlayer', { + resizeWindow: (size) => ipcRenderer.send(`resize-window-${size}`), + maximize: () => ipcRenderer.send('maximize'), + toggleAlwaysOnTop: () => ipcRenderer.send('always-on-top') +}) diff --git a/renderer.js b/renderer.js index 995ce89..d999555 100644 --- a/renderer.js +++ b/renderer.js @@ -3,15 +3,23 @@ url = $('#url').val() id = null - // 입력된 값에서 ID 추출 - if (url.match(/^https:\/\/drive\.google\.com\/open\?id\=(.*)/g)) { - id = url.split('=')[1] + // 입력된 값에서 ID 추출 (기존 open?id=... 링크와 현재 file/d/ID/view 링크 모두 지원) + try { + parsed = new URL(url) + fileMatch = parsed.pathname.match(/^\/file\/d\/([^/]+)/) + if (fileMatch) { + id = fileMatch[1] + } else if (parsed.pathname === '/open' && parsed.searchParams.has('id')) { + id = parsed.searchParams.get('id') + } + } catch (e) { + id = null } // ID를 찾으면 작업 처리 if (id) { // 플레이어 삽입 스크립트 - player = '' $('#player').html(player) $('#window_size').css('display', 'inline') @@ -29,13 +37,12 @@ } $('#window_size span').click(function() { size = $(this).attr('id') - const { ipcRenderer } = require('electron') if (size == 'w_small') { - ipcRenderer.send('resize-window-small') + window.gdPlayer.resizeWindow('small') } else if (size == 'w_medium') { - ipcRenderer.send('resize-window-medium') + window.gdPlayer.resizeWindow('medium') } else if (size == 'w_large') { - ipcRenderer.send('resize-window-large') + window.gdPlayer.resizeWindow('large') } if (typeof(size_list[size]) != 'undefined') { width = size_list[size] @@ -46,13 +53,11 @@ }) $('#always_on_top').click(function() { - const { ipcRenderer } = require('electron') - ipcRenderer.send('always-on-top') + window.gdPlayer.toggleAlwaysOnTop() }) $('#maximize').click(function() { - const { ipcRenderer } = require('electron') - ipcRenderer.send('maximize') + window.gdPlayer.maximize() $('#player').css('width', "95%") $('#player').css('height', "90%") @@ -62,8 +67,7 @@ }) $('#unmaximize').click(function() { - const { ipcRenderer } = require('electron') - ipcRenderer.send('resize-window-small') + window.gdPlayer.resizeWindow('small') width = 700 height = Math.round(width * 0.5625) $('#player').css('width', width) From 62f7b2f0c76162f81127cb6776074c10c35dfdef Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 8 Jul 2026 06:04:54 +0000 Subject: [PATCH 2/2] Address Copilot review feedback on PR #22 - renderer.js: declare url/id/parsed/fileMatch/player with const/let instead of leaking as implicit globals - main.js: explicitly set nodeIntegration:false and webviewTag:false instead of relying on defaults - preload.js: whitelist the resizeWindow size argument before interpolating it into the IPC channel name --- main.js | 2 ++ preload.js | 7 ++++++- renderer.js | 10 +++++----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/main.js b/main.js index bd51bea..ae6f228 100644 --- a/main.js +++ b/main.js @@ -13,6 +13,8 @@ function createWindow() { webPreferences: { contextIsolation: true, sandbox: true, + nodeIntegration: false, + webviewTag: false, preload: path.join(__dirname, 'preload.js') } }) diff --git a/preload.js b/preload.js index 27de2f2..b140986 100644 --- a/preload.js +++ b/preload.js @@ -1,7 +1,12 @@ const { contextBridge, ipcRenderer } = require('electron') +const VALID_SIZES = ['small', 'medium', 'large'] + contextBridge.exposeInMainWorld('gdPlayer', { - resizeWindow: (size) => ipcRenderer.send(`resize-window-${size}`), + resizeWindow: (size) => { + if (!VALID_SIZES.includes(size)) return + ipcRenderer.send(`resize-window-${size}`) + }, maximize: () => ipcRenderer.send('maximize'), toggleAlwaysOnTop: () => ipcRenderer.send('always-on-top') }) diff --git a/renderer.js b/renderer.js index d999555..5113484 100644 --- a/renderer.js +++ b/renderer.js @@ -1,12 +1,12 @@ $(function() { $('#load_button').click(function() { - url = $('#url').val() - id = null + const url = $('#url').val() + let id = null // 입력된 값에서 ID 추출 (기존 open?id=... 링크와 현재 file/d/ID/view 링크 모두 지원) try { - parsed = new URL(url) - fileMatch = parsed.pathname.match(/^\/file\/d\/([^/]+)/) + const parsed = new URL(url) + const fileMatch = parsed.pathname.match(/^\/file\/d\/([^/]+)/) if (fileMatch) { id = fileMatch[1] } else if (parsed.pathname === '/open' && parsed.searchParams.has('id')) { @@ -19,7 +19,7 @@ // ID를 찾으면 작업 처리 if (id) { // 플레이어 삽입 스크립트 - player = '' + const player = '' $('#player').html(player) $('#window_size').css('display', 'inline')