faisalman / ua-parser-js

UAParser.js - The Essential Web Development Tool for User-Agent Detection.
https://uaparser.dev/
GNU Affero General Public License v3.0
9.14k stars 1.19k forks source link

don't rely on getHighEntropyValues to detect Apple Silicon #732

Open kkuepper opened 3 months ago

kkuepper commented 3 months ago

Is your feature request related to a problem? Please describe. isAppleSilicon() is not returning the expected result on Firefox and Safari.

Describe the solution you'd like Instead of relying on getHighEntropyValues, it's testing if WebGL is working as described on StackOverflow

Describe alternatives you've considered Currently we're using the following code instead of ua-parser-js implementation:

function isAppleSilicon() {
  try {
    // Best guess if the device uses Apple Silicon: https://stackoverflow.com/a/65412357
    const w = document.createElement("canvas").getContext("webgl");
    if (w == null) {
      return false;
    }
    const d = w.getExtension("WEBGL_debug_renderer_info");
    const g = (d && w.getParameter(d.UNMASKED_RENDERER_WEBGL)) || "";
    if (g.match(/Apple/) && !g.match(/Apple GPU/)) {
      return true;
    }

    if (
      // @ts-expect-error - Object is possibly 'null'
      w.getSupportedExtensions().includes("WEBGL_compressed_texture_s3tc_srgb")
    ) {
      return true;
    }
  } catch {
    return false;
  }

  return false;
}

Additional context I tested the above solution on Safari, Firefox and Chrome on M1 Mac. I didn't test on non-Apple Silicon though.

SubJunk commented 3 months ago

I confirm this bug. This is a screenshot from https://uaparser.dev in Firefox on macOS with M1. The CPU field is empty. It also incorrectly displays the OS version as v10.15 when I am using v14.2.1:

image
faisalman commented 3 months ago

Thanks for the report @kkuepper @SubJunk

In the linked StackOverflow answer, the latest comment mentioned that the WEBGL_compressed_texture_s3tc_srgb extension doesn't seem to be missing anymore in his M1.

Thus it leaves us with this only WebGL renderer check:

if (g.match(/Apple/) && !g.match(/Apple GPU/)) {

Is there a chance that it would return true on any Intel-based Apple device? If not, I would be happy to add this check as well to the existing isAppleSilicon().

kkuepper commented 2 months ago

Is there a chance that it would return true on any Intel-based Apple device? If not, I would be happy to add this check as well to the existing isAppleSilicon().

@faisalman Is that a question to me? I can't really answer that, since I have an M1 Mac.

SubJunk commented 2 months ago

I can check on an Intel Mac soon

Stitchuuuu commented 2 months ago

@faisalman

Thanks for the report @kkuepper @SubJunk

In the linked StackOverflow answer, the latest comment mentioned that the WEBGL_compressed_texture_s3tc_srgb extension doesn't seem to be missing anymore in his M1.

Thus it leaves us with this only WebGL renderer check:

if (g.match(/Apple/) && !g.match(/Apple GPU/)) {

Is there a chance that it would return true on any Intel-based Apple device? If not, I would be happy to add this check as well to the existing isAppleSilicon().

I don't think so. On my Intel Mac (Mac Mini 2018), it's showing Intel UHD Graphics. And this website got a lot of those values, and it shows there's no other "Apple" except "Apple GPU" : https://deviceandbrowserinfo.com/data/fingerprints/attribute/webGLRenderer

If there's people who have other Intel Mac, here is a codepen link to test it : https://codepen.io/Stitchuuuu/full/XWLKGJN/full

EDIT: Just a precision. It's working for every browsers except Safari. Safari always set "Apple GPU" in this property, whatever the graphic card is.

SubJunk commented 2 months ago

Thanks for checking, I forgot to check

momon commented 2 months ago

One of my team mates and I tested this. He is on an Intel Mac and I am on Apple Silicon.

In our use case, we are just trying to validate if the user is on Apple Silicon or not, so our tests are only relevant to that.

His test results are successful on Firefox, Chrome and Safari (as in, it doesn't detect apple silicon). When I test it works on all browsers, except for Safari. Safari reports me as NOT being on apple silicon whereas I actually am.

Stitchuuuu commented 2 months ago

One of my team mates and I tested this. He is on an Intel Mac and I am on Apple Silicon.

In our use case, we are just trying to validate if the user is on Apple Silicon or not, so our tests are only relevant to that.

His test results are successful on Firefox, Chrome and Safari (as in, it doesn't detect apple silicon). When I test it works on all browsers, except for Safari. Safari reports me as NOT being on apple silicon whereas I actually am.

It was always a problem on a Safari even on day 1. It seems there is no method, even getHighEntropies that’s working on Safari Apple Silicon :x