aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/net/xpc/iframepollingtransport.js
diff options
context:
space:
mode:
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/net/xpc/iframepollingtransport.js')
-rw-r--r--contexts/data/lib/closure-library/closure/goog/net/xpc/iframepollingtransport.js907
1 files changed, 0 insertions, 907 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/net/xpc/iframepollingtransport.js b/contexts/data/lib/closure-library/closure/goog/net/xpc/iframepollingtransport.js
deleted file mode 100644
index 9f52c44..0000000
--- a/contexts/data/lib/closure-library/closure/goog/net/xpc/iframepollingtransport.js
+++ /dev/null
@@ -1,907 +0,0 @@
-// Copyright 2007 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Contains the iframe polling transport.
- */
-
-
-goog.provide('goog.net.xpc.IframePollingTransport');
-goog.provide('goog.net.xpc.IframePollingTransport.Receiver');
-goog.provide('goog.net.xpc.IframePollingTransport.Sender');
-
-goog.require('goog.array');
-goog.require('goog.dom');
-goog.require('goog.net.xpc');
-goog.require('goog.net.xpc.CrossPageChannelRole');
-goog.require('goog.net.xpc.Transport');
-goog.require('goog.userAgent');
-
-
-
-/**
- * Iframe polling transport. Uses hidden iframes to transfer data
- * in the fragment identifier of the URL. The peer polls the iframe's location
- * for changes.
- * Unfortunately, in Safari this screws up the history, because Safari doesn't
- * allow to call location.replace() on a window containing a document from a
- * different domain (last version tested: 2.0.4).
- *
- * @param {goog.net.xpc.CrossPageChannel} channel The channel this
- * transport belongs to.
- * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for finding
- * the correct window.
- * @constructor
- * @extends {goog.net.xpc.Transport}
- */
-goog.net.xpc.IframePollingTransport = function(channel, opt_domHelper) {
- goog.base(this, opt_domHelper);
-
- /**
- * The channel this transport belongs to.
- * @type {goog.net.xpc.CrossPageChannel}
- * @private
- */
- this.channel_ = channel;
-
- /**
- * The URI used to send messages.
- * @type {string}
- * @private
- */
- this.sendUri_ =
- this.channel_.getConfig()[goog.net.xpc.CfgFields.PEER_POLL_URI];
-
- /**
- * The URI which is polled for incoming messages.
- * @type {string}
- * @private
- */
- this.rcvUri_ =
- this.channel_.getConfig()[goog.net.xpc.CfgFields.LOCAL_POLL_URI];
-
- /**
- * The queue to hold messages which can't be sent immediately.
- * @type {Array}
- * @private
- */
- this.sendQueue_ = [];
-};
-goog.inherits(goog.net.xpc.IframePollingTransport, goog.net.xpc.Transport);
-
-
-/**
- * The number of times the inner frame will check for evidence of the outer
- * frame before it tries its reconnection sequence. These occur at 100ms
- * intervals, making this an effective max waiting period of 500ms.
- * @type {number}
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.pollsBeforeReconnect_ = 5;
-
-
-/**
- * The transport type.
- * @type {number}
- * @protected
- * @override
- */
-goog.net.xpc.IframePollingTransport.prototype.transportType =
- goog.net.xpc.TransportTypes.IFRAME_POLLING;
-
-
-/**
- * Sequence counter.
- * @type {number}
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.sequence_ = 0;
-
-
-/**
- * Flag indicating whether we are waiting for an acknoledgement.
- * @type {boolean}
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.waitForAck_ = false;
-
-
-/**
- * Flag indicating if channel has been initialized.
- * @type {boolean}
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.initialized_ = false;
-
-
-/**
- * Reconnection iframe created by inner peer.
- * @type {Element}
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.reconnectFrame_ = null;
-
-
-/**
- * The string used to prefix all iframe names and IDs.
- * @type {string}
- */
-goog.net.xpc.IframePollingTransport.IFRAME_PREFIX = 'googlexpc';
-
-
-/**
- * Returns the name/ID of the message frame.
- * @return {string} Name of message frame.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.getMsgFrameName_ = function() {
- return goog.net.xpc.IframePollingTransport.IFRAME_PREFIX + '_' +
- this.channel_.name + '_msg';
-};
-
-
-/**
- * Returns the name/ID of the ack frame.
- * @return {string} Name of ack frame.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.getAckFrameName_ = function() {
- return goog.net.xpc.IframePollingTransport.IFRAME_PREFIX + '_' +
- this.channel_.name + '_ack';
-};
-
-
-/**
- * Determines whether the channel is still available. The channel is
- * unavailable if the transport was disposed or the peer is no longer
- * available.
- * @return {boolean} Whether the channel is available.
- */
-goog.net.xpc.IframePollingTransport.prototype.isChannelAvailable = function() {
- return !this.isDisposed() && this.channel_.isPeerAvailable();
-};
-
-
-/**
- * Safely retrieves the frames from the peer window. If an error is thrown
- * (e.g. the window is closing) an empty frame object is returned.
- * @return {!Object.<!Window>} The frames from the peer window.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.getPeerFrames_ = function() {
- try {
- if (this.isChannelAvailable()) {
- return this.channel_.getPeerWindowObject().frames || {};
- }
- } catch (e) {
- // An error may be thrown if the window is closing.
- goog.net.xpc.logger.fine('error retrieving peer frames');
- }
- return {};
-};
-
-
-/**
- * Safely retrieves the peer frame with the specified name.
- * @param {string} frameName The name of the peer frame to retrieve.
- * @return {Window} The peer frame with the specified name.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.getPeerFrame_ = function(
- frameName) {
- return this.getPeerFrames_()[frameName];
-};
-
-
-/**
- * Connects this transport.
- * @override
- */
-goog.net.xpc.IframePollingTransport.prototype.connect = function() {
- if (!this.isChannelAvailable()) {
- // When the channel is unavailable there is no peer to poll so stop trying
- // to connect.
- return;
- }
-
- goog.net.xpc.logger.fine('transport connect called');
- if (!this.initialized_) {
- goog.net.xpc.logger.fine('initializing...');
- this.constructSenderFrames_();
- this.initialized_ = true;
- }
- this.checkForeignFramesReady_();
-};
-
-
-/**
- * Creates the iframes which are used to send messages (and acknowledgements)
- * to the peer. Sender iframes contain a document from a different origin and
- * therefore their content can't be accessed.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.constructSenderFrames_ =
- function() {
- var name = this.getMsgFrameName_();
- this.msgIframeElm_ = this.constructSenderFrame_(name);
- this.msgWinObj_ = this.getWindow().frames[name];
-
- name = this.getAckFrameName_();
- this.ackIframeElm_ = this.constructSenderFrame_(name);
- this.ackWinObj_ = this.getWindow().frames[name];
-};
-
-
-/**
- * Constructs a sending frame the the given id.
- * @param {string} id The id.
- * @return {Element} The constructed frame.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.constructSenderFrame_ =
- function(id) {
- goog.net.xpc.logger.finest('constructing sender frame: ' + id);
- var ifr = goog.dom.createElement('iframe');
- var s = ifr.style;
- s.position = 'absolute';
- s.top = '-10px'; s.left = '10px'; s.width = '1px'; s.height = '1px';
- ifr.id = ifr.name = id;
- ifr.src = this.sendUri_ + '#INITIAL';
- this.getWindow().document.body.appendChild(ifr);
- return ifr;
-};
-
-
-/**
- * The protocol for reconnecting is for the inner frame to change channel
- * names, and then communicate the new channel name to the outer peer.
- * The outer peer looks in a predefined location for the channel name
- * upate. It is important to use a completely new channel name, as this
- * will ensure that all messaging iframes are not in the bfcache.
- * Otherwise, Safari may pollute the history when modifying the location
- * of bfcached iframes.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.maybeInnerPeerReconnect_ =
- function() {
- // Reconnection has been found to not function on some browsers (eg IE7), so
- // it's important that the mechanism only be triggered as a last resort. As
- // such, we poll a number of times to find the outer iframe before triggering
- // it.
- if (this.reconnectFrame_ || this.pollsBeforeReconnect_-- > 0) {
- return;
- }
-
- goog.net.xpc.logger.finest('Inner peer reconnect triggered.');
- this.channel_.name = goog.net.xpc.getRandomString(10);
- goog.net.xpc.logger.finest('switching channels: ' + this.channel_.name);
- this.deconstructSenderFrames_();
- this.initialized_ = false;
- // Communicate new channel name to outer peer.
- this.reconnectFrame_ = this.constructSenderFrame_(
- goog.net.xpc.IframePollingTransport.IFRAME_PREFIX +
- '_reconnect_' + this.channel_.name);
-};
-
-
-/**
- * Scans inner peer for a reconnect message, which will be used to update
- * the outer peer's channel name. If a reconnect message is found, the
- * sender frames will be cleaned up to make way for the new sender frames.
- * Only called by the outer peer.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.outerPeerReconnect_ = function() {
- goog.net.xpc.logger.finest('outerPeerReconnect called');
- var frames = this.getPeerFrames_();
- var length = frames.length;
- for (var i = 0; i < length; i++) {
- var frameName;
- try {
- if (frames[i] && frames[i].name) {
- frameName = frames[i].name;
- }
- } catch (e) {
- // Do nothing.
- }
- if (!frameName) {
- continue;
- }
- var message = frameName.split('_');
- if (message.length == 3 &&
- message[0] == goog.net.xpc.IframePollingTransport.IFRAME_PREFIX &&
- message[1] == 'reconnect') {
- // This is a legitimate reconnect message from the peer. Start using
- // the peer provided channel name, and start a connection over from
- // scratch.
- this.channel_.name = message[2];
- this.deconstructSenderFrames_();
- this.initialized_ = false;
- break;
- }
- }
-};
-
-
-/**
- * Cleans up the existing sender frames owned by this peer. Only called by
- * the outer peer.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.deconstructSenderFrames_ =
- function() {
- goog.net.xpc.logger.finest('deconstructSenderFrames called');
- if (this.msgIframeElm_) {
- this.msgIframeElm_.parentNode.removeChild(this.msgIframeElm_);
- this.msgIframeElm_ = null;
- this.msgWinObj_ = null;
- }
- if (this.ackIframeElm_) {
- this.ackIframeElm_.parentNode.removeChild(this.ackIframeElm_);
- this.ackIframeElm_ = null;
- this.ackWinObj_ = null;
- }
-};
-
-
-/**
- * Checks if the frames in the peer's page are ready. These contain a
- * document from the own domain and are the ones messages are received through.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.checkForeignFramesReady_ =
- function() {
- // check if the connected iframe ready
- if (!(this.isRcvFrameReady_(this.getMsgFrameName_()) &&
- this.isRcvFrameReady_(this.getAckFrameName_()))) {
- goog.net.xpc.logger.finest('foreign frames not (yet) present');
-
- if (this.channel_.getRole() == goog.net.xpc.CrossPageChannelRole.INNER) {
- // The outer peer might need a short time to get its frames ready, as
- // CrossPageChannel prevents them from getting created until the inner
- // peer's frame has thrown its loaded event. This method is a noop for
- // the first few times it's called, and then allows the reconnection
- // sequence to begin.
- this.maybeInnerPeerReconnect_();
- } else if (this.channel_.getRole() ==
- goog.net.xpc.CrossPageChannelRole.OUTER) {
- // The inner peer is either not loaded yet, or the receiving
- // frames are simply missing. Since we cannot discern the two cases, we
- // should scan for a reconnect message from the inner peer.
- this.outerPeerReconnect_();
- }
-
- // start a timer to check again
- this.getWindow().setTimeout(goog.bind(this.connect, this), 100);
- } else {
- goog.net.xpc.logger.fine('foreign frames present');
-
- // Create receivers.
- this.msgReceiver_ = new goog.net.xpc.IframePollingTransport.Receiver(
- this,
- this.getPeerFrame_(this.getMsgFrameName_()),
- goog.bind(this.processIncomingMsg, this));
- this.ackReceiver_ = new goog.net.xpc.IframePollingTransport.Receiver(
- this,
- this.getPeerFrame_(this.getAckFrameName_()),
- goog.bind(this.processIncomingAck, this));
-
- this.checkLocalFramesPresent_();
- }
-};
-
-
-/**
- * Checks if the receiving frame is ready.
- * @param {string} frameName Which receiving frame to check.
- * @return {boolean} Whether the receiving frame is ready.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.isRcvFrameReady_ =
- function(frameName) {
- goog.net.xpc.logger.finest('checking for receive frame: ' + frameName);
- /** @preserveTry */
- try {
- var winObj = this.getPeerFrame_(frameName);
- if (!winObj || winObj.location.href.indexOf(this.rcvUri_) != 0) {
- return false;
- }
- } catch (e) {
- return false;
- }
- return true;
-};
-
-
-/**
- * Checks if the iframes created in the own document are ready.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.checkLocalFramesPresent_ =
- function() {
-
- // Are the sender frames ready?
- // These contain a document from the peer's domain, therefore we can only
- // check if the frame itself is present.
- var frames = this.getPeerFrames_();
- if (!(frames[this.getAckFrameName_()] &&
- frames[this.getMsgFrameName_()])) {
- // start a timer to check again
- if (!this.checkLocalFramesPresentCb_) {
- this.checkLocalFramesPresentCb_ = goog.bind(
- this.checkLocalFramesPresent_, this);
- }
- this.getWindow().setTimeout(this.checkLocalFramesPresentCb_, 100);
- goog.net.xpc.logger.fine('local frames not (yet) present');
- } else {
- // Create senders.
- this.msgSender_ = new goog.net.xpc.IframePollingTransport.Sender(
- this.sendUri_, this.msgWinObj_);
- this.ackSender_ = new goog.net.xpc.IframePollingTransport.Sender(
- this.sendUri_, this.ackWinObj_);
-
- goog.net.xpc.logger.fine('local frames ready');
-
- this.getWindow().setTimeout(goog.bind(function() {
- this.msgSender_.send(goog.net.xpc.SETUP);
- this.sentConnectionSetup_ = true;
- this.waitForAck_ = true;
- goog.net.xpc.logger.fine('SETUP sent');
- }, this), 100);
- }
-};
-
-
-/**
- * Check if connection is ready.
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.checkIfConnected_ = function() {
- if (this.sentConnectionSetupAck_ && this.rcvdConnectionSetupAck_) {
- this.channel_.notifyConnected();
-
- if (this.deliveryQueue_) {
- goog.net.xpc.logger.fine('delivering queued messages ' +
- '(' + this.deliveryQueue_.length + ')');
-
- for (var i = 0, m; i < this.deliveryQueue_.length; i++) {
- m = this.deliveryQueue_[i];
- this.channel_.xpcDeliver(m.service, m.payload);
- }
- delete this.deliveryQueue_;
- }
- } else {
- goog.net.xpc.logger.finest('checking if connected: ' +
- 'ack sent:' + this.sentConnectionSetupAck_ +
- ', ack rcvd: ' + this.rcvdConnectionSetupAck_);
- }
-};
-
-
-/**
- * Processes an incoming message.
- * @param {string} raw The complete received string.
- */
-goog.net.xpc.IframePollingTransport.prototype.processIncomingMsg =
- function(raw) {
- goog.net.xpc.logger.finest('msg received: ' + raw);
-
- if (raw == goog.net.xpc.SETUP) {
- if (!this.ackSender_) {
- // Got SETUP msg, but we can't send an ack.
- return;
- }
-
- this.ackSender_.send(goog.net.xpc.SETUP_ACK_);
- goog.net.xpc.logger.finest('SETUP_ACK sent');
-
- this.sentConnectionSetupAck_ = true;
- this.checkIfConnected_();
-
- } else if (this.channel_.isConnected() || this.sentConnectionSetupAck_) {
-
- var pos = raw.indexOf('|');
- var head = raw.substring(0, pos);
- var frame = raw.substring(pos + 1);
-
- // check if it is a framed message
- pos = head.indexOf(',');
- if (pos == -1) {
- var seq = head;
- // send acknowledgement
- this.ackSender_.send('ACK:' + seq);
- this.deliverPayload_(frame);
- } else {
- var seq = head.substring(0, pos);
- // send acknowledgement
- this.ackSender_.send('ACK:' + seq);
-
- var partInfo = head.substring(pos + 1).split('/');
- var part0 = parseInt(partInfo[0], 10);
- var part1 = parseInt(partInfo[1], 10);
- // create an array to accumulate the parts if this is the
- // first frame of a message
- if (part0 == 1) {
- this.parts_ = [];
- }
- this.parts_.push(frame);
- // deliver the message if this was the last frame of a message
- if (part0 == part1) {
- this.deliverPayload_(this.parts_.join(''));
- delete this.parts_;
- }
- }
- } else {
- goog.net.xpc.logger.warning('received msg, but channel is not connected');
- }
-};
-
-
-/**
- * Process an incoming acknowdedgement.
- * @param {string} msgStr The incoming ack string to process.
- */
-goog.net.xpc.IframePollingTransport.prototype.processIncomingAck =
- function(msgStr) {
- goog.net.xpc.logger.finest('ack received: ' + msgStr);
-
- if (msgStr == goog.net.xpc.SETUP_ACK_) {
- this.waitForAck_ = false;
- this.rcvdConnectionSetupAck_ = true;
- // send the next frame
- this.checkIfConnected_();
-
- } else if (this.channel_.isConnected()) {
- if (!this.waitForAck_) {
- goog.net.xpc.logger.warning('got unexpected ack');
- return;
- }
-
- var seq = parseInt(msgStr.split(':')[1], 10);
- if (seq == this.sequence_) {
- this.waitForAck_ = false;
- this.sendNextFrame_();
- } else {
- goog.net.xpc.logger.warning('got ack with wrong sequence');
- }
- } else {
- goog.net.xpc.logger.warning('received ack, but channel not connected');
- }
-};
-
-
-/**
- * Sends a frame (message part).
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.sendNextFrame_ = function() {
- // do nothing if we are waiting for an acknowledgement or the
- // queue is emtpy
- if (this.waitForAck_ || !this.sendQueue_.length) {
- return;
- }
-
- var s = this.sendQueue_.shift();
- ++this.sequence_;
- this.msgSender_.send(this.sequence_ + s);
- goog.net.xpc.logger.finest('msg sent: ' + this.sequence_ + s);
-
-
- this.waitForAck_ = true;
-};
-
-
-/**
- * Delivers a message.
- * @param {string} s The complete message string ("<service_name>:<payload>").
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.deliverPayload_ = function(s) {
- // determine the service name and the payload
- var pos = s.indexOf(':');
- var service = s.substr(0, pos);
- var payload = s.substring(pos + 1);
-
- // deliver the message
- if (!this.channel_.isConnected()) {
- // as valid messages can come in before a SETUP_ACK has
- // been received (because subchannels for msgs and acks are independent),
- // delay delivery of early messages until after 'connect'-event
- (this.deliveryQueue_ || (this.deliveryQueue_ = [])).
- push({service: service, payload: payload});
- goog.net.xpc.logger.finest('queued delivery');
- } else {
- this.channel_.xpcDeliver(service, payload);
- }
-};
-
-
-// ---- send message ----
-
-
-/**
- * Maximal frame length.
- * @type {number}
- * @private
- */
-goog.net.xpc.IframePollingTransport.prototype.MAX_FRAME_LENGTH_ = 3800;
-
-
-/**
- * Sends a message. Splits it in multiple frames if too long (exceeds IE's
- * URL-length maximum.
- * Wireformat: <seq>[,<frame_no>/<#frames>]|<frame_content>
- *
- * @param {string} service Name of service this the message has to be delivered.
- * @param {string} payload The message content.
- * @override
- */
-goog.net.xpc.IframePollingTransport.prototype.send =
- function(service, payload) {
- var frame = service + ':' + payload;
- // put in queue
- if (!goog.userAgent.IE || payload.length <= this.MAX_FRAME_LENGTH_) {
- this.sendQueue_.push('|' + frame);
- }
- else {
- var l = payload.length;
- var num = Math.ceil(l / this.MAX_FRAME_LENGTH_); // number of frames
- var pos = 0;
- var i = 1;
- while (pos < l) {
- this.sendQueue_.push(',' + i + '/' + num + '|' +
- frame.substr(pos, this.MAX_FRAME_LENGTH_));
- i++;
- pos += this.MAX_FRAME_LENGTH_;
- }
- }
- this.sendNextFrame_();
-};
-
-
-/** @override */
-goog.net.xpc.IframePollingTransport.prototype.disposeInternal = function() {
- goog.base(this, 'disposeInternal');
-
- var receivers = goog.net.xpc.IframePollingTransport.receivers_;
- goog.array.remove(receivers, this.msgReceiver_);
- goog.array.remove(receivers, this.ackReceiver_);
- this.msgReceiver_ = this.ackReceiver_ = null;
-
- goog.dom.removeNode(this.msgIframeElm_);
- goog.dom.removeNode(this.ackIframeElm_);
- this.msgIframeElm_ = this.ackIframeElm_ = null;
- this.msgWinObj_ = this.ackWinObj_ = null;
-};
-
-
-/**
- * Array holding all Receiver-instances.
- * @type {Array.<goog.net.xpc.IframePollingTransport.Receiver>}
- * @private
- */
-goog.net.xpc.IframePollingTransport.receivers_ = [];
-
-
-/**
- * Short polling interval.
- * @type {number}
- * @private
- */
-goog.net.xpc.IframePollingTransport.TIME_POLL_SHORT_ = 10;
-
-
-/**
- * Long polling interval.
- * @type {number}
- * @private
- */
-goog.net.xpc.IframePollingTransport.TIME_POLL_LONG_ = 100;
-
-
-/**
- * Period how long to use TIME_POLL_SHORT_ before raising polling-interval
- * to TIME_POLL_LONG_ after an activity.
- * @type {number}
- * @private
- */
-goog.net.xpc.IframePollingTransport.TIME_SHORT_POLL_AFTER_ACTIVITY_ =
- 1000;
-
-
-/**
- * Polls all receivers.
- * @private
- */
-goog.net.xpc.IframePollingTransport.receive_ = function() {
- var receivers = goog.net.xpc.IframePollingTransport.receivers_;
- var receiver;
- var rcvd = false;
-
- /** @preserveTry */
- try {
- for (var i = 0; receiver = receivers[i]; i++) {
- rcvd = rcvd || receiver.receive();
- }
- } catch (e) {
- goog.net.xpc.logger.info('receive_() failed: ' + e);
-
- // Notify the channel that the transport had an error.
- receiver.transport_.channel_.notifyTransportError();
-
- // notifyTransportError() closes the channel and disposes the transport.
- // If there are no other channels present, this.receivers_ will now be empty
- // and there is no need to keep polling.
- if (!receivers.length) {
- return;
- }
- }
-
- var now = goog.now();
- if (rcvd) {
- goog.net.xpc.IframePollingTransport.lastActivity_ = now;
- }
-
- // Schedule next check.
- var t = now - goog.net.xpc.IframePollingTransport.lastActivity_ <
- goog.net.xpc.IframePollingTransport.TIME_SHORT_POLL_AFTER_ACTIVITY_ ?
- goog.net.xpc.IframePollingTransport.TIME_POLL_SHORT_ :
- goog.net.xpc.IframePollingTransport.TIME_POLL_LONG_;
- goog.net.xpc.IframePollingTransport.rcvTimer_ = window.setTimeout(
- goog.net.xpc.IframePollingTransport.receiveCb_, t);
-};
-
-
-/**
- * Callback that wraps receive_ to be used in timers.
- * @type {Function}
- * @private
- */
-goog.net.xpc.IframePollingTransport.receiveCb_ = goog.bind(
- goog.net.xpc.IframePollingTransport.receive_,
- goog.net.xpc.IframePollingTransport);
-
-
-/**
- * Starts the polling loop.
- * @private
- */
-goog.net.xpc.IframePollingTransport.startRcvTimer_ = function() {
- goog.net.xpc.logger.fine('starting receive-timer');
- goog.net.xpc.IframePollingTransport.lastActivity_ = goog.now();
- if (goog.net.xpc.IframePollingTransport.rcvTimer_) {
- window.clearTimeout(goog.net.xpc.IframePollingTransport.rcvTimer_);
- }
- goog.net.xpc.IframePollingTransport.rcvTimer_ = window.setTimeout(
- goog.net.xpc.IframePollingTransport.receiveCb_,
- goog.net.xpc.IframePollingTransport.TIME_POLL_SHORT_);
-};
-
-
-
-/**
- * goog.net.xpc.IframePollingTransport.Sender
- *
- * Utility class to send message-parts to a document from a different origin.
- *
- * @constructor
- * @param {string} url The url the other document will use for polling.
- * @param {Object} windowObj The frame used for sending information to.
- */
-goog.net.xpc.IframePollingTransport.Sender = function(url, windowObj) {
- /**
- * The URI used to sending messages.
- * @type {string}
- * @private
- */
- this.sendUri_ = url;
-
- /**
- * The window object of the iframe used to send messages.
- * The script instantiating the Sender won't have access to
- * the content of sendFrame_.
- * @type {Object}
- * @private
- */
- this.sendFrame_ = windowObj;
-
- /**
- * Cycle counter (used to make sure that sending two identical messages sent
- * in direct succession can be recognized as such by the receiver).
- * @type {number}
- * @private
- */
- this.cycle_ = 0;
-};
-
-
-/**
- * Sends a message-part (frame) to the peer.
- * The message-part is encoded and put in the fragment identifier
- * of the URL used for sending (and belongs to the origin/domain of the peer).
- * @param {string} payload The message to send.
- */
-goog.net.xpc.IframePollingTransport.Sender.prototype.send = function(payload) {
- this.cycle_ = ++this.cycle_ % 2;
-
- var url = this.sendUri_ + '#' + this.cycle_ + encodeURIComponent(payload);
-
- // TODO(user) Find out if try/catch is still needed
- /** @preserveTry */
- try {
- // safari doesn't allow to call location.replace()
- if (goog.userAgent.WEBKIT) {
- this.sendFrame_.location.href = url;
- } else {
- this.sendFrame_.location.replace(url);
- }
- } catch (e) {
- goog.net.xpc.logger.severe('sending failed', e);
- }
-
- // Restart receiver timer on short polling interval, to support use-cases
- // where we need to capture responses quickly.
- goog.net.xpc.IframePollingTransport.startRcvTimer_();
-};
-
-
-
-/**
- * goog.net.xpc.IframePollingTransport.Receiver
- *
- * @constructor
- * @param {goog.net.xpc.IframePollingTransport} transport The transport to
- * receive from.
- * @param {Object} windowObj The window-object to poll for location-changes.
- * @param {Function} callback The callback-function to be called when
- * location has changed.
- */
-goog.net.xpc.IframePollingTransport.Receiver = function(transport,
- windowObj,
- callback) {
- /**
- * The transport to receive from.
- * @type {goog.net.xpc.IframePollingTransport}
- * @private
- */
- this.transport_ = transport;
- this.rcvFrame_ = windowObj;
-
- this.cb_ = callback;
- this.currentLoc_ = this.rcvFrame_.location.href.split('#')[0] + '#INITIAL';
-
- goog.net.xpc.IframePollingTransport.receivers_.push(this);
- goog.net.xpc.IframePollingTransport.startRcvTimer_();
-};
-
-
-/**
- * Polls the location of the receiver-frame for changes.
- * @return {boolean} Whether a change has been detected.
- */
-goog.net.xpc.IframePollingTransport.Receiver.prototype.receive = function() {
- var loc = this.rcvFrame_.location.href;
-
- if (loc != this.currentLoc_) {
- this.currentLoc_ = loc;
- var payload = loc.split('#')[1];
- if (payload) {
- payload = payload.substr(1); // discard first character (cycle)
- this.cb_(decodeURIComponent(payload));
- }
- return true;
- } else {
- return false;
- }
-};