view static-files/js/api.js @ 61:2d981c2a7f9a

Backed out changeset be00b5be37d6 Hey, it was just a proof of concept.
author Atul Varma <avarma@mozilla.com>
date Mon, 28 Jun 2010 22:32:03 -0700
parents be00b5be37d6
children
line wrap: on
line source

(
  // Set up the public API for the Summit IDP.
  function(window) {
    // parseUri 1.2.2
    // (c) Steven Levithan <stevenlevithan.com>
    // MIT License

    function parseUri (str) {
	var	o   = parseUri.options,
		m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
		uri = {},
		i   = 14;

	while (i--) uri[o.key[i]] = m[i] || "";

	uri[o.q.name] = {};
	uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
		if ($1) uri[o.q.name][$1] = $2;
	});

	return uri;
    };

    parseUri.options = {
	strictMode: false,
	key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
	q:   {
		name:   "queryKey",
		parser: /(?:^|&)([^&=]*)=?([^&]*)/g
	},
	parser: {
		strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
		loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
	}
    };

    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, url) {
      var broker = new MessageBroker({}, postMessage);
      var iframe = window.document.createElement("iframe");
      var otherWindow;
      var queuedMessages = [];

      iframe.src = url;

      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(url) {
      if (url === undefined)
        url = ".";

      var parsed = parseUri(url);

      if (parsed.protocol == "") {
        var a = window.document.createElement("a");
        a.href = url;
        window.document.documentElement.appendChild(a);
        url = a.href;
        window.document.documentElement.removeChild(a);
        parsed = parseUri(url);
      }

      if (parsed.protocol != "http" &&
          parsed.protocol != "https")
        throw new Error("invalid server URL: " + url);

      var self = this;
      var origin = parsed.protocol + "://" + parsed.authority;
      var client = new GenericClient(origin, url + "server.html");

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