Author: johnh
Date: Wed Mar  2 02:23:13 2011
New Revision: 1076087

URL: http://svn.apache.org/viewvc?rev=1076087&view=rev
Log:
First working cut of Flash gadgets.rpc transport!

Change desc from http://codereview.appspot.com/4258043/:

With these changes, the Flash transport for gadgets.rpc works for the
first time! This is with a number of caveats, for the moment:

1. It's only activated when the &flash=1 parameter is added to
feature.xml
2. Doesn't work on IE since embed code uses <embed> rather than <object>

Both of these will be removed in subsequent CLs.

The test harness is updated here in various small ways as well to allow
testing of this and other transports.

Tested:
* Initialization from gadgets.config (asynchronous application of SWF)
for configurability.
* Callbacks and multiple fast requests (performance is slow)
* RPC call before setup completed (early RPC queueing re-enabled).

The last point bears attention, since it re-enables the ability to call
gadgets.rpc.call before any given transport's setup mechanism is
complete (window.postMessage can have dropped messages as a result as
well w/o this). But it also means that the transport handshake mechanism
is quite important, as completion of it unlocks message passing.

Committing now since the transport isn't enabled.



Modified:
    shindig/trunk/config/container.js
    shindig/trunk/content/container/rpctest_container.html
    shindig/trunk/content/container/rpctest_gadget.xml
    shindig/trunk/content/xpc.swf
    shindig/trunk/features/src/main/flex/Main.as
    shindig/trunk/features/src/main/javascript/features/rpc/feature.xml
    shindig/trunk/features/src/main/javascript/features/rpc/flash.transport.js
    shindig/trunk/features/src/main/javascript/features/rpc/rpc.js

Modified: shindig/trunk/config/container.js
URL: 
http://svn.apache.org/viewvc/shindig/trunk/config/container.js?rev=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
--- shindig/trunk/config/container.js (original)
+++ shindig/trunk/config/container.js Wed Mar  2 02:23:13 2011
@@ -227,7 +227,10 @@
 
     // If true, this will use the legacy ifpc wire format when making rpc
     // requests.
-    "useLegacyProtocol" : false
+    "useLegacyProtocol" : false,
+
+    // Path to the cross-domain enabling SWF for rpc's Flash transport.
+    "commSwf": "/xpc.swf"
   },
   // Skin defaults
   "skins" : {

Modified: shindig/trunk/content/container/rpctest_container.html
URL: 
http://svn.apache.org/viewvc/shindig/trunk/content/container/rpctest_container.html?rev=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
--- shindig/trunk/content/container/rpctest_container.html (original)
+++ shindig/trunk/content/container/rpctest_container.html Wed Mar  2 02:23:13 
2011
@@ -37,7 +37,6 @@
   This test container/gadget pair is configurable via two other options:
   * &gadgetdeferred=1 - tests early-message queueing from container to
     gadget, by preventing attachment of gadget until a button is pressed.
-  * &uselegacy=1 - tests legacy IFPC functionality.
   * &uabackward=1 - tests "incorrect" rpc.js setup in container:
     gadgets.rpc.setAuthToken(...) called before, not after, gadget frame 
exists.
 
@@ -50,29 +49,18 @@
       // Configurable test harness options.
       var gadgethost = 'http://' + 
window.location.search.substring(1).split('&')[0];
       var gadgetdeferred = window.location.search.indexOf('&gadgetdeferred=1') 
!== -1;
-      var uselegacy = window.location.search.indexOf('&uselegacy=1') !== -1;
       var uabackward = window.location.search.indexOf('&uabackward=1') !== -1;
+      var flash = window.location.search.indexOf('&flash=1') !== -1;
 
       // Useful per-page variables.
       var gadgeturl = gadgethost + '/container/rpctest_gadget.xml';
       var cachebust = 'cachebust=' + Math.random();
-      var gadgetrenderingurl = gadgethost + '/gadgets/ifr?url=' + gadgeturl + 
'&libs=rpc&parent=' + window.location.protocol + '//' + window.location.host + 
'&debug=1&' + cachebust;
+      var gadgetrenderingurl = gadgethost + '/gadgets/ifr?url=' + gadgeturl + 
'&libs=rpc&parent=' + window.location.protocol + '//' + window.location.host + 
'&debug=1&nocache=1&' + cachebust + (flash ? '&flash=1' : '');
       var gadgetrelay = gadgethost + '/container/rpc_relay.uncompressed.html';
 
-      // Set up faux gadgets.config(...)
-      var gadgets = {};
-      gadgets.config = {
-        register: function(rpc, requiredConfig, callback) {
-          // rpc === "rpc", requiredConfig is ignored here.
-          // Just call the callback (function init(...) in rpc.js)
-          // with a dummy config object.
-          callback({ rpc: { parentRelayUrl: "", uselegacyProtocol: uselegacy } 
});
-        }
-      };
-
       // Include rpc.js. Append random cache-busting param to ensure caching 
doesn't occur.
       document.write('<scr' + 'ipt language="JavaScript" 
type="text/javascript" src="' +
-                     '/gadgets/js/rpc.js?c=1&debug=1&' + cachebust + '"></scr' 
+ 'ipt>');
+                     '/gadgets/js/rpc.js?c=1&nocache=1&debug=1&' + cachebust + 
'"></scr' + 'ipt>');
 
       // Include rpctest_perf.js JS test helper, also with cachebusting.
       document.write('<scr' + 'ipt language="JavaScript" 
type="text/javascript" src="' +

Modified: shindig/trunk/content/container/rpctest_gadget.xml
URL: 
http://svn.apache.org/viewvc/shindig/trunk/content/container/rpctest_gadget.xml?rev=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
--- shindig/trunk/content/container/rpctest_gadget.xml (original)
+++ shindig/trunk/content/container/rpctest_gadget.xml Wed Mar  2 02:23:13 2011
@@ -64,7 +64,7 @@
     </script>
     <div>gadgets.rpc Performance: "Gadget" page</div><hr/>
     <script>
-      document.write("<div>Parent relay: " + gadgets.rpc.getRelayUrl('..') + 
"</div><hr/>");
+      document.write("<div>Parent relay: " + gadgets.rpc.getRelayUrl('..') + 
"<br/>method: " + gadgets.rpc.getRelayChannel() + "</div><hr/>");
     </script>
     <div>Test<br/>
       <ul>

Modified: shindig/trunk/content/xpc.swf
URL: 
http://svn.apache.org/viewvc/shindig/trunk/content/xpc.swf?rev=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
Files shindig/trunk/content/xpc.swf (original) and 
shindig/trunk/content/xpc.swf Wed Mar  2 02:23:13 2011 differ

Modified: shindig/trunk/features/src/main/flex/Main.as
URL: 
http://svn.apache.org/viewvc/shindig/trunk/features/src/main/flex/Main.as?rev=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
--- shindig/trunk/features/src/main/flex/Main.as (original)
+++ shindig/trunk/features/src/main/flex/Main.as Wed Mar  2 02:23:13 2011
@@ -36,7 +36,7 @@ class Main {
     } else {
       my_origin = _level0.origin;
     }
-    
+
     var domain:String = my_origin.substr(my_origin.indexOf("//") + 2, 
my_origin.length);
     
     if (my_origin.substr(0,5)==="http:") {
@@ -45,34 +45,41 @@ class Main {
       security.allowDomain(domain);
     }
     
-    ExternalInterface.addCallback("setup", { }, 
function(channel_recv_id:String, role:String) {
-      if (channel_recv_id.indexOf(":") > -1) {
+    ExternalInterface.addCallback("setup", { }, function(my_id:String, 
target_id:String) {
+      if (target_id.indexOf(":") > -1) {
         return;
       }
 
+      var role:String;
       var other_role:String;
-      
-      if (role == "INNER") {
+      var channel_recv_id:String;
+
+      if (target_id == "..") {
+        role = "INNER";
         other_role = "OUTER";
+        channel_recv_id = my_id;
       } else {
         role = "OUTER";
         other_role = "INNER";
+        channel_recv_id = target_id;
       }
 
       var receiving_lc:LocalConnection = new LocalConnection();
       var sending_lc:LocalConnection = new LocalConnection();
-      receiving_lc.receiveMessage = function(to_origin:String, 
from_origin:String, target_id:String, message:String) {
-        if ((to_origin === "*" || to_origin === my_origin) && target_id === 
channel_recv_id) {
-          ExternalInterface.call("gadgets.rpctx.flash._receiveMessage", 
target_id, message, from_origin, to_origin);
+      receiving_lc.receiveMessage = function(to_origin:String, 
from_origin:String, from_id:String, message:String) {
+        //ExternalInterface.call("alert", "receiving_lc.receiveMessage(), 
to_origin=" + to_origin + ", from_origin=" + from_origin + ", from_id=" + 
from_id + ", my_origin=" + my_origin + ", target_id=" + target_id + ", 
channel_recv_id=" + channel_recv_id + ", check1=" + (to_origin===my_origin) + 
", check2.1=" + (from_id === target_id) + ", check2.2=" + (from_id === "_top") 
+ ", check2.3=" + (target_id === ".."));
+        if ((to_origin === "*" || to_origin === my_origin) && ((from_id === 
target_id) || (from_id === "_top" && target_id === ".."))) {
+          ExternalInterface.call("gadgets.rpctx.flash._receiveMessage", 
from_id, message, from_origin, to_origin);
         }
       };
 
-      ExternalInterface.addCallback("sendMessage_" + channel_recv_id, { }, 
function(message:String, to_origin:String) {
+      ExternalInterface.addCallback("sendMessage_" + target_id, { }, 
function(message:String, to_origin:String) {
         if (!to_origin) to_origin = "*";
-        sending_lc.send(channel_recv_id + "_" + other_role, "receiveMessage", 
to_origin, my_origin, channel_recv_id, message);
-      } );
+        //ExternalInterface.call("alert", "attempting to send message: " + 
message + " to=" + to_origin + ", channel=" + channel_recv_id + "_" + 
other_role + ", target_id=" + target_id);
+        sending_lc.send(channel_recv_id + "_" + other_role, "receiveMessage", 
to_origin, my_origin, my_id, message);
+      });
       receiving_lc.connect(channel_recv_id + "_" + role);
-    } );
+    });
     ExternalInterface.call("gadgets.rpctx.flash._ready");
   }
   

Modified: shindig/trunk/features/src/main/javascript/features/rpc/feature.xml
URL: 
http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/rpc/feature.xml?rev=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/rpc/feature.xml 
(original)
+++ shindig/trunk/features/src/main/javascript/features/rpc/feature.xml Wed Mar 
 2 02:23:13 2011
@@ -45,6 +45,7 @@ specific language governing permissions 
       <exports type="js">gadgets.rpc.getReceiverOrigin</exports>
     </api>
     <script src="wpm.transport.js"/>
+    <script src="flash.transport.js"/>
     <script src="fe.transport.js"/>
     <script src="nix.transport.js"/>
     <script src="rmr.transport.js"/>

Modified: 
shindig/trunk/features/src/main/javascript/features/rpc/flash.transport.js
URL: 
http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/rpc/flash.transport.js?rev=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/rpc/flash.transport.js 
(original)
+++ shindig/trunk/features/src/main/javascript/features/rpc/flash.transport.js 
Wed Mar  2 02:23:13 2011
@@ -32,8 +32,8 @@ gadgets.rpctx = gadgets.rpctx || {};
 if (!gadgets.rpctx.flash) {  // make lib resilient to double-inclusion
 
   gadgets.rpctx.flash = function() {
-    // TODO: provide method to override this
-    var swfUrl = "//flashrpc.googleusercontent.com/xpc.swf";
+    var swfUrl = null;
+    var usingFlash = false;
     var process = null;
     var ready = null;
     var secureReceivers = {};
@@ -45,13 +45,24 @@ if (!gadgets.rpctx.flash) {  // make lib
     var setupHandle = null;
     var setupAttempts = 0;
 
-    var myLoc = window.location.href;
+    var myLoc = window.location.protocol + "//" + window.location.host;
+
+    function init(config) {
+      if (usingFlash) {
+        swfUrl = config['rpc']['commSwf'] || "/xpc.swf";
+      }
+    }
+    gadgets.config.register('rpc', null, init);
 
     function relayLoader() {
-      if (relayHandle === null && document.body) {
+      if (relayHandle === null && document.body && swfUrl) {
         relayHandle = document.createElement('embed');
-        relayHandle.allowScriptAccess = true;
+        relayHandle.setAttribute("allowScriptAccess", "always");
         relayHandle.src = swfUrl + '?origin=' + myLoc;
+        relayHandle.style.top = -1;
+        relayHandle.style.left = -1;
+        relayHandle.style.height = 1;
+        relayHandle.style.width = 1;
         document.body.appendChild(relayHandle);
       }
       ++setupAttempts;
@@ -65,7 +76,8 @@ if (!gadgets.rpctx.flash) {  // make lib
       if (relayHandle !== null) {
         while (pendingHandshakes.length > 0) {
           var shake = pendingHandshakes.shift();
-          relayHandle.setup(shake.id, shake.role);
+          relayHandle['setup'](shake.myId, shake.targetId);
+          ready(shake.targetId, true);
         }
       }
     }
@@ -83,6 +95,7 @@ if (!gadgets.rpctx.flash) {  // make lib
       init: function(processFn, readyFn) {
         process = processFn;
         ready = readyFn;
+        usingFlash = true;
         return true;
       },
 
@@ -95,8 +108,7 @@ if (!gadgets.rpctx.flash) {  // make lib
         // otherwise polling will occur until the SWF has completed loading, at
         // which point all connections will complete their handshake.
         secureReceivers[receiverId] = !!forceSecure;
-        var role = targetId === ".." ? "OUTER" : "INNER";
-        pendingHandshakes.push({ id: targetId, role: role });
+        pendingHandshakes.push({ myId: gadgets.rpc.RPC_ID, targetId: 
receiverId });
         if (relayHandle === null && setupHandle === null) {
           setupHandle = window.setTimeout(relayLoader, LOADER_TIMEOUT_MS);
         }
@@ -106,13 +118,14 @@ if (!gadgets.rpctx.flash) {  // make lib
 
       call: function(targetId, from, rpc) {
         var targetOrigin = gadgets.rpc.getTargetOrigin(targetId);;
-        relayHandle["sendMessage_" + targetId](gadgets.json.stringify(rpc), 
targetOrigin);
+        var messageHandler = relayHandle["sendMessage_" + targetId];
+        messageHandler.call(relayHandle, gadgets.json.stringify(rpc), 
targetOrigin);
         return true;
       },
 
       // Methods called by relay SWF. Should be considered private.
-      _receiveMessage: function(targetId, message, fromOrigin, toOrigin) {
-        // TODO: validate targetId for sanity, and fromOrigin/toOrigin for 
domain verification.
+      _receiveMessage: function(fromId, message, fromOrigin, toOrigin) {
+        // TODO: validate fromId for sanity, and fromOrigin/toOrigin for 
domain verification.
         window.setTimeout(function() { process(gadgets.json.parse(message)); 
}, 0);
       },
 

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=1076087&r1=1076086&r2=1076087&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/rpc/rpc.js (original)
+++ shindig/trunk/features/src/main/javascript/features/rpc/rpc.js Wed Mar  2 
02:23:13 2011
@@ -180,6 +180,7 @@ if (!gadgets.rpc) { // make lib resilien
      * @member gadgets.rpc
      */
     function getTransport() {
+      if (params['flash'] == "1") return gadgets.rpctx.flash;
       return typeof window.postMessage === 'function' ? gadgets.rpctx.wpm :
           typeof window.postMessage === 'object' ? gadgets.rpctx.wpm :
           window.ActiveXObject ? gadgets.rpctx.nix :
@@ -872,7 +873,7 @@ if (!gadgets.rpc) { // make lib resilien
         // target is misconfigured, it won't affect the others.
         // In the case of a sibling relay, channel is not found
         // in the receiverTx map but in the transport itself.
-        var channel = receiverTx[targetId] || transport;
+        var channel = receiverTx[targetId]; // || transport;
 
         if (!channel) {
           // Not set up yet. Enqueue the rpc for such time as it is.
@@ -1024,7 +1025,7 @@ if (!gadgets.rpc) { // make lib resilien
 
       ACK: ACK,
 
-      RPC_ID: rpcId,
+      RPC_ID: rpcId || "_top",
 
       SEC_ERROR_LOAD_TIMEOUT: LOAD_TIMEOUT,
       SEC_ERROR_FRAME_PHISH: FRAME_PHISH,


Reply via email to