Merge "Stop suspicious widgets"
diff --git a/dev/demo/plugin-client.html b/dev/demo/plugin-client.html
index 52f35de..f426d8f 100644
--- a/dev/demo/plugin-client.html
+++ b/dev/demo/plugin-client.html
@@ -17,9 +17,20 @@
   </head>
   <body style="background-color: yellow">
     <h2>Example Widget!</h2>
+    <script>
+      function flood () {
+        var i = 0;
+        for (; i < 90; i++) {
+          KorAPlugin._sendMsg({
+            'action' : '-'
+          });
+        };
+      };
+    </script>
     <ul>
       <li><a onclick="KorAPlugin.log(333, 'Huhu!')">Send log!</a></li>
       <li><a onclick="KorAPlugin.resize()">Resize</a></li>
+      <li><a onclick="flood()">Flood!</a></li>
     </ul>
   </body>
 </html>
diff --git a/dev/demo/plugin-server.html b/dev/demo/plugin-server.html
index f513b46..21362fd 100644
--- a/dev/demo/plugin-server.html
+++ b/dev/demo/plugin-server.html
@@ -3,6 +3,10 @@
   <head>
     <title>Plugin demo</title>
     <link type="text/css" rel="stylesheet" href="/css/kalamar.css" />
+    <!--
+        see https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
+-->
     <script data-main="/demo/plugin-serverdemo.js" src="/js/lib/require.js" async="async"></script>
   </head>
   <body>
diff --git a/dev/js/src/plugin/client.js b/dev/js/src/plugin/client.js
index 6918da4..1c2af18 100644
--- a/dev/js/src/plugin/client.js
+++ b/dev/js/src/plugin/client.js
@@ -18,6 +18,11 @@
 *   add a unique ID to the message and will call on the cb
 *   once the answer to that message arrives.
 */
+/*
+ * When loading the script from a remote KorAP instance,
+ * demand using integrity check:
+ * https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
+ */
 
 var cs = document.currentScript;
 
diff --git a/dev/js/src/plugin/server.js b/dev/js/src/plugin/server.js
index db59422..d26de27 100644
--- a/dev/js/src/plugin/server.js
+++ b/dev/js/src/plugin/server.js
@@ -16,7 +16,8 @@
   //   to hundred. For every message, this will be decreased
   //   (down to 0), for every second this will be increased
   //   (up to 100).
-  var c = 100;
+  var maxMessages = 100;
+  var limits = {};
 
   // Contains all widgets to address with
   // messages to them
@@ -41,6 +42,15 @@
       window.addEventListener("message", function (e) {
         that._receiveMsg(e);
       });
+
+      // Every second increase the limits of all registered widgets
+      var myTimer = setInterval(function () {
+        for (var i in limits) {
+          if (limits[i]++ >= maxMessages) {
+            limits[i] = maxMessages;
+          }
+        }
+      }, 1000);
       return this;
     },
 
@@ -57,6 +67,7 @@
 
       // Store the widget based on the identifier
       widgets[id] = widget;
+      limits[id] = maxMessages;
 
       // Open widget in frontend
       element.appendChild(
@@ -69,18 +80,37 @@
       // Get event data
       var d = e.data;
 
-      // e.origin is probably set and okay
+      // If no data given - fail
+      // (probably check that it's an assoc array)
+      if (!d)
+        return;
+
+      // e.origin is probably set and okay - CHECK!
 
       // TODO:
       //   Deal with mad iframes
 
+      // Get origin ID
+      var id = d["originID"];
+
+      // If no origin ID given - fail
+      if (!id)
+        return;
+
       // Get the widget
-      var widget = widgets[d["originID"]];
+      var widget = widgets[id];
 
       // If the addressed widget does not exist - fail
       if (!widget)
         return;
 
+      // Check for message limits
+      if (limits[id]-- < 0) {
+        widget.shutdown();
+        delete limits[id];
+        delete widgets[id];
+        return;
+      };
 
       // Resize the iframe
       if (d.action === 'resize') {
diff --git a/dev/js/src/plugin/widget.js b/dev/js/src/plugin/widget.js
index 4c2f09c..cb4a33d 100644
--- a/dev/js/src/plugin/widget.js
+++ b/dev/js/src/plugin/widget.js
@@ -49,6 +49,12 @@
     // Resize iframe
     resize : function (data) {
       this._element.style.height = data.height + 'px';
+    },
+
+    // Shutdown suspicious iframe
+    shutdown : function () {
+      KorAP.log(0, 'Suspicious action from ' + this.src);
+      this._element.parentNode.removeChild(this._element);
     }
   }
 });