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; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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
		Add a link
		
	
		Reference in a new issue
	
	 Kevin Sawicki
				Kevin Sawicki