diff --git a/src/browser/index.jsx b/src/browser/index.jsx index eee3ffaa..ea2b2739 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -15,6 +15,7 @@ const AppConfig = require('./config/AppConfig.js'); const url = require('url'); const badge = require('./js/badge'); +const utils = require('../utils/util'); remote.getCurrentWindow().removeAllListeners('focus'); @@ -86,12 +87,59 @@ function showUnreadBadge(unreadCount, mentionCount) { } } +const permissionRequestQueue = []; +const requestingPermission = new Array(AppConfig.data.teams.length); + function teamConfigChange(teams) { AppConfig.set('teams', teams); + requestingPermission.length = teams.length; ipcRenderer.send('update-menu', AppConfig.data); ipcRenderer.send('update-config'); } +function feedPermissionRequest() { + const webviews = document.getElementsByTagName('webview'); + const webviewOrigins = Array.from(webviews).map((w) => utils.getDomain(w.getAttribute('src'))); + for (let index = 0; index < requestingPermission.length; index++) { + if (requestingPermission[index]) { + break; + } + for (const request of permissionRequestQueue) { + if (request.origin === webviewOrigins[index]) { + requestingPermission[index] = request; + break; + } + } + } +} + +function handleClickPermissionDialog(index, status) { + const requesting = requestingPermission[index]; + ipcRenderer.send('update-permission', requesting.origin, requesting.permission, status); + if (status === 'allow' || status === 'block') { + const newRequests = permissionRequestQueue.filter((request) => { + if (request.permission === requesting.permission && request.origin === requesting.origin) { + return false; + } + return true; + }); + permissionRequestQueue.splice(0, permissionRequestQueue.length, ...newRequests); + } else if (status === 'close') { + const i = permissionRequestQueue.findIndex((e) => e.permission === requesting.permission && e.origin === requesting.origin); + permissionRequestQueue.splice(i, 1); + } + requestingPermission[index] = null; + feedPermissionRequest(); +} + +ipcRenderer.on('request-permission', (event, origin, permission) => { + if (permissionRequestQueue.length >= 100) { + return; + } + permissionRequestQueue.push({origin, permission}); + feedPermissionRequest(); +}); + function handleSelectSpellCheckerLocale(locale) { console.log(locale); AppConfig.set('spellCheckerLocale', locale); @@ -117,6 +165,8 @@ ReactDOM.render( onSelectSpellCheckerLocale={handleSelectSpellCheckerLocale} deeplinkingUrl={deeplinkingUrl} showAddServerButton={AppConfig.data.enableServerManagement} + requestingPermission={requestingPermission} + onClickPermissionDialog={handleClickPermissionDialog} />, document.getElementById('content') ); diff --git a/src/main/permissionRequestHandler.js b/src/main/permissionRequestHandler.js index f9525e84..cb67eb75 100644 --- a/src/main/permissionRequestHandler.js +++ b/src/main/permissionRequestHandler.js @@ -1,4 +1,4 @@ -const {dialog} = require('electron'); +const {ipcMain} = require('electron'); const {URL} = require('url'); const fs = require('fs'); @@ -54,8 +54,41 @@ class PermissionManager { } } +function dequeueRequests(requestQueue, permissionManager, origin, permission, status) { + switch (status) { + case 'allow': + permissionManager.grant(origin, permission); + break; + case 'block': + permissionManager.deny(origin, permission); + break; + default: + break; + } + if (status === 'allow' || status === 'block') { + const newQueue = requestQueue.filter((request) => { + if (request.origin === origin && request.permission === permission) { + request.callback(status === 'allow'); + return false; + } + return true; + }); + requestQueue.splice(0, requestQueue.length, ...newQueue); + } else { + const index = requestQueue.findIndex((request) => { + return request.origin === origin && request.permission === permission; + }); + requestQueue[index].callback(false); + requestQueue.splice(index, 1); + } +} + function permissionRequestHandler(mainWindow, permissionFile) { const permissionManager = new PermissionManager(permissionFile); + const requestQueue = []; + ipcMain.on('update-permission', (event, origin, permission, status) => { + dequeueRequests(requestQueue, permissionManager, origin, permission, status); + }); return (webContents, permission, callback) => { const targetURL = new URL(webContents.getURL()); if (permissionManager.isDenied(targetURL.origin, permission)) { @@ -67,28 +100,12 @@ function permissionRequestHandler(mainWindow, permissionFile) { return; } - const buttons = ['Allow', 'Deny', 'Skip']; - const result = dialog.showMessageBox(mainWindow, { - type: 'warning', - buttons, - title: 'Permission Required', - message: `${targetURL.host} is requesting "${permission}" permission`, - cancelId: 2, - noLink: false + requestQueue.push({ + origin: targetURL.origin, + permission, + callback }); - switch (result) { - case buttons.indexOf('Allow'): - permissionManager.grant(targetURL.origin, permission); - callback(true); - return; - case buttons.indexOf('Deny'): - permissionManager.deny(targetURL.origin, permission); - callback(false); - return; - default: - callback(false); - - } + mainWindow.webContents.send('request-permission', targetURL.origin, permission); }; }