lib/atoms/userAgent.js

1// Licensed to the Software Freedom Conservancy (SFC) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The SFC licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18/**
19 * @fileoverview Similar to goog.userAgent.isVersion, but with support for
20 * getting the version information when running in a firefox extension.
21 */
22goog.provide('bot.userAgent');
23
24goog.require('goog.string');
25goog.require('goog.userAgent');
26goog.require('goog.userAgent.product');
27goog.require('goog.userAgent.product.isVersion');
28
29
30/**
31 * Whether the rendering engine version of the current browser is equal to or
32 * greater than the given version. This implementation differs from
33 * goog.userAgent.isVersion in the following ways:
34 * <ol>
35 * <li>in a Firefox extension, tests the engine version through the XUL version
36 * comparator service, because no window.navigator object is available
37 * <li>in IE, compares the given version to the current documentMode
38 * </ol>
39 *
40 * @param {string|number} version The version number to check.
41 * @return {boolean} Whether the browser engine version is the same or higher
42 * than the given version.
43 */
44bot.userAgent.isEngineVersion = function(version) {
45 if (bot.userAgent.FIREFOX_EXTENSION) {
46 return bot.userAgent.FIREFOX_EXTENSION_IS_ENGINE_VERSION_(version);
47 } else if (goog.userAgent.IE) {
48 return goog.string.compareVersions(
49 /** @type {number} */ (goog.userAgent.DOCUMENT_MODE), version) >= 0;
50 } else {
51 return goog.userAgent.isVersionOrHigher(version);
52 }
53};
54
55
56/**
57 * Whether the product version of the current browser is equal to or greater
58 * than the given version. This implementation differs from
59 * goog.userAgent.product.isVersion in the following ways:
60 * <ol>
61 * <li>in a Firefox extension, tests the product version through the XUL version
62 * comparator service, because no window.navigator object is available
63 * <li>on Android, always compares to the version to the OS version
64 * </ol>
65 *
66 * @param {string|number} version The version number to check.
67 * @return {boolean} Whether the browser product version is the same or higher
68 * than the given version.
69 */
70bot.userAgent.isProductVersion = function(version) {
71 if (bot.userAgent.FIREFOX_EXTENSION) {
72 return bot.userAgent.FIREFOX_EXTENSION_IS_PRODUCT_VERSION_(version);
73 } else if (goog.userAgent.product.ANDROID) {
74 return goog.string.compareVersions(
75 bot.userAgent.ANDROID_VERSION_, version) >= 0;
76 } else {
77 return goog.userAgent.product.isVersion(version);
78 }
79};
80
81
82/**
83 * When we are in a Firefox extension, this is a function that accepts a version
84 * and returns whether the version of Gecko we are on is the same or higher
85 * than the given version. When we are not in a Firefox extension, this is null.
86 * @private {(undefined|function((string|number)): boolean)}
87 */
88bot.userAgent.FIREFOX_EXTENSION_IS_ENGINE_VERSION_;
89
90
91/**
92 * When we are in a Firefox extension, this is a function that accepts a version
93 * and returns whether the version of Firefox we are on is the same or higher
94 * than the given version. When we are not in a Firefox extension, this is null.
95 * @private {(undefined|function((string|number)): boolean)}
96 */
97bot.userAgent.FIREFOX_EXTENSION_IS_PRODUCT_VERSION_;
98
99
100/**
101 * Whether we are in a Firefox extension.
102 *
103 * @const
104 * @type {boolean}
105 */
106bot.userAgent.FIREFOX_EXTENSION = (function() {
107 // False if this browser is not a Gecko browser.
108 if (!goog.userAgent.GECKO) {
109 return false;
110 }
111
112 // False if this code isn't running in an extension.
113 var Components = goog.global.Components;
114 if (!Components) {
115 return false;
116 }
117 try {
118 if (!Components['classes']) {
119 return false;
120 }
121 } catch (e) {
122 return false;
123 }
124
125 // Populate the version checker functions.
126 var cc = Components['classes'];
127 var ci = Components['interfaces'];
128 var versionComparator = cc['@mozilla.org/xpcom/version-comparator;1'][
129 'getService'](ci['nsIVersionComparator']);
130 var appInfo = cc['@mozilla.org/xre/app-info;1']['getService'](
131 ci['nsIXULAppInfo']);
132 var geckoVersion = appInfo['platformVersion'];
133 var firefoxVersion = appInfo['version'];
134
135 bot.userAgent.FIREFOX_EXTENSION_IS_ENGINE_VERSION_ = function(version) {
136 return versionComparator.compare(geckoVersion, '' + version) >= 0;
137 };
138 bot.userAgent.FIREFOX_EXTENSION_IS_PRODUCT_VERSION_ = function(version) {
139 return versionComparator.compare(firefoxVersion, '' + version) >= 0;
140 };
141
142 return true;
143})();
144
145
146/**
147 * Whether we are on IOS.
148 *
149 * @const
150 * @type {boolean}
151 */
152bot.userAgent.IOS = goog.userAgent.product.IPAD ||
153 goog.userAgent.product.IPHONE;
154
155
156/**
157 * Whether we are on a mobile browser.
158 *
159 * @const
160 * @type {boolean}
161 */
162bot.userAgent.MOBILE = bot.userAgent.IOS || goog.userAgent.product.ANDROID;
163
164
165/**
166 * Android Operating System Version.
167 * @private {string}
168 * @const
169 */
170bot.userAgent.ANDROID_VERSION_ = (function() {
171 if (goog.userAgent.product.ANDROID) {
172 var userAgentString = goog.userAgent.getUserAgentString();
173 var match = /Android\s+([0-9\.]+)/.exec(userAgentString);
174 return match ? match[1] : '0';
175 } else {
176 return '0';
177 }
178})();
179
180
181/**
182 * Whether the current document is IE in a documentMode older than 8.
183 * @type {boolean}
184 * @const
185 */
186bot.userAgent.IE_DOC_PRE8 = goog.userAgent.IE &&
187 !goog.userAgent.isDocumentModeOrHigher(8);
188
189
190/**
191 * Whether the current document is IE in IE9 (or newer) standards mode.
192 * @type {boolean}
193 * @const
194 */
195bot.userAgent.IE_DOC_9 = goog.userAgent.isDocumentModeOrHigher(9);
196
197
198/**
199 * Whether the current document is IE in a documentMode older than 9.
200 * @type {boolean}
201 * @const
202 */
203bot.userAgent.IE_DOC_PRE9 = goog.userAgent.IE &&
204 !goog.userAgent.isDocumentModeOrHigher(9);
205
206
207/**
208 * Whether the current document is IE in IE10 (or newer) standards mode.
209 * @type {boolean}
210 * @const
211 */
212bot.userAgent.IE_DOC_10 = goog.userAgent.isDocumentModeOrHigher(10);
213
214
215/**
216 * Whether the current document is IE in a documentMode older than 10.
217 * @type {boolean}
218 * @const
219 */
220bot.userAgent.IE_DOC_PRE10 = goog.userAgent.IE &&
221 !goog.userAgent.isDocumentModeOrHigher(10);
222
223
224/**
225 * Whether the current browser is Android pre-gingerbread.
226 * @type {boolean}
227 * @const
228 */
229bot.userAgent.ANDROID_PRE_GINGERBREAD = goog.userAgent.product.ANDROID &&
230 !bot.userAgent.isProductVersion(2.3);
231
232
233/**
234 * Whether the current browser is Android pre-icecreamsandwich
235 * @type {boolean}
236 * @const
237 */
238bot.userAgent.ANDROID_PRE_ICECREAMSANDWICH = goog.userAgent.product.ANDROID &&
239 !bot.userAgent.isProductVersion(4);
240
241
242/**
243 * Whether the current browser is Safari 6.
244 * @type {boolean}
245 * @const
246 */
247bot.userAgent.SAFARI_6 = goog.userAgent.product.SAFARI &&
248 bot.userAgent.isProductVersion(6);
249
250
251/**
252 * Whether the current browser is Windows Phone.
253 * @type {boolean}
254 * @const
255 */
256bot.userAgent.WINDOWS_PHONE = goog.userAgent.IE &&
257 goog.userAgent.getUserAgentString().indexOf('IEMobile') != -1;