Merge "Implement requestMsg() for client-server-communication to receive data from the server"
diff --git a/Changes b/Changes
index 8539b59..9bd15fb 100755
--- a/Changes
+++ b/Changes
@@ -1,9 +1,11 @@
-0.38 2020-03-17
+0.38 2020-03-30
         - Support X-Forwarded-Host name for proxy.
         - Document API URI.
         - Improve redirect handling in proxy.
         - Added support for OAuth2 client registration.
         - Added support for OAuth2 client listing.
+        - Added requestMsg() methods to clients for retrieving
+          data from the embedding server.
 
 0.37 2020-01-16
         - Removed deprecated 'kalamar_test_port' helper.
diff --git a/dev/demo/plugin-client.html b/dev/demo/plugin-client.html
index 0250c6c..3cce6de 100644
--- a/dev/demo/plugin-client.html
+++ b/dev/demo/plugin-client.html
@@ -27,7 +27,7 @@
       function flood () {
         var i = 0;
         for (; i < 90; i++) {
-          KorAPlugin._sendMsg({
+          KorAPlugin.sendMsg({
             'action' : '-'
           });
         };
@@ -57,6 +57,7 @@
       <li><a onclick="KorAPlugin.resize()">Resize</a></li>
       <li><a onclick="KorAPlugin.sendMsg({'action':'pipe','service':'Glemm'})">Add Glemm</a></li>
       <li><a onclick="flood()">Flood!</a></li>
+      <li><a onclick="KorAPlugin.requestMsg({'action':'get', 'key':'KQ'}, function (d) { document.write(JSON.stringify(d.value))})">Get KQ</a></li>
     </ul>
     <p style="width: 2000px">------------------------------------------------------------------------------------------------------------------------</p>
   </body>
diff --git a/dev/js/src/plugin/client.js b/dev/js/src/plugin/client.js
index 389d093..2f34c4e 100644
--- a/dev/js/src/plugin/client.js
+++ b/dev/js/src/plugin/client.js
@@ -29,7 +29,18 @@
 (function () {
   "use strict";
 
-  var obj = {
+  // Similar to randomID in server, but a bit cheaper
+  function randomID () {
+    let s = '';
+    for (let i = 0; i < 16; i++) {
+      s += Math.floor((Math.random()*16)%16).toString(16);
+    };
+    return '_' + s;
+  };
+
+  let response = {};
+  
+  let obj = {
 
     /**
      * Create new plugin
@@ -57,7 +68,15 @@
       window.parent.postMessage(data, this.server);
     },
 
-    // Receive a call from the embedded platform.
+    // Request data
+    requestMsg : function (data, cb) {
+      let id = randomID();
+      data["_id"] = id;
+      response[id] = cb;
+      this.sendMsg(data);
+    },
+    
+    // Receive a call from the embedding platform.
     _receiveMsg : function (e) {
       // Get event data
       let d = e.data;
@@ -71,6 +90,17 @@
       //   check e.origin and d["originID"]!!!
       //   probably against window.parent!
 
+      // There is an associated callback registered:
+      // call and remove the function
+      if (d["_id"]) {
+        let id = d["_id"];
+        if (response[id]) {
+          response[id](d);
+          delete response[id];
+        };
+        return;
+      };
+      
       if (this.onMessage)
         this.onMessage(d)
     },
diff --git a/dev/js/src/plugin/server.js b/dev/js/src/plugin/server.js
index d5c9cfb..4aeb6b9 100644
--- a/dev/js/src/plugin/server.js
+++ b/dev/js/src/plugin/server.js
@@ -194,19 +194,19 @@
 
           // TODO:
           //   This is a bit stupid to get the service window
-          let iframe = services[id].load();
-          let win = iframe.contentWindow;
+          let service = services[id];
+          let iframe = service.load();
 
           // Create object to communicate the toggle state
           // once the iframe is loaded.
           iframe.onload = function () {
             let sendToggle = {
               setState : function (val) {
-                win.postMessage({
+                service.sendMsg({
                   action: 'state',
                   key : onClick['state'],
                   value : val
-                }, '*'); // TODO: Fix origin
+                });
               }
             };
 
@@ -404,6 +404,19 @@
           };
         };
         break;
+
+      // Get information from the embedding platform
+      case 'get':
+        if (d.key == 'KQ') {
+          if (KorAP.koralQuery !== undefined) {    
+            d["value"] = KorAP.koralQuery;
+          };
+        };
+      };
+
+      // data needs to be mirrored
+      if (d._id) {
+        service.sendMsg(d);
       };
 
       // TODO:
diff --git a/dev/js/src/plugin/service.js b/dev/js/src/plugin/service.js
index a02e945..c8b42dd 100644
--- a/dev/js/src/plugin/service.js
+++ b/dev/js/src/plugin/service.js
@@ -1,5 +1,6 @@
 define(function () {
   "use strict";
+
   return {
     create : function (name, src, id) {
       return Object.create(this)._init(name, src, id);
@@ -43,6 +44,17 @@
       return e;
     },
 
+    /**
+     * Send a message to the embedded service.
+     */
+    sendMsg : function (d) {
+      let iframe = this.load();
+      iframe.contentWindow.postMessage(
+        d,
+        '*'
+      ); // TODO: Fix origin
+    },
+
     // onClose : function () {},
 
     /**
diff --git a/dev/js/src/util.js b/dev/js/src/util.js
index 5df346b..5eab4b3 100644
--- a/dev/js/src/util.js
+++ b/dev/js/src/util.js
@@ -78,7 +78,7 @@
  * https://stackoverflow.com/questions/1349404/generate-random-string-characters-in-javascript#8084248
  */
 function randomID (len) {
-  var arr = new Uint8Array((len || 40) / 2)
+  let arr = new Uint8Array((len || 40) / 2)
   window.crypto.getRandomValues(arr)
   return Array.from(arr, _dec2hex).join('')
 };