Add custom user agent option

This commit is contained in:
hensm
2022-08-07 09:32:44 +01:00
parent 3709df869b
commit 4b7c685660
6 changed files with 84 additions and 39 deletions

View File

@@ -346,6 +346,14 @@
"message": "Custom", "message": "Custom",
"description": "Default <option> for knownApps <select>." "description": "Default <option> for knownApps <select>."
}, },
"optionsSiteWhitelistCustomUserAgent": {
"message": "Custom user agent:",
"description": "Custom user agent option label."
},
"optionsSiteWhitelistCustomUserAgentDescription": {
"message": "If specified, a custom user agent string to use for whitelisted sites.",
"description": "Custom user agent option description."
},
"optionsMirroringCategoryName": { "optionsMirroringCategoryName": {
"message": "Screen/tab casting", "message": "Screen/tab casting",

View File

@@ -33,6 +33,8 @@ let platform: string;
let chromeUserAgent: string | undefined; let chromeUserAgent: string | undefined;
let chromeUserAgentHybrid: string | undefined; let chromeUserAgentHybrid: string | undefined;
let customUserAgent: string | undefined;
export async function initWhitelist() { export async function initWhitelist() {
logger.info("init (whitelist)"); logger.info("init (whitelist)");
@@ -42,6 +44,8 @@ export async function initWhitelist() {
chromeUserAgent = getChromeUserAgent(platform); chromeUserAgent = getChromeUserAgent(platform);
chromeUserAgentHybrid = getChromeUserAgent(platform, true); chromeUserAgentHybrid = getChromeUserAgent(platform, true);
customUserAgent = await options.get("siteWhitelistCustomUserAgent");
/** /**
* If a UA string can't be obtained, don't bother continuing * If a UA string can't be obtained, don't bother continuing
* extension initialization * extension initialization
@@ -55,9 +59,13 @@ export async function initWhitelist() {
await registerSiteWhitelist(); await registerSiteWhitelist();
// Re-register when options change // Re-register when options change
options.addEventListener("changed", ev => { options.addEventListener("changed", async ev => {
const alteredOpts = ev.detail; const alteredOpts = ev.detail;
if (alteredOpts.includes("siteWhitelistCustomUserAgent")) {
customUserAgent = await options.get("siteWhitelistCustomUserAgent");
}
if ( if (
alteredOpts.includes("siteWhitelist") || alteredOpts.includes("siteWhitelist") ||
alteredOpts.includes("siteWhitelistEnabled") alteredOpts.includes("siteWhitelistEnabled")
@@ -92,9 +100,10 @@ async function onWhitelistedBeforeSendHeaders(
for (const header of details.requestHeaders) { for (const header of details.requestHeaders) {
if (header.name === "User-Agent") { if (header.name === "User-Agent") {
header.value = header.value =
host?.value === "www.youtube.com" customUserAgent ||
(host?.value === "www.youtube.com"
? chromeUserAgentHybrid ? chromeUserAgentHybrid
: chromeUserAgent; : chromeUserAgent);
break; break;
} }
} }
@@ -126,9 +135,10 @@ function onWhitelistedChildBeforeSendHeaders(
for (const header of details.requestHeaders) { for (const header of details.requestHeaders) {
if (header.name === "User-Agent") { if (header.name === "User-Agent") {
header.value = header.value =
host?.value === "www.youtube.com" customUserAgent ||
(host?.value === "www.youtube.com"
? chromeUserAgentHybrid ? chromeUserAgentHybrid
: chromeUserAgent; : chromeUserAgent);
break; break;
} }
} }

View File

@@ -1,6 +1,27 @@
"use strict"; "use strict";
import { Options } from "./lib/options"; import type { WhitelistItemData } from "./background/whitelist";
export interface Options {
bridgeApplicationName: string;
bridgeBackupEnabled: boolean;
bridgeBackupHost: string;
bridgeBackupPort: number;
mediaEnabled: boolean;
mediaSyncElement: boolean;
mediaStopOnUnload: boolean;
localMediaEnabled: boolean;
localMediaServerPort: number;
mirroringEnabled: boolean;
mirroringAppId: string;
receiverSelectorCloseIfFocusLost: boolean;
receiverSelectorWaitForConnection: boolean;
siteWhitelistEnabled: boolean;
siteWhitelist: WhitelistItemData[];
siteWhitelistCustomUserAgent: string;
[key: string]: Options[keyof Options];
}
export default { export default {
bridgeApplicationName: BRIDGE_NAME, bridgeApplicationName: BRIDGE_NAME,
@@ -17,5 +38,6 @@ export default {
receiverSelectorCloseIfFocusLost: true, receiverSelectorCloseIfFocusLost: true,
receiverSelectorWaitForConnection: true, receiverSelectorWaitForConnection: true,
siteWhitelistEnabled: true, siteWhitelistEnabled: true,
siteWhitelist: [{ pattern: "https://www.netflix.com/*" }] siteWhitelist: [{ pattern: "https://www.netflix.com/*" }],
siteWhitelistCustomUserAgent: ""
} as Options; } as Options;

View File

@@ -1,7 +1,7 @@
"use strict"; "use strict";
import defaultOptions from "../defaultOptions"; import defaultOptions, { Options } from "../defaultOptions";
import type { WhitelistItemData } from "../background/whitelist"; export { Options };
import logger from "./logger"; import logger from "./logger";
@@ -12,26 +12,6 @@ const storageArea = new TypedStorageArea<{
options: Options; options: Options;
}>(browser.storage.sync); }>(browser.storage.sync);
export interface Options {
bridgeApplicationName: string;
bridgeBackupEnabled: boolean;
bridgeBackupHost: string;
bridgeBackupPort: number;
mediaEnabled: boolean;
mediaSyncElement: boolean;
mediaStopOnUnload: boolean;
localMediaEnabled: boolean;
localMediaServerPort: number;
mirroringEnabled: boolean;
mirroringAppId: string;
receiverSelectorCloseIfFocusLost: boolean;
receiverSelectorWaitForConnection: boolean;
siteWhitelistEnabled: boolean;
siteWhitelist: WhitelistItemData[];
[key: string]: Options[keyof Options];
}
interface EventMap { interface EventMap {
changed: Array<keyof Options>; changed: Array<keyof Options>;
} }

View File

@@ -10,14 +10,20 @@
import options, { Options } from "../../lib/options"; import options, { Options } from "../../lib/options";
import defaultOptions from "../../defaultOptions"; import defaultOptions from "../../defaultOptions";
import { getChromeUserAgent } from "../../lib/userAgents";
const _ = browser.i18n.getMessage; const _ = browser.i18n.getMessage;
let formElement: HTMLFormElement; let formElement: HTMLFormElement;
let isFormValid = true; let isFormValid = true;
let showSavedIndicator = false; let showSavedIndicator = false;
let platform: string;
let opts: Options | undefined; let opts: Options | undefined;
onMount(async () => { onMount(async () => {
platform = (await browser.runtime.getPlatformInfo()).os;
opts = await options.getAll(); opts = await options.getAll();
options.addEventListener("changed", async () => { options.addEventListener("changed", async () => {
opts = await options.getAll(); opts = await options.getAll();
@@ -277,6 +283,23 @@
</div> </div>
</div> </div>
<div class="option">
<label class="option__label" for="siteWhitelistCustomUserAgent">
{_("optionsSiteWhitelistCustomUserAgent")}
</label>
<div class="option__control">
<input
type="text"
class="user-agent-string-custom"
bind:value={opts.siteWhitelistCustomUserAgent}
placeholder={getChromeUserAgent(platform)}
/>
<div class="option__description">
{_("optionsSiteWhitelistCustomUserAgentDescription")}
</div>
</div>
</div>
<div class="option"> <div class="option">
<div class="option__label"> <div class="option__label">
{_("optionsSiteWhitelistContent")} {_("optionsSiteWhitelistContent")}

View File

@@ -20,10 +20,15 @@ body {
font-size: 13px; font-size: 13px;
} }
a { color: var(--blue-40); } a {
a:hover { color: var(--blue-50); } color: var(--blue-40);
a:hover:active { color: var(--blue-60); } }
a:hover {
color: var(--blue-50);
}
a:hover:active {
color: var(--blue-60);
}
button.ghost { button.ghost {
width: 24px !important; width: 24px !important;
@@ -38,7 +43,6 @@ button.ghost:not(:hover) {
background-color: initial; background-color: initial;
} }
#form { #form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -209,7 +213,6 @@ button.ghost:not(:hover) {
width: 75px; width: 75px;
} }
.category { .category {
border: initial; border: initial;
display: grid; display: grid;
@@ -228,7 +231,6 @@ button.ghost:not(:hover) {
border-bottom: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color);
} }
.category > hr { .category > hr {
border: initial; border: initial;
border-top: 1px solid var(--border-color); border-top: 1px solid var(--border-color);
@@ -258,7 +260,6 @@ button.ghost:not(:hover) {
grid-column: span 2; grid-column: span 2;
} }
.option { .option {
display: contents; display: contents;
} }
@@ -316,7 +317,6 @@ button.ghost:not(:hover) {
margin-inline-start: initial; margin-inline-start: initial;
} }
.whitelist { .whitelist {
background-color: var(--box-background); background-color: var(--box-background);
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
@@ -389,7 +389,6 @@ button.ghost:not(:hover) {
margin-inline-end: auto; margin-inline-end: auto;
} }
.translator__tag { .translator__tag {
color: #0a84ff; color: #0a84ff;
display: inline-block; display: inline-block;
@@ -400,6 +399,9 @@ button.ghost:not(:hover) {
vertical-align: text-top; vertical-align: text-top;
} }
.user-agent-string-custom {
width: -moz-available;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.whitelist__item:nth-child(even) { .whitelist__item:nth-child(even) {