Implement asynchronous permission requests

This commit is contained in:
Yuya Ochiai
2017-11-05 00:08:59 +09:00
parent d83e7fecd7
commit 77427ad75a
2 changed files with 89 additions and 22 deletions

View File

@@ -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')
);

View File

@@ -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);
};
}