changeset 17:18d28e6a9887

Added sample client and postMessage-based API.
author Atul Varma <avarma@mozilla.com>
date Fri, 25 Jun 2010 11:39:28 -0700
parents 9455ec115a5c
children f6db6f8cbf5b
files static-files/api.js static-files/example-client.html static-files/index.html static-files/index.js
diffstat 4 files changed, 215 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/static-files/api.js	Fri Jun 25 11:39:28 2010 -0700
@@ -0,0 +1,146 @@
+(
+  // Set up the public API for the Summit IDP.
+  function(window) {
+    var currId = 0;
+
+    function MessageBroker(handlers, postMessage) {
+      var awaitingResponses = {};
+
+      function sendResponse(id, value) {
+        var responseMsg = {
+          type: "response",
+          id: id,
+          value: value
+        };
+        postMessage(responseMsg);
+      }
+
+      this.callCmd = function callCmd(cmd, options, cb) {
+        var msg = {
+          type: "cmd",
+          name: cmd,
+          id: ++currId,
+          options: options
+        };
+        if (cb) {
+          awaitingResponses[currId] = cb;
+          msg.cb = true;
+        }
+        postMessage(msg);
+      };
+
+      this.onMessage = function onMessage(msg) {
+        switch (msg.type) {
+        case "response":
+          if (msg.id in awaitingResponses) {
+            var cb = awaitingResponses[msg.id];
+            delete awaitingResponses[msg.id];
+            cb(msg.value);
+          }
+          break;
+        case "cmd":
+          var handler = msg.name;
+          if (handler in handlers) {
+            var cb = undefined;
+            if (msg.cb)
+              cb = function(response) {
+                sendResponse(msg.id, response);
+              };
+            handlers[handler](msg.options, cb);
+          }
+          break;
+        }
+      };
+    }
+
+    function Server(handlers, isOriginValid) {
+      var broker = new MessageBroker(handlers, postMessage);
+      var originBrokers = {};
+      var allSources = [];
+
+      function brokerForOrigin(origin, source) {
+        function postMessage(msg) {
+          source.postMessage(JSON.stringify(msg), origin);
+        }
+        
+        return new MessageBroker(handlers, postMessage);
+      }
+
+      function onMessage(event) {
+        if (!(event.origin in originBrokers)) {
+          if (isOriginValid && !isOriginValid(event.origin))
+            return;
+          originBrokers[event.origin] = brokerForOrigin(event.origin,
+                                                        event.source);
+          allSources.push(event.source);
+        }
+
+        if (allSources.indexOf(event.source) == -1)
+          throw new Error("Clients from the same origin are not " + 
+                          "currently supported: " + event.origin);
+        originBrokers[event.origin].onMessage(JSON.parse(event.data));
+      }
+
+      window.addEventListener("message", onMessage, false);
+    }
+
+    function GenericClient(origin, path) {
+      var broker = new MessageBroker({}, postMessage);
+      var iframe = window.document.createElement("iframe");
+      var otherWindow;
+      var queuedMessages = [];
+
+      if (!path)
+        path = "/";
+
+      iframe.src = origin + path;
+
+      iframe.onload = function() {
+        otherWindow = iframe.contentWindow;
+        queuedMessages.forEach(postMessage);
+        queuedMessages = [];
+      };
+
+      iframe.style.display = "none";
+      window.document.documentElement.appendChild(iframe);
+
+      function postMessage(msg) {
+        if (!otherWindow)
+          queuedMessages.push(msg);
+        else
+          otherWindow.postMessage(JSON.stringify(msg), origin);
+      }
+
+      function onMessage(event) {
+        if (event.origin == origin)
+          broker.onMessage(JSON.parse(event.data));
+      }
+
+      this.callCmd = broker.callCmd;
+
+      window.addEventListener("message", onMessage, false);
+    };
+
+    function Client(origin, path) {
+      var self = this;
+      var client = new GenericClient(origin, path);
+
+      function addMethod(name) {
+        self[name] = function(options, cb) {
+          if (typeof(options) == "function" && !cb) {
+            cb = options;
+            options = null;
+          }
+          client.callCmd(name, options, cb);
+        };
+      }
+
+      addMethod("getAllUsers");
+    }
+
+    window.Summit = {
+      Client: Client,
+      Server: Server
+    };
+  }
+)(window);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/static-files/example-client.html	Fri Jun 25 11:39:28 2010 -0700
@@ -0,0 +1,37 @@
+<html>
+<head>
+  <title>Example Client</title>
+  <style>
+  #error {
+    background: red;
+    color: white;
+    display: none;
+  }
+  </style>
+</head>
+<body>
+<p>JSON data for all users should appear below, unless you're not
+logged in, in which case you should <a target="_blank" href="/">log
+in</a>.</p>
+<pre id="users"></pre>
+<div id="error">
+  Error: <span class="reason"></span>
+</div>
+<script src="api.js"></script>
+<script src="jquery-1.4.2.min.js"></script>
+<script>
+$(window).ready(function(event) {
+  var api = new Summit.Client(window.location.protocol + "//" +
+                              window.location.host);
+  api.getAllUsers(function(response) {
+    if (response.error) {
+      $("#error .reason").text(response.error);
+      $("#error").slideDown();
+    } else {
+      $("#users").text(JSON.stringify(response.users));
+    }
+  });
+});
+</script>
+</body>
+</html>
\ No newline at end of file
--- a/static-files/index.html	Thu Jun 24 22:53:16 2010 -0700
+++ b/static-files/index.html	Fri Jun 25 11:39:28 2010 -0700
@@ -54,6 +54,7 @@
   <div class="button start-over">Log Out</div>
 </div>
 <script src="jquery-1.4.2.min.js"></script>
+<script src="api.js"></script>
 <script src="index.js"></script>
 </body>
 </html>
--- a/static-files/index.js	Thu Jun 24 22:53:16 2010 -0700
+++ b/static-files/index.js	Fri Jun 25 11:39:28 2010 -0700
@@ -70,13 +70,6 @@
         break;
       case "logged-in":
         $(".login-email").text(Config.value.email);
-        jQuery.getJSON(
-          "/profile",
-          {token: Config.value.token},
-          function(data, textStatus) {
-            // TODO: This is only temporary, change it.
-            console.log(data, textStatus);
-          });
         break;
       }
     }
@@ -148,3 +141,34 @@
     $(window).ready(initUI);
   }
 )(window);
+
+(
+  // Set up the postMessage API.
+  function(window) {
+    var handlers = {
+      getAllUsers: function(options, cb) {
+        if (Config.value.state != "logged-in") {
+          cb({error: "not logged in"});
+          return;
+        }
+
+        jQuery.getJSON(
+          "/profile",
+          {token: Config.value.token},
+          function(data, textStatus) {
+            if (textStatus == "success")
+              cb({users: data});
+            else
+              cb({error: "an error occurred retrieving user data."});
+          });
+      }
+    };
+
+    function isOriginValid(origin) {
+      // TODO: Finish this.
+      return true;
+    }
+
+    var server = new Summit.Server(handlers, isOriginValid);
+  }
+)(window);