mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-05-19 18:57:47 +00:00
jitsi/lib-jitsi-meet#66b601e disabled the execution of Temasys' adapter.screenshare.js on browsers on which we don't use Temasys such as React Native. Henceforth, no Temasys workarounds are necessary on React Native.
317 lines
9.4 KiB
JavaScript
317 lines
9.4 KiB
JavaScript
/**
|
|
* Gets the first common prototype of two specified Objects (treating the
|
|
* objects themselves as prototypes as well).
|
|
*
|
|
* @param {Object} a - The first prototype chain to climb in search of a common
|
|
* prototype.
|
|
* @param {Object} b - The second prototype chain to climb in search of a common
|
|
* prototype.
|
|
* @returns {Object|undefined} - The first common prototype of a and b.
|
|
*/
|
|
function _getCommonPrototype(a, b) {
|
|
// Allow the arguments to be prototypes themselves.
|
|
if (a === b) {
|
|
return a;
|
|
}
|
|
|
|
let p;
|
|
|
|
if ((p = Object.getPrototypeOf(a)) && (p = _getCommonPrototype(b, p))) {
|
|
return p;
|
|
}
|
|
if ((p = Object.getPrototypeOf(b)) && (p = _getCommonPrototype(a, p))) {
|
|
return p;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* Implements an absolute minimum of the common logic of Document.querySelector
|
|
* and Element.querySelector. Implements the most simple of selectors necessary
|
|
* to satisfy the call sites at the time of this writing i.e. select by tagName.
|
|
*
|
|
* @param {Node} node - The Node which is the root of the tree to query.
|
|
* @param {string} selectors - The group of CSS selectors to match on.
|
|
* @returns {Element} - The first Element which is a descendant of the specified
|
|
* node and matches the specified group of selectors.
|
|
*/
|
|
function _querySelector(node, selectors) {
|
|
let element = null;
|
|
|
|
node && _visitNode(node, n => {
|
|
if (n.nodeType === 1 /* ELEMENT_NODE */
|
|
&& n.nodeName === selectors) {
|
|
element = n;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
});
|
|
|
|
return element;
|
|
}
|
|
|
|
/**
|
|
* Visits each Node in the tree of a specific root Node (using depth-first
|
|
* traversal) and invokes a specific callback until the callback returns true.
|
|
*
|
|
* @param {Node} node - The root Node which represents the tree of Nodes to
|
|
* visit.
|
|
* @param {Function} callback - The callback to invoke with each visited Node.
|
|
* @returns {boolean} - True if the specified callback returned true for a Node
|
|
* (at which point the visiting stopped); otherwise, false.
|
|
*/
|
|
function _visitNode(node, callback) {
|
|
if (callback(node)) {
|
|
return true;
|
|
}
|
|
|
|
/* eslint-disable no-param-reassign, no-extra-parens */
|
|
|
|
if ((node = node.firstChild)) {
|
|
do {
|
|
if (_visitNode(node, callback)) {
|
|
return true;
|
|
}
|
|
} while ((node = node.nextSibling));
|
|
}
|
|
|
|
/* eslint-enable no-param-reassign, no-extra-parens */
|
|
|
|
return false;
|
|
}
|
|
|
|
(global => {
|
|
|
|
const DOMParser = require('xmldom').DOMParser;
|
|
|
|
// addEventListener
|
|
//
|
|
// Required by:
|
|
// - jQuery
|
|
if (typeof global.addEventListener === 'undefined') {
|
|
// eslint-disable-next-line no-empty-function
|
|
global.addEventListener = () => {};
|
|
}
|
|
|
|
// document
|
|
//
|
|
// Required by:
|
|
// - jQuery
|
|
// - lib-jitsi-meet/modules/RTC/adapter.screenshare.js
|
|
// - Strophe
|
|
if (typeof global.document === 'undefined') {
|
|
const document
|
|
= new DOMParser().parseFromString(
|
|
/* source */ '<html><head></head><body></body></html>',
|
|
/* mineType */ 'text/xml');
|
|
|
|
// document.addEventListener
|
|
//
|
|
// Required by:
|
|
// - jQuery
|
|
if (typeof document.addEventListener === 'undefined') {
|
|
// eslint-disable-next-line no-empty-function
|
|
document.addEventListener = () => {};
|
|
}
|
|
|
|
// Document.querySelector
|
|
//
|
|
// Required by:
|
|
// - strophejs-plugins/caps/strophe.caps.jsonly.js
|
|
const documentPrototype = Object.getPrototypeOf(document);
|
|
|
|
if (documentPrototype) {
|
|
if (typeof documentPrototype.querySelector === 'undefined') {
|
|
documentPrototype.querySelector = function(selectors) {
|
|
return _querySelector(this.elementNode, selectors);
|
|
};
|
|
}
|
|
}
|
|
|
|
// Element.querySelector
|
|
//
|
|
// Required by:
|
|
// - strophejs-plugins/caps/strophe.caps.jsonly.js
|
|
const elementPrototype
|
|
= Object.getPrototypeOf(document.documentElement);
|
|
|
|
if (elementPrototype
|
|
&& typeof elementPrototype.querySelector === 'undefined') {
|
|
elementPrototype.querySelector = function(selectors) {
|
|
return _querySelector(this, selectors);
|
|
};
|
|
}
|
|
|
|
// FIXME There is a weird infinite loop related to console.log and
|
|
// Document and/or Element at the time of this writing. Work around it
|
|
// by patching Node and/or overriding console.log.
|
|
const nodePrototype
|
|
= _getCommonPrototype(documentPrototype, elementPrototype);
|
|
|
|
if (nodePrototype
|
|
|
|
// XXX The intention was to find Node from which Document and
|
|
// Element extend. If for whatever reason we've reached Object,
|
|
// then it doesn't sound like what expected.
|
|
&& nodePrototype !== Object.getPrototypeOf({})) {
|
|
// Override console.log.
|
|
const console = global.console;
|
|
|
|
if (console) {
|
|
const loggerLevels = require('jitsi-meet-logger').levels;
|
|
|
|
Object.keys(loggerLevels).forEach(key => {
|
|
const level = loggerLevels[key];
|
|
const consoleLog = console[level];
|
|
|
|
/* eslint-disable prefer-rest-params */
|
|
|
|
if (typeof consoleLog === 'function') {
|
|
console[level] = function(...args) {
|
|
const length = args.length;
|
|
|
|
for (let i = 0; i < length; ++i) {
|
|
let arg = args[i];
|
|
|
|
if (arg
|
|
&& typeof arg !== 'string'
|
|
|
|
// Limit the console.log override to
|
|
// Node (instances).
|
|
&& nodePrototype.isPrototypeOf(arg)) {
|
|
const toString = arg.toString;
|
|
|
|
if (toString) {
|
|
arg = toString.call(arg);
|
|
}
|
|
}
|
|
args[i] = arg;
|
|
}
|
|
|
|
consoleLog.apply(this, args);
|
|
};
|
|
}
|
|
|
|
/* eslint-enable prefer-rest-params */
|
|
});
|
|
}
|
|
}
|
|
|
|
global.document = document;
|
|
}
|
|
|
|
// location
|
|
if (typeof global.location === 'undefined') {
|
|
global.location = {
|
|
href: ''
|
|
};
|
|
}
|
|
|
|
// performance
|
|
if (typeof global.performance === 'undefined') {
|
|
global.performance = {
|
|
now() {
|
|
return 0;
|
|
}
|
|
};
|
|
}
|
|
|
|
// sessionStorage
|
|
//
|
|
// Required by:
|
|
// - Strophe
|
|
if (typeof global.sessionStorage === 'undefined') {
|
|
global.sessionStorage = {
|
|
/* eslint-disable no-empty-function */
|
|
getItem() {},
|
|
removeItem() {},
|
|
setItem() {}
|
|
|
|
/* eslint-enable no-empty-function */
|
|
};
|
|
}
|
|
|
|
const navigator = global.navigator;
|
|
|
|
if (navigator) {
|
|
// platform
|
|
//
|
|
// Required by:
|
|
// - lib-jitsi-meet/modules/RTC/adapter.screenshare.js
|
|
if (typeof navigator.platform === 'undefined') {
|
|
navigator.platform = '';
|
|
}
|
|
|
|
// plugins
|
|
//
|
|
// Required by:
|
|
// - lib-jitsi-meet/modules/RTC/adapter.screenshare.js
|
|
if (typeof navigator.plugins === 'undefined') {
|
|
navigator.plugins = [];
|
|
}
|
|
|
|
// userAgent
|
|
//
|
|
// Required by:
|
|
// - lib-jitsi-meet/modules/RTC/adapter.screenshare.js
|
|
// - lib-jitsi-meet/modules/RTC/RTCBrowserType.js
|
|
(() => {
|
|
const reactNativePackageJSON = require('react-native/package.json');
|
|
let userAgent = reactNativePackageJSON.name || 'react-native';
|
|
|
|
const version = reactNativePackageJSON.version;
|
|
|
|
if (version) {
|
|
userAgent += `/${version}`;
|
|
}
|
|
|
|
if (typeof navigator.userAgent !== 'undefined') {
|
|
const s = navigator.userAgent.toString();
|
|
|
|
if (s.length > 0 && s.indexOf(userAgent) === -1) {
|
|
userAgent = `${s} ${userAgent}`;
|
|
}
|
|
}
|
|
|
|
navigator.userAgent = userAgent;
|
|
})();
|
|
}
|
|
|
|
// WebRTC
|
|
require('./polyfills-webrtc');
|
|
|
|
// XMLHttpRequest
|
|
if (global.XMLHttpRequest) {
|
|
const prototype = global.XMLHttpRequest.prototype;
|
|
|
|
// XMLHttpRequest.responseXML
|
|
//
|
|
// Required by:
|
|
// - Strophe
|
|
if (prototype && typeof prototype.responseXML === 'undefined') {
|
|
Object.defineProperty(prototype, 'responseXML', {
|
|
configurable: true,
|
|
enumerable: true,
|
|
get() {
|
|
const responseText = this.responseText;
|
|
let responseXML;
|
|
|
|
if (responseText) {
|
|
responseXML = new DOMParser()
|
|
.parseFromString(responseText);
|
|
}
|
|
|
|
return responseXML;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Polyfill for URL constructor
|
|
require('url-polyfill');
|
|
|
|
})(global || window || this); // eslint-disable-line no-invalid-this
|