function HermesFDAChrome(isChrome) { this.states = { uninitialized : 0, notInstalled : 1, initializing : 2, initialized : 3, initializationFailed : 4 }; // propiedades this.version = 0; this.state = this.states.uninitialized; this.lastErrorMessage = ""; this.description = ""; this.pinLength = 0; this.lastError = 0; this.lastLowLevelError = 0; this.pinModuleName = ""; this.isPinMissing = false; this.isPinInvalid = false; this.pinRetryCount = 0; this.isChrome = isChrome; // eventos this.onCertificatesReady = null; this.onUpdated = null; this.onCertificateReady = null; this.onSignatureReady = null; } HermesFDAChrome.prototype.initialize = function (signature, domains, currentDomain, subjectNames) { if (this.state != this.states.uninitialized) { return; } if (!this.isInstalled()) { state = this.states.notInstalled; return; } // escuchar los mensajes de la extensión var outerThis = this; window.addEventListener ( "message", function(event) { // Solo aceptar mensajes de la misma ventana if (event.source != window) { return; } // Procesar las respuestas de la extensión if (event.data.type && (event.data.type == "HermesFDAResponse")) { outerThis.processExtensionMessage(event.data.text); } }, false ); this.state = this.states.initializing; // Pedir a la extensión que se inicialice. Es necesario hacerlo por un timeout para esperar que la extensión enganche el evento onMessage window.setTimeout( function () { var message = {command: 0, signature : signature, domains : domains, currentDomain : currentDomain, caSubjectNames : HermesFDACaSubjectNames}; window.postMessage({ type: "HermesFDARequest", text: JSON.stringify(message) }, "*"); }, 100 ); } HermesFDAChrome.prototype.isInstalled = function () { if (this.isChrome) { return this.version > 0 || this.detectChromeExtension("pcbdpnhgogngimbhngoanbkgpmoeiobj", "manifest.json"); } else { return this.version > 0 || this.detectFirefoxExtension(); } } HermesFDAChrome.prototype.getVersion = function () { return this.version; } HermesFDAChrome.prototype.detectChromeExtension = function(extensionId, accesibleResource) { if (typeof(chrome) !== 'undefined') { try { var testUrl = 'chrome-extension://' +extensionId +'/' +accesibleResource; var result = $.ajax({ type: "GET", url: testUrl, async: false, cache: false, global: false}); if (result.statusText == "OK") { var manifest = JSON.parse(result.responseText); this.version = parseFloat(manifest.version); this.description = manifest.description; return this.version > 0; } } catch(e) { } } return false; } HermesFDAChrome.prototype.detectFirefoxExtension = function () { try { var testUrl = window.localStorage.getItem("8847BAF82DEB47DA808A9D4E1C2B0C9A"); if (testUrl == null || testUrl.length == 0) { return false; } var result = $.ajax({ type: "GET", url: testUrl, async: false, cache: false, global: false }); if (result.statusText == "OK") { var manifest = JSON.parse(result.responseText); this.version = parseFloat(manifest.version); this.description = manifest.description; return this.version > 0; } } catch (e) { } return false; } HermesFDAChrome.prototype.processExtensionMessage = function (data) { var extensionMessage = JSON.parse(data); if (this.state == this.states.initializing) { if (extensionMessage.command == 0) // inicializar { if (extensionMessage.error) { this.state = this.states.initializationFailed; this.lastErrorMessage = extensionMessage.errorMessage; this.lastError = extensionMessage.lastError; this.lastLowLevelError = extensionMessage.lastLowLevelError; } else { this.state = this.states.initialized; } // invocar evento generico que se llama cada vez que se actualiza el objeto if (this.onUpdated != null) { this.onUpdated(this); } } } else if (this.state == this.states.initialized) { // si es una respuesta diferente a inicializar entonces cargar los valores de los campos if (extensionMessage.command>0) { if (extensionMessage.error) { this.lastError = extensionMessage.lastError; this.lastErrorMessage = extensionMessage.errorMessage; this.lastLowLevelError = extensionMessage.lastLowLevelError; } else { this.lastError = 0; this.lastErrorMessage = ""; this.lastLowLevelError = 0; } this.pinModuleName = extensionMessage.pinModuleName; this.isPinMissing = extensionMessage.missingPin; this.isPinInvalid = extensionMessage.invalidPin; this.pinLength = extensionMessage.pinLength; this.pinRetryCount = extensionMessage.pinRetryCount; // invocar evento generico que se llama cada vez que se actualiza el objeto if (this.onUpdated != null) { this.onUpdated(this, extensionMessage.command); } if (extensionMessage.command == 2) // lista de certificados { if (this.onCertificatesReady != null) { this.onCertificatesReady(this,extensionMessage.error?"":extensionMessage.certificates); } } else if (extensionMessage.command == 4) // certificado en base 64 { if (this.onCertificateReady != null) { this.onCertificateReady(this,extensionMessage.error?"":extensionMessage.certificate); } } else if (extensionMessage.command == 5) // firma digital { if (this.onSignatureReady != null) { this.onSignatureReady(this,extensionMessage.error?"":extensionMessage.pkcs1); } } } } } HermesFDAChrome.prototype.processPinChar = function (char) { if (this.state != this.states.initialized) { return; } var message = {command: 6, pinChar : char}; window.postMessage({ type: "HermesFDARequest", text: JSON.stringify(message) }, "*"); this.pinLength += 1; } HermesFDAChrome.prototype.deletePinChar = function () { if (this.state != this.states.initialized) { return; } var message = {command: 7}; window.postMessage({ type: "HermesFDARequest", text: JSON.stringify(message) }, "*"); if (this.pinLength > 0) { this.pinLength -= 1; } } HermesFDAChrome.prototype.getDigitalSignatureCertificates = function () { if (this.state != this.states.initialized) { return ""; } var message = {command: 2}; window.postMessage({ type: "HermesFDARequest", text: JSON.stringify(message) }, "*"); return null; } HermesFDAChrome.prototype.getCertificate = function (certId) { if (this.state != this.states.initialized) { return; } var message = {command: 4, certId: certId}; window.postMessage({ type: "HermesFDARequest", text: JSON.stringify(message) }, "*"); return null; } HermesFDAChrome.prototype.signPkcs1 = function(certId, digest) { if (this.state != this.states.initialized) { return null; } var message = {command: 5, certId: certId, digest : digest }; window.postMessage({ type: "HermesFDARequest", text: JSON.stringify(message) }, "*"); return null; } // Activar el host de native messaging function InitHermesFDAChrome() { var message = { command: 1000 }; window.postMessage({ type: "HermesFDARequest", text: JSON.stringify(message) }, "*"); } InitHermesFDAChrome();