browser.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * noVNC: HTML5 VNC client
  3. * Copyright (C) 2019 The noVNC Authors
  4. * Licensed under MPL 2.0 (see LICENSE.txt)
  5. *
  6. * See README.md for usage and integration instructions.
  7. *
  8. * Browser feature support detection
  9. */
  10. import * as Log from './logging.js';
  11. // Touch detection
  12. export let isTouchDevice = ('ontouchstart' in document.documentElement) ||
  13. // requried for Chrome debugger
  14. (document.ontouchstart !== undefined) ||
  15. // required for MS Surface
  16. (navigator.maxTouchPoints > 0) ||
  17. (navigator.msMaxTouchPoints > 0);
  18. window.addEventListener('touchstart', function onFirstTouch() {
  19. isTouchDevice = true;
  20. window.removeEventListener('touchstart', onFirstTouch, false);
  21. }, false);
  22. // The goal is to find a certain physical width, the devicePixelRatio
  23. // brings us a bit closer but is not optimal.
  24. export let dragThreshold = 10 * (window.devicePixelRatio || 1);
  25. let _supportsCursorURIs = false;
  26. try {
  27. const target = document.createElement('canvas');
  28. target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default';
  29. if (target.style.cursor.indexOf("url") === 0) {
  30. Log.Info("Data URI scheme cursor supported");
  31. _supportsCursorURIs = true;
  32. } else {
  33. Log.Warn("Data URI scheme cursor not supported");
  34. }
  35. } catch (exc) {
  36. Log.Error("Data URI scheme cursor test exception: " + exc);
  37. }
  38. export const supportsCursorURIs = _supportsCursorURIs;
  39. let _hasScrollbarGutter = true;
  40. try {
  41. // Create invisible container
  42. const container = document.createElement('div');
  43. container.style.visibility = 'hidden';
  44. container.style.overflow = 'scroll'; // forcing scrollbars
  45. document.body.appendChild(container);
  46. // Create a div and place it in the container
  47. const child = document.createElement('div');
  48. container.appendChild(child);
  49. // Calculate the difference between the container's full width
  50. // and the child's width - the difference is the scrollbars
  51. const scrollbarWidth = (container.offsetWidth - child.offsetWidth);
  52. // Clean up
  53. container.parentNode.removeChild(container);
  54. _hasScrollbarGutter = scrollbarWidth != 0;
  55. } catch (exc) {
  56. Log.Error("Scrollbar test exception: " + exc);
  57. }
  58. export const hasScrollbarGutter = _hasScrollbarGutter;
  59. /*
  60. * The functions for detection of platforms and browsers below are exported
  61. * but the use of these should be minimized as much as possible.
  62. *
  63. * It's better to use feature detection than platform detection.
  64. */
  65. /* OS */
  66. export function isMac() {
  67. return !!(/mac/i).exec(navigator.platform);
  68. }
  69. export function isWindows() {
  70. return !!(/win/i).exec(navigator.platform);
  71. }
  72. export function isIOS() {
  73. return (!!(/ipad/i).exec(navigator.platform) ||
  74. !!(/iphone/i).exec(navigator.platform) ||
  75. !!(/ipod/i).exec(navigator.platform));
  76. }
  77. export function isAndroid() {
  78. /* Android sets navigator.platform to Linux :/ */
  79. return !!navigator.userAgent.match('Android ');
  80. }
  81. export function isChromeOS() {
  82. /* ChromeOS sets navigator.platform to Linux :/ */
  83. return !!navigator.userAgent.match(' CrOS ');
  84. }
  85. /* Browser */
  86. export function isSafari() {
  87. return !!navigator.userAgent.match('Safari/...') &&
  88. !navigator.userAgent.match('Chrome/...') &&
  89. !navigator.userAgent.match('Chromium/...') &&
  90. !navigator.userAgent.match('Epiphany/...');
  91. }
  92. export function isFirefox() {
  93. return !!navigator.userAgent.match('Firefox/...') &&
  94. !navigator.userAgent.match('Seamonkey/...');
  95. }
  96. export function isChrome() {
  97. return !!navigator.userAgent.match('Chrome/...') &&
  98. !navigator.userAgent.match('Chromium/...') &&
  99. !navigator.userAgent.match('Edg/...') &&
  100. !navigator.userAgent.match('OPR/...');
  101. }
  102. export function isChromium() {
  103. return !!navigator.userAgent.match('Chromium/...');
  104. }
  105. export function isOpera() {
  106. return !!navigator.userAgent.match('OPR/...');
  107. }
  108. export function isEdge() {
  109. return !!navigator.userAgent.match('Edg/...');
  110. }
  111. /* Engine */
  112. export function isGecko() {
  113. return !!navigator.userAgent.match('Gecko/...');
  114. }
  115. export function isWebKit() {
  116. return !!navigator.userAgent.match('AppleWebKit/...') &&
  117. !navigator.userAgent.match('Chrome/...');
  118. }
  119. export function isBlink() {
  120. return !!navigator.userAgent.match('Chrome/...');
  121. }