Skip to content

Instantly share code, notes, and snippets.

@pygy
Created May 2, 2020 22:20
Show Gist options
  • Save pygy/1347bf87837f17d3c7e7ab225bfbf490 to your computer and use it in GitHub Desktop.
Save pygy/1347bf87837f17d3c7e7ab225bfbf490 to your computer and use it in GitHub Desktop.
<!doctype html>
<title>ChargingGate </title>
<input type=checkbox id="hasGetBattery"><input type=checkbox id="batteryStatus">
<div id=ua></div>
<hr>
<h1>
#ChargingGate?
</h1>
<p>
Another day, another dystopian browser API...
</p>
<p>
Google Chrome, Microsoft Edge, Opera, and other Chromium derivatives let Web sites monitor the charging state of your device.
</p>
<p>
This is nifty for fingerprinying, as the status can be correlated across tabs and browsers, even if one session goes through a proxy/VPN, and the other doesn't.
</p>
<p>
Firefox, Safari, and Internet Explorer do not provide the battery status. Brave has the API enabled, but neutered (it behaves as if you were always charging).
</p>
<p>
That is this information freely available to anyone baffles the mind. The standard was misguided and has been deprecated, why is this still enabled, Google?
</p>
<pre>
<script>
if (typeof navigator.getBattery === "function") {
hasGetBattery.checked = true
navigator.getBattery().then(bm => {
batteryStatus.checked = bm.charging
bm.onchargingchange = e => (
batteryStatus.checked = e.target.charging
)
})
}
ua.textContent = navigator.userAgent
for (const [name, rx] of Object.entries({
Safari: /Version\/[\d+\.]+ Safari\/[\d+\.]+/i,
"Microsoft Edge": /edge?/i,
Opera: /OPR\//i,
Firefox: /Gecko\/\d+ Firefox\/\d+/,
"Google Chrome": /Chrome\/[\d\.]+ Safari\/[\d\.]+/,
Chromium: /\bChrome\b/,
"Your Unrecognized Browser": /.*/
})) {
if (rx.test(navigator.userAgent)) {
const title = document.head.firstChild
title.textContent += (document.body.className = name)
break
}
}
var request = new XMLHttpRequest()
request.open('GET', 'https://api.duckduckgo.com/?q=useragent&format=json', true)
request.onload = function () {
var data = JSON.parse(this.response)
var isBrave = data['Answer'].includes('Brave');
if(isBrave){
document.body.className = "Brave"
}
}
request.send()
</script>
</pre>
<style>
* {
font-family: sans-serif;
}
body {
max-width: 600px;
margin: 0 auto;
padding: 12px 15px;
}
body::before {
content: attr(class);
display: inline;
font-size: 20px;
}
#ua {
margin-top: 0.75em;
font-size: 0.75em
}
p {
margin-top: 1.5em;
line-height: 1.5em;
}
input {
-webkit-appearance:none;
display: inline;
pointer-events: none;
font-size: 18px;
}
input:checked {
display: none;
}
input + #batteryStatus {
display:none;
}
input:checked + #batteryStatus {
display:inline;
}
input::after {
display: inline;
}
#hasGetBattery::before {
content: "👍, thankfully, does not let Web sites access the battery status.";
}
#hasGetBattery:checked::before{
content: "";
}
.Brave input#hasGetBattery:checked {
margin: 0;
display: inline;
}
.Brave input#hasGetBattery:checked::before{
content: " 👍";
}
#batteryStatus::before {
content: "🔋 tells Web pages that your device is";
}
#batteryStatus:checked::before {
content: "🔌tells the Web that your device is";
}
#batteryStatus::after {
font-weight: bold;
content: " unplugged.";
}
#batteryStatus:checked::after {
content: " plugged.";
}
.Brave #batteryStatus:checked::after {
font-weight: normal;
content: " plugged... no matter what its actual status is. Good.";
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment