Fix shell.openExternal() freezing GNU/Linux

Electron's `shell.openExternal()` fails on GNU/Linux when Electron is

ran with `sudo`.  The issue was reported, and this is a workaround until

its fixed on the Electron side.



`node-open` is smart enough to check the `$SUDO_USER` environment

variable and to prepend `sudo -u <user>` if needed.



We keep `shell.openExternal()` for OSes other than Linux since we intend

to fully rely on it when the issue is fixed, and since its closer

integration with the operating system might lead to more accurate

results than a third party NPM module.



See https://github.com/electron/electron/issues/5039

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
Juan Cruz Viotti 2016-04-06 11:12:46 -04:00
parent 912373a389
commit e8516b1727
3 changed files with 43 additions and 7 deletions

View File

@ -18,6 +18,8 @@
const electron = require('electron');
const shell = electron.remote.require('shell');
const os = require('os');
const nodeOpen = require('open');
/**
* This directive provides an attribute to open an external
@ -41,6 +43,25 @@ module.exports = function() {
element.css('cursor', 'pointer');
element.on('click', function() {
// Electron's `shell.openExternal()` fails on GNU/Linux
// when Electron is ran with `sudo`.
// The issue was reported, and this is a workaround until
// its fixed on the Electron side.
// `node-open` is smart enough to check the `$SUDO_USER`
// environment variable and to prepend `sudo -u <user>`
// if needed.
// We keep `shell.openExternal()` for OSes other than
// Linux since we intend to fully rely on it when the
// issue is fixed, and since its closer integration with
// the operating system might lead to more accurate results
// than a third party NPM module.
//
// See https://github.com/electron/electron/issues/5039
if (os.platform() === 'linux') {
return nodeOpen(scope.openExternal);
}
shell.openExternal(scope.openExternal);
});
}

View File

@ -83,6 +83,7 @@
"is-elevated": "^1.0.0",
"lodash": "^4.5.1",
"ngstorage": "^0.3.10",
"open": "0.0.5",
"resin-image-write": "^2.0.5",
"resin-zip-image": "^1.1.2",
"sudo-prompt": "^2.2.0",

View File

@ -17,6 +17,7 @@
'use strict';
const m = require('mochainon');
const os = require('os');
const angular = require('angular');
const electron = require('electron');
const shell = electron.remote.require('shell');
@ -43,13 +44,26 @@ describe('Browser: OpenExternal', function() {
m.chai.expect(element.css('cursor')).to.equal('pointer');
});
it('should call Electron shell.openExternal with the attribute value', function() {
const shellExternalStub = m.sinon.stub(shell, 'openExternal');
const element = $compile('<span open-external="https://resin.io">Resin.io</span>')($rootScope);
element.triggerHandler('click');
$rootScope.$digest();
m.chai.expect(shellExternalStub).to.have.been.calledWith('https://resin.io');
shellExternalStub.restore();
describe('given non linux', function() {
beforeEach(function() {
this.osPlatformStub = m.sinon.stub(os, 'platform');
this.osPlatformStub.returns('darwin');
});
afterEach(function() {
this.osPlatformStub.restore();
});
it('should call Electron shell.openExternal with the attribute value', function() {
const shellExternalStub = m.sinon.stub(shell, 'openExternal');
const element = $compile('<span open-external="https://resin.io">Resin.io</span>')($rootScope);
element.triggerHandler('click');
$rootScope.$digest();
m.chai.expect(shellExternalStub).to.have.been.calledWith('https://resin.io');
shellExternalStub.restore();
});
});
});