Skip to content

Commit

Permalink
Fix: Compatibility issues for Firefox (#287)
Browse files Browse the repository at this point in the history
* Fixes Support for Setting Net Rules on Firefox

Firefox has random IDs, so we have to make a dynamic rule instead.

* Add simple permission popup

* Restyle popup

* Make sure to reload extension

* chore: run format

* chore: update Chrome types

* Update button style for disabled state

* Update button text

* Adjust offer tracking banner for Firefox

* chore: run formatting

* Update alert text

Co-authored-by: Step7750 <[email protected]>

* Require optional host permission on Firefox

---------

Co-authored-by: Step7750 <[email protected]>
  • Loading branch information
GODrums and Step7750 authored Feb 14, 2025
1 parent b651874 commit eb36ba4
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 15 deletions.
15 changes: 8 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"homepage": "https://github.com/csfloat/extension#readme",
"devDependencies": {
"@types/chrome": "^0.0.193",
"@types/chrome": "^0.0.300",
"@types/firefox-webext-browser": "^111.0.1",
"@types/jquery": "^3.5.14",
"@types/lodash": "^4.14.195",
Expand Down
39 changes: 38 additions & 1 deletion src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {alarmListener, registerTradeAlarmIfPossible} from './lib/alarms/setup';
import {pingTradeStatus} from './lib/alarms/csfloat_trade_pings';
import {gStore} from './lib/storage/store';
import {StorageKey} from './lib/storage/keys';
import {isFirefox} from './lib/utils/detect';

function unifiedHandler(request: any, sender: MessageSender, sendResponse: (response?: any) => void) {
Handle(request, sender)
Expand All @@ -24,7 +25,7 @@ function unifiedHandler(request: any, sender: MessageSender, sendResponse: (resp
});
}

function requestPermissions(permissions: string[], origins: string[], sendResponse: any) {
function requestPermissions(permissions: chrome.runtime.ManifestPermissions[], origins: string[], sendResponse: any) {
chrome.permissions.request({permissions, origins}, (granted) => sendResponse(granted));

return true;
Expand Down Expand Up @@ -66,3 +67,39 @@ async function checkTradeStatus() {
}
}
checkTradeStatus();

if (isFirefox()) {
// Need to manually update the rule to allow the extension to send trade offers
// Since Firefox IDs are random and we still want to scope it to only this extension
browser.declarativeNetRequest
.updateDynamicRules({
removeRuleIds: [1738196326],
addRules: [
{
id: 1738196326,
priority: 2,
action: {
type: 'modifyHeaders',
requestHeaders: [
{
header: 'referer',
operation: 'set',
value: 'https://steamcommunity.com/tradeoffer/new',
},
],
},
condition: {
urlFilter: 'https://steamcommunity.com/tradeoffer/new/send',
resourceTypes: ['xmlhttprequest'],
initiatorDomains: [new URL(browser.runtime.getURL('')).hostname],
},
},
],
})
.then(() => {
console.log('[INFO] Successfully updated ruleset');
})
.catch((e) => {
console.error('[ERROR] Failed to update ruleset for Firefox');
});
}
7 changes: 3 additions & 4 deletions src/lib/bridge/handlers/has_permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {SimpleHandler} from './main';
import {RequestType} from './types';

export interface HasPermissionsRequest {
permissions: string[];
permissions: chrome.runtime.ManifestPermissions[];
origins: string[];
}

Expand All @@ -13,11 +13,10 @@ export interface HasPermissionsResponse {
export const HasPermissions = new SimpleHandler<HasPermissionsRequest, HasPermissionsResponse>(
RequestType.HAS_PERMISSIONS,
async (req) => {
// @ts-ignore
const granted = (await chrome.permissions.contains({
const granted = await chrome.permissions.contains({
permissions: req.permissions,
origins: req.origins,
})) as boolean;
});

return {
granted,
Expand Down
10 changes: 10 additions & 0 deletions src/lib/components/common/ui/steam-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export class SteamButton extends FloatElement {
@property({type: String})
private type: ButtonType = ButtonType.GreenWhite;

@property({type: Boolean})
private disabled: boolean = false;

static styles = [
...FloatElement.styles,
css`
Expand Down Expand Up @@ -102,6 +105,10 @@ export class SteamButton extends FloatElement {
font-size: 12px;
line-height: 20px;
}
.btn_disabled {
cursor: default;
}
`,
];

Expand All @@ -112,6 +119,9 @@ export class SteamButton extends FloatElement {
btnClass() {
const r: {[key: string]: boolean} = {btn_small: true};
r[`btn_${this.type}_innerfade`] = true;
if (this.disabled) {
r.btn_disabled = true;
}
return classMap(r);
}

Expand Down
19 changes: 18 additions & 1 deletion src/lib/components/trade_offers/better_tracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {state} from 'lit/decorators.js';
import {FetchPendingTrades} from '../../bridge/handlers/fetch_pending_trades';
import {HasPermissions} from '../../bridge/handlers/has_permissions';
import {PingSetupExtension} from '../../bridge/handlers/ping_setup_extension';
import {isFirefox} from '../../utils/detect';

@CustomElement()
@InjectAfter(
Expand All @@ -18,6 +19,9 @@ export class BetterTrackingWidget extends FloatElement {
@state()
show = false;

@state()
isFirefox = isFirefox();

static styles = [
...FloatElement.styles,
css`
Expand Down Expand Up @@ -50,6 +54,14 @@ export class BetterTrackingWidget extends FloatElement {
`,
];

steamButton() {
return {
text: this.isFirefox ? 'Enable in the Extension Popup' : 'Enable',
type: this.isFirefox ? 'grey_white' : 'green_white',
disabled: this.isFirefox,
};
}

async connectedCallback() {
super.connectedCallback();

Expand Down Expand Up @@ -92,7 +104,12 @@ export class BetterTrackingWidget extends FloatElement {
<span class="item-name">Setup Offer Tracking on CSFloat</span>
<div class="sale-info">Verify trades while preserving your privacy.</div>
</div>
<csfloat-steam-button id="csfloat-enable-enhanced" .text="${'Enable'}"></csfloat-steam-button>
<csfloat-steam-button
id="csfloat-enable-enhanced"
.text="${this.steamButton().text}"
.type="${this.steamButton().type}"
.disabled=${this.steamButton().disabled}
></csfloat-steam-button>
</div>
`
: html``;
Expand Down
5 changes: 5 additions & 0 deletions src/lib/page_scripts/trade_offers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {PingSetupExtension} from '../bridge/handlers/ping_setup_extension';
import {PingExtensionStatus} from '../bridge/handlers/ping_extension_status';
import {FetchSteamTrades, FetchSteamTradesResponse} from '../bridge/handlers/fetch_steam_trades';
import {convertSteamID32To64, getUserSteamID} from '../utils/userinfo';
import {isFirefox} from '../utils/detect';

init('src/lib/page_scripts/trade_offers.js', main);

Expand Down Expand Up @@ -112,6 +113,10 @@ if (!inPageContext()) {
}

btn.addEventListener('click', async () => {
if (isFirefox()) {
alert('Please enable the feature in the extension popup in the top right of your browser');
return;
}
chrome.runtime.sendMessage(
{
message: 'requestPermissions',
Expand Down
66 changes: 66 additions & 0 deletions src/popup/popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"
rel="stylesheet"
/>
<style>
body {
width: 300px;
padding: 16px;
background-color: #15171c;
}
button {
width: 100%;
padding: 10px;
background-color: rgba(35, 123, 255, 0.15);
color: #237bff;
border: none;
border-radius: 8px;
cursor: pointer;
font-family: 'Roboto', serif;
font-size: 14px;
font-weight: 500;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
button:hover {
background-color: #2a374d;
}
button:disabled {
cursor: not-allowed;
background-color: rgba(255, 255, 255, .12);
color: rgba(255, 255, 255, .5);
}
</style>
</head>
<body>
<button id="requestPermissions">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"
/>
<path d="M12 8v4" />
<path d="M12 16h.01" />
</svg>
<span>Enable Offer Tracking</span>
</button>
<script src="popup/popup.js"></script>
</body>
</html>
30 changes: 30 additions & 0 deletions src/popup/popup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
window.addEventListener('DOMContentLoaded', async () => {
const requestButton = document.getElementById('requestPermissions');
if (!requestButton) {
return;
}

const hasPermissions = await chrome.permissions.contains({
origins: ['*://*.steampowered.com/*'],
});

if (hasPermissions) {
// If permissions are already granted, disable the button
requestButton.children[1].textContent = 'Offer Tracking Enabled';
requestButton.setAttribute('disabled', 'true');
} else {
requestButton.addEventListener('click', async () => {
try {
const success = await chrome.permissions.request({
origins: ['*://*.steampowered.com/*'],
});
if (success) {
// extension requires reload to apply permissions
browser.runtime.reload();
}
} catch (error) {
console.error('Error requesting permissions:', error);
}
});
}
});
9 changes: 8 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ function getPathEntries(path) {

function convertToFirefoxManifest(manifest) {
const cp = Object.assign({}, manifest);
cp.action = {
default_popup: "src/popup.html"
}
cp.background = {
page: 'src/background_ff.html',
};
cp.browser_specific_settings = {
gecko: {
id: '{194d0dc6-7ada-41c6-88b8-95d7636fe43c}',
strict_min_version: '109.0',
strict_min_version: '127.0',
},
};
// Allow getting the extension version from CSFloat page in Firefox
Expand All @@ -36,6 +39,8 @@ function convertToFirefoxManifest(manifest) {
js: ['src/lib/page_scripts/csfloat.js'],
});
cp.host_permissions.push('*://*.csfloat.com/*');
// Force optional host permissions to be required
cp.host_permissions = cp.host_permissions.concat(cp.optional_host_permissions);
return cp;
}

Expand All @@ -48,6 +53,7 @@ module.exports = (env) => {
getPathEntries('./src/lib/page_scripts/*.ts'),
getPathEntries('./src/lib/types/*.d.ts'),
getPathEntries('./src/background.ts'),
getPathEntries('./src/popup/popup.ts'),
getPathEntries('./src/**/*.js')
),
output: {
Expand Down Expand Up @@ -97,6 +103,7 @@ module.exports = (env) => {
{from: 'src/steamcommunity_ruleset.json', to: 'src/', context: '.'},
{from: 'src', to: 'raw/', context: '.'},
{from: 'README.md', to: '', context: '.'},
{from: 'src/popup/popup.html', to: 'src/', context: '.'},
{
from: 'manifest.json',
to: 'manifest.json',
Expand Down

0 comments on commit eb36ba4

Please sign in to comment.