aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/messaging/portchannel.js
diff options
context:
space:
mode:
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/messaging/portchannel.js')
-rw-r--r--contexts/data/lib/closure-library/closure/goog/messaging/portchannel.js399
1 files changed, 0 insertions, 399 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/messaging/portchannel.js b/contexts/data/lib/closure-library/closure/goog/messaging/portchannel.js
deleted file mode 100644
index ae867cc..0000000
--- a/contexts/data/lib/closure-library/closure/goog/messaging/portchannel.js
+++ /dev/null
@@ -1,399 +0,0 @@
-// Copyright 2010 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 A class that wraps several types of HTML5 message-passing
- * entities ({@link MessagePort}s, {@link WebWorker}s, and {@link Window}s),
- * providing a unified interface.
- *
- * This is tested under Chrome, Safari, and Firefox. Since Firefox 3.6 has an
- * incomplete implementation of web workers, it doesn't support sending ports
- * over Window connections. IE has no web worker support at all, and so is
- * unsupported by this class.
- *
- */
-
-goog.provide('goog.messaging.PortChannel');
-
-goog.require('goog.Timer');
-goog.require('goog.array');
-goog.require('goog.async.Deferred');
-goog.require('goog.debug');
-goog.require('goog.debug.Logger');
-goog.require('goog.dom');
-goog.require('goog.dom.DomHelper');
-goog.require('goog.events');
-goog.require('goog.events.EventType');
-goog.require('goog.json');
-goog.require('goog.messaging.AbstractChannel');
-goog.require('goog.messaging.DeferredChannel');
-goog.require('goog.object');
-goog.require('goog.string');
-
-
-
-/**
- * A wrapper for several types of HTML5 message-passing entities
- * ({@link MessagePort}s and {@link WebWorker}s). This class implements the
- * {@link goog.messaging.MessageChannel} interface.
- *
- * This class can be used in conjunction with other communication on the port.
- * It sets {@link goog.messaging.PortChannel.FLAG} to true on all messages it
- * sends.
- *
- * @param {!MessagePort|!WebWorker} underlyingPort The message-passing
- * entity to wrap. If this is a {@link MessagePort}, it should be started.
- * The remote end should also be wrapped in a PortChannel. This will be
- * disposed along with the PortChannel; this means terminating it if it's a
- * worker or removing it from the DOM if it's an iframe.
- * @constructor
- * @extends {goog.messaging.AbstractChannel}
- */
-goog.messaging.PortChannel = function(underlyingPort) {
- goog.base(this);
-
- /**
- * The wrapped message-passing entity.
- * @type {!MessagePort|!WebWorker}
- * @private
- */
- this.port_ = underlyingPort;
-
- /**
- * The key for the event listener.
- * @type {?number}
- * @private
- */
- this.listenerKey_ = goog.events.listen(
- this.port_, goog.events.EventType.MESSAGE, this.deliver_, false, this);
-};
-goog.inherits(goog.messaging.PortChannel, goog.messaging.AbstractChannel);
-
-
-/**
- * Create a PortChannel that communicates with a window embedded in the current
- * page (e.g. an iframe contentWindow). The code within the window should call
- * {@link forGlobalWindow} to establish the connection.
- *
- * It's possible to use this channel in conjunction with other messages to the
- * embedded window. However, only one PortChannel should be used for a given
- * window at a time.
- *
- * @param {!Window} window The window object to communicate with.
- * @param {string} peerOrigin The expected origin of the window. See
- * http://dev.w3.org/html5/postmsg/#dom-window-postmessage.
- * @param {goog.Timer=} opt_timer The timer that regulates how often the initial
- * connection message is attempted. This will be automatically disposed once
- * the connection is established, or when the connection is cancelled.
- * @return {!goog.messaging.DeferredChannel} The PortChannel. Although this is
- * not actually an instance of the PortChannel class, it will behave like
- * one in that MessagePorts may be sent across it. The DeferredChannel may
- * be cancelled before a connection is established in order to abort the
- * attempt to make a connection.
- */
-goog.messaging.PortChannel.forEmbeddedWindow = function(
- window, peerOrigin, opt_timer) {
- var timer = opt_timer || new goog.Timer(50);
-
- var disposeTimer = goog.partial(goog.dispose, timer);
- var deferred = new goog.async.Deferred(disposeTimer);
- deferred.addBoth(disposeTimer);
-
- timer.start();
- // Every tick, attempt to set up a connection by sending in one end of an
- // HTML5 MessageChannel. If the inner window posts a response along a channel,
- // then we'll use that channel to create the PortChannel.
- //
- // As per http://dev.w3.org/html5/postmsg/#ports-and-garbage-collection, any
- // ports that are not ultimately used to set up the channel will be garbage
- // collected (since there are no references in this context, and the remote
- // context hasn't seen them).
- goog.events.listen(timer, goog.Timer.TICK, function() {
- var channel = new MessageChannel();
- var gotMessage = function(e) {
- channel.port1.removeEventListener(
- goog.events.EventType.MESSAGE, gotMessage, true);
- // If the connection has been cancelled, don't create the channel.
- if (!timer.isDisposed()) {
- deferred.callback(new goog.messaging.PortChannel(channel.port1));
- }
- };
- channel.port1.start();
- // Don't use goog.events because we don't want any lingering references to
- // the ports to prevent them from getting GCed. Only modern browsers support
- // these APIs anyway, so we don't need to worry about event API
- // compatibility.
- channel.port1.addEventListener(
- goog.events.EventType.MESSAGE, gotMessage, true);
-
- var msg = {};
- msg[goog.messaging.PortChannel.FLAG] = true;
- window.postMessage(msg, [channel.port2], peerOrigin);
- });
-
- return new goog.messaging.DeferredChannel(deferred);
-};
-
-
-/**
- * Create a PortChannel that communicates with the document in which this window
- * is embedded (e.g. within an iframe). The enclosing document should call
- * {@link forEmbeddedWindow} to establish the connection.
- *
- * It's possible to use this channel in conjunction with other messages posted
- * to the global window. However, only one PortChannel should be used for the
- * global window at a time.
- *
- * @param {string} peerOrigin The expected origin of the enclosing document. See
- * http://dev.w3.org/html5/postmsg/#dom-window-postmessage.
- * @return {!goog.messaging.MessageChannel} The PortChannel. Although this may
- * not actually be an instance of the PortChannel class, it will behave like
- * one in that MessagePorts may be sent across it.
- */
-goog.messaging.PortChannel.forGlobalWindow = function(peerOrigin) {
- var deferred = new goog.async.Deferred();
- // Wait for the external page to post a message containing the message port
- // which we'll use to set up the PortChannel. Ignore all other messages. Once
- // we receive the port, notify the other end and then set up the PortChannel.
- var key = goog.events.listen(
- window, goog.events.EventType.MESSAGE, function(e) {
- var browserEvent = e.getBrowserEvent();
- var data = browserEvent.data;
- if (!goog.isObject(data) || !data[goog.messaging.PortChannel.FLAG]) {
- return;
- }
-
- if (peerOrigin != '*' && peerOrigin != browserEvent.origin) {
- return;
- }
-
- var port = browserEvent.ports[0];
- // Notify the other end of the channel that we've received our port
- port.postMessage({});
-
- port.start();
- deferred.callback(new goog.messaging.PortChannel(port));
- goog.events.unlistenByKey(key);
- });
- return new goog.messaging.DeferredChannel(deferred);
-};
-
-
-/**
- * The flag added to messages that are sent by a PortChannel, and are meant to
- * be handled by one on the other side.
- * @type {string}
- */
-goog.messaging.PortChannel.FLAG = '--goog.messaging.PortChannel';
-
-
-/**
- * Whether the messages sent across the channel must be JSON-serialized. This is
- * required for older versions of Webkit, which can only send string messages.
- *
- * Although Safari and Chrome have separate implementations of message passing,
- * both of them support passing objects by Webkit 533.
- *
- * @type {boolean}
- * @private
- */
-goog.messaging.PortChannel.REQUIRES_SERIALIZATION_ = goog.userAgent.WEBKIT &&
- goog.string.compareVersions(goog.userAgent.VERSION, '533') < 0;
-
-
-/**
- * Logger for this class.
- * @type {goog.debug.Logger}
- * @protected
- * @override
- */
-goog.messaging.PortChannel.prototype.logger =
- goog.debug.Logger.getLogger('goog.messaging.PortChannel');
-
-
-/**
- * Sends a message over the channel.
- *
- * As an addition to the basic MessageChannel send API, PortChannels can send
- * objects that contain MessagePorts. Note that only plain Objects and Arrays,
- * not their subclasses, can contain MessagePorts.
- *
- * As per {@link http://www.w3.org/TR/html5/comms.html#clone-a-port}, once a
- * port is copied to be sent across a channel, the original port will cease
- * being able to send or receive messages.
- *
- * @override
- * @param {string} serviceName The name of the service this message should be
- * delivered to.
- * @param {string|!Object|!MessagePort} payload The value of the message. May
- * contain MessagePorts or be a MessagePort.
- */
-goog.messaging.PortChannel.prototype.send = function(serviceName, payload) {
- var ports = [];
- payload = this.extractPorts_(ports, payload);
- var message = {'serviceName': serviceName, 'payload': payload};
- message[goog.messaging.PortChannel.FLAG] = true;
-
- if (goog.messaging.PortChannel.REQUIRES_SERIALIZATION_) {
- message = goog.json.serialize(message);
- }
-
- this.port_.postMessage(message, ports);
-};
-
-
-/**
- * Delivers a message to the appropriate service handler. If this message isn't
- * a GearsWorkerChannel message, it's ignored and passed on to other handlers.
- *
- * @param {goog.events.Event} e The event.
- * @private
- */
-goog.messaging.PortChannel.prototype.deliver_ = function(e) {
- var browserEvent = e.getBrowserEvent();
- var data = browserEvent.data;
-
- if (goog.messaging.PortChannel.REQUIRES_SERIALIZATION_) {
- try {
- data = goog.json.parse(data);
- } catch (error) {
- // Ignore any non-JSON messages.
- return;
- }
- }
-
- if (!goog.isObject(data) || !data[goog.messaging.PortChannel.FLAG]) {
- return;
- }
-
- if (this.validateMessage_(data)) {
- var serviceName = data['serviceName'];
- var payload = data['payload'];
- var service = this.getService(serviceName, payload);
- if (!service) {
- return;
- }
-
- payload = this.decodePayload(
- serviceName,
- this.injectPorts_(browserEvent.ports || [], payload),
- service.objectPayload);
- if (goog.isDefAndNotNull(payload)) {
- service.callback(payload);
- }
- }
-};
-
-
-/**
- * Checks whether the message is invalid in some way.
- *
- * @param {Object} data The contents of the message.
- * @return {boolean} True if the message is valid, false otherwise.
- * @private
- */
-goog.messaging.PortChannel.prototype.validateMessage_ = function(data) {
- if (!('serviceName' in data)) {
- this.logger.warning('Message object doesn\'t contain service name: ' +
- goog.debug.deepExpose(data));
- return false;
- }
-
- if (!('payload' in data)) {
- this.logger.warning('Message object doesn\'t contain payload: ' +
- goog.debug.deepExpose(data));
- return false;
- }
-
- return true;
-};
-
-
-/**
- * Extracts all MessagePort objects from a message to be sent into an array.
- *
- * The message ports are replaced by placeholder objects that will be replaced
- * with the ports again on the other side of the channel.
- *
- * @param {Array.<MessagePort>} ports The array that will contain ports
- * extracted from the message. Will be destructively modified. Should be
- * empty initially.
- * @param {string|!Object} message The message from which ports will be
- * extracted.
- * @return {string|!Object} The message with ports extracted.
- * @private
- */
-goog.messaging.PortChannel.prototype.extractPorts_ = function(ports, message) {
- // Can't use instanceof here because MessagePort is undefined in workers
- if (message &&
- Object.prototype.toString.call(/** @type {!Object} */ (message)) ==
- '[object MessagePort]') {
- ports.push(message);
- return {'_port': {'type': 'real', 'index': ports.length - 1}};
- } else if (goog.isArray(message)) {
- return goog.array.map(message, goog.bind(this.extractPorts_, this, ports));
- // We want to compare the exact constructor here because we only want to
- // recurse into object literals, not native objects like Date.
- } else if (message && message.constructor == Object) {
- return goog.object.map(/** @type {Object} */ (message), function(val, key) {
- val = this.extractPorts_(ports, val);
- return key == '_port' ? {'type': 'escaped', 'val': val} : val;
- }, this);
- } else {
- return message;
- }
-};
-
-
-/**
- * Injects MessagePorts back into a message received from across the channel.
- *
- * @param {Array.<MessagePort>} ports The array of ports to be injected into the
- * message.
- * @param {string|!Object} message The message into which the ports will be
- * injected.
- * @return {string|!Object} The message with ports injected.
- * @private
- */
-goog.messaging.PortChannel.prototype.injectPorts_ = function(ports, message) {
- if (goog.isArray(message)) {
- return goog.array.map(message, goog.bind(this.injectPorts_, this, ports));
- } else if (message && message.constructor == Object) {
- message = /** @type {!Object} */ (message);
- if (message['_port'] && message['_port']['type'] == 'real') {
- return /** @type {!MessagePort} */ (ports[message['_port']['index']]);
- }
- return goog.object.map(message, function(val, key) {
- return this.injectPorts_(ports, key == '_port' ? val['val'] : val);
- }, this);
- } else {
- return message;
- }
-};
-
-
-/** @override */
-goog.messaging.PortChannel.prototype.disposeInternal = function() {
- goog.events.unlistenByKey(this.listenerKey_);
- // Can't use instanceof here because MessagePort is undefined in workers and
- // in Firefox
- if (Object.prototype.toString.call(this.port_) == '[object MessagePort]') {
- this.port_.close();
- // Worker is undefined in workers as well as of Chrome 9
- } else if (Object.prototype.toString.call(this.port_) == '[object Worker]') {
- this.port_.terminate();
- }
- delete this.port_;
- goog.base(this, 'disposeInternal');
-};