Show permissions dialog only for untrusted origins

This commit is contained in:
Yuya Ochiai 2017-12-04 23:52:49 +09:00
parent 7dc75a1b86
commit 5eafe2e7fb
5 changed files with 95 additions and 73 deletions

View file

@ -37,6 +37,7 @@ const appMenu = require('./main/menus/app');
const trayMenu = require('./main/menus/tray');
const downloadURL = require('./main/downloadURL');
const allowProtocolDialog = require('./main/allowProtocolDialog');
const PermissionManager = require('./main/PermissionManager');
const permissionRequestHandler = require('./main/permissionRequestHandler');
const SpellChecker = require('./main/SpellChecker');
@ -49,6 +50,7 @@ var mainWindow = null;
let spellChecker = null;
let deeplinkingUrl = null;
let scheme = null;
let permissionManager = null;
var argv = require('yargs').parse(process.argv.slice(1));
@ -83,10 +85,11 @@ try {
settings.writeFileSync(configFile, config);
}
}
ipcMain.on('update-config', () => {
const configFile = app.getPath('userData') + '/config.json';
config = settings.readFileSync(configFile);
const trustedURLs = settings.mergeDefaultTeams(config.teams).map((team) => team.url);
permissionManager.setTrustedURLs(trustedURLs);
ipcMain.emit('update-dict', true, config.spellCheckerLocale);
});
@ -583,7 +586,9 @@ app.on('ready', () => {
ipcMain.emit('update-dict');
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.
// mainWindow.openDevTools();

View 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;

View file

@ -1,63 +1,5 @@
const {ipcMain} = require('electron');
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) {
switch (status) {
@ -88,8 +30,7 @@ function dequeueRequests(requestQueue, permissionManager, origin, permission, st
}
}
function permissionRequestHandler(mainWindow, permissionFile) {
const permissionManager = new PermissionManager(permissionFile);
function permissionRequestHandler(mainWindow, permissionManager) {
const requestQueue = [];
ipcMain.on('update-permission', (event, origin, permission, status) => {
dequeueRequests(requestQueue, permissionManager, origin, permission, status);
@ -114,6 +55,4 @@ function permissionRequestHandler(mainWindow, permissionFile) {
};
}
permissionRequestHandler.PermissionManager = PermissionManager;
module.exports = permissionRequestHandler;

View file

@ -1,10 +1,8 @@
const {URL} = require('url');
const url = require('url');
export function getDomain(url) {
try {
const objectUrl = new URL(url);
return objectUrl.origin;
} catch (e) {
return null;
}
function getDomain(inputURL) {
const parsedURL = url.parse(inputURL);
return `${parsedURL.protocol}//${parsedURL.host}`;
}
module.exports = {getDomain};

View file

@ -3,7 +3,7 @@
const fs = require('fs');
const path = require('path');
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');
@ -77,4 +77,11 @@ describe('PermissionManager', function() {
manager.isDenied('origin', 'permission').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;
});
});