Author: johnh
Date: Tue Nov  2 21:06:30 2010
New Revision: 1030218

URL: http://svn.apache.org/viewvc?rev=1030218&view=rev
Log:
Adds support to gadgets.rpc for sending messages to a sibling IFRAME, rather 
than always to parent.

The syntax used to do so is to send a message to "/<siblingId>", fully 
enshrining "/" as an invalid character
in an IFRAME name/ID (as should already be the case).

Only window.postMessage is updated to support direct messaging in this way, in 
this CL. As such,
the support should be considered provisional, and used only by those who 
acknowledge this limitation.

Tested on Chrome 7, Firefox 3.6 and IE 8.


Modified:
    shindig/trunk/features/src/main/javascript/features/rpc/rpc.js
    shindig/trunk/features/src/main/javascript/features/rpc/wpm.transport.js

Modified: shindig/trunk/features/src/main/javascript/features/rpc/rpc.js
URL: 
http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/rpc/rpc.js?rev=1030218&r1=1030217&r2=1030218&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/rpc/rpc.js (original)
+++ shindig/trunk/features/src/main/javascript/features/rpc/rpc.js Tue Nov  2 
21:06:30 2010
@@ -28,7 +28,7 @@
  * to the core gadgets.rpc library by various build rules.
  *
  * Transports used by core gadgets.rpc code to actually pass messages.
- * each transport implements the same interface exposing hooks that
+ * Each transport implements the same interface exposing hooks that
  * the core library calls at strategic points to set up and use
  * the transport.
  *
@@ -93,6 +93,12 @@ if (!gadgets.rpc) { // make lib resilien
    */
     var SETUP_FRAME_MAX_TRIES = 10;
 
+    /**
+     * @const
+     * @private
+     */
+    var ID_ORIGIN_DELIMITER = '|';
+
     var services = {};
     var relayUrl = {};
     var useLegacyProtocol = {};
@@ -359,12 +365,39 @@ if (!gadgets.rpc) { // make lib resilien
       return protocol + '://' + host + portStr;
     }
 
+    /*
+     * Makes a sibling id in the format of "/<siblingFrameId>|<siblingOrigin>".
+     */
+    function makeSiblingId(id, opt_origin) {
+      return '/' + id + (opt_origin ? ID_ORIGIN_DELIMITER + opt_origin : '');
+    }
+
+    /*
+     * Parses an iframe id.  Returns null if not a sibling id or
+     *   {id: <siblingId>, origin: <siblingOrigin>} otherwise.
+     */
+    function parseSiblingId(id) {
+      if (id[0] == '/') {
+        var delimiter = id.indexOf(ID_ORIGIN_DELIMITER);
+        var siblingId = delimiter > 0 ? id.substring(1, delimiter) : 
id.substring(1);
+        var origin = delimiter > 0 ? id.substring(delimiter + 1) : null;
+        return {id: siblingId, origin: origin};
+      } else {
+        return null;
+      }
+    }
+
     function getTargetWin(id) {
       if (typeof id === 'undefined' ||
           id === '..') {
         return window.parent;
       }
 
+      var siblingId = parseSiblingId(id);
+      if (siblingId) {
+        return window.top.frames[siblingId.id];
+      }
+
       // Cast to a String to avoid an index lookup.
       id = String(id);
 
@@ -416,7 +449,7 @@ if (!gadgets.rpc) { // make lib resilien
         setup[frameId] = 0;
       }
 
-      var tgtFrame = document.getElementById(frameId);
+      var tgtFrame = getTargetWin(frameId);
       if (frameId === '..' || tgtFrame != null) {
         if (transport.setup(frameId, token, forcesecure) === true) {
           setup[frameId] = true;
@@ -596,13 +629,16 @@ if (!gadgets.rpc) { // make lib resilien
     }
 
     function setupChildIframe(gadgetId, opt_frameurl, opt_authtoken, 
opt_forcesecure) {
-      if (!gadgets.util) {
-        return;
-      }
-      var childIframe = document.getElementById(gadgetId);
-      if (!childIframe) {
-        throw new Error('Cannot set up gadgets.rpc receiver with ID: ' + 
gadgetId +
-            ', element not found.');
+      if (gadgetId[0] != '/') {
+        // only set up child (and not sibling) iframe
+        if (!gadgets.util) {
+          return;
+        }
+        var childIframe = document.getElementById(gadgetId);
+        if (!childIframe) {
+          throw new Error('Cannot set up gadgets.rpc receiver with ID: ' + 
gadgetId +
+              ', element not found.');
+        }
       }
 
       // The "relay URL" can either be explicitly specified or is set as
@@ -611,7 +647,7 @@ if (!gadgets.rpc) { // make lib resilien
       setRelayUrl(gadgetId, relayUrl);
 
       // The auth token is parsed from child params (rpctoken) or overridden.
-      var childParams = gadgets.util.getUrlParameters(childIframe.src);
+      var childParams = gadgets.util.getUrlParameters(relayUrl);
       var rpctoken = opt_authtoken || childParams.rpctoken;
       var forcesecure = opt_forcesecure || childParams.forcesecure;
       setAuthToken(gadgetId, rpctoken, forcesecure);
@@ -774,6 +810,9 @@ if (!gadgets.rpc) { // make lib resilien
 
         if (targetId === '..') {
           from = rpcId;
+        } else if (targetId[0] == '/') {
+          // sending to sibling
+          from = makeSiblingId(rpcId, gadgets.rpc.getOrigin(location.href));
         }
 
         ++callId;
@@ -947,6 +986,9 @@ if (!gadgets.rpc) { // make lib resilien
       /** Returns the window keyed by the ID. null/".." for parent, else child 
*/
       _getTargetWin: getTargetWin,
 
+      /** Parses a sibling id into {id: <siblingId>, origin: <siblingOrigin>} 
*/
+      _parseSiblingId: parseSiblingId,
+
       /** Create an iframe for loading the relay URL. Used by child only. */
       _createRelayIframe: function(token, data) {
         var relay = gadgets.rpc.getRelayUrl('..');

Modified: 
shindig/trunk/features/src/main/javascript/features/rpc/wpm.transport.js
URL: 
http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/rpc/wpm.transport.js?rev=1030218&r1=1030217&r2=1030218&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/rpc/wpm.transport.js 
(original)
+++ shindig/trunk/features/src/main/javascript/features/rpc/wpm.transport.js 
Tue Nov  2 21:06:30 2010
@@ -103,6 +103,22 @@ if (!gadgets.rpctx.wpm) {  // make lib r
       process(rpc);
     }
 
+    function getTargetOrigin(id, parentUrl) {
+      var siblingId = gadgets.rpc._parseSiblingId(id);
+      if (siblingId) {
+        // sibling
+        return siblingId.origin;
+      }
+
+      if (id == '..') {
+        // parent
+        return parentUrl;
+      } else {
+        // child
+        return document.getElementById(id).src;
+      }
+    }
+
     return {
       getCode: function() {
         return 'wpm';
@@ -154,7 +170,7 @@ if (!gadgets.rpctx.wpm) {  // make lib r
         var targetWin = gadgets.rpc._getTargetWin(targetId);
         // targetOrigin = canonicalized relay URL
         var origRelay = gadgets.rpc.getRelayUrl(targetId) ||
-            gadgets.util.getUrlParameters()['parent'];
+            getTargetOrigin(targetId, 
gadgets.util.getUrlParameters()['parent']);
         var origin = gadgets.rpc.getOrigin(origRelay);
         if (origin) {
           postMessage(targetWin, gadgets.json.stringify(rpc), origin);


Reply via email to