Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
bee4106
Initial PoC windows brand hints override
laghee Oct 14, 2025
b1a0458
Clean up extraneous quick test and comments
laghee Oct 14, 2025
9592f42
Mirror native approach for headers in js api override
laghee Oct 21, 2025
dbdebd9
Fix errant space
laghee Oct 21, 2025
d142735
Return early if brands config is missing or malformed
laghee Nov 2, 2025
cc7a316
Rename feature more generally
laghee Nov 2, 2025
3ce98f8
Merge remote-tracking branch 'origin/main' into km/add-ch-brand-shim
laghee Nov 2, 2025
4bc32a4
Clean up unnecessary bits, fix auto-complaints
laghee Nov 3, 2025
0bf2a5f
Merge remote-tracking branch 'origin/main' into km/add-ch-brand-shim
laghee Nov 3, 2025
271e18d
Fix missing GREASE value
laghee Nov 3, 2025
1125d9d
Lint
laghee Nov 3, 2025
c6b0a1f
Add debug logging
laghee Nov 21, 2025
bbc26a4
Add different logging attempt
laghee Nov 21, 2025
56e2faa
Force debug to surface logging
laghee Nov 21, 2025
308501b
Force debug logging in content-feature
laghee Nov 21, 2025
8aa428c
LOG, DAMMIT
laghee Nov 21, 2025
0ef8669
Figure out why not running
laghee Nov 21, 2025
ec67adf
Switch order to match header indices + clean up debug logging
laghee Nov 21, 2025
129f447
Address bot comment
laghee Nov 21, 2025
152f3d5
Merge branch 'origin/main' into km/add-ch-brand-shim
laghee Nov 21, 2025
ae9abf9
Clean up old cached code
laghee Nov 24, 2025
2f535c0
Simplify approach by replicating native: overwrite Edge, zap WebView2…
laghee Nov 24, 2025
941714d
Overwrite fullVersionList brands as well
laghee Nov 24, 2025
deb3631
Address cursorbot comment on not directly modifying browser objects
laghee Nov 24, 2025
2fefa76
Make test names clearer
laghee Nov 24, 2025
c90d720
Merge 'origin/main' into km/add-ch-brand-shim
laghee Nov 24, 2025
537a8d5
Address further cranky bot comment
laghee Nov 24, 2025
94796ff
Botttttt
laghee Nov 24, 2025
9e4d0a6
Dimishing returns critical mass
laghee Nov 24, 2025
651637f
Add ability to apply different overrides per domain
laghee Nov 26, 2025
d34a0fe
Merge remote-tracking branch 'origin/main' into km/add-ch-brand-shim
laghee Nov 26, 2025
ba172b1
Switch to using conditionalChanges for more config control
laghee Nov 27, 2025
fcbe6e8
Merge remote-tracking branch 'origin/main' into km/add-ch-brand-shim
laghee Nov 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"readme": "This config tests that uaChBrands can override navigator.userAgentData brands",
"version": 1,
"unprotectedTemporary": [],
"features": {
"uaChBrands": {
"state": "enabled",
"exceptions": []
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"readme": "This config tests domain-specific brand overrides using conditionalChanges",
"version": 1,
"unprotectedTemporary": [],
"features": {
"uaChBrands": {
"state": "enabled",
"exceptions": [],
"settings": {
"conditionalChanges": [
{
"domain": "localhost",
"patchSettings": [
{
"op": "add",
"path": "/brandName",
"value": "Netscape Navigator"
}
]
}
]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"readme": "Test config with overrideEdge disabled but filterWebView2 enabled (default)",
"version": 1,
"unprotectedTemporary": [],
"features": {
"uaChBrands": {
"state": "enabled",
"exceptions": [],
"settings": {
"overrideEdge": "disabled"
}
}
}
}
17 changes: 17 additions & 0 deletions injected/integration-test/test-pages/ua-ch-brands/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>UA CH Brands</title>
<link rel="stylesheet" href="../shared/style.css">
</head>
<body>
<p><a href="../index.html">[Home]</a></p>

<p>UA CH Brands</p>
<ul>
<li><a href="./pages/brand-override.html">Brand Override</a> - <a href="./config/brand-override.json">Config</a></li>
</ul>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>UA CH Brands - Brand Override</title>
<link rel="stylesheet" href="../../shared/style.css">
</head>
<body>
<script src="../../shared/utils.js"></script>
<p><a href="../index.html">[UA CH Brands]</a></p>

<p>This page verifies that navigator.userAgentData overwrites the UA CH brands to match the Sec-CH-UA header when the uaChBrands feature is enabled.</p>

<script>
test('Brand override', async () => {
const results = [];

if (navigator.userAgentData && navigator.userAgentData.brands) {
const brands = navigator.userAgentData.brands;
const brandNames = new Set(brands.map(b => b.brand));

results.push({
name: 'navigator.userAgentData.brands contains DuckDuckGo',
result: brandNames.has('DuckDuckGo'),
expected: true
});

if (navigator.userAgentData.getHighEntropyValues) {
try {
const highEntropyValues = await navigator.userAgentData.getHighEntropyValues(['brands']);
if (highEntropyValues.brands) {
const heBrandNames = new Set(highEntropyValues.brands.map(b => b.brand));

results.push({
name: 'navigator.userAgentData.getHighEntropyValues brands contains DuckDuckGo',
result: heBrandNames.has('DuckDuckGo'),
expected: true
});
}
} catch (error) {
results.push({
name: 'getHighEntropyValues brands works',
result: false,
expected: true
});
}

try {
const fullVersionData = await navigator.userAgentData.getHighEntropyValues(['fullVersionList']);
if (fullVersionData.fullVersionList) {
const fvlBrandNames = new Set(fullVersionData.fullVersionList.map(b => b.brand));

results.push({
name: 'navigator.userAgentData.getHighEntropyValues fullVersionList contains DuckDuckGo',
result: fvlBrandNames.has('DuckDuckGo'),
expected: true
});
}
} catch (error) {
results.push({
name: 'getHighEntropyValues fullVersionList works',
result: false,
expected: true
});
}
}
} else {
results.push({
name: 'navigator.userAgentData.brands available',
result: false,
expected: true
});
}

return results;
});

renderResults();
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>UA-CH-Brands: Domain Brand Override Test</title>
</head>
<body>
<h1>UA-CH-Brands Domain Brand Override Test</h1>
<div id="results"></div>

<script type="module">
const results = [];

if (navigator.userAgentData?.brands) {
const brands = navigator.userAgentData.brands;
const netscapeCount = brands.filter(b => b.brand === 'Netscape Navigator').length;
const ddgCount = brands.filter(b => b.brand === 'DuckDuckGo').length;

results.push({
test: 'brands-contains-netscape',
result: netscapeCount > 0 ? 'PASS' : 'FAIL',
details: `Found ${netscapeCount} Netscape Navigator brand(s)`
});

results.push({
test: 'brands-no-duckduckgo',
result: ddgCount === 0 ? 'PASS' : 'FAIL',
details: `Found ${ddgCount} DuckDuckGo brand(s) (expected 0)`
});
}

if (navigator.userAgentData?.getHighEntropyValues) {
try {
const highEntropy = await navigator.userAgentData.getHighEntropyValues(['brands']);
if (highEntropy.brands) {
const brands = highEntropy.brands;
const netscapeCount = brands.filter(b => b.brand === 'Netscape Navigator').length;
const ddgCount = brands.filter(b => b.brand === 'DuckDuckGo').length;

results.push({
test: 'getHighEntropyValues-brands-contains-netscape',
result: netscapeCount > 0 ? 'PASS' : 'FAIL',
details: `Found ${netscapeCount} Netscape Navigator brand(s) in getHighEntropyValues brands`
});

results.push({
test: 'getHighEntropyValues-brands-no-duckduckgo',
result: ddgCount === 0 ? 'PASS' : 'FAIL',
details: `Found ${ddgCount} DuckDuckGo brand(s) in getHighEntropyValues brands (expected 0)`
});
}
} catch (e) {
results.push({
test: 'getHighEntropyValues-brands-error',
result: 'ERROR',
details: e.message
});
}
}

if (navigator.userAgentData?.getHighEntropyValues) {
try {
const highEntropy = await navigator.userAgentData.getHighEntropyValues(['fullVersionList']);
if (highEntropy.fullVersionList) {
const fvl = highEntropy.fullVersionList;
const netscapeCount = fvl.filter(b => b.brand === 'Netscape Navigator').length;
const ddgCount = fvl.filter(b => b.brand === 'DuckDuckGo').length;

results.push({
test: 'fullVersionList-contains-netscape',
result: netscapeCount > 0 ? 'PASS' : 'FAIL',
details: `Found ${netscapeCount} Netscape Navigator brand(s) in fullVersionList`
});

results.push({
test: 'fullVersionList-no-duckduckgo',
result: ddgCount === 0 ? 'PASS' : 'FAIL',
details: `Found ${ddgCount} DuckDuckGo brand(s) in fullVersionList (expected 0)`
});
}
} catch (e) {
results.push({
test: 'fullVersionList-error',
result: 'ERROR',
details: e.message
});
}
}

window.results = results;

const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = '<pre>' + JSON.stringify(results, null, 2) + '</pre>';
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>UA-CH-Brands: Override Edge Disabled Test</title>
</head>
<body>
<h1>UA-CH-Brands Override Edge Disabled Test</h1>
<div id="results"></div>

<script type="module">
const results = [];

if (navigator.userAgentData?.brands) {
const brands = navigator.userAgentData.brands;
const ddgCount = brands.filter(b => b.brand === 'DuckDuckGo').length;

results.push({
test: 'brands-no-duckduckgo',
result: ddgCount === 0 ? 'PASS' : 'FAIL',
details: `Found ${ddgCount} DuckDuckGo brand(s) (expected 0 - overrideEdge disabled)`
});
}

if (navigator.userAgentData?.getHighEntropyValues) {
try {
const highEntropy = await navigator.userAgentData.getHighEntropyValues(['brands']);
if (highEntropy.brands) {
const brands = highEntropy.brands;
const ddgCount = brands.filter(b => b.brand === 'DuckDuckGo').length;

results.push({
test: 'getHighEntropyValues-brands-no-duckduckgo',
result: ddgCount === 0 ? 'PASS' : 'FAIL',
details: `Found ${ddgCount} DuckDuckGo brand(s) in getHighEntropyValues brands (expected 0)`
});
}
} catch (e) {
results.push({
test: 'getHighEntropyValues-brands-error',
result: 'ERROR',
details: e.message
});
}
}

if (navigator.userAgentData?.getHighEntropyValues) {
try {
const highEntropy = await navigator.userAgentData.getHighEntropyValues(['fullVersionList']);
if (highEntropy.fullVersionList) {
const fvl = highEntropy.fullVersionList;
const ddgCount = fvl.filter(b => b.brand === 'DuckDuckGo').length;

results.push({
test: 'fullVersionList-no-duckduckgo',
result: ddgCount === 0 ? 'PASS' : 'FAIL',
details: `Found ${ddgCount} DuckDuckGo brand(s) in fullVersionList (expected 0)`
});
}
} catch (e) {
results.push({
test: 'fullVersionList-error',
result: 'ERROR',
details: e.message
});
}
}

window.results = results;

const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = '<pre>' + JSON.stringify(results, null, 2) + '</pre>';
</script>
</body>
</html>
Loading
Loading