Merge pull request #8134 from deepak1556/empty_client_certificate_patch
app: select-client-certificate event callback can accept certificate optionally
This commit is contained in:
commit
2a8b36c761
4 changed files with 102 additions and 31 deletions
|
@ -378,9 +378,21 @@ void OnClientCertificateSelected(
|
||||||
v8::Isolate* isolate,
|
v8::Isolate* isolate,
|
||||||
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
||||||
mate::Arguments* args) {
|
mate::Arguments* args) {
|
||||||
|
if (args->Length() == 2) {
|
||||||
|
delegate->ContinueWithCertificate(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> val;
|
||||||
|
args->GetNext(&val);
|
||||||
|
if (val->IsNull()) {
|
||||||
|
delegate->ContinueWithCertificate(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mate::Dictionary cert_data;
|
mate::Dictionary cert_data;
|
||||||
if (!args->GetNext(&cert_data)) {
|
if (!mate::ConvertFromV8(isolate, val, &cert_data)) {
|
||||||
args->ThrowError();
|
args->ThrowError("Must pass valid certificate object.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ Returns:
|
||||||
* `url` String
|
* `url` String
|
||||||
|
|
||||||
Emitted when the user wants to open a URL with the application. Your application's
|
Emitted when the user wants to open a URL with the application. Your application's
|
||||||
`Info.plist` file must define the url scheme within the `CFBundleURLTypes` key, and
|
`Info.plist` file must define the url scheme within the `CFBundleURLTypes` key, and
|
||||||
set `NSPrincipalClass` to `AtomApplication`.
|
set `NSPrincipalClass` to `AtomApplication`.
|
||||||
|
|
||||||
You should call `event.preventDefault()` if you want to handle this event.
|
You should call `event.preventDefault()` if you want to handle this event.
|
||||||
|
@ -222,12 +222,12 @@ Returns:
|
||||||
* `url` URL
|
* `url` URL
|
||||||
* `certificateList` [Certificate[]](structures/certificate.md)
|
* `certificateList` [Certificate[]](structures/certificate.md)
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `certificate` [Certificate](structures/certificate.md)
|
* `certificate` [Certificate](structures/certificate.md) (optional)
|
||||||
|
|
||||||
Emitted when a client certificate is requested.
|
Emitted when a client certificate is requested.
|
||||||
|
|
||||||
The `url` corresponds to the navigation entry requesting the client certificate
|
The `url` corresponds to the navigation entry requesting the client certificate
|
||||||
and `callback` needs to be called with an entry filtered from the list. Using
|
and `callback` can be called with an entry filtered from the list. Using
|
||||||
`event.preventDefault()` prevents the application from using the first
|
`event.preventDefault()` prevents the application from using the first
|
||||||
certificate from the store.
|
certificate from the store.
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ const https = require('https')
|
||||||
const net = require('net')
|
const net = require('net')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const {remote} = require('electron')
|
const {ipcRenderer, remote} = require('electron')
|
||||||
const {closeWindow} = require('./window-helpers')
|
const {closeWindow} = require('./window-helpers')
|
||||||
|
|
||||||
const {app, BrowserWindow, ipcMain} = remote
|
const {app, BrowserWindow, ipcMain} = remote
|
||||||
|
@ -41,6 +41,41 @@ describe('electron module', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('app module', function () {
|
describe('app module', function () {
|
||||||
|
let server, secureUrl
|
||||||
|
const certPath = path.join(__dirname, 'fixtures', 'certificates')
|
||||||
|
|
||||||
|
before(function () {
|
||||||
|
const options = {
|
||||||
|
key: fs.readFileSync(path.join(certPath, 'server.key')),
|
||||||
|
cert: fs.readFileSync(path.join(certPath, 'server.pem')),
|
||||||
|
ca: [
|
||||||
|
fs.readFileSync(path.join(certPath, 'rootCA.pem')),
|
||||||
|
fs.readFileSync(path.join(certPath, 'intermediateCA.pem'))
|
||||||
|
],
|
||||||
|
requestCert: true,
|
||||||
|
rejectUnauthorized: false
|
||||||
|
}
|
||||||
|
|
||||||
|
server = https.createServer(options, function (req, res) {
|
||||||
|
if (req.client.authorized) {
|
||||||
|
res.writeHead(200)
|
||||||
|
res.end('<title>authorized</title>')
|
||||||
|
} else {
|
||||||
|
res.writeHead(401)
|
||||||
|
res.end('<title>denied</title>')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
server.listen(0, '127.0.0.1', function () {
|
||||||
|
const port = server.address().port
|
||||||
|
secureUrl = `https://127.0.0.1:${port}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(function () {
|
||||||
|
server.close()
|
||||||
|
})
|
||||||
|
|
||||||
describe('app.getVersion()', function () {
|
describe('app.getVersion()', function () {
|
||||||
it('returns the version field of package.json', function () {
|
it('returns the version field of package.json', function () {
|
||||||
assert.equal(app.getVersion(), '0.1.0')
|
assert.equal(app.getVersion(), '0.1.0')
|
||||||
|
@ -165,24 +200,6 @@ describe('app module', function () {
|
||||||
if (process.platform !== 'linux') return
|
if (process.platform !== 'linux') return
|
||||||
|
|
||||||
var w = null
|
var w = null
|
||||||
var certPath = path.join(__dirname, 'fixtures', 'certificates')
|
|
||||||
var options = {
|
|
||||||
key: fs.readFileSync(path.join(certPath, 'server.key')),
|
|
||||||
cert: fs.readFileSync(path.join(certPath, 'server.pem')),
|
|
||||||
ca: [
|
|
||||||
fs.readFileSync(path.join(certPath, 'rootCA.pem')),
|
|
||||||
fs.readFileSync(path.join(certPath, 'intermediateCA.pem'))
|
|
||||||
],
|
|
||||||
requestCert: true,
|
|
||||||
rejectUnauthorized: false
|
|
||||||
}
|
|
||||||
|
|
||||||
var server = https.createServer(options, function (req, res) {
|
|
||||||
if (req.client.authorized) {
|
|
||||||
res.writeHead(200)
|
|
||||||
res.end('authorized')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
return closeWindow(w).then(function () { w = null })
|
return closeWindow(w).then(function () { w = null })
|
||||||
|
@ -199,25 +216,24 @@ describe('app module', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
w.webContents.on('did-finish-load', function () {
|
w.webContents.on('did-finish-load', function () {
|
||||||
server.close()
|
assert.equal(w.webContents.getTitle(), 'authorized')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('select-client-certificate', function (event, webContents, url, list, callback) {
|
ipcRenderer.once('select-client-certificate', function (event, webContentsId, list) {
|
||||||
|
assert.equal(webContentsId, w.webContents.id)
|
||||||
assert.equal(list.length, 1)
|
assert.equal(list.length, 1)
|
||||||
assert.equal(list[0].issuerName, 'Intermediate CA')
|
assert.equal(list[0].issuerName, 'Intermediate CA')
|
||||||
assert.equal(list[0].subjectName, 'Client Cert')
|
assert.equal(list[0].subjectName, 'Client Cert')
|
||||||
assert.equal(list[0].issuer.commonName, 'Intermediate CA')
|
assert.equal(list[0].issuer.commonName, 'Intermediate CA')
|
||||||
assert.equal(list[0].subject.commonName, 'Client Cert')
|
assert.equal(list[0].subject.commonName, 'Client Cert')
|
||||||
callback(list[0])
|
event.sender.send('client-certificate-response', list[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
app.importCertificate(options, function (result) {
|
app.importCertificate(options, function (result) {
|
||||||
assert(!result)
|
assert(!result)
|
||||||
server.listen(0, '127.0.0.1', function () {
|
ipcRenderer.sendSync('set-client-certificate-option', false)
|
||||||
var port = server.address().port
|
w.loadURL(secureUrl)
|
||||||
w.loadURL(`https://127.0.0.1:${port}`)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -359,4 +375,32 @@ describe('app module', function () {
|
||||||
assert.equal(app.getPath('music'), __dirname)
|
assert.equal(app.getPath('music'), __dirname)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('select-client-certificate event', function () {
|
||||||
|
let w = null
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
w = new BrowserWindow({
|
||||||
|
show: false,
|
||||||
|
webPreferences: {
|
||||||
|
partition: 'empty-certificate'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
return closeWindow(w).then(function () { w = null })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can respond with empty certificate list', function (done) {
|
||||||
|
w.webContents.on('did-finish-load', function () {
|
||||||
|
assert.equal(w.webContents.getTitle(), 'denied')
|
||||||
|
server.close()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcRenderer.sendSync('set-client-certificate-option', true)
|
||||||
|
w.webContents.loadURL(secureUrl)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -206,3 +206,18 @@ app.on('ready', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.on('set-client-certificate-option', function (event, skip) {
|
||||||
|
app.once('select-client-certificate', function (event, webContents, url, list, callback) {
|
||||||
|
event.preventDefault()
|
||||||
|
if (skip) {
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
ipcMain.on('client-certificate-response', function (event, certificate) {
|
||||||
|
callback(certificate)
|
||||||
|
})
|
||||||
|
window.webContents.send('select-client-certificate', webContents.id, list)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
event.returnValue = 'done'
|
||||||
|
})
|
||||||
|
|
Loading…
Add table
Reference in a new issue