metamask-onboarding.bundle.js 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462
  1. var MetaMaskOnboarding = (function () {
  2. 'use strict';
  3. /*! *****************************************************************************
  4. Copyright (c) Microsoft Corporation.
  5. Permission to use, copy, modify, and/or distribute this software for any
  6. purpose with or without fee is hereby granted.
  7. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  8. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  12. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. PERFORMANCE OF THIS SOFTWARE.
  14. ***************************************************************************** */
  15. function __awaiter(thisArg, _arguments, P, generator) {
  16. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  17. return new (P || (P = Promise))(function (resolve, reject) {
  18. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  19. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  20. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  21. step((generator = generator.apply(thisArg, _arguments || [])).next());
  22. });
  23. }
  24. function __generator(thisArg, body) {
  25. var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  26. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  27. function verb(n) { return function (v) { return step([n, v]); }; }
  28. function step(op) {
  29. if (f) throw new TypeError("Generator is already executing.");
  30. while (_) try {
  31. if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  32. if (y = 0, t) op = [op[0] & 2, t.value];
  33. switch (op[0]) {
  34. case 0: case 1: t = op; break;
  35. case 4: _.label++; return { value: op[1], done: false };
  36. case 5: _.label++; y = op[1]; op = [0]; continue;
  37. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  38. default:
  39. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  40. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  41. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  42. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  43. if (t[2]) _.ops.pop();
  44. _.trys.pop(); continue;
  45. }
  46. op = body.call(thisArg, _);
  47. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  48. if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  49. }
  50. }
  51. // NOTE: this list must be up-to-date with browsers listed in
  52. // test/acceptance/useragentstrings.yml
  53. const BROWSER_ALIASES_MAP = {
  54. 'Amazon Silk': 'amazon_silk',
  55. 'Android Browser': 'android',
  56. Bada: 'bada',
  57. BlackBerry: 'blackberry',
  58. Chrome: 'chrome',
  59. Chromium: 'chromium',
  60. Electron: 'electron',
  61. Epiphany: 'epiphany',
  62. Firefox: 'firefox',
  63. Focus: 'focus',
  64. Generic: 'generic',
  65. 'Google Search': 'google_search',
  66. Googlebot: 'googlebot',
  67. 'Internet Explorer': 'ie',
  68. 'K-Meleon': 'k_meleon',
  69. Maxthon: 'maxthon',
  70. 'Microsoft Edge': 'edge',
  71. 'MZ Browser': 'mz',
  72. 'NAVER Whale Browser': 'naver',
  73. Opera: 'opera',
  74. 'Opera Coast': 'opera_coast',
  75. PhantomJS: 'phantomjs',
  76. Puffin: 'puffin',
  77. QupZilla: 'qupzilla',
  78. QQ: 'qq',
  79. QQLite: 'qqlite',
  80. Safari: 'safari',
  81. Sailfish: 'sailfish',
  82. 'Samsung Internet for Android': 'samsung_internet',
  83. SeaMonkey: 'seamonkey',
  84. Sleipnir: 'sleipnir',
  85. Swing: 'swing',
  86. Tizen: 'tizen',
  87. 'UC Browser': 'uc',
  88. Vivaldi: 'vivaldi',
  89. 'WebOS Browser': 'webos',
  90. WeChat: 'wechat',
  91. 'Yandex Browser': 'yandex',
  92. Roku: 'roku',
  93. };
  94. const BROWSER_MAP = {
  95. amazon_silk: 'Amazon Silk',
  96. android: 'Android Browser',
  97. bada: 'Bada',
  98. blackberry: 'BlackBerry',
  99. chrome: 'Chrome',
  100. chromium: 'Chromium',
  101. electron: 'Electron',
  102. epiphany: 'Epiphany',
  103. firefox: 'Firefox',
  104. focus: 'Focus',
  105. generic: 'Generic',
  106. googlebot: 'Googlebot',
  107. google_search: 'Google Search',
  108. ie: 'Internet Explorer',
  109. k_meleon: 'K-Meleon',
  110. maxthon: 'Maxthon',
  111. edge: 'Microsoft Edge',
  112. mz: 'MZ Browser',
  113. naver: 'NAVER Whale Browser',
  114. opera: 'Opera',
  115. opera_coast: 'Opera Coast',
  116. phantomjs: 'PhantomJS',
  117. puffin: 'Puffin',
  118. qupzilla: 'QupZilla',
  119. qq: 'QQ Browser',
  120. qqlite: 'QQ Browser Lite',
  121. safari: 'Safari',
  122. sailfish: 'Sailfish',
  123. samsung_internet: 'Samsung Internet for Android',
  124. seamonkey: 'SeaMonkey',
  125. sleipnir: 'Sleipnir',
  126. swing: 'Swing',
  127. tizen: 'Tizen',
  128. uc: 'UC Browser',
  129. vivaldi: 'Vivaldi',
  130. webos: 'WebOS Browser',
  131. wechat: 'WeChat',
  132. yandex: 'Yandex Browser',
  133. };
  134. const PLATFORMS_MAP = {
  135. tablet: 'tablet',
  136. mobile: 'mobile',
  137. desktop: 'desktop',
  138. tv: 'tv',
  139. };
  140. const OS_MAP = {
  141. WindowsPhone: 'Windows Phone',
  142. Windows: 'Windows',
  143. MacOS: 'macOS',
  144. iOS: 'iOS',
  145. Android: 'Android',
  146. WebOS: 'WebOS',
  147. BlackBerry: 'BlackBerry',
  148. Bada: 'Bada',
  149. Tizen: 'Tizen',
  150. Linux: 'Linux',
  151. ChromeOS: 'Chrome OS',
  152. PlayStation4: 'PlayStation 4',
  153. Roku: 'Roku',
  154. };
  155. const ENGINE_MAP = {
  156. EdgeHTML: 'EdgeHTML',
  157. Blink: 'Blink',
  158. Trident: 'Trident',
  159. Presto: 'Presto',
  160. Gecko: 'Gecko',
  161. WebKit: 'WebKit',
  162. };
  163. class Utils {
  164. /**
  165. * Get first matched item for a string
  166. * @param {RegExp} regexp
  167. * @param {String} ua
  168. * @return {Array|{index: number, input: string}|*|boolean|string}
  169. */
  170. static getFirstMatch(regexp, ua) {
  171. const match = ua.match(regexp);
  172. return (match && match.length > 0 && match[1]) || '';
  173. }
  174. /**
  175. * Get second matched item for a string
  176. * @param regexp
  177. * @param {String} ua
  178. * @return {Array|{index: number, input: string}|*|boolean|string}
  179. */
  180. static getSecondMatch(regexp, ua) {
  181. const match = ua.match(regexp);
  182. return (match && match.length > 1 && match[2]) || '';
  183. }
  184. /**
  185. * Match a regexp and return a constant or undefined
  186. * @param {RegExp} regexp
  187. * @param {String} ua
  188. * @param {*} _const Any const that will be returned if regexp matches the string
  189. * @return {*}
  190. */
  191. static matchAndReturnConst(regexp, ua, _const) {
  192. if (regexp.test(ua)) {
  193. return _const;
  194. }
  195. return void (0);
  196. }
  197. static getWindowsVersionName(version) {
  198. switch (version) {
  199. case 'NT': return 'NT';
  200. case 'XP': return 'XP';
  201. case 'NT 5.0': return '2000';
  202. case 'NT 5.1': return 'XP';
  203. case 'NT 5.2': return '2003';
  204. case 'NT 6.0': return 'Vista';
  205. case 'NT 6.1': return '7';
  206. case 'NT 6.2': return '8';
  207. case 'NT 6.3': return '8.1';
  208. case 'NT 10.0': return '10';
  209. default: return undefined;
  210. }
  211. }
  212. /**
  213. * Get macOS version name
  214. * 10.5 - Leopard
  215. * 10.6 - Snow Leopard
  216. * 10.7 - Lion
  217. * 10.8 - Mountain Lion
  218. * 10.9 - Mavericks
  219. * 10.10 - Yosemite
  220. * 10.11 - El Capitan
  221. * 10.12 - Sierra
  222. * 10.13 - High Sierra
  223. * 10.14 - Mojave
  224. * 10.15 - Catalina
  225. *
  226. * @example
  227. * getMacOSVersionName("10.14") // 'Mojave'
  228. *
  229. * @param {string} version
  230. * @return {string} versionName
  231. */
  232. static getMacOSVersionName(version) {
  233. const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
  234. v.push(0);
  235. if (v[0] !== 10) return undefined;
  236. switch (v[1]) {
  237. case 5: return 'Leopard';
  238. case 6: return 'Snow Leopard';
  239. case 7: return 'Lion';
  240. case 8: return 'Mountain Lion';
  241. case 9: return 'Mavericks';
  242. case 10: return 'Yosemite';
  243. case 11: return 'El Capitan';
  244. case 12: return 'Sierra';
  245. case 13: return 'High Sierra';
  246. case 14: return 'Mojave';
  247. case 15: return 'Catalina';
  248. default: return undefined;
  249. }
  250. }
  251. /**
  252. * Get Android version name
  253. * 1.5 - Cupcake
  254. * 1.6 - Donut
  255. * 2.0 - Eclair
  256. * 2.1 - Eclair
  257. * 2.2 - Froyo
  258. * 2.x - Gingerbread
  259. * 3.x - Honeycomb
  260. * 4.0 - Ice Cream Sandwich
  261. * 4.1 - Jelly Bean
  262. * 4.4 - KitKat
  263. * 5.x - Lollipop
  264. * 6.x - Marshmallow
  265. * 7.x - Nougat
  266. * 8.x - Oreo
  267. * 9.x - Pie
  268. *
  269. * @example
  270. * getAndroidVersionName("7.0") // 'Nougat'
  271. *
  272. * @param {string} version
  273. * @return {string} versionName
  274. */
  275. static getAndroidVersionName(version) {
  276. const v = version.split('.').splice(0, 2).map(s => parseInt(s, 10) || 0);
  277. v.push(0);
  278. if (v[0] === 1 && v[1] < 5) return undefined;
  279. if (v[0] === 1 && v[1] < 6) return 'Cupcake';
  280. if (v[0] === 1 && v[1] >= 6) return 'Donut';
  281. if (v[0] === 2 && v[1] < 2) return 'Eclair';
  282. if (v[0] === 2 && v[1] === 2) return 'Froyo';
  283. if (v[0] === 2 && v[1] > 2) return 'Gingerbread';
  284. if (v[0] === 3) return 'Honeycomb';
  285. if (v[0] === 4 && v[1] < 1) return 'Ice Cream Sandwich';
  286. if (v[0] === 4 && v[1] < 4) return 'Jelly Bean';
  287. if (v[0] === 4 && v[1] >= 4) return 'KitKat';
  288. if (v[0] === 5) return 'Lollipop';
  289. if (v[0] === 6) return 'Marshmallow';
  290. if (v[0] === 7) return 'Nougat';
  291. if (v[0] === 8) return 'Oreo';
  292. if (v[0] === 9) return 'Pie';
  293. return undefined;
  294. }
  295. /**
  296. * Get version precisions count
  297. *
  298. * @example
  299. * getVersionPrecision("1.10.3") // 3
  300. *
  301. * @param {string} version
  302. * @return {number}
  303. */
  304. static getVersionPrecision(version) {
  305. return version.split('.').length;
  306. }
  307. /**
  308. * Calculate browser version weight
  309. *
  310. * @example
  311. * compareVersions('1.10.2.1', '1.8.2.1.90') // 1
  312. * compareVersions('1.010.2.1', '1.09.2.1.90'); // 1
  313. * compareVersions('1.10.2.1', '1.10.2.1'); // 0
  314. * compareVersions('1.10.2.1', '1.0800.2'); // -1
  315. * compareVersions('1.10.2.1', '1.10', true); // 0
  316. *
  317. * @param {String} versionA versions versions to compare
  318. * @param {String} versionB versions versions to compare
  319. * @param {boolean} [isLoose] enable loose comparison
  320. * @return {Number} comparison result: -1 when versionA is lower,
  321. * 1 when versionA is bigger, 0 when both equal
  322. */
  323. /* eslint consistent-return: 1 */
  324. static compareVersions(versionA, versionB, isLoose = false) {
  325. // 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
  326. const versionAPrecision = Utils.getVersionPrecision(versionA);
  327. const versionBPrecision = Utils.getVersionPrecision(versionB);
  328. let precision = Math.max(versionAPrecision, versionBPrecision);
  329. let lastPrecision = 0;
  330. const chunks = Utils.map([versionA, versionB], (version) => {
  331. const delta = precision - Utils.getVersionPrecision(version);
  332. // 2) "9" -> "9.0" (for precision = 2)
  333. const _version = version + new Array(delta + 1).join('.0');
  334. // 3) "9.0" -> ["000000000"", "000000009"]
  335. return Utils.map(_version.split('.'), chunk => new Array(20 - chunk.length).join('0') + chunk).reverse();
  336. });
  337. // adjust precision for loose comparison
  338. if (isLoose) {
  339. lastPrecision = precision - Math.min(versionAPrecision, versionBPrecision);
  340. }
  341. // iterate in reverse order by reversed chunks array
  342. precision -= 1;
  343. while (precision >= lastPrecision) {
  344. // 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
  345. if (chunks[0][precision] > chunks[1][precision]) {
  346. return 1;
  347. }
  348. if (chunks[0][precision] === chunks[1][precision]) {
  349. if (precision === lastPrecision) {
  350. // all version chunks are same
  351. return 0;
  352. }
  353. precision -= 1;
  354. } else if (chunks[0][precision] < chunks[1][precision]) {
  355. return -1;
  356. }
  357. }
  358. return undefined;
  359. }
  360. /**
  361. * Array::map polyfill
  362. *
  363. * @param {Array} arr
  364. * @param {Function} iterator
  365. * @return {Array}
  366. */
  367. static map(arr, iterator) {
  368. const result = [];
  369. let i;
  370. if (Array.prototype.map) {
  371. return Array.prototype.map.call(arr, iterator);
  372. }
  373. for (i = 0; i < arr.length; i += 1) {
  374. result.push(iterator(arr[i]));
  375. }
  376. return result;
  377. }
  378. /**
  379. * Array::find polyfill
  380. *
  381. * @param {Array} arr
  382. * @param {Function} predicate
  383. * @return {Array}
  384. */
  385. static find(arr, predicate) {
  386. let i;
  387. let l;
  388. if (Array.prototype.find) {
  389. return Array.prototype.find.call(arr, predicate);
  390. }
  391. for (i = 0, l = arr.length; i < l; i += 1) {
  392. const value = arr[i];
  393. if (predicate(value, i)) {
  394. return value;
  395. }
  396. }
  397. return undefined;
  398. }
  399. /**
  400. * Object::assign polyfill
  401. *
  402. * @param {Object} obj
  403. * @param {Object} ...objs
  404. * @return {Object}
  405. */
  406. static assign(obj, ...assigners) {
  407. const result = obj;
  408. let i;
  409. let l;
  410. if (Object.assign) {
  411. return Object.assign(obj, ...assigners);
  412. }
  413. for (i = 0, l = assigners.length; i < l; i += 1) {
  414. const assigner = assigners[i];
  415. if (typeof assigner === 'object' && assigner !== null) {
  416. const keys = Object.keys(assigner);
  417. keys.forEach((key) => {
  418. result[key] = assigner[key];
  419. });
  420. }
  421. }
  422. return obj;
  423. }
  424. /**
  425. * Get short version/alias for a browser name
  426. *
  427. * @example
  428. * getBrowserAlias('Microsoft Edge') // edge
  429. *
  430. * @param {string} browserName
  431. * @return {string}
  432. */
  433. static getBrowserAlias(browserName) {
  434. return BROWSER_ALIASES_MAP[browserName];
  435. }
  436. /**
  437. * Get short version/alias for a browser name
  438. *
  439. * @example
  440. * getBrowserAlias('edge') // Microsoft Edge
  441. *
  442. * @param {string} browserAlias
  443. * @return {string}
  444. */
  445. static getBrowserTypeByAlias(browserAlias) {
  446. return BROWSER_MAP[browserAlias] || '';
  447. }
  448. }
  449. /**
  450. * Browsers' descriptors
  451. *
  452. * The idea of descriptors is simple. You should know about them two simple things:
  453. * 1. Every descriptor has a method or property called `test` and a `describe` method.
  454. * 2. Order of descriptors is important.
  455. *
  456. * More details:
  457. * 1. Method or property `test` serves as a way to detect whether the UA string
  458. * matches some certain browser or not. The `describe` method helps to make a result
  459. * object with params that show some browser-specific things: name, version, etc.
  460. * 2. Order of descriptors is important because a Parser goes through them one by one
  461. * in course. For example, if you insert Chrome's descriptor as the first one,
  462. * more then a half of browsers will be described as Chrome, because they will pass
  463. * the Chrome descriptor's test.
  464. *
  465. * Descriptor's `test` could be a property with an array of RegExps, where every RegExp
  466. * will be applied to a UA string to test it whether it matches or not.
  467. * If a descriptor has two or more regexps in the `test` array it tests them one by one
  468. * with a logical sum operation. Parser stops if it has found any RegExp that matches the UA.
  469. *
  470. * Or `test` could be a method. In that case it gets a Parser instance and should
  471. * return true/false to get the Parser know if this browser descriptor matches the UA or not.
  472. */
  473. const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
  474. const browsersList = [
  475. /* Googlebot */
  476. {
  477. test: [/googlebot/i],
  478. describe(ua) {
  479. const browser = {
  480. name: 'Googlebot',
  481. };
  482. const version = Utils.getFirstMatch(/googlebot\/(\d+(\.\d+))/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  483. if (version) {
  484. browser.version = version;
  485. }
  486. return browser;
  487. },
  488. },
  489. /* Opera < 13.0 */
  490. {
  491. test: [/opera/i],
  492. describe(ua) {
  493. const browser = {
  494. name: 'Opera',
  495. };
  496. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i, ua);
  497. if (version) {
  498. browser.version = version;
  499. }
  500. return browser;
  501. },
  502. },
  503. /* Opera > 13.0 */
  504. {
  505. test: [/opr\/|opios/i],
  506. describe(ua) {
  507. const browser = {
  508. name: 'Opera',
  509. };
  510. const version = Utils.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  511. if (version) {
  512. browser.version = version;
  513. }
  514. return browser;
  515. },
  516. },
  517. {
  518. test: [/SamsungBrowser/i],
  519. describe(ua) {
  520. const browser = {
  521. name: 'Samsung Internet for Android',
  522. };
  523. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
  524. if (version) {
  525. browser.version = version;
  526. }
  527. return browser;
  528. },
  529. },
  530. {
  531. test: [/Whale/i],
  532. describe(ua) {
  533. const browser = {
  534. name: 'NAVER Whale Browser',
  535. };
  536. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i, ua);
  537. if (version) {
  538. browser.version = version;
  539. }
  540. return browser;
  541. },
  542. },
  543. {
  544. test: [/MZBrowser/i],
  545. describe(ua) {
  546. const browser = {
  547. name: 'MZ Browser',
  548. };
  549. const version = Utils.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  550. if (version) {
  551. browser.version = version;
  552. }
  553. return browser;
  554. },
  555. },
  556. {
  557. test: [/focus/i],
  558. describe(ua) {
  559. const browser = {
  560. name: 'Focus',
  561. };
  562. const version = Utils.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  563. if (version) {
  564. browser.version = version;
  565. }
  566. return browser;
  567. },
  568. },
  569. {
  570. test: [/swing/i],
  571. describe(ua) {
  572. const browser = {
  573. name: 'Swing',
  574. };
  575. const version = Utils.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  576. if (version) {
  577. browser.version = version;
  578. }
  579. return browser;
  580. },
  581. },
  582. {
  583. test: [/coast/i],
  584. describe(ua) {
  585. const browser = {
  586. name: 'Opera Coast',
  587. };
  588. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i, ua);
  589. if (version) {
  590. browser.version = version;
  591. }
  592. return browser;
  593. },
  594. },
  595. {
  596. test: [/yabrowser/i],
  597. describe(ua) {
  598. const browser = {
  599. name: 'Yandex Browser',
  600. };
  601. const version = Utils.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  602. if (version) {
  603. browser.version = version;
  604. }
  605. return browser;
  606. },
  607. },
  608. {
  609. test: [/ucbrowser/i],
  610. describe(ua) {
  611. const browser = {
  612. name: 'UC Browser',
  613. };
  614. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
  615. if (version) {
  616. browser.version = version;
  617. }
  618. return browser;
  619. },
  620. },
  621. {
  622. test: [/Maxthon|mxios/i],
  623. describe(ua) {
  624. const browser = {
  625. name: 'Maxthon',
  626. };
  627. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i, ua);
  628. if (version) {
  629. browser.version = version;
  630. }
  631. return browser;
  632. },
  633. },
  634. {
  635. test: [/epiphany/i],
  636. describe(ua) {
  637. const browser = {
  638. name: 'Epiphany',
  639. };
  640. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i, ua);
  641. if (version) {
  642. browser.version = version;
  643. }
  644. return browser;
  645. },
  646. },
  647. {
  648. test: [/puffin/i],
  649. describe(ua) {
  650. const browser = {
  651. name: 'Puffin',
  652. };
  653. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i, ua);
  654. if (version) {
  655. browser.version = version;
  656. }
  657. return browser;
  658. },
  659. },
  660. {
  661. test: [/sleipnir/i],
  662. describe(ua) {
  663. const browser = {
  664. name: 'Sleipnir',
  665. };
  666. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i, ua);
  667. if (version) {
  668. browser.version = version;
  669. }
  670. return browser;
  671. },
  672. },
  673. {
  674. test: [/k-meleon/i],
  675. describe(ua) {
  676. const browser = {
  677. name: 'K-Meleon',
  678. };
  679. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i, ua);
  680. if (version) {
  681. browser.version = version;
  682. }
  683. return browser;
  684. },
  685. },
  686. {
  687. test: [/micromessenger/i],
  688. describe(ua) {
  689. const browser = {
  690. name: 'WeChat',
  691. };
  692. const version = Utils.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  693. if (version) {
  694. browser.version = version;
  695. }
  696. return browser;
  697. },
  698. },
  699. {
  700. test: [/qqbrowser/i],
  701. describe(ua) {
  702. const browser = {
  703. name: (/qqbrowserlite/i).test(ua) ? 'QQ Browser Lite' : 'QQ Browser',
  704. };
  705. const version = Utils.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  706. if (version) {
  707. browser.version = version;
  708. }
  709. return browser;
  710. },
  711. },
  712. {
  713. test: [/msie|trident/i],
  714. describe(ua) {
  715. const browser = {
  716. name: 'Internet Explorer',
  717. };
  718. const version = Utils.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i, ua);
  719. if (version) {
  720. browser.version = version;
  721. }
  722. return browser;
  723. },
  724. },
  725. {
  726. test: [/\sedg\//i],
  727. describe(ua) {
  728. const browser = {
  729. name: 'Microsoft Edge',
  730. };
  731. const version = Utils.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i, ua);
  732. if (version) {
  733. browser.version = version;
  734. }
  735. return browser;
  736. },
  737. },
  738. {
  739. test: [/edg([ea]|ios)/i],
  740. describe(ua) {
  741. const browser = {
  742. name: 'Microsoft Edge',
  743. };
  744. const version = Utils.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i, ua);
  745. if (version) {
  746. browser.version = version;
  747. }
  748. return browser;
  749. },
  750. },
  751. {
  752. test: [/vivaldi/i],
  753. describe(ua) {
  754. const browser = {
  755. name: 'Vivaldi',
  756. };
  757. const version = Utils.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i, ua);
  758. if (version) {
  759. browser.version = version;
  760. }
  761. return browser;
  762. },
  763. },
  764. {
  765. test: [/seamonkey/i],
  766. describe(ua) {
  767. const browser = {
  768. name: 'SeaMonkey',
  769. };
  770. const version = Utils.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i, ua);
  771. if (version) {
  772. browser.version = version;
  773. }
  774. return browser;
  775. },
  776. },
  777. {
  778. test: [/sailfish/i],
  779. describe(ua) {
  780. const browser = {
  781. name: 'Sailfish',
  782. };
  783. const version = Utils.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i, ua);
  784. if (version) {
  785. browser.version = version;
  786. }
  787. return browser;
  788. },
  789. },
  790. {
  791. test: [/silk/i],
  792. describe(ua) {
  793. const browser = {
  794. name: 'Amazon Silk',
  795. };
  796. const version = Utils.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i, ua);
  797. if (version) {
  798. browser.version = version;
  799. }
  800. return browser;
  801. },
  802. },
  803. {
  804. test: [/phantom/i],
  805. describe(ua) {
  806. const browser = {
  807. name: 'PhantomJS',
  808. };
  809. const version = Utils.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i, ua);
  810. if (version) {
  811. browser.version = version;
  812. }
  813. return browser;
  814. },
  815. },
  816. {
  817. test: [/slimerjs/i],
  818. describe(ua) {
  819. const browser = {
  820. name: 'SlimerJS',
  821. };
  822. const version = Utils.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i, ua);
  823. if (version) {
  824. browser.version = version;
  825. }
  826. return browser;
  827. },
  828. },
  829. {
  830. test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
  831. describe(ua) {
  832. const browser = {
  833. name: 'BlackBerry',
  834. };
  835. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i, ua);
  836. if (version) {
  837. browser.version = version;
  838. }
  839. return browser;
  840. },
  841. },
  842. {
  843. test: [/(web|hpw)[o0]s/i],
  844. describe(ua) {
  845. const browser = {
  846. name: 'WebOS Browser',
  847. };
  848. const version = Utils.getFirstMatch(commonVersionIdentifier, ua) || Utils.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i, ua);
  849. if (version) {
  850. browser.version = version;
  851. }
  852. return browser;
  853. },
  854. },
  855. {
  856. test: [/bada/i],
  857. describe(ua) {
  858. const browser = {
  859. name: 'Bada',
  860. };
  861. const version = Utils.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i, ua);
  862. if (version) {
  863. browser.version = version;
  864. }
  865. return browser;
  866. },
  867. },
  868. {
  869. test: [/tizen/i],
  870. describe(ua) {
  871. const browser = {
  872. name: 'Tizen',
  873. };
  874. const version = Utils.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  875. if (version) {
  876. browser.version = version;
  877. }
  878. return browser;
  879. },
  880. },
  881. {
  882. test: [/qupzilla/i],
  883. describe(ua) {
  884. const browser = {
  885. name: 'QupZilla',
  886. };
  887. const version = Utils.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  888. if (version) {
  889. browser.version = version;
  890. }
  891. return browser;
  892. },
  893. },
  894. {
  895. test: [/firefox|iceweasel|fxios/i],
  896. describe(ua) {
  897. const browser = {
  898. name: 'Firefox',
  899. };
  900. const version = Utils.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, ua);
  901. if (version) {
  902. browser.version = version;
  903. }
  904. return browser;
  905. },
  906. },
  907. {
  908. test: [/electron/i],
  909. describe(ua) {
  910. const browser = {
  911. name: 'Electron',
  912. };
  913. const version = Utils.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i, ua);
  914. if (version) {
  915. browser.version = version;
  916. }
  917. return browser;
  918. },
  919. },
  920. {
  921. test: [/chromium/i],
  922. describe(ua) {
  923. const browser = {
  924. name: 'Chromium',
  925. };
  926. const version = Utils.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i, ua) || Utils.getFirstMatch(commonVersionIdentifier, ua);
  927. if (version) {
  928. browser.version = version;
  929. }
  930. return browser;
  931. },
  932. },
  933. {
  934. test: [/chrome|crios|crmo/i],
  935. describe(ua) {
  936. const browser = {
  937. name: 'Chrome',
  938. };
  939. const version = Utils.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua);
  940. if (version) {
  941. browser.version = version;
  942. }
  943. return browser;
  944. },
  945. },
  946. {
  947. test: [/GSA/i],
  948. describe(ua) {
  949. const browser = {
  950. name: 'Google Search',
  951. };
  952. const version = Utils.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i, ua);
  953. if (version) {
  954. browser.version = version;
  955. }
  956. return browser;
  957. },
  958. },
  959. /* Android Browser */
  960. {
  961. test(parser) {
  962. const notLikeAndroid = !parser.test(/like android/i);
  963. const butAndroid = parser.test(/android/i);
  964. return notLikeAndroid && butAndroid;
  965. },
  966. describe(ua) {
  967. const browser = {
  968. name: 'Android Browser',
  969. };
  970. const version = Utils.getFirstMatch(commonVersionIdentifier, ua);
  971. if (version) {
  972. browser.version = version;
  973. }
  974. return browser;
  975. },
  976. },
  977. /* PlayStation 4 */
  978. {
  979. test: [/playstation 4/i],
  980. describe(ua) {
  981. const browser = {
  982. name: 'PlayStation 4',
  983. };
  984. const version = Utils.getFirstMatch(commonVersionIdentifier, ua);
  985. if (version) {
  986. browser.version = version;
  987. }
  988. return browser;
  989. },
  990. },
  991. /* Safari */
  992. {
  993. test: [/safari|applewebkit/i],
  994. describe(ua) {
  995. const browser = {
  996. name: 'Safari',
  997. };
  998. const version = Utils.getFirstMatch(commonVersionIdentifier, ua);
  999. if (version) {
  1000. browser.version = version;
  1001. }
  1002. return browser;
  1003. },
  1004. },
  1005. /* Something else */
  1006. {
  1007. test: [/.*/i],
  1008. describe(ua) {
  1009. /* Here we try to make sure that there are explicit details about the device
  1010. * in order to decide what regexp exactly we want to apply
  1011. * (as there is a specific decision based on that conclusion)
  1012. */
  1013. const regexpWithoutDeviceSpec = /^(.*)\/(.*) /;
  1014. const regexpWithDeviceSpec = /^(.*)\/(.*)[ \t]\((.*)/;
  1015. const hasDeviceSpec = ua.search('\\(') !== -1;
  1016. const regexp = hasDeviceSpec ? regexpWithDeviceSpec : regexpWithoutDeviceSpec;
  1017. return {
  1018. name: Utils.getFirstMatch(regexp, ua),
  1019. version: Utils.getSecondMatch(regexp, ua),
  1020. };
  1021. },
  1022. },
  1023. ];
  1024. var osParsersList = [
  1025. /* Roku */
  1026. {
  1027. test: [/Roku\/DVP/],
  1028. describe(ua) {
  1029. const version = Utils.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i, ua);
  1030. return {
  1031. name: OS_MAP.Roku,
  1032. version,
  1033. };
  1034. },
  1035. },
  1036. /* Windows Phone */
  1037. {
  1038. test: [/windows phone/i],
  1039. describe(ua) {
  1040. const version = Utils.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i, ua);
  1041. return {
  1042. name: OS_MAP.WindowsPhone,
  1043. version,
  1044. };
  1045. },
  1046. },
  1047. /* Windows */
  1048. {
  1049. test: [/windows /i],
  1050. describe(ua) {
  1051. const version = Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i, ua);
  1052. const versionName = Utils.getWindowsVersionName(version);
  1053. return {
  1054. name: OS_MAP.Windows,
  1055. version,
  1056. versionName,
  1057. };
  1058. },
  1059. },
  1060. /* Firefox on iPad */
  1061. {
  1062. test: [/Macintosh(.*?) FxiOS(.*?) Version\//],
  1063. describe(ua) {
  1064. const version = Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/, ua);
  1065. return {
  1066. name: OS_MAP.iOS,
  1067. version,
  1068. };
  1069. },
  1070. },
  1071. /* macOS */
  1072. {
  1073. test: [/macintosh/i],
  1074. describe(ua) {
  1075. const version = Utils.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i, ua).replace(/[_\s]/g, '.');
  1076. const versionName = Utils.getMacOSVersionName(version);
  1077. const os = {
  1078. name: OS_MAP.MacOS,
  1079. version,
  1080. };
  1081. if (versionName) {
  1082. os.versionName = versionName;
  1083. }
  1084. return os;
  1085. },
  1086. },
  1087. /* iOS */
  1088. {
  1089. test: [/(ipod|iphone|ipad)/i],
  1090. describe(ua) {
  1091. const version = Utils.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i, ua).replace(/[_\s]/g, '.');
  1092. return {
  1093. name: OS_MAP.iOS,
  1094. version,
  1095. };
  1096. },
  1097. },
  1098. /* Android */
  1099. {
  1100. test(parser) {
  1101. const notLikeAndroid = !parser.test(/like android/i);
  1102. const butAndroid = parser.test(/android/i);
  1103. return notLikeAndroid && butAndroid;
  1104. },
  1105. describe(ua) {
  1106. const version = Utils.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i, ua);
  1107. const versionName = Utils.getAndroidVersionName(version);
  1108. const os = {
  1109. name: OS_MAP.Android,
  1110. version,
  1111. };
  1112. if (versionName) {
  1113. os.versionName = versionName;
  1114. }
  1115. return os;
  1116. },
  1117. },
  1118. /* WebOS */
  1119. {
  1120. test: [/(web|hpw)[o0]s/i],
  1121. describe(ua) {
  1122. const version = Utils.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i, ua);
  1123. const os = {
  1124. name: OS_MAP.WebOS,
  1125. };
  1126. if (version && version.length) {
  1127. os.version = version;
  1128. }
  1129. return os;
  1130. },
  1131. },
  1132. /* BlackBerry */
  1133. {
  1134. test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
  1135. describe(ua) {
  1136. const version = Utils.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i, ua)
  1137. || Utils.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i, ua)
  1138. || Utils.getFirstMatch(/\bbb(\d+)/i, ua);
  1139. return {
  1140. name: OS_MAP.BlackBerry,
  1141. version,
  1142. };
  1143. },
  1144. },
  1145. /* Bada */
  1146. {
  1147. test: [/bada/i],
  1148. describe(ua) {
  1149. const version = Utils.getFirstMatch(/bada\/(\d+(\.\d+)*)/i, ua);
  1150. return {
  1151. name: OS_MAP.Bada,
  1152. version,
  1153. };
  1154. },
  1155. },
  1156. /* Tizen */
  1157. {
  1158. test: [/tizen/i],
  1159. describe(ua) {
  1160. const version = Utils.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i, ua);
  1161. return {
  1162. name: OS_MAP.Tizen,
  1163. version,
  1164. };
  1165. },
  1166. },
  1167. /* Linux */
  1168. {
  1169. test: [/linux/i],
  1170. describe() {
  1171. return {
  1172. name: OS_MAP.Linux,
  1173. };
  1174. },
  1175. },
  1176. /* Chrome OS */
  1177. {
  1178. test: [/CrOS/],
  1179. describe() {
  1180. return {
  1181. name: OS_MAP.ChromeOS,
  1182. };
  1183. },
  1184. },
  1185. /* Playstation 4 */
  1186. {
  1187. test: [/PlayStation 4/],
  1188. describe(ua) {
  1189. const version = Utils.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i, ua);
  1190. return {
  1191. name: OS_MAP.PlayStation4,
  1192. version,
  1193. };
  1194. },
  1195. },
  1196. ];
  1197. /*
  1198. * Tablets go first since usually they have more specific
  1199. * signs to detect.
  1200. */
  1201. var platformParsersList = [
  1202. /* Googlebot */
  1203. {
  1204. test: [/googlebot/i],
  1205. describe() {
  1206. return {
  1207. type: 'bot',
  1208. vendor: 'Google',
  1209. };
  1210. },
  1211. },
  1212. /* Huawei */
  1213. {
  1214. test: [/huawei/i],
  1215. describe(ua) {
  1216. const model = Utils.getFirstMatch(/(can-l01)/i, ua) && 'Nova';
  1217. const platform = {
  1218. type: PLATFORMS_MAP.mobile,
  1219. vendor: 'Huawei',
  1220. };
  1221. if (model) {
  1222. platform.model = model;
  1223. }
  1224. return platform;
  1225. },
  1226. },
  1227. /* Nexus Tablet */
  1228. {
  1229. test: [/nexus\s*(?:7|8|9|10).*/i],
  1230. describe() {
  1231. return {
  1232. type: PLATFORMS_MAP.tablet,
  1233. vendor: 'Nexus',
  1234. };
  1235. },
  1236. },
  1237. /* iPad */
  1238. {
  1239. test: [/ipad/i],
  1240. describe() {
  1241. return {
  1242. type: PLATFORMS_MAP.tablet,
  1243. vendor: 'Apple',
  1244. model: 'iPad',
  1245. };
  1246. },
  1247. },
  1248. /* Firefox on iPad */
  1249. {
  1250. test: [/Macintosh(.*?) FxiOS(.*?) Version\//],
  1251. describe() {
  1252. return {
  1253. type: PLATFORMS_MAP.tablet,
  1254. vendor: 'Apple',
  1255. model: 'iPad',
  1256. };
  1257. },
  1258. },
  1259. /* Amazon Kindle Fire */
  1260. {
  1261. test: [/kftt build/i],
  1262. describe() {
  1263. return {
  1264. type: PLATFORMS_MAP.tablet,
  1265. vendor: 'Amazon',
  1266. model: 'Kindle Fire HD 7',
  1267. };
  1268. },
  1269. },
  1270. /* Another Amazon Tablet with Silk */
  1271. {
  1272. test: [/silk/i],
  1273. describe() {
  1274. return {
  1275. type: PLATFORMS_MAP.tablet,
  1276. vendor: 'Amazon',
  1277. };
  1278. },
  1279. },
  1280. /* Tablet */
  1281. {
  1282. test: [/tablet(?! pc)/i],
  1283. describe() {
  1284. return {
  1285. type: PLATFORMS_MAP.tablet,
  1286. };
  1287. },
  1288. },
  1289. /* iPod/iPhone */
  1290. {
  1291. test(parser) {
  1292. const iDevice = parser.test(/ipod|iphone/i);
  1293. const likeIDevice = parser.test(/like (ipod|iphone)/i);
  1294. return iDevice && !likeIDevice;
  1295. },
  1296. describe(ua) {
  1297. const model = Utils.getFirstMatch(/(ipod|iphone)/i, ua);
  1298. return {
  1299. type: PLATFORMS_MAP.mobile,
  1300. vendor: 'Apple',
  1301. model,
  1302. };
  1303. },
  1304. },
  1305. /* Nexus Mobile */
  1306. {
  1307. test: [/nexus\s*[0-6].*/i, /galaxy nexus/i],
  1308. describe() {
  1309. return {
  1310. type: PLATFORMS_MAP.mobile,
  1311. vendor: 'Nexus',
  1312. };
  1313. },
  1314. },
  1315. /* Mobile */
  1316. {
  1317. test: [/[^-]mobi/i],
  1318. describe() {
  1319. return {
  1320. type: PLATFORMS_MAP.mobile,
  1321. };
  1322. },
  1323. },
  1324. /* BlackBerry */
  1325. {
  1326. test(parser) {
  1327. return parser.getBrowserName(true) === 'blackberry';
  1328. },
  1329. describe() {
  1330. return {
  1331. type: PLATFORMS_MAP.mobile,
  1332. vendor: 'BlackBerry',
  1333. };
  1334. },
  1335. },
  1336. /* Bada */
  1337. {
  1338. test(parser) {
  1339. return parser.getBrowserName(true) === 'bada';
  1340. },
  1341. describe() {
  1342. return {
  1343. type: PLATFORMS_MAP.mobile,
  1344. };
  1345. },
  1346. },
  1347. /* Windows Phone */
  1348. {
  1349. test(parser) {
  1350. return parser.getBrowserName() === 'windows phone';
  1351. },
  1352. describe() {
  1353. return {
  1354. type: PLATFORMS_MAP.mobile,
  1355. vendor: 'Microsoft',
  1356. };
  1357. },
  1358. },
  1359. /* Android Tablet */
  1360. {
  1361. test(parser) {
  1362. const osMajorVersion = Number(String(parser.getOSVersion()).split('.')[0]);
  1363. return parser.getOSName(true) === 'android' && (osMajorVersion >= 3);
  1364. },
  1365. describe() {
  1366. return {
  1367. type: PLATFORMS_MAP.tablet,
  1368. };
  1369. },
  1370. },
  1371. /* Android Mobile */
  1372. {
  1373. test(parser) {
  1374. return parser.getOSName(true) === 'android';
  1375. },
  1376. describe() {
  1377. return {
  1378. type: PLATFORMS_MAP.mobile,
  1379. };
  1380. },
  1381. },
  1382. /* desktop */
  1383. {
  1384. test(parser) {
  1385. return parser.getOSName(true) === 'macos';
  1386. },
  1387. describe() {
  1388. return {
  1389. type: PLATFORMS_MAP.desktop,
  1390. vendor: 'Apple',
  1391. };
  1392. },
  1393. },
  1394. /* Windows */
  1395. {
  1396. test(parser) {
  1397. return parser.getOSName(true) === 'windows';
  1398. },
  1399. describe() {
  1400. return {
  1401. type: PLATFORMS_MAP.desktop,
  1402. };
  1403. },
  1404. },
  1405. /* Linux */
  1406. {
  1407. test(parser) {
  1408. return parser.getOSName(true) === 'linux';
  1409. },
  1410. describe() {
  1411. return {
  1412. type: PLATFORMS_MAP.desktop,
  1413. };
  1414. },
  1415. },
  1416. /* PlayStation 4 */
  1417. {
  1418. test(parser) {
  1419. return parser.getOSName(true) === 'playstation 4';
  1420. },
  1421. describe() {
  1422. return {
  1423. type: PLATFORMS_MAP.tv,
  1424. };
  1425. },
  1426. },
  1427. /* Roku */
  1428. {
  1429. test(parser) {
  1430. return parser.getOSName(true) === 'roku';
  1431. },
  1432. describe() {
  1433. return {
  1434. type: PLATFORMS_MAP.tv,
  1435. };
  1436. },
  1437. },
  1438. ];
  1439. /*
  1440. * More specific goes first
  1441. */
  1442. var enginesParsersList = [
  1443. /* EdgeHTML */
  1444. {
  1445. test(parser) {
  1446. return parser.getBrowserName(true) === 'microsoft edge';
  1447. },
  1448. describe(ua) {
  1449. const isBlinkBased = /\sedg\//i.test(ua);
  1450. // return blink if it's blink-based one
  1451. if (isBlinkBased) {
  1452. return {
  1453. name: ENGINE_MAP.Blink,
  1454. };
  1455. }
  1456. // otherwise match the version and return EdgeHTML
  1457. const version = Utils.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i, ua);
  1458. return {
  1459. name: ENGINE_MAP.EdgeHTML,
  1460. version,
  1461. };
  1462. },
  1463. },
  1464. /* Trident */
  1465. {
  1466. test: [/trident/i],
  1467. describe(ua) {
  1468. const engine = {
  1469. name: ENGINE_MAP.Trident,
  1470. };
  1471. const version = Utils.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i, ua);
  1472. if (version) {
  1473. engine.version = version;
  1474. }
  1475. return engine;
  1476. },
  1477. },
  1478. /* Presto */
  1479. {
  1480. test(parser) {
  1481. return parser.test(/presto/i);
  1482. },
  1483. describe(ua) {
  1484. const engine = {
  1485. name: ENGINE_MAP.Presto,
  1486. };
  1487. const version = Utils.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i, ua);
  1488. if (version) {
  1489. engine.version = version;
  1490. }
  1491. return engine;
  1492. },
  1493. },
  1494. /* Gecko */
  1495. {
  1496. test(parser) {
  1497. const isGecko = parser.test(/gecko/i);
  1498. const likeGecko = parser.test(/like gecko/i);
  1499. return isGecko && !likeGecko;
  1500. },
  1501. describe(ua) {
  1502. const engine = {
  1503. name: ENGINE_MAP.Gecko,
  1504. };
  1505. const version = Utils.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i, ua);
  1506. if (version) {
  1507. engine.version = version;
  1508. }
  1509. return engine;
  1510. },
  1511. },
  1512. /* Blink */
  1513. {
  1514. test: [/(apple)?webkit\/537\.36/i],
  1515. describe() {
  1516. return {
  1517. name: ENGINE_MAP.Blink,
  1518. };
  1519. },
  1520. },
  1521. /* WebKit */
  1522. {
  1523. test: [/(apple)?webkit/i],
  1524. describe(ua) {
  1525. const engine = {
  1526. name: ENGINE_MAP.WebKit,
  1527. };
  1528. const version = Utils.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i, ua);
  1529. if (version) {
  1530. engine.version = version;
  1531. }
  1532. return engine;
  1533. },
  1534. },
  1535. ];
  1536. /**
  1537. * The main class that arranges the whole parsing process.
  1538. */
  1539. class Parser {
  1540. /**
  1541. * Create instance of Parser
  1542. *
  1543. * @param {String} UA User-Agent string
  1544. * @param {Boolean} [skipParsing=false] parser can skip parsing in purpose of performance
  1545. * improvements if you need to make a more particular parsing
  1546. * like {@link Parser#parseBrowser} or {@link Parser#parsePlatform}
  1547. *
  1548. * @throw {Error} in case of empty UA String
  1549. *
  1550. * @constructor
  1551. */
  1552. constructor(UA, skipParsing = false) {
  1553. if (UA === void (0) || UA === null || UA === '') {
  1554. throw new Error("UserAgent parameter can't be empty");
  1555. }
  1556. this._ua = UA;
  1557. /**
  1558. * @typedef ParsedResult
  1559. * @property {Object} browser
  1560. * @property {String|undefined} [browser.name]
  1561. * Browser name, like `"Chrome"` or `"Internet Explorer"`
  1562. * @property {String|undefined} [browser.version] Browser version as a String `"12.01.45334.10"`
  1563. * @property {Object} os
  1564. * @property {String|undefined} [os.name] OS name, like `"Windows"` or `"macOS"`
  1565. * @property {String|undefined} [os.version] OS version, like `"NT 5.1"` or `"10.11.1"`
  1566. * @property {String|undefined} [os.versionName] OS name, like `"XP"` or `"High Sierra"`
  1567. * @property {Object} platform
  1568. * @property {String|undefined} [platform.type]
  1569. * platform type, can be either `"desktop"`, `"tablet"` or `"mobile"`
  1570. * @property {String|undefined} [platform.vendor] Vendor of the device,
  1571. * like `"Apple"` or `"Samsung"`
  1572. * @property {String|undefined} [platform.model] Device model,
  1573. * like `"iPhone"` or `"Kindle Fire HD 7"`
  1574. * @property {Object} engine
  1575. * @property {String|undefined} [engine.name]
  1576. * Can be any of this: `WebKit`, `Blink`, `Gecko`, `Trident`, `Presto`, `EdgeHTML`
  1577. * @property {String|undefined} [engine.version] String version of the engine
  1578. */
  1579. this.parsedResult = {};
  1580. if (skipParsing !== true) {
  1581. this.parse();
  1582. }
  1583. }
  1584. /**
  1585. * Get UserAgent string of current Parser instance
  1586. * @return {String} User-Agent String of the current <Parser> object
  1587. *
  1588. * @public
  1589. */
  1590. getUA() {
  1591. return this._ua;
  1592. }
  1593. /**
  1594. * Test a UA string for a regexp
  1595. * @param {RegExp} regex
  1596. * @return {Boolean}
  1597. */
  1598. test(regex) {
  1599. return regex.test(this._ua);
  1600. }
  1601. /**
  1602. * Get parsed browser object
  1603. * @return {Object}
  1604. */
  1605. parseBrowser() {
  1606. this.parsedResult.browser = {};
  1607. const browserDescriptor = Utils.find(browsersList, (_browser) => {
  1608. if (typeof _browser.test === 'function') {
  1609. return _browser.test(this);
  1610. }
  1611. if (_browser.test instanceof Array) {
  1612. return _browser.test.some(condition => this.test(condition));
  1613. }
  1614. throw new Error("Browser's test function is not valid");
  1615. });
  1616. if (browserDescriptor) {
  1617. this.parsedResult.browser = browserDescriptor.describe(this.getUA());
  1618. }
  1619. return this.parsedResult.browser;
  1620. }
  1621. /**
  1622. * Get parsed browser object
  1623. * @return {Object}
  1624. *
  1625. * @public
  1626. */
  1627. getBrowser() {
  1628. if (this.parsedResult.browser) {
  1629. return this.parsedResult.browser;
  1630. }
  1631. return this.parseBrowser();
  1632. }
  1633. /**
  1634. * Get browser's name
  1635. * @return {String} Browser's name or an empty string
  1636. *
  1637. * @public
  1638. */
  1639. getBrowserName(toLowerCase) {
  1640. if (toLowerCase) {
  1641. return String(this.getBrowser().name).toLowerCase() || '';
  1642. }
  1643. return this.getBrowser().name || '';
  1644. }
  1645. /**
  1646. * Get browser's version
  1647. * @return {String} version of browser
  1648. *
  1649. * @public
  1650. */
  1651. getBrowserVersion() {
  1652. return this.getBrowser().version;
  1653. }
  1654. /**
  1655. * Get OS
  1656. * @return {Object}
  1657. *
  1658. * @example
  1659. * this.getOS();
  1660. * {
  1661. * name: 'macOS',
  1662. * version: '10.11.12'
  1663. * }
  1664. */
  1665. getOS() {
  1666. if (this.parsedResult.os) {
  1667. return this.parsedResult.os;
  1668. }
  1669. return this.parseOS();
  1670. }
  1671. /**
  1672. * Parse OS and save it to this.parsedResult.os
  1673. * @return {*|{}}
  1674. */
  1675. parseOS() {
  1676. this.parsedResult.os = {};
  1677. const os = Utils.find(osParsersList, (_os) => {
  1678. if (typeof _os.test === 'function') {
  1679. return _os.test(this);
  1680. }
  1681. if (_os.test instanceof Array) {
  1682. return _os.test.some(condition => this.test(condition));
  1683. }
  1684. throw new Error("Browser's test function is not valid");
  1685. });
  1686. if (os) {
  1687. this.parsedResult.os = os.describe(this.getUA());
  1688. }
  1689. return this.parsedResult.os;
  1690. }
  1691. /**
  1692. * Get OS name
  1693. * @param {Boolean} [toLowerCase] return lower-cased value
  1694. * @return {String} name of the OS — macOS, Windows, Linux, etc.
  1695. */
  1696. getOSName(toLowerCase) {
  1697. const { name } = this.getOS();
  1698. if (toLowerCase) {
  1699. return String(name).toLowerCase() || '';
  1700. }
  1701. return name || '';
  1702. }
  1703. /**
  1704. * Get OS version
  1705. * @return {String} full version with dots ('10.11.12', '5.6', etc)
  1706. */
  1707. getOSVersion() {
  1708. return this.getOS().version;
  1709. }
  1710. /**
  1711. * Get parsed platform
  1712. * @return {{}}
  1713. */
  1714. getPlatform() {
  1715. if (this.parsedResult.platform) {
  1716. return this.parsedResult.platform;
  1717. }
  1718. return this.parsePlatform();
  1719. }
  1720. /**
  1721. * Get platform name
  1722. * @param {Boolean} [toLowerCase=false]
  1723. * @return {*}
  1724. */
  1725. getPlatformType(toLowerCase = false) {
  1726. const { type } = this.getPlatform();
  1727. if (toLowerCase) {
  1728. return String(type).toLowerCase() || '';
  1729. }
  1730. return type || '';
  1731. }
  1732. /**
  1733. * Get parsed platform
  1734. * @return {{}}
  1735. */
  1736. parsePlatform() {
  1737. this.parsedResult.platform = {};
  1738. const platform = Utils.find(platformParsersList, (_platform) => {
  1739. if (typeof _platform.test === 'function') {
  1740. return _platform.test(this);
  1741. }
  1742. if (_platform.test instanceof Array) {
  1743. return _platform.test.some(condition => this.test(condition));
  1744. }
  1745. throw new Error("Browser's test function is not valid");
  1746. });
  1747. if (platform) {
  1748. this.parsedResult.platform = platform.describe(this.getUA());
  1749. }
  1750. return this.parsedResult.platform;
  1751. }
  1752. /**
  1753. * Get parsed engine
  1754. * @return {{}}
  1755. */
  1756. getEngine() {
  1757. if (this.parsedResult.engine) {
  1758. return this.parsedResult.engine;
  1759. }
  1760. return this.parseEngine();
  1761. }
  1762. /**
  1763. * Get engines's name
  1764. * @return {String} Engines's name or an empty string
  1765. *
  1766. * @public
  1767. */
  1768. getEngineName(toLowerCase) {
  1769. if (toLowerCase) {
  1770. return String(this.getEngine().name).toLowerCase() || '';
  1771. }
  1772. return this.getEngine().name || '';
  1773. }
  1774. /**
  1775. * Get parsed platform
  1776. * @return {{}}
  1777. */
  1778. parseEngine() {
  1779. this.parsedResult.engine = {};
  1780. const engine = Utils.find(enginesParsersList, (_engine) => {
  1781. if (typeof _engine.test === 'function') {
  1782. return _engine.test(this);
  1783. }
  1784. if (_engine.test instanceof Array) {
  1785. return _engine.test.some(condition => this.test(condition));
  1786. }
  1787. throw new Error("Browser's test function is not valid");
  1788. });
  1789. if (engine) {
  1790. this.parsedResult.engine = engine.describe(this.getUA());
  1791. }
  1792. return this.parsedResult.engine;
  1793. }
  1794. /**
  1795. * Parse full information about the browser
  1796. */
  1797. parse() {
  1798. this.parseBrowser();
  1799. this.parseOS();
  1800. this.parsePlatform();
  1801. this.parseEngine();
  1802. return this;
  1803. }
  1804. /**
  1805. * Get parsed result
  1806. * @return {ParsedResult}
  1807. */
  1808. getResult() {
  1809. return Utils.assign({}, this.parsedResult);
  1810. }
  1811. /**
  1812. * Check if parsed browser matches certain conditions
  1813. *
  1814. * @param {Object} checkTree It's one or two layered object,
  1815. * which can include a platform or an OS on the first layer
  1816. * and should have browsers specs on the bottom-laying layer
  1817. *
  1818. * @returns {Boolean|undefined} Whether the browser satisfies the set conditions or not.
  1819. * Returns `undefined` when the browser is no described in the checkTree object.
  1820. *
  1821. * @example
  1822. * const browser = Bowser.getParser(window.navigator.userAgent);
  1823. * if (browser.satisfies({chrome: '>118.01.1322' }))
  1824. * // or with os
  1825. * if (browser.satisfies({windows: { chrome: '>118.01.1322' } }))
  1826. * // or with platforms
  1827. * if (browser.satisfies({desktop: { chrome: '>118.01.1322' } }))
  1828. */
  1829. satisfies(checkTree) {
  1830. const platformsAndOSes = {};
  1831. let platformsAndOSCounter = 0;
  1832. const browsers = {};
  1833. let browsersCounter = 0;
  1834. const allDefinitions = Object.keys(checkTree);
  1835. allDefinitions.forEach((key) => {
  1836. const currentDefinition = checkTree[key];
  1837. if (typeof currentDefinition === 'string') {
  1838. browsers[key] = currentDefinition;
  1839. browsersCounter += 1;
  1840. } else if (typeof currentDefinition === 'object') {
  1841. platformsAndOSes[key] = currentDefinition;
  1842. platformsAndOSCounter += 1;
  1843. }
  1844. });
  1845. if (platformsAndOSCounter > 0) {
  1846. const platformsAndOSNames = Object.keys(platformsAndOSes);
  1847. const OSMatchingDefinition = Utils.find(platformsAndOSNames, name => (this.isOS(name)));
  1848. if (OSMatchingDefinition) {
  1849. const osResult = this.satisfies(platformsAndOSes[OSMatchingDefinition]);
  1850. if (osResult !== void 0) {
  1851. return osResult;
  1852. }
  1853. }
  1854. const platformMatchingDefinition = Utils.find(
  1855. platformsAndOSNames,
  1856. name => (this.isPlatform(name)),
  1857. );
  1858. if (platformMatchingDefinition) {
  1859. const platformResult = this.satisfies(platformsAndOSes[platformMatchingDefinition]);
  1860. if (platformResult !== void 0) {
  1861. return platformResult;
  1862. }
  1863. }
  1864. }
  1865. if (browsersCounter > 0) {
  1866. const browserNames = Object.keys(browsers);
  1867. const matchingDefinition = Utils.find(browserNames, name => (this.isBrowser(name, true)));
  1868. if (matchingDefinition !== void 0) {
  1869. return this.compareVersion(browsers[matchingDefinition]);
  1870. }
  1871. }
  1872. return undefined;
  1873. }
  1874. /**
  1875. * Check if the browser name equals the passed string
  1876. * @param browserName The string to compare with the browser name
  1877. * @param [includingAlias=false] The flag showing whether alias will be included into comparison
  1878. * @returns {boolean}
  1879. */
  1880. isBrowser(browserName, includingAlias = false) {
  1881. const defaultBrowserName = this.getBrowserName().toLowerCase();
  1882. let browserNameLower = browserName.toLowerCase();
  1883. const alias = Utils.getBrowserTypeByAlias(browserNameLower);
  1884. if (includingAlias && alias) {
  1885. browserNameLower = alias.toLowerCase();
  1886. }
  1887. return browserNameLower === defaultBrowserName;
  1888. }
  1889. compareVersion(version) {
  1890. let expectedResults = [0];
  1891. let comparableVersion = version;
  1892. let isLoose = false;
  1893. const currentBrowserVersion = this.getBrowserVersion();
  1894. if (typeof currentBrowserVersion !== 'string') {
  1895. return void 0;
  1896. }
  1897. if (version[0] === '>' || version[0] === '<') {
  1898. comparableVersion = version.substr(1);
  1899. if (version[1] === '=') {
  1900. isLoose = true;
  1901. comparableVersion = version.substr(2);
  1902. } else {
  1903. expectedResults = [];
  1904. }
  1905. if (version[0] === '>') {
  1906. expectedResults.push(1);
  1907. } else {
  1908. expectedResults.push(-1);
  1909. }
  1910. } else if (version[0] === '=') {
  1911. comparableVersion = version.substr(1);
  1912. } else if (version[0] === '~') {
  1913. isLoose = true;
  1914. comparableVersion = version.substr(1);
  1915. }
  1916. return expectedResults.indexOf(
  1917. Utils.compareVersions(currentBrowserVersion, comparableVersion, isLoose),
  1918. ) > -1;
  1919. }
  1920. isOS(osName) {
  1921. return this.getOSName(true) === String(osName).toLowerCase();
  1922. }
  1923. isPlatform(platformType) {
  1924. return this.getPlatformType(true) === String(platformType).toLowerCase();
  1925. }
  1926. isEngine(engineName) {
  1927. return this.getEngineName(true) === String(engineName).toLowerCase();
  1928. }
  1929. /**
  1930. * Is anything? Check if the browser is called "anything",
  1931. * the OS called "anything" or the platform called "anything"
  1932. * @param {String} anything
  1933. * @returns {Boolean}
  1934. */
  1935. is(anything) {
  1936. return this.isBrowser(anything) || this.isOS(anything) || this.isPlatform(anything);
  1937. }
  1938. /**
  1939. * Check if any of the given values satisfies this.is(anything)
  1940. * @param {String[]} anythings
  1941. * @returns {Boolean}
  1942. */
  1943. some(anythings = []) {
  1944. return anythings.some(anything => this.is(anything));
  1945. }
  1946. }
  1947. /*!
  1948. * Bowser - a browser detector
  1949. * https://github.com/lancedikson/bowser
  1950. * MIT License | (c) Dustin Diaz 2012-2015
  1951. * MIT License | (c) Denis Demchenko 2015-2019
  1952. */
  1953. /**
  1954. * Bowser class.
  1955. * Keep it simple as much as it can be.
  1956. * It's supposed to work with collections of {@link Parser} instances
  1957. * rather then solve one-instance problems.
  1958. * All the one-instance stuff is located in Parser class.
  1959. *
  1960. * @class
  1961. * @classdesc Bowser is a static object, that provides an API to the Parsers
  1962. * @hideconstructor
  1963. */
  1964. class Bowser {
  1965. /**
  1966. * Creates a {@link Parser} instance
  1967. *
  1968. * @param {String} UA UserAgent string
  1969. * @param {Boolean} [skipParsing=false] Will make the Parser postpone parsing until you ask it
  1970. * explicitly. Same as `skipParsing` for {@link Parser}.
  1971. * @returns {Parser}
  1972. * @throws {Error} when UA is not a String
  1973. *
  1974. * @example
  1975. * const parser = Bowser.getParser(window.navigator.userAgent);
  1976. * const result = parser.getResult();
  1977. */
  1978. static getParser(UA, skipParsing = false) {
  1979. if (typeof UA !== 'string') {
  1980. throw new Error('UserAgent should be a string');
  1981. }
  1982. return new Parser(UA, skipParsing);
  1983. }
  1984. /**
  1985. * Creates a {@link Parser} instance and runs {@link Parser.getResult} immediately
  1986. *
  1987. * @param UA
  1988. * @return {ParsedResult}
  1989. *
  1990. * @example
  1991. * const result = Bowser.parse(window.navigator.userAgent);
  1992. */
  1993. static parse(UA) {
  1994. return (new Parser(UA)).getResult();
  1995. }
  1996. static get BROWSER_MAP() {
  1997. return BROWSER_MAP;
  1998. }
  1999. static get ENGINE_MAP() {
  2000. return ENGINE_MAP;
  2001. }
  2002. static get OS_MAP() {
  2003. return OS_MAP;
  2004. }
  2005. static get PLATFORMS_MAP() {
  2006. return PLATFORMS_MAP;
  2007. }
  2008. }
  2009. var ONBOARDING_STATE = {
  2010. INSTALLED: 'INSTALLED',
  2011. NOT_INSTALLED: 'NOT_INSTALLED',
  2012. REGISTERED: 'REGISTERED',
  2013. REGISTERING: 'REGISTERING',
  2014. RELOADING: 'RELOADING',
  2015. };
  2016. var EXTENSION_DOWNLOAD_URL = {
  2017. CHROME: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
  2018. FIREFOX: 'https://addons.mozilla.org/firefox/addon/ether-metamask/',
  2019. DEFAULT: 'https://metamask.io',
  2020. };
  2021. // sessionStorage key
  2022. var REGISTRATION_IN_PROGRESS = 'REGISTRATION_IN_PROGRESS';
  2023. // forwarder iframe id
  2024. var FORWARDER_ID = 'FORWARDER_ID';
  2025. var Onboarding = /** @class */ (function () {
  2026. function Onboarding(_a) {
  2027. var _b = _a === void 0 ? {} : _a, _c = _b.forwarderOrigin, forwarderOrigin = _c === void 0 ? 'https://fwd.metamask.io' : _c, _d = _b.forwarderMode, forwarderMode = _d === void 0 ? Onboarding.FORWARDER_MODE.INJECT : _d;
  2028. this.forwarderOrigin = forwarderOrigin;
  2029. this.forwarderMode = forwarderMode;
  2030. this.state = Onboarding.isMetaMaskInstalled()
  2031. ? ONBOARDING_STATE.INSTALLED
  2032. : ONBOARDING_STATE.NOT_INSTALLED;
  2033. var browser = Onboarding._detectBrowser();
  2034. if (browser) {
  2035. this.downloadUrl = EXTENSION_DOWNLOAD_URL[browser];
  2036. }
  2037. else {
  2038. this.downloadUrl = EXTENSION_DOWNLOAD_URL.DEFAULT;
  2039. }
  2040. this._onMessage = this._onMessage.bind(this);
  2041. this._onMessageFromForwarder = this._onMessageFromForwarder.bind(this);
  2042. this._openForwarder = this._openForwarder.bind(this);
  2043. this._openDownloadPage = this._openDownloadPage.bind(this);
  2044. this.startOnboarding = this.startOnboarding.bind(this);
  2045. this.stopOnboarding = this.stopOnboarding.bind(this);
  2046. window.addEventListener('message', this._onMessage);
  2047. if (forwarderMode === Onboarding.FORWARDER_MODE.INJECT &&
  2048. sessionStorage.getItem(REGISTRATION_IN_PROGRESS) === 'true') {
  2049. Onboarding._injectForwarder(this.forwarderOrigin);
  2050. }
  2051. }
  2052. Onboarding.prototype._onMessage = function (event) {
  2053. if (event.origin !== this.forwarderOrigin) {
  2054. // Ignoring non-forwarder message
  2055. return undefined;
  2056. }
  2057. if (event.data.type === 'metamask:reload') {
  2058. return this._onMessageFromForwarder(event);
  2059. }
  2060. console.debug("Unknown message from '" + event.origin + "' with data " + JSON.stringify(event.data));
  2061. return undefined;
  2062. };
  2063. Onboarding.prototype._onMessageUnknownStateError = function (state) {
  2064. throw new Error("Unknown state: '" + state + "'");
  2065. };
  2066. Onboarding.prototype._onMessageFromForwarder = function (event) {
  2067. return __awaiter(this, void 0, void 0, function () {
  2068. var _a;
  2069. return __generator(this, function (_b) {
  2070. switch (_b.label) {
  2071. case 0:
  2072. _a = this.state;
  2073. switch (_a) {
  2074. case ONBOARDING_STATE.RELOADING: return [3 /*break*/, 1];
  2075. case ONBOARDING_STATE.NOT_INSTALLED: return [3 /*break*/, 2];
  2076. case ONBOARDING_STATE.INSTALLED: return [3 /*break*/, 3];
  2077. case ONBOARDING_STATE.REGISTERING: return [3 /*break*/, 5];
  2078. case ONBOARDING_STATE.REGISTERED: return [3 /*break*/, 6];
  2079. }
  2080. return [3 /*break*/, 7];
  2081. case 1:
  2082. console.debug('Ignoring message while reloading');
  2083. return [3 /*break*/, 8];
  2084. case 2:
  2085. console.debug('Reloading now to register with MetaMask');
  2086. this.state = ONBOARDING_STATE.RELOADING;
  2087. location.reload();
  2088. return [3 /*break*/, 8];
  2089. case 3:
  2090. console.debug('Registering with MetaMask');
  2091. this.state = ONBOARDING_STATE.REGISTERING;
  2092. return [4 /*yield*/, Onboarding._register()];
  2093. case 4:
  2094. _b.sent();
  2095. this.state = ONBOARDING_STATE.REGISTERED;
  2096. event.source.postMessage({ type: 'metamask:registrationCompleted' }, event.origin);
  2097. this.stopOnboarding();
  2098. return [3 /*break*/, 8];
  2099. case 5:
  2100. console.debug('Already registering - ignoring reload message');
  2101. return [3 /*break*/, 8];
  2102. case 6:
  2103. console.debug('Already registered - ignoring reload message');
  2104. return [3 /*break*/, 8];
  2105. case 7:
  2106. this._onMessageUnknownStateError(this.state);
  2107. _b.label = 8;
  2108. case 8: return [2 /*return*/];
  2109. }
  2110. });
  2111. });
  2112. };
  2113. /**
  2114. * Starts onboarding by opening the MetaMask download page and the Onboarding forwarder
  2115. */
  2116. Onboarding.prototype.startOnboarding = function () {
  2117. sessionStorage.setItem(REGISTRATION_IN_PROGRESS, 'true');
  2118. this._openDownloadPage();
  2119. this._openForwarder();
  2120. };
  2121. /**
  2122. * Stops onboarding registration, including removing the injected forwarder (if any)
  2123. *
  2124. * Typically this function is not necessary, but it can be useful for cases where
  2125. * onboarding completes before the forwarder has registered.
  2126. */
  2127. Onboarding.prototype.stopOnboarding = function () {
  2128. if (sessionStorage.getItem(REGISTRATION_IN_PROGRESS) === 'true') {
  2129. if (this.forwarderMode === Onboarding.FORWARDER_MODE.INJECT) {
  2130. console.debug('Removing forwarder');
  2131. Onboarding._removeForwarder();
  2132. }
  2133. sessionStorage.setItem(REGISTRATION_IN_PROGRESS, 'false');
  2134. }
  2135. };
  2136. Onboarding.prototype._openForwarder = function () {
  2137. if (this.forwarderMode === Onboarding.FORWARDER_MODE.OPEN_TAB) {
  2138. window.open(this.forwarderOrigin, '_blank');
  2139. }
  2140. else {
  2141. Onboarding._injectForwarder(this.forwarderOrigin);
  2142. }
  2143. };
  2144. Onboarding.prototype._openDownloadPage = function () {
  2145. window.open(this.downloadUrl, '_blank');
  2146. };
  2147. /**
  2148. * Checks whether the MetaMask extension is installed
  2149. */
  2150. Onboarding.isMetaMaskInstalled = function () {
  2151. return Boolean(window.ethereum && window.ethereum.isMetaMask);
  2152. };
  2153. Onboarding._register = function () {
  2154. return window.ethereum.request({
  2155. method: 'wallet_registerOnboarding',
  2156. });
  2157. };
  2158. Onboarding._injectForwarder = function (forwarderOrigin) {
  2159. var container = document.body;
  2160. var iframe = document.createElement('iframe');
  2161. iframe.setAttribute('height', '0');
  2162. iframe.setAttribute('width', '0');
  2163. iframe.setAttribute('style', 'display: none;');
  2164. iframe.setAttribute('src', forwarderOrigin);
  2165. iframe.setAttribute('id', FORWARDER_ID);
  2166. container.insertBefore(iframe, container.children[0]);
  2167. };
  2168. Onboarding._removeForwarder = function () {
  2169. var _a;
  2170. (_a = document.getElementById(FORWARDER_ID)) === null || _a === void 0 ? void 0 : _a.remove();
  2171. };
  2172. Onboarding._detectBrowser = function () {
  2173. var browserInfo = Bowser.parse(window.navigator.userAgent);
  2174. if (browserInfo.browser.name === 'Firefox') {
  2175. return 'FIREFOX';
  2176. }
  2177. else if (['Chrome', 'Chromium'].includes(browserInfo.browser.name || '')) {
  2178. return 'CHROME';
  2179. }
  2180. return null;
  2181. };
  2182. Onboarding.FORWARDER_MODE = {
  2183. INJECT: 'INJECT',
  2184. OPEN_TAB: 'OPEN_TAB',
  2185. };
  2186. return Onboarding;
  2187. }());
  2188. return Onboarding;
  2189. }());