Index: build/chrome/Makefile ================================================================== --- build/chrome/Makefile +++ build/chrome/Makefile @@ -26,11 +26,11 @@ endif export NACL_SDK_ROOT all: cackey.crx -cackey.crx: cackey.pexe cackey.nmf manifest.json cackey.js google-pcsc.js pin.html pin-icon.png +cackey.crx: cackey.pexe cackey.nmf manifest.json cackey.js google-pcsc.js pin.html pin.js pin-icon.png rm -f cackey.crx zip cackey.crx.new $^ mv cackey.crx.new cackey.crx cackey.pexe: cackey-chrome.o cackey-chrome-init.o lib/libcackey.a lib/libpcsc.a lib/libz.a Index: build/chrome/cackey.js ================================================================== --- build/chrome/cackey.js +++ build/chrome/cackey.js @@ -17,10 +17,15 @@ * Handle and ID for outstanding callbacks */ var cackeyOutstandingCallbacks = [] var cackeyOutstandingCallbackCounter = -1; +/* + * Communication with the PIN entry window + */ +var pinWindowDidWork = 0; + /* * Handle a response from the NaCl side regarding certificates available */ function cackeyMessageIncomingListCertificates(message, chromeCallback) { var idx; @@ -86,25 +91,92 @@ console.log("[cackey] Discarding outdated message"); return; } - if (messageEvent.data.status != "success") { - console.error("[cackey] Failed to execute command '" + messageEvent.data.command + "': " + messageEvent.data.error); - - chromeCallback(); - } else { - switch (messageEvent.data.command) { - case "listcertificates": - nextFunction = cackeyMessageIncomingListCertificates; - - break; - case "sign": - nextFunction = cackeyMessageIncomingSignMessage; - - break; - } + switch (messageEvent.data.status) { + case "error": + console.error("[cackey] Failed to execute command '" + messageEvent.data.command + "': " + messageEvent.data.error); + + chromeCallback(); + + break; + case "retry": + pinWindowDidWork = 0; + + chrome.app.window.create("pin.html", { + "id": "cackeyPINEntry", + "resizable": false, + "alwaysOnTop": true, + "focused": true, + "visibleOnAllWorkspaces": true, + "innerBounds": { + "width": 350, + "minWidth": 350, + "height": 135, + "minHeight": 135 + } + }, function(pinWindow) { + if (!pinWindow) { + console.log("[cackey] No window was provided for PIN entry, this will not go well."); + + return; + } + pinWindow.drawAttention(); + pinWindow.focus(); + + /* + * Register a handler to handle the window being closed without + * having sent anything + */ + pinWindow.onClosed.addListener(function() { + if (pinWindowDidWork != 1) { + console.log("[cackey] The PIN dialog was closed without resubmitting the request, treating it as a failure"); + + cackeyMessageIncoming( + { + "data": { + "target": "cackey", + "command": messageEvent.data.command, + "id": messageEvent.data.id, + "status": "error", + "error": "PIN window closed without a PIN being provided" + } + } + ) + + } + return; + }) + + /* + * Pass this message off to the other window so that it may resubmit the request. + */ + pinWindow.contentWindow.parentWindow = window; + pinWindow.contentWindow.messageEvent = messageEvent; + + return; + }); + + /* + * We return here instead of break to avoid deleting the callback + * entry. + */ + return; + case "success": + switch (messageEvent.data.command) { + case "listcertificates": + nextFunction = cackeyMessageIncomingListCertificates; + + break; + case "sign": + nextFunction = cackeyMessageIncomingSignMessage; + + break; + } + + break; } if (nextFunction != null) { nextFunction(messageEvent.data, chromeCallback); } Index: build/chrome/pin.html ================================================================== --- build/chrome/pin.html +++ build/chrome/pin.html @@ -1,8 +1,14 @@ CACKey PIN Entry + +
@@ -13,11 +19,11 @@ - +
PIN Entry Required
PIN:
ADDED build/chrome/pin.js Index: build/chrome/pin.js ================================================================== --- build/chrome/pin.js +++ build/chrome/pin.js @@ -0,0 +1,46 @@ +function clickOk() { + + parentWindow.pinWindowDidWork = 1; + + window.close(); + + return; +} + +function clickCancel() { + window.close(); + + return; +} + +function focusPin() { + window.focus(); + + document.getElementById('pin').focus(); + + return; +} + +setTimeout(function() { + var noFocusObjects, idx; + + document.getElementById('ok').onclick = function() { + clickOk(); + }; + + document.getElementById('cancel').onclick = function() { + clickCancel(); + }; + + window.onfocus = function() { + focusPin(); + } + + document.getElementById('pin').onblur = function() { + setTimeout(function() { + if (document.activeElement.className != "button") { + focusPin(); + } + }, 1); + } +}, 1);