@magield/collectors 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@ import { hashRecord } from '../hash.js';
10
10
  export const navigatorCollector = {
11
11
  id: 'nav',
12
12
  wave: 'instant',
13
- collect({ navigator }) {
13
+ collect({ navigator, window }) {
14
14
  const out = {
15
15
  'nav.userAgent': navigator.userAgent ?? null,
16
16
  'nav.platform': read(() => navigator.platform),
@@ -36,6 +36,13 @@ export const navigatorCollector = {
36
36
  // correct outcome — they are then judged on everything else, like any
37
37
  // other client.
38
38
  'nav.brave': read(() => 'brave' in navigator),
39
+ // Opera's own object, the way `navigator.brave` is Brave's: Opera puts
40
+ // `window.opr` on its pages, and a script that only rewrote its user
41
+ // agent to say `OPR/` has no reason to. Read beside the browser's
42
+ // brands when the gateway decides whether a TLS handshake that looks
43
+ // nothing like a browser's was made by Opera's own proxy. A fact, scored
44
+ // at nothing.
45
+ 'nav.opr': read(() => 'opr' in window),
39
46
  };
40
47
  // Plugin *shape* is browser-family specific and survives spoofing of the
41
48
  // user agent, because faking it convincingly means faking a whole list.
@@ -44,6 +51,14 @@ export const navigatorCollector = {
44
51
  // client claiming Gecko while exposing it is claiming two things that have
45
52
  // never been true together.
46
53
  out['nav.hasUserAgentData'] = navigator.userAgentData !== undefined;
54
+ // The brands the browser generates for itself, in the form `cap.uaBrands`
55
+ // writes. Read here as well because that collector runs in the deep wave,
56
+ // which a default collect skips: a synchronous property costs nothing, and
57
+ // the gateway reads it to tell Opera from a script that says `OPR/`.
58
+ out['nav.uaBrands'] = read(() => {
59
+ const brands = navigator.userAgentData?.brands;
60
+ return brands === undefined ? undefined : brands.map((b) => `${b.brand}/${b.version}`).sort().join(',');
61
+ });
47
62
  out['nav.pluginCount'] = plugins;
48
63
  if (typeof plugins === 'number' && plugins > 0) {
49
64
  const names = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magield/collectors",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "Browser signal collectors used by the Magic Shield web SDK",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "files": [