- warning!! are you sure you want this extension to do what it says it does? here at fastforward we care about your privacy and want to make sure you don't accidentally use this extension because that could be disastrous. are you sure you want this button that you don't have to press to function when you press it?
-
-
- this message was brought to you because of mozilla"
-
-
-
-
-
-
You have declined consent. This extension cannot work.
-
-
-
-
-
-
+
+ FastForward
+
+
+
+
+
+
+
+
+
+
+
Thank you for installing FastForward
+
+ This extension collects the tab url when you choose to add a website to the whitelist.
+
+
+ If you consent to this data collection hit "Agree" to continue. Otherwise hit "Refuse" and the extension will be uninstalled.
+
+
+
+
+
+
diff --git a/src/html/consent.js b/src/html/consent.js
index 8851108c9..2d284ce8d 100644
--- a/src/html/consent.js
+++ b/src/html/consent.js
@@ -1,28 +1,26 @@
-// Check if the user has already given or declined consent
-const consentStatus = localStorage.getItem('consentStatus');
+// Function to save consent status
+async function saveConsentStatus(consentStatus) {
+ return browser.storage.local.set({ consentStatus: consentStatus });
+}
-// Handle the "I Agree" button click event
-document.getElementById("consentButton").addEventListener("click", function () {
- // Save consent in localStorage
- localStorage.setItem('consentStatus', 'granted');
+// Function to get consent status
+async function getConsentStatus() {
+ return new Promise((resolve) => {
+ browser.storage.local.get('consentStatus').then((result) => {
+ resolve(result.consentStatus);
+ });
+ });
+}
- // You can add additional logic here, such as performing actions that require consent.
-
- // Example: Redirect to another page after consent
+// Event listener for "Agree" button
+document.querySelector('#agree').addEventListener('click', async function () {
+ console.log("Agree button clicked.");
+ await saveConsentStatus('consent-granted');
window.location.href = 'options.html';
});
-document.getElementById("declineButton").addEventListener("click", function () {
- // Save decline status in localStorage
- localStorage.setItem('consentStatus', 'declined');
- console.log("Decline button clicked");
-
- // Show the popup
- document.getElementById("popup").style.display = "block";
-});
-
-// Handle the "Uninstall" button click event within the popup
-document.getElementById("uninstallPopupButton").addEventListener("click", function () {
- // Uninstall the extension
+// Event listener for "Refuse" button
+document.querySelector('#refuse').addEventListener('click', async function () {
+ console.log("Uninstalling extension.");
browser.management.uninstallSelf();
-});
+});
\ No newline at end of file
diff --git a/src/js/background.js b/src/js/background.js
index b5af38feb..24db0b9a6 100644
--- a/src/js/background.js
+++ b/src/js/background.js
@@ -1,172 +1,193 @@
-import * as constants from './constants.js';
-const brws = typeof browser !== 'undefined' ? browser : chrome;
-const fetchDomains = ['crowd.fastforward.team', 'redirect-api.work.ink']; //only allow requests to these domains
-
-async function getOptions() {
- return new Promise((resolve) => {
- brws.storage.local.get('options').then((result) => {
- resolve(result.options);
- });
- });
-}
+const isFirefox = /Firefox/i.test(navigator.userAgent);
-function ffclipboardClear() {
- brws.storage.local.set({ ff_clipboard: '{}' });
+// Check if the browser is Firefox
+if (isFirefox) {
+ browser.runtime.onInstalled.addListener((details) => {
+ if (details.reason === "install") {
+ browser.storage.local.get('consentStatus').then(function (data) {
+ const consentStatus = data.consentStatus;
+ if (consentStatus !== 'granted') {
+ browser.tabs.create({
+ url: "html/consent.html"
+ });
+ } else {
+ executeBackgroundScript();
+ }
+ });
+ }
+ });
+} else {
+ // For non-Firefox browsers, execute background script
+ executeBackgroundScript();
}
-function clearCrowdIgnoredURLs() {
- brws.storage.local.set({ crowd_ignore: '{}' });
-}
+function executeBackgroundScript() {
+ const brws = typeof browser !== 'undefined' ? browser : chrome;
+ const fetchDomains = ['crowd.fastforward.team', 'redirect-api.work.ink']; //only allow requests to these domains
-function firstrun(details) {
- if (details.reason == 'install' || details.reason == 'update') {
- brws.tabs.create({ url: 'https://fastforward.team/firstrun' });
- ffclipboardClear();
- brws.storage.local.set({ tempDisableCrowd: 'false' });
- brws.storage.local.set({ version: brws.runtime.getManifest().version });
- brws.runtime.openOptionsPage(); //required for loading default options, to do: implement a better way
- brws.declarativeNetRequest.updateDynamicRules({
- addRules: constants.beforeNavigateRules,
- removeRuleIds: constants.beforeNavigateRules.map((rule) => rule.id),
+ async function getOptions() {
+ return new Promise((resolve) => {
+ brws.storage.local.get('options').then((result) => {
+ resolve(result.options);
+ });
});
}
-}
-function preflight(details) {
- let url = new URL(details.url);
- if (url.hostname !== 'fastforward.team') {
- return;
+ function ffclipboardClear() {
+ brws.storage.local.set({ ff_clipboard: '{}' });
}
- //navigate
- if (url.pathname === '/bypassed') {
- let ext_url = new URL(brws.runtime.getURL(''));
- url.hostname = ext_url.hostname;
- url.protocol = ext_url.protocol;
- url.pathname = '/html' + url.pathname;
- if (url.searchParams.get('crowd') === 'true') {
- url.pathname =
- url.pathname.split('/').slice(0, -1).join('/') + '/crowd-bypassed.html';
- } else {
- url.pathname =
- url.pathname.split('/').slice(0, -1).join('/') +
- '/before-navigate.html';
- }
- brws.tabs.update(details.tabId, {
- url: url.href,
- });
+ function clearCrowdIgnoredURLs() {
+ brws.storage.local.set({ crowd_ignore: '{}' });
}
-}
-// If user restarts the browser before the is alarm triggered
-function reEnableCrowdBypassStartup() {
- brws.storage.local.get(['tempDisableCrowd']).then((result) => {
- if (result.tempDisableCrowd === 'true') {
- brws.storage.local.get(['options']).then((result) => {
- let opt = result.options;
- opt.optionCrowdBypass = true;
- brws.storage.local.set({ options: opt });
+ function firstrun(details) {
+ if (details.reason == 'install' || details.reason == 'update') {
+ brws.tabs.create({ url: 'https://fastforward.team/firstrun' });
+ ffclipboardClear();
+ brws.storage.local.set({ tempDisableCrowd: 'false' });
+ brws.storage.local.set({ version: brws.runtime.getManifest().version });
+ brws.runtime.openOptionsPage(); //required for loading default options, to do: implement a better way
+ brws.declarativeNetRequest.updateDynamicRules({
+ addRules: constants.beforeNavigateRules,
+ removeRuleIds: constants.beforeNavigateRules.map((rule) => rule.id),
});
}
- brws.storage.local.set({ tempDisableCrowd: 'false' });
- });
-}
+ }
+
+ function preflight(details) {
+ let url = new URL(details.url);
+ if (url.hostname !== 'fastforward.team') {
+ return;
+ }
+ //navigate
+ if (url.pathname === '/bypassed') {
+ let ext_url = new URL(brws.runtime.getURL(''));
+ url.hostname = ext_url.hostname;
+ url.protocol = ext_url.protocol;
+ url.pathname = '/html' + url.pathname;
+ if (url.searchParams.get('crowd') === 'true') {
+ url.pathname =
+ url.pathname.split('/').slice(0, -1).join('/') + '/crowd-bypassed.html';
+ } else {
+ url.pathname =
+ url.pathname.split('/').slice(0, -1).join('/') +
+ '/before-navigate.html';
+ }
-// Add a listener for the temp crowd disable alarm
-brws.alarms.onAlarm.addListener((alarm) => {
- brws.storage.local.get(['tempDisableCrowd']).then((result) => {
- if (
- alarm.name === 'enableCrowdBypass' &&
- result.tempDisableCrowd === 'true'
- ) {
- brws.storage.local.get(['options']).then((result) => {
- let opt = result.options;
- opt.optionCrowdBypass = true;
- brws.storage.local.set({ options: opt });
- brws.storage.local.set({ tempDisableCrowd: 'false' });
+ brws.tabs.update(details.tabId, {
+ url: url.href,
});
}
+ }
+
+ function reEnableCrowdBypassStartup() {
+ brws.storage.local.get(['tempDisableCrowd']).then((result) => {
+ if (result.tempDisableCrowd === 'true') {
+ brws.storage.local.get(['options']).then((result) => {
+ let opt = result.options;
+ opt.optionCrowdBypass = true;
+ brws.storage.local.set({ options: opt });
+ });
+ }
+ brws.storage.local.set({ tempDisableCrowd: 'false' });
+ });
+ }
+
+ brws.alarms.onAlarm.addListener((alarm) => {
+ brws.storage.local.get(['tempDisableCrowd']).then((result) => {
+ if (
+ alarm.name === 'enableCrowdBypass' &&
+ result.tempDisableCrowd === 'true'
+ ) {
+ brws.storage.local.get(['options']).then((result) => {
+ let opt = result.options;
+ opt.optionCrowdBypass = true;
+ brws.storage.local.set({ options: opt });
+ brws.storage.local.set({ tempDisableCrowd: 'false' });
+ });
+ }
+ });
});
-});
-
-brws.runtime.onInstalled.addListener(firstrun);
-brws.runtime.onStartup.addListener(() => {
- ffclipboardClear();
- clearCrowdIgnoredURLs();
- reEnableCrowdBypassStartup();
- brws.storage.local.set({ version: brws.runtime.getManifest().version });
-});
-
-brws.runtime.onMessage.addListener((request, _, sendResponse) => {
- (async () => {
- let options = await getOptions();
- if (options.optionCrowdBypass === false) {
- return;
- }
- let url;
- request.type === 'crowdQuery'
- ? (url = 'https://crowd.fastforward.team/crowd/query_v1')
- : (url = 'https://crowd.fastforward.team/crowd/contribute_v1');
- let params = new URLSearchParams();
+ brws.runtime.onInstalled.addListener(firstrun);
+ brws.runtime.onStartup.addListener(() => {
+ ffclipboardClear();
+ clearCrowdIgnoredURLs();
+ reEnableCrowdBypassStartup();
+ brws.storage.local.set({ version: brws.runtime.getManifest().version });
+ });
- if (request.type !== 'followAndContribute') {
- for (let key in request.detail) {
- params.append(key, request.detail[key]);
+ brws.runtime.onMessage.addListener((request, _, sendResponse) => {
+ (async () => {
+ let options = await getOptions();
+ if (options.optionCrowdBypass === false) {
+ return;
}
- } else {
- //use fetch api to get final url after redirects from detail.target
- for (let key in request.detail) {
- if (key === 'target') {
- let dest = new URL(request.detail[key]);
- if (!fetchDomains.includes(dest.hostname)) {
- return;
- }
- let res = await fetch(dest.href, {
- method: 'GET',
- redirect: 'follow',
- });
- params.append(key, res.url);
- } else {
+ let url;
+ request.type === 'crowdQuery'
+ ? (url = 'https://crowd.fastforward.team/crowd/query_v1')
+ : (url = 'https://crowd.fastforward.team/crowd/contribute_v1');
+
+ let params = new URLSearchParams();
+
+ if (request.type !== 'followAndContribute') {
+ for (let key in request.detail) {
params.append(key, request.detail[key]);
}
+ } else {
+ for (let key in request.detail) {
+ if (key === 'target') {
+ let dest = new URL(request.detail[key]);
+ if (!fetchDomains.includes(dest.hostname)) {
+ return;
+ }
+ let res = await fetch(dest.href, {
+ method: 'GET',
+ redirect: 'follow',
+ });
+ params.append(key, res.url);
+ } else {
+ params.append(key, request.detail[key]);
+ }
+ }
}
- }
- let response = await fetch(url, {
- method: 'POST',
- body: params.toString(),
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- },
- });
- if (request.type === 'crowdQuery')
- response.text().then((res) => {
- sendResponse(res);
- });
- })();
- return true;
-});
-
-brws.storage.onChanged.addListener(() => {
- getOptions().then((options) => {
- if (options.optionBlockIpLoggers === false) {
- brws.declarativeNetRequest.updateEnabledRulesets({
- disableRulesetIds: ['ipLoggerRuleset'],
- });
- } else {
- brws.declarativeNetRequest.updateEnabledRulesets({
- enableRulesetIds: ['ipLoggerRuleset'],
- });
- }
- if (options.optionTrackerBypass === false) {
- brws.declarativeNetRequest.updateEnabledRulesets({
- disableRulesetIds: ['trackerRuleset'],
+ let response = await fetch(url, {
+ method: 'POST',
+ body: params.toString(),
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
});
- } else {
- brws.declarativeNetRequest.updateEnabledRulesets({
- enableRulesetIds: ['trackerRuleset'],
- });
- }
+ if (request.type === 'crowdQuery')
+ response.text().then((res) => {
+ sendResponse(res);
+ });
+ })();
+ return true;
+ });
+
+ brws.storage.onChanged.addListener(() => {
+ getOptions().then((options) => {
+ if (options.optionBlockIpLoggers === false) {
+ brws.declarativeNetRequest.updateEnabledRulesets({
+ disableRulesetIds: ['ipLoggerRuleset'],
+ });
+ } else {
+ brws.declarativeNetRequest.updateEnabledRulesets({
+ enableRulesetIds: ['ipLoggerRuleset'],
+ });
+ }
+ if (options.optionTrackerBypass === false) {
+ brws.declarativeNetRequest.updateEnabledRulesets({
+ disableRulesetIds: ['trackerRuleset'],
+ });
+ } else {
+ brws.declarativeNetRequest.updateEnabledRulesets({
+ enableRulesetIds: ['trackerRuleset'],
+ });
+ }
+ });
});
-});
+}
\ No newline at end of file