var Features = { /** * @property {boolean} canvas - Is canvas available? * @default */ canvas: false, /** * @property {?boolean} canvasBitBltShift - True if canvas supports a 'copy' bitblt onto itself when the source and destination regions overlap. * @default */ canvasBitBltShift: null, /** * @property {boolean} webGL - Is webGL available? * @default */ webGL: false, /** * @property {boolean} file - Is file available? * @default */ file: false, /** * @property {boolean} fileSystem - Is fileSystem available? * @default */ fileSystem: false, /** * @property {boolean} localStorage - Is localStorage available? * @default */ localStorage: false, /** * @property {boolean} worker - Is worker available? * @default */ worker: false, /** * @property {boolean} pointerLock - Is Pointer Lock available? * @default */ pointerLock: false, /** * @property {boolean} vibration - Does the device support the Vibration API? * @default */ vibration: false, /** * @property {boolean} getUserMedia - Does the device support the getUserMedia API? * @default */ getUserMedia: true, /** * @property {boolean} littleEndian - Is the device big or little endian? (only detected if the browser supports TypedArrays) * @default */ littleEndian: false, /** * @property {boolean} support32bit - Does the device context support 32bit pixel manipulation using array buffer views? * @default */ support32bit: false }; /** * Check Little or Big Endian system. * * @author Matt DesLauriers (@mattdesl) */ function checkIsLittleEndian () { var a = new ArrayBuffer(4); var b = new Uint8Array(a); var c = new Uint32Array(a); b[0] = 0xa1; b[1] = 0xb2; b[2] = 0xc3; b[3] = 0xd4; if (c[0] === 0xd4c3b2a1) { return true; } if (c[0] === 0xa1b2c3d4) { return false; } else { // Could not determine endianness return null; } } function init (OS, Browser) { Features.canvas = !!window['CanvasRenderingContext2D'] || OS.cocoonJS; try { Features.localStorage = !!localStorage.getItem; } catch (error) { Features.localStorage = false; } Features.file = !!window['File'] && !!window['FileReader'] && !!window['FileList'] && !!window['Blob']; Features.fileSystem = !!window['requestFileSystem']; var isUint8 = false; var testWebGL = function () { if (window['WebGLRenderingContext']) { try { var canvas = document.createElement('canvas'); // cocoon ... canvas.screencanvas = false; var ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); var image = ctx.createImageData(1, 1); /** * Test to see if ImageData uses CanvasPixelArray or Uint8ClampedArray. * * @author Matt DesLauriers (@mattdesl) */ isUint8 = image.data instanceof Uint8ClampedArray; return (ctx !== null); } catch (e) { return false; } } return false; }; Features.webGL = testWebGL(); Features.worker = !!window['Worker']; Features.pointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia; window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL; Features.getUserMedia = Features.getUserMedia && !!navigator.getUserMedia && !!window.URL; // Older versions of firefox (< 21) apparently claim support but user media does not actually work if (Browser.firefox && Browser.firefoxVersion < 21) { Features.getUserMedia = false; } // Excludes iOS versions as they generally wrap UIWebView (eg. Safari WebKit) and it // is safer to not try and use the fast copy-over method. if (!OS.iOS && (Browser.ie || Browser.firefox || Browser.chrome)) { Features.canvasBitBltShift = true; } // Known not to work if (Browser.safari || Browser.mobileSafari) { Features.canvasBitBltShift = false; } navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate; if (navigator.vibrate) { Features.vibration = true; } if (typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined' && typeof Uint32Array !== 'undefined') { Features.littleEndian = checkIsLittleEndian(); } Features.support32bit = ( typeof ArrayBuffer !== 'undefined' && typeof Uint8ClampedArray !== 'undefined' && typeof Int32Array !== 'undefined' && Features.littleEndian !== null && isUint8 ); return Features; } module.exports = init;