Skip to content

Commit

Permalink
Update extension to actually work
Browse files Browse the repository at this point in the history
Instead of the extension injecting into Bungie.net and monkey patching fetch, the background script will now redirect /Settings/ requests to another server that provides the fake response
  • Loading branch information
joshhunt committed Feb 24, 2022
1 parent 8ed62ea commit 1ac59c2
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 81 deletions.
4 changes: 3 additions & 1 deletion README.md
Expand Up @@ -61,6 +61,8 @@ Season Pass Pass has been built with **Node 16.13.2** and **Yarn 1.22.15**. The

## Permissions

This browser extension requires permission to view and modify all data on bungie.net. It only uses these permissions to do the bare minumum functionality that's expected of this extension. This extension uses no analytics, tracking, reporting or telemetry. No data leaves this extension.
This browser extension requires permission to view and modify all data on bungie.net. It only uses these permissions to do the bare minumum functionality that's expected of this extension. This extension uses no analytics, tracking, reporting or telemetry.

In order to change the "Previous Season", this extension redirects the Bungie API settings request to another service which provides a "modified" settings response with the new previous season. No personal information is sent with this request, and nothing is tracked or stored.

Because Bungie.net login happens on the Playstation/Xbox/Steam/etc websites, and this extension [requests permisision to _bungie.net only_](https://github.com/joshhunt/season-pass-extension/blob/v1.0.0/public/manifest.json#L34), **this extension _does not_ have the ability to see your passwords for those sites.**
3 changes: 1 addition & 2 deletions package.json
Expand Up @@ -8,9 +8,8 @@
"scripts": {
"dev": "node manifestIcons.js && webpack --mode=development --watch",
"build": "rimraf dist && node manifestIcons.js && webpack --mode=production",
"zip": "rimraf artifacts/* && cd dist; bestzip ../artifacts/chrome.zip *",
"package": "web-ext build",
"deploy": "yarn build && yarn zip"
"deploy": "yarn build && yarn package"
},
"dependencies": {
"@babel/core": "^7.16.12",
Expand Down
12 changes: 1 addition & 11 deletions public/manifest.json
@@ -1,23 +1,13 @@
{
"name": "Season Pass Pass",
"description": "Travel back in time and pull rewards from any previous season pass",
"version": "1.0.0",
"version": "1.0.1",
"manifest_version": 2,
"background": {
"scripts": [
"background.bundle.js"
]
},
"content_scripts": [
{
"matches": [
"*://*.bungie.net/*"
],
"js": [
"contentScript.bundle.js"
]
}
],
"icons": {
"16": "icons/icon_16.png",
"32": "icons/icon_32.png",
Expand Down
189 changes: 127 additions & 62 deletions src/background.ts
Expand Up @@ -6,18 +6,72 @@ import { changesToValues, hasTimedout } from "./utils";

import debug from "debug";

localStorage.debug = "background";
localStorage.debug = "*";
debug.enabled("*");

const log = debug("background");

let seasonOverride = -1;
let bungieApiKey: string | undefined = undefined;
let lastChangedDate = 0;

const allBgImages = SEASONS.map(
(v) => `https://www.bungie.net${v.progressPageImage}`
);

browser.storage.onChanged.addListener((changes, area) => {
log("storage.onChanged emitted", changes);
const values = changesToValues(changes);
unpackStorageValues(values);
});

browser.storage.local.get().then((values) => {
log("storage.local.get", values);
unpackStorageValues(values);
});

browser.webRequest.onSendHeaders.addListener(
interceptPlatformHeaders,
{
urls: ["https://www.bungie.net/Platform/*"],
},
["requestHeaders"]
);

browser.webRequest.onBeforeRequest.addListener(
interceptBackgroundImages,
{ urls: allBgImages },
["blocking"]
);

function chromeOnlySettingsIntercept() {
log("Registering chrome-only onBeforeRequest");
browser.webRequest.onBeforeRequest.addListener(
chromeInterceptSettingsRequest,
{ urls: ["https://www.bungie.net/Platform/Settings*"] },
["blocking"]
);
}

chromeOnlySettingsIntercept();

// if (browser.runtime.getBrowserInfo) {
// browser.runtime.getBrowserInfo().then((browserInfo) => {
// if (browserInfo.name.toLowerCase() !== "firefox") {
// chromeOnlySettingsIntercept();
// }
// });
// } else {
// // If we don't have getBrowserInfo, we're probably in Chrome
// chromeOnlySettingsIntercept();
// }

const wait = (timeout: number) =>
new Promise((resolve) => setTimeout(resolve, timeout));

function unpackStorageValues(values: Record<string, any>) {
console.group("Synced storage values to local variables");
console.groupCollapsed("Synced storage values to local variables");
log("Values:", values);
log("from:", new Error().stack);

if ("lastChangedDate" in values && hasTimedout(values.lastChangedDate)) {
log("Last change was too long ago, clearing all storage");
Expand All @@ -44,87 +98,98 @@ function unpackStorageValues(values: Record<string, any>) {
console.groupEnd();
}

browser.storage.onChanged.addListener((changes, area) => {
log("storage.onChanged emitted", changes);
const values = changesToValues(changes);
unpackStorageValues(values);
});

browser.storage.local.get().then((values) => {
log("storage.local.get", values);
unpackStorageValues(values);
});

async function handleSendHeaders(
/**
* Intercepts Bungie.net API header requests to obtain the API key
*/
async function interceptPlatformHeaders(
request: browser.WebRequest.OnSendHeadersDetailsType
) {
const apiKeyHeader = request.requestHeaders?.find(
(v) => v.name.toLowerCase() === "x-api-key"
);
if (!apiKeyHeader?.value) return;
if (request.url.includes("?seasonPassPass")) return;

const path = new URL(request.url).pathname;
log("Grabbed API key from Bungie request", path);
await browser.storage.local.set({ bungieApiKey: apiKeyHeader.value });
}

const allBgImages = SEASONS.map(
(v) => `https://www.bungie.net${v.progressPageImage}`
);
/**
* Intercepts requests for season background images to return the background image for the overridden season
*/
function interceptBackgroundImages(
request: browser.WebRequest.OnSendHeadersDetailsType
): { redirectUrl: string } | undefined {
if (hasTimedout(lastChangedDate)) {
return undefined;
}

const requestFilter = {
urls: ["https://www.bungie.net/Platform/*"],
};
const requestedImagePathname = new URL(request.url).pathname;
console.groupCollapsed("Request for", requestedImagePathname);

browser.webRequest.onSendHeaders.addListener(handleSendHeaders, requestFilter, [
"requestHeaders",
]);
log("seasonOverride", seasonOverride);

browser.webRequest.onBeforeRequest.addListener(
(req) => {
if (hasTimedout(lastChangedDate)) {
return undefined;
}
const seasonForOverride = SEASONS.find((v) => v.hash === seasonOverride);
log("seasonForOverride", seasonForOverride);

const requestedImagePathname = new URL(req.url).pathname;
console.group("Request for", requestedImagePathname);
if (!seasonForOverride) {
log("Could not find season data for the override");
console.groupEnd();
return undefined;
}

log("seasonOverride", seasonOverride);
if (seasonForOverride.progressPageImage === requestedImagePathname) {
log("Correct image anyway");
console.groupEnd();
return undefined;
}

const seasonForOverride = SEASONS.find((v) => v.hash === seasonOverride);
log("seasonForOverride", seasonForOverride);
const requestedSeason = SEASONS.find(
(v) => v.progressPageImage === requestedImagePathname
);

if (!seasonForOverride) {
log("Could not find season data for the override");
console.groupEnd();
return undefined;
}
log("The season the browser requested is", requestedSeason);

if (seasonForOverride.progressPageImage === requestedImagePathname) {
log("Correct image anyway");
console.groupEnd();
return undefined;
}
if (requestedSeason && requestedSeason.endDate.getTime() < Date.now()) {
const redirectUrl = `https://www.bungie.net${seasonForOverride.progressPageImage}`;
log("Redirecting", request.url, "to", redirectUrl);

const requestedSeason = SEASONS.find(
(v) => v.progressPageImage === requestedImagePathname
);
console.groupEnd();
return {
redirectUrl,
};
}

log("The season the browser requested is", requestedSeason);
console.groupEnd();
return undefined;
}

if (requestedSeason && requestedSeason.endDate.getTime() < Date.now()) {
const redirectUrl = `https://www.bungie.net${seasonForOverride.progressPageImage}`;
log("Redirecting", req.url, "to", redirectUrl);
/**
* Intercepts requests for the Settings endpoint and potentially provides a modified response
*/
function chromeInterceptSettingsRequest(
request: browser.WebRequest.OnBeforeSendHeadersDetailsType
) {
const logIntercept = debug("background:intercept:" + request.requestId);
logIntercept("Intercepted settings request", request.url);

console.groupEnd();
return {
redirectUrl,
};
}
if (request.url.includes("?seasonPassPass")) {
logIntercept("Intercepted our own request. Stopping.");
return;
}

console.groupEnd();
return undefined;
},
{ urls: allBgImages },
["blocking"]
);
if (hasTimedout(lastChangedDate)) {
logIntercept("Has timed out. Stopping.");
return;
}

if (!seasonOverride) {
logIntercept("Don't have a season override. Stopping.");
return;
}

return {
redirectUrl: `https://destiny-activities.destinyreport.workers.dev/seasonPassPass?season=${seasonOverride}`,
};
}
7 changes: 4 additions & 3 deletions src/contentScript.ts
Expand Up @@ -17,16 +17,17 @@ function injectScript(scriptName: string) {
}

async function main() {
console.log("🎫 Season Pass Pass content script");
await injectScript("injected.bundle.js");
await waitForMessage("SEASON_PASS_INJECTED_LOADED");

const values = await browser.storage.local.get();

if (hasTimedout(values.lastChangedDate)) {
console.log("content script giving up");
return;
}

await injectScript("injected.bundle.js");
await waitForMessage("SEASON_PASS_INJECTED_LOADED");

console.log("[CONTENT] Extension storage:", values);

sendMessage("SEASON_PASS_LOCAL_STORAGE", values);
Expand Down
5 changes: 3 additions & 2 deletions src/injected.ts
Expand Up @@ -20,9 +20,10 @@ async function main() {
return;
}

console.log("[INJECTED] fetchIntercept.register");
fetchIntercept.register({
request(url, config) {
return [url, config];
request(request, config) {
return [request, config];
},

requestError(error) {
Expand Down

0 comments on commit 1ac59c2

Please sign in to comment.