view static-files/api.js @ 19:e1b3e9916b57

made origin detection happen on a per-handler basis.
author Atul Varma <avarma@mozilla.com>
date Fri, 25 Jun 2010 12:15:27 -0700
parents 18d28e6a9887
children 18de6b362cc5
line wrap: on
line source

(
  // Set up the public API for the Summit IDP.
  function(window) {
    var currId = 0;

    function MessageBroker(handlers, postMessage) {
      var awaitingResponses = {};

      function sendResponse(id, value, target) {
      }

      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, origin, source) {
        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) {
                postMessage({type: "response",
                             id: msg.id,
                             value: response
                            },
                            source);
              };
            handlers[handler](msg.options, cb, origin);
          }
          break;
        }
      };
    }

    function Server(handlers) {
      var broker = new MessageBroker(handlers, postMessage);
      var originBrokers = {};

      function brokerForOrigin(origin) {
        function postMessage(msg, target) {
          target.postMessage(JSON.stringify(msg), origin);
        }
        
        return new MessageBroker(handlers, postMessage);
      }

      function onMessage(event) {
        if (!(event.origin in originBrokers))
          originBrokers[event.origin] = brokerForOrigin(event.origin);

        originBrokers[event.origin].onMessage(JSON.parse(event.data),
                                              event.origin,
                                              event.source);
      }

      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), event.origin,
                           event.source);
      }

      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);