302 lines
7.5 KiB
JavaScript
302 lines
7.5 KiB
JavaScript
|
|
|
||
|
|
|
||
|
|
|
||
|
|
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();
|