@@ -10,10 +10,11 @@ /* * Handle for the CACKey NaCl Target */ var cackeyHandle = null; +var cackeyPCSCHandle = null; /* * Handle and ID for outstanding callbacks */ var cackeyOutstandingCallbacks = {} @@ -383,10 +384,55 @@ console.log("[cackey] Thrown."); } return; } + +/* + * Uninitializes CACKey (probably due to a crash) + */ +function cackeyUninit() { + if (chrome.certificateProvider) { + chrome.certificateProvider.onCertificatesRequested.removeListener(cackeyListCertificates); + chrome.certificateProvider.onSignDigestRequested.removeListener(cackeySignMessage); + } + + if (cackeyPCSCHandle != null) { + delete cackeyPCSCHandle; + + cackeyPCSCHandle = null; + } + + if (cackeyHandle != null) { + try { + document.body.removeChild(cackeyHandle); + } catch (e) { } + + delete cackeyHandle; + + cackeyHandle = null; + } +} + +/* + * Restarts CACKey + */ +function cackeyRestart() { + cackeyUninit(); + cackeyInit(); +} + +/* + * Handle a CACKey crash (probably due to loss of connectivity to the PCSC daemon) + */ +function cackeyCrash() { + /* + * Schedule the restart to occur in 30 seconds in case we really are + * not working. + */ + setTimeout(cackeyRestart, 30000); +} /* * Finish performing initialization that must wait until we have loaded the CACKey module */ function cackeyInitLoaded(messageEvent) { @@ -410,24 +456,73 @@ ); /* * Start the Google PCSC Interface */ - new GoogleSmartCard.PcscNacl(cackeyHandle); + cackeyPCSCHandle = new GoogleSmartCard.PcscNacl(cackeyHandle); return; } /* * Initialize CACKey and the PCSC library from Google */ function cackeyInit() { var elementEmbed; + var forceLoadElement; /* Log that we are operational */ console.log("[cackey] cackeyInit(): Called."); + /* + * Do not initialize multiple times + */ + if (cackeyHandle != null) { + console.log("[cackey] cackeyInit(): Already initialized. Returning."); + + return; + } + + /* Verify that we can register callbacks */ + if (!chrome.certificateProvider) { + if (!GoogleSmartCard.IS_DEBUG_BUILD) { + console.error("[cackey] This extension only works on ChromeOS!"); + + return; + } else { + console.log("[cackey] This extension only works on ChromeOS, but you appear to be debugging it -- trying anyway."); + } + } + + elementEmbed = document.createElement('embed'); + elementEmbed.type = "application/x-pnacl"; + elementEmbed.width = 0; + elementEmbed.height = 0; + elementEmbed.src = "cackey.nmf"; + elementEmbed.id = "cackeyModule"; + elementEmbed.addEventListener('error', function(messageEvent) { console.error("Error loading CACKey PNaCl Module: " + messageEvent.data); }, true); + elementEmbed.addEventListener('load', cackeyInitLoaded, true); + elementEmbed.addEventListener('crash', cackeyCrash, true); + elementEmbed.addEventListener('message', cackeyMessageIncoming, true); + + cackeyHandle = elementEmbed; + + document.body.appendChild(cackeyHandle) + + /* + * Force the browser to load the element + * by requesting its position + */ + forceLoadElement = cackeyHandle.offsetTop; + + console.log("[cackey] cackeyInit(): Completed. Returning."); +} + +/* + * Initialize the CACKey Chrome Application + */ +function cackeyAppInit() { /* * Create a handler for starting the application UI */ chrome.app.runtime.onLaunched.addListener(function() { chrome.app.window.create('ui.html', { @@ -439,42 +534,10 @@ "height": 135, "minHeight": 135 } }); }); - - /* Verify that we can register callbacks */ - if (!chrome.certificateProvider) { - if (!GoogleSmartCard.IS_DEBUG_BUILD) { - console.error("[cackey] This extension only works on ChromeOS!"); - - return; - } else { - console.log("[cackey] This extension only works on ChromeOS, but you appear to be debugging it -- trying anyway."); - } - } - - if (cackeyHandle != null) { - console.log("[cackey] cackeyInit(): Already initialized. Returning."); - - return; - } - - elementEmbed = document.createElement('embed'); - elementEmbed.type = "application/x-pnacl"; - elementEmbed.width = 0; - elementEmbed.height = 0; - elementEmbed.src = "cackey.nmf"; - elementEmbed.id = "cackeyModule"; - elementEmbed.addEventListener('error', function(messageEvent) { console.error("Error loading CACKey PNaCl Module: " + messageEvent.data); }, true); - elementEmbed.addEventListener('load', cackeyInitLoaded, true); - elementEmbed.addEventListener('message', cackeyMessageIncoming, true); - - cackeyHandle = elementEmbed; - - document.body.appendChild(cackeyHandle) - - console.log("[cackey] cackeyInit(): Completed. Returning."); } /* Initialize CACKey */ +cackeyAppInit(); cackeyInit();