174 lines
5.7 KiB
JavaScript
174 lines
5.7 KiB
JavaScript
// Below lets us print errors, huge thanks to Jonathan @ https://stackoverflow.com/questions/18391212/is-it-not-possible-to-stringify-an-error-using-json-stringify
|
|
if (!("toJSON" in Error.prototype))
|
|
Object.defineProperty(Error.prototype, "toJSON", {
|
|
value: function() {
|
|
const alt = {};
|
|
|
|
Object.getOwnPropertyNames(this).forEach(function(key) {
|
|
alt[key] = this[key];
|
|
}, this);
|
|
|
|
return alt;
|
|
},
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
|
|
|
|
// This object allows other scripts to access the list mapping containers to their proxies
|
|
proxifiedContainers = {
|
|
|
|
// Slightly modified version of 'retrieve' which returns a direct proxy whenever an error is met.
|
|
retrieveFromBackground(cookieStoreId = null) {
|
|
return new Promise((resolve, reject) => {
|
|
proxifiedContainers.retrieve(cookieStoreId).then((success) => {
|
|
resolve(success.proxy);
|
|
}, function() {
|
|
resolve(Utils.DEFAULT_PROXY);
|
|
}).catch((error) => {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
|
|
report_proxy_error(error, identifier = null) {
|
|
// Currently I print to console but this is inefficient
|
|
const relevant_id_str = identifier === null ? "" : ` call supplied with id: ${identifier.toString()}`;
|
|
browser.extension.getBackgroundPage().console.log(`proxifiedContainers error occured ${relevant_id_str}: ${JSON.stringify(error)}`);
|
|
},
|
|
|
|
// Resolves to a proxy object which can be used in the return of the listener required for browser.proxy.onRequest.addListener
|
|
retrieve(cookieStoreId = null) {
|
|
return new Promise((resolve, reject) => {
|
|
browser.storage.local.get("proxifiedContainersKey").then((results) => {
|
|
// Steps to test:
|
|
// 1. Is result empty? If so we must inform the caller to intialize proxifiedContainersStore with some initial info.
|
|
// 2. Is cookieStoreId null? This means the caller probably wants everything currently in the proxifiedContainersStore object store
|
|
// 3. If there doesn't exist an entry for the associated cookieStoreId, inform the caller of this
|
|
// 4. Normal operation - if the cookieStoreId exists in the map, we can simply resolve with the correct proxy value
|
|
|
|
const results_array = results["proxifiedContainersKey"];
|
|
|
|
if (Object.getOwnPropertyNames(results).length === 0) {
|
|
reject({
|
|
error: "uninitialized",
|
|
message: ""
|
|
});
|
|
} else if (cookieStoreId === null) {
|
|
resolve(results_array);
|
|
} else {
|
|
const val = results_array.find(o => o.cookieStoreId === cookieStoreId);
|
|
|
|
if (typeof val !== "object" || val === null) {
|
|
reject({
|
|
error: "doesnotexist",
|
|
message: ""
|
|
});
|
|
} else {
|
|
resolve(val);
|
|
}
|
|
}
|
|
|
|
}, (error) => {
|
|
reject({
|
|
error: "internal",
|
|
message: error
|
|
});
|
|
}).catch((error) => {
|
|
proxifiedContainers.report_proxy_error(error, "proxified-containers.js: error 1");
|
|
});
|
|
});
|
|
},
|
|
set(cookieStoreId, proxy, initialize = false) {
|
|
return new Promise((resolve, reject) => {
|
|
if (initialize === true) {
|
|
const proxifiedContainersStore = [];
|
|
proxifiedContainersStore.push({
|
|
cookieStoreId: cookieStoreId,
|
|
proxy: proxy
|
|
});
|
|
|
|
browser.storage.local.set({
|
|
proxifiedContainersKey: proxifiedContainersStore
|
|
});
|
|
|
|
resolve(proxy);
|
|
}
|
|
|
|
// Assumes proxy is a properly formatted object
|
|
proxifiedContainers.retrieve().then((proxifiedContainersStore) => {
|
|
let index = proxifiedContainersStore.findIndex(i => i.cookieStoreId === cookieStoreId);
|
|
|
|
if (index === -1) {
|
|
proxifiedContainersStore.push({
|
|
cookieStoreId: cookieStoreId,
|
|
proxy: proxy
|
|
});
|
|
index = proxifiedContainersStore.length - 1;
|
|
} else {
|
|
proxifiedContainersStore[index] = {
|
|
cookieStoreId: cookieStoreId,
|
|
proxy: proxy
|
|
};
|
|
}
|
|
|
|
browser.storage.local.set({
|
|
proxifiedContainersKey: proxifiedContainersStore
|
|
});
|
|
|
|
resolve(proxifiedContainersStore[index]);
|
|
}, (errorObj) => {
|
|
reject(errorObj);
|
|
}).catch((error) => {
|
|
throw error;
|
|
});
|
|
});
|
|
},
|
|
|
|
//Parses a proxy description string of the format host[:port] or username:password@host[:port] (port is optional)
|
|
parseProxy(proxy_str) {
|
|
const regexp = /(\b(\w+):(\w+)@)?(((?:\d{1,3}\.){3}\d{1,3}\b)|(\b(\w+)(\.(\w+))+))(:(\d+))?/;
|
|
if (regexp.test(proxy_str) !== true)
|
|
return false;
|
|
|
|
else {
|
|
const matches = regexp.exec(proxy_str);
|
|
|
|
const result = {
|
|
type: "http",
|
|
host: matches[4],
|
|
port: parseInt(matches[11], 10) || 8080,
|
|
username: matches[2] || "",
|
|
password: matches[3] || ""
|
|
};
|
|
|
|
return result;
|
|
}
|
|
},
|
|
|
|
// Deletes the proxy information object for a specified cookieStoreId [useful for cleaning]
|
|
delete(cookieStoreId) {
|
|
return new Promise((resolve, reject) => {
|
|
// Assumes proxy is a properly formatted object
|
|
proxifiedContainers.retrieve().then((proxifiedContainersStore) => {
|
|
const index = proxifiedContainersStore.findIndex(i => i.cookieStoreId === cookieStoreId);
|
|
|
|
if (index === -1) {
|
|
reject({error: "not-found", message: `Container '${cookieStoreId}' not found.`});
|
|
} else {
|
|
proxifiedContainersStore.splice(index, 1);
|
|
}
|
|
|
|
browser.storage.local.set({
|
|
proxifiedContainersKey: proxifiedContainersStore
|
|
});
|
|
|
|
resolve();
|
|
}, (errorObj) => {
|
|
reject(errorObj);
|
|
}).catch((error) => {
|
|
throw error;
|
|
});
|
|
});
|
|
}
|
|
};
|