/**
* @license
* Copyright 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
goog.provide('shaka.util.Platform');
goog.require('shaka.util.Timer');
/**
* A wrapper for platform-specific functions.
*
* @final
*/
shaka.util.Platform = class {
/**
* Check if the current platform supports media source. We assume that if
* the current platform supports media source, then we can use media source
* as per its design.
*
* @return {boolean}
*/
static supportsMediaSource() {
// Browsers that lack a media source implementation will have no reference
// to |window.MediaSource|. Platforms that we see having problematic media
// source implementations will have this reference removed via a polyfill.
if (!window.MediaSource) {
return false;
}
// Some very old MediaSource implementations didn't have isTypeSupported.
if (!MediaSource.isTypeSupported) {
return false;
}
return true;
}
/**
* Returns true if the media type is supported natively by the platform.
*
* @param {string} mimeType
* @return {boolean}
*/
static supportsMediaType(mimeType) {
const video = shaka.util.Platform.anyMediaElement_();
return video.canPlayType(mimeType) != '';
}
/**
* Check if the current platform is MS Edge.
*
* @return {boolean}
*/
static isEdge() {
return shaka.util.Platform.userAgentContains_('Edge/');
}
/**
* Check if the current platform is MS IE.
*
* @return {boolean}
*/
static isIE() {
return shaka.util.Platform.userAgentContains_('Trident/');
}
/**
* Check if the current platform is a Tizen TV.
*
* @return {boolean}
*/
static isTizen() {
return shaka.util.Platform.userAgentContains_('Tizen');
}
/**
* Check if the current platform is a Tizen 3 TV.
*
* @return {boolean}
*/
static isTizen3() {
return shaka.util.Platform.userAgentContains_('Tizen 3');
}
/**
* Check if the current platform is a WebOS.
*
* @return {boolean}
*/
static isWebOS() {
return shaka.util.Platform.userAgentContains_('Web0S');
}
/**
* Check if the current platform is a Google Chromecast.
*
* @return {boolean}
*/
static isChromecast() {
return shaka.util.Platform.userAgentContains_('CrKey');
}
/**
* Check if the current platform is Google Chrome.
*
* @return {boolean}
*/
static isChrome() {
// The Edge user agent will also contain the "Chrome" keyword, so we need
// to make sure this is not Edge.
return shaka.util.Platform.userAgentContains_('Chrome') &&
!shaka.util.Platform.isEdge();
}
/**
* Check if the current platform is an Apple device (iOS, desktop Safari, etc)
*
* @return {boolean}
*/
static isApple() {
return !!navigator.vendor && navigator.vendor.includes('Apple');
}
/**
* Guesses if the platform is a mobile one (iOS or Android).
*
* @return {boolean}
*/
static isMobile() {
return /(?:iPhone|iPad|iPod|Android)/.test(navigator.userAgent);
}
/**
* Check if the user agent contains a key. This is the best way we know of
* right now to detect platforms. If there is a better way, please send a
* PR.
*
* @param {string} key
* @return {boolean}
* @private
*/
static userAgentContains_(key) {
const userAgent = navigator.userAgent || '';
return userAgent.includes(key);
}
/**
* For canPlayType queries, we just need any instance.
*
* First, use a cached element from a previous query.
* Second, search the page for one.
* Third, create a temporary one.
*
* Cached elements expire in one second so that they can be GC'd or removed.
*
* @return {!HTMLMediaElement}
*/
static anyMediaElement_() {
const Platform = shaka.util.Platform;
if (Platform.cachedMediaElement_) {
return Platform.cachedMediaElement_;
}
if (!Platform.cacheExpirationTimer_) {
Platform.cacheExpirationTimer_ = new shaka.util.Timer(() => {
Platform.cachedMediaElement_ = null;
});
}
Platform.cachedMediaElement_ = /** @type {HTMLMediaElement} */(
document.querySelector('video') || document.querySelector('audio'));
if (!Platform.cachedMediaElement_) {
Platform.cachedMediaElement_ = /** @type {!HTMLMediaElement} */(
document.createElement('video'));
}
Platform.cacheExpirationTimer_.tickAfter(/* seconds= */ 1);
return Platform.cachedMediaElement_;
}
};
/** @private {shaka.util.Timer} */
shaka.util.Platform.cacheExpirationTimer_ = null;
/** @private {HTMLMediaElement} */
shaka.util.Platform.cachedMediaElement_ = null;