You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by jo...@apache.org on 2008/07/17 23:53:23 UTC
svn commit: r677755 - /incubator/shindig/trunk/features/rpc/rpc.js
Author: johnh
Date: Thu Jul 17 14:53:22 2008
New Revision: 677755
URL: http://svn.apache.org/viewvc?rev=677755&view=rev
Log:
Same-domain gadgets.rpc call support.
Detects if the receiving context of a given gadgets.rpc call
is on the same domain as the caller. In that case, makes a direct call to the
receiver rather than relying on other cross-domain tricks. This is useful
for trusted gadgets rendered on the same domain as their container, irrespective
of browser, since this "transport" is simply a function call that works on any
browser.
This patch closes SHINDIG-456.
Modified:
incubator/shindig/trunk/features/rpc/rpc.js
Modified: incubator/shindig/trunk/features/rpc/rpc.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/rpc/rpc.js?rev=677755&r1=677754&r2=677755&view=diff
==============================================================================
--- incubator/shindig/trunk/features/rpc/rpc.js (original)
+++ incubator/shindig/trunk/features/rpc/rpc.js Thu Jul 17 14:53:22 2008
@@ -47,6 +47,7 @@
var callId = 0;
var callbacks = {};
var setup = {};
+ var sameDomain = {};
var params = {};
@@ -371,6 +372,45 @@
setTimeout(function() { document.body.appendChild(iframe); }, 0);
}
+ /**
+ * Attempts to make an rpc by calling the target's receive method directly.
+ * This works when gadgets are rendered on the same domain as their container,
+ * a potentially useful optimization for trusted content which keeps
+ * RPC behind a consistent interface.
+ * @param {String} target Module id of the rpc service provider
+ * @param {String} from Module id of the caller (this)
+ * @param {String} callbackId Id of the call
+ * @param {String} rpcData JSON-encoded RPC payload
+ * @return
+ */
+ function callSameDomain(target, rpc) {
+ if (typeof sameDomain[target] === 'undefined') {
+ // Seed with a negative, typed value to avoid
+ // hitting this code path repeatedly
+ sameDomain[target] = false;
+ var targetEl = null;
+ if (target === '..') {
+ targetEl = parent;
+ } else {
+ targetEl = frames[target];
+ }
+ try {
+ // If this succeeds, then same-domain policy applied
+ sameDomain[target] = targetEl.gadgets.rpc.receiveSameDomain;
+ } catch (e) {
+ // Usual case: different domains
+ }
+ }
+
+ if (typeof sameDomain[target] === 'function') {
+ // Call target's receive method
+ sameDomain[target](rpc);
+ return true;
+ }
+
+ return false;
+ }
+
// gadgets.config might not be available, such as when serving container js.
if (gadgets.config) {
/**
@@ -493,13 +533,20 @@
}
// Not used by legacy, create it anyway...
- var rpcData = gadgets.json.stringify({
+ var rpc = {
s: serviceName,
f: from,
c: callback ? callId : 0,
a: Array.prototype.slice.call(arguments, 3),
t: authToken[targetId]
- });
+ };
+
+ // If target is on the same domain, call method directly
+ if (callSameDomain(targetId, rpc)) {
+ return;
+ }
+
+ var rpcData = gadgets.json.stringify(rpc);
var channelType = relayChannel;
@@ -595,6 +642,18 @@
process(gadgets.json.parse(
decodeURIComponent(fragment[fragment.length - 1])));
}
+ },
+
+ /**
+ * Receives and processes an RPC request sent via the same domain.
+ * (Not to be used directly). Converts the inbound rpc object's
+ * Array into a local Array to pass the process() Array test.
+ * @param {Object} rpc RPC object containing all request params
+ */
+ receiveSameDomain: function(rpc) {
+ // Pass through to local process method but converting to a local Array
+ rpc.a = Array.prototype.slice.call(rpc.a);
+ window.setTimeout(function() { process(rpc) }, 0);
}
};
}();