FeatureDetection.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. import when from '../ThirdParty/when.js';
  2. import defaultValue from './defaultValue.js';
  3. import defined from './defined.js';
  4. import defineProperties from './defineProperties.js';
  5. import DeveloperError from './DeveloperError.js';
  6. import Fullscreen from './Fullscreen.js';
  7. /*global CanvasPixelArray*/
  8. var theNavigator;
  9. if (typeof navigator !== 'undefined') {
  10. theNavigator = navigator;
  11. } else {
  12. theNavigator = {};
  13. }
  14. function extractVersion(versionString) {
  15. var parts = versionString.split('.');
  16. for (var i = 0, len = parts.length; i < len; ++i) {
  17. parts[i] = parseInt(parts[i], 10);
  18. }
  19. return parts;
  20. }
  21. var isChromeResult;
  22. var chromeVersionResult;
  23. function isChrome() {
  24. if (!defined(isChromeResult)) {
  25. isChromeResult = false;
  26. // Edge contains Chrome in the user agent too
  27. if (!isEdge()) {
  28. var fields = (/ Chrome\/([\.0-9]+)/).exec(theNavigator.userAgent);
  29. if (fields !== null) {
  30. isChromeResult = true;
  31. chromeVersionResult = extractVersion(fields[1]);
  32. }
  33. }
  34. }
  35. return isChromeResult;
  36. }
  37. function chromeVersion() {
  38. return isChrome() && chromeVersionResult;
  39. }
  40. var isSafariResult;
  41. var safariVersionResult;
  42. function isSafari() {
  43. if (!defined(isSafariResult)) {
  44. isSafariResult = false;
  45. // Chrome and Edge contain Safari in the user agent too
  46. if (!isChrome() && !isEdge() && (/ Safari\/[\.0-9]+/).test(theNavigator.userAgent)) {
  47. var fields = (/ Version\/([\.0-9]+)/).exec(theNavigator.userAgent);
  48. if (fields !== null) {
  49. isSafariResult = true;
  50. safariVersionResult = extractVersion(fields[1]);
  51. }
  52. }
  53. }
  54. return isSafariResult;
  55. }
  56. function safariVersion() {
  57. return isSafari() && safariVersionResult;
  58. }
  59. var isWebkitResult;
  60. var webkitVersionResult;
  61. function isWebkit() {
  62. if (!defined(isWebkitResult)) {
  63. isWebkitResult = false;
  64. var fields = (/ AppleWebKit\/([\.0-9]+)(\+?)/).exec(theNavigator.userAgent);
  65. if (fields !== null) {
  66. isWebkitResult = true;
  67. webkitVersionResult = extractVersion(fields[1]);
  68. webkitVersionResult.isNightly = !!fields[2];
  69. }
  70. }
  71. return isWebkitResult;
  72. }
  73. function webkitVersion() {
  74. return isWebkit() && webkitVersionResult;
  75. }
  76. var isInternetExplorerResult;
  77. var internetExplorerVersionResult;
  78. function isInternetExplorer() {
  79. if (!defined(isInternetExplorerResult)) {
  80. isInternetExplorerResult = false;
  81. var fields;
  82. if (theNavigator.appName === 'Microsoft Internet Explorer') {
  83. fields = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
  84. if (fields !== null) {
  85. isInternetExplorerResult = true;
  86. internetExplorerVersionResult = extractVersion(fields[1]);
  87. }
  88. } else if (theNavigator.appName === 'Netscape') {
  89. fields = /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
  90. if (fields !== null) {
  91. isInternetExplorerResult = true;
  92. internetExplorerVersionResult = extractVersion(fields[1]);
  93. }
  94. }
  95. }
  96. return isInternetExplorerResult;
  97. }
  98. function internetExplorerVersion() {
  99. return isInternetExplorer() && internetExplorerVersionResult;
  100. }
  101. var isEdgeResult;
  102. var edgeVersionResult;
  103. function isEdge() {
  104. if (!defined(isEdgeResult)) {
  105. isEdgeResult = false;
  106. var fields = (/ Edge\/([\.0-9]+)/).exec(theNavigator.userAgent);
  107. if (fields !== null) {
  108. isEdgeResult = true;
  109. edgeVersionResult = extractVersion(fields[1]);
  110. }
  111. }
  112. return isEdgeResult;
  113. }
  114. function edgeVersion() {
  115. return isEdge() && edgeVersionResult;
  116. }
  117. var isFirefoxResult;
  118. var firefoxVersionResult;
  119. function isFirefox() {
  120. if (!defined(isFirefoxResult)) {
  121. isFirefoxResult = false;
  122. var fields = /Firefox\/([\.0-9]+)/.exec(theNavigator.userAgent);
  123. if (fields !== null) {
  124. isFirefoxResult = true;
  125. firefoxVersionResult = extractVersion(fields[1]);
  126. }
  127. }
  128. return isFirefoxResult;
  129. }
  130. var isWindowsResult;
  131. function isWindows() {
  132. if (!defined(isWindowsResult)) {
  133. isWindowsResult = /Windows/i.test(theNavigator.appVersion);
  134. }
  135. return isWindowsResult;
  136. }
  137. function firefoxVersion() {
  138. return isFirefox() && firefoxVersionResult;
  139. }
  140. var hasPointerEvents;
  141. function supportsPointerEvents() {
  142. if (!defined(hasPointerEvents)) {
  143. //While navigator.pointerEnabled is deprecated in the W3C specification
  144. //we still need to use it if it exists in order to support browsers
  145. //that rely on it, such as the Windows WebBrowser control which defines
  146. //PointerEvent but sets navigator.pointerEnabled to false.
  147. //Firefox disabled because of https://github.com/AnalyticalGraphicsInc/cesium/issues/6372
  148. hasPointerEvents = !isFirefox() && typeof PointerEvent !== 'undefined' && (!defined(theNavigator.pointerEnabled) || theNavigator.pointerEnabled);
  149. }
  150. return hasPointerEvents;
  151. }
  152. var imageRenderingValueResult;
  153. var supportsImageRenderingPixelatedResult;
  154. function supportsImageRenderingPixelated() {
  155. if (!defined(supportsImageRenderingPixelatedResult)) {
  156. var canvas = document.createElement('canvas');
  157. canvas.setAttribute('style',
  158. 'image-rendering: -moz-crisp-edges;' +
  159. 'image-rendering: pixelated;');
  160. //canvas.style.imageRendering will be undefined, null or an empty string on unsupported browsers.
  161. var tmp = canvas.style.imageRendering;
  162. supportsImageRenderingPixelatedResult = defined(tmp) && tmp !== '';
  163. if (supportsImageRenderingPixelatedResult) {
  164. imageRenderingValueResult = tmp;
  165. }
  166. }
  167. return supportsImageRenderingPixelatedResult;
  168. }
  169. function imageRenderingValue() {
  170. return supportsImageRenderingPixelated() ? imageRenderingValueResult : undefined;
  171. }
  172. function supportsWebP() {
  173. //>>includeStart('debug', pragmas.debug);
  174. if (!supportsWebP.initialized) {
  175. throw new DeveloperError('You must call FeatureDetection.supportsWebP.initialize and wait for the promise to resolve before calling FeatureDetection.supportsWebP');
  176. }
  177. //>>includeEnd('debug');
  178. return supportsWebP._result;
  179. }
  180. supportsWebP._promise = undefined;
  181. supportsWebP._result = undefined;
  182. supportsWebP.initialize = function() {
  183. // From https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_for_webp
  184. if (defined(supportsWebP._promise)) {
  185. return supportsWebP._promise;
  186. }
  187. var supportsWebPDeferred = when.defer();
  188. supportsWebP._promise = supportsWebPDeferred.promise;
  189. if (isEdge()) {
  190. // Edge's WebP support with WebGL is incomplete.
  191. // See bug report: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19221241/
  192. supportsWebP._result = false;
  193. supportsWebPDeferred.resolve(supportsWebP._result);
  194. return supportsWebPDeferred.promise;
  195. }
  196. var image = new Image();
  197. image.onload = function () {
  198. supportsWebP._result = (image.width > 0) && (image.height > 0);
  199. supportsWebPDeferred.resolve(supportsWebP._result);
  200. };
  201. image.onerror = function () {
  202. supportsWebP._result = false;
  203. supportsWebPDeferred.resolve(supportsWebP._result);
  204. };
  205. image.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';
  206. return supportsWebPDeferred.promise;
  207. };
  208. defineProperties(supportsWebP, {
  209. initialized: {
  210. get: function() {
  211. return defined(supportsWebP._result);
  212. }
  213. }
  214. });
  215. var typedArrayTypes = [];
  216. if (typeof ArrayBuffer !== 'undefined') {
  217. typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
  218. if (typeof Uint8ClampedArray !== 'undefined') {
  219. typedArrayTypes.push(Uint8ClampedArray);
  220. }
  221. if (typeof CanvasPixelArray !== 'undefined') {
  222. typedArrayTypes.push(CanvasPixelArray);
  223. }
  224. }
  225. /**
  226. * A set of functions to detect whether the current browser supports
  227. * various features.
  228. *
  229. * @exports FeatureDetection
  230. */
  231. var FeatureDetection = {
  232. isChrome : isChrome,
  233. chromeVersion : chromeVersion,
  234. isSafari : isSafari,
  235. safariVersion : safariVersion,
  236. isWebkit : isWebkit,
  237. webkitVersion : webkitVersion,
  238. isInternetExplorer : isInternetExplorer,
  239. internetExplorerVersion : internetExplorerVersion,
  240. isEdge : isEdge,
  241. edgeVersion : edgeVersion,
  242. isFirefox : isFirefox,
  243. firefoxVersion : firefoxVersion,
  244. isWindows : isWindows,
  245. hardwareConcurrency : defaultValue(theNavigator.hardwareConcurrency, 3),
  246. supportsPointerEvents : supportsPointerEvents,
  247. supportsImageRenderingPixelated: supportsImageRenderingPixelated,
  248. supportsWebP: supportsWebP,
  249. imageRenderingValue: imageRenderingValue,
  250. typedArrayTypes: typedArrayTypes
  251. };
  252. /**
  253. * Detects whether the current browser supports the full screen standard.
  254. *
  255. * @returns {Boolean} true if the browser supports the full screen standard, false if not.
  256. *
  257. * @see Fullscreen
  258. * @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}
  259. */
  260. FeatureDetection.supportsFullscreen = function() {
  261. return Fullscreen.supportsFullscreen();
  262. };
  263. /**
  264. * Detects whether the current browser supports typed arrays.
  265. *
  266. * @returns {Boolean} true if the browser supports typed arrays, false if not.
  267. *
  268. * @see {@link http://www.khronos.org/registry/typedarray/specs/latest/|Typed Array Specification}
  269. */
  270. FeatureDetection.supportsTypedArrays = function() {
  271. return typeof ArrayBuffer !== 'undefined';
  272. };
  273. /**
  274. * Detects whether the current browser supports Web Workers.
  275. *
  276. * @returns {Boolean} true if the browsers supports Web Workers, false if not.
  277. *
  278. * @see {@link http://www.w3.org/TR/workers/}
  279. */
  280. FeatureDetection.supportsWebWorkers = function() {
  281. return typeof Worker !== 'undefined';
  282. };
  283. /**
  284. * Detects whether the current browser supports Web Assembly.
  285. *
  286. * @returns {Boolean} true if the browsers supports Web Assembly, false if not.
  287. *
  288. * @see {@link https://developer.mozilla.org/en-US/docs/WebAssembly}
  289. */
  290. FeatureDetection.supportsWebAssembly = function() {
  291. return typeof WebAssembly !== 'undefined' && !FeatureDetection.isEdge();
  292. };
  293. export default FeatureDetection;