Browse Source

feat(desktop): implement clipboard write permission handling (#25998)

Brendan Allan 4 months ago
parent
commit
043a5c7c0d
1 changed files with 30 additions and 0 deletions
  1. 30 0
      packages/desktop/src/main/windows.ts

+ 30 - 0
packages/desktop/src/main/windows.ts

@@ -8,6 +8,7 @@ const root = dirname(fileURLToPath(import.meta.url))
 const rendererRoot = join(root, "../renderer")
 const rendererRoot = join(root, "../renderer")
 const rendererProtocol = "oc"
 const rendererProtocol = "oc"
 const rendererHost = "renderer"
 const rendererHost = "renderer"
+const clipboardWritePermission = "clipboard-sanitized-write"
 
 
 protocol.registerSchemesAsPrivileged([
 protocol.registerSchemesAsPrivileged([
   {
   {
@@ -107,6 +108,8 @@ export function createMainWindow() {
     },
     },
   })
   })
 
 
+  allowClipboardWrite(win)
+
   win.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
   win.webContents.session.webRequest.onBeforeSendHeaders((details, callback) => {
     const { requestHeaders } = details
     const { requestHeaders } = details
     upsertKeyValue(requestHeaders, "Access-Control-Allow-Origin", ["*"])
     upsertKeyValue(requestHeaders, "Access-Control-Allow-Origin", ["*"])
@@ -157,6 +160,8 @@ export function createLoadingWindow() {
     },
     },
   })
   })
 
 
+  allowClipboardWrite(win)
+
   loadWindow(win, "loading.html")
   loadWindow(win, "loading.html")
 
 
   return win
   return win
@@ -191,6 +196,31 @@ function loadWindow(win: BrowserWindow, html: string) {
 
 
   void win.loadURL(`${rendererProtocol}://${rendererHost}/${html}`)
   void win.loadURL(`${rendererProtocol}://${rendererHost}/${html}`)
 }
 }
+
+function allowClipboardWrite(win: BrowserWindow) {
+  win.webContents.session.setPermissionRequestHandler((webContents, permission, callback, details) => {
+    callback(
+      permission === clipboardWritePermission &&
+        isTrustedRendererUrl(details.requestingUrl) &&
+        webContents.id === win.webContents.id,
+    )
+  })
+  win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
+    if (permission !== clipboardWritePermission) return false
+    if (webContents && webContents.id !== win.webContents.id) return false
+    return isTrustedRendererUrl(details.requestingUrl) || isTrustedRendererUrl(requestingOrigin)
+  })
+}
+
+function isTrustedRendererUrl(value?: string) {
+  if (!value || !URL.canParse(value)) return false
+  const url = new URL(value)
+  if (url.protocol === `${rendererProtocol}:` && url.host === rendererHost) return true
+  const devUrl = process.env.ELECTRON_RENDERER_URL
+  if (!devUrl || !URL.canParse(devUrl)) return false
+  return url.origin === new URL(devUrl).origin
+}
+
 function wireZoom(win: BrowserWindow) {
 function wireZoom(win: BrowserWindow) {
   win.webContents.setZoomFactor(1)
   win.webContents.setZoomFactor(1)
   win.webContents.on("zoom-changed", () => {
   win.webContents.on("zoom-changed", () => {