Show permissions dialog only for untrusted origins
This commit is contained in:
@@ -37,6 +37,7 @@ const appMenu = require('./main/menus/app');
|
|||||||
const trayMenu = require('./main/menus/tray');
|
const trayMenu = require('./main/menus/tray');
|
||||||
const downloadURL = require('./main/downloadURL');
|
const downloadURL = require('./main/downloadURL');
|
||||||
const allowProtocolDialog = require('./main/allowProtocolDialog');
|
const allowProtocolDialog = require('./main/allowProtocolDialog');
|
||||||
|
const PermissionManager = require('./main/PermissionManager');
|
||||||
const permissionRequestHandler = require('./main/permissionRequestHandler');
|
const permissionRequestHandler = require('./main/permissionRequestHandler');
|
||||||
|
|
||||||
const SpellChecker = require('./main/SpellChecker');
|
const SpellChecker = require('./main/SpellChecker');
|
||||||
@@ -49,6 +50,7 @@ var mainWindow = null;
|
|||||||
let spellChecker = null;
|
let spellChecker = null;
|
||||||
let deeplinkingUrl = null;
|
let deeplinkingUrl = null;
|
||||||
let scheme = null;
|
let scheme = null;
|
||||||
|
let permissionManager = null;
|
||||||
|
|
||||||
var argv = require('yargs').parse(process.argv.slice(1));
|
var argv = require('yargs').parse(process.argv.slice(1));
|
||||||
|
|
||||||
@@ -83,10 +85,11 @@ try {
|
|||||||
settings.writeFileSync(configFile, config);
|
settings.writeFileSync(configFile, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcMain.on('update-config', () => {
|
ipcMain.on('update-config', () => {
|
||||||
const configFile = app.getPath('userData') + '/config.json';
|
const configFile = app.getPath('userData') + '/config.json';
|
||||||
config = settings.readFileSync(configFile);
|
config = settings.readFileSync(configFile);
|
||||||
|
const trustedURLs = settings.mergeDefaultTeams(config.teams).map((team) => team.url);
|
||||||
|
permissionManager.setTrustedURLs(trustedURLs);
|
||||||
ipcMain.emit('update-dict', true, config.spellCheckerLocale);
|
ipcMain.emit('update-dict', true, config.spellCheckerLocale);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -583,7 +586,9 @@ app.on('ready', () => {
|
|||||||
ipcMain.emit('update-dict');
|
ipcMain.emit('update-dict');
|
||||||
|
|
||||||
const permissionFile = path.join(app.getPath('userData'), 'permission.json');
|
const permissionFile = path.join(app.getPath('userData'), 'permission.json');
|
||||||
session.defaultSession.setPermissionRequestHandler(permissionRequestHandler(mainWindow, permissionFile));
|
const trustedURLs = settings.mergeDefaultTeams(config.teams).map((team) => team.url);
|
||||||
|
permissionManager = new PermissionManager(permissionFile, trustedURLs);
|
||||||
|
session.defaultSession.setPermissionRequestHandler(permissionRequestHandler(mainWindow, permissionManager));
|
||||||
|
|
||||||
// Open the DevTools.
|
// Open the DevTools.
|
||||||
// mainWindow.openDevTools();
|
// mainWindow.openDevTools();
|
||||||
|
73
src/main/PermissionManager.js
Normal file
73
src/main/PermissionManager.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const utils = require('../utils/util');
|
||||||
|
|
||||||
|
const PERMISSION_GRANTED = 'granted';
|
||||||
|
const PERMISSION_DENIED = 'denied';
|
||||||
|
|
||||||
|
class PermissionManager {
|
||||||
|
constructor(file, trustedURLs = []) {
|
||||||
|
this.file = file;
|
||||||
|
this.setTrustedURLs(trustedURLs);
|
||||||
|
if (fs.existsSync(file)) {
|
||||||
|
try {
|
||||||
|
this.permissions = JSON.parse(fs.readFileSync(this.file, 'utf-8'));
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
this.permissions = {};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.permissions = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileSync() {
|
||||||
|
fs.writeFileSync(this.file, JSON.stringify(this.permissions, null, ' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
grant(origin, permission) {
|
||||||
|
if (!this.permissions[origin]) {
|
||||||
|
this.permissions[origin] = {};
|
||||||
|
}
|
||||||
|
this.permissions[origin][permission] = PERMISSION_GRANTED;
|
||||||
|
this.writeFileSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
deny(origin, permission) {
|
||||||
|
if (!this.permissions[origin]) {
|
||||||
|
this.permissions[origin] = {};
|
||||||
|
}
|
||||||
|
this.permissions[origin][permission] = PERMISSION_DENIED;
|
||||||
|
this.writeFileSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(origin, permission) {
|
||||||
|
delete this.permissions[origin][permission];
|
||||||
|
}
|
||||||
|
|
||||||
|
isGranted(origin, permission) {
|
||||||
|
if (this.trustedOrigins[origin] === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (this.permissions[origin]) {
|
||||||
|
return this.permissions[origin][permission] === PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDenied(origin, permission) {
|
||||||
|
if (this.permissions[origin]) {
|
||||||
|
return this.permissions[origin][permission] === PERMISSION_DENIED;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTrustedURLs(trustedURLs) {
|
||||||
|
this.trustedOrigins = {};
|
||||||
|
for (const url of trustedURLs) {
|
||||||
|
const origin = utils.getDomain(url);
|
||||||
|
this.trustedOrigins[origin] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = PermissionManager;
|
@@ -1,63 +1,5 @@
|
|||||||
const {ipcMain} = require('electron');
|
const {ipcMain} = require('electron');
|
||||||
const {URL} = require('url');
|
const {URL} = require('url');
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const PERMISSION_GRANTED = 'granted';
|
|
||||||
const PERMISSION_DENIED = 'denied';
|
|
||||||
|
|
||||||
class PermissionManager {
|
|
||||||
constructor(file) {
|
|
||||||
this.file = file;
|
|
||||||
if (fs.existsSync(file)) {
|
|
||||||
try {
|
|
||||||
this.permissions = JSON.parse(fs.readFileSync(this.file, 'utf-8'));
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
this.permissions = {};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.permissions = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeFileSync() {
|
|
||||||
fs.writeFileSync(this.file, JSON.stringify(this.permissions, null, ' '));
|
|
||||||
}
|
|
||||||
|
|
||||||
grant(origin, permission) {
|
|
||||||
if (!this.permissions[origin]) {
|
|
||||||
this.permissions[origin] = {};
|
|
||||||
}
|
|
||||||
this.permissions[origin][permission] = PERMISSION_GRANTED;
|
|
||||||
this.writeFileSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
deny(origin, permission) {
|
|
||||||
if (!this.permissions[origin]) {
|
|
||||||
this.permissions[origin] = {};
|
|
||||||
}
|
|
||||||
this.permissions[origin][permission] = PERMISSION_DENIED;
|
|
||||||
this.writeFileSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
clear(origin, permission) {
|
|
||||||
delete this.permissions[origin][permission];
|
|
||||||
}
|
|
||||||
|
|
||||||
isGranted(origin, permission) {
|
|
||||||
if (this.permissions[origin]) {
|
|
||||||
return this.permissions[origin][permission] === PERMISSION_GRANTED;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
isDenied(origin, permission) {
|
|
||||||
if (this.permissions[origin]) {
|
|
||||||
return this.permissions[origin][permission] === PERMISSION_DENIED;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function dequeueRequests(requestQueue, permissionManager, origin, permission, status) {
|
function dequeueRequests(requestQueue, permissionManager, origin, permission, status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -88,8 +30,7 @@ function dequeueRequests(requestQueue, permissionManager, origin, permission, st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function permissionRequestHandler(mainWindow, permissionFile) {
|
function permissionRequestHandler(mainWindow, permissionManager) {
|
||||||
const permissionManager = new PermissionManager(permissionFile);
|
|
||||||
const requestQueue = [];
|
const requestQueue = [];
|
||||||
ipcMain.on('update-permission', (event, origin, permission, status) => {
|
ipcMain.on('update-permission', (event, origin, permission, status) => {
|
||||||
dequeueRequests(requestQueue, permissionManager, origin, permission, status);
|
dequeueRequests(requestQueue, permissionManager, origin, permission, status);
|
||||||
@@ -114,6 +55,4 @@ function permissionRequestHandler(mainWindow, permissionFile) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
permissionRequestHandler.PermissionManager = PermissionManager;
|
|
||||||
|
|
||||||
module.exports = permissionRequestHandler;
|
module.exports = permissionRequestHandler;
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
const {URL} = require('url');
|
const url = require('url');
|
||||||
|
|
||||||
export function getDomain(url) {
|
function getDomain(inputURL) {
|
||||||
try {
|
const parsedURL = url.parse(inputURL);
|
||||||
const objectUrl = new URL(url);
|
return `${parsedURL.protocol}//${parsedURL.host}`;
|
||||||
return objectUrl.origin;
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {getDomain};
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const env = require('../modules/environment');
|
const env = require('../modules/environment');
|
||||||
const {PermissionManager} = require('../../src/main/permissionRequestHandler');
|
const PermissionManager = require('../../src/main/PermissionManager');
|
||||||
|
|
||||||
const permissionFile = path.join(env.userDataDir, 'permission.json');
|
const permissionFile = path.join(env.userDataDir, 'permission.json');
|
||||||
|
|
||||||
@@ -77,4 +77,11 @@ describe('PermissionManager', function() {
|
|||||||
manager.isDenied('origin', 'permission').should.be.true;
|
manager.isDenied('origin', 'permission').should.be.true;
|
||||||
manager.isGranted('origin_another', 'permission_another').should.be.true;
|
manager.isGranted('origin_another', 'permission_another').should.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should allow permissions for trusted URLs', function() {
|
||||||
|
fs.writeFileSync(permissionFile, JSON.stringify({}));
|
||||||
|
const manager = new PermissionManager(permissionFile, ['https://example.com', 'https://example2.com/2']);
|
||||||
|
manager.isGranted('https://example.com', 'notifications').should.be.true;
|
||||||
|
manager.isGranted('https://example2.com', 'test').should.be.true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user