diff options
Diffstat (limited to 'platform/web/js')
| -rw-r--r-- | platform/web/js/engine/engine.js | 25 | ||||
| -rw-r--r-- | platform/web/js/engine/features.js | 96 | 
2 files changed, 105 insertions, 16 deletions
| diff --git a/platform/web/js/engine/engine.js b/platform/web/js/engine/engine.js index 6f0d51b2be..9227aa1f05 100644 --- a/platform/web/js/engine/engine.js +++ b/platform/web/js/engine/engine.js @@ -61,20 +61,6 @@ const Engine = (function () {  	};  	/** -	 * Check whether WebGL is available. Optionally, specify a particular version of WebGL to check for. -	 * -	 * @param {number=} [majorVersion=1] The major WebGL version to check for. -	 * @returns {boolean} If the given major version of WebGL is available. -	 * @function Engine.isWebGLAvailable -	 */ -	Engine.isWebGLAvailable = function (majorVersion = 1) { -		try { -			return !!document.createElement('canvas').getContext(['webgl', 'webgl2'][majorVersion - 1]); -		} catch (e) { /* Not available */ } -		return false; -	}; - -	/**  	 * Safe Engine constructor, creates a new prototype for every new instance to avoid prototype pollution.  	 * @ignore  	 * @constructor @@ -265,14 +251,21 @@ const Engine = (function () {  		// Also expose static methods as instance methods  		Engine.prototype['load'] = Engine.load;  		Engine.prototype['unload'] = Engine.unload; -		Engine.prototype['isWebGLAvailable'] = Engine.isWebGLAvailable;  		return new Engine(initConfig);  	}  	// Closure compiler exported static methods.  	SafeEngine['load'] = Engine.load;  	SafeEngine['unload'] = Engine.unload; -	SafeEngine['isWebGLAvailable'] = Engine.isWebGLAvailable; + +	// Feature-detection utilities. +	SafeEngine['isWebGLAvailable'] = Features.isWebGLAvailable; +	SafeEngine['isFetchAvailable'] = Features.isFetchAvailable; +	SafeEngine['isSecureContext'] = Features.isSecureContext; +	SafeEngine['isCrossOriginIsolated'] = Features.isCrossOriginIsolated; +	SafeEngine['isSharedArrayBufferAvailable'] = Features.isSharedArrayBufferAvailable; +	SafeEngine['isAudioWorkletAvailable'] = Features.isAudioWorkletAvailable; +	SafeEngine['getMissingFeatures'] = Features.getMissingFeatures;  	return SafeEngine;  }()); diff --git a/platform/web/js/engine/features.js b/platform/web/js/engine/features.js new file mode 100644 index 0000000000..f91a4eff81 --- /dev/null +++ b/platform/web/js/engine/features.js @@ -0,0 +1,96 @@ +const Features = { // eslint-disable-line no-unused-vars +	/** +	 * Check whether WebGL is available. Optionally, specify a particular version of WebGL to check for. +	 * +	 * @param {number=} [majorVersion=1] The major WebGL version to check for. +	 * @returns {boolean} If the given major version of WebGL is available. +	 * @function Engine.isWebGLAvailable +	 */ +	isWebGLAvailable: function (majorVersion = 1) { +		try { +			return !!document.createElement('canvas').getContext(['webgl', 'webgl2'][majorVersion - 1]); +		} catch (e) { /* Not available */ } +		return false; +	}, + +	/** +	 * Check whether the Fetch API available and supports streaming responses. +	 * +	 * @returns {boolean} If the Fetch API is available and supports streaming responses. +	 * @function Engine.isFetchAvailable +	 */ +	isFetchAvailable: function () { +		return 'fetch' in window && 'Response' in window && 'body' in window.Response.prototype; +	}, + +	/** +	 * Check whether the engine is running in a Secure Context. +	 * +	 * @returns {boolean} If the engine is running in a Secure Context. +	 * @function Engine.isSecureContext +	 */ +	isSecureContext: function () { +		return window['isSecureContext'] === true; +	}, + +	/** +	 * Check whether the engine is cross origin isolated. +	 * This value is dependent on Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers sent by the server. +	 * +	 * @returns {boolean} If the engine is running in a Secure Context. +	 * @function Engine.isSecureContext +	 */ +	isCrossOriginIsolated: function () { +		return window['crossOriginIsolated'] === true; +	}, + +	/** +	 * Check whether SharedBufferArray is available. +	 * +	 * Most browsers require the page to be running in a secure context, and the +	 * the server to provide specific CORS headers for SharedArrayBuffer to be available. +	 * +	 * @returns {boolean} If SharedArrayBuffer is available. +	 * @function Engine.isSharedArrayBufferAvailable +	 */ +	isSharedArrayBufferAvailable: function () { +		return 'SharedArrayBuffer' in window; +	}, + +	/** +	 * Check whether the AudioContext supports AudioWorkletNodes. +	 * +	 * @returns {boolean} If AudioWorkletNode is available. +	 * @function Engine.isAudioWorkletAvailable +	 */ +	isAudioWorkletAvailable: function () { +		return 'AudioContext' in window && 'audioWorklet' in AudioContext.prototype; +	}, + +	/** +	 * Return an array of missing required features (as string). +	 * +	 * @returns {Array<string>} A list of human-readable missing features. +	 * @function Engine.getMissingFeatures +	 */ +	getMissingFeatures: function () { +		const missing = []; +		if (!Features.isWebGLAvailable(2)) { +			missing.push('WebGL2'); +		} +		if (!Features.isFetchAvailable()) { +			missing.push('Fetch'); +		} +		if (!Features.isSecureContext()) { +			missing.push('Secure Context'); +		} +		if (!Features.isCrossOriginIsolated()) { +			missing.push('Cross Origin Isolation'); +		} +		if (!Features.isSharedArrayBufferAvailable()) { +			missing.push('SharedArrayBuffer'); +		} +		// Audio is normally optional since we have a dummy fallback. +		return missing; +	}, +}; |