# 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 | */
22 | goog.provide('bot.userAgent');
23 |
24 | goog.require('goog.string');
25 | goog.require('goog.userAgent');
26 | goog.require('goog.userAgent.product');
27 | goog.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 | */
44 | bot.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 | */
70 | bot.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 | */
88 | bot.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 | */
97 | bot.userAgent.FIREFOX_EXTENSION_IS_PRODUCT_VERSION_;
98 |
99 |
100 | /**
101 | * Whether we are in a Firefox extension.
102 | *
103 | * @const
104 | * @type {boolean}
105 | */
106 | bot.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 | */
152 | bot.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 | */
162 | bot.userAgent.MOBILE = bot.userAgent.IOS || goog.userAgent.product.ANDROID;
163 |
164 |
165 | /**
166 | * Android Operating System Version.
167 | * @private {string}
168 | * @const
169 | */
170 | bot.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 | */
186 | bot.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 | */
195 | bot.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 | */
203 | bot.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 | */
212 | bot.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 | */
220 | bot.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 | */
229 | bot.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 | */
238 | bot.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 | */
247 | bot.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 | */
256 | bot.userAgent.WINDOWS_PHONE = goog.userAgent.IE &&
257 | goog.userAgent.getUserAgentString().indexOf('IEMobile') != -1;