// Copyright 2006 Google Inc. // All Rights Reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in // the documentation and/or other materials provided with the // distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. /** * @fileoverview Rendering engine detection. * @see User agent strings * For information on the browser brand (such as Safari versus Chrome), see * goog.userAgent.product. */ goog.provide('goog.userAgent'); goog.require('goog.string'); /** * @define {boolean} Whether we know at compile-time that the browser is IE. */ goog.userAgent.ASSUME_IE = false; /** * @define {boolean} Whether we know at compile-time that the browser is GECKO. */ goog.userAgent.ASSUME_GECKO = false; /** * @define {boolean} Whether we know at compile-time that the browser is CAMINO. * @deprecated Use goog.userAgent.product.ASSUME_CAMINO instead. */ goog.userAgent.ASSUME_CAMINO = false; /** * @define {boolean} Whether we know at compile-time that the browser is WEBKIT. */ 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.userAgent.ASSUME_MOBILE_WEBKIT = false; /** * @define {boolean} Whether we know at compile-time that the browser is OPERA. */ goog.userAgent.ASSUME_OPERA = false; /** * Whether we know the browser engine at compile-time. * @type {boolean} * @private */ goog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE || goog.userAgent.ASSUME_GECKO || goog.userAgent.ASSUME_CAMINO || goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_OPERA; /** * Returns the userAgent string for the current browser. * Some user agents (I'm thinking of you, Gears WorkerPool) do not expose a * navigator object off the global scope. In that case we return null. * * @return {string?} The userAgent string or null if there is none. */ goog.userAgent.getUserAgentString = function() { return goog.global['navigator'] ? goog.global['navigator'].userAgent : null; }; /** * @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. // (goog.gears.FakeWorkerPool, for example). return goog.global['navigator']; }; /** * Initializer for goog.userAgent. * * This is a named function so that it can be stripped via the jscompiler * option for stripping types. * @private */ goog.userAgent.init_ = function() { /** * Whether the user agent string denotes Opera. * @type {boolean} * @private */ goog.userAgent.detectedOpera_ = false; /** * Whether the user agent string denotes Internet Explorer. This includes * other browsers using Trident as its rendering engine. For example AOL * and Netscape 8 * @type {boolean} * @private */ goog.userAgent.detectedIe_ = false; /** * Whether the user agent string denotes WebKit. WebKit is the rendering * engine that Safari, Android and others use. * @type {boolean} * @private */ goog.userAgent.detectedWebkit_ = false; /** * Whether the user agent string denotes a mobile device. * @type {boolean} * @private */ goog.userAgent.detectedMobile_ = false; /** * Whether the user agent string denotes Gecko. Gecko is the rendering * engine used by Mozilla, Mozilla Firefox, Camino and many more. * @type {boolean} * @private */ goog.userAgent.detectedGecko_ = false; /** * Whether the user agent is Camino. * @type {boolean} */ goog.userAgent.detectedCamino_ = false; var ua; if (!goog.userAgent.BROWSER_KNOWN_ && (ua = goog.userAgent.getUserAgentString())) { var navigator = goog.userAgent.getNavigator(); goog.userAgent.detectedOpera_ = ua.indexOf('Opera') == 0; goog.userAgent.detectedIe_ = !goog.userAgent.detectedOpera_ && ua.indexOf('MSIE') != -1; goog.userAgent.detectedWebkit_ = !goog.userAgent.detectedOpera_ && ua.indexOf('WebKit') != -1; // WebKit also gives navigator.product string equal to 'Gecko'. goog.userAgent.detectedMobile_ = goog.userAgent.detectedWebkit_ && ua.indexOf('Mobile') != -1; goog.userAgent.detectedGecko_ = !goog.userAgent.detectedOpera_ && !goog.userAgent.detectedWebkit_ && navigator.product == 'Gecko'; goog.userAgent.detectedCamino_ = goog.userAgent.detectedGecko_ && navigator.vendor == 'Camino'; } }; if (!goog.userAgent.BROWSER_KNOWN_) { goog.userAgent.init_(); } /** * Whether the user agent is Opera. * @type {boolean} */ goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_OPERA : goog.userAgent.detectedOpera_; /** * Whether the user agent is Internet Explorer. This includes other browsers * using Trident as its rendering engine. For example AOL and Netscape 8 * @type {boolean} */ goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_IE : goog.userAgent.detectedIe_; /** * Whether the user agent is Gecko. Gecko is the rendering engine used by * Mozilla, Mozilla Firefox, Camino and many more. * @type {boolean} */ goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_GECKO || goog.userAgent.ASSUME_CAMINO : goog.userAgent.detectedGecko_; /** * Whether the user agent is Camino. * @type {boolean} * @deprecated Use {@link goog.userAgent.product.CAMINO} instead. */ goog.userAgent.CAMINO = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_CAMINO : goog.userAgent.detectedCamino_; /** * 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.userAgent.detectedWebkit_; /** * Whether the user agent is running on a mobile device. * @type {boolean} */ goog.userAgent.MOBILE = goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.detectedMobile_; /** * Used while transitioning code to use WEBKIT instead. * @type {boolean} * @deprecated Use {@link goog.userAgent.product.SAFARI} instead. */ 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.userAgent.ASSUME_MAC = false; /** * @define {boolean} Whether the user agent is running on a Windows operating * system. */ goog.userAgent.ASSUME_WINDOWS = false; /** * @define {boolean} Whether the user agent is running on a Linux operating * system. */ goog.userAgent.ASSUME_LINUX = false; /** * @type {boolean} * @private */ goog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC || goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX; /** * Initialize the goog.userAgent constants that define which platform the user * agent is running on. * @private */ goog.userAgent.initPlatform_ = function() { /** * Whether the user agent is running on a Macintosh operating system. * @type {boolean} */ goog.userAgent.detectedMac_ = goog.string.contains(goog.userAgent.PLATFORM, 'Mac'); /** * Whether the user agent is running on a Windows operating system. * @type {boolean} */ goog.userAgent.detectedWindows_ = goog.string.contains( goog.userAgent.PLATFORM, 'Win'); /** * Whether the user agent is running on a Linux operating system. * @type {boolean} */ goog.userAgent.detectedLinux_ = goog.string.contains(goog.userAgent.PLATFORM, 'Linux'); }; if (!goog.userAgent.PLATFORM_KNOWN_) { goog.userAgent.initPlatform_(); } /** * 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.userAgent.detectedMac_; /** * 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.userAgent.detectedWindows_; /** * Whether the user agent is running on a Linux operating system. * @type {boolean} */ goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_LINUX : goog.userAgent.detectedLinux_; /** * @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 = '', re; // goog.userAgent.X and goog.userAgent.DETECTED_X_ are both checked so this // code can be tested in useragent_test.html but also be compiled efficiently // as verified in CompileUserAgentTest.java. if (goog.userAgent.OPERA && goog.global['opera']) { var operaVersion = goog.global['opera'].version; version = typeof operaVersion == 'function' ? operaVersion() : operaVersion; } else { if (goog.userAgent.GECKO) { re = /rv\:([^\);]+)(\)|;)/; } else if (goog.userAgent.IE) { re = /MSIE\s+([^\);]+)(\)|;)/; } else if (goog.userAgent.WEBKIT) { // WebKit/125.4 re = /WebKit\/(\S+)/; } if (re) { var arr = re.exec(goog.userAgent.getUserAgentString()); version = arr ? arr[1] : ''; } } return version; }; /** * 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.isVersion}. Calls to compareVersions are * surprisingly expensive and as a browsers version number is unlikely to change * during a session we cache the results. * @type {Object} * @private */ goog.userAgent.isVersionCache_ = {}; /** * 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.
* @see Webkit * @see Gecko * * @param {string} version The version to check. * @return {boolean} Whether the user agent version is higher or the same as * the given version. */ goog.userAgent.isVersion = function(version) { return goog.userAgent.isVersionCache_[version] || (goog.userAgent.isVersionCache_[version] = goog.string.compareVersions(goog.userAgent.VERSION, version) >= 0); };