ua_helpers.js (6450B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 /* globals browser, exportFunction */ 8 9 var UAHelpers = { 10 _deviceAppropriateChromeUAs: {}, 11 getRunningFirefoxVersion() { 12 return (navigator.userAgent.match(/Firefox\/([0-9.]+)/) || ["", "58.0"])[1]; 13 }, 14 getFxQuantumSegment() { 15 return `FxQuantum/${UAHelpers.getRunningFirefoxVersion()} `; 16 }, 17 getDeviceAppropriateChromeUA(config = {}) { 18 let { androidVersion, version = "143.0.0.0", phone, tablet, OS } = config; 19 const key = JSON.stringify(config); 20 if (config.noCache || !UAHelpers._deviceAppropriateChromeUAs[key]) { 21 const userAgent = 22 config.ua || 23 (typeof navigator !== "undefined" ? navigator.userAgent : ""); 24 const fxQuantum = config.noFxQuantum 25 ? "" 26 : UAHelpers.getFxQuantumSegment(); 27 const noOSGiven = !OS || OS === "nonLinux"; 28 if (OS === "android" || (noOSGiven && userAgent.includes("Android"))) { 29 const AndroidVersion = androidVersion 30 ? `Android ${androidVersion}` 31 : userAgent.match(/Android [0-9.]+/) || "Android 6.0"; 32 if (phone === undefined && tablet === undefined) { 33 phone = userAgent.includes("Mobile"); 34 tablet = userAgent.includes("Tablet"); 35 } 36 if (phone === true) { 37 phone = "Nexus 5 Build/MRA58N"; 38 } 39 if (tablet === true || (!tablet && !phone)) { 40 tablet = "Nexus 7 Build/JSS15Q"; 41 } 42 if (phone) { 43 UAHelpers._deviceAppropriateChromeUAs[key] = 44 `Mozilla/5.0 (Linux; ${AndroidVersion}; ${phone}) ${fxQuantum}AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version} Mobile Safari/537.36`; 45 } else { 46 UAHelpers._deviceAppropriateChromeUAs[key] = 47 `Mozilla/5.0 (Linux; ${AndroidVersion}; ${tablet}) ${fxQuantum}AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version} Safari/537.36`; 48 } 49 } else { 50 const WIN_SEGMENT = "Windows NT 11.0; Win64; x64"; 51 let osSegment; 52 if (OS === "macOS" || (noOSGiven && userAgent.includes("Macintosh"))) { 53 osSegment = "Macintosh; Intel Mac OS X 10_15_7"; 54 } else if ( 55 OS === "linux" || 56 (noOSGiven && userAgent.includes("Linux")) 57 ) { 58 if (OS !== "nonLinux") { 59 osSegment = "X11; Ubuntu; Linux x86_64"; 60 } else { 61 osSegment = WIN_SEGMENT; 62 } 63 } else { 64 osSegment = WIN_SEGMENT; 65 } 66 67 UAHelpers._deviceAppropriateChromeUAs[key] = 68 `Mozilla/5.0 (${osSegment}) ${fxQuantum}AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version} Safari/537.36`; 69 } 70 } 71 return UAHelpers._deviceAppropriateChromeUAs[key]; 72 }, 73 addGecko( 74 ua = navigator.userAgent, 75 version = UAHelpers.getRunningFirefoxVersion() 76 ) { 77 return `${ua} Gecko/${version}`; 78 }, 79 addChrome(ua = navigator.userAgent, version = "143.0.0.0") { 80 const isMobile = 81 navigator.userAgent.includes("Mobile") || 82 navigator.userAgent.includes("Tablet"); 83 return `${ua} AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version} ${isMobile ? "Mobile " : ""}Safari/537.36`; 84 }, 85 safari(config = {}) { 86 const version = config.version || "26.1"; 87 const webkitVersion = config.webkitVersion || "605.1.15"; 88 const osVersion = config.osVersion?.replace(".", "_") || "10_15_7"; 89 const arch = config.arch || "Intel"; 90 let firefox = ""; 91 if (config.withFirefox) { 92 firefox = `Firefox/${UAHelpers.getRunningFirefoxVersion()} `; 93 } else if (config.withFxQuantum) { 94 firefox = UAHelpers.getFxQuantumSegment(); 95 } 96 return `Mozilla/5.0 (Macintosh; ${arch} Mac OS X ${osVersion}) ${firefox}AppleWebKit/${webkitVersion} (KHTML, like Gecko) Version/${version} Safari/${webkitVersion}`; 97 }, 98 androidHotspot2Device(originalUA) { 99 return originalUA.replace(/\(.+?\)/, "(Linux; Android 10; K)"); 100 }, 101 changeFirefoxToFireFox(ua = navigator.userAgent) { 102 return ua.replace("Firefox", "FireFox"); 103 }, 104 windows(ua = navigator.userAgent) { 105 const rv = navigator.userAgent.match("rv:[0-9]+.[0-9]+")[0]; 106 return ua.replace(/\(.+?\)/, `(Windows NT 10.0; Win64; x64; ${rv})`); 107 }, 108 desktopUA(ua = navigator.userAgent) { 109 return ua.replace(/ (Mobile|Tablet);/, ""); 110 }, 111 addSamsungForSamsungDevices(ua = navigator.userAgent) { 112 if (!browser.systemManufacturer) { 113 return ua; 114 } 115 116 const manufacturer = browser.systemManufacturer.getManufacturer(); 117 if (manufacturer && manufacturer.toLowerCase() === "samsung") { 118 return ua.replace("Mobile;", "Mobile; Samsung;"); 119 } 120 121 return ua; 122 }, 123 getPrefix(originalUA) { 124 return originalUA.substr(0, originalUA.indexOf(")") + 1); 125 }, 126 overrideWithDeviceAppropriateChromeUA(config) { 127 const chromeUA = UAHelpers.getDeviceAppropriateChromeUA(config); 128 const nav = Object.getPrototypeOf(navigator.wrappedJSObject); 129 const ua = Object.getOwnPropertyDescriptor(nav, "userAgent"); 130 ua.get = exportFunction(() => chromeUA, window); 131 Object.defineProperty(nav, "userAgent", ua); 132 }, 133 capVersionTo99(originalUA) { 134 const ver = originalUA.match(/Firefox\/(\d+\.\d+)/); 135 if (!ver || parseFloat(ver[1]) < 100) { 136 return originalUA; 137 } 138 return originalUA 139 .replace(`Firefox/${ver[1]}`, "Firefox/99.0") 140 .replace(`rv:${ver[1]}`, "rv:99.0"); 141 }, 142 capRvTo109(originalUA) { 143 const ver = originalUA.match(/rv:(\d+\.\d+)/); 144 if (!ver || parseFloat(ver[1]) <= 109) { 145 return originalUA; 146 } 147 return originalUA.replace(`rv:${ver[1]}`, "rv:109.0"); 148 }, 149 capVersionToNumber(originalUA, cap = 120) { 150 const ver = originalUA.match(/Firefox\/(\d+\.\d+)/); 151 if (!ver || parseFloat(ver[1]) <= cap) { 152 return originalUA; 153 } 154 const capped = `Firefox/${cap}.0`; 155 return originalUA.replace(`Firefox/${ver[1]}`, capped); 156 }, 157 getMacOSXUA(originalUA, arch = "Intel", version = "10.15") { 158 return originalUA.replace( 159 /\(.+?\)/, 160 `(Macintosh; ${arch} Mac OS X ${version})` 161 ); 162 }, 163 getWindowsUA(originalUA) { 164 const rv = originalUA.match("rv:[0-9]+.[0-9]+")[0]; 165 const ver = originalUA.match("Firefox/[0-9]+.[0-9]+")[0]; 166 return `Mozilla/5.0 (Windows NT 10.0; Win64; x64; ${rv}) Gecko/20100101 ${ver}`; 167 }, 168 };