Skip to content

Commit b06512e

Browse files
Remote value support (#65)
* Moving to use Swift module * Make values for hardware remoted * Support feature setting types objects from remote config * Support apple silicon config values Co-authored-by: Brad Slayter <slayterdevelopment@gmail.com>
1 parent 80dcfca commit b06512e

File tree

15 files changed

+511
-39
lines changed

15 files changed

+511
-39
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
build/
22
lib/
3+
Sources/ContentScopeScripts/dist/
34
integration-test/extension/contentScope.js

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
Sources/ContentScopeScripts/dist/** binary
12
build/** binary linguist-generated
23
shared/** binary linguist-generated

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.DS_Store
22
node_modules/
3+
.swiftpm

Package.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// swift-tools-version:5.3
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "ContentScopeScripts",
8+
products: [
9+
// Products define the executables and libraries a package produces, and make them visible to other packages.
10+
.library(
11+
name: "ContentScopeScripts",
12+
targets: ["ContentScopeScripts"]),
13+
],
14+
dependencies: [
15+
],
16+
targets: [
17+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
18+
// Targets can depend on other targets in this package, and on products in packages this package depends on.
19+
.target(
20+
name: "ContentScopeScripts",
21+
dependencies: [],
22+
resources: [
23+
.process("dist")
24+
]
25+
),
26+
]
27+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Foundation
2+
3+
public struct ContentScopeScripts {
4+
public static var Bundle: Bundle = .module
5+
}

build/apple/contentScope.js renamed to Sources/ContentScopeScripts/dist/contentScope.js

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,17 @@
717717
};
718718
// TODO
719719
preferences.cookie = {};
720+
721+
// Copy feature settings from remote config to preferences object
722+
preferences.featureSettings = {};
723+
remoteFeatureNames.forEach((featureName) => {
724+
if (!enabledFeatures.includes(featureName)) {
725+
return
726+
}
727+
728+
preferences.featureSettings[featureName] = data.features[featureName].settings;
729+
});
730+
720731
return preferences
721732
}
722733

@@ -1596,6 +1607,83 @@
15961607
})
15971608
}
15981609

1610+
// We use this method to detect M1 macs and set appropriate API values to prevent sites from detecting fingerprinting protections
1611+
function isAppleSilicon () {
1612+
const canvas = document.createElement('canvas');
1613+
const gl = canvas.getContext('webgl');
1614+
1615+
// Best guess if the device is an Apple Silicon
1616+
// https://stackoverflow.com/a/65412357
1617+
return gl.getSupportedExtensions().indexOf('WEBGL_compressed_texture_etc') !== -1
1618+
}
1619+
1620+
/**
1621+
* Take configSeting which should be an array of possible values.
1622+
* If a value contains a criteria that is a match for this environment then return that value.
1623+
* Otherwise return the first value that doesn't have a criteria.
1624+
*
1625+
* @param {*[]} configSetting - Config setting which should contain a list of possible values
1626+
* @returns {*|undefined} - The value from the list that best matches the criteria in the config
1627+
*/
1628+
function processAttrByCriteria (configSetting) {
1629+
let bestOption;
1630+
for (const item of configSetting) {
1631+
if (item.criteria) {
1632+
if (item.criteria.arch === 'AppleSilicon' && isAppleSilicon()) {
1633+
bestOption = item;
1634+
break
1635+
}
1636+
} else {
1637+
bestOption = item;
1638+
}
1639+
}
1640+
1641+
return bestOption
1642+
}
1643+
1644+
/**
1645+
* Get the value of a config setting.
1646+
* If the value is not set, return the default value.
1647+
* If the value is not an object, return the value.
1648+
* If the value is an object, check its type property.
1649+
*
1650+
* @param {string} featureName
1651+
* @param {object} args
1652+
* @param {string} prop
1653+
* @param {any} defaultValue - The default value to use if the config setting is not set
1654+
* @returns The value of the config setting or the default value
1655+
*/
1656+
function getFeatureAttr (featureName, args, prop, defaultValue) {
1657+
let configSetting = getFeatureSetting(featureName, args, prop);
1658+
1659+
if (configSetting === undefined) {
1660+
return defaultValue
1661+
}
1662+
1663+
const configSettingType = typeof configSetting;
1664+
switch (configSettingType) {
1665+
case 'object':
1666+
if (Array.isArray(configSetting)) {
1667+
configSetting = processAttrByCriteria(configSetting);
1668+
if (configSetting === undefined) {
1669+
return defaultValue
1670+
}
1671+
}
1672+
1673+
if (!configSetting.type) {
1674+
return defaultValue
1675+
}
1676+
1677+
if (configSetting.type === 'undefined') {
1678+
return undefined
1679+
}
1680+
1681+
return configSetting.value
1682+
default:
1683+
return defaultValue
1684+
}
1685+
}
1686+
15991687
/**
16001688
* @param {string} featureName
16011689
* @param {object} args
@@ -3610,24 +3698,26 @@
36103698
init: init$9
36113699
});
36123700

3701+
const featureName$1 = 'fingerprinting-hardware';
3702+
36133703
function init$8 (args) {
36143704
const Navigator = globalThis.Navigator;
36153705
const navigator = globalThis.navigator;
36163706

36173707
overrideProperty('keyboard', {
36183708
object: Navigator.prototype,
36193709
origValue: navigator.keyboard,
3620-
targetValue: undefined
3710+
targetValue: getFeatureAttr(featureName$1, args, 'keyboard')
36213711
});
36223712
overrideProperty('hardwareConcurrency', {
36233713
object: Navigator.prototype,
36243714
origValue: navigator.hardwareConcurrency,
3625-
targetValue: 2
3715+
targetValue: getFeatureAttr(featureName$1, args, 'hardwareConcurrency', 2)
36263716
});
36273717
overrideProperty('deviceMemory', {
36283718
object: Navigator.prototype,
36293719
origValue: navigator.deviceMemory,
3630-
targetValue: 8
3720+
targetValue: getFeatureAttr(featureName$1, args, 'deviceMemory', 8)
36313721
});
36323722
}
36333723

@@ -3636,6 +3726,8 @@
36363726
init: init$8
36373727
});
36383728

3729+
const featureName = 'fingerprinting-screen-size';
3730+
36393731
/**
36403732
* normalize window dimensions, if more than one monitor is in play.
36413733
* X/Y values are set in the browser based on distance to the main monitor top or left, which
@@ -3725,12 +3817,12 @@
37253817
origPropertyValues.availTop = overrideProperty('availTop', {
37263818
object: Screen.prototype,
37273819
origValue: screen.availTop,
3728-
targetValue: 0
3820+
targetValue: getFeatureSetting(featureName, args, 'availTop')
37293821
});
37303822
origPropertyValues.availLeft = overrideProperty('availLeft', {
37313823
object: Screen.prototype,
37323824
origValue: screen.availLeft,
3733-
targetValue: 0
3825+
targetValue: getFeatureSetting(featureName, args, 'availLeft')
37343826
});
37353827
origPropertyValues.availWidth = overrideProperty('availWidth', {
37363828
object: Screen.prototype,
@@ -3745,12 +3837,12 @@
37453837
overrideProperty('colorDepth', {
37463838
object: Screen.prototype,
37473839
origValue: screen.colorDepth,
3748-
targetValue: 24
3840+
targetValue: getFeatureSetting(featureName, args, 'colorDepth')
37493841
});
37503842
overrideProperty('pixelDepth', {
37513843
object: Screen.prototype,
37523844
origValue: screen.pixelDepth,
3753-
targetValue: 24
3845+
targetValue: getFeatureSetting(featureName, args, 'pixelDepth')
37543846
});
37553847

37563848
window.addEventListener('resize', function () {

build/chrome/inject.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/firefox/inject.js

Lines changed: 88 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)