Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,635 @@
|
||||
// Copyright 2013 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 Provides an implementation of a transport that can call methods
|
||||
* directly on a frame. Useful if you want to use XPC for crossdomain messaging
|
||||
* (using another transport), or same domain messaging (using this transport).
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.net.xpc.DirectTransport');
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.events.EventHandler');
|
||||
goog.require('goog.log');
|
||||
goog.require('goog.net.xpc');
|
||||
goog.require('goog.net.xpc.CfgFields');
|
||||
goog.require('goog.net.xpc.CrossPageChannelRole');
|
||||
goog.require('goog.net.xpc.Transport');
|
||||
goog.require('goog.net.xpc.TransportTypes');
|
||||
goog.require('goog.object');
|
||||
|
||||
|
||||
goog.scope(function() {
|
||||
var CfgFields = goog.net.xpc.CfgFields;
|
||||
var CrossPageChannelRole = goog.net.xpc.CrossPageChannelRole;
|
||||
var Deferred = goog.async.Deferred;
|
||||
var EventHandler = goog.events.EventHandler;
|
||||
var Timer = goog.Timer;
|
||||
var Transport = goog.net.xpc.Transport;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A direct window to window method transport.
|
||||
*
|
||||
* If the windows are in the same security context, this transport calls
|
||||
* directly into the other window without using any additional mechanism. This
|
||||
* is mainly used in scenarios where you want to optionally use a cross domain
|
||||
* transport in cross security context situations, or optionally use a direct
|
||||
* transport in same security context situations.
|
||||
*
|
||||
* Note: Global properties are exported by using this transport. One to
|
||||
* communicate with the other window by, currently crosswindowmessaging.channel,
|
||||
* and by using goog.getUid on window, currently closure_uid_[0-9]+.
|
||||
*
|
||||
* @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/document. If omitted, uses the current
|
||||
* document.
|
||||
* @constructor
|
||||
* @extends {Transport}
|
||||
*/
|
||||
goog.net.xpc.DirectTransport = function(channel, opt_domHelper) {
|
||||
goog.net.xpc.DirectTransport.base(this, 'constructor', opt_domHelper);
|
||||
|
||||
/**
|
||||
* The channel this transport belongs to.
|
||||
* @private {!goog.net.xpc.CrossPageChannel}
|
||||
*/
|
||||
this.channel_ = channel;
|
||||
|
||||
/** @private {!EventHandler<!goog.net.xpc.DirectTransport>} */
|
||||
this.eventHandler_ = new EventHandler(this);
|
||||
this.registerDisposable(this.eventHandler_);
|
||||
|
||||
/**
|
||||
* Timer for connection reattempts.
|
||||
* @private {!Timer}
|
||||
*/
|
||||
this.maybeAttemptToConnectTimer_ = new Timer(
|
||||
DirectTransport.CONNECTION_ATTEMPT_INTERVAL_MS_,
|
||||
this.getWindow());
|
||||
this.registerDisposable(this.maybeAttemptToConnectTimer_);
|
||||
|
||||
/**
|
||||
* Fires once we've received our SETUP_ACK message.
|
||||
* @private {!Deferred}
|
||||
*/
|
||||
this.setupAckReceived_ = new Deferred();
|
||||
|
||||
/**
|
||||
* Fires once we've sent our SETUP_ACK message.
|
||||
* @private {!Deferred}
|
||||
*/
|
||||
this.setupAckSent_ = new Deferred();
|
||||
|
||||
/**
|
||||
* Fires once we're marked connected.
|
||||
* @private {!Deferred}
|
||||
*/
|
||||
this.connected_ = new Deferred();
|
||||
|
||||
/**
|
||||
* The unique ID of this side of the connection. Used to determine when a peer
|
||||
* is reloaded.
|
||||
* @private {string}
|
||||
*/
|
||||
this.endpointId_ = goog.net.xpc.getRandomString(10);
|
||||
|
||||
/**
|
||||
* The unique ID of the peer. If we get a message from a peer with an ID we
|
||||
* don't expect, we reset the connection.
|
||||
* @private {?string}
|
||||
*/
|
||||
this.peerEndpointId_ = null;
|
||||
|
||||
/**
|
||||
* The map of sending messages.
|
||||
* @private {Object}
|
||||
*/
|
||||
this.asyncSendsMap_ = {};
|
||||
|
||||
/**
|
||||
* The original channel name.
|
||||
* @private {string}
|
||||
*/
|
||||
this.originalChannelName_ = this.channel_.name;
|
||||
|
||||
// We reconfigure the channel name to include the role so that we can
|
||||
// communicate in the same window between the different roles on the
|
||||
// same channel.
|
||||
this.channel_.updateChannelNameAndCatalog(
|
||||
DirectTransport.getRoledChannelName_(this.channel_.name,
|
||||
this.channel_.getRole()));
|
||||
|
||||
/**
|
||||
* Flag indicating if this instance of the transport has been initialized.
|
||||
* @private {boolean}
|
||||
*/
|
||||
this.initialized_ = false;
|
||||
|
||||
// We don't want to mark ourselves connected until we have sent whatever
|
||||
// message will cause our counterpart in the other frame to also declare
|
||||
// itself connected, if there is such a message. Otherwise we risk a user
|
||||
// message being sent in advance of that message, and it being discarded.
|
||||
|
||||
// Two sided handshake:
|
||||
// SETUP_ACK has to have been received, and sent.
|
||||
this.connected_.awaitDeferred(this.setupAckReceived_);
|
||||
this.connected_.awaitDeferred(this.setupAckSent_);
|
||||
|
||||
this.connected_.addCallback(this.notifyConnected_, this);
|
||||
this.connected_.callback(true);
|
||||
|
||||
this.eventHandler_.
|
||||
listen(this.maybeAttemptToConnectTimer_, Timer.TICK,
|
||||
this.maybeAttemptToConnect_);
|
||||
|
||||
goog.log.info(
|
||||
goog.net.xpc.logger,
|
||||
'DirectTransport created. role=' + this.channel_.getRole());
|
||||
};
|
||||
goog.inherits(goog.net.xpc.DirectTransport, Transport);
|
||||
var DirectTransport = goog.net.xpc.DirectTransport;
|
||||
|
||||
|
||||
/**
|
||||
* @private {number}
|
||||
* @const
|
||||
*/
|
||||
DirectTransport.CONNECTION_ATTEMPT_INTERVAL_MS_ = 100;
|
||||
|
||||
|
||||
/**
|
||||
* The delay to notify the xpc of a successful connection. This is used
|
||||
* to allow both parties to be connected if one party's connection callback
|
||||
* invokes an immediate send.
|
||||
* @private {number}
|
||||
* @const
|
||||
*/
|
||||
DirectTransport.CONNECTION_DELAY_INTERVAL_MS_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Window} peerWindow The peer window to check if DirectTranport is
|
||||
* supported on.
|
||||
* @return {boolean} Whether this transport is supported.
|
||||
*/
|
||||
DirectTransport.isSupported = function(peerWindow) {
|
||||
/** @preserveTry */
|
||||
try {
|
||||
return window.document.domain == peerWindow.document.domain;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tracks the number of DirectTransport channels that have been
|
||||
* initialized but not disposed yet in a map keyed by the UID of the window
|
||||
* object. This allows for multiple windows to be initiallized and listening
|
||||
* for messages.
|
||||
* @private {!Object<number>}
|
||||
*/
|
||||
DirectTransport.activeCount_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* Path of global message proxy.
|
||||
* @private {string}
|
||||
* @const
|
||||
*/
|
||||
// TODO(user): Make this configurable using the CfgFields.
|
||||
DirectTransport.GLOBAL_TRANPORT_PATH_ = 'crosswindowmessaging.channel';
|
||||
|
||||
|
||||
/**
|
||||
* The delimiter used for transport service messages.
|
||||
* @private {string}
|
||||
* @const
|
||||
*/
|
||||
DirectTransport.MESSAGE_DELIMITER_ = ',';
|
||||
|
||||
|
||||
/**
|
||||
* Initializes this transport. Registers a method for 'message'-events in the
|
||||
* global scope.
|
||||
* @param {!Window} listenWindow The window to listen to events on.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.initialize_ = function(listenWindow) {
|
||||
var uid = goog.getUid(listenWindow);
|
||||
var value = DirectTransport.activeCount_[uid] || 0;
|
||||
if (value == 0) {
|
||||
// Set up a handler on the window to proxy messages to class.
|
||||
var globalProxy = goog.getObjectByName(
|
||||
DirectTransport.GLOBAL_TRANPORT_PATH_,
|
||||
listenWindow);
|
||||
if (globalProxy == null) {
|
||||
goog.exportSymbol(
|
||||
DirectTransport.GLOBAL_TRANPORT_PATH_,
|
||||
DirectTransport.messageReceivedHandler_,
|
||||
listenWindow);
|
||||
}
|
||||
}
|
||||
DirectTransport.activeCount_[uid]++;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} channelName The channel name.
|
||||
* @param {string|number} role The role.
|
||||
* @return {string} The formatted channel name including role.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.getRoledChannelName_ = function(channelName, role) {
|
||||
return channelName + '_' + role;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Object} literal The literal unrenamed message.
|
||||
* @return {boolean} Whether the message was successfully delivered to a
|
||||
* channel.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.messageReceivedHandler_ = function(literal) {
|
||||
var msg = DirectTransport.Message_.fromLiteral(literal);
|
||||
|
||||
var channelName = msg.channelName;
|
||||
var service = msg.service;
|
||||
var payload = msg.payload;
|
||||
|
||||
goog.log.fine(goog.net.xpc.logger,
|
||||
'messageReceived: channel=' + channelName +
|
||||
', service=' + service + ', payload=' + payload);
|
||||
|
||||
// Attempt to deliver message to the channel. Keep in mind that it may not
|
||||
// exist for several reasons, including but not limited to:
|
||||
// - a malformed message
|
||||
// - the channel simply has not been created
|
||||
// - channel was created in a different namespace
|
||||
// - message was sent to the wrong window
|
||||
// - channel has become stale (e.g. caching iframes and back clicks)
|
||||
var channel = goog.net.xpc.channels[channelName];
|
||||
if (channel) {
|
||||
channel.xpcDeliver(service, payload);
|
||||
return true;
|
||||
}
|
||||
|
||||
var transportMessageType = DirectTransport.parseTransportPayload_(payload)[0];
|
||||
|
||||
// Check if there are any stale channel names that can be updated.
|
||||
for (var staleChannelName in goog.net.xpc.channels) {
|
||||
var staleChannel = goog.net.xpc.channels[staleChannelName];
|
||||
if (staleChannel.getRole() == CrossPageChannelRole.INNER &&
|
||||
!staleChannel.isConnected() &&
|
||||
service == goog.net.xpc.TRANSPORT_SERVICE_ &&
|
||||
transportMessageType == goog.net.xpc.SETUP) {
|
||||
// Inner peer received SETUP message but channel names did not match.
|
||||
// Start using the channel name sent from outer peer. The channel name
|
||||
// of the inner peer can easily become out of date, as iframe's and their
|
||||
// JS state get cached in many browsers upon page reload or history
|
||||
// navigation (particularly Firefox 1.5+).
|
||||
staleChannel.updateChannelNameAndCatalog(channelName);
|
||||
staleChannel.xpcDeliver(service, payload);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to find a channel to deliver this message to, so simply ignore it.
|
||||
goog.log.info(goog.net.xpc.logger, 'channel name mismatch; message ignored.');
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The transport type.
|
||||
* @type {number}
|
||||
* @override
|
||||
*/
|
||||
DirectTransport.prototype.transportType = goog.net.xpc.TransportTypes.DIRECT;
|
||||
|
||||
|
||||
/**
|
||||
* Handles transport service messages.
|
||||
* @param {string} payload The message content.
|
||||
* @override
|
||||
*/
|
||||
DirectTransport.prototype.transportServiceHandler = function(payload) {
|
||||
var transportParts = DirectTransport.parseTransportPayload_(payload);
|
||||
var transportMessageType = transportParts[0];
|
||||
var peerEndpointId = transportParts[1];
|
||||
switch (transportMessageType) {
|
||||
case goog.net.xpc.SETUP_ACK_:
|
||||
if (!this.setupAckReceived_.hasFired()) {
|
||||
this.setupAckReceived_.callback(true);
|
||||
}
|
||||
break;
|
||||
case goog.net.xpc.SETUP:
|
||||
this.sendSetupAckMessage_();
|
||||
if ((this.peerEndpointId_ != null) &&
|
||||
(this.peerEndpointId_ != peerEndpointId)) {
|
||||
// Send a new SETUP message since the peer has been replaced.
|
||||
goog.log.info(goog.net.xpc.logger,
|
||||
'Sending SETUP and changing peer ID to: ' + peerEndpointId);
|
||||
this.sendSetupMessage_();
|
||||
}
|
||||
this.peerEndpointId_ = peerEndpointId;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends a SETUP transport service message.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.prototype.sendSetupMessage_ = function() {
|
||||
// Although we could send real objects, since some other transports are
|
||||
// limited to strings we also keep this requirement.
|
||||
var payload = goog.net.xpc.SETUP;
|
||||
payload += DirectTransport.MESSAGE_DELIMITER_;
|
||||
payload += this.endpointId_;
|
||||
this.send(goog.net.xpc.TRANSPORT_SERVICE_, payload);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends a SETUP_ACK transport service message.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.prototype.sendSetupAckMessage_ = function() {
|
||||
this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP_ACK_);
|
||||
if (!this.setupAckSent_.hasFired()) {
|
||||
this.setupAckSent_.callback(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
DirectTransport.prototype.connect = function() {
|
||||
var win = this.getWindow();
|
||||
if (win) {
|
||||
DirectTransport.initialize_(win);
|
||||
this.initialized_ = true;
|
||||
this.maybeAttemptToConnect_();
|
||||
} else {
|
||||
goog.log.fine(goog.net.xpc.logger, 'connect(): no window to initialize.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Connects to other peer. In the case of the outer peer, the setup messages are
|
||||
* likely sent before the inner peer is ready to receive them. Therefore, this
|
||||
* function will continue trying to send the SETUP message until the inner peer
|
||||
* responds. In the case of the inner peer, it will occasionally have its
|
||||
* channel name fall out of sync with the outer peer, particularly during
|
||||
* soft-reloads and history navigations.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.prototype.maybeAttemptToConnect_ = function() {
|
||||
var outerRole = this.channel_.getRole() == CrossPageChannelRole.OUTER;
|
||||
if (this.channel_.isConnected()) {
|
||||
this.maybeAttemptToConnectTimer_.stop();
|
||||
return;
|
||||
}
|
||||
this.maybeAttemptToConnectTimer_.start();
|
||||
this.sendSetupMessage_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Prepares to send a message.
|
||||
* @param {string} service The name of the service the message is to be
|
||||
* delivered to.
|
||||
* @param {string} payload The message content.
|
||||
* @override
|
||||
*/
|
||||
DirectTransport.prototype.send = function(service, payload) {
|
||||
if (!this.channel_.getPeerWindowObject()) {
|
||||
goog.log.fine(goog.net.xpc.logger, 'send(): window not ready');
|
||||
return;
|
||||
}
|
||||
var channelName = DirectTransport.getRoledChannelName_(
|
||||
this.originalChannelName_,
|
||||
this.getPeerRole_());
|
||||
|
||||
var message = new DirectTransport.Message_(
|
||||
channelName,
|
||||
service,
|
||||
payload);
|
||||
|
||||
if (this.channel_.getConfig()[CfgFields.DIRECT_TRANSPORT_SYNC_MODE]) {
|
||||
this.executeScheduledSend_(message);
|
||||
} else {
|
||||
// Note: goog.async.nextTick doesn't support cancelling or disposal so
|
||||
// leaving as 0ms timer, though this may have performance implications.
|
||||
this.asyncSendsMap_[goog.getUid(message)] =
|
||||
Timer.callOnce(goog.bind(this.executeScheduledSend_, this, message), 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends the message.
|
||||
* @param {!DirectTransport.Message_} message The message to send.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.prototype.executeScheduledSend_ = function(message) {
|
||||
var messageId = goog.getUid(message);
|
||||
if (this.asyncSendsMap_[messageId]) {
|
||||
delete this.asyncSendsMap_[messageId];
|
||||
}
|
||||
|
||||
/** @preserveTry */
|
||||
try {
|
||||
var peerProxy = goog.getObjectByName(
|
||||
DirectTransport.GLOBAL_TRANPORT_PATH_,
|
||||
this.channel_.getPeerWindowObject());
|
||||
} catch (error) {
|
||||
goog.log.warning(
|
||||
goog.net.xpc.logger,
|
||||
'Can\'t access other window, ignoring.',
|
||||
error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (goog.isNull(peerProxy)) {
|
||||
goog.log.warning(
|
||||
goog.net.xpc.logger,
|
||||
'Peer window had no global function.');
|
||||
return;
|
||||
}
|
||||
|
||||
/** @preserveTry */
|
||||
try {
|
||||
peerProxy(message.toLiteral());
|
||||
goog.log.info(
|
||||
goog.net.xpc.logger,
|
||||
'send(): channelName=' + message.channelName +
|
||||
' service=' + message.service +
|
||||
' payload=' + message.payload);
|
||||
} catch (error) {
|
||||
goog.log.warning(
|
||||
goog.net.xpc.logger,
|
||||
'Error performing call, ignoring.',
|
||||
error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.net.xpc.CrossPageChannelRole} The role of peer channel (either
|
||||
* inner or outer).
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.prototype.getPeerRole_ = function() {
|
||||
var role = this.channel_.getRole();
|
||||
return role == goog.net.xpc.CrossPageChannelRole.OUTER ?
|
||||
goog.net.xpc.CrossPageChannelRole.INNER :
|
||||
goog.net.xpc.CrossPageChannelRole.OUTER;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Notifies the channel that this transport is connected.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.prototype.notifyConnected_ = function() {
|
||||
// Add a delay as the connection callback will break if this transport is
|
||||
// synchronous and the callback invokes send() immediately.
|
||||
this.channel_.notifyConnected(
|
||||
this.channel_.getConfig()[CfgFields.DIRECT_TRANSPORT_SYNC_MODE] ?
|
||||
DirectTransport.CONNECTION_DELAY_INTERVAL_MS_ : 0);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
DirectTransport.prototype.disposeInternal = function() {
|
||||
if (this.initialized_) {
|
||||
var listenWindow = this.getWindow();
|
||||
var uid = goog.getUid(listenWindow);
|
||||
var value = --DirectTransport.activeCount_[uid];
|
||||
if (value == 1) {
|
||||
goog.exportSymbol(
|
||||
DirectTransport.GLOBAL_TRANPORT_PATH_,
|
||||
null,
|
||||
listenWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.asyncSendsMap_) {
|
||||
goog.object.forEach(this.asyncSendsMap_, function(timerId) {
|
||||
Timer.clear(timerId);
|
||||
});
|
||||
this.asyncSendsMap_ = null;
|
||||
}
|
||||
|
||||
// Deferred's aren't disposables.
|
||||
if (this.setupAckReceived_) {
|
||||
this.setupAckReceived_.cancel();
|
||||
delete this.setupAckReceived_;
|
||||
}
|
||||
if (this.setupAckSent_) {
|
||||
this.setupAckSent_.cancel();
|
||||
delete this.setupAckSent_;
|
||||
}
|
||||
if (this.connected_) {
|
||||
this.connected_.cancel();
|
||||
delete this.connected_;
|
||||
}
|
||||
|
||||
DirectTransport.base(this, 'disposeInternal');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parses a transport service payload message.
|
||||
* @param {string} payload The payload.
|
||||
* @return {!Array<?string>} An array with the message type as the first member
|
||||
* and the endpoint id as the second, if one was sent, or null otherwise.
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.parseTransportPayload_ = function(payload) {
|
||||
var transportParts = /** @type {!Array<?string>} */ (payload.split(
|
||||
DirectTransport.MESSAGE_DELIMITER_));
|
||||
transportParts[1] = transportParts[1] || null; // Usually endpointId.
|
||||
return transportParts;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Message container that gets passed back and forth between windows.
|
||||
* @param {string} channelName The channel name to tranport messages on.
|
||||
* @param {string} service The service to send the payload to.
|
||||
* @param {string} payload The payload to send.
|
||||
* @constructor
|
||||
* @struct
|
||||
* @private
|
||||
*/
|
||||
DirectTransport.Message_ = function(channelName, service, payload) {
|
||||
/**
|
||||
* The name of the channel.
|
||||
* @type {string}
|
||||
*/
|
||||
this.channelName = channelName;
|
||||
|
||||
/**
|
||||
* The service on the channel.
|
||||
* @type {string}
|
||||
*/
|
||||
this.service = service;
|
||||
|
||||
/**
|
||||
* The payload.
|
||||
* @type {string}
|
||||
*/
|
||||
this.payload = payload;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a message to a literal object.
|
||||
* @return {!Object} The message as a literal object.
|
||||
*/
|
||||
DirectTransport.Message_.prototype.toLiteral = function() {
|
||||
return {
|
||||
'channelName': this.channelName,
|
||||
'service': this.service,
|
||||
'payload': this.payload
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Message_ from a literal object.
|
||||
* @param {!Object} literal The literal to convert to Message.
|
||||
* @return {!DirectTransport.Message_} The Message.
|
||||
*/
|
||||
DirectTransport.Message_.fromLiteral = function(literal) {
|
||||
return new DirectTransport.Message_(
|
||||
literal['channelName'],
|
||||
literal['service'],
|
||||
literal['payload']);
|
||||
};
|
||||
|
||||
}); // goog.scope
|
||||
Reference in New Issue
Block a user