diff --git a/css/index.css b/css/index.css
index eeb341c0..40603c3b 100644
--- a/css/index.css
+++ b/css/index.css
@@ -56,10 +56,6 @@ code {
background: rgba(142, 142, 145, 0.25) !important;
padding: 2px 6px; /* top+bottom | left+ right */
}
-code.lies {
- background-color: rgba(255, 79, 79, 0.6) !important;
- color: white;
-}
#modaloverlay {
position: fixed;
@@ -122,6 +118,10 @@ a.return {color: var(--test12); text-decoration: none; font-size: 14px; line-he
.strike {text-decoration: line-through;}
.spaces {white-space: pre-wrap;}
.perf {font-family: monospace, "Courier New"; font-size: 12px; white-space: pre-wrap;}
+.lies {
+ color: var(--test99);
+ text-decoration: underline; /*var(--test0);*/
+}
.cursive {font-family: cursive;}
.emoji {font-family: emoji;}
diff --git a/css/media.css b/css/media.css
index 3673a5d8..f51bd478 100644
--- a/css/media.css
+++ b/css/media.css
@@ -58,7 +58,11 @@
@media (color:18){#cssC:after{content:"18";}}
@media (color:19){#cssC:after{content:"19";}}
@media (color:20){#cssC:after{content:"20";}}
-@media (color:21){#cssC:after{content:"";}}
+@media (color:21){#cssC:after{content:"21";}}
+@media (color:22){#cssC:after{content:"22";}}
+@media (color:23){#cssC:after{content:"23";}}
+@media (color:24){#cssC:after{content:"24";}}
+@media (color:25){#cssC:after{content:"";}}
#cssP:after{content:"n/a";}
@media (pointer:fine){#cssP:after{content:"fine";}}
diff --git a/js/audio.js b/js/audio.js
index 4f1e8a1f..14e57411 100644
--- a/js/audio.js
+++ b/js/audio.js
@@ -73,7 +73,7 @@ const get_audio2_context = (os = isOS) => new Promise(resolve => {
// ac-outputLatency is variable per tab and even on page load
// so on non RFP hashes, change it to variable and display the original on screen
- if (note !== rfp_green) {
+ if (isGecko && note !== rfp_green) {
latencynote = " [" + objnew["ac-outputLatency"]+ " latency]"
objnew["ac-outputLatency"] = "variable"
hash = mini(objnew)
diff --git a/js/css.js b/js/css.js
index cb5c97fa..24bd7d6f 100644
--- a/js/css.js
+++ b/js/css.js
@@ -19,20 +19,22 @@ function get_colors() {
'InfoText','Menu','MenuText','Scrollbar','ThreeDDarkShadow','ThreeDFace','ThreeDHighlight',
'ThreeDLightShadow','ThreeDShadow','Window','WindowFrame','WindowText',
],
- "moz": [ // FF117+:
+ "moz": [ // FF120+:
'-moz-buttonhoverface','-moz-buttonhovertext','-moz-cellhighlight','-moz-cellhighlighttext',
'-moz-combobox','-moz-comboboxtext','-moz-dialog','-moz-dialogtext','-moz-eventreerow','-moz-field',
'-moz-fieldtext','-moz-html-cellhighlight','-moz-html-cellhighlighttext','-moz-mac-active-menuitem',
'-moz-mac-active-source-list-selection','-moz-mac-defaultbuttontext','-moz-mac-disabledtoolbartext',
- '-moz-mac-focusring','-moz-mac-menuitem','-moz-mac-menupopup','-moz-mac-menutextdisable',
- '-moz-mac-menutextselect','-moz-mac-source-list','-moz-mac-source-list-selection','-moz-mac-tooltip',
- '-moz-menubarhovertext','-moz-menuhover','-moz-menuhovertext','-moz-nativehyperlinktext','-moz-oddtreerow',
+ '-moz-mac-focusring','-moz-mac-menuitem','-moz-mac-menupopup','-moz-mac-source-list',
+ '-moz-mac-source-list-selection','-moz-mac-tooltip','-moz-menubarhovertext','-moz-menuhover',
+ '-moz-menuhovertext','-moz-nativehyperlinktext','-moz-oddtreerow',
],
}
- if (isVer < 117) {
+ if (isVer < 120) { // ToDo: change to < 119 once beta backport confirmed
let aTmp = oList["moz"]
aTmp.push (
+ // removed/backported FF119 1857695
+ '-moz-mac-menutextdisable','-moz-mac-menutextselect',
// removed FF117
"-moz-buttondefault","-moz-dragtargetzone","-moz-mac-chrome-active","-moz-mac-chrome-inactive",
"-moz-mac-menuselect","-moz-mac-menushadow","-moz-mac-secondaryhighlight","-moz-menubartext",
@@ -85,9 +87,10 @@ function get_colors() {
let btn = addButton(14, METRIC, Object.keys(newobj).length +"/"+ count)
addData(14, METRIC, newobj, hash)
if (isSmart && type == "moz") {
- let check = "5a00aa84" // FF117+
- if (isVer < 103) {check = "c0df6598"} else if (isVer < 117) {check = "788e7d22"}
- notation = hash == check ? rfp_green : rfp_red // 1734115
+ let check = "47538602" // FF119+
+ if (isVer < 117) {check = "788e7d22" // 115-116
+ } else if (isVer < 119) {check = "5a00aa84"} // 117-118
+ notation = hash == check ? rfp_green : rfp_red
}
log_display(14, METRIC, hash + btn + notation)
} catch(e) {
@@ -118,7 +121,7 @@ function get_computed_styles() {
const names = ["styles_cssrulelist","styles_getcomputed","styles_htmlelement"]
let aErr = [false, false, false], isLies = false
let aHashes = [], intHashes = [], oDisplay = {}
- let check = (isSmart && isTB && isVer > 114)
+ let check = (isSmart && isTB)
let notation = check ? tb_red : ""
let styleVersion = type => {
@@ -297,12 +300,17 @@ function get_computed_styles() {
log_known(SECT14, METRIC)
} else {
if (check) {
- /* win diff
- layout.css.font-variations.enabled = locked false on win 7
- fontOpticalSizing, font-optical-sizing, fontVariationSettings, font-variation-settings
- */
- if (hash === "e32d06bd") {notation = tb_green // TB/MB win11 + linux, TB android: 1102
- } else if (hash === "e14684e7") {notation = tb_green} // TB/MB win7 1098
+ if (isOS == "mac") {
+ /* mac 1102 vs win 1102: mac has: MozOsxFontSmoothing, -moz-osx-font-smoothing */
+ if (hash === "75600d93") {notation = tb_green} // TB 1102
+ } else {
+ /* win diff
+ layout.css.font-variations.enabled = locked false on win 7
+ fontOpticalSizing, font-optical-sizing, fontVariationSettings, font-variation-settings
+ */
+ if (hash === "e32d06bd") {notation = tb_green // TB/MB win11 + linux, TB android: 1102
+ } else if (hash === "e14684e7") {notation = tb_green} // TB/MB win7 1098
+ }
}
addData(14, METRIC, res[lookup]["keys"], hash)
}
@@ -343,7 +351,7 @@ function get_computed_styles() {
const get_mm_css = () => new Promise(resolve => {
function get_mm(type, id, rfpvalue, minVer) {
- const METRIC = type
+ const METRIC = type, METRIC2 = type +"_css"
let value = zNA, display = value, q = type, isErr = false
try {
if (window.matchMedia("("+ q +":no-preference)").matches) {value = "no-preference"
@@ -362,24 +370,26 @@ const get_mm_css = () => new Promise(resolve => {
display = log_error(SECT14, METRIC, e)
value = zErr
}
+ let cssvalue = getElementProp(SECT14, "#css"+ id, METRIC2)
+ let isErrCss = cssvalue == zErr
if (isSmart) {
- let cssvalue = getElementProp(SECT14, "#css"+ id)
- if (value !== cssvalue && cssvalue !== "x") {
- if (!isErr) {
+ if (!isErr && !isErrCss) {
+ if (value !== cssvalue) {
display = colorFn(display)
value = zLIE
log_known(SECT14, METRIC)
}
}
if (rfpvalue !== undefined) {
- // notate: only apply notation from when it was flipped
+ // notate from when it was flipped
if (minVer == undefined || minVer < isVer) {
- display += display == rfpvalue ? rfp_green : rfp_red
+ display += display == rfpvalue ? rfp_green : rfp_red // mm
+ log_display(14, type +"_css", (cssvalue == rfpvalue ? rfp_green : rfp_red)) // css
}
}
}
log_display(14, type, display)
- res.push([METRIC, value])
+ res.push([METRIC, value], [METRIC2, cssvalue])
}
let res = []
diff --git a/js/devices.js b/js/devices.js
index 81c69bd4..0478e27a 100644
--- a/js/devices.js
+++ b/js/devices.js
@@ -66,11 +66,7 @@ const get_maxtouch = () => new Promise(resolve => {
})
const get_mm_color = () => new Promise(resolve => {
- const METRIC = "color"
- function exit(value, display) {
- log_display(7, METRIC, display)
- return resolve([METRIC, value])
- }
+ const METRIC = "color", METRIC2 = METRIC +"_css"
let isErr = false, value, display
try {
if (runSE) {foo++}
@@ -85,61 +81,57 @@ const get_mm_color = () => new Promise(resolve => {
} catch(e) {
isErr = true; value = zErr; display = log_error(SECT7, METRIC, e)
}
+ let cssvalue = getElementProp(SECT7, "#cssC", METRIC2)
+ let isErrCss = cssvalue == zErr
if (isSmart) {
- let cssvalue = getElementProp(SECT7, "#cssC")
- if (value !== cssvalue && cssvalue !== "x") {
- if (!isErr) {
+ if (!isErr && !isErrCss) {
+ if (value !== cssvalue) {
display = colorFn(display)
value = zLIE
log_known(SECT7, METRIC)
}
}
- display += display === 8 ? rfp_green : rfp_red
+ display += display === 8 ? rfp_green : rfp_red // mm
+ log_display(7, METRIC2, (cssvalue === 8 ? rfp_green : rfp_red)) // css
}
- exit(value, display)
+ log_display(7, METRIC, display)
+ return resolve([[METRIC, value], [METRIC2, cssvalue]])
})
const get_mm_colorgamut = () => new Promise(resolve => {
- const METRIC = "color-gamut"
- function exit(value, display) {
- log_display(7, METRIC, display)
- return resolve([METRIC, value])
- }
+ const METRIC = "color-gamut", METRIC2 = METRIC +"_css"
+ let value = zNA, display = value, isErr = false
try {
if (runSE) {foo++}
- let value = zNA, display = value
let q = "(color-gamut: "
if (window.matchMedia(q +"srgb)").matches) {value = "srgb"}
if (window.matchMedia(q +"p3)").matches) {value = "p3"}
if (window.matchMedia(q +"rec2020)").matches) {value = "rec2020"}
if (runSL) {value = "p3"}
display = value
- if (isSmart) {
- let cssvalue = getElementProp(SECT7, "#cssCG")
- if (value !== cssvalue && cssvalue !== "x") {
+ } catch(e) {
+ isErr = true; value = zErr; display = log_error(SECT7, METRIC, e)
+ }
+ let cssvalue = getElementProp(SECT7, "#cssCG", METRIC2)
+ let isErrCss = cssvalue == zErr
+ if (isSmart) {
+ if (!isErr && !isErrCss) {
+ if (value !== cssvalue) {
display = colorFn(display)
value = zLIE
log_known(SECT7, METRIC)
}
- // FF110+: 1422237
- if (isVer > 109) {
- display += display === "srgb" ? rfp_green : rfp_red
- }
}
- exit(value, display)
- } catch(e) {
- log_error(SECT7, METRIC, e)
- log_display(7, METRIC, zErr + (isSmart ? rfp_red : ""))
- return resolve([METRIC, zErr])
+ // FF110+: 1422237
+ display += display === "srgb" ? rfp_green : rfp_red // mm
+ log_display(7, METRIC2, (cssvalue === "srgb" ? rfp_green : rfp_red)) // css
}
+ log_display(7, METRIC, display)
+ return resolve([[METRIC, value], [METRIC2, cssvalue]])
})
const get_mm_pointer = (group, type, id, rfpvalue) => new Promise(resolve => {
- const METRIC = type
- function exit(value, display) {
- log_display(7, type, display)
- return resolve([METRIC, value])
- }
+ const METRIC = type, METRIC2 = type +"_css"
let value = zNA, display = value, isErr = false
try {
if (runSE) {foo++}
@@ -168,14 +160,15 @@ const get_mm_pointer = (group, type, id, rfpvalue) => new Promise(resolve => {
display = log_error(SECT7, METRIC, e)
isErr = true; value = zErr
}
+ let cssvalue = getElementProp(SECT7, id, METRIC2)
+ let isErrCss = cssvalue == zErr
if (isSmart) {
if (value !== zErr) {
- let cssvalue = getElementProp(SECT7, id)
- if (group == 2 && cssvalue !== "x") {
- let cssvalue2 = getElementProp(SECT7, id, ":before")
+ if (group == 2 && !isErrCss) {
+ let cssvalue2 = getElementProp(SECT7, id, METRIC2, ":before")
cssvalue = cssvalue2 + cssvalue
}
- if (value !== cssvalue && cssvalue !== "x") {
+ if (value !== cssvalue && !isErrCss) {
display = colorFn(display)
value = zLIE
log_known(SECT7, METRIC)
@@ -183,12 +176,15 @@ const get_mm_pointer = (group, type, id, rfpvalue) => new Promise(resolve => {
}
// notate: FF74+ 1607316
if (type == "any-pointer" && isOS !== "android") {
- display += display === "fine + fine" ? rfp_green : rfp_red
+ display += display === "fine + fine" ? rfp_green : rfp_red // mm
+ log_display(7, METRIC2, (cssvalue === "fine + fine" ? rfp_green : rfp_red)) // css
} else if (isOS == "android") {
- display += display === rfpvalue ? rfp_green : rfp_red
+ display += display === rfpvalue ? rfp_green : rfp_red // mm
+ log_display(7, METRIC2, (cssvalue === rfpvalue ? rfp_green : rfp_red)) // css
}
}
- exit(value, display)
+ log_display(7, type, display)
+ return resolve([[METRIC, value], [METRIC2, cssvalue]])
})
const get_media_devices = () => new Promise(resolve => {
@@ -202,10 +198,14 @@ const get_media_devices = () => new Promise(resolve => {
return value == "TypeError: navigator.mediaDevices is undefined" ? tb_green : tb_red
} else { // RFP
if (isLies) {return (isMullvad ? tb_red : rfp_red)}
- let rfplegacy = "02ab1e4c", rfpnew = "7a2e5d0c"
- if (isVer < 115) {rfpnew = rfplegacy
- } else if (isMullvad) {rfplegacy = rfpnew} // tor-browser#42043
- return ((value == rfplegacy || value == rfpnew) ? rfp_green : (isMullvad ? tb_red : rfp_red)) + legacy
+ let rfplegacy = "02ab1e4c", rfpnew = "7a2e5d0c"
+ if (isMullvad) {
+ // tor-browser#42043
+ return (value == rfpnew ? tb_green : tb_red) + legacy
+ } else {
+ // FF: ToDo: 1843434: add version check when flipped
+ return ((value == rfplegacy || value == rfpnew) ? rfp_green : rfp_red) + legacy
+ }
}
}
return "" + legacy
@@ -403,7 +403,6 @@ function get_plugins_mimetypes() {
get_mimetypes(),
]).then(function(results){
-
return resolve()
})
})
diff --git a/js/elements.js b/js/elements.js
index b9ca8bec..f683cd0e 100644
--- a/js/elements.js
+++ b/js/elements.js
@@ -3,7 +3,7 @@
const get_element_keys = () => new Promise(resolve => {
const METRIC = "htmlelement_keys"
const id = "html-element-version"
- let check = (isSmart && isTB && isVer > 114)
+ let check = (isSmart && isTB)
let notation = check ? tb_red : ""
function cleanup() {
diff --git a/js/fonts.js b/js/fonts.js
index 6534fc59..d6a5ecbb 100644
--- a/js/fonts.js
+++ b/js/fonts.js
@@ -97,9 +97,19 @@ let fntMaster = {
'Cantarell','DejaVu Sans','DejaVu Serif','Droid Sans','STIX', // fedora
'Dingbats','FreeMono','Ubuntu', // ubuntu
'Liberation Mono','Liberation Sans','Liberation Serif', // popular
+ // TB12 fontnames, should have been removed
+ 'Noto Serif Hmong Nyiakeng','Noto Sans Symbols2','STIX Math',
+ ],
+ 'mac': [
+ 'Apple Symbols','Avenir','Charter','Impact','Palatino','Rockwell',
+ // TB12 fontnames, should have been removed
+ 'Noto Serif Hmong Nyiakeng','Noto Sans Symbols2','STIX Math',
+ ],
+ 'windows': [
+ 'Calibri','Candara','Corbel','Impact','Ebrima','Gabriola',
+ // TB12 fontnames, should have been removed
+ 'Noto Serif Hmong Nyiakeng','Noto Sans Symbols2',
],
- 'mac': ['Apple Symbols','Avenir','Charter','Impact','Palatino','Rockwell',],
- 'windows': ['Calibri','Candara','Corbel','Impact','Ebrima','Gabriola',],
},
// kBaseFonts: https://searchfox.org/mozilla-central/search?path=StandardFonts*.inc
'base': {
@@ -120,6 +130,8 @@ let fntMaster = {
'Microsoft Sans Serif','Microsoft Tai Le','Microsoft YaHei','Microsoft Yi Baiti','MingLiU-ExtB','MingLiU_HKSCS-ExtB',
'Mongolian Baiti','NSimSun','PMingLiU-ExtB','Palatino Linotype','Segoe Print','Segoe Script','Segoe UI','Segoe UI Symbol',
'SimSun','SimSun-ExtB','Sylfaen','Symbol','Tahoma','Times New Roman','Trebuchet MS','Verdana','Webdings','Wingdings',
+ // 7 but not detected if font-vis < 3: 1720408
+ 'Franklin Gothic Medium',
// 8
'Gadugi','Nirmala UI','Microsoft JhengHei UI','Microsoft YaHei UI','Myanmar Text',
// 8.1
@@ -127,21 +139,19 @@ let fntMaster = {
'Sitka Heading','Sitka Small','Sitka Subheading','Sitka Text','Yu Gothic',
// 10
'Bahnschrift','HoloLens MDL2 Assets','Segoe MDL2 Assets','Segoe UI Historic','Yu Gothic UI',
- // FontSubstitutes
- // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes
- 'MS Shell Dlg','MS Shell Dlg \\32', // might differ based on system locale/install
- 'Helv','Helvetica','Times','Tms Rmn', // seems stable
-
- // localized: kBase: detected FF120+: 1850672
+ // localized: kBase: detected FF119+: 1850672
'微软雅黑', // Microsoft YaHei
'MS ゴシック', // MS Gothic
'MS Pゴシック', // MS PGothic
'宋体', // SimSun
'游ゴシック', // Yu Gothic
-
/* ignore: https://searchfox.org/mozilla-central/source/gfx/thebes/gfxDWriteFontList.cpp#1990
'MS Sans Serif','MS Serif','Courier','Small Fonts','Roman',
*/
+ // FontSubstitutes
+ // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes
+ 'MS Shell Dlg','MS Shell Dlg \\32', // might differ based on system locale/install
+ 'Helv','Helvetica','Times','Tms Rmn', // seems stable
/* variants
// 7
@@ -236,6 +246,8 @@ let fntMaster = {
'Simplified Arabic Fixed','Traditional Arabic','Tunga','UD Digi Kyokasho N-B','UD Digi Kyokasho N-R',
'UD Digi Kyokasho NK-B','UD Digi Kyokasho NK-R','UD Digi Kyokasho NP-B','UD Digi Kyokasho NP-R','Urdu Typesetting',
'Utsaah','Vani','Verdana Pro','Vijaya','Vrinda','Yu Mincho',
+ // win11
+ 'Sans Serif Collection',
// localized ^
'바탕', // Batang
'BIZ UDPゴシック', // BIZ UDPGothic
@@ -247,8 +259,6 @@ let fntMaster = {
'MS P明朝', // MS PMincho
'新細明體', // PMingLiU
- // kBase but broken: 1720408
- 'Franklin Gothic Medium',
// MS products
'Arial Unicode MS','MS Reference Specialty','MS Outlook',
// MS downloads
@@ -287,34 +297,6 @@ function set_fntList(os = isOS) {
"generic": [],
}
- // diffs fom TB13
- if (isTB) {
- if (isVer < 115) {
- // ToDo: isSmartMin=115 remove
- // renamed: Noto Sans Symbols 2 (new) vs Noto Sans Symbols2 (old)
- let tmpArray = fntMaster["bundled"]["allnotosans"]
- tmpArray.push("Symbols2")
- tmpArray = tmpArray.filter(x => !["Symbols 2"].includes(x))
- fntMaster["bundled"]["allnotosans"] = tmpArray.sort()
- // renamed: Noto Serif NP Hmong (new) vs Noto Serif Hmong Nyiakeng (old)
- tmpArray = fntMaster["bundled"]["allnotoserif"]
- tmpArray.push("Hmong Nyiakeng")
- tmpArray = tmpArray.filter(x => !["NP Hmong"].includes(x))
- fntMaster["bundled"]["allnotoserif"] = tmpArray.sort()
- // mac/linux: STIX Two Math (new) vs STIX Math (old)
- tmpArray = fntMaster["bundled"]["linux"]
- tmpArray.push("STIX Math")
- tmpArray = tmpArray.filter(x => !["STIX Two Math"].includes(x))
- fntMaster["bundled"]["linux"] = tmpArray.sort()
- fntMaster["bundled"]["mac"] = ['Noto Sans Armenian','Noto Sans Hebrew','Noto Serif Armenian','Noto Serif Hebrew','STIX Math',]
- } else {
- // make sure old fonts + font names were removed
- fntMaster.blocklist.windows.push("Noto Serif Hmong Nyiakeng","Noto Sans Symbols2")
- fntMaster.blocklist.linux.push("Noto Serif Hmong Nyiakeng","Noto Sans Symbols2","STIX Math")
- fntMaster.blocklist.mac.push("Noto Serif Hmong Nyiakeng","Noto Sans Symbols2","STIX Math")
- }
- }
-
// baseSize: add fallback for misconfigured/missing
// isPlatformFont: expected + can't be blocked + differs vs most fonts
// no entropy loss: size collisions of expected system fonts e.g. Tahoma
@@ -992,6 +974,7 @@ const get_system_fonts = (os = isOS) => new Promise(resolve => {
]
let aProps = ['font-size','font-style','font-weight','font-family']
let oRes = {}, notation = ""
+ let check = (isSmart && isTB)
try {
if (runSE) {foo++}
let el = dom.sysFont
@@ -1005,14 +988,14 @@ const get_system_fonts = (os = isOS) => new Promise(resolve => {
let newobj = {}, count = 0
for (const k of Object.keys(oRes).sort()) {newobj[k] = oRes[k]; count += newobj[k].length}
let hash = mini(newobj)
- if (isSmart && isTB && isVer > 114) {
+ if (check) {
// https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/41646
notation = tb_red
if (os == "windows") {
/* "12px normal 400 sans-serif" */
if (hash == "c89fb033") {notation = tb_green}
} else if (os == "mac") {
- if (hash == "") {notation = tb_green}
+ if (hash == "1dc326ac") {notation = tb_green}
} else if (os == "linux") {
/* "15px normal 400 sans-serif" */
if (hash == "7b469d36") {notation = tb_green}
@@ -1025,7 +1008,7 @@ const get_system_fonts = (os = isOS) => new Promise(resolve => {
log_display(12, METRIC, hash + addButton(12, METRIC, Object.keys(newobj).length +"/"+ count) + notation)
return resolve()
} catch(e) {
- notation = (isSmart && isTB && isVer > 14) ? tb_red : ""
+ notation = check ? tb_red : ""
log_display(12, METRIC, log_error(SECT12, METRIC, e) + notation)
return resolve([METRIC, zErr])
}
diff --git a/js/generic.js b/js/generic.js
index 2cab1885..4875f5c9 100644
--- a/js/generic.js
+++ b/js/generic.js
@@ -121,7 +121,7 @@ function json_stringify(passedObj, options = {}) {
const newFn = x => typeof x != 'string' ? x : new Function(x)()
function nowFn() {if (isPerf) {return performance.now()}; return}
-function colorFn(str) {return ""+ str +"
"}
+function colorFn(str) {return ""+ str +""}
function rnd_string() {return Math.random().toString(36).substring(2, 15)}
function rnd_number() {return Math.floor((Math.random() * (99999-10000))+10000)}
@@ -158,19 +158,45 @@ function run_basic() {
}
}
-function getElementProp(SECT, id, pseudo = ":after") {
- if (runPS) {return "x"}
+function getElementProp(SECT, id, name, pseudo = ":after") {
+ // default none: https://www.w3.org/TR/CSS21/generate.html#content
try {
+ if (runSE) {foo++}
let item = window.getComputedStyle(document.querySelector(id), pseudo)
item = item.getPropertyValue("content")
- if (item == "none") {item = "x"}
- item = item.replace(/"/g,"")
+ if (runPS) {item = "none"}
+ let originalitem = item
+ item = item.replace(/"/g,"") // trim quote marks
+ //console.log(SECT, id, name, pseudo, "~"+ item +"~", "~"+ originalitem +"~")
+
+ // out of range: screen/window returns "none"
+ if (id == "#S" || id == "#D") {
+ if (item == "none") {
+ item = "?"
+ } else if (pseudo == ":after") {
+ item = item.slice(3)
+ }
+ } else if (id == "#P") {
+ // out of range: dpi returns ""
+ if (item == "") {item = "?"}
+ }
if (!isNaN(item * 1)) {item = item * 1} // number
- if (item == "") {item = "x"} // blanks
+
+ // fuckery
+ if (item == "") {
+ log_error(SECT, name, zErrInvalid +"got ''")
+ item = zErr
+ } else if (originalitem == "none") {
+ // ignore screen/window
+ if (id !== "#S" && id !== "#D") {
+ log_error(SECT, name, zErrInvalid +"got 'none'")
+ item = zErr
+ }
+ }
return item
} catch(e) {
- log_error(SECT, id, e)
- return "x"
+ log_error(SECT, name, e)
+ return zErr
}
}
@@ -272,6 +298,9 @@ function get_isGecko() {
}
const get_isOS = () => new Promise(resolve => {
+ if (!isGecko) {
+ return resolve()
+ }
let t0 = nowFn()
setTimeout(() => resolve(zErrTime), 100)
const METRIC = "isOS"
@@ -356,6 +385,9 @@ const get_isSystemFont = () => new Promise(resolve => {
})
const get_isTB = () => new Promise(resolve => {
+ if (!isGecko) {
+ return resolve(false)
+ }
let t0 = nowFn()
setTimeout(() => resolve(t0), 150)
const METRIC = "isTB"
@@ -388,13 +420,11 @@ const get_isTB = () => new Promise(resolve => {
})
const get_isVer = () => new Promise(resolve => {
+ if (!isGecko) {
+ return resolve()
+ }
let t0 = nowFn()
function output(verNo) {
- if (!Number.isInteger(verNo)) {
- log_perf(SECTG, "isVer", t0, "", verNo)
- isVer = 0
- return resolve()
- }
isVer = verNo
if (verNo < 102) {isVerExtra = " or lower"
} else if (verNo == 120) {isVerExtra = "+"}
@@ -428,7 +458,8 @@ const get_isVer = () => new Promise(resolve => {
}
return 101
} catch(e) {
- return zErr
+ console.error(e)
+ return 0
}
}
})
@@ -436,6 +467,9 @@ const get_isVer = () => new Promise(resolve => {
/*** PREREQ ***/
const get_isClientRect = () => new Promise(resolve => {
+ if (!isGecko) {
+ return resolve()
+ }
// determine valid domrect methods
let t0 = nowFn()
let aNames = ["Element.getBoundingClientRect", "Element.getClientRects",
@@ -547,17 +581,20 @@ function showMetrics(name, scope, isConsole = false) {
let data, showhash = true, results, color = 99
if (name == SECT98 || name == SECT99) { data = gData[name]
- } else if (name == "fingerprint" || name == "errors" || name == "health") {
+ } else if (name == "fingerprint" || name == "errors" || name == "health" || name == "lies") {
data = gData[name][scope]
} else if (name == "fingerprint_summary") { data = gData[zFP][scope+"_summary"]
- } else if (name == "untrustworthy") {data = gKnown
- } else if (name == "known methods") {data = gMethods
} else if (name == "alerts") {data = gAlert; showhash = false
} else if (name.slice(0,6) == "errors") {
name = name.slice(6)
data = sData["errors"][scope][name]
name = name.toUpperCase() +": errors"
showhash = false
+ } else if (name.slice(0,4) == "lies") {
+ name = name.slice(4)
+ data = sData["lies"][scope][name]
+ name = name.toUpperCase() +": lies"
+ showhash = false
} else if (sectionNames.includes(name)) {
data = sData[zFP][scope][name]; name = name.toUpperCase()
} else {
@@ -611,7 +648,13 @@ function output_health(scope) {
} else if (metric == "fontnames") {
data = sDetail[scope]["fontnames_health"]
} else if (metric == "letterboxing" || metric == "new_window") {
- data = gData[zFP][scope]["screen"]["metrics"]["window_inner"]
+ data = gData[zFP][scope]["screen"]["metrics"]["window_sizes"]["metrics"]["innerWidth"]
+ +" x "+ gData[zFP][scope]["screen"]["metrics"]["window_sizes"]["metrics"]["innerHeight"]
+ } else {
+ let aList = ["devicePixelRatio", "-moz-device-pixel-ratio", "dpi", "dpcm", "dppx", "dpi_css"]
+ if (aList.includes(metric)) {
+ data = gData[zFP][scope]["screen"]["metrics"]["pixels"]["metrics"][metric]
+ }
}
// handle non data so at least it shows in JSON display
if (data == undefined) { data =""}
@@ -731,7 +774,7 @@ function output_section(section, scope) {
try {
btnList.forEach(function(item) {
let once = item+"once"
- if (gData[once][scope] !== undefined) {
+ if (gData[once] !== undefined && gData[once][scope] !== undefined) {
for (const s of Object.keys(gData[once][scope])) {
if (!sectionNames.includes(s)) {
// non-section: straight to sData: sorted
@@ -823,12 +866,19 @@ function output_section(section, scope) {
btnList.forEach(function(item) {
let btn = "", source = {}, target = {}
if (sDataTemp[item][scope] !== undefined && sDataTemp[item][scope][name] !== undefined) {
- if (sData[item][scope] == undefined) {sData[item][scope] = {}}
- if (sData[item][scope][name] == undefined) {sData[item][scope][name] = {}}
- for (const m of Object.keys(sDataTemp[item][scope][name]).sort()) {
- sData[item][scope][name][m] = sDataTemp[item][scope][name][m]
+ let len = 0
+ if (sData[item][scope] == undefined) {sData[item][scope] = {}}
+ if (sData[item][scope][name] == undefined) {sData[item][scope][name] = {}}
+ if (item == "errors") {
+ for (const m of Object.keys(sDataTemp[item][scope][name]).sort()) {
+ sData[item][scope][name][m] = sDataTemp[item][scope][name][m]
+ }
+ len = Object.keys(sData[item][scope][name]).length
+ } else {
+ let array = sDataTemp[item][scope][name].sort()
+ sData[item][scope][name] = array
+ len = array.length
}
- let len = Object.keys(sData[item][scope][name]).length
// catch zero length: e.g. object cleared not deleted
if (len > 0) {
let btnText = len + " "+ (len == 1 ? item.slice(0,-1) : item) // single/plural
@@ -846,10 +896,8 @@ function output_section(section, scope) {
/*** INCOMING ***/
-function addButton(color, name, text = "details", btn = "btnc", scope = isScope, color2 = undefined) {
- text = "["+ text +"]"
- if (color2 !== undefined) {text = colorFn(text)}
- return " "+ text +""
+function addButton(color, name, text = "details", btn = "btnc", scope = isScope) {
+ return " ["+ text +"]"
}
function addData(section, metric, data, hash = undefined, includeDetail = true) {
@@ -954,8 +1002,11 @@ function log_health(scope, type, section, metric, h = "health") {
}
}
-function log_known(section, metric) {
- if (gRun) {gKnown.push(section +":" + metric)}
+function log_known(section, metric, scope = isScope) {
+ let obj = "lies"
+ if (sDataTemp[obj][scope] == undefined) {sDataTemp[obj][scope] = {}}
+ if (sDataTemp[obj][scope][section] == undefined) {sDataTemp[obj][scope][section] = []}
+ sDataTemp[obj][scope][section].push(metric)
}
function log_perf(section, metric = "", time1, time2, extra) {
@@ -1051,27 +1102,6 @@ function log_section(name, time, scope = isScope) {
gAlert = gAlert.concat(gAlertOnce)
gAlert = gAlert.filter(function(item, position) {return gAlert.indexOf(item) === position})
gAlert.sort()
- gKnown = gKnown.filter(function(item, position) {return gKnown.indexOf(item) === position})
- gKnown.sort()
- gMethods = gMethods.filter(function(item, position) {return gMethods.indexOf(item) === position})
- gMethods.sort()
- // known
- let knownStr = ""
- if (gKnown.length) {
- let knownText = gKnown.length +" lie"+ (gKnown.length > 1 ? "s" : "")
- knownStr = mini(gKnown) + addButton(0, "untrustworthy", knownText, "btnc", zDOC, 1)
- } else {
- knownStr = isSmart ? "none" : zNA
- }
- dom.knownhash.innerHTML = knownStr
- // methods
- if (gMethods.length) {
- let methodStr = gMethods.length +" noted"
- let methodBtn = addButton(0, "known methods", methodStr)
- dom.knownmethods.innerHTML = mini(gMethods) + methodBtn
- } else {
- dom.knownmethods = isSmart ? "none" : zNA
- }
// alerts
dom.allcheck = (gAlert.length ? "[ alerts ]" : "")
@@ -1087,19 +1117,18 @@ function log_section(name, time, scope = isScope) {
/*** RUN ***/
function countJS(filename) {
- if (!isGecko) {
+ if (!isGecko && !isAllowNonGecko) {
isBlock = true
run_block() // non-gecko
return
}
-
jsFiles++
if (jsFiles === 1) {
get_isVer() // as long as don't touch the dom this is fine here: required for isTB
get_isSystemFont()
return
} else if (jsFiles === jsFilesExpected) {
- gData["perf"].push([1, "RUN ONCE", nowFn()])
+ if (isGecko) {gData["perf"].push([1, "RUN ONCE", nowFn()])}
let t0 = nowFn()
Promise.all([
get_isTB()
@@ -1110,7 +1139,13 @@ function countJS(filename) {
log_perf(SECTG, METRIC, results[0], "", zErrTime)
log_alert(SECTG, METRIC +": "+ zErrTime, true)
}
- isBlock = isVer < isBlockMin[0]
+ // might allow non-Gecko later
+ if (isGecko) {
+ isBlock = isVer < isBlockMin[0]
+ } else {
+ isBlock = false // allow non-gecko
+ isSmart = false // force basic mode
+ }
if (isBlock) {
run_block() // old gecko
return
@@ -1232,6 +1267,7 @@ function outputSection(id, cls) {
//*/
gData[zFP] = {"document":{}, "document_summary": {}}
gData["errors"] = {}
+ gData["lies"] = {}
if (!gLoad) { // don't wipe gLoad perf
gData["perf"] = []
}
@@ -1240,12 +1276,14 @@ function outputSection(id, cls) {
"errors": {},
"fingerprint": {"document":{}},
"health": {},
+ "lies": {},
}
// sDataTemp
sDataTemp = {
"display": {"document":{}},
"errors": {},
"fingerprint": {"document":{}},
+ "lies": {},
"perf": [],
}
sDetail = {}
@@ -1272,7 +1310,6 @@ function outputSection(id, cls) {
gCount = 0
gAlert = []
gKnown = []
- gMethods = []
// reset section
sDetail = {}
get_isDevices()
diff --git a/js/globals.js b/js/globals.js
index 25d2cf75..8d9708af 100644
--- a/js/globals.js
+++ b/js/globals.js
@@ -4,7 +4,7 @@ var dom;
const SECTG = "_global", SECTP = "_prereq", SECTNF = "NON-FP",
SECT1 = "screen", SECT2 = "ua", SECT3 = "feature", SECT4 = "region",
- SECT5 = "network", SECT6 = "storage", SECT7 = "devices", SECT9 = "canvas",
+ SECT5 = "headers", SECT6 = "storage", SECT7 = "devices", SECT9 = "canvas",
SECT10 = "webgl", SECT11 = "audio", SECT12 = "fonts", SECT13 = "media",
SECT14 = "css", SECT15 = "elements", SECT18 = "misc",
SECT98 = "prototype", SECT99 = "proxy"
@@ -17,7 +17,7 @@ const sectionMap = {
let sectionOrder = [], sectionNames = []
-const btnList = ["errors"] // ToDo: expand e.g alerts, lies
+const btnList = ["errors", "lies"] // ToDo: expand e.g alerts
const jsFilesExpected = 14
let gCountExpected = 15
@@ -29,7 +29,6 @@ let gData = { // from sData
"perf": [],
},
gKnown = [], // known, methods, alerts
- gMethods = [],
gAlert = [],
gAlertOnce = []
@@ -134,12 +133,12 @@ let isArch = true,
isOSErr,
isSystemFont = [],
isTB = false,
- isVer,
+ isVer = 0,
isVerExtra = "",
isWordmark
// other
-let isClientRect = 1,
+let isClientRect = 0,
isPerf = false
// runtypes
@@ -147,8 +146,9 @@ let gt0, gt1,
gLoad = true,
gRun = true,
gClick = true,
+ isAllowNonGecko = false, // not supported: to see what other engines return
isBlock = true,
- isBlockMin = [115, 13], // [FF, equivalent TB version]
+ isBlockMin = [102, 12], // [FF, equivalent TB version]
isSmart = false,
isSmartMin = 115 // we can't treat TB differently as we haven't gotten isMullvad yet which if true then sets isTB
diff --git a/js/media.js b/js/media.js
index d2cb5002..af1f9194 100644
--- a/js/media.js
+++ b/js/media.js
@@ -237,7 +237,7 @@ const get_midi = () => new Promise(resolve => {
let notation = "", count = 0
function exit(name, value) {
count++
- if (isSmart && isVer > 109) {
+ if (isSmart) {
notation = value == "prompt" ? default_green : default_red
}
addData(13, name, value)
diff --git a/js/misc.js b/js/misc.js
index d1eaa798..a2b88c91 100644
--- a/js/misc.js
+++ b/js/misc.js
@@ -11,7 +11,6 @@ function check_mathLies() {
}
const get_component_shims = () => new Promise(resolve => {
- // ToDo: 1448046: isSmartMin=115 ? remove this metric
const METRIC = "component_interfaces"
let notation = ""
try {
@@ -207,22 +206,23 @@ function get_navigator() {
display = colorFn(display)
log_known(SECT18, METRIC)
}
- // health: only do TB/MB as ESR is stable
+ // health: 115+ only do TB/MB as ESR is stable
// otherwise it's way too much work to track OSes/releases and beta/early etc
- if (isSmart && isTB && isVer > 114) {
+ if (isSmart && isTB) {
notation = tb_red
if (!isLies) {
if (isMullvad) {
- // MB
+ // MB13 desktop
if (hash === "1bfbd5d3") {notation = tb_green} // 37: mediaDevices, mediaSession
} else {
- // TB
- if (isOS == "android") {
- if (hash === "3b7f79c3") {notation = tb_green} // 37: share, canShare (dom.webshare.enabled)
- } else {
- if (hash === "1054f985") {notation = tb_green} // 35
- }
+ if (isOS == "android") {
+ // TBA13
+ if (hash === "3b7f79c3") {notation = tb_green} // 37: share, canShare (dom.webshare.enabled)
+ } else {
+ // TB13 desktop
+ if (hash === "1054f985") {notation = tb_green} // 35
}
+ }
}
}
log_display(18, METRIC, display + addButton(18, METRIC, keys.length) + tamperBtn + notation)
@@ -257,10 +257,9 @@ function get_recursion(log = false) {
}
function get_perf_mark_entries() {
- // ToDo: isSmartMin=115 remove this metric
+ // FF111+ 1811567: no longer a health metric, but keep to detect timing fuckery
const METRIC = "perf_mark_entries"
- let entries = "", valueEntries = "", ctrlEntries = "0, 0, 0, 0"
- let measure = "", notation = ""
+ let entries = "", valueEntries = "", ctrlEntries = "0, 0, 0, 0", measure = ""
try {
if (runSE) {foo++}
performance.mark("a")
@@ -291,15 +290,10 @@ function get_perf_mark_entries() {
// cleanup
performance.clearMarks()
performance.clearMeasures()
- // FF111+ 811567
- if (isSmart && isVer < 111) {
- notation = entries == ctrlEntries && measure == 0 ? rfp_green : rfp_red
- }
- log_display(18, METRIC, entries +" | "+ measure + notation)
+ log_display(18, METRIC, entries +" | "+ measure)
return [METRIC, valueEntries +" | "+ measure]
} catch(e) {
- if (isSmart && isVer < 111) {notation = rfp_red}
- log_display(18, METRIC, log_error(SECT18, METRIC, e) + notation)
+ log_display(18, METRIC, log_error(SECT18, METRIC, e))
return [METRIC, zErr]
}
}
@@ -323,8 +317,8 @@ function get_perf_now(log = false) {
}
// analyse
function output() {
- let isMatch = true,
- goodRFP = [0, 16.7, 16.6, 33.3, 33.4, 50, 66.6, 66.7]
+ let isMatch = true
+ let goodRFP = [0, 16.6, 16.7, 33.3, 33.4, 50, 66.6, 66.7, 83.3, 83.4, 100, 116.6, 116.7]
// tidy times
for (let i=0; i < aData.length ; i++) {
let time = aData[i] - p0
@@ -392,7 +386,7 @@ const get_window_props = () => new Promise(resolve => {
/* https://github.com/abrahamjuliot/creepjs */
let t0 = nowFn(), iframe
const METRIC = "window_properties"
- let check = (isSmart && isTB && isVer > 114)
+ let check = (isSmart && isTB)
let notation = check ? tb_red : ""
try {
@@ -416,10 +410,6 @@ const get_window_props = () => new Promise(resolve => {
// cleanup
iframe.parentNode.removeChild(iframe)
- // ToDo: isSmartMin=115 remove this metric
- let perf = aProps.includes("PerformanceNavigationTiming") ? zE : zD
- if (isSmart && isVer < 111) {perf += (perf == zD ? rfp_green : rfp_red)} // 78-110: 1511941 - 1811567
- log_display(18, "perf_navigation", perf)
// wasm
let wasm = aProps.includes("WebAssembly") ? zE : zD
if (isSmart && isTB) {wasm += (wasm == zE ? tb_standard : tb_safer)}
@@ -464,11 +454,17 @@ const get_window_props = () => new Promise(resolve => {
display += addButton(18, METRIC, aProps.length) + tamperBtn
// health
if (check && fpvalue !== zLIE) {
+ // ToDo: touch devices
+ // "Touch", "TouchEvent", "TouchList","ontouchcancel", "ontouchend", "ontouchmove", "ontouchstart"
+ // e.g. is not in my windows touch-capable laptop but may be present in a tablet
+ // dom.w3c_touch_events.enabled: 0=disabled (macOS) 1=enabled 2=autodetect (linux/win/android)
+ // autodetection is currently only supported on Windows and GTK3 (and assumed on Android)
+ // on touch devices: 0 (all false) 1 or 2 (all true)
if (isMullvad) {
if (fpvalue == "0d0dd5d5" || fpvalue == "8815bd33") {notation = tb_green} // 823 standard | 822 safer
} else {
if (isOS == "android") {
- notation = sbx +" TBv13 "+ fpvalue +"]"+sc
+ if (fpvalue == "c70d9b44" || fpvalue == "6623eaa2") {notation = tb_green} // 783 standard | 782 safer
} else {
if (fpvalue == "226bc5ca" || fpvalue == "df3d8de8") {notation = tb_green} // 774 standard | 773 safer
}
@@ -498,7 +494,6 @@ const get_window_props = () => new Promise(resolve => {
try {iframe.parentNode.removeChild(iframe)} catch(err) {}
let eMsg = log_error(SECT18, METRIC, e)
let note = (isSmart && isTB) ? rfp_red : ""
- log_display(18, "perf_navigation", eMsg + note) // ToDo: 1448046: isSmartMin=115 ? remove this metric
log_display(18, "wasm", eMsg + (isSmart && isTB ? tb_slider_red : ""))
log_display(18, "webgpu", eMsg + note)
diff --git a/js/region.js b/js/region.js
index 14948530..8c3c4647 100644
--- a/js/region.js
+++ b/js/region.js
@@ -2,7 +2,6 @@
const get_geo = () => new Promise(resolve => {
const METRIC = "geolocation"
-
// nav
let value, display
try {
@@ -25,7 +24,6 @@ const get_geo = () => new Promise(resolve => {
value = zErr, display = value
log_error(SECT4, METRIC +"_navigator", e)
}
-
// window
let geoWin
try {
@@ -87,7 +85,7 @@ const get_nav_connection = () => new Promise(resolve => {
if (isSmart && sData[SECT99].includes("Navigator.connection")) {
nav = zLIE
display = colorFn(display)
- log_known(METRIC)
+ log_known(SECT5, METRIC)
}
finish(nav, display)
} else {
@@ -144,20 +142,22 @@ const get_nav_dnt = () => new Promise(resolve => {
// expected nav: i.e you can't remove it
const METRIC = "doNotTrack"
function exit(value, display) {
- log_display(5, METRIC, display)
+ log_display(5, METRIC, display +"")
return resolve([METRIC, value])
}
try {
let value = navigator[METRIC]
if (runST) {value = 1}
let display = value
- if ("1" !== value && "unspecified" !== value) {
- if ("string" === typeof value) {
- display = log_error(SECT5, METRIC, zErrInvalid + cleanFn(value))
- } else {
- display = log_error(SECT5, METRIC, zErrType + typeof value)
+ if (isGecko) {
+ if ("1" !== value && "unspecified" !== value) {
+ if ("string" === typeof value) {
+ display = log_error(SECT5, METRIC, zErrInvalid + cleanFn(value))
+ } else {
+ display = log_error(SECT5, METRIC, zErrType + typeof value)
+ }
+ value = zErr
}
- value = zErr
}
exit(value, display)
} catch(e) {
@@ -171,7 +171,14 @@ const get_nav_gpc = () => new Promise(resolve => {
// privacy.globalprivacycontrol.enabled = true/false
const METRIC = "globalPrivacyControl"
function exit(value, display) {
- log_display(5, METRIC, display)
+ let notation = ""
+ if (isSmart) {
+ notation = default_red
+ if (isVer > 119 && value === false) {notation = default_green
+ } else if (isVer < 120 && value == "undefined") {notation = default_green
+ }
+ }
+ log_display(5, METRIC, display + notation)
return resolve([METRIC, value])
}
try {
@@ -185,7 +192,7 @@ const get_nav_gpc = () => new Promise(resolve => {
} else if (isSmart && sData[SECT99].includes("Navigator."+ METRIC)) {
value = zLIE
display = colorFn(display)
- log_known(SECT4, METRIC)
+ log_known(SECT5, METRIC)
}
exit(value, display)
} catch(e) {
@@ -241,12 +248,6 @@ function get_lang() {
"second": {"long": [1], "narrow": [1], "short": [987654]},
"terabyte": optL,
}
- // ToDo: isSmartMin=115 remove FF < 110 tweak
- if (isVer < 110) {
- tests["unit"]["month"] = {"narrow": [1], "short": [987654]}
- tests["unit"]["day"] = optL
- tests["unit"]["gallon"] = {"short": [987654]}
- }
}
set_tests()
@@ -503,7 +504,7 @@ function get_lang() {
// LANGUAGES
METRIC = "languages"
data = oTempData[METRIC]
- let langcheck = (isSmart && isTB && isOS !== "android" && isVer > 114) // ToDo: android may differ, ignore for now
+ let langcheck = (isSmart && isTB && isOS !== "android") // ToDo: android may differ, ignore for now
Object.keys(data).forEach(function(item){
METRIC = item
if (langcheck) {
@@ -551,11 +552,14 @@ function get_lang() {
} else if (res.length == 0) {
value = zErr
fpvalue = zErr
- } else {
+ } else {
value = "mixed"
- fpvalue = zLIE
- value = colorFn(value)
- log_known(SECT4, METRIC)
+ fpvalue = "mixed"
+ if (isSmart) {
+ fpvalue = zLIE
+ value = colorFn(value)
+ log_known(SECT4, METRIC)
+ }
}
addData(4, METRIC, fpvalue)
if (langcheck) {
@@ -695,21 +699,11 @@ function get_lang() {
let period2 = dteL.format(hr08) // long08
if (period1 == period2) {res.push(period1)} else {res.push(period1 +" / "+ period2)}
res.push( dteS.format(hr12)) // short12
-
- // ToDo: isSmartMin=115 remove FF < 110 tweak
- if (isVer > 109) {
- // FF110+: assuming ICU 72: 1792775
- period1 = dteN.format(hr15) // narrow15
- period2 = dteS.format(hr15) // short15
- if (period1 == period2) {res.push(period1)} else {res.push(period1 +" / "+ period2)}
- res.push( dteS.format(hr18)) // short18
- res.push( dteL.format(hr22)) // long22
- } else {
- // FF109 or lower
- res.push( dteN.format(hr15)) // narrow15
- res.push( dteS.format(hr18)) // short18
- res.push( dteS.format(hr22)) // short22
- }
+ period1 = dteN.format(hr15) // narrow15
+ period2 = dteS.format(hr15) // short15
+ if (period1 == period2) {res.push(period1)} else {res.push(period1 +" / "+ period2)}
+ res.push( dteS.format(hr18)) // short18
+ res.push( dteL.format(hr22)) // long22
return res.join(" | ")
} else if (item == 24) {
// ListFormat: 5 tests max required
diff --git a/js/screen.js b/js/screen.js
index 5c26eb52..52267495 100644
--- a/js/screen.js
+++ b/js/screen.js
@@ -25,11 +25,13 @@ function return_nw(w,h, isNew) {
return (bw && bh) ? nw_green : nw_red
}
-const get_scr_fullscreen = () => new Promise(resolve => {
+const get_scr_fullscreen = (runtype) => new Promise(resolve => {
let oRes = {}
+ let cssvalue = getElementProp(SECT1, "#cssDM", "display-mode_css")
+ let isErrCss = cssvalue == zErr
function get_display_mode() {
- const METRIC = "display-mode"
+ const METRIC = "display-mode", METRIC2 = METRIC +"_css"
let value, display
try {
let q = "(display-mode:"
@@ -37,9 +39,8 @@ const get_scr_fullscreen = () => new Promise(resolve => {
if (window.matchMedia(q +"browser)").matches) {value = "browser"}
if (window.matchMedia(q +"minimal-ui)").matches) {value = "minimal-ui"}
display = value
- if (isSmart) {
- let cssCheck = getElementProp(SECT1, "#cssDM")
- if (value !== cssCheck && cssCheck !== "x") {
+ if (isSmart && !isErrCss) {
+ if (value !== cssvalue) {
value = zLIE
display = colorFn(display)
log_known(SECT1, METRIC)
@@ -52,6 +53,41 @@ const get_scr_fullscreen = () => new Promise(resolve => {
}
log_display(1, METRIC, display)
oRes[METRIC] = value
+ oRes[METRIC2] = cssvalue
+ }
+
+ // fullScreen
+ function get_fullScreen() {
+ const METRIC = "fullScreen"
+ let value, display
+ if (isGecko) {
+ try {
+ // ToDo: shouldn't this be a standard and work in blink etc?
+ value = window.fullScreen
+ if (runSE) {foo++} else if (runST) {value = undefined}
+ display = value
+ if ("boolean" !== typeof value) {
+ log_error(SECT1, METRIC, zErrType + typeof value)
+ value = zErr
+ display = zErr
+ } else if (isSmart && !isErrCss) {
+ let boolCss = cssvalue == "fullscreen" ? true : false
+ if (boolCss !== value) {
+ value = zLIE
+ display = colorFn(display)
+ log_known(SECT1, METRIC)
+ }
+ }
+ } catch(e) {
+ log_error(SECT1, METRIC, e)
+ value = zErr
+ display = value
+ }
+ } else {
+ value = zNA; display = value
+ }
+ log_display(1, METRIC, display)
+ oRes[METRIC] = value
}
// full-screen-api.enabled
@@ -69,64 +105,397 @@ const get_scr_fullscreen = () => new Promise(resolve => {
oRes[METRIC] = r
}
- // fullScreen
- function get_fullScreen() {
- const METRIC = "fullScreen"
- let value, display
- try {
- value = window.fullScreen
- if (runSE) {foo++} else if (runST) {value = undefined}
- display = value
- if ("boolean" !== typeof value) {
- log_error(SECT1, METRIC, zErrType + typeof value)
- value = zErr
- display = zErr
- } else if (isSmart) {
- let cssCheck = getElementProp(SECT1, "#cssDM")
- if (cssCheck !== "x") {
- cssCheck = cssCheck == "fullscreen" ? true : false
- if (cssCheck !== value) {
- value = zLIE
- display = colorFn(display)
- log_known(SECT1, METRIC)
- }
+ // do in order so oRes keys = sorted
+ get_display_mode()
+ get_fullScreen()
+ get_mozFullScreenEnabled()
+ if (runtype !== "resize") {
+ addData(1, "fullscreen", oRes, mini(oRes))
+ }
+ return resolve()
+})
+
+const get_scr_measure = (runtype) => new Promise(resolve => {
+ let t0 = nowFn()
+ Promise.all([
+ get_scr_mm(runtype, "measure"),
+ ]).then(function(mmres){
+ let tmpScreen = {}, tmpWindow = {}, oScreen = {}, oWindow = {}
+
+ // matchmedia
+ tmpScreen["device-height"] = mmres[0]["device-height"]
+ tmpScreen["device-width"] = mmres[0]["device-width"]
+ tmpWindow["window_height"] = mmres[0]["window_height"]
+ tmpWindow["window_width"] = mmres[0]["window_width"]
+ // screen/window
+ let aList = [
+ "width","height","availWidth","availHeight", // scr
+ "outerWidth","outerHeight","innerWidth","innerHeight", // window
+ ]
+ for (let i=0; i < 8; i++) {
+ let x
+ let prefix = (i < 2) ? "screen_" : "" // width/height is ambiguous: also clashes with matchmedia inner
+ try {
+ if (i < 4) {x = screen[aList[i]]
+ } else {x = window[aList[i]]
+ }
+ if (typeof x !== "number") {
+ log_error(SECT1, prefix + aList[i], zErrType + typeof x)
+ x = "NaN"
}
+ } catch (e) {
+ log_error(SECT1, prefix + aList[i], e)
+ x = zErr
}
- } catch(e) {
- log_error(SECT1, METRIC, e)
+ if (i < 4) {tmpScreen[prefix + aList[i]] = x
+ } else {tmpWindow[aList[i]] = x
+ }
+ }
+ // css
+ let cList = [
+ ["#S", "device-width_css", ":before"],
+ ["#S", "device-height_css", ":after"],
+ ["#D", "window_width_css", ":before"],
+ ["#D", "window_height_css", ":after"],
+ ]
+ cList.forEach(function(array) {
+ let value = getElementProp(SECT1, array[0], array[1], array[2])
+ if ("number" !== typeof value && value !== "?") {
+ log_error(SECT1, array[1], zErrType + typeof value)
+ value = "NaN"
+ }
+ // NaNs
+ if (array[0] == "#S") {
+ tmpScreen[array[1]] = value
+ } else {
+ tmpWindow[array[1]] = value
+ }
+ })
+
+ // reorder object
+ if (runtype !== "resize") {
+ for (const h of Object.keys(tmpScreen).sort()) {
+ oScreen[h] = tmpScreen[h]
+ }
+ for (const k of Object.keys(tmpWindow).sort()) {
+ oWindow[k] = tmpWindow[k]
+ }
+ }
+
+ // just display it for now
+ log_display(1, "mAvailable", tmpScreen.availWidth +" x "+ tmpScreen.availHeight)
+ log_display(1, "mmScreen", tmpScreen["device-width"] +" x "+ tmpScreen["device-height"])
+ log_display(1, "mScreen", tmpScreen.screen_width +" x "+ tmpScreen.screen_height)
+ addData(1, "screen_sizes", oScreen, mini(oScreen))
+
+ log_display(1, "mOuter", tmpWindow.outerWidth +" x "+ tmpWindow.outerHeight)
+ log_display(1, "mmInner", tmpWindow.window_width +" x "+ tmpWindow.window_height)
+ log_display(1, "mInner", tmpWindow.innerWidth +" x "+ tmpWindow.innerHeight)
+ addData(1, "window_sizes", oWindow, mini(oWindow))
+
+ // inner: LB/NW
+ if (isSmart) {
+ if (isOS !== "android") {
+ // TB13 changes newwin to max 1400x900, and aligns LB to match NW steps
+ log_display(1, "letterboxing", return_lb(tmpWindow.innerWidth, tmpWindow.innerHeight, isTB))
+ log_display(1, "new_window", return_nw(tmpWindow.innerWidth, tmpWindow.innerHeight, isTB))
+ }
+ }
+
+ })
+ return resolve()
+
+ /*
+ // notate
+ let match = true, r = ""
+ if (mScreen !== mAvailable) {match = false
+ } else if (mAvailable !== mOuter) {match = false
+ } else if (mOuter !== mInner) {match = false
+ } else {
+ aMeasures.forEach(function(value) {
+ if (isNaN(value)) {match = false}
+ })
+ }
+ r = match ? screen_green : screen_red
+ dom.scrmatch.innerHTML = r
+ */
+
+ // inner
+ let newW = getElementProp(SECT1, "#D",":before"),
+ newH = getElementProp(SECT1, "#D"),
+ isLies = 0, oldW = w4, oldH = h4
+ if (newW !== "?") {
+ newW = newW * 1
+ if (newW == oldW-1) {newW = oldW}
+ if (newW !== oldW) {isLies++}
+ }
+ if (newH !== "?") {
+ newH = newH.slice(3) * 1
+ if (newH == oldH-1) {newH = oldH}
+ if (newH !== oldH) {isLies++}
+ }
+ if (isLies > 0) {
+ dom.mInner.innerHTML = colorFn(mInner)
+ log_known(SECT1, "window inner")
+ }
+ res["window_inner"] = (isLies > 0 ? zLIE : mInner)
+
+ // screen
+ newW = getElementProp(SECT1, "#S",":before")
+ newH = getElementProp(SECT1, "#S")
+ isLies = 0, oldW = w1, oldH = h1
+ if (newW !== "?") {
+ newW = newW * 1
+ if (newW == oldW-1) {newW = oldW}
+ if (newW !== oldW) {isLies++}
+ }
+ if (newH !== "?") {
+ newH = newH.slice(3) * 1
+ if (newH == oldH-1) {newH = oldH}
+ if (newH !== oldH) {isLies++}
+ }
+ if (["Screen.width","Screen.height"].some(lie => sData[SECT99].indexOf(lie) >= 0)) {isLies++}
+ if (isLies > 0) {
+ dom.mScreen.innerHTML = colorFn(mScreen)
+ log_known(SECT1, "screen")
+ }
+ res["screen"] = (isLies > 0 ? zLIE : mScreen)
+
+ // screen available
+ isLies = false
+ if (["Screen.availWidth","Screen.availHeight"].some(lie => sData[SECT99].indexOf(lie) >= 0)) {
+ isLies = true
+ dom.mAvailable.innerHTML = colorFn(mAvailable)
+ log_known(SECT1, "screen available")
+ }
+ res["screen_available"] = (isLies > 0 ? zLIE : mAvailable)
+
+ // outer
+ res["window_outer"] = mOuter
+ if (runtype !== "resize") {log_perf(SECT1, "scr/win",t0)}
+ // resolve
+ return resolve(res)
+
+})
+
+const get_scr_mm = (runtype, datatype) => new Promise(resolve => {
+ const unable = "unable to find upper bound"
+ const oList = {
+ "measure": [
+ ["device-width", "device-width", "max-device-width", "px", 512, 0.01],
+ ["device-height", "device-height", "max-device-height", "px", 512, 0.01],
+ ["window_width", "width", "max-width", "px", 512, 0.01],
+ ["window_height", "height", "max-height", "px", 512, 0.01],
+ ],
+ "pixels": [
+ ["-moz-device-pixel-ratio", "-moz-device-pixel-ratio", "max--moz-device-pixel-ratio", "", 4, 0.0000001],
+ ["-webkit-min-device-pixel-ratio", "-webkit-min-device-pixel-ratio", "-webkit-max-device-pixel-ratio", "", 4, 0.01],
+ // webkit seems limited to and rounds down to 0.25, 0.5, 1, 2, 4
+ ["dpcm", "resolution", "max-resolution", "dpcm", 1e-5, 0.0000001],
+ ["dpi", "resolution", "max-resolution", "dpi", 1e-5, 0.0000001],
+ ["dppx", "resolution", "max-resolution", "dppx", 1e-5, 0.0000001],
+ ]
+ }
+ let list = oList[datatype], maxCount = oList[datatype].length, count = 0, oData = {}
+ function exit(id, value) {
+ if (value == unable) {
+ log_error(SECT1, id, unable)
value = zErr
- display = value
}
- log_display(1, METRIC, display)
- oRes[METRIC] = value
+ oData[id] = value
+ count++
+ if (count == maxCount) {
+ return resolve(oData)
+ }
}
+ function runTest(callback){
+ list.forEach(function(k){
+ let metric = k[0], lower = k[1], upper = k[2], suffix = k[3], epsilon = k[4], precision = k[5]
+ Promise.all([
+ callback(lower, upper, suffix, epsilon, precision),
+ ]).then(function(result){
+ exit(metric, result[0])
+ }).catch(function(err){
+ exit(metric, err)
+ })
+ })
+ }
+ function searchValue(tester, maxValue, precision){
+ let minValue = 0
+ let ceiling = Math.pow(2, 32)
+ function stepUp(){
+ if (maxValue > ceiling || runST){
+ return Promise.reject(unable)
+ }
+ return tester(maxValue).then(function(testResult){
+ if (testResult === searchValue.isEqual){
+ return maxValue
+ }
+ else if (testResult === searchValue.isBigger){
+ minValue = maxValue
+ maxValue *= 2
+ return stepUp()
+ }
+ else {
+ return false
+ }
+ })
+ }
+ function binarySearch() {
+ if (maxValue - minValue < precision) {
+ return tester(minValue).then(function(testResult) {
+ if (testResult.isEqual) {return minValue
+ } else {
+ return tester(maxValue).then(function(testResult) {
+ if (testResult.isEqual) {return maxValue
+ } else {
+ return Promise.resolve(minValue) // +" to "+ maxValue // just return min
+ }
+ })
+ }
+ })
+ } else {
+ let pivot = (minValue + maxValue) / 2
+ return tester(pivot).then(function(testResult) {
+ if (testResult === searchValue.isEqual) {return pivot
+ } else if (testResult === searchValue.isBigger) {
+ minValue = pivot
+ return binarySearch()
+ } else {
+ maxValue = pivot
+ return binarySearch()
+ }
+ })
+ }
+ }
+ return stepUp().then(function(stepUpResult) {
+ if (stepUpResult){return stepUpResult
+ } else {return binarySearch()}
+ })
+ }
+ searchValue.isSmaller = -1
+ searchValue.isEqual = 0
+ searchValue.isBigger = 1
- get_display_mode()
- get_mozFullScreenEnabled()
- get_fullScreen()
- return resolve(oRes)
+ runTest(function(prefix, maxPrefix, suffix, maxValue, precision) {
+ return searchValue(function(valueToTest) {
+ try {
+ if (runSE) {foo++}
+ if (window.matchMedia("("+ prefix +": "+ valueToTest + suffix+")").matches){
+ return Promise.resolve(searchValue.isEqual)
+ } else if (window.matchMedia("("+ maxPrefix +": "+ valueToTest + suffix+")").matches){
+ return Promise.resolve(searchValue.isSmaller)
+ } else {
+ return Promise.resolve(searchValue.isBigger)
+ }
+ } catch(e) {
+ log_error(SECT1, prefix, e, isScope, 40)
+ return Promise.reject(zErr)
+ }
+ }, maxValue, precision)
+ })
})
-const get_scr_subpixels = (runtype) => new Promise(resolve => {
- function return_mm_dpi(type, denominator) {
- const METRIC = "max-resolution_"+ type
- let r = ""
+const get_scr_orientation = (type) => new Promise(resolve => {
+ let oScreen = {}, oWindow = {}
+ // matchmedia: sorted names
+ let names = [
+ ["-moz-device-orientation", "#cssOm"],
+ ["device-aspect-ratio", "#cssDAR"],
+ ["aspect-ratio", "#cssAR"],
+ ["orientation", "#cssO"],
+ ]
+ let l = "landscape", p = "portrait", q = "(orientation: ", s = "square", a = "aspect-ratio"
+ let aWindow = [], aScreen = []
+ for (let i=0; i < names.length; i++) {
+ let value, isErr = false
+ let METRIC = names[i][0], METRIC2 = METRIC +"_css"
try {
- r = (function() {
- let i = 1
- for (1; i < 3001; i++) {
- let n = i/denominator
- if (matchMedia("(max-resolution:"+ n + type +")").matches === true) {return n}
- }
- log_error(SECT1, METRIC, zErrInvalid +"> "+ ((i-1)/denominator))
- return zErr
- })()
+ if (runSE) {foo++}
+ if (i == 0) {
+ if (window.matchMedia("(-moz-device-orientation:"+ l +")").matches) value = l
+ if (window.matchMedia("(-moz-device-orientation:"+ p +")").matches) value = p
+ } else if (i == 1) {
+ if (window.matchMedia("(device-"+ a +":1/1)").matches) value = s
+ if (window.matchMedia("(min-device-"+ a +":10000/9999)").matches) value = l
+ if (window.matchMedia("(max-device-"+ a +":9999/10000)").matches) value = p
+ } else if (i == 2) {
+ if (window.matchMedia("("+ a +":1/1)").matches) value = s
+ if (window.matchMedia("(min-"+ a +":10000/9999)").matches) value = l
+ if (window.matchMedia("(max-"+ a +":9999/10000)").matches) value = p
+ } else {
+ if (window.matchMedia(q + p +")").matches) value = p
+ if (window.matchMedia(q + l +")").matches) value = l
+ }
+ if (value == undefined) {value = zU}
} catch(e) {
log_error(SECT1, METRIC, e)
- return zErr
+ value = zErr
+ isErr = true
+ }
+ if (runSL) {value += "_fake"}
+ let display = value
+ // css
+ let isLies = false
+ let cssvalue = getElementProp(SECT1, names[i][1], METRIC2)
+ let isErrCss = cssvalue == zErr
+ if (isSmart && !isErr && !isErrCss) {
+ if (value !== cssvalue) {
+ display = colorFn(display)
+ value = zLIE
+ log_known(SECT1, names[i][0])
+ }
+ }
+ if (i < 2) {
+ aScreen.push(display)
+ oScreen[METRIC] = value
+ oScreen[METRIC2] = cssvalue
+ } else {
+ aWindow.push(display)
+ oWindow[METRIC] = value
+ oWindow[METRIC2] = cssvalue
+ }
+ }
+ log_display(1, "screen_mmorientation", aScreen.join(" | "))
+ log_display(1, "window_mmorientation", aWindow.join(" | "))
+
+ // screen
+ names = ["mozOrientation", "orientation.angle", "orientation.type"], aScreen = []
+ for (let i=0; i < 3; i++) {
+ let value
+ try {
+ if (runSE) {foo++}
+ if (i == 0) {value = screen.mozOrientation
+ } else if (i == 1) {value = screen.orientation.angle
+ } else {value = screen.orientation.type
+ }
+ if (value == undefined) {value = zU}
+ } catch(e) {
+ log_error(SECT1, names[i], e)
+ value = zErr
}
- return r
+ aScreen.push(value)
+ oScreen[names[i]] = value
}
+ let display = aScreen.join(" | ")
+ if (isSmart) {
+ // does this makes sense? e.g. we control the screen, based on inner, so it should reflect
+ // that, not sure about angle. i.e this is just lying about equivalency of already protected values?
+ // ... BUT we should continue to protect -primary vs -secondary
+ // ... AND we should make sure subpixels round up (e.g min)
+ display += (display == "landscape-primary | 0 | landscape-primary" ? rfp_green : rfp_red)
+ }
+ log_display(1, "screen_orientation", display)
+
+ if (type !== "resize") {
+ // objects are already sorted
+ addData(1, "screen_orientation", oScreen, mini(oScreen))
+ addData(1, "window_orientation", oWindow, mini(oWindow))
+ }
+ return resolve()
+})
+
+const get_scr_pixels = (runtype) => new Promise(resolve => {
function get_dpr() {
const METRICw = "devicePixelRatio", METRICb = "devicePixelRatio_border"
// DPR window
@@ -148,11 +517,10 @@ const get_scr_subpixels = (runtype) => new Promise(resolve => {
}
let notation = ""
if (isSmart) {
- let rfpvalue = isTB && isVer > 102 ? 2 : 1
- notation = value === rfpvalue ? rfp_green : rfp_red
+ notation = value === (isTB ? 2 : 1) ? rfp_green : rfp_red
}
log_display(1, METRICw, display + notation)
- oSubpixels[METRICw] = value
+ oData[METRICw] = value
// DPR border: 477157: don't notate this for health
value = undefined, display = undefined
@@ -183,18 +551,14 @@ const get_scr_subpixels = (runtype) => new Promise(resolve => {
display = zErr
}
log_display(1, METRICb, display)
- oSubpixels[METRICb] = value
+ oData[METRICb] = value
return
}
- // DPI x 3 methods, DPPX, DPCM
+ // DPI
function get_dpi() {
- const METRIC = "dpi"
- let mmDPPX = return_mm_dpi("dppx",100),
- mmDPCM = return_mm_dpi("dpcm",10)
- mmDPI = return_mm_dpi("dpi",1)
+ const METRIC = "dpi_div", METRIC2 = "dpi_css"
//note: divDPI relies on css: if css is blocked (dpi_y = 0) this causes issues
-
// measure div
try {dpi_x = Math.round(dom.divDPI.offsetWidth * varDPR)} catch(e) {dpi_x = zErr}
try {dpi_y = Math.round(dom.divDPI.offsetHeight * varDPR)} catch(e) {dpi_y = zErr}
@@ -205,16 +569,18 @@ const get_scr_subpixels = (runtype) => new Promise(resolve => {
if (dpi_y !== 0 && !isNaN(dpi_y)) {
// this is the one: RFP spoofs cssDPI and mmDPI
varDPI = dpi_y
- } else if (cssDPI !== "x" && mmDPI !== zErr) {
+ } else if ("number" == typeof cssDPI && mmDPI !== zErr) {
diffDPI = Math.abs(mmDPI - cssDPI)
varDPI = (diffDPI == 1 ? mmDPI : cssDPI)
} else if (mmDPI !== zErr) {
varDPI = mmDPI
}
+ // notate css
+ log_display(1, METRIC2, (cssDPI == 96 ? rfp_green : rfp_red))
}
- log_display(1, "mmDPI", mmDPI +" | "+ mmDPPX +" | "+ mmDPCM)
log_display(1, METRIC, varDPI)
- oSubpixels[METRIC] = varDPI
+ oData[METRIC2] = cssDPI
+ oData[METRIC] = varDPI
return
}
@@ -238,123 +604,59 @@ const get_scr_subpixels = (runtype) => new Promise(resolve => {
value = zErr
}
log_display(1, METRIC, display)
- oSubpixels[METRIC] = value
+ if (runtype !== "resize") {
+ oData[METRIC] = value
+ }
return
}
// run
// if dpi_x/y stay at 0 = css blocked or offsetWidth blocked
let t0 = nowFn()
- let oSubpixels = {}
+ let oData = {}
let varDPR, varDPI, mmDPI, dpi_x = 0, dpi_y = 0
- let cssDPI = getElementProp(SECT1, "#P",":before")
- // get
- get_dpr()
- get_dpi()
- get_vv_scale()
- if (runtype !== "resize") {
- log_perf(SECT1, "dpi/dpr", t0, "", varDPI +" "+ cssDPI +" "+ mmDPI +" "+ dpi_x +" "+ dpi_y)
+ let cssDPI = getElementProp(SECT1, "#P", "dpi_css", ":before")
+ if (cssDPI !== "?" && cssDPI !== zErr) {
+ if ("number" !== typeof cssDPI) {
+ cssDPI = "NaN"
+ log_error(SECT1, "dpi_css", zErrType + typeof cssDPI)
+ }
}
- return resolve(oSubpixels)
-})
-const get_scr_orientation = (type) => new Promise(resolve => {
- let oScreen = {}, oWindow = {}
- // matchmedia: sorted names
- let names = [
- ["-moz-device-orientation", "#cssOm"],
- ["device-aspect-ratio", "#cssDAR"],
- ["aspect-ratio", "#cssAR"],
- ["orientation", "#cssO"],
- ]
- let l = "landscape", p = "portrait", q = "(orientation: ", s = "square", a = "aspect-ratio"
- let aWindow = [], aScreen = []
- for (let i=0; i < names.length; i++) {
- let value
- try {
- if (runSE) {foo++}
- if (i == 0) {
- if (window.matchMedia("(-moz-device-orientation:"+ l +")").matches) value = l
- if (window.matchMedia("(-moz-device-orientation:"+ p +")").matches) value = p
- } else if (i == 1) {
- if (window.matchMedia("(device-"+ a +":1/1)").matches) value = s
- if (window.matchMedia("(min-device-"+ a +":10000/9999)").matches) value = l
- if (window.matchMedia("(max-device-"+ a +":9999/10000)").matches) value = p
- } else if (i == 2) {
- if (window.matchMedia("("+ a +":1/1)").matches) value = s
- if (window.matchMedia("(min-"+ a +":10000/9999)").matches) value = l
- if (window.matchMedia("(max-"+ a +":9999/10000)").matches) value = p
- } else {
- if (window.matchMedia(q + p +")").matches) value = p
- if (window.matchMedia(q + l +")").matches) value = l
+ // get
+ Promise.all([
+ get_scr_mm(runtype, "pixels")
+ ]).then(function(results){
+
+ for (const k of Object.keys(results[0])) {
+ // expected 100% zoom values
+ let oMatch = {
+ "-moz-device-pixel-ratio": 1,
+ "-webkit-min-device-pixel-ratio": 1,
+ "dpcm": 37.79527499999999,
+ "dpi": 96.00000000000003,
+ "dppx": 1,
}
- if (value == undefined) {value = zU}
- } catch(e) {
- log_error(SECT1, names[i][0], e)
- value = zErr
- }
- if (runSL) {value += "_fake"}
- let display = value
- // css
- let isLies = false
- let cssvalue = getElementProp(SECT1, names[i][1])
- if (isSmart && value !== zErr && cssvalue !== "x") {
- if (value !== cssvalue) {
- display = colorFn(display)
- value = zLIE
- log_known(SECT1, names[i][0])
+ let value = results[0][k], notation = ""
+ if (isSmart && oMatch[k] !== undefined) {
+ notation = value == oMatch[k] ? rfp_green : rfp_red
}
+ oData[k] = value
+ log_display(1, k, value + notation)
}
- if (i < 2) {
- aScreen.push(display)
- oScreen[names[i][0]] = value
- oScreen[names[i][0] +"_css"] = cssvalue
- } else {
- aWindow.push(display)
- oWindow[names[i][0]] = value
- oWindow[names[i][0] +"_css"] = cssvalue
- }
- }
- log_display(1, "screen_mmorientation", aScreen.join(" | "))
- log_display(1, "window_mmorientation", aWindow.join(" | "))
-
- // screen
- names = ["mozOrientation", "orientation.angle", "orientation.type"], aScreen = []
- for (let i=0; i < 3; i++) {
- let value
- try {
- if (runSE) {foo++}
- if (i == 0) {value = screen.mozOrientation
- } else if (i == 1) {value = screen.orientation.angle
- } else {value = screen.orientation.type
- }
- if (value == undefined) {value = zU}
- } catch(e) {
- log_error(SECT1, names[i], e)
- value = zErr
+ get_dpr()
+ get_dpi()
+ get_vv_scale()
+ if (runtype !== "resize") {
+ let newobj = {}
+ for (const k of Object.keys(oData).sort()) {newobj[k] = oData[k]}
+ addData(1, "pixels", newobj, mini(newobj))
+ log_perf(SECT1, "pixels", t0, "", varDPI +" "+ cssDPI +" "+ oData["dpi"] +" "+ dpi_x +" "+ dpi_y)
}
- aScreen.push(value)
- oScreen[names[i]] = value
- }
- let display = aScreen.join(" | ")
- if (isSmart) {
- // does this makes sense? e.g. we control the screen, based on inner, so it should reflect
- // that, not sure about angle. i.e this is just lying about equivalency of already protected values?
- // ... BUT we should continue to protect -primary vs -secondary
- // ... AND we should make sure subpixels round up (e.g min)
- display += (display == "landscape-primary | 0 | landscape-primary" ? rfp_green : rfp_red)
- }
- log_display(1, "screen_orientation", display)
-
- if (type !== "resize") {
- // objects are already sorted
- addData(1, "screen_orientation", oScreen, mini(oScreen))
- addData(1, "window_orientation", oWindow, mini(oWindow))
- }
- return resolve()
+ return resolve()
+ })
})
-
const get_scr_positions = (type) => new Promise(resolve => {
const METRIC = type +"_positions"
let oRes = {}, notation = "", aDisplay = [], aList, check, x
@@ -393,21 +695,31 @@ const get_scr_positions = (type) => new Promise(resolve => {
})
const get_scr_scrollbar = (runtype) => new Promise(resolve => {
- // we need to wait for the viewport width
+ // ui.useOverlayScrollbars: 0 = no, 1 = yes use-overlays
+ // win11 = overlay = very thin scrollbar
+
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1786665
+ // widget.non-native-theme.scrollbar.style = values 1 to 5
+ // widget.non-native-theme.scrollbar.size.override <-- non-overlay only?
+
Promise.all([
+ // get the viewport width: we only return zErr or a number
get_scr_viewport(runtype)
- ]).then(function(res){
+ ]).then(function(res) {
let t0 = nowFn()
+ let oData = {}, aDisplay = []
+
// css inner width
- let cssW = getElementProp(SECT1, "#D",":before")
+ let cssW = getElementProp(SECT1, "#D", "innerWidth_css", ":before")
- // element
- function get_sb_element() {
- const METRIC = "scollbar_element"
+ // scrollWidth
+ function get_scrollwidth(METRIC) {
let value, display
try {
- value = (100 - dom.eScroll.scrollWidth)
- if (runSE) {foo++}
+ let scrollWidth = dom.eScroll.scrollWidth
+ if ("number" !== typeof scrollWidth) {scrollWidth = "x"}
+ value = (100 - scrollWidth)
+ if (runSE) {foo++} else if (runST) {value = "x"}
if ("number" !== typeof value) {
log_error(SECT1, METRIC, zErrType + typeof value)
value = zErr
@@ -424,449 +736,132 @@ const get_scr_scrollbar = (runtype) => new Promise(resolve => {
display = zErr
log_error(SECT1, METRIC, e)
}
- return [display, value]
+ oData[METRIC] = value
+ aDisplay.push(display)
}
- // viewport
- function get_sb_viewport() {
- let eViewport = res[0][0] // calculated from element
-
- }
-
-
- /*
- let eViewport = res[0][0] // calculated from element
- let eWidth, eValue, eLies = false
- if (eViewport == zErr) {
- eValue = eViewport
- eWidth = eViewport
- } else if (isSmart && "number" !== typeof eViewport) {
- eWidth = "NaN"; eLies = true; eValue = zLIE
- } else {
- try {
- eWidth = (window.innerWidth - eViewport)
- eWidth = cleanFn(eWidth)
- eValue = eWidth
- if (isSmart) {
- // leverage css value
- let cssE = cssW
- if (cssE !== "x" && "number" == typeof eWidth) {
- if (cssE * 1 == eWidth - 1) {cssE = eWidth} // allow for min-
- eWidth = cssE - eViewport
- }
- // lies
- let eMin = -1
- if ("number" !== typeof eWidth) {eLies = true
- } else if (eWidth < eMin) {eLies = true}
- eValue = eLies ? zLIE : eWidth
- }
- } catch(e) {
- eWidth = zErr; eValue = zErr
- log_error(SECT1, "scrollbar_viewport", e)
- }
- }
- if (eLies) {
- eWidth = colorFn(eWidth); if (runtype !== "resize") {log_known(SECT1, "scrollbar_viewport")}
- }
- */
-
- // visualViewport
- function get_sb_visualviewport() {
-
- }
- /*
- let vViewport = res[0][1]
- let vValue, vWidth, vLies = false
- if (vViewport == eViewport) {
- vValue = eValue
- vWidth = eWidth
- vLies = eLies
- } else if (vViewport == zErr) {
- vValue = vViewport
- vWidth = vViewport
- } else if ("number" !== typeof vViewport) {
- vWidth = "NaN"; vLies = true; vValue = zLIE
- } else {
- try {
- vWidth = (window.innerWidth - vViewport)
- vWidth = cleanFn(vWidth)
- vValue = vWidth
- if (isSmart) {
- // leverage css value
- if (cssW !== "x" && "number" == typeof vWidth) {
- if (cssW * 1 == vWidth - 1) {cssW = vWidth} // allow for min-
- vWidth = cssW - vViewport
+ // viewport (calculated from element), visualViewport
+ function get_viewport(METRIC) {
+ let viewport = METRIC == "viewport" ? res[0][0] : res[0][1]
+ let value, display
+ if (viewport == zErr) {
+ value = zErr
+ display = zErr
+ } else {
+ try {
+ let innerwidth = window.innerWidth
+ if ("number" !== typeof innerwidth) {
+ log_error(SECT1, METRIC, zErrType + typeof value)
+ value = zErr
+ width = "NaN"
+ } else {
+ value = (innerWidth - viewport)
+ display = value
+ if (isSmart) {
+ // leverage css value
+ if (cssW !== "?") {
+ if (cssW * 1 == value - 1) {cssW = value} // allow for min-
+ value = cssW - viewport
+ display = value
+ }
+ // lies
+ if (value < -1) {
+ value = zLIE
+ display = colorFn(eWidth)
+ if (runtype !== "resize") {log_known(SECT1, METRIC)}
+ }
+ }
}
- // lies
- let vMin = -1
- if ("number" !== typeof vWidth) {vLies = true
- } else if (vWidth < vMin) {vLies = true}
- vValue = vLies ? zLIE : vWidth
+ } catch(e) {
+ value = zErr; display = zErr
+ log_error(SECT1, METRIC, e)
}
- } catch(e) {
- vWidth = zErr; vValue = zErr
- log_error(SECT1, "scrollbar_visualViewport", e)
}
+ oData[METRIC] = value
+ aDisplay.push(display)
}
- if (vLies) {
- vWidth = colorFn(vWidth); if (runtype !== "resize") {log_known(SECT1, "scrollbar_visualViewport")}
- }
- */
-
- get_sb_element()
- get_sb_viewport()
- get_sb_visualviewport()
-
- // display
- //dom.mScrollbar.innerHTML = vWidth +" | "+ eWidth +" | "+ elWidth
- if (runtype !== "resize") {log_perf(SECT1, "scrollbars", t0)}
- return resolve(["scrollbars", "TBA"])
+ get_scrollwidth("scrollWidth")
+ get_viewport("viewport")
+ get_viewport("visualViewport")
+ const METRIC = "scrollbar_widths"
+ log_display(1, METRIC, aDisplay.join(" | "))
+ addData(1, METRIC, oData, mini(oData))
+ if (runtype !== "resize") {log_perf(SECT1, METRIC, t0)}
+ return resolve()
})
})
-function get_scr_viewport(runtype) {
+const get_scr_viewport = (runtype) => new Promise(resolve => {
let t0 = nowFn()
- // element
- let eViewport, evh, evw, eValue, eValid = false
- try {
- if (runSE) {foo++}
- let e = document.createElement("div")
- e.style.cssText = "position:fixed;top:0;left:0;bottom:0;right:0;"
- document.documentElement.insertBefore(e,document.documentElement.firstChild)
- evw = e.offsetWidth
- evh = e.offsetHeight
- document.documentElement.removeChild(e)
- if (isSmart && "number" !== typeof evw || "number" !== typeof evh) {
- eViewport = colorFn(cleanFn(evw) +" x "+ cleanFn(evh))
- eValue = "NaN"
- log_known(SECT1, "viewport")
- } else {
- eValid = true; eValue = evw
- if (avh == "") {avh = evh} // get android height once
- eViewport = cleanFn(evw) +" x "+ cleanFn(evh)
+ let oData = {}, aDisplay = []
+
+ // viewport
+ // visualViewport: note: FF63+ dom.visualviewport.enabled FF91+ default true (desktop at least)
+ function get_viewport(type) {
+ let METRIC1 = "viewport_height", METRIC2 = "viewport_width"
+ if (type == "vViewport") {
+ METRIC1 = "visualViewport_height", METRIC2 = "visualViewport_width"
}
- } catch(e) {
- eViewport = log_error(SECT1,"viewport", e)
- eValue = zErr
- }
-
- // visualViewport
- // note: FF63+ dom.visualviewport.enabled FF91+ default true (desktop at least)
- let vViewport, vvw, vvh, vValue, vValid = false
- try {
- if (runSE) {foo++}
- vvw = window.visualViewport.width
- vvh = window.visualViewport.height
- if (isSmart && "number" !== typeof vvw || "number" !== typeof vvh) {
- vViewport = colorFn(cleanFn(vvw) +" x "+ cleanFn(vvh))
- vValue = "NaN"
- log_known(SECT1, "visualViewport size")
- } else {
- vValid = true; vValue = vvw
- if (avh == "") {avh = vvh} // get android height once
- vViewport = cleanFn(vvw) +" x "+ cleanFn(vvh)
+ let wValue, hValue, wDisplay = "", hDisplay
+ try {
+ if (runSE) {foo++}
+ if (type == "eViewport") {
+ let e = document.createElement("div")
+ e.style.cssText = "position:fixed;top:0;left:0;bottom:0;right:0;"
+ document.documentElement.insertBefore(e,document.documentElement.firstChild)
+ wValue = e.offsetWidth
+ hValue = e.offsetHeight
+ document.documentElement.removeChild(e)
+ } else {
+ wValue = window.visualViewport.width
+ hValue = window.visualViewport.height
+ }
+ if (runST) {hValue = undefined}
+ if ("number" !== typeof hValue) {
+ log_error(SECT1, METRIC1, zErrType + typeof hValue)
+ hValue = zErr
+ hDisplay = "NaN"
+ } else {
+ hDisplay = hValue
+ if (avh == "") {avh = hValue} // get android height once
+ }
+ if (runST) {wValue = ""}
+ if ("number" !== typeof wValue) {
+ log_error(SECT1, METRIC2, zErrType + typeof wValue)
+ wValue = zErr
+ wDisplay = "NaN"
+ } else {
+ wDisplay = wValue
+ }
+ } catch(e) {
+ hValue = zErr; wValue = zErr
+ hDisplay = log_error(SECT1, METRIC1, e); wDisplay = ""
+ log_error(SECT1, METRIC2, e)
+ }
+ oData[METRIC1] = hValue
+ oData[METRIC2] = wValue
+ if (runtype !== "height") {
+ log_display(1, type, (wDisplay == "" ? hDisplay : wDisplay +" x "+ hDisplay))
}
- } catch(e) {
- vViewport = log_error(SECT1, "visualViewport size", e)
- vValue = zErr
}
- // get viewport height once on first load
- if (avh == "") {avh = "undefined"}
-
+ get_viewport("eViewport")
+ get_viewport("vViewport")
+ if (avh == "") {avh = "undefined"} // get viewport height once on first load
// return
if (runtype == "height") {
- return vValid ? evh : vvh // android tests
+ let vvh = oData["visualViewport_height"]
+ return resolve(vvh !== zErr ? vvh : oData["viewport_height"]) // android tests
} else {
- dom.eViewport = eViewport
- dom.vViewport.innerHTML = vViewport
// perf
if (runtype !== "resize") {
- log_perf(SECT1, "viewport", t0, "", "e: "+ evh +" v: "+ vvh +" a: "+ avh)
+ addData(1, "viewport", oData, mini(oData))
+ log_perf(SECT1, "viewport", t0, "", "e: "+ oData["viewport_height"] +" v: "+ oData["visualViewport_height"] +" a: "+ avh)
}
- return [eValue, vValue] // scrollbar
+ return resolve([oData["viewport_width"], oData["visualViewport_width"]]) // for scrollbar
}
-}
-
-function get_scr_window(runtype) {
- return new Promise(resolve => {
- let t0 = nowFn()
- let res = {}
- // MEASURE: ToDo: catch errors/undefined etc
- let aMeasures = []
- let aPos = []
- let aList = [
- "screen.width","screen.height","screen.availWidth","screen.availHeight",
- "window.outerWidth","window.outerHeight","window.innerWidth","window.innerHeight",
- ]
- for (let i=0; i < 8; i++) {
- let x
- try {
- if (i == 0) {x = screen.width
- } else if (i == 1) {x = screen.height
- } else if (i == 2) {x = screen.availWidth
- } else if (i == 3) {x = screen.availHeight
- } else if (i == 4) {x = window.outerWidth
- } else if (i == 5) {x = window.outerHeight
- } else if (i == 6) {x = window.innerWidth
- } else if (i == 7) {x = window.innerHeight
- }
- if (typeof x !== "number") {
- log_error(SECT1, aList[i], zErrType + typeof x)
- x = "NaN"
- }
- } catch (e) {
- log_error(SECT1, aList[i], e)
- x = zErr
- }
- aMeasures.push(x)
- }
-
- let w1 = aMeasures[0], h1 = aMeasures[1],
- w2 = aMeasures[2], h2 = aMeasures[3],
- w3 = aMeasures[4], h3 = aMeasures[5],
- w4 = aMeasures[6], h4 = aMeasures[7]
- let mScreen = w1 +" x "+ h1,
- mAvailable = w2 +" x "+ h2,
- mOuter = w3 +" x "+ h3,
- mInner = w4 +" x "+ h4
- // default display
- dom.mScreen = mScreen
- dom.mAvailable = mAvailable
- dom.mOuter = mOuter
- dom.mInner.innerHTML = mInner
-
- if (!isSmart) {
- res["screen"] = mScreen
- res["screen_available"] = mAvailable
- res["window_inner"] = mInner
- res["window_outer"] = mOuter
- return resolve(res)
- }
-
- /*
- // notate
- let match = true, r = ""
- if (mScreen !== mAvailable) {match = false
- } else if (mAvailable !== mOuter) {match = false
- } else if (mOuter !== mInner) {match = false
- } else {
- aMeasures.forEach(function(value) {
- if (isNaN(value)) {match = false}
- })
- }
- r = match ? screen_green : screen_red
- dom.scrmatch.innerHTML = r
- */
-
- // inner: LB/NW
- if (isOS !== "android") {
- // TB changes newwin to max 1400x900, and aligns LB to match NW steps
- let isNewSteps = (isTB && isVer > 102)
- log_display(1, "letterboxing", return_lb(w4,h4, isNewSteps))
- log_display(1, "new_window", return_nw(w4,h4, isNewSteps))
- }
-
- // inner
- let newW = getElementProp(SECT1, "#D",":before"),
- newH = getElementProp(SECT1, "#D"),
- isLies = 0, oldW = w4, oldH = h4
- if (newW !== "x") {
- newW = newW * 1
- if (newW == oldW-1) {newW = oldW}
- if (newW !== oldW) {isLies++}
- }
- if (newH !== "x") {
- newH = newH.slice(3) * 1
- if (newH == oldH-1) {newH = oldH}
- if (newH !== oldH) {isLies++}
- }
- if (isLies > 0) {
- dom.mInner.innerHTML = colorFn(mInner)
- log_known(SECT1, "window inner")
- }
- res["window_inner"] = (isLies > 0 ? zLIE : mInner)
-
- // screen
- newW = getElementProp(SECT1, "#S",":before")
- newH = getElementProp(SECT1, "#S")
- isLies = 0, oldW = w1, oldH = h1
- if (newW !== "x") {
- newW = newW * 1
- if (newW == oldW-1) {newW = oldW}
- if (newW !== oldW) {isLies++}
- }
- if (newH !== "x") {
- newH = newH.slice(3) * 1
- if (newH == oldH-1) {newH = oldH}
- if (newH !== oldH) {isLies++}
- }
- if (["Screen.width","Screen.height"].some(lie => sData[SECT99].indexOf(lie) >= 0)) {isLies++}
- if (isLies > 0) {
- dom.mScreen.innerHTML = colorFn(mScreen)
- log_known(SECT1, "screen")
- }
- res["screen"] = (isLies > 0 ? zLIE : mScreen)
-
- // screen available
- isLies = false
- if (["Screen.availWidth","Screen.availHeight"].some(lie => sData[SECT99].indexOf(lie) >= 0)) {
- isLies = true
- dom.mAvailable.innerHTML = colorFn(mAvailable)
- log_known(SECT1, "screen available")
- }
- res["screen_available"] = (isLies > 0 ? zLIE : mAvailable)
-
- // outer
- res["window_outer"] = mOuter
-
- if (runtype !== "resize") {log_perf(SECT1, "scr/win",t0)}
- // resolve
- return resolve(res)
- })
-}
-
-function get_scr_window_mm(runtype) {
- return new Promise(resolve => {
- let t0 = nowFn()
- let count = 0, res = []
- let unable = "unable to find upper bound"
- // perf
- function perf(id, str, type) {
- if (runtype == "screen" && id == "devicePixelRatio_moz") {
- addData(1, id, ("number" == typeof str ? str : zErr))
- }
- document.getElementById(id).innerHTML = str //== unable ? zErr : str
- if (str == unable) {
- log_error(SECT1, "matchmedia "+ type, unable)
- }
- count++
- if (count == 3) {
- if (runtype !== "resize") {log_perf(SECT1, "mm scr/win",t0)}
- return resolve("skip")
- }
- }
-
- function runTest(callback){
- // screen
- Promise.all([
- callback("device-width", "max-device-width", "px", 512, 0.01), // 0.01
- callback("device-height", "max-device-height", "px", 512, 0.01) // 0.01
- ]).then(function(device){
- perf("mmScreen", device.join(" x "), "screen")
- }).catch(function(err){
- perf("mmScreen", err, "screen")
- })
- // inner
- Promise.all([
- callback("width", "max-width", "px", 512, 0.01),
- callback("height", "max-height", "px", 512, 0.01)
- ]).then(function(inner){
- perf("mmInner", inner.join(" x "), "inner")
- }).catch(function(err){
- perf("mmInner", err, "inner")
- })
- // moz
- callback("-moz-device-pixel-ratio", "max--moz-device-pixel-ratio", "", 2, 0.0000001
- ).then(function(moz){
- perf("devicePixelRatio_moz", moz, "-moz-device-pixel-ratio")
- }).catch(function(err){
- perf("devicePixelRatio_moz", err, "-moz-device-pixel-ratio")
- })
- }
- function searchValue(tester, maxValue, precision){
- let minValue = 0
- let ceiling = Math.pow(2, 32)
- function stepUp(){
- if (maxValue > ceiling){
- return Promise.reject("unable to find upper bound")
- }
- return tester(maxValue).then(function(testResult){
- if (testResult === searchValue.isEqual){
- return maxValue
- }
- else if (testResult === searchValue.isBigger){
- minValue = maxValue
- maxValue *= 2
- return stepUp()
- }
- else {
- return false
- }
- })
- }
- function binarySearch(){
- if (maxValue - minValue < precision){
- return tester(minValue).then(function(testResult){
- if (testResult.isEqual){
- return minValue
- }
- else {
- return tester(maxValue).then(function(testResult){
- if (testResult.isEqual){
- return maxValue
- }
- else {
- return Promise.resolve(
- minValue // +" to "+ maxValue // just return min
- )
- }
- })
- }
- })
- }
- else {
- let pivot = (minValue + maxValue) / 2
- return tester(pivot).then(function(testResult){
- if (testResult === searchValue.isEqual){
- return pivot
- }
- else if (testResult === searchValue.isBigger){
- minValue = pivot
- return binarySearch()
- }
- else {
- maxValue = pivot
- return binarySearch()
- }
- })
- }
- }
- return stepUp().then(function(stepUpResult){
- if (stepUpResult){
- return stepUpResult
- }
- else {
- return binarySearch()
- }
- })
- }
- searchValue.isSmaller = -1
- searchValue.isEqual = 0
- searchValue.isBigger = 1
-
- runTest(function(prefix, maxPrefix, suffix, maxValue, precision){
- return searchValue(function(valueToTest){
- try {
- //if (runSE) {foo++}
- if (window.matchMedia("("+ prefix +": "+ valueToTest + suffix+")").matches){
- return Promise.resolve(searchValue.isEqual)
- }
- else if (window.matchMedia("("+ maxPrefix +": "+ valueToTest + suffix+")").matches){
- return Promise.resolve(searchValue.isSmaller)
- }
- else {
- return Promise.resolve(searchValue.isBigger)
- }
- } catch(e) {
- if (prefix == "-moz-device-pixel-ratio") {prefix = "devicePixelRatio_moz"}
- return Promise.reject(log_error("screen", prefix, e, isScope, 40))
- }
- }, maxValue, precision)
- })
- })
-}
+})
/* UA */
@@ -1013,7 +1008,8 @@ function get_android_tap() {
function goFS() {
dom.fsLeak = ""
- const initialState = getElementProp(SECT1, "#cssDM")
+ const initialState = getElementProp(SECT1, "#cssDM", "display-mode_css")
+
let ih1 = window.innerHeight,
delay = 1, n = 1,
sizeS = [], sizeE = []
@@ -1171,6 +1167,7 @@ function goNW_UA() {
}
/* OUTPUT */
+
function outputUA(os = isOS) {
let t0 = nowFn()
let aReported = [], oComplex = {}
@@ -1252,31 +1249,20 @@ function outputUA(os = isOS) {
},
}
if (isSmart && os !== undefined) {
- // 1818889: RFP 115-119 freezes rv at 109
- let uaVer = isVer, rvVer = (isVer > 114 && isVer < 120 ? 109 : isVer)
- let uaRFP = "Mozilla/5.0 (" + oRFP[os].ua_os +"; rv:"
- let uaNext = isVerExtra === "+" ? uaRFP : undefined
- if (os == "android") {
- // android
- if (isVer > 119) {
- // 1806690: RFP 120+ drops matching ESR + frozen rv
- uaRFP += uaVer +".0) Gecko/"+ isVer +".0 Firefox/"+ uaVer +".0"
- if (isVerExtra === "+") {
- // next: isVer is now at least 120 so we can ignore frozen rv
- uaNext += (isVer + 1) +".0) Gecko/"+ (isVer + 1) +".0 Firefox/"+ (isVer + 1) +".0"
- oRFP[os]["userAgentNext"] = uaNext
- }
- } else {
- uaVer = isVer < 115 ? 102 : 115
- rvVer = (isVer < 114 && isVer > 120) ? uaVer : 109
- uaRFP += rvVer +".0) Gecko/"+ uaVer +".0 Firefox/"+ uaVer +".0"
- }
+ let uaVer = isVer, isDroid = isOS == "android"
+ let uaRFP = "Mozilla/5.0 (" + oRFP[os].ua_os +"; rv:" // base
+ let uaNext = uaRFP // only used if ver+
+
+ if (uaVer < 120) {
+ // 1818889: RFP 115-119 rv=109, droid version = 115
+ uaRFP += "109.0) Gecko/"+ (isDroid ? "115.0" : "20100101") +" Firefox/"+ (isDroid? "115" : uaVer) +".0"
} else {
- // desktop
- uaRFP += rvVer +".0) Gecko/20100101 Firefox/"+ uaVer +".0"
+ // 1806690: RFP 120+ drops frozen rv + droid version spoof
+ uaRFP += uaVer +".0) Gecko/" + (isDroid ? uaVer +".0" : "20100101") +" Firefox/"+ uaVer +".0"
+ // next
if (isVerExtra === "+") {
- // next: isVer is now at least 120 so we can ignore frozen rv
- uaNext += (uaVer + 1) +".0) Gecko/20100101 Firefox/"+ (uaVer + 1) +".0"
+ let nxtVer = uaVer + 1
+ uaNext += nxtVer +".0) Gecko/"+ (isDroid ? nxtVer +".0" : "20100101") +" Firefox/"+ nxtVer +".0"
oRFP[os]["userAgentNext"] = uaNext
}
}
@@ -1323,6 +1309,19 @@ function outputUA(os = isOS) {
function outputFD() {
let t0 = nowFn()
+
+ if (!isGecko) {
+ addData(3, "browser", "non-gecko")
+ log_display(3, "fdBrandingCss", zNA)
+ log_display(3, "fdResourceCss", zNA)
+ log_display(3, "browser", zNA)
+ log_display(3, "browser_architecture", zNA)
+ log_display(3, "os", zNA)
+ log_display(3, "version", zNA)
+ log_section(3, t0)
+ return
+ }
+
// logo
if (gLoad || isLogo == zErr || runST || runSE) {
try {
@@ -1382,6 +1381,7 @@ function outputFD() {
// browser
let METRIC = "browser"
let browser = (isMullvad ? "Mullvad Browser" : (isTB ? "Tor Browser" : "Firefox"))
+
log_display(3, METRIC, browser + " | "+ isLogo +" | "+ isWordmark)
addData(3, METRIC, browser)
addData(3, "logo", isLogo)
@@ -1399,34 +1399,29 @@ function outputFD() {
log_error(SECT3, METRIC, e)
}
- // version
- let r = isVer
- if (isVerExtra !== "") {r += isVerExtra}
- addDataDisplay(3, "version", r)
-
// os
METRIC = "os"
let hasErr = isOSErr !== undefined
log_display(3, METRIC, (hasErr ? isOSErr : isOS))
addData(3, METRIC, (hasErr ? zErr : isOS))
+ // version
+ let ver = isVer
+ if (isVerExtra !== "") {ver += isVerExtra}
+ addDataDisplay(3, "version", ver)
+
// os arch: FF110+ pref removed: error means 32bit
METRIC = "browser_architecture"
- let notation = ""
- let check = (isTB && isSmart && isVer < 110) // TB health check
if (isArch === true) {
- notation = check ? tb_red : ""
- log_display(3, METRIC, "64bit" + notation)
+ log_display(3, METRIC, "64bit")
addData(3, METRIC, 64)
} else {
let isMsg = isArch === "RangeError: invalid array length"
- if (isVer > 109 && isMsg) {
- if (check) {notation = tb_red}
- log_display(3, METRIC, "32bit" + notation)
+ if (ver > 109 && isMsg) {
+ log_display(3, METRIC, "32bit")
addData(3, METRIC, 32)
} else {
- if (check) {notation = (isMsg ? tb_green : tb_red)}
- log_display(3, METRIC, isArch + notation)
+ log_display(3, METRIC, isArch)
addData(3, METRIC, zErr)
}
}
@@ -1440,15 +1435,14 @@ function outputScreenResize(runtype) {
return new Promise(resolve => {
Promise.all([
- get_scr_fullscreen(),
+ get_scr_fullscreen(runtype),
get_scr_positions("screen"),
get_scr_positions("window"),
- get_scr_subpixels(runtype),
+ get_scr_pixels(runtype),
get_scr_scrollbar(runtype), // gets viewport
get_scr_orientation(runtype),
- get_scr_window(runtype),
- get_scr_window_mm(runtype),
+ get_scr_measure(runtype),
]).then(function(results){
if (runtype !== "screen") {
diff --git a/js/storage.js b/js/storage.js
index f66217ef..2574605b 100644
--- a/js/storage.js
+++ b/js/storage.js
@@ -119,7 +119,9 @@ const get_storage_manager = (delay = 170) => new Promise(resolve => {
try {
navigator.storage.persist().then(function(persistent) {
navigator.storage.estimate().then(estimate => {
- exit(`${estimate.usage} of ${estimate.quota} bytes`)
+ // we don't care about estimate.usage
+ let value = Math.floor(estimate.quota/(1073741824) * 10)/10 // round down
+ exit(value +"GB ["+ estimate.quota +" bytes]")
})
})
} catch(e) {
@@ -154,8 +156,9 @@ const get_storage_quota = () => new Promise(resolve => {
const get_permissions = (item) => new Promise(resolve => {
const METRIC = "permission_"+ item
+ let notation = ""
function exit(value) {
- let notation = value == "prompt" ? "" : default_red
+ if (isSmart) {notation = value == "prompt" ? "" : default_red}
log_display(6, METRIC, value + notation)
if (item == "persistent-storage" && value == "granted") {
// silent run manager to force granted quota when run
diff --git a/js/webgl.js b/js/webgl.js
index 69901054..b258b045 100644
--- a/js/webgl.js
+++ b/js/webgl.js
@@ -342,7 +342,7 @@ function outputWebGL() {
const [webGL2Data, webGL2Errors] = webGL2
const [experimentalWebGLData, experimentalWebGLErrors] = experimentalWebGL
- //*
+ /*
console.log('WebGLRenderingContext: ', mini(webGLData), webGLData)
if (webGLErrors.length) {console.log('webGL Errors',webGLErrors)}
console.log('WebGL2RenderingContext: ', webGL2Data)
diff --git a/tzp.html b/tzp.html
index 6a0f4727..62c20b87 100644
--- a/tzp.html
+++ b/tzp.html
@@ -31,7 +31,7 @@
- | |
---|---|
@@ -407,7 +407,7 @@ | |
[PoC]   sign | |
[PoC] -   timezonename | |
[PoC]   unit | |
- | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
[ re-run ]
-
+
| ||||||||||||||||||
connection | ||||||||||||||||||
doNotTrack | ||||||||||||||||||
notifications | | | |||||||||||||||||
[ i ]
- notifications | push | persistent-storage
+ notifications | persistent-storage | push
  permissions | - | | + | | |||||||||||||||||
[ click ] storage manager | ||||||||||||||||||
color | -| | | | ||||||||||||||||
pixel depth | color depth | | | |||||||||||||||||
color gamut | -| | | | ||||||||||||||||
[ i ]
dom.maxHardwareConcurrency
  hardwareConcurrency | ||||||||||||||||||
any-hover | | | |||||||||||||||||
hover | | | |||||||||||||||||
any-hover | | | |||||||||||||||||
hover | | | |||||||||||||||||
[ i ]
media.navigator.enabled
  media devicesmedia.peerconnection.enabled | ||||||||||||||||||
mimeTypes | ||||||||||||||||||
plugins | ||||||||||||||||||
pdfViewerEnabled | ||||||||||||||||||
any-pointer | | | |||||||||||||||||
pointer | | | |||||||||||||||||
any-pointer | + | | |||||||||||||||||
pointer | | | |||||||||||||||||
[ mouse ]
[ i ]
@@ -636,8 +637,8 @@
[ click ]
hash | audioContext 2 | OscillatorNode 2 | OscillatorNode/DynamicsCompressor 2 | OscillatorNode 2 | audio code based on work by
kkapsner &
@@ -774,15 +775,15 @@
| forced-colors |
| | inverted-colors |
- | | | ||||||||
prefers-color-scheme | - | | |||||||||||||||||
prefers-contrast | - | | |||||||||||||||||
prefers-reduced-data | | | |||||||||||||||||
prefers-reduced-motion | - | | |||||||||||||||||
prefers-reduced-transparency | | | |||||||||||||||||
code by @@ -869,7 +870,6 @@ | ||||||||||||||||||
[ i ]
dom.enable_performance
  performance.timing | ||||||||||||||||||
PerformanceNavigationTiming | ||||||||||||||||||
stack depth | length | ||||||||||||||||||
[ i ]
svg.disabled
|