Implement user agent switching + whitelist

This commit is contained in:
hensm
2018-10-21 06:14:28 +01:00
parent 30dd357e46
commit e5686c2017
3 changed files with 110 additions and 2 deletions

View File

@@ -29,6 +29,20 @@
, "options_option_localMediaServerPort": {
"message": "HTTP server port"
}
, "options_category_uaWhitelist": {
"message": "User agent whitelist"
}
, "options_category_uaWhitelist_description": {
"message": "Sites for which to replace the user agent with a Chrome version for compatibility."
}
, "options_option_uaWhitelistEnabled": {
"message": "Enabled"
}
, "options_option_uaWhitelist": {
"message": "Site list (newline-separated)"
}
, "options_submit": {
"message": "Submit"
}

View File

@@ -9,6 +9,8 @@ browser.runtime.onInstalled.addListener(async details => {
const initialOptions = {
option_localMediaEnabled: true
, option_localMediaServerPort: 9555
, option_uaWhitelistEnabled: true
, option_uaWhitelist: [ "www.netflix.com" ].join("\n")
};
switch (details.reason) {
@@ -89,6 +91,67 @@ browser.webRequest.onBeforeRequest.addListener(
]}
, [ "blocking" ]);
/**
* Returns a Chrome user agent string with the provided platform.
*/
function getChromeUA (platform) {
return `Mozilla/5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36`;
}
// Desktop platform Chrome UA strings
const UA_STRINGS = {
"mac" : getChromeUA("Macintosh; Intel Mac OS X 10_14_1")
, "win" : getChromeUA("Windows NT 10.0; Win64; x64")
, "linux" : getChromeUA("Mozilla/5.0 (X11; Linux x86_64")
};
// Current user agent string for all whitelisted requests
let currentUAString;
/**
* Web apps usually only load the sender library and
* provide cast functionality if the browser is detected
* as Chrome, so we should rewrite the User-Agent header
* to reflect this on whitelisted sites.
*
* TODO: Inject script to change navigator.userAgent
* property.
*/
browser.webRequest.onBeforeSendHeaders.addListener(
async details => {
const { options } = await browser.storage.sync.get("options");
// Cancel if feature is disabled
if (!options.option_uaWhitelistEnabled) return;
// Cancel if not on whitelist
// TODO: Do this with the built in filter
const { hostname } = new URL(details.url);
if (!options.option_uaWhitelist.split("\n").includes(hostname)) return;
// Create Chrome UA from platform info on first run
if (!currentUAString) {
currentUAString = UA_STRINGS[
(await browser.runtime.getPlatformInfo()).os]
}
// Find and rewrite the User-Agent header
for (const header of details.requestHeaders) {
if (header.name.toLowerCase() === "user-agent") {
header.value = currentUAString;
break;
}
}
return {
requestHeaders: details.requestHeaders
};
}
, { urls: [ "<all_urls>" ]}
, [ "blocking", "requestHeaders" ]);
// Defines window.chrome for site compatibility
browser.contentScripts.register({
allFrames: true

View File

@@ -28,6 +28,8 @@ class OptionsApp extends Component {
options: {
option_localMediaEnabled: this.state.option_localMediaEnabled
, option_localMediaServerPort: this.state.option_localMediaServerPort
, option_uaWhitelistEnabled: this.state.option_uaWhitelistEnabled
, option_uaWhitelist: this.state.option_uaWhitelist
}
});
}
@@ -37,6 +39,7 @@ class OptionsApp extends Component {
*/
async componentDidMount () {
const { options } = await browser.storage.sync.get("options");
if (options) {
this.setState({
...options
@@ -80,8 +83,6 @@ class OptionsApp extends Component {
}
};
console.log(ev.target.name);
this.setState({
[ ev.target.name ]: val
});
@@ -124,6 +125,36 @@ class OptionsApp extends Component {
</label>
</fieldset>
<fieldset className="category">
<legend className="category-name">
{ _("options_category_uaWhitelist") }
</legend>
<p className="category-description">
{ _("options_category_uaWhitelist_description") }
</p>
<label className="option">
<div className="option-label">
{ _("options_option_uaWhitelistEnabled") }
</div>
<input name="option_uaWhitelistEnabled"
type="checkbox"
checked={ this.state.option_uaWhitelistEnabled }
onChange={ this.handleInputChange } />
</label>
<label className="option">
<div className="option-label">
{ _("options_option_uaWhitelist") }
</div>
<textarea name="option_uaWhitelist"
value={this.state.option_uaWhitelist}
required
onChange={ this.handleInputChange }>
</textarea>
</label>
</fieldset>
<div id="buttons">
<button type="submit"
disabled={ !this.state.isFormValid }>