creepjs icon indicating copy to clipboard operation
creepjs copied to clipboard

create screen test and capture css media fingerprint

Open abrahamjuliot opened this issue 4 years ago • 17 comments

https://developer.mozilla.org/en-US/docs/Web/CSS/@media

  • [x] - devicePixelRatio
  • [x] - matchMedia
  • [x] - @media: https://jsfiddle.net/w8qxu1p2/1/
  • [x] - detect screen via getComputedStyle: https://jsfiddle.net/jrnca3wh/
  • [x] @import can access media queries: https://jsfiddle.net/s8xcg0ou/3/
matchMedia(`(min-device-height:${screen.height}px)`).matches
matchMedia(`(min-device-width:${screen.width}px)`).matches
matchMedia(`(max-device-height:${screen.height}px)`).matches
matchMedia(`(max-device-width:${screen.width}px)`).matches
matchMedia(`(device-height:${screen.height}px)`).matches
matchMedia(`(device-width:${screen.width}px)`).matches

abrahamjuliot avatar Dec 05 '20 23:12 abrahamjuliot

https://abrahamjuliot.github.io/creepjs/tests/screen.html

orientation and viewport are undefined - FF nightly 86, and yes my inner is square :)

undefined

tzp has a scrollbar hence viewport is not 1000x1000 tzp

Thorin-Oakenpants avatar Jan 10 '21 06:01 Thorin-Oakenpants

https://jsfiddle.net/873kspn4/1/

FF nightly 86 RFP off = prefersColorScheme: "", prefersReducedMotion: "" FF nightly 86 RFP on = prefersColorScheme: "", prefersReducedMotion: "no-preference"

What does import gain over just a straight css (besides the fact that JS can read it quickly)

Thorin-Oakenpants avatar Jan 10 '21 08:01 Thorin-Oakenpants

viewport

I'm now discovering, FF has visualViewport behind the flag dom.visualviewport.enabled. This should now yield the unsupported label if both dimensions are undefined.

orientation

Oops, that's a bug I left in there. Fixed.

@import

@media and @import are pretty much the same. I might add this later to test if Chromium's proposed privacy budget covers both and matchMedia.

abrahamjuliot avatar Jan 10 '21 09:01 abrahamjuliot

https://bugzilla.mozilla.org/show_bug.cgi?id=1579584#c5 and subsequent comments

I've been letting android tests lapse. Anyway, if I read that right, then we can detect if dynamic toolbar is enabled? I should make a test: i.e if enabled 100vh - inner = toolbar height ... if disabled 100vh - inner = zero

wanna test that for me?

Thorin-Oakenpants avatar Jan 10 '21 12:01 Thorin-Oakenpants

I do not know what you mean by @media and by MediaQueryList. What is the difference? Which one is @matchmedia if any?

I have questions. Using Firefox Nightly on Android. RFP off on the left, RFP on on the right

screen test

  • Both
    • why the fake screen returns
    • why is the height different in visualViewport
      • note: how are you getting this. In TZP we use a binary search in matchmedia to get subpixels (decimals) for measurements (screen, inner etc) which show up when the devicePixelRatio != 1 = almost always on android = entropy galore!!
  • RFP on
    • why undefined for heights
    • why is aspect ratio fake? in TZP with RFP on this is all portrait (all 8 values). What are you using to calculate 16/9 or 6/13 etc
    • FWIW I don't think it's worthwhile returning e.g. 16/9 when that entropy is already in the width + height measurements: but maybe you're trying to catch something out here, like an extension lie? Please explain yourself young man, or you won't get any pudding.

screen


creepy test

  • green boxes on RFP=on

creepy

Thorin-Oakenpants avatar Jan 10 '21 16:01 Thorin-Oakenpants

100vh - inner = toolbar height ... if disabled 100vh - inner = zero

This seems the same as obtaining 100vh and inner (the difference is only unspoken). I'm not sure how 100vh were obtained to verify this, but document.documentElement.clientHeight should match window.innerHeight. I don't have a dynamic tooldbar (?) on my devices.

 const hasToolbar = !!(document.documentElement.clientHeight - window.innerHeight)

abrahamjuliot avatar Jan 11 '21 03:01 abrahamjuliot

MediaQueryList and matchMedia are the same. MediaQueryList is the object returned.

abrahamjuliot avatar Jan 11 '21 04:01 abrahamjuliot

I don't have a dynamic toolbar

Android > Firefox > Settings > General > Customize > Scroll to hide toolbar (default = on)

Thorin-Oakenpants avatar Jan 11 '21 04:01 Thorin-Oakenpants

screen test

  • fake screen: if a result is undefined, the screen is presumed fake. I added the output and limited the fake test to screen (the test just compares screen with matchMedia). I'm realizing this returns a false positive if the matchMedia only matches a float, but I've only noticed this in an android emulator (I presume it's the same in a virtual machine) and in those context, the screen size is technically fake. Are you getting a fake screen on an actual android device?
  • visualViewport: this returns a float height on FF Android. I'm now using Math.round in the template output, but the floating point might provide some entropy in a fingerprint.
const vViewport = 'visualViewport' in window ? visualViewport : { }
const { width: viewportWidth, height: viewportHeight } = vViewport
console.log(`${Math.round(viewportWidth)} x ${Math.round(viewportHeight)}`)
  • undefined heights/aspect ratio: since I'm searching for an integer (up to 10000px), if there is no match it's undefined.
  • 16/9 aspect ratio: this is really not that useful since width height reveals the same (aspect-ratio is only unspoken)
// gcd is based on https://stackoverflow.com/a/1186465
const gcd = (a, b) => b == 0 ? a : gcd(b, a%b)
const { innerWidth, innerHeight } = window
const { width: screenWidth, height: screenHeight } = screen
const ratio = gcd(innerWidth, innerHeight)
const screenRatio = gcd(screenWidth, screenHeight)
const aspectRatio = `${innerWidth/ratio}/${innerHeight/ratio}`
const deviceAspectRatio = `${screenWidth/screenRatio}/${screenHeight/screenRatio}`
/*css*/
@media (aspect-ratio: ${aspectRatio}) {
	body {--viewport-aspect-ratio: ${aspectRatio};}
}
@media (device-aspect-ratio: ${deviceAspectRatio}) {
	body {--device-aspect-ratio: ${deviceAspectRatio};}
}

abrahamjuliot avatar Jan 11 '21 05:01 abrahamjuliot

dynamic toolbar

I'm not sure there is practical method to detect this since the toolbar is only hidden when/if the user scrolls.

abrahamjuliot avatar Jan 11 '21 05:01 abrahamjuliot

creepy test

I use an iframe for the screen metrics on creep, and as far as I know RFP restricts screen metrics in iframes.

abrahamjuliot avatar Jan 11 '21 05:01 abrahamjuliot

what are you using for getting vunits?

function get_vunits() {
	let div, vh1, vw1
	div = document.createElement("vunits")
	div.style.height = "100vh"
	div.style.width = "100vw"
	div.style.maxHeight = "none"
	div.style.boxSizing = "content-box"
	document.body.appendChild(div)
	vw1 = div.clientWidth
	vh1 = div.clientHeight
	document.body.removeChild(div)
	console.log(vw1 +" x "+ vh1) // I get 0x0 .. approx 2ms

	function vh(v) {
		let h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
		return (v * h) / 100;
	}
	function vw(v) {
		let w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
		return (v * w) / 100;
	}
	function vmin(v) {
		return Math.min(vh(v), vw(v));
	}
	function vmax(v) {
		return Math.max(vh(v), vw(v));
	}
	console.log(vw(100), Math.max(document.documentElement.clientWidth, window.innerWidth || 0));
	console.log(vh(100), Math.max(document.documentElement.clientHeight, window.innerHeight || 0));
	console.log(vmin(100));
	console.log(vmax(100)); // approx 1 or 2 ms
}

Thorin-Oakenpants avatar Jan 11 '21 05:01 Thorin-Oakenpants

Are you getting a fake screen on an actual android device

Yes. The screen shots are from my realsies android

but the floating point might provide some entropy in a fingerprint

entropy is good: we get this (decimals) on TZP when devicePixelRatio is not 1. Just wondering why the value changed

edit: there is also this: https://devicepixelratio.glitch.me/

PS: I have been looking at expanding other measuring methods in the screen section for some time

  • v units was one on my list
  • visualViewport was also noted (and there's a change in FF coming to allow subpixel measurements: not sure if VViewport or just inner etc)
  • I wanted to look at that glitchme code
  • now you've listed
    • import
    • computedStyle
    • @media (I'm still not sure what that means)
    • matchMedia object
    • using an iframe
  • I also already have an element that is set to 100 width/height that I use for when you do the FS test

Would be nice to list get all this into TZP

Thorin-Oakenpants avatar Jan 11 '21 05:01 Thorin-Oakenpants

vh units

I use document.documentElement.clientHeight. It's the same as above. Where v is 100 and h is clientHeight, (v * h) / 100 yields the same result as h

abrahamjuliot avatar Jan 11 '21 05:01 abrahamjuliot

TZP when devicePixelRatio is not 1

That's sounds awesome. I'll take a look and try it out.

abrahamjuliot avatar Jan 11 '21 05:01 abrahamjuliot

^^ big edit 3 posts up :)

edit: and intersection observer which I have a poc lying around

Thorin-Oakenpants avatar Jan 11 '21 05:01 Thorin-Oakenpants

TZP when devicePixelRatio is not 1

That's sounds awesome. I'll take a look and try it out.

the decimal places happen because of the real devicePixelRatio, not because I factor in the reported dPR

Here is my realsies android with RFP on

  • it hides dPR as 1, in reality it is 2.60.. something. Note my PoC that exposes an almost real value
  • I am not using that dPR PoC at all, but note the two matchMedia ~~min~~ height results have decimal places - revealing entropy and the existence of subpixels tzp

Thorin-Oakenpants avatar Jan 11 '21 05:01 Thorin-Oakenpants