123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580 |
- // Copyright 2006 The Closure Library Authors. All Rights Reserved.
- //
- // 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.
- /**
- * @fileoverview Rendering engine detection.
- * @see <a href="http://www.useragentstring.com/">User agent strings</a>
- * For information on the browser brand (such as Safari versus Chrome), see
- * goog.userAgent.product.
- * @author arv@google.com (Erik Arvidsson)
- * @see ../demos/useragent.html
- */
- goog.provide('goog.userAgent');
- goog.require('goog.labs.userAgent.browser');
- goog.require('goog.labs.userAgent.engine');
- goog.require('goog.labs.userAgent.platform');
- goog.require('goog.labs.userAgent.util');
- goog.require('goog.reflect');
- goog.require('goog.string');
- /**
- * @define {boolean} Whether we know at compile-time that the browser is IE.
- */
- goog.define('goog.userAgent.ASSUME_IE', false);
- /**
- * @define {boolean} Whether we know at compile-time that the browser is EDGE.
- */
- goog.define('goog.userAgent.ASSUME_EDGE', false);
- /**
- * @define {boolean} Whether we know at compile-time that the browser is GECKO.
- */
- goog.define('goog.userAgent.ASSUME_GECKO', false);
- /**
- * @define {boolean} Whether we know at compile-time that the browser is WEBKIT.
- */
- goog.define('goog.userAgent.ASSUME_WEBKIT', false);
- /**
- * @define {boolean} Whether we know at compile-time that the browser is a
- * mobile device running WebKit e.g. iPhone or Android.
- */
- goog.define('goog.userAgent.ASSUME_MOBILE_WEBKIT', false);
- /**
- * @define {boolean} Whether we know at compile-time that the browser is OPERA.
- */
- goog.define('goog.userAgent.ASSUME_OPERA', false);
- /**
- * @define {boolean} Whether the
- * {@code goog.userAgent.isVersionOrHigher}
- * function will return true for any version.
- */
- goog.define('goog.userAgent.ASSUME_ANY_VERSION', false);
- /**
- * Whether we know the browser engine at compile-time.
- * @type {boolean}
- * @private
- */
- goog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE ||
- goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_GECKO ||
- goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT ||
- goog.userAgent.ASSUME_OPERA;
- /**
- * Returns the userAgent string for the current browser.
- *
- * @return {string} The userAgent string.
- */
- goog.userAgent.getUserAgentString = function() {
- return goog.labs.userAgent.util.getUserAgent();
- };
- /**
- * TODO(nnaze): Change type to "Navigator" and update compilation targets.
- * @return {?Object} The native navigator object.
- */
- goog.userAgent.getNavigator = function() {
- // Need a local navigator reference instead of using the global one,
- // to avoid the rare case where they reference different objects.
- // (in a WorkerPool, for example).
- return goog.global['navigator'] || null;
- };
- /**
- * Whether the user agent is Opera.
- * @type {boolean}
- */
- goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_OPERA :
- goog.labs.userAgent.browser.isOpera();
- /**
- * Whether the user agent is Internet Explorer.
- * @type {boolean}
- */
- goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_IE :
- goog.labs.userAgent.browser.isIE();
- /**
- * Whether the user agent is Microsoft Edge.
- * @type {boolean}
- */
- goog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_EDGE :
- goog.labs.userAgent.engine.isEdge();
- /**
- * Whether the user agent is MS Internet Explorer or MS Edge.
- * @type {boolean}
- */
- goog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE;
- /**
- * Whether the user agent is Gecko. Gecko is the rendering engine used by
- * Mozilla, Firefox, and others.
- * @type {boolean}
- */
- goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_GECKO :
- goog.labs.userAgent.engine.isGecko();
- /**
- * Whether the user agent is WebKit. WebKit is the rendering engine that
- * Safari, Android and others use.
- * @type {boolean}
- */
- goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ?
- goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT :
- goog.labs.userAgent.engine.isWebKit();
- /**
- * Whether the user agent is running on a mobile device.
- *
- * This is a separate function so that the logic can be tested.
- *
- * TODO(nnaze): Investigate swapping in goog.labs.userAgent.device.isMobile().
- *
- * @return {boolean} Whether the user agent is running on a mobile device.
- * @private
- */
- goog.userAgent.isMobile_ = function() {
- return goog.userAgent.WEBKIT &&
- goog.labs.userAgent.util.matchUserAgent('Mobile');
- };
- /**
- * Whether the user agent is running on a mobile device.
- *
- * TODO(nnaze): Consider deprecating MOBILE when labs.userAgent
- * is promoted as the gecko/webkit logic is likely inaccurate.
- *
- * @type {boolean}
- */
- goog.userAgent.MOBILE =
- goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.isMobile_();
- /**
- * Used while transitioning code to use WEBKIT instead.
- * @type {boolean}
- * @deprecated Use {@link goog.userAgent.product.SAFARI} instead.
- * TODO(nicksantos): Delete this from goog.userAgent.
- */
- goog.userAgent.SAFARI = goog.userAgent.WEBKIT;
- /**
- * @return {string} the platform (operating system) the user agent is running
- * on. Default to empty string because navigator.platform may not be defined
- * (on Rhino, for example).
- * @private
- */
- goog.userAgent.determinePlatform_ = function() {
- var navigator = goog.userAgent.getNavigator();
- return navigator && navigator.platform || '';
- };
- /**
- * The platform (operating system) the user agent is running on. Default to
- * empty string because navigator.platform may not be defined (on Rhino, for
- * example).
- * @type {string}
- */
- goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();
- /**
- * @define {boolean} Whether the user agent is running on a Macintosh operating
- * system.
- */
- goog.define('goog.userAgent.ASSUME_MAC', false);
- /**
- * @define {boolean} Whether the user agent is running on a Windows operating
- * system.
- */
- goog.define('goog.userAgent.ASSUME_WINDOWS', false);
- /**
- * @define {boolean} Whether the user agent is running on a Linux operating
- * system.
- */
- goog.define('goog.userAgent.ASSUME_LINUX', false);
- /**
- * @define {boolean} Whether the user agent is running on a X11 windowing
- * system.
- */
- goog.define('goog.userAgent.ASSUME_X11', false);
- /**
- * @define {boolean} Whether the user agent is running on Android.
- */
- goog.define('goog.userAgent.ASSUME_ANDROID', false);
- /**
- * @define {boolean} Whether the user agent is running on an iPhone.
- */
- goog.define('goog.userAgent.ASSUME_IPHONE', false);
- /**
- * @define {boolean} Whether the user agent is running on an iPad.
- */
- goog.define('goog.userAgent.ASSUME_IPAD', false);
- /**
- * @define {boolean} Whether the user agent is running on an iPod.
- */
- goog.define('goog.userAgent.ASSUME_IPOD', false);
- /**
- * @type {boolean}
- * @private
- */
- goog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC ||
- goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX ||
- goog.userAgent.ASSUME_X11 || goog.userAgent.ASSUME_ANDROID ||
- goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD ||
- goog.userAgent.ASSUME_IPOD;
- /**
- * Whether the user agent is running on a Macintosh operating system.
- * @type {boolean}
- */
- goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_MAC :
- goog.labs.userAgent.platform.isMacintosh();
- /**
- * Whether the user agent is running on a Windows operating system.
- * @type {boolean}
- */
- goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_WINDOWS :
- goog.labs.userAgent.platform.isWindows();
- /**
- * Whether the user agent is Linux per the legacy behavior of
- * goog.userAgent.LINUX, which considered ChromeOS to also be
- * Linux.
- * @return {boolean}
- * @private
- */
- goog.userAgent.isLegacyLinux_ = function() {
- return goog.labs.userAgent.platform.isLinux() ||
- goog.labs.userAgent.platform.isChromeOS();
- };
- /**
- * Whether the user agent is running on a Linux operating system.
- *
- * Note that goog.userAgent.LINUX considers ChromeOS to be Linux,
- * while goog.labs.userAgent.platform considers ChromeOS and
- * Linux to be different OSes.
- *
- * @type {boolean}
- */
- goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_LINUX :
- goog.userAgent.isLegacyLinux_();
- /**
- * @return {boolean} Whether the user agent is an X11 windowing system.
- * @private
- */
- goog.userAgent.isX11_ = function() {
- var navigator = goog.userAgent.getNavigator();
- return !!navigator &&
- goog.string.contains(navigator['appVersion'] || '', 'X11');
- };
- /**
- * Whether the user agent is running on a X11 windowing system.
- * @type {boolean}
- */
- goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_X11 :
- goog.userAgent.isX11_();
- /**
- * Whether the user agent is running on Android.
- * @type {boolean}
- */
- goog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_ANDROID :
- goog.labs.userAgent.platform.isAndroid();
- /**
- * Whether the user agent is running on an iPhone.
- * @type {boolean}
- */
- goog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_IPHONE :
- goog.labs.userAgent.platform.isIphone();
- /**
- * Whether the user agent is running on an iPad.
- * @type {boolean}
- */
- goog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_IPAD :
- goog.labs.userAgent.platform.isIpad();
- /**
- * Whether the user agent is running on an iPod.
- * @type {boolean}
- */
- goog.userAgent.IPOD = goog.userAgent.PLATFORM_KNOWN_ ?
- goog.userAgent.ASSUME_IPOD :
- goog.labs.userAgent.platform.isIpod();
- /**
- * Whether the user agent is running on iOS.
- * @type {boolean}
- */
- goog.userAgent.IOS = goog.userAgent.PLATFORM_KNOWN_ ?
- (goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD ||
- goog.userAgent.ASSUME_IPOD) :
- goog.labs.userAgent.platform.isIos();
- /**
- * @return {string} The string that describes the version number of the user
- * agent.
- * @private
- */
- goog.userAgent.determineVersion_ = function() {
- // All browsers have different ways to detect the version and they all have
- // different naming schemes.
- // version is a string rather than a number because it may contain 'b', 'a',
- // and so on.
- var version = '';
- var arr = goog.userAgent.getVersionRegexResult_();
- if (arr) {
- version = arr ? arr[1] : '';
- }
- if (goog.userAgent.IE) {
- // IE9 can be in document mode 9 but be reporting an inconsistent user agent
- // version. If it is identifying as a version lower than 9 we take the
- // documentMode as the version instead. IE8 has similar behavior.
- // It is recommended to set the X-UA-Compatible header to ensure that IE9
- // uses documentMode 9.
- var docMode = goog.userAgent.getDocumentMode_();
- if (docMode != null && docMode > parseFloat(version)) {
- return String(docMode);
- }
- }
- return version;
- };
- /**
- * @return {?Array|undefined} The version regex matches from parsing the user
- * agent string. These regex statements must be executed inline so they can
- * be compiled out by the closure compiler with the rest of the useragent
- * detection logic when ASSUME_* is specified.
- * @private
- */
- goog.userAgent.getVersionRegexResult_ = function() {
- var userAgent = goog.userAgent.getUserAgentString();
- if (goog.userAgent.GECKO) {
- return /rv\:([^\);]+)(\)|;)/.exec(userAgent);
- }
- if (goog.userAgent.EDGE) {
- return /Edge\/([\d\.]+)/.exec(userAgent);
- }
- if (goog.userAgent.IE) {
- return /\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(userAgent);
- }
- if (goog.userAgent.WEBKIT) {
- // WebKit/125.4
- return /WebKit\/(\S+)/.exec(userAgent);
- }
- if (goog.userAgent.OPERA) {
- // If none of the above browsers were detected but the browser is Opera, the
- // only string that is of interest is 'Version/<number>'.
- return /(?:Version)[ \/]?(\S+)/.exec(userAgent);
- }
- return undefined;
- };
- /**
- * @return {number|undefined} Returns the document mode (for testing).
- * @private
- */
- goog.userAgent.getDocumentMode_ = function() {
- // NOTE(user): goog.userAgent may be used in context where there is no DOM.
- var doc = goog.global['document'];
- return doc ? doc['documentMode'] : undefined;
- };
- /**
- * The version of the user agent. This is a string because it might contain
- * 'b' (as in beta) as well as multiple dots.
- * @type {string}
- */
- goog.userAgent.VERSION = goog.userAgent.determineVersion_();
- /**
- * Compares two version numbers.
- *
- * @param {string} v1 Version of first item.
- * @param {string} v2 Version of second item.
- *
- * @return {number} 1 if first argument is higher
- * 0 if arguments are equal
- * -1 if second argument is higher.
- * @deprecated Use goog.string.compareVersions.
- */
- goog.userAgent.compare = function(v1, v2) {
- return goog.string.compareVersions(v1, v2);
- };
- /**
- * Cache for {@link goog.userAgent.isVersionOrHigher}.
- * Calls to compareVersions are surprisingly expensive and, as a browser's
- * version number is unlikely to change during a session, we cache the results.
- * @const
- * @private
- */
- goog.userAgent.isVersionOrHigherCache_ = {};
- /**
- * Whether the user agent version is higher or the same as the given version.
- * NOTE: When checking the version numbers for Firefox and Safari, be sure to
- * use the engine's version, not the browser's version number. For example,
- * Firefox 3.0 corresponds to Gecko 1.9 and Safari 3.0 to Webkit 522.11.
- * Opera and Internet Explorer versions match the product release number.<br>
- * @see <a href="http://en.wikipedia.org/wiki/Safari_version_history">
- * Webkit</a>
- * @see <a href="http://en.wikipedia.org/wiki/Gecko_engine">Gecko</a>
- *
- * @param {string|number} version The version to check.
- * @return {boolean} Whether the user agent version is higher or the same as
- * the given version.
- */
- goog.userAgent.isVersionOrHigher = function(version) {
- return goog.userAgent.ASSUME_ANY_VERSION ||
- goog.reflect.cache(
- goog.userAgent.isVersionOrHigherCache_, version, function() {
- return goog.string.compareVersions(
- goog.userAgent.VERSION, version) >= 0;
- });
- };
- /**
- * Deprecated alias to {@code goog.userAgent.isVersionOrHigher}.
- * @param {string|number} version The version to check.
- * @return {boolean} Whether the user agent version is higher or the same as
- * the given version.
- * @deprecated Use goog.userAgent.isVersionOrHigher().
- */
- goog.userAgent.isVersion = goog.userAgent.isVersionOrHigher;
- /**
- * Whether the IE effective document mode is higher or the same as the given
- * document mode version.
- * NOTE: Only for IE, return false for another browser.
- *
- * @param {number} documentMode The document mode version to check.
- * @return {boolean} Whether the IE effective document mode is higher or the
- * same as the given version.
- */
- goog.userAgent.isDocumentModeOrHigher = function(documentMode) {
- return Number(goog.userAgent.DOCUMENT_MODE) >= documentMode;
- };
- /**
- * Deprecated alias to {@code goog.userAgent.isDocumentModeOrHigher}.
- * @param {number} version The version to check.
- * @return {boolean} Whether the IE effective document mode is higher or the
- * same as the given version.
- * @deprecated Use goog.userAgent.isDocumentModeOrHigher().
- */
- goog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher;
- /**
- * For IE version < 7, documentMode is undefined, so attempt to use the
- * CSS1Compat property to see if we are in standards mode. If we are in
- * standards mode, treat the browser version as the document mode. Otherwise,
- * IE is emulating version 5.
- * @type {number|undefined}
- * @const
- */
- goog.userAgent.DOCUMENT_MODE = (function() {
- var doc = goog.global['document'];
- var mode = goog.userAgent.getDocumentMode_();
- if (!doc || !goog.userAgent.IE) {
- return undefined;
- }
- return mode || (doc['compatMode'] == 'CSS1Compat' ?
- parseInt(goog.userAgent.VERSION, 10) :
- 5);
- })();
|