You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by li...@apache.org on 2010/09/15 03:40:15 UTC

svn commit: r997163 [36/37] - in /shindig/trunk/features/src/main/javascript/features: caja/ com.google.gadgets.analytics/ container/ core.config/ core.io/ core.json/ core.legacy/ core.log/ core.prefs/ core.util/ dynamic-height.util/ dynamic-height/ fl...

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=997163&r1=997162&r2=997163&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/rpc/rpc.js (original)
+++ shindig/trunk/features/src/main/javascript/features/rpc/rpc.js Wed Sep 15 01:39:49 2010
@@ -26,7 +26,7 @@
  *
  * All transports are stored in object gadgets.rpctx, and are provided
  * 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
  * the core library calls at strategic points to set up and use
@@ -54,101 +54,101 @@
 
 if (!gadgets.rpc) { // make lib resilient to double-inclusion
 
-/**
+  /**
  * @static
  * @namespace Provides operations for making rpc calls.
  * @name gadgets.rpc
  */
 
-gadgets.rpc = function() {
-  /** 
+  gadgets.rpc = function() {
+    /**
    * @const
    * @private
    */
-  var CALLBACK_NAME = '__cb';
+    var CALLBACK_NAME = '__cb';
 
-  /** 
+    /**
    * @const
    * @private
    */
-  var DEFAULT_NAME = '';
+    var DEFAULT_NAME = '';
 
-  /** Exported constant, for use by transports only.
+    /** Exported constant, for use by transports only.
    * @const
    * @type {string}
    * @member gadgets.rpc
    */
-  var ACK = '__ack';
+    var ACK = '__ack';
 
-  /** 
+    /**
    * Timeout and number of attempts made to setup a transport receiver.
    * @const
    * @private
    */
-  var SETUP_FRAME_TIMEOUT = 500;
+    var SETUP_FRAME_TIMEOUT = 500;
 
-  /** 
+    /**
    * @const
    * @private
    */
-  var SETUP_FRAME_MAX_TRIES = 10;
+    var SETUP_FRAME_MAX_TRIES = 10;
 
-  var services = {};
-  var relayUrl = {};
-  var useLegacyProtocol = {};
-  var authToken = {};
-  var callId = 0;
-  var callbacks = {};
-  var setup = {};
-  var sameDomain = {};
-  var params = {};
-  var receiverTx = {};
-  var earlyRpcQueue = {};
-
-  // isGadget =~ isChild for the purposes of rpc (used only in setup).
-  var isChild = (window.top !== window.self);
-
-  // Set the current rpc ID from window.name immediately, to prevent
-  // shadowing of window.name by a "var name" declaration, or similar.
-  var rpcId = window.name;
-
-  var securityCallback = function() {};
-  var LOAD_TIMEOUT = 0;
-  var FRAME_PHISH = 1;
-  var FORGED_MSG = 2;
-
-  // Fallback transport is simply a dummy impl that emits no errors
-  // and logs info on calls it receives, to avoid undesired side-effects
-  // from falling back to IFPC or some other transport.
-  var fallbackTransport = (function() {
-    function logFn(name) {
-      return function() {
-        gadgets.log("gadgets.rpc." + name + "(" +
-                    gadgets.json.stringify(Array.prototype.slice.call(arguments)) +
-                    "): call ignored. [caller: " + document.location +
-                    ", isChild: " + isChild + "]");
+    var services = {};
+    var relayUrl = {};
+    var useLegacyProtocol = {};
+    var authToken = {};
+    var callId = 0;
+    var callbacks = {};
+    var setup = {};
+    var sameDomain = {};
+    var params = {};
+    var receiverTx = {};
+    var earlyRpcQueue = {};
+
+    // isGadget =~ isChild for the purposes of rpc (used only in setup).
+    var isChild = (window.top !== window.self);
+
+    // Set the current rpc ID from window.name immediately, to prevent
+    // shadowing of window.name by a "var name" declaration, or similar.
+    var rpcId = window.name;
+
+    var securityCallback = function() {};
+    var LOAD_TIMEOUT = 0;
+    var FRAME_PHISH = 1;
+    var FORGED_MSG = 2;
+
+    // Fallback transport is simply a dummy impl that emits no errors
+    // and logs info on calls it receives, to avoid undesired side-effects
+    // from falling back to IFPC or some other transport.
+    var fallbackTransport = (function() {
+      function logFn(name) {
+        return function() {
+          gadgets.log('gadgets.rpc.' + name + '(' +
+              gadgets.json.stringify(Array.prototype.slice.call(arguments)) +
+              '): call ignored. [caller: ' + document.location +
+              ', isChild: ' + isChild + ']');
+        };
+      }
+      return {
+        getCode: function() {
+          return 'noop';
+        },
+        isParentVerifiable: function() {
+          return true;  // Not really, but prevents transport assignment to IFPC.
+        },
+        init: logFn('init'),
+        setup: logFn('setup'),
+        call: logFn('call')
       };
-    }
-    return {
-      getCode: function() {
-        return "noop";
-      },
-      isParentVerifiable: function() {
-        return true;  // Not really, but prevents transport assignment to IFPC.
-      },
-      init: logFn("init"),
-      setup: logFn("setup"),
-      call: logFn("call")
-    };
-  })();
+    })();
 
-  // Load the authentication token for speaking to the container
-  // from the gadget's parameters, or default to '0' if not found.
-  if (gadgets.util) {
-    params = gadgets.util.getUrlParameters();
-  }
+    // Load the authentication token for speaking to the container
+    // from the gadget's parameters, or default to '0' if not found.
+    if (gadgets.util) {
+      params = gadgets.util.getUrlParameters();
+    }
 
-  /**
+    /**
    * Return a transport representing the best available cross-domain
    * message-passing mechanism available to the browser.
    *
@@ -166,149 +166,149 @@ gadgets.rpc = function() {
    * @return {Object}
    * @member gadgets.rpc
    */
-  function getTransport() {
-    return typeof window.postMessage === 'function' ? gadgets.rpctx.wpm :
-           typeof window.postMessage === 'object' ? gadgets.rpctx.wpm :
-           window.ActiveXObject ? gadgets.rpctx.nix :
-           navigator.userAgent.indexOf('WebKit') > 0 ? gadgets.rpctx.rmr :
-           navigator.product === 'Gecko' ? gadgets.rpctx.frameElement :
-           gadgets.rpctx.ifpc;
-  }
+    function getTransport() {
+      return typeof window.postMessage === 'function' ? gadgets.rpctx.wpm :
+          typeof window.postMessage === 'object' ? gadgets.rpctx.wpm :
+          window.ActiveXObject ? gadgets.rpctx.nix :
+          navigator.userAgent.indexOf('WebKit') > 0 ? gadgets.rpctx.rmr :
+          navigator.product === 'Gecko' ? gadgets.rpctx.frameElement :
+          gadgets.rpctx.ifpc;
+    }
 
-  /**
+    /**
    * Function passed to, and called by, a transport indicating it's ready to
    * send and receive messages.
    */
-  function transportReady(receiverId, readySuccess) {
-    var tx = transport;
-    if (!readySuccess) {
-      tx = fallbackTransport;
-    }
-    receiverTx[receiverId] = tx;
-
-    // If there are any early-queued messages, send them now directly through
-    // the needed transport.
-    var earlyQueue = earlyRpcQueue[receiverId] || [];
-    for (var i = 0; i < earlyQueue.length; ++i) {
-      var rpc = earlyQueue[i];
-      // There was no auth/rpc token set before, so set it now.
-      rpc.t = getAuthToken(receiverId);
-      tx.call(receiverId, rpc.f, rpc);
-    }
-
-    // Clear the queue so it won't be sent again.
-    earlyRpcQueue[receiverId] = [];
-  }
-
-  //  Track when this main page is closed or navigated to a different location
-  // ("unload" event).
-  //  NOTE: The use of the "unload" handler here and for the relay iframe
-  // prevents the use of the in-memory page cache in modern browsers.
-  // See: https://developer.mozilla.org/en/using_firefox_1.5_caching
-  // See: http://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
-  var mainPageUnloading = false,
-      hookedUnload = false;
-  
-  function hookMainPageUnload() {
-    if ( hookedUnload ) {
-      return;
-    }
-    function onunload() {
-      mainPageUnloading = true;
-    }
-    gadgets.util.attachBrowserEvent(window, 'unload', onunload, false);
-    hookedUnload = true;
-  }
-
-  function relayOnload(targetId, sourceId, token, data, relayWindow) {
-    // Validate auth token.
-    if (!authToken[sourceId] || authToken[sourceId] !== token) {
-      gadgets.error("Invalid auth token. " + authToken[sourceId] + " vs " + token);
-      securityCallback(sourceId, FORGED_MSG);
-    }
-    
-    relayWindow.onunload = function() {
-      if (setup[sourceId] && !mainPageUnloading) {
-        securityCallback(sourceId, FRAME_PHISH);
-        gadgets.rpc.removeReceiver(sourceId);
+    function transportReady(receiverId, readySuccess) {
+      var tx = transport;
+      if (!readySuccess) {
+        tx = fallbackTransport;
+      }
+      receiverTx[receiverId] = tx;
+
+      // If there are any early-queued messages, send them now directly through
+      // the needed transport.
+      var earlyQueue = earlyRpcQueue[receiverId] || [];
+      for (var i = 0; i < earlyQueue.length; ++i) {
+        var rpc = earlyQueue[i];
+        // There was no auth/rpc token set before, so set it now.
+        rpc.t = getAuthToken(receiverId);
+        tx.call(receiverId, rpc.f, rpc);
+      }
+
+      // Clear the queue so it won't be sent again.
+      earlyRpcQueue[receiverId] = [];
+    }
+
+    //  Track when this main page is closed or navigated to a different location
+    // ("unload" event).
+    //  NOTE: The use of the "unload" handler here and for the relay iframe
+    // prevents the use of the in-memory page cache in modern browsers.
+    // See: https://developer.mozilla.org/en/using_firefox_1.5_caching
+    // See: http://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
+    var mainPageUnloading = false,
+        hookedUnload = false;
+
+    function hookMainPageUnload() {
+      if (hookedUnload) {
+        return;
       }
-    };
-    hookMainPageUnload();
-    
-    data = gadgets.json.parse(decodeURIComponent(data));
-    transport.relayOnload(sourceId, data);
-  }
+      function onunload() {
+        mainPageUnloading = true;
+      }
+      gadgets.util.attachBrowserEvent(window, 'unload', onunload, false);
+      hookedUnload = true;
+    }
 
-  /**
+    function relayOnload(targetId, sourceId, token, data, relayWindow) {
+      // Validate auth token.
+      if (!authToken[sourceId] || authToken[sourceId] !== token) {
+        gadgets.error('Invalid auth token. ' + authToken[sourceId] + ' vs ' + token);
+        securityCallback(sourceId, FORGED_MSG);
+      }
+
+      relayWindow.onunload = function() {
+        if (setup[sourceId] && !mainPageUnloading) {
+          securityCallback(sourceId, FRAME_PHISH);
+          gadgets.rpc.removeReceiver(sourceId);
+        }
+      };
+      hookMainPageUnload();
+
+      data = gadgets.json.parse(decodeURIComponent(data));
+      transport.relayOnload(sourceId, data);
+    }
+
+    /**
    * Helper function to process an RPC request
-   * @param {Object} rpc RPC request object
+   * @param {Object} rpc RPC request object.
    * @private
    */
-  function process(rpc) {
-    //
-    // RPC object contents:
-    //   s: Service Name
-    //   f: From
-    //   c: The callback ID or 0 if none.
-    //   a: The arguments for this RPC call.
-    //   t: The authentication token.
-    //
-    if (rpc && typeof rpc.s === 'string' && typeof rpc.f === 'string' &&
-        rpc.a instanceof Array) {
+    function process(rpc) {
+      //
+      // RPC object contents:
+      //   s: Service Name
+      //   f: From
+      //   c: The callback ID or 0 if none.
+      //   a: The arguments for this RPC call.
+      //   t: The authentication token.
+      //
+      if (rpc && typeof rpc.s === 'string' && typeof rpc.f === 'string' &&
+          rpc.a instanceof Array) {
 
-      // Validate auth token.
-      if (authToken[rpc.f]) {
-        // We don't do type coercion here because all entries in the authToken
-        // object are strings, as are all url params. See setupReceiver(...).
-        if (authToken[rpc.f] !== rpc.t) {
-          gadgets.error("Invalid auth token. " + authToken[rpc.f] + " vs " + rpc.t);
-          securityCallback(rpc.f, FORGED_MSG);
+        // Validate auth token.
+        if (authToken[rpc.f]) {
+          // We don't do type coercion here because all entries in the authToken
+          // object are strings, as are all url params. See setupReceiver(...).
+          if (authToken[rpc.f] !== rpc.t) {
+            gadgets.error('Invalid auth token. ' + authToken[rpc.f] + ' vs ' + rpc.t);
+            securityCallback(rpc.f, FORGED_MSG);
+          }
         }
-      }
 
-      if (rpc.s === ACK) {
-        // Acknowledgement API, used to indicate a receiver is ready.
-        window.setTimeout(function() { transportReady(rpc.f, true); }, 0);
-        return;
-      }
+        if (rpc.s === ACK) {
+          // Acknowledgement API, used to indicate a receiver is ready.
+          window.setTimeout(function() { transportReady(rpc.f, true); }, 0);
+          return;
+        }
 
-      // If there is a callback for this service, attach a callback function
-      // to the rpc context object for asynchronous rpc services.
-      //
-      // Synchronous rpc request handlers should simply ignore it and return a
-      // value as usual.
-      // Asynchronous rpc request handlers, on the other hand, should pass its
-      // result to this callback function and not return a value on exit.
-      //
-      // For example, the following rpc handler passes the first parameter back
-      // to its rpc client with a one-second delay.
-      //
-      // function asyncRpcHandler(param) {
-      //   var me = this;
-      //   setTimeout(function() {
-      //     me.callback(param);
-      //   }, 1000);
-      // }
-      if (rpc.c) {
-        rpc.callback = function(result) {
-          gadgets.rpc.call(rpc.f, CALLBACK_NAME, null, rpc.c, result);
-        };
-      }
+        // If there is a callback for this service, attach a callback function
+        // to the rpc context object for asynchronous rpc services.
+        //
+        // Synchronous rpc request handlers should simply ignore it and return a
+        // value as usual.
+        // Asynchronous rpc request handlers, on the other hand, should pass its
+        // result to this callback function and not return a value on exit.
+        //
+        // For example, the following rpc handler passes the first parameter back
+        // to its rpc client with a one-second delay.
+        //
+        // function asyncRpcHandler(param) {
+        //   var me = this;
+        //   setTimeout(function() {
+        //     me.callback(param);
+        //   }, 1000);
+        // }
+        if (rpc.c) {
+          rpc.callback = function(result) {
+            gadgets.rpc.call(rpc.f, CALLBACK_NAME, null, rpc.c, result);
+          };
+        }
 
-      // Call the requested RPC service.
-      var result = (services[rpc.s] ||
-                    services[DEFAULT_NAME]).apply(rpc, rpc.a);
-
-      // If the rpc request handler returns a value, immediately pass it back
-      // to the callback. Otherwise, do nothing, assuming that the rpc handler
-      // will make an asynchronous call later.
-      if (rpc.c && typeof result !== 'undefined') {
-        gadgets.rpc.call(rpc.f, CALLBACK_NAME, null, rpc.c, result);
+        // Call the requested RPC service.
+        var result = (services[rpc.s] ||
+            services[DEFAULT_NAME]).apply(rpc, rpc.a);
+
+        // If the rpc request handler returns a value, immediately pass it back
+        // to the callback. Otherwise, do nothing, assuming that the rpc handler
+        // will make an asynchronous call later.
+        if (rpc.c && typeof result !== 'undefined') {
+          gadgets.rpc.call(rpc.f, CALLBACK_NAME, null, rpc.c, result);
+        }
       }
     }
-  }
 
-  /**
+    /**
    * Helper method returning a canonicalized protocol://host[:port] for
    * a given input URL, provided as a string. Used to compute convenient
    * relay URLs and to determine whether a call is coming from the same
@@ -319,164 +319,164 @@ gadgets.rpc = function() {
    * @memberOf gadgets.rpc
    */
 
-  function getOrigin(url) {
-    if (!url) {
-      return "";
-    }
-    url = url.toLowerCase();
-    if (url.indexOf("//") == 0) {
-      url = window.location.protocol + url;
-    }
-    if (url.indexOf("://") == -1) {
-      // Assumed to be schemaless. Default to current protocol.
-      url = window.location.protocol + "//" + url;
-    }
-    // At this point we guarantee that "://" is in the URL and defines
-    // current protocol. Skip past this to search for host:port.
-    var host = url.substring(url.indexOf("://") + 3);
-
-    // Find the first slash char, delimiting the host:port.
-    var slashPos = host.indexOf("/");
-    if (slashPos != -1) {
-      host = host.substring(0, slashPos);
-    }
-
-    var protocol = url.substring(0, url.indexOf("://"));
-
-    // Use port only if it's not default for the protocol.
-    var portStr = "";
-    var portPos = host.indexOf(":");
-    if (portPos != -1) {
-      var port = host.substring(portPos + 1);
-      host = host.substring(0, portPos);
-      if ((protocol === "http" && port !== "80") ||
-          (protocol === "https" && port !== "443")) {
-        portStr = ":" + port;
-      }
-    }
-
-    // Return <protocol>://<host>[<port>]
-    return protocol + "://" + host + portStr;
-  }
-
-  function getTargetWin(id) {
-    if (typeof id === "undefined" ||
-        id === "..") {
-      return window.parent;
-    }
-
-    // Cast to a String to avoid an index lookup.
-    id = String(id);
-    
-    // Try window.frames first
-    var target = window.frames[id];
-    if (target) {
-      return target;
-    }
-    
-    // Fall back to getElementById()
-    target = document.getElementById(id);
-    if (target && target.contentWindow) {
-      return target.contentWindow;
-    }
-
-    return null;
-  }
-
-  // Pick the most efficient RPC relay mechanism.
-  var transport = getTransport();
-
-  // Create the Default RPC handler.
-  services[DEFAULT_NAME] = function() {
-    gadgets.warn('Unknown RPC service: ' + this.s);
-  };
-
-  // Create a Special RPC handler for callbacks.
-  services[CALLBACK_NAME] = function(callbackId, result) {
-    var callback = callbacks[callbackId];
-    if (callback) {
-      delete callbacks[callbackId];
-      callback(result);
+    function getOrigin(url) {
+      if (!url) {
+        return '';
+      }
+      url = url.toLowerCase();
+      if (url.indexOf('//') == 0) {
+        url = window.location.protocol + url;
+      }
+      if (url.indexOf('://') == -1) {
+        // Assumed to be schemaless. Default to current protocol.
+        url = window.location.protocol + '//' + url;
+      }
+      // At this point we guarantee that "://" is in the URL and defines
+      // current protocol. Skip past this to search for host:port.
+      var host = url.substring(url.indexOf('://') + 3);
+
+      // Find the first slash char, delimiting the host:port.
+      var slashPos = host.indexOf('/');
+      if (slashPos != -1) {
+        host = host.substring(0, slashPos);
+      }
+
+      var protocol = url.substring(0, url.indexOf('://'));
+
+      // Use port only if it's not default for the protocol.
+      var portStr = '';
+      var portPos = host.indexOf(':');
+      if (portPos != -1) {
+        var port = host.substring(portPos + 1);
+        host = host.substring(0, portPos);
+        if ((protocol === 'http' && port !== '80') ||
+            (protocol === 'https' && port !== '443')) {
+          portStr = ':' + port;
+        }
+      }
+
+      // Return <protocol>://<host>[<port>]
+      return protocol + '://' + host + portStr;
     }
-  };
 
-  /**
+    function getTargetWin(id) {
+      if (typeof id === 'undefined' ||
+          id === '..') {
+        return window.parent;
+      }
+
+      // Cast to a String to avoid an index lookup.
+      id = String(id);
+
+      // Try window.frames first
+      var target = window.frames[id];
+      if (target) {
+        return target;
+      }
+
+      // Fall back to getElementById()
+      target = document.getElementById(id);
+      if (target && target.contentWindow) {
+        return target.contentWindow;
+      }
+
+      return null;
+    }
+
+    // Pick the most efficient RPC relay mechanism.
+    var transport = getTransport();
+
+    // Create the Default RPC handler.
+    services[DEFAULT_NAME] = function() {
+      gadgets.warn('Unknown RPC service: ' + this.s);
+    };
+
+    // Create a Special RPC handler for callbacks.
+    services[CALLBACK_NAME] = function(callbackId, result) {
+      var callback = callbacks[callbackId];
+      if (callback) {
+        delete callbacks[callbackId];
+        callback(result);
+      }
+    };
+
+    /**
    * Conducts any frame-specific work necessary to setup
    * the channel type chosen. This method is called when
    * the container page first registers the gadget in the
    * RPC mechanism. Gadgets, in turn, will complete the setup
    * of the channel once they send their first messages.
    */
-  function setupFrame(frameId, token, forcesecure) {
-    if (setup[frameId] === true) {
-      return;
-    }
+    function setupFrame(frameId, token, forcesecure) {
+      if (setup[frameId] === true) {
+        return;
+      }
 
-    if (typeof setup[frameId] === 'undefined') {
-      setup[frameId] = 0;
-    }
+      if (typeof setup[frameId] === 'undefined') {
+        setup[frameId] = 0;
+      }
 
-    var tgtFrame = document.getElementById(frameId);
-    if (frameId === '..' || tgtFrame != null) {
-      if (transport.setup(frameId, token, forcesecure) === true) {
-        setup[frameId] = true;
-        return;
+      var tgtFrame = document.getElementById(frameId);
+      if (frameId === '..' || tgtFrame != null) {
+        if (transport.setup(frameId, token, forcesecure) === true) {
+          setup[frameId] = true;
+          return;
+        }
       }
-    }
 
-    if (setup[frameId] !== true && setup[frameId]++ < SETUP_FRAME_MAX_TRIES) {
-      // Try again in a bit, assuming that frame will soon exist.
-      window.setTimeout(function() { setupFrame(frameId, token, forcesecure) },
+      if (setup[frameId] !== true && setup[frameId]++ < SETUP_FRAME_MAX_TRIES) {
+        // Try again in a bit, assuming that frame will soon exist.
+        window.setTimeout(function() { setupFrame(frameId, token, forcesecure) },
                         SETUP_FRAME_TIMEOUT);
-    } else {
-      // Fail: fall back for this gadget.
-      receiverTx[frameId] = fallbackTransport;
-      setup[frameId] = true;
+      } else {
+        // Fail: fall back for this gadget.
+        receiverTx[frameId] = fallbackTransport;
+        setup[frameId] = true;
+      }
     }
-  }
 
-  /**
+    /**
    * 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 {Object} rpc RPC data
+   * @param {string} target Module id of the rpc service provider.
+   * @param {Object} rpc RPC data.
    * @return {boolean}
    */
-  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 targetRelay = gadgets.rpc.getRelayUrl(target);
-      if (getOrigin(targetRelay) !== getOrigin(window.location.href)) {
-        // Not worth trying -- avoid the error and just return.
-        return false;
-      }
-
-      var targetEl = getTargetWin(target);
-      try {
-        // If this succeeds, then same-domain policy applied
-        sameDomain[target] = targetEl.gadgets.rpc.receiveSameDomain;
-      } catch (e) {
-        // Shouldn't happen due to origin check. Caught to emit
-        // more meaningful error to the caller.
-        gadgets.error("Same domain call failed: parent= incorrectly set.");
+    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 targetRelay = gadgets.rpc.getRelayUrl(target);
+        if (getOrigin(targetRelay) !== getOrigin(window.location.href)) {
+          // Not worth trying -- avoid the error and just return.
+          return false;
+        }
+
+        var targetEl = getTargetWin(target);
+        try {
+          // If this succeeds, then same-domain policy applied
+          sameDomain[target] = targetEl.gadgets.rpc.receiveSameDomain;
+        } catch (e) {
+          // Shouldn't happen due to origin check. Caught to emit
+          // more meaningful error to the caller.
+          gadgets.error('Same domain call failed: parent= incorrectly set.');
+        }
       }
-    }
 
-    if (typeof sameDomain[target] === 'function') {
-      // Call target's receive method
-      sameDomain[target](rpc);
-      return true;
-    }
+      if (typeof sameDomain[target] === 'function') {
+        // Call target's receive method
+        sameDomain[target](rpc);
+        return true;
+      }
 
-    return false;
-  }
+      return false;
+    }
 
-  /**
+    /**
    * Sets the relay URL of a target frame.
    * @param {string} targetId Name of the target frame.
    * @param {string} url Full relay URL of the target frame.
@@ -486,33 +486,33 @@ gadgets.rpc = function() {
    * @member gadgets.rpc
    * @deprecated
    */
-  function setRelayUrl(targetId, url, opt_useLegacy) {
-    // make URL absolute if necessary
-    if (!/http(s)?:\/\/.+/.test(url)) {
-      if (url.indexOf("//") == 0) {
-        url = window.location.protocol + url;
-      } else if (url.charAt(0) == '/') {
-        url = window.location.protocol + "//" + window.location.host + url;
-      } else if (url.indexOf("://") == -1) {
-        // Assumed to be schemaless. Default to current protocol.
-        url = window.location.protocol + "//" + url;
+    function setRelayUrl(targetId, url, opt_useLegacy) {
+      // make URL absolute if necessary
+      if (!/http(s)?:\/\/.+/.test(url)) {
+        if (url.indexOf('//') == 0) {
+          url = window.location.protocol + url;
+        } else if (url.charAt(0) == '/') {
+          url = window.location.protocol + '//' + window.location.host + url;
+        } else if (url.indexOf('://') == -1) {
+          // Assumed to be schemaless. Default to current protocol.
+          url = window.location.protocol + '//' + url;
+        }
       }
+      relayUrl[targetId] = url;
+      useLegacyProtocol[targetId] = !!opt_useLegacy;
     }
-    relayUrl[targetId] = url;
-    useLegacyProtocol[targetId] = !!opt_useLegacy;
-  }
 
-  /**
+    /**
    * Helper method to retrieve the authToken for a given gadget.
    * Not to be used directly.
    * @member gadgets.rpc
    * @return {string}
    */
-  function getAuthToken(targetId) {
-    return authToken[targetId];
-  }
+    function getAuthToken(targetId) {
+      return authToken[targetId];
+    }
 
-  /**
+    /**
    * Sets the auth token of a target frame.
    * @param {string} targetId Name of the target frame.
    * @param {string} token The authentication token to use for all
@@ -521,103 +521,103 @@ gadgets.rpc = function() {
    * @member gadgets.rpc
    * @deprecated
    */
-  function setAuthToken(targetId, token, forcesecure) {
-    token = token || "";
+    function setAuthToken(targetId, token, forcesecure) {
+      token = token || '';
 
-    // Coerce token to a String, ensuring that all authToken values
-    // are strings. This ensures correct comparison with URL params
-    // in the process(rpc) method.
-    authToken[targetId] = String(token);
+      // Coerce token to a String, ensuring that all authToken values
+      // are strings. This ensures correct comparison with URL params
+      // in the process(rpc) method.
+      authToken[targetId] = String(token);
 
-    setupFrame(targetId, token, forcesecure);
-  }
+      setupFrame(targetId, token, forcesecure);
+    }
 
-  function setupContainerGadgetContext(rpctoken, opt_forcesecure) {
-    /**
+    function setupContainerGadgetContext(rpctoken, opt_forcesecure) {
+      /**
      * Initializes gadget to container RPC params from the provided configuration.
      */
-    function init(config) {
-      var configRpc = config ? config.rpc : {};
-      var parentRelayUrl = configRpc.parentRelayUrl;
-
-      // Allow for wild card parent relay files as long as it's from a
-      // white listed domain. This is enforced by the rendering servlet.
-      if (parentRelayUrl.substring(0, 7) !== 'http://' &&
-          parentRelayUrl.substring(0, 8) !== 'https://' &&
-          parentRelayUrl.substring(0, 2) !== '//') {
-        // Relative path: we append to the parent.
-        // We're relying on the server validating the parent parameter in this
-        // case. Because of this, parent may only be passed in the query, not fragment.
-        if (typeof params.parent === "string" && params.parent !== "") {
-          // Otherwise, relayUrl['..'] will be null, signaling transport
-          // code to ignore rpc calls since they cannot work without a
-          // relay URL with host qualification.
-          if (parentRelayUrl.substring(0, 1) !== '/') {
-            // Path-relative. Trust that parent is passed in appropriately.
-            var lastSlash = params.parent.lastIndexOf('/');
-            parentRelayUrl = params.parent.substring(0, lastSlash + 1) + parentRelayUrl;
-          } else {
-            // Host-relative.
-            parentRelayUrl = getOrigin(params.parent) + parentRelayUrl;
+      function init(config) {
+        var configRpc = config ? config.rpc : {};
+        var parentRelayUrl = configRpc.parentRelayUrl;
+
+        // Allow for wild card parent relay files as long as it's from a
+        // white listed domain. This is enforced by the rendering servlet.
+        if (parentRelayUrl.substring(0, 7) !== 'http://' &&
+            parentRelayUrl.substring(0, 8) !== 'https://' &&
+            parentRelayUrl.substring(0, 2) !== '//') {
+          // Relative path: we append to the parent.
+          // We're relying on the server validating the parent parameter in this
+          // case. Because of this, parent may only be passed in the query, not fragment.
+          if (typeof params.parent === 'string' && params.parent !== '') {
+            // Otherwise, relayUrl['..'] will be null, signaling transport
+            // code to ignore rpc calls since they cannot work without a
+            // relay URL with host qualification.
+            if (parentRelayUrl.substring(0, 1) !== '/') {
+              // Path-relative. Trust that parent is passed in appropriately.
+              var lastSlash = params.parent.lastIndexOf('/');
+              parentRelayUrl = params.parent.substring(0, lastSlash + 1) + parentRelayUrl;
+            } else {
+              // Host-relative.
+              parentRelayUrl = getOrigin(params.parent) + parentRelayUrl;
+            }
           }
         }
-      }
 
-      var useLegacy = !!configRpc.useLegacyProtocol;
-      setRelayUrl('..', parentRelayUrl, useLegacy);
+        var useLegacy = !!configRpc.useLegacyProtocol;
+        setRelayUrl('..', parentRelayUrl, useLegacy);
 
-      if (useLegacy) {
-        transport = gadgets.rpctx.ifpc;
-        transport.init(process, transportReady);
+        if (useLegacy) {
+          transport = gadgets.rpctx.ifpc;
+          transport.init(process, transportReady);
+        }
+
+        // Sets the auth token and signals transport to setup connection to container.
+        var forceSecure = opt_forcesecure || params.forcesecure || false;
+        setAuthToken('..', rpctoken, forceSecure);
       }
 
-      // Sets the auth token and signals transport to setup connection to container.
-      var forceSecure = opt_forcesecure || params.forcesecure || false;
-      setAuthToken('..', rpctoken, forceSecure);
+      var requiredConfig = {
+        parentRelayUrl: gadgets.config.NonEmptyStringValidator
+      };
+      gadgets.config.register('rpc', requiredConfig, init);
     }
 
-    var requiredConfig = {
-      parentRelayUrl : gadgets.config.NonEmptyStringValidator
-    };
-    gadgets.config.register("rpc", requiredConfig, init);
-  }
+    function setupContainerGenericIframe(rpctoken, opt_parent, opt_forcesecure) {
+      // Generic child IFRAME setting up connection w/ its container.
+      // Use the opt_parent param if provided, or the "parent" query param
+      // if found -- otherwise, do nothing since this call might be initiated
+      // automatically at first, then actively later in IFRAME code.
+      var forcesecure = opt_forcesecure || params.forcesecure || false;
+      var parent = opt_parent || params.parent;
+      if (parent) {
+        setRelayUrl('..', parent);
+        setAuthToken('..', rpctoken, forcesecure);
+      }
+    }
 
-  function setupContainerGenericIframe(rpctoken, opt_parent, opt_forcesecure) {
-    // Generic child IFRAME setting up connection w/ its container.
-    // Use the opt_parent param if provided, or the "parent" query param
-    // if found -- otherwise, do nothing since this call might be initiated
-    // automatically at first, then actively later in IFRAME code.
-    var forcesecure = opt_forcesecure || params.forcesecure || false;
-    var parent = opt_parent || params.parent;
-    if (parent) {
-      setRelayUrl('..', parent);
-      setAuthToken('..', rpctoken, forcesecure);
-    }
-  }
-
-  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.");
-    }
-
-    // The "relay URL" can either be explicitly specified or is set as
-    // the child IFRAME URL verbatim.
-    var relayUrl = opt_frameurl || childIframe.src;
-    setRelayUrl(gadgetId, relayUrl);
-
-    // The auth token is parsed from child params (rpctoken) or overridden.
-    var childParams = gadgets.util.getUrlParameters(childIframe.src);
-    var rpctoken = opt_authtoken || childParams.rpctoken;
-    var forcesecure = opt_forcesecure || childParams.forcesecure;
-    setAuthToken(gadgetId, rpctoken, forcesecure);
-  }
+    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.');
+      }
+
+      // The "relay URL" can either be explicitly specified or is set as
+      // the child IFRAME URL verbatim.
+      var relayUrl = opt_frameurl || childIframe.src;
+      setRelayUrl(gadgetId, relayUrl);
+
+      // The auth token is parsed from child params (rpctoken) or overridden.
+      var childParams = gadgets.util.getUrlParameters(childIframe.src);
+      var rpctoken = opt_authtoken || childParams.rpctoken;
+      var forcesecure = opt_forcesecure || childParams.forcesecure;
+      setAuthToken(gadgetId, rpctoken, forcesecure);
+    }
 
-  /**
+    /**
    * Sets up the gadgets.rpc library to communicate with the receiver.
    * <p>This method replaces setRelayUrl(...) and setAuthToken(...)
    *
@@ -661,102 +661,102 @@ gadgets.rpc = function() {
    * @param {string=} opt_authtoken
    * @param {boolean=} opt_forcesecure
    */
-  function setupReceiver(targetId, opt_receiverurl, opt_authtoken, opt_forcesecure) {
-    if (targetId === '..') {
-      // Gadget/IFRAME to container.
-      var rpctoken = opt_authtoken || params.rpctoken || params.ifpctok || "";
-      if (window['__isgadget'] === true) {
-        setupContainerGadgetContext(rpctoken, opt_forcesecure);
+    function setupReceiver(targetId, opt_receiverurl, opt_authtoken, opt_forcesecure) {
+      if (targetId === '..') {
+        // Gadget/IFRAME to container.
+        var rpctoken = opt_authtoken || params.rpctoken || params.ifpctok || '';
+        if (window['__isgadget'] === true) {
+          setupContainerGadgetContext(rpctoken, opt_forcesecure);
+        } else {
+          setupContainerGenericIframe(rpctoken, opt_receiverurl, opt_forcesecure);
+        }
       } else {
-        setupContainerGenericIframe(rpctoken, opt_receiverurl, opt_forcesecure);
+        // Container to child.
+        setupChildIframe(targetId, opt_receiverurl, opt_authtoken, opt_forcesecure);
       }
-    } else {
-      // Container to child.
-      setupChildIframe(targetId, opt_receiverurl, opt_authtoken, opt_forcesecure);
     }
-  }
 
-  return /** @scope gadgets.rpc */ {
-    config: function(config) {
-      if (typeof config.securityCallback === 'function') {
-        securityCallback = config.securityCallback;
-      }
-    },
-    
-    /**
+    return /** @scope gadgets.rpc */ {
+      config: function(config) {
+        if (typeof config.securityCallback === 'function') {
+          securityCallback = config.securityCallback;
+        }
+      },
+
+      /**
      * Registers an RPC service.
      * @param {string} serviceName Service name to register.
      * @param {function(Object,Object)} handler Service handler.
      *
      * @member gadgets.rpc
      */
-    register: function(serviceName, handler) {
-      if (serviceName === CALLBACK_NAME || serviceName === ACK) {
-        throw new Error("Cannot overwrite callback/ack service");
-      }
+      register: function(serviceName, handler) {
+        if (serviceName === CALLBACK_NAME || serviceName === ACK) {
+          throw new Error('Cannot overwrite callback/ack service');
+        }
 
-      if (serviceName === DEFAULT_NAME) {
-        throw new Error("Cannot overwrite default service:"
-                        + " use registerDefault");
-      }
+        if (serviceName === DEFAULT_NAME) {
+          throw new Error('Cannot overwrite default service:'
+                        + ' use registerDefault');
+        }
 
-      services[serviceName] = handler;
-    },
+        services[serviceName] = handler;
+      },
 
-    /**
+      /**
      * Unregisters an RPC service.
      * @param {string} serviceName Service name to unregister.
      *
      * @member gadgets.rpc
      */
-    unregister: function(serviceName) {
-      if (serviceName === CALLBACK_NAME || serviceName === ACK) {
-        throw new Error("Cannot delete callback/ack service");
-      }
+      unregister: function(serviceName) {
+        if (serviceName === CALLBACK_NAME || serviceName === ACK) {
+          throw new Error('Cannot delete callback/ack service');
+        }
 
-      if (serviceName === DEFAULT_NAME) {
-        throw new Error("Cannot delete default service:"
-                        + " use unregisterDefault");
-      }
+        if (serviceName === DEFAULT_NAME) {
+          throw new Error('Cannot delete default service:'
+                        + ' use unregisterDefault');
+        }
 
-      delete services[serviceName];
-    },
+        delete services[serviceName];
+      },
 
-    /**
+      /**
      * Registers a default service handler to processes all unknown
      * RPC calls which raise an exception by default.
      * @param {function(Object,Object)} handler Service handler.
      *
      * @member gadgets.rpc
      */
-    registerDefault: function(handler) {
-      services[DEFAULT_NAME] = handler;
-    },
+      registerDefault: function(handler) {
+        services[DEFAULT_NAME] = handler;
+      },
 
-    /**
+      /**
      * Unregisters the default service handler. Future unknown RPC
      * calls will fail silently.
      *
      * @member gadgets.rpc
      */
-    unregisterDefault: function() {
-      delete services[DEFAULT_NAME];
-    },
+      unregisterDefault: function() {
+        delete services[DEFAULT_NAME];
+      },
 
-    /**
+      /**
      * Forces all subsequent calls to be made by a transport
      * method that allows the caller to verify the message receiver
      * (by way of the parent parameter, through getRelayUrl(...)).
      * At present this means IFPC or WPM.
      * @member gadgets.rpc
      */
-    forceParentVerifiable: function() {
-      if (!transport.isParentVerifiable()) {
-        transport = gadgets.rpctx.ifpc;
-      }
-    },
+      forceParentVerifiable: function() {
+        if (!transport.isParentVerifiable()) {
+          transport = gadgets.rpctx.ifpc;
+        }
+      },
 
-    /**
+      /**
      * Calls an RPC service.
      * @param {string} targetId Module Id of the RPC service provider.
      *                          Empty if calling the parent container.
@@ -767,116 +767,116 @@ gadgets.rpc = function() {
      *
      * @member gadgets.rpc
      */
-    call: function(targetId, serviceName, callback, var_args) {
-      targetId = targetId || '..';
-      // Default to the container calling.
-      var from = '..';
+      call: function(targetId, serviceName, callback, var_args) {
+        targetId = targetId || '..';
+        // Default to the container calling.
+        var from = '..';
 
-      if (targetId === '..') {
-        from = rpcId;
-      }
+        if (targetId === '..') {
+          from = rpcId;
+        }
 
-      ++callId;
-      if (callback) {
-        callbacks[callId] = callback;
-      }
+        ++callId;
+        if (callback) {
+          callbacks[callId] = callback;
+        }
 
-      var rpc = {
-        s: serviceName,
-        f: from,
-        c: callback ? callId : 0,
-        a: Array.prototype.slice.call(arguments, 3),
-        t: authToken[targetId],
-        l: useLegacyProtocol[targetId]
-      };
+        var rpc = {
+          s: serviceName,
+          f: from,
+          c: callback ? callId : 0,
+          a: Array.prototype.slice.call(arguments, 3),
+          t: authToken[targetId],
+          l: useLegacyProtocol[targetId]
+        };
 
-      if (targetId !== '..' && !document.getElementById(targetId)) {
-        // The target has been removed from the DOM. Don't even try.
-        gadgets.log("WARNING: attempted send to nonexistent frame: " + targetId);
-        return;
-      }
+        if (targetId !== '..' && !document.getElementById(targetId)) {
+          // The target has been removed from the DOM. Don't even try.
+          gadgets.log('WARNING: attempted send to nonexistent frame: ' + targetId);
+          return;
+        }
 
-      // If target is on the same domain, call method directly
-      if (callSameDomain(targetId, rpc)) {
-        return;
-      }
+        // If target is on the same domain, call method directly
+        if (callSameDomain(targetId, rpc)) {
+          return;
+        }
 
-      // Attempt to make call via a cross-domain transport.
-      // Retrieve the transport for the given target - if one
-      // target is misconfigured, it won't affect the others.
-      var channel = receiverTx[targetId];
-
-      if (!channel) {
-        // Not set up yet. Enqueue the rpc for such time as it is.
-        if (!earlyRpcQueue[targetId]) {
-          earlyRpcQueue[targetId] = [ rpc ];
-        } else {
-          earlyRpcQueue[targetId].push(rpc);
+        // Attempt to make call via a cross-domain transport.
+        // Retrieve the transport for the given target - if one
+        // target is misconfigured, it won't affect the others.
+        var channel = receiverTx[targetId];
+
+        if (!channel) {
+          // Not set up yet. Enqueue the rpc for such time as it is.
+          if (!earlyRpcQueue[targetId]) {
+            earlyRpcQueue[targetId] = [rpc];
+          } else {
+            earlyRpcQueue[targetId].push(rpc);
+          }
+          return;
         }
-        return;
-      }
 
-      // If we are told to use the legacy format, then we must
-      // default to IFPC.
-      if (useLegacyProtocol[targetId]) {
-        channel = gadgets.rpctx.ifpc;
-      }
+        // If we are told to use the legacy format, then we must
+        // default to IFPC.
+        if (useLegacyProtocol[targetId]) {
+          channel = gadgets.rpctx.ifpc;
+        }
 
-      if (channel.call(targetId, from, rpc) === false) {
-        // Fall back to IFPC. This behavior may be removed as IFPC is as well.
-        receiverTx[targetId] = fallbackTransport;
-        transport.call(targetId, from, rpc);
-      }
-    },
+        if (channel.call(targetId, from, rpc) === false) {
+          // Fall back to IFPC. This behavior may be removed as IFPC is as well.
+          receiverTx[targetId] = fallbackTransport;
+          transport.call(targetId, from, rpc);
+        }
+      },
 
-    /**
+      /**
      * Gets the relay URL of a target frame.
      * @param {string} targetId Name of the target frame.
      * @return {string|undefined} Relay URL of the target frame.
      *
      * @member gadgets.rpc
      */
-    getRelayUrl: function(targetId) {
-      var url = relayUrl[targetId];
-      // Some RPC methods (wpm, for one) are unhappy with schemeless URLs.
-      if (url && url.substring(0,1) === '/') {
-        if (url.substring(1,2) === '/') {    // starts with '//'
-          url = document.location.protocol + url;
-        } else {    // relative URL, starts with '/'
-          url = document.location.protocol + '//' + document.location.host + url;
-        }
-      }
-      
-      return url;
-    },
-
-    setRelayUrl: setRelayUrl,
-    setAuthToken: setAuthToken,
-    setupReceiver: setupReceiver,
-    getAuthToken: getAuthToken,
-    
-    // Note: Does not delete iframe
-    removeReceiver: function(receiverId) {
-      delete relayUrl[receiverId];
-      delete useLegacyProtocol[receiverId];
-      delete authToken[receiverId];
-      delete setup[receiverId];
-      delete sameDomain[receiverId];
-      delete receiverTx[receiverId];
-    },
+      getRelayUrl: function(targetId) {
+        var url = relayUrl[targetId];
+        // Some RPC methods (wpm, for one) are unhappy with schemeless URLs.
+        if (url && url.substring(0, 1) === '/') {
+          if (url.substring(1, 2) === '/') {    // starts with '//'
+            url = document.location.protocol + url;
+          } else {    // relative URL, starts with '/'
+            url = document.location.protocol + '//' + document.location.host + url;
+          }
+        }
 
-    /**
+        return url;
+      },
+
+      setRelayUrl: setRelayUrl,
+      setAuthToken: setAuthToken,
+      setupReceiver: setupReceiver,
+      getAuthToken: getAuthToken,
+
+      // Note: Does not delete iframe
+      removeReceiver: function(receiverId) {
+        delete relayUrl[receiverId];
+        delete useLegacyProtocol[receiverId];
+        delete authToken[receiverId];
+        delete setup[receiverId];
+        delete sameDomain[receiverId];
+        delete receiverTx[receiverId];
+      },
+
+      /**
      * Gets the RPC relay mechanism.
      * @return {string} RPC relay mechanism. See above for
      *   a list of supported types.
      *
      * @member gadgets.rpc
      */
-    getRelayChannel: function() {
-      return transport.getCode();
-    },
+      getRelayChannel: function() {
+        return transport.getCode();
+      },
 
-    /**
+      /**
      * Receives and processes an RPC request. (Not to be used directly.)
      * Only used by IFPC.
      * @param {Array.<string>} fragment An RPC request fragment encoded as
@@ -887,115 +887,115 @@ gadgets.rpc = function() {
      * @member gadgets.rpc
      * @deprecated
      */
-    receive: function(fragment, otherWindow) {
-      if (fragment.length > 4) {
-        process(gadgets.json.parse(
-            decodeURIComponent(fragment[fragment.length - 1])));
-      } else {
-        relayOnload.apply(null, fragment.concat(otherWindow));
-      }
-    },
+      receive: function(fragment, otherWindow) {
+        if (fragment.length > 4) {
+          process(gadgets.json.parse(
+              decodeURIComponent(fragment[fragment.length - 1])));
+        } else {
+          relayOnload.apply(null, fragment.concat(otherWindow));
+        }
+      },
 
-    /**
+      /**
      * 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
+     * @param {Object} rpc RPC object containing all request params.
      * @member gadgets.rpc
      */
-    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);
-    },
-
-    // Helper method to get the protocol://host:port of an input URL.
-    // see docs above
-    getOrigin: getOrigin,
-
-    getReceiverOrigin: function(receiverId) {
-      var channel = receiverTx[receiverId];
-      if (!channel) {
-        // not set up yet
-        return null;
-      }
-      if (!channel.isParentVerifiable(receiverId)) {
-        // given transport cannot verify receiver origin
-        return null;
-      }
-      var origRelay = gadgets.rpc.getRelayUrl(receiverId) ||
-                      gadgets.util.getUrlParameters().parent;
-      return gadgets.rpc.getOrigin(origRelay);
-    },
+      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);
+      },
 
-    /**
+      // Helper method to get the protocol://host:port of an input URL.
+      // see docs above
+      getOrigin: getOrigin,
+
+      getReceiverOrigin: function(receiverId) {
+        var channel = receiverTx[receiverId];
+        if (!channel) {
+          // not set up yet
+          return null;
+        }
+        if (!channel.isParentVerifiable(receiverId)) {
+          // given transport cannot verify receiver origin
+          return null;
+        }
+        var origRelay = gadgets.rpc.getRelayUrl(receiverId) ||
+            gadgets.util.getUrlParameters().parent;
+        return gadgets.rpc.getOrigin(origRelay);
+      },
+
+      /**
      * Internal-only method used to initialize gadgets.rpc.
      * @member gadgets.rpc
      */
-    init: function() {
-      // Conduct any global setup necessary for the chosen transport.
-      // Do so after gadgets.rpc definition to allow transport to access
-      // gadgets.rpc methods.
-      if (transport.init(process, transportReady) === false) {
-        transport = fallbackTransport;
-      }
-      if (isChild) {
-        setupReceiver('..');
-      }
-    },
-
-    /** Returns the window keyed by the ID. null/".." for parent, else child */
-    _getTargetWin: getTargetWin,
-
-    /** Create an iframe for loading the relay URL. Used by child only. */ 
-    _createRelayIframe: function(token, data) {
-      var relay = gadgets.rpc.getRelayUrl('..');
-      if (!relay) {
-        return null;
-      }
-      
-      // Format: #targetId & sourceId & authToken & data
-      var src = relay + '#..&' + rpcId + '&' + token + '&' +
-          encodeURIComponent(gadgets.json.stringify(data));
-  
-      var iframe = document.createElement('iframe');
-      iframe.style.border = iframe.style.width = iframe.style.height = '0px';
-      iframe.style.visibility = 'hidden';
-      iframe.style.position = 'absolute';
-
-      function appendFn() {
-        // Append the iframe.
-        document.body.appendChild(iframe);
-  
-        // Set the src of the iframe to 'about:blank' first and then set it
-        // to the relay URI. This prevents the iframe from maintaining a src
-        // to the 'old' relay URI if the page is returned to from another.
-        // In other words, this fixes the bfcache issue that causes the iframe's
-        // src property to not be updated despite us assigning it a new value here.
-        iframe.src = 'javascript:"<html></html>"';
-        iframe.src = src;
-      }
-      
-      if (document.body) {
-        appendFn();
-      } else {
-        gadgets.util.registerOnLoadHandler(function() { appendFn(); });
-      }
-      
-      return iframe;
-    },
-
-    ACK: ACK,
-
-    RPC_ID: rpcId,
-    
-    SEC_ERROR_LOAD_TIMEOUT: LOAD_TIMEOUT,
-    SEC_ERROR_FRAME_PHISH: FRAME_PHISH,
-    SEC_ERROR_FORGED_MSG : FORGED_MSG
-  };
-}();
+      init: function() {
+        // Conduct any global setup necessary for the chosen transport.
+        // Do so after gadgets.rpc definition to allow transport to access
+        // gadgets.rpc methods.
+        if (transport.init(process, transportReady) === false) {
+          transport = fallbackTransport;
+        }
+        if (isChild) {
+          setupReceiver('..');
+        }
+      },
+
+      /** Returns the window keyed by the ID. null/".." for parent, else child */
+      _getTargetWin: getTargetWin,
+
+      /** Create an iframe for loading the relay URL. Used by child only. */
+      _createRelayIframe: function(token, data) {
+        var relay = gadgets.rpc.getRelayUrl('..');
+        if (!relay) {
+          return null;
+        }
+
+        // Format: #targetId & sourceId & authToken & data
+        var src = relay + '#..&' + rpcId + '&' + token + '&' +
+            encodeURIComponent(gadgets.json.stringify(data));
+
+        var iframe = document.createElement('iframe');
+        iframe.style.border = iframe.style.width = iframe.style.height = '0px';
+        iframe.style.visibility = 'hidden';
+        iframe.style.position = 'absolute';
+
+        function appendFn() {
+          // Append the iframe.
+          document.body.appendChild(iframe);
+
+          // Set the src of the iframe to 'about:blank' first and then set it
+          // to the relay URI. This prevents the iframe from maintaining a src
+          // to the 'old' relay URI if the page is returned to from another.
+          // In other words, this fixes the bfcache issue that causes the iframe's
+          // src property to not be updated despite us assigning it a new value here.
+          iframe.src = 'javascript:"<html></html>"';
+          iframe.src = src;
+        }
+
+        if (document.body) {
+          appendFn();
+        } else {
+          gadgets.util.registerOnLoadHandler(function() { appendFn(); });
+        }
+
+        return iframe;
+      },
+
+      ACK: ACK,
+
+      RPC_ID: rpcId,
+
+      SEC_ERROR_LOAD_TIMEOUT: LOAD_TIMEOUT,
+      SEC_ERROR_FRAME_PHISH: FRAME_PHISH,
+      SEC_ERROR_FORGED_MSG: FORGED_MSG
+    };
+  }();
 
-// Initialize library/transport.
-gadgets.rpc.init();
+  // Initialize library/transport.
+  gadgets.rpc.init();
 
 } // !end of double-inclusion guard

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=997163&r1=997162&r2=997163&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 Wed Sep 15 01:39:49 2010
@@ -43,132 +43,132 @@ gadgets.rpctx = gadgets.rpctx || {};
  */
 if (!gadgets.rpctx.wpm) {  // make lib resilient to double-inclusion
 
-gadgets.rpctx.wpm = function() {
-  var process, ready;
-  var postMessage;
-  var pmSync = false;
-  var pmEventDomain = false;
-  var isForceSecure = false;
-
-  // Some browsers (IE, Opera) have an implementation of postMessage that is
-  // synchronous, although HTML5 specifies that it should be asynchronous.  In
-  // order to make all browsers behave consistently, we run a small test to detect
-  // if postMessage is asynchronous or not.  If not, we wrap calls to postMessage
-  // in a setTimeout with a timeout of 0.
-  // Also, Opera's "message" event does not have an "origin" property (at least,
-  // it doesn't in version 9.64;  presumably, it will in version 10).  If
-  // event.origin does not exist, use event.domain.  The other difference is that
-  // while event.origin looks like <scheme>://<hostname>:<port>, event.domain
-  // consists only of <hostname>.
-  //
-  function testPostMessage() {
-    var hit = false;
-    
-    function receiveMsg(event) {
-      if (event.data == "postmessage.test") {
-        hit = true;
-        if (typeof event.origin === "undefined") {
-          pmEventDomain = true;
+  gadgets.rpctx.wpm = function() {
+    var process, ready;
+    var postMessage;
+    var pmSync = false;
+    var pmEventDomain = false;
+    var isForceSecure = false;
+
+    // Some browsers (IE, Opera) have an implementation of postMessage that is
+    // synchronous, although HTML5 specifies that it should be asynchronous.  In
+    // order to make all browsers behave consistently, we run a small test to detect
+    // if postMessage is asynchronous or not.  If not, we wrap calls to postMessage
+    // in a setTimeout with a timeout of 0.
+    // Also, Opera's "message" event does not have an "origin" property (at least,
+    // it doesn't in version 9.64;  presumably, it will in version 10).  If
+    // event.origin does not exist, use event.domain.  The other difference is that
+    // while event.origin looks like <scheme>://<hostname>:<port>, event.domain
+    // consists only of <hostname>.
+    //
+    function testPostMessage() {
+      var hit = false;
+
+      function receiveMsg(event) {
+        if (event.data == 'postmessage.test') {
+          hit = true;
+          if (typeof event.origin === 'undefined') {
+            pmEventDomain = true;
+          }
         }
       }
-    }
-    
-    gadgets.util.attachBrowserEvent(window, "message", receiveMsg, false);
-    window.postMessage("postmessage.test", "*");
-    
-    // if 'hit' is true here, then postMessage is synchronous
-    if (hit) {
-      pmSync = true;
-    }
-    
-    gadgets.util.removeBrowserEvent(window, "message", receiveMsg, false);
-  }
-
-  function onmessage(packet) {
-    var rpc = gadgets.json.parse(packet.data);
-    if (isForceSecure) {
-      if (!rpc || !rpc.f) {
-        return;
+
+      gadgets.util.attachBrowserEvent(window, 'message', receiveMsg, false);
+      window.postMessage('postmessage.test', '*');
+
+      // if 'hit' is true here, then postMessage is synchronous
+      if (hit) {
+        pmSync = true;
       }
-    
-      // for security, check origin against expected value
-      var origRelay = gadgets.rpc.getRelayUrl(rpc.f) ||
-                      gadgets.util.getUrlParameters()["parent"];
-      var origin = gadgets.rpc.getOrigin(origRelay);
-      if (!pmEventDomain ? packet.origin !== origin :
-                           packet.domain !== /^.+:\/\/([^:]+).*/.exec( origin )[1]) {
-        return;
+
+      gadgets.util.removeBrowserEvent(window, 'message', receiveMsg, false);
+    }
+
+    function onmessage(packet) {
+      var rpc = gadgets.json.parse(packet.data);
+      if (isForceSecure) {
+        if (!rpc || !rpc.f) {
+          return;
+        }
+
+        // for security, check origin against expected value
+        var origRelay = gadgets.rpc.getRelayUrl(rpc.f) ||
+            gadgets.util.getUrlParameters()['parent'];
+        var origin = gadgets.rpc.getOrigin(origRelay);
+        if (!pmEventDomain ? packet.origin !== origin :
+            packet.domain !== /^.+:\/\/([^:]+).*/.exec(origin)[1]) {
+          return;
+        }
       }
+      process(rpc);
     }
-    process(rpc);
-  }
 
-  return {
-    getCode: function() {
-      return 'wpm';
-    },
-
-    isParentVerifiable: function() {
-      return true;
-    },
-
-    init: function(processFn, readyFn) {
-      process = processFn;
-      ready = readyFn;
-
-      testPostMessage();
-      if (!pmSync) {
-        postMessage = function(win, msg, origin) {
-          win.postMessage(msg, origin);
-        };
-      } else {
-        postMessage = function(win, msg, origin) {
-          window.setTimeout( function() {
+    return {
+      getCode: function() {
+        return 'wpm';
+      },
+
+      isParentVerifiable: function() {
+        return true;
+      },
+
+      init: function(processFn, readyFn) {
+        process = processFn;
+        ready = readyFn;
+
+        testPostMessage();
+        if (!pmSync) {
+          postMessage = function(win, msg, origin) {
             win.postMessage(msg, origin);
-          }, 0);
-        };
-      }
- 
-      // Set up native postMessage handler.
-      gadgets.util.attachBrowserEvent(window, 'message', onmessage, false);
-
-      ready('..', true);  // Immediately ready to send to parent.
-      return true;
-    },
-
-    setup: function(receiverId, token, forceSecure) {
-      isForceSecure = forceSecure;
-      // If we're a gadget, send an ACK message to indicate to container
-      // that we're ready to receive messages.
-      if (receiverId === '..') {
-        if (isForceSecure) {
-          gadgets.rpc._createRelayIframe(token);
+          };
         } else {
-          gadgets.rpc.call(receiverId, gadgets.rpc.ACK);
+          postMessage = function(win, msg, origin) {
+            window.setTimeout(function() {
+              win.postMessage(msg, origin);
+            }, 0);
+          };
         }
-      }
-      return true;
-    },
 
-    call: function(targetId, from, rpc) {
-      var targetWin = gadgets.rpc._getTargetWin(targetId);
-      // targetOrigin = canonicalized relay URL
-      var origRelay = gadgets.rpc.getRelayUrl(targetId) ||
-                      gadgets.util.getUrlParameters()["parent"];
-      var origin = gadgets.rpc.getOrigin(origRelay);
-      if (origin) {
-        postMessage(targetWin, gadgets.json.stringify(rpc), origin);
-      } else {
-        gadgets.error("No relay set (used as window.postMessage targetOrigin)" +
-            ", cannot send cross-domain message");
-      }
-      return true;
-    },
+        // Set up native postMessage handler.
+        gadgets.util.attachBrowserEvent(window, 'message', onmessage, false);
 
-    relayOnload: function(receiverId, data) {
-      ready(receiverId, true);
-    }
-  };
-}();
+        ready('..', true);  // Immediately ready to send to parent.
+        return true;
+      },
+
+      setup: function(receiverId, token, forceSecure) {
+        isForceSecure = forceSecure;
+        // If we're a gadget, send an ACK message to indicate to container
+        // that we're ready to receive messages.
+        if (receiverId === '..') {
+          if (isForceSecure) {
+            gadgets.rpc._createRelayIframe(token);
+          } else {
+            gadgets.rpc.call(receiverId, gadgets.rpc.ACK);
+          }
+        }
+        return true;
+      },
+
+      call: function(targetId, from, rpc) {
+        var targetWin = gadgets.rpc._getTargetWin(targetId);
+        // targetOrigin = canonicalized relay URL
+        var origRelay = gadgets.rpc.getRelayUrl(targetId) ||
+            gadgets.util.getUrlParameters()['parent'];
+        var origin = gadgets.rpc.getOrigin(origRelay);
+        if (origin) {
+          postMessage(targetWin, gadgets.json.stringify(rpc), origin);
+        } else {
+          gadgets.error('No relay set (used as window.postMessage targetOrigin)' +
+              ', cannot send cross-domain message');
+        }
+        return true;
+      },
+
+      relayOnload: function(receiverId, data) {
+        ready(receiverId, true);
+      }
+    };
+  }();
 
 } // !end of double-inclusion guard

Modified: shindig/trunk/features/src/main/javascript/features/setprefs/setprefs.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/setprefs/setprefs.js?rev=997163&r1=997162&r2=997163&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/setprefs/setprefs.js (original)
+++ shindig/trunk/features/src/main/javascript/features/setprefs/setprefs.js Wed Sep 15 01:39:49 2010
@@ -50,10 +50,10 @@ gadgets.Prefs.prototype.set = function(k
 
   var args = [
     null, // go to parent
-    "set_pref", // service name
+    'set_pref', // service name
     null, // no callback
     gadgets.util.getUrlParameters().ifpctok ||
-      gadgets.util.getUrlParameters().rpctoken || 0 // Legacy IFPC "security".
+        gadgets.util.getUrlParameters().rpctoken || 0 // Legacy IFPC "security".
   ].concat(Array.prototype.slice.call(arguments));
 
   gadgets.rpc.call.apply(gadgets.rpc, args);
@@ -69,8 +69,8 @@ gadgets.Prefs.prototype.setArray = funct
   // We must escape pipe (|) characters to ensure that decoding in
   // getArray actually works properly.
   for (var i = 0, j = val.length; i < j; ++i) {
-    if (typeof val[i] !== "number") {
-      val[i] = val[i].replace(/\|/g, "%7C");
+    if (typeof val[i] !== 'number') {
+      val[i] = val[i].replace(/\|/g, '%7C');
     }
   }
   this.set(key, val.join('|'));

Modified: shindig/trunk/features/src/main/javascript/features/settitle/settitle.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/settitle/settitle.js?rev=997163&r1=997162&r2=997163&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/settitle/settitle.js (original)
+++ shindig/trunk/features/src/main/javascript/features/settitle/settitle.js Wed Sep 15 01:39:49 2010
@@ -31,7 +31,7 @@ gadgets.window = gadgets.window || {};
  * @scope gadgets.window
  */
 gadgets.window.setTitle = function(title) {
-  gadgets.rpc.call(null, "set_title", null, title);
+  gadgets.rpc.call(null, 'set_title', null, title);
 };
 
 // Alias for legacy code

Modified: shindig/trunk/features/src/main/javascript/features/settitle/taming.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/settitle/taming.js?rev=997163&r1=997162&r2=997163&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/settitle/taming.js (original)
+++ shindig/trunk/features/src/main/javascript/features/settitle/taming.js Wed Sep 15 01:39:49 2010
@@ -26,5 +26,5 @@ var tamings___ = tamings___ || [];
 tamings___.push(function(imports) {
   caja___.whitelistFuncs([
     [gadgets.window, 'setTitle']
-  ]);                   
+  ]);
 });

Modified: shindig/trunk/features/src/main/javascript/features/shindig.auth/auth.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/shindig.auth/auth.js?rev=997163&r1=997162&r2=997163&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/shindig.auth/auth.js (original)
+++ shindig/trunk/features/src/main/javascript/features/shindig.auth/auth.js Wed Sep 15 01:39:49 2010
@@ -133,9 +133,9 @@ shindig.Auth = function() {
     authToken = args.join('&');
   }
 
-  function init (configuration) {
+  function init(configuration) {
     var urlParams = gadgets.util.getUrlParameters();
-    var config = configuration["shindig.auth"] || {};
+    var config = configuration['shindig.auth'] || {};
 
     // Auth token - might be injected into the gadget directly, or might
     // be on the URL (hopefully on the fragment).
@@ -151,22 +151,22 @@ shindig.Auth = function() {
     // Trusted JSON.  We use eval directly because this was injected by the
     // container server and json parsing is slow in IE.
     if (config.trustedJson) {
-      trusted = eval("(" + config.trustedJson + ")");
+      trusted = eval('(' + config.trustedJson + ')');
     }
   }
 
-  gadgets.config.register("shindig.auth", null, init);
+  gadgets.config.register('shindig.auth', null, init);
 
   return /** @scope shindig.auth */ {
 
     /**
      * Gets the auth token.
      *
-     * @return {string} the gadget authentication token
+     * @return {string} the gadget authentication token.
      *
      * @member shindig.auth
      */
-    getSecurityToken : function() {
+    getSecurityToken: function() {
       return authToken;
     },
 
@@ -177,7 +177,7 @@ shindig.Auth = function() {
      *
      * @member shindig.auth
      */
-    updateSecurityToken : function(newToken) {
+    updateSecurityToken: function(newToken) {
       authToken = newToken;
     },
 
@@ -186,7 +186,7 @@ shindig.Auth = function() {
      * a trusted container server.
      * @return {Object}
      */
-    getTrustedData : function() {
+    getTrustedData: function() {
       return trusted;
     }
   };

Modified: shindig/trunk/features/src/main/javascript/features/shindig.container/cookies.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/shindig.container/cookies.js?rev=997163&r1=997162&r2=997163&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/shindig.container/cookies.js (original)
+++ shindig/trunk/features/src/main/javascript/features/shindig.container/cookies.js Wed Sep 15 01:39:49 2010
@@ -17,7 +17,7 @@
  */
 
 /**
- * @fileoverview Functions for setting, getting and deleting cookies
+ * @fileoverview Functions for setting, getting and deleting cookies.
  */
 
 /**
@@ -102,14 +102,14 @@ shindig.cookies.set = function(name, val
 
 /**
  * Returns the value for the first cookie with the given name
- * @param {string} name The name of the cookie to get
+ * @param {string} name The name of the cookie to get.
  * @param {string} opt_default If not found this is returned instead.
  * @return {string|undefined} The value of the cookie. If no cookie is set this
  *                            returns opt_default or undefined if opt_default is
  *                            not provided.
  */
 shindig.cookies.get = function(name, opt_default) {
-  var nameEq = name + "=";
+  var nameEq = name + '=';
   var cookie = String(document.cookie);
   for (var pos = -1; (pos = cookie.indexOf(nameEq, pos + 1)) >= 0;) {
     var i = pos;
@@ -157,7 +157,7 @@ shindig.cookies.remove = function(name, 
 /**
  * Gets the names and values for all the cookies
  * @private
- * @return {Object} An object with keys and values
+ * @return {Object} An object with keys and values.
  */
 shindig.cookies.getKeyValues_ = function() {
   var cookie = String(document.cookie);
@@ -180,7 +180,7 @@ shindig.cookies.getKeyValues_ = function
 
 /**
  * Gets the names for all the cookies
- * @return {Array} An array with the names of the cookies
+ * @return {Array} An array with the names of the cookies.
  */
 shindig.cookies.getKeys = function() {
   return shindig.cookies.getKeyValues_().keys;
@@ -189,7 +189,7 @@ shindig.cookies.getKeys = function() {
 
 /**
  * Gets the values for all the cookies
- * @return {Array} An array with the values of the cookies
+ * @return {Array} An array with the values of the cookies.
  */
 shindig.cookies.getValues = function() {
   return shindig.cookies.getKeyValues_().values;
@@ -221,7 +221,7 @@ shindig.cookies.getCount = function() {
 
 /**
  * Returns whether there is a cookie with the given name
- * @param {string} key The name of the cookie to test for
+ * @param {string} key The name of the cookie to test for.
  * @return {boolean}
  */
 shindig.cookies.containsKey = function(key) {
@@ -236,7 +236,7 @@ shindig.cookies.containsKey = function(k
 /**
  * Returns whether there is a cookie with the given value. (This is an O(n)
  * operation.)
- * @param {string} value The value to check for
+ * @param {string} value The value to check for.
  * @return {boolean}
  */
 shindig.cookies.containsValue = function(value) {
@@ -266,6 +266,6 @@ shindig.cookies.clear = function() {
  * to the size of a cookie. To make sure users can't break this limit, we
  * should truncate long cookies at 3950 bytes, to be extra careful with dumb
  * browsers/proxies that interpret 4K as 4000 rather than 4096
- * @type number
+ * @type {number}
  */
 shindig.cookies.MAX_COOKIE_LENGTH = 3950;

Modified: shindig/trunk/features/src/main/javascript/features/shindig.container/osapi.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/shindig.container/osapi.js?rev=997163&r1=997162&r2=997163&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/shindig.container/osapi.js (original)
+++ shindig/trunk/features/src/main/javascript/features/shindig.container/osapi.js Wed Sep 15 01:39:49 2010
@@ -17,7 +17,7 @@
  */
 
 /**
- * @fileoverview Base OSAPI binding
+ * @fileoverview Base OSAPI binding.
  */
 
 /**
@@ -43,8 +43,8 @@ if (gadgets && gadgets.rpc) { //Only def
       // Don't allow underscores in any part of the method name as a convention
       // for restricted methods
       var current = osapi;
-      if (requests[i].method.indexOf("_") == -1) {
-        var path = requests[i].method.split(".");
+      if (requests[i].method.indexOf('_') == -1) {
+        var path = requests[i].method.split('.');
         for (var j = 0; j < path.length; j++) {
           if (current.hasOwnProperty(path[j])) {
             current = current[path[j]];
@@ -63,7 +63,7 @@ if (gadgets && gadgets.rpc) { //Only def
       current(requests[i].params, function(i) {
         return function(response) {
           // Put back in json-rpc format
-          responses[i] = { id : requests[i].id, data : response};
+          responses[i] = { id: requests[i].id, data: response};
           callCount++;
           if (callCount == requests.length) {
             callback(responses);
@@ -80,9 +80,9 @@ if (gadgets && gadgets.rpc) { //Only def
    * @param callback
    */
   osapi.container = {};
-  osapi.container["listMethods"] = function(request, callback) {
+  osapi.container['listMethods'] = function(request, callback) {
     var names = [];
-    recurseNames(osapi, "", 5, names)
+    recurseNames(osapi, '', 5, names);
     callback(names);
   };
 
@@ -92,17 +92,17 @@ if (gadgets && gadgets.rpc) { //Only def
   function recurseNames(base, path, depth, accumulated) {
     if (depth == 0) return;
     for (var prop in base) if (base.hasOwnProperty(prop)) {
-      if (prop.indexOf("_") == -1) {
+      if (prop.indexOf('_') == -1) {
         var type = typeof(base[prop]);
-        if (type == "function") {
+        if (type == 'function') {
           accumulated.push(path + prop);
-        } else if (type == "object") {
-          recurseNames(base[prop], path + prop + ".", depth - 1, accumulated);
+        } else if (type == 'object') {
+          recurseNames(base[prop], path + prop + '.', depth - 1, accumulated);
         }
       }
     }
   }
 
   // Register the osapi RPC dispatcher.
-  gadgets.rpc.register("osapi._handleGadgetRpcMethod", osapi._handleGadgetRpcMethod);
+  gadgets.rpc.register('osapi._handleGadgetRpcMethod', osapi._handleGadgetRpcMethod);
 }