FeatureDetection.js 9.7 KB

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