ludus/out/goog/net/xpc/crosspagechannel.js

341 lines
15 KiB
JavaScript
Raw Normal View History

2023-11-16 18:22:15 +00:00
/*TRANSPILED*//*
Copyright The Closure Library Authors.
SPDX-License-Identifier: Apache-2.0
*/
'use strict';
goog.provide("goog.net.xpc.CrossPageChannel");
goog.require("goog.Uri");
goog.require("goog.async.Deferred");
goog.require("goog.async.Delay");
goog.require("goog.dispose");
goog.require("goog.dom");
goog.require("goog.dom.TagName");
goog.require("goog.dom.safe");
goog.require("goog.events");
goog.require("goog.events.EventHandler");
goog.require("goog.events.EventType");
goog.require("goog.functions");
goog.require("goog.html.legacyconversions");
goog.require("goog.json");
goog.require("goog.log");
goog.require("goog.messaging.AbstractChannel");
goog.require("goog.net.xpc");
goog.require("goog.net.xpc.CfgFields");
goog.require("goog.net.xpc.ChannelStates");
goog.require("goog.net.xpc.CrossPageChannelRole");
goog.require("goog.net.xpc.NativeMessagingTransport");
goog.require("goog.net.xpc.TransportTypes");
goog.require("goog.net.xpc.UriCfgFields");
goog.require("goog.string");
goog.require("goog.uri.utils");
goog.require("goog.userAgent");
goog.requireType("goog.net.xpc.Transport");
goog.net.xpc.CrossPageChannel = function(cfg, opt_domHelper) {
goog.net.xpc.CrossPageChannel.base(this, "constructor");
for (let i = 0, uriField; uriField = goog.net.xpc.UriCfgFields[i]; i++) {
if (uriField in cfg && !/^https?:\/\//.test(cfg[uriField])) {
throw new Error("URI " + cfg[uriField] + " is invalid for field " + uriField);
}
}
this.cfg_ = cfg;
this.name = this.cfg_[goog.net.xpc.CfgFields.CHANNEL_NAME] || goog.net.xpc.getRandomString(10);
this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
this.deferredDeliveries_ = [];
this.peerLoadHandler_ = new goog.events.EventHandler(this);
cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] = cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] || goog.uri.utils.getHost(this.domHelper_.getWindow().location.href) + "/robots.txt";
cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] = cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] || goog.uri.utils.getHost(cfg[goog.net.xpc.CfgFields.PEER_URI] || "") + "/robots.txt";
goog.net.xpc.CrossPageChannel.channels[this.name] = this;
if (!goog.events.getListener(window, goog.events.EventType.UNLOAD, goog.net.xpc.CrossPageChannel.disposeAll_)) {
goog.events.listenOnce(window, goog.events.EventType.UNLOAD, goog.net.xpc.CrossPageChannel.disposeAll_);
}
goog.log.info(goog.net.xpc.logger, "CrossPageChannel created: " + this.name);
};
goog.inherits(goog.net.xpc.CrossPageChannel, goog.messaging.AbstractChannel);
goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_ESCAPE_RE_ = new RegExp("^%*" + goog.net.xpc.TRANSPORT_SERVICE + "$");
goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_UNESCAPE_RE_ = new RegExp("^%+" + goog.net.xpc.TRANSPORT_SERVICE + "$");
goog.net.xpc.CrossPageChannel.prototype.connectionDelay_ = null;
goog.net.xpc.CrossPageChannel.prototype.peerWindowDeferred_ = null;
goog.net.xpc.CrossPageChannel.prototype.transport_ = null;
goog.net.xpc.CrossPageChannel.prototype.state_ = goog.net.xpc.ChannelStates.NOT_CONNECTED;
goog.net.xpc.CrossPageChannel.prototype.isConnected = function() {
return this.state_ == goog.net.xpc.ChannelStates.CONNECTED;
};
goog.net.xpc.CrossPageChannel.prototype.peerWindowObject_ = null;
goog.net.xpc.CrossPageChannel.prototype.iframeElement_ = null;
goog.net.xpc.CrossPageChannel.prototype.getConfig = function() {
return this.cfg_;
};
goog.net.xpc.CrossPageChannel.prototype.getIframeElement = function() {
return this.iframeElement_;
};
goog.net.xpc.CrossPageChannel.prototype.setPeerWindowObject = function(peerWindowObject) {
this.peerWindowObject_ = peerWindowObject;
};
goog.net.xpc.CrossPageChannel.prototype.getPeerWindowObject = function() {
return this.peerWindowObject_;
};
goog.net.xpc.CrossPageChannel.prototype.isPeerAvailable = function() {
try {
return !!this.peerWindowObject_ && !this.peerWindowObject_.closed;
} catch (e) {
return false;
}
};
goog.net.xpc.CrossPageChannel.prototype.determineTransportType_ = function() {
let transportType;
if (typeof document.postMessage === "function" || typeof window.postMessage === "function" || goog.userAgent.IE && window.postMessage) {
transportType = goog.net.xpc.TransportTypes.NATIVE_MESSAGING;
} else {
transportType = goog.net.xpc.TransportTypes.UNDEFINED;
}
return transportType;
};
goog.net.xpc.CrossPageChannel.prototype.createTransport_ = function() {
if (this.transport_) {
return;
}
const CfgFields = goog.net.xpc.CfgFields;
if (!this.cfg_[CfgFields.TRANSPORT]) {
this.cfg_[CfgFields.TRANSPORT] = this.determineTransportType_();
}
if (typeof this.cfg_[CfgFields.TRANSPORT] === "function") {
this.transport_ = new this.cfg_[CfgFields.TRANSPORT](this, this.domHelper_);
} else {
switch(this.cfg_[CfgFields.TRANSPORT]) {
case goog.net.xpc.TransportTypes.NATIVE_MESSAGING:
const protocolVersion = this.cfg_[CfgFields.NATIVE_TRANSPORT_PROTOCOL_VERSION] || 2;
this.transport_ = new goog.net.xpc.NativeMessagingTransport(this, this.cfg_[CfgFields.PEER_HOSTNAME], this.domHelper_, !!this.cfg_[CfgFields.ONE_SIDED_HANDSHAKE], protocolVersion);
break;
}
}
if (this.transport_) {
goog.log.info(goog.net.xpc.logger, "Transport created: " + this.transport_.getName());
} else {
throw new Error("CrossPageChannel: No suitable transport found! You may " + "try injecting a Transport constructor directly via the channel " + "config object.");
}
};
goog.net.xpc.CrossPageChannel.prototype.getTransportType = function() {
return this.transport_.getType();
};
goog.net.xpc.CrossPageChannel.prototype.getTransportName = function() {
return this.transport_.getName();
};
goog.net.xpc.CrossPageChannel.prototype.getPeerConfiguration = function() {
const peerCfg = {};
peerCfg[goog.net.xpc.CfgFields.CHANNEL_NAME] = this.name;
peerCfg[goog.net.xpc.CfgFields.TRANSPORT] = this.cfg_[goog.net.xpc.CfgFields.TRANSPORT];
peerCfg[goog.net.xpc.CfgFields.ONE_SIDED_HANDSHAKE] = this.cfg_[goog.net.xpc.CfgFields.ONE_SIDED_HANDSHAKE];
if (this.cfg_[goog.net.xpc.CfgFields.LOCAL_RELAY_URI]) {
peerCfg[goog.net.xpc.CfgFields.PEER_RELAY_URI] = this.cfg_[goog.net.xpc.CfgFields.LOCAL_RELAY_URI];
}
if (this.cfg_[goog.net.xpc.CfgFields.LOCAL_POLL_URI]) {
peerCfg[goog.net.xpc.CfgFields.PEER_POLL_URI] = this.cfg_[goog.net.xpc.CfgFields.LOCAL_POLL_URI];
}
if (this.cfg_[goog.net.xpc.CfgFields.PEER_POLL_URI]) {
peerCfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] = this.cfg_[goog.net.xpc.CfgFields.PEER_POLL_URI];
}
const role = this.cfg_[goog.net.xpc.CfgFields.ROLE];
if (role) {
peerCfg[goog.net.xpc.CfgFields.ROLE] = role == goog.net.xpc.CrossPageChannelRole.INNER ? goog.net.xpc.CrossPageChannelRole.OUTER : goog.net.xpc.CrossPageChannelRole.INNER;
}
return peerCfg;
};
goog.net.xpc.CrossPageChannel.prototype.createPeerIframe = function(parentElm, opt_configureIframeCb, opt_addCfgParam) {
goog.log.info(goog.net.xpc.logger, "createPeerIframe()");
let iframeId = this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID];
if (!iframeId) {
iframeId = this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID] = "xpcpeer" + goog.net.xpc.getRandomString(4);
}
const iframeElm = goog.dom.getDomHelper(parentElm).createElement(goog.dom.TagName.IFRAME);
iframeElm.id = iframeElm.name = iframeId;
if (opt_configureIframeCb) {
opt_configureIframeCb(iframeElm);
} else {
iframeElm.style.width = iframeElm.style.height = "100%";
}
this.cleanUpIncompleteConnection_();
this.peerWindowDeferred_ = new goog.async.Deferred(undefined, this);
const peerUri = this.getPeerUri(opt_addCfgParam);
this.peerLoadHandler_.listenOnceWithScope(iframeElm, "load", this.peerWindowDeferred_.callback, false, this.peerWindowDeferred_);
if (goog.userAgent.GECKO || goog.userAgent.WEBKIT) {
window.setTimeout(goog.bind(function() {
parentElm.appendChild(iframeElm);
goog.dom.safe.setIframeSrc(iframeElm, goog.html.legacyconversions.trustedResourceUrlFromString(peerUri.toString()));
goog.log.info(goog.net.xpc.logger, "peer iframe created (" + iframeId + ")");
}, this), 1);
} else {
goog.dom.safe.setIframeSrc(iframeElm, goog.html.legacyconversions.trustedResourceUrlFromString(peerUri.toString()));
parentElm.appendChild(iframeElm);
goog.log.info(goog.net.xpc.logger, "peer iframe created (" + iframeId + ")");
}
return iframeElm;
};
goog.net.xpc.CrossPageChannel.prototype.cleanUpIncompleteConnection_ = function() {
if (this.peerWindowDeferred_) {
this.peerWindowDeferred_.cancel();
this.peerWindowDeferred_ = null;
}
this.deferredDeliveries_.length = 0;
this.peerLoadHandler_.removeAll();
};
goog.net.xpc.CrossPageChannel.prototype.getPeerUri = function(opt_addCfgParam) {
let peerUri = this.cfg_[goog.net.xpc.CfgFields.PEER_URI];
if (typeof peerUri === "string") {
peerUri = this.cfg_[goog.net.xpc.CfgFields.PEER_URI] = new goog.Uri(peerUri);
}
if (opt_addCfgParam !== false) {
peerUri.setParameterValue("xpc", goog.json.serialize(this.getPeerConfiguration()));
}
return peerUri;
};
goog.net.xpc.CrossPageChannel.prototype.connect = function(opt_connectCb) {
this.connectCb_ = opt_connectCb || goog.functions.UNDEFINED;
if (this.state_ == goog.net.xpc.ChannelStates.CLOSED) {
this.state_ = goog.net.xpc.ChannelStates.NOT_CONNECTED;
}
if (this.peerWindowDeferred_) {
this.peerWindowDeferred_.addCallback(this.continueConnection_);
} else {
this.continueConnection_();
}
};
goog.net.xpc.CrossPageChannel.prototype.continueConnection_ = function() {
goog.log.info(goog.net.xpc.logger, "continueConnection_()");
this.peerWindowDeferred_ = null;
if (this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID]) {
this.iframeElement_ = this.domHelper_.getElement(this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID]);
}
if (this.iframeElement_) {
let winObj = this.iframeElement_.contentWindow;
if (!winObj) {
winObj = window.frames[this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID]];
}
this.setPeerWindowObject(winObj);
}
if (!this.peerWindowObject_) {
if (window == window.top) {
throw new Error("CrossPageChannel: Can't connect, peer window-object not set.");
} else {
this.setPeerWindowObject(window.parent);
}
}
this.createTransport_();
this.transport_.connect();
while (this.deferredDeliveries_.length > 0) {
this.deferredDeliveries_.shift()();
}
};
goog.net.xpc.CrossPageChannel.prototype.close = function() {
this.cleanUpIncompleteConnection_();
this.state_ = goog.net.xpc.ChannelStates.CLOSED;
goog.dispose(this.transport_);
this.transport_ = null;
this.connectCb_ = null;
goog.dispose(this.connectionDelay_);
this.connectionDelay_ = null;
goog.log.info(goog.net.xpc.logger, 'Channel "' + this.name + '" closed');
};
goog.net.xpc.CrossPageChannel.prototype.notifyConnected = function(opt_delay) {
if (this.isConnected() || this.connectionDelay_ && this.connectionDelay_.isActive()) {
return;
}
this.state_ = goog.net.xpc.ChannelStates.CONNECTED;
goog.log.info(goog.net.xpc.logger, 'Channel "' + this.name + '" connected');
goog.dispose(this.connectionDelay_);
if (opt_delay !== undefined) {
this.connectionDelay_ = new goog.async.Delay(this.connectCb_, opt_delay);
this.connectionDelay_.start();
} else {
this.connectionDelay_ = null;
this.connectCb_();
}
};
goog.net.xpc.CrossPageChannel.prototype.notifyTransportError = function() {
goog.log.info(goog.net.xpc.logger, "Transport Error");
this.close();
};
goog.net.xpc.CrossPageChannel.prototype.send = function(serviceName, payload) {
if (!this.isConnected()) {
goog.log.error(goog.net.xpc.logger, "Can't send. Channel not connected.");
return;
}
if (!this.isPeerAvailable()) {
goog.log.error(goog.net.xpc.logger, "Peer has disappeared.");
this.close();
return;
}
if (goog.isObject(payload)) {
payload = goog.json.serialize(payload);
}
this.transport_.send(this.escapeServiceName_(serviceName), payload);
};
goog.net.xpc.CrossPageChannel.prototype.xpcDeliver = function(serviceName, payload, opt_origin) {
if (this.peerWindowDeferred_) {
this.deferredDeliveries_.push(goog.bind(this.xpcDeliver, this, serviceName, payload, opt_origin));
return;
}
if (!this.isMessageOriginAcceptable(opt_origin)) {
goog.log.warning(goog.net.xpc.logger, 'Message received from unapproved origin "' + opt_origin + '" - rejected.');
return;
}
if (this.isDisposed() || this.state_ == goog.net.xpc.ChannelStates.CLOSED) {
goog.log.warning(goog.net.xpc.logger, "CrossPageChannel::xpcDeliver(): Channel closed.");
} else if (!serviceName || serviceName == goog.net.xpc.TRANSPORT_SERVICE) {
this.transport_.transportServiceHandler(payload);
} else {
if (this.isConnected()) {
this.deliver(this.unescapeServiceName_(serviceName), payload);
} else {
goog.log.info(goog.net.xpc.logger, "CrossPageChannel::xpcDeliver(): Not connected.");
}
}
};
goog.net.xpc.CrossPageChannel.prototype.escapeServiceName_ = function(name) {
if (goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_ESCAPE_RE_.test(name)) {
name = "%" + name;
}
return name.replace(/[%:|]/g, encodeURIComponent);
};
goog.net.xpc.CrossPageChannel.prototype.unescapeServiceName_ = function(name) {
name = name.replace(/%[0-9a-f]{2}/gi, decodeURIComponent);
if (goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_UNESCAPE_RE_.test(name)) {
return name.substring(1);
} else {
return name;
}
};
goog.net.xpc.CrossPageChannel.prototype.getRole = function() {
const role = this.cfg_[goog.net.xpc.CfgFields.ROLE];
if (typeof role === "number") {
return role;
} else {
return window.parent == this.peerWindowObject_ ? goog.net.xpc.CrossPageChannelRole.INNER : goog.net.xpc.CrossPageChannelRole.OUTER;
}
};
goog.net.xpc.CrossPageChannel.prototype.updateChannelNameAndCatalog = function(name) {
goog.log.fine(goog.net.xpc.logger, "changing channel name to " + name);
delete goog.net.xpc.CrossPageChannel.channels[this.name];
this.name = name;
goog.net.xpc.CrossPageChannel.channels[name] = this;
};
goog.net.xpc.CrossPageChannel.prototype.isMessageOriginAcceptable = function(opt_origin) {
const peerHostname = this.cfg_[goog.net.xpc.CfgFields.PEER_HOSTNAME];
return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(opt_origin)) || goog.string.isEmptyOrWhitespace(goog.string.makeSafe(peerHostname)) || opt_origin == this.cfg_[goog.net.xpc.CfgFields.PEER_HOSTNAME];
};
goog.net.xpc.CrossPageChannel.prototype.disposeInternal = function() {
this.close();
this.peerWindowObject_ = null;
this.iframeElement_ = null;
delete goog.net.xpc.CrossPageChannel.channels[this.name];
goog.dispose(this.peerLoadHandler_);
delete this.peerLoadHandler_;
goog.net.xpc.CrossPageChannel.base(this, "disposeInternal");
};
goog.net.xpc.CrossPageChannel.disposeAll_ = function() {
for (let name in goog.net.xpc.CrossPageChannel.channels) {
goog.dispose(goog.net.xpc.CrossPageChannel.channels[name]);
}
};
goog.net.xpc.CrossPageChannel.channels = {};