Source: lib/device/webkit_stb.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2025 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.device.WebKitSTB');
  7. goog.require('shaka.device.AbstractDevice');
  8. goog.require('shaka.device.DeviceFactory');
  9. goog.require('shaka.device.IDevice');
  10. goog.require('shaka.util.Lazy');
  11. /**
  12. * @final
  13. */
  14. shaka.device.WebKitSTB = class extends shaka.device.AbstractDevice {
  15. constructor() {
  16. super();
  17. /**
  18. * SkyQ STB
  19. *
  20. * @private {!shaka.util.Lazy<boolean>}
  21. */
  22. this.isSkyQ_ = new shaka.util.Lazy(() => {
  23. return navigator.userAgent.includes('DT_STB_BCM');
  24. });
  25. /** @private {!shaka.util.Lazy<?number>} */
  26. this.version_ = new shaka.util.Lazy(() => {
  27. if (navigator.userAgent.includes('DT_STB_BCM')) {
  28. return 11;
  29. }
  30. // This works for iOS Safari and desktop Safari, which contain something
  31. // like "Version/13.0" indicating the major Safari or iOS version.
  32. let match = navigator.userAgent.match(/Version\/(\d+)/);
  33. if (match) {
  34. return parseInt(match[1], /* base= */ 10);
  35. }
  36. // This works for all other browsers on iOS, which contain something like
  37. // "OS 13_3" indicating the major & minor iOS version.
  38. match = navigator.userAgent.match(/OS (\d+)(?:_\d+)?/);
  39. if (match) {
  40. return parseInt(match[1], /* base= */ 10);
  41. }
  42. return null;
  43. });
  44. }
  45. /**
  46. * @override
  47. */
  48. getVersion() {
  49. return this.version_.value();
  50. }
  51. /**
  52. * @override
  53. */
  54. getDeviceName() {
  55. return 'WebKit STB';
  56. }
  57. /**
  58. * @override
  59. */
  60. getDeviceType() {
  61. return shaka.device.IDevice.DeviceType.TV;
  62. }
  63. /**
  64. * @override
  65. */
  66. getBrowserEngine() {
  67. return shaka.device.IDevice.BrowserEngine.WEBKIT;
  68. }
  69. /**
  70. * @override
  71. */
  72. supportsMediaCapabilities() {
  73. return false;
  74. }
  75. /**
  76. * @override
  77. */
  78. supportsSequenceMode() {
  79. // See: https://bugs.webkit.org/show_bug.cgi?id=210341
  80. const version = this.version_.value();
  81. return version !== null ? version >= 15 : true;
  82. }
  83. /**
  84. * @override
  85. */
  86. detectMaxHardwareResolution() {
  87. const maxResolution = {
  88. width: window.screen.width * window.devicePixelRatio,
  89. height: window.screen.height * window.devicePixelRatio,
  90. };
  91. return Promise.resolve(maxResolution);
  92. }
  93. /**
  94. * @override
  95. */
  96. supportsEncryptionSchemePolyfill() {
  97. return !this.isSkyQ_.value();
  98. }
  99. /**
  100. * @return {boolean}
  101. * @private
  102. */
  103. static isWebkitSTB_() {
  104. if (navigator.userAgent.includes('DT_STB_BCM') ||
  105. navigator.userAgent.includes('DT_STB_BCM')) {
  106. return true;
  107. }
  108. if (!(navigator.vendor || '').includes('Apple')) {
  109. return false;
  110. }
  111. if (/(?:iPhone|iPad|iPod)/.test(navigator.userAgent) ||
  112. navigator.maxTouchPoints > 1) {
  113. return false;
  114. }
  115. if (navigator.userAgentData && navigator.userAgentData.platform &&
  116. navigator.userAgentData.platform.toLowerCase() == 'macos') {
  117. return false;
  118. } else if (navigator.platform &&
  119. navigator.platform.toLowerCase().includes('mac')) {
  120. return false;
  121. }
  122. return true;
  123. }
  124. };
  125. if (shaka.device.WebKitSTB.isWebkitSTB_()) {
  126. shaka.device.DeviceFactory.registerDeviceFactory(
  127. () => new shaka.device.WebKitSTB());
  128. }