From 6279e71b36404b010e0ff14cf68174be0a0ab389 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 14 Nov 2016 12:58:33 -0500 Subject: [PATCH] LP#1640255 Hatch native messaging extension Replaces Hatch Websockets communication layer with browser extension- based communication. Hatch API remains the same with 2 notable exceptions: 1. appendItem() API call has been removed. It did not work as designed and (thus far) has served no purpose. It was originally intended for offline data storage, but that will probably require something a little smarter. 2. The printer configuration API is no more. This will be replaced with an in-app configuration page. Note, this does not prevent use of the printer dialog, it only means settings are not collected from the printer dialog. Overhaul still in design... Signed-off-by: Bill Erickson --- .../staff/admin/workstation/t_print_config.tt2 | 18 --- .../templates/staff/admin/workstation/t_splash.tt2 | 9 -- .../js/ui/default/staff/admin/workstation/app.js | 20 --- Open-ILS/web/js/ui/default/staff/services/hatch.js | 151 +++++++++------------ 4 files changed, 66 insertions(+), 132 deletions(-) diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 index ef5dafbccb..ce4d670fa0 100644 --- a/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 +++ b/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 @@ -71,24 +71,6 @@ value="{{printConfig[context].printer}}"> -
-
-
- - -
-
-
diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 index 4e60199dc3..fdee8c6dbb 100644 --- a/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 +++ b/Open-ILS/src/templates/staff/admin/workstation/t_splash.tt2 @@ -12,15 +12,6 @@
-
-
- -
-
diff --git a/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js b/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js index dd51bc8129..f0ea4fd4cf 100644 --- a/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js +++ b/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js @@ -167,7 +167,6 @@ function($scope , $window , $location , egCore , egConfirmDialog) { // --------------------- // Hatch Configs - $scope.hatchURL = egCore.hatch.hatchURL(); $scope.hatchRequired = egCore.hatch.getLocalItem('eg.hatch.required'); @@ -176,11 +175,6 @@ function($scope , $window , $location , egCore , egConfirmDialog) { 'eg.hatch.required', $scope.hatchRequired); } - $scope.updateHatchURL = function() { - egCore.hatch.setLocalItem( - 'eg.hatch.url', $scope.hatchURL); - } - egCore.hatch.getItem('eg.audio.disable').then(function(val) { $scope.disable_sound = val; }); @@ -314,20 +308,6 @@ function($scope , egCore) { .finally(function() {$scope.actionPending = false}); } - $scope.configurePrinter = function() { - $scope.printConfigError = null; - $scope.actionPending = true; - egCore.hatch.configurePrinter( - $scope.context, - $scope.printConfig[$scope.context].printer - ) - .then( - function(config) {$scope.printConfig = config}, - function(error) {$scope.printConfigError = error} - ) - .finally(function() {$scope.actionPending = false}); - } - $scope.setPrinter = function(name) { $scope.printConfig[$scope.context].printer = name; } diff --git a/Open-ILS/web/js/ui/default/staff/services/hatch.js b/Open-ILS/web/js/ui/default/staff/services/hatch.js index ff517fc940..7115ecc11f 100644 --- a/Open-ILS/web/js/ui/default/staff/services/hatch.js +++ b/Open-ILS/web/js/ui/default/staff/services/hatch.js @@ -24,19 +24,27 @@ */ angular.module('egCoreMod') +.constant("HATCH_CONFIG", { + /* TODO: Extension name will change once the extension is + * registered and will presumably be different per browser. + * Current extension name is borrowed from: + * https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/docs/examples/api/nativeMessaging + */ + EXT_NAME_CHROME : "knldjmfmopnpolahpmmgbagdohdnhkik" +}) + .factory('egHatch', - ['$q','$window','$timeout','$interpolate','$http','$cookies', - function($q , $window , $timeout , $interpolate , $http , $cookies) { + ['$q','$window','$timeout','$interpolate','$http','$cookies','HATCH_CONFIG', + function($q , $window , $timeout , $interpolate , $http , $cookies , HATCH_CONFIG) { var service = {}; - service.msgId = 0; + service.port = null; // Hatch extension connection + service.msgId = 1; service.messages = {}; service.pending = []; - service.socket = null; service.hatchAvailable = null; - service.defaultHatchURL = 'wss://localhost:8443/hatch'; - // write a message to the Hatch websocket + // write a message to the Hatch port service.sendToHatch = function(msg) { var msg2 = {}; @@ -47,7 +55,7 @@ angular.module('egCoreMod') }); console.debug("sending to Hatch: " + JSON.stringify(msg2,null,2)); - service.socket.send(JSON.stringify(msg2)); + service.port.postMessage(msg2); } // Send the request to Hatch if it's available. @@ -90,18 +98,18 @@ angular.module('egCoreMod') msg.deferred = service.messages[msg.msgid].deferred; delete service.messages[msg.msgid]; // un-cache - // resolve / reject - if (msg.error) { - throw new Error( - "egHatch command failed : " - + JSON.stringify(msg.error, null, 2)); + if (msg.status != 200) { + msg.deferred.reject(); + throw new Error("Hatch command failed with status=" + + msg.status + " and message=" + msg.message); + } else { msg.deferred.resolve(msg.content); } } service.hatchClosed = function() { - service.socket = null; + service.port = null; service.printers = []; service.printConfig = {}; while ( (msg = service.pending.shift()) ) { @@ -112,11 +120,6 @@ angular.module('egCoreMod') service.onHatchClose(); } - service.hatchURL = function() { - return service.getLocalItem('eg.hatch.url') - || service.defaultHatchURL; - } - // Returns true if Hatch is required or if we are currently // communicating with the Hatch service. service.usingHatch = function() { @@ -131,56 +134,59 @@ angular.module('egCoreMod') service.hatchConnect = function() { - if (service.socket && - service.socket.readyState == service.socket.CONNECTING) { - // connection in progress. Nothing to do. Our queued - // message will be delivered when onopen() fires - return; - } + if (service.port) return; + + service.initting = true; try { - service.socket = new WebSocket(service.hatchURL()); + service.port = + chrome.runtime.connect(HATCH_CONFIG.EXT_NAME_CHROME); } catch(e) { service.hatchAvailable = false; service.hatchClosed(); + console.debug("Hatch connection failed: " + e); return; } - service.socket.onopen = function() { - console.debug('connected to Hatch'); - service.hatchAvailable = true; - if (service.onHatchOpen) - service.onHatchOpen(); - while ( (msg = service.pending.shift()) ) { - service.sendToHatch(msg); - }; - } + service.port.onDisconnect.addListener(function() { + if (service.hatchAvailable === false) return; // already noted + service.hatchAvailable = null; // reset + service.hatchClosed(); + }); - service.socket.onclose = function() { - if (service.hatchAvailable === false) return; // already registered + service.port.onMessage.addListener(function(msg) { + console.debug('Hatch says: ' + JSON.stringify(msg, null, 2)); - // onclose() will be called regularly as we disconnect from - // Hatch via timeouts. Return hatchAvailable to its unknow state - service.hatchAvailable = null; - service.hatchClosed(); - } + if (service.initting) { + service.initting = false; + console.debug("Hatch init completed with " + msg.message); - service.socket.onerror = function() { - if (service.hatchAvailable === false) return; // already registered - service.hatchAvailable = false; - console.debug( - "unable to connect to Hatch server at " + service.hatchURL()); - service.hatchClosed(); - } + if (msg.status == 200) { + service.hatchOpened(); + } else { + console.warn("Hatch init failed"); + } - service.socket.onmessage = function(evt) { - var msgStr = evt.data; - if (!msgStr) throw new Error("Hatch returned empty message"); + } else { + service.resolveRequest(msg); + } + }); - var msgObj = JSON.parse(msgStr); - console.debug('Hatch says ' + JSON.stringify(msgObj, null, 2)); - service.resolveRequest(msgObj); - } + console.debug('Connected to Hatch'); + service.hatchAvailable = true; + + // The first message to Hatch must be "init" + service.attemptHatchDelivery({action : 'init'}); + } + + service.hatchOpened = function() { + // let others know we're connected + if (service.onHatchOpen) service.onHatchOpen(); + + // Deliver any previously queued requests + while ( (msg = service.pending.shift()) ) { + service.sendToHatch(msg); + }; } service.getPrintConfig = function() { @@ -291,8 +297,8 @@ angular.module('egCoreMod') service.getRemoteItem = function(key) { return service.attemptHatchDelivery({ key : key, - action : 'get', - }); + action : 'get' + }) } service.getLocalItem = function(key) { @@ -318,16 +324,14 @@ angular.module('egCoreMod') * tmp values are removed during logout or browser close. */ service.setItem = function(key, value) { - var str = JSON.stringify(value); - - return service.setRemoteItem(key, str)['catch']( + return service.setRemoteItem(key, value)['catch']( function(msg) { if (service.hatchRequired()) { console.error("Unable to setItem: " + key + "; hatchRequired=true, but hatch is not connected"); return null; } - return service.setLocalItem(msg.key, null, str); + return service.setLocalItem(msg.key, value); } ); } @@ -336,7 +340,7 @@ angular.module('egCoreMod') service.setRemoteItem = function(key, value) { return service.attemptHatchDelivery({ key : key, - value : value, + content : value, action : 'set', }); } @@ -374,29 +378,6 @@ angular.module('egCoreMod') $window.sessionStorage.setItem(key, jsonified); } - // appends the value to the existing item stored at key. - // If not item is found at key, this behaves just like setItem() - service.appendItem = function(key, value) { - return service.appendRemoteItem(key, value)['catch']( - function(msg) { - if (service.hatchRequired()) { - console.error("Unable to appendItem: " + key - + "; hatchRequired=true, but hatch is not connected"); - return null; - } - service.appendLocalItem(msg.key, msg.value); - } - ); - } - - service.appendRemoteItem = function(key, value) { - return service.attemptHatchDelivery({ - key : key, - value : value, - action : 'append', - }); - } - // assumes the appender and appendee are both strings // TODO: support arrays as well service.appendLocalItem = function(key, value) { -- 2.11.0