From 1dd48e434439ae5e4db97ef49b6b91f4fa17dec8 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 04:13:12 -0500
Subject: [PATCH 01/37] Try some android stuff
---
Makefile | 7 +--
background.js | 123 +++++++++++++++++++++++++++++------------------
context.js | 17 +++----
debian/changelog | 6 +++
handler.js | 6 +--
info.js | 4 +-
manifest.json | 2 +-
scrub.js | 15 ++++--
8 files changed, 112 insertions(+), 68 deletions(-)
diff --git a/Makefile b/Makefile
index 3150e13..3ce0e52 100644
--- a/Makefile
+++ b/Makefile
@@ -36,8 +36,8 @@ clean:
## EVEN RELEASES are AMO RELEASES
## ODD RELEASES are SELFHOSTED RELEASES
-MOZ_VERSION=0.46
-VERSION=0.47
+MOZ_VERSION=0.48
+VERSION=0.49
#VERSION=$(MOZ_VERSION)
#VERSION=1.27
@@ -112,7 +112,8 @@ moz-sign: version
@echo "Using the 'sign' target to instantly sign an extension for self-distribution"
@echo "requires a JWT API Key and Secret from addons.mozilla.org to be made available"
@echo "to the Makefile under the variables WEB_EXT_API_KEY and WEB_EXT_API_SECRET."
- web-ext sign --channel unlisted --config-discovery false --api-key $(WEB_EXT_API_KEY) --api-secret $(WEB_EXT_API_SECRET); true
+ web-ext-submit --channel unlisted --config-discovery false --api-key $(WEB_EXT_API_KEY) --api-secret $(WEB_EXT_API_SECRET); true
+ cp web-ext-artifacts/*.xpi ./i2ppb@eyedeekay.github.io.xpi
##EVEN NUMBERED, MOZILLA-DISTRIBUTED VERSIONS HERE!
moz-submit: moz-version
diff --git a/background.js b/background.js
index 230db28..bee4126 100644
--- a/background.js
+++ b/background.js
@@ -84,19 +84,32 @@ function onError(e) {
browser.contextualIdentities.query({}).then(onGot, onError);
-if (!isDroid()) {
- chrome.windows.onCreated.addListener(themeWindow);
- chrome.windows.onFocusChanged.addListener(themeWindow);
- chrome.windows.onRemoved.addListener(themeWindow);
- chrome.tabs.onUpdated.addListener(themeWindowByTab);
- chrome.tabs.onActivated.addListener(themeWindowByTab);
-} else {
-}
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os == "android") {
+ console.log("Running in Android detected");
+ return true;
+ } else {
+ browser.windows.onCreated.addListener(themeWindow);
+ browser.windows.onFocusChanged.addListener(themeWindow);
+ browser.windows.onRemoved.addListener(themeWindow);
+ browser.tabs.onUpdated.addListener(themeWindowByTab);
+ browser.tabs.onActivated.addListener(themeWindowByTab);
+ }
+});
function themeWindowByTab(tabId) {
function tabWindow(tab) {
- getwindow = browser.windows.get(tab.windowId);
- getwindow.then(themeWindow);
+ var gettingInfo = browser.runtime.getPlatformInfo();
+ gettingInfo.then(got => {
+ if (got.os == "android") {
+ getwindow = browser.tabs.get(tab.tabId);
+ getwindow.then(themeWindow);
+ } else {
+ getwindow = browser.windows.get(tab.windowId);
+ getwindow.then(themeWindow);
+ }
+ });
}
if (typeof tabId === "number") {
tab = browser.tabs.get(tabId);
@@ -113,14 +126,14 @@ function themeWindow(window) {
if (context.name == titlepref) {
console.log("Active in I2P window");
if (window.incognito) {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#FFC56D",
toolbar: "#FFC56D"
}
});
} else {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#FFC56D",
toolbar: "#FFC56D"
@@ -130,14 +143,14 @@ function themeWindow(window) {
} else if (context.name == routerpref) {
console.log("Active in Router Console window");
if (window.incognito) {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#A4C8E1",
toolbar: "#A4C8E1"
}
});
} else {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#A4C8E1",
toolbar: "#A4C8E1"
@@ -147,14 +160,14 @@ function themeWindow(window) {
} else if (context.name == tunnelpref) {
console.log("Active in Hidden Services Manager window");
if (window.incognito) {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#D9D9D6",
toolbar: "#D9D9D6"
}
});
} else {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#D9D9D6",
toolbar: "#D9D9D6"
@@ -164,14 +177,14 @@ function themeWindow(window) {
} else if (context.name == mailpref) {
console.log("Active in Web Mail window");
if (window.incognito) {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#F7E59A",
toolbar: "#F7E59A"
}
});
} else {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#F7E59A",
toolbar: "#F7E59A"
@@ -181,14 +194,14 @@ function themeWindow(window) {
} else if (context.name == torrentpref) {
console.log("Active in Bittorrent window");
if (window.incognito) {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#A48FE1",
toolbar: "#A48FE1"
}
});
} else {
- chrome.theme.update(window.id, {
+ browser.theme.update(window.id, {
colors: {
frame: "#A48FE1",
toolbar: "#A48FE1"
@@ -197,7 +210,7 @@ function themeWindow(window) {
}
} else {
console.log("Not active in I2P window");
- chrome.theme.reset(window.id);
+ browser.theme.reset(window.id);
}
}
if (
@@ -208,7 +221,7 @@ function themeWindow(window) {
.get(tabInfo[0].cookieStoreId)
.then(onGot, onError);
} else {
- chrome.theme.reset(window.id);
+ browser.theme.reset(window.id);
}
}
@@ -228,11 +241,11 @@ function setTitle(window) {
console.log("Active in I2P window");
if (window.incognito) {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: titleprefpriv
});
} else {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: titlepref
});
}
@@ -240,22 +253,22 @@ function setTitle(window) {
console.log("Active in Web window");
if (window.incognito) {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: ""
});
} else {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: ""
});
}
} else if (context.name == routerpref) {
console.log("Active in Router Console window");
if (window.incognito) {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: routerprefpriv
});
} else {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: routerpref
});
}
@@ -263,11 +276,11 @@ function setTitle(window) {
console.log("Active in Hidden Services Manager window");
if (window.incognito) {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: tunnelprefpriv
});
} else {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: tunnelpref
});
}
@@ -275,11 +288,11 @@ function setTitle(window) {
console.log("Active in Web Mail window");
if (window.incognito) {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: mailprefpriv
});
} else {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: mailpref
});
}
@@ -287,11 +300,11 @@ function setTitle(window) {
console.log("Active in I2P window");
if (window.incognito) {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: torrentprefpriv
});
} else {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: torrentpref
});
}
@@ -307,11 +320,11 @@ function setTitle(window) {
.then(onGot, onError);
} else {
if (window.incognito) {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: ""
});
} else {
- chrome.windows.update(window.id, {
+ browser.windows.update(window.id, {
titlePreface: ""
});
}
@@ -325,7 +338,7 @@ function setTitle(window) {
querying.then(logTabs, onError);
}
-chrome.windows.onCreated.addListener(() => {
+browser.windows.onCreated.addListener(() => {
/* var gettingStoredSettings = chrome.storage.local.get();
gettingStoredSettings.then(setupProxy, onError); */
chrome.storage.local.get(function(got) {
@@ -333,18 +346,34 @@ chrome.windows.onCreated.addListener(() => {
});
});
-chrome.tabs.onCreated.addListener(() => {
- var getting = browser.windows.getCurrent({
- populate: true
- });
- getting.then(setTitle, onError);
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os == "android") {
+ console.log("Running in Android detected");
+ return true;
+ } else {
+ browser.tabs.onCreated.addListener(() => {
+ var getting = browser.windows.getCurrent({
+ populate: true
+ });
+ getting.then(setTitle, onError);
+ });
+ }
});
-chrome.tabs.onActivated.addListener(() => {
- var getting = browser.windows.getCurrent({
- populate: true
- });
- getting.then(setTitle, onError);
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os == "android") {
+ console.log("Running in Android detected");
+ return true;
+ } else {
+ browser.tabs.onActivated.addListener(() => {
+ var getting = browser.windows.getCurrent({
+ populate: true
+ });
+ getting.then(setTitle, onError);
+ });
+ }
});
function handleUpdated(updateInfo) {
diff --git a/context.js b/context.js
index ad4a8b0..5df468b 100644
--- a/context.js
+++ b/context.js
@@ -1,19 +1,18 @@
//var windowIds = []
-function onCreated(windowInfo) {
- console.log(`Created window: ${windowInfo.id}`);
- browser.tabs.create({
- windowId: windowInfo.id,
- url: "about:blank",
- cookieStoreId: event.target.dataset.identity
- });
-}
-
function onError(error) {
console.log(`Error: ${error}`);
}
function eventHandler(event) {
+ function onCreated(windowInfo) {
+ console.log(`Created window: ${windowInfo.id}`);
+ browser.tabs.create({
+ windowId: windowInfo.id,
+ url: "about:blank",
+ cookieStoreId: event.target.dataset.identity
+ });
+ }
if (event.target.dataset.action == "create") {
var creating = browser.tabs.create({
cookieStoreId: event.target.dataset.identity
diff --git a/debian/changelog b/debian/changelog
index 11b6f36..b2e9217 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+i2psetproxy.js (0.49-1) UNRELEASED; urgency=low
+
+ * fix tabs
+
+ -- idk Sat, 23 NOV 2019 22:51:11 -0400
+
i2psetproxy.js (0.47-1) UNRELEASED; urgency=low
* Improve android compatibility
diff --git a/handler.js b/handler.js
index 0666be8..379d77d 100644
--- a/handler.js
+++ b/handler.js
@@ -21,9 +21,9 @@ function trimHost(url) {
} else {
hostname = url.split("/")[0];
}
- let path = url.replace(prefix+hostname, "")
- console.log("(handler) path", prefix+hostname, path)
- return path
+ let path = url.replace(prefix + hostname, "");
+ console.log("(handler) path", prefix + hostname, path);
+ return path;
}
var handlerSetup = async function(requestDetails) {
diff --git a/info.js b/info.js
index 6f54122..d7ae4cd 100644
--- a/info.js
+++ b/info.js
@@ -1,6 +1,6 @@
document.addEventListener("click", e => {
function getCurrentWindow() {
- return chrome.windows.getCurrent();
+ return browser.windows.getCurrent();
}
if (e.target.id === "window-create-help-panel") {
@@ -38,7 +38,7 @@ document.addEventListener("click", e => {
let updateInfo = {
titlePreface: "I2P Help | "
};
- chrome.windows.update(currentWindow.id, updateInfo);
+ browser.windows.update(currentWindow.id, updateInfo);
});
} else if (e.target.id === "window-visit-homepage") {
console.log("attempting to create homepage tab");
diff --git a/manifest.json b/manifest.json
index 6341866..973556c 100644
--- a/manifest.json
+++ b/manifest.json
@@ -24,7 +24,7 @@
],
"manifest_version": 2,
"name": "__MSG_extensionName__",
- "version": "0.46",
+ "version": "0.48",
"description": "__MSG_extensionDescription__",
"homepage_url": "https://github.com/eyedeekay/i2psetproxy.js",
"icons": {
diff --git a/scrub.js b/scrub.js
index e8b500e..689f855 100644
--- a/scrub.js
+++ b/scrub.js
@@ -333,9 +333,18 @@ var contextSetup = async function(requestDetails) {
});
created.then(onCreated, onError);
}
- var getting = browser.windows.getCurrent();
- getting.then(Create);
- return tabId;
+ var gettingInfo = browser.runtime.getPlatformInfo();
+ gettingInfo.then(got => {
+ if (got.os == "android") {
+ var getting = browser.tabs.getCurrent();
+ getting.then(Create);
+ return tabId;
+ } else {
+ var getting = browser.windows.getCurrent();
+ getting.then(Create);
+ return tabId;
+ }
+ });
}
}
} catch (error) {
From 916ee8166877ebeb24862e339d03dd337634d662 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 04:25:06 -0500
Subject: [PATCH 02/37] Try some android stuff
---
bookmarks.js | 301 +++++++++++++++++++++++++++------------------------
1 file changed, 157 insertions(+), 144 deletions(-)
diff --git a/bookmarks.js b/bookmarks.js
index 491dca6..55a82d0 100644
--- a/bookmarks.js
+++ b/bookmarks.js
@@ -1,153 +1,166 @@
-function bookmarks(bookmarkToolbar) {
- console.log("Setting up bookmark toolbar", bookmarkToolbar);
- function bookHome(bookmarkItems) {
- if (!bookmarkItems.length) {
- function gotProxyInfo(info) {
- let host = info.value.http.split(":")[0];
- let port = info.value.http.split(":")[1];
- if (port == "7644") {
- var createBookmark = browser.bookmarks.create({
- url: "about:I2p",
- title: "I2P Home Page",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
- } else {
- var createBookmark = browser.bookmarks.create({
- url: browser.runtime.getURL("home.html"),
- title: "I2P Home Page",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
- }
- console.log("(bookmarks) adding home page bookmark");
- }
- console.log("(bookmarks) checking if we're running in an I2P Browser");
- var gettingInfo = browser.proxy.settings.get({});
- gettingInfo.then(gotProxyInfo);
- }
- }
- function bookTorrent(bookmarkItems) {
- if (!bookmarkItems.length) {
- function gotProxyInfo(info) {
- let host = info.value.http.split(":")[0];
- let port = info.value.http.split(":")[1];
- if (port == "7644") {
- var createBookmark = browser.bookmarks.create({
- url: "http://localhost:7647/i2psnark",
- title: "Bittorrent",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
- } else {
- var createBookmark = browser.bookmarks.create({
- url: "http://localhost:7657/i2psnark",
- title: "Bittorrent",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os != "android") {
+ function bookmarks(bookmarkToolbar) {
+ console.log("Setting up bookmark toolbar", bookmarkToolbar);
+ function bookHome(bookmarkItems) {
+ if (!bookmarkItems.length) {
+ function gotProxyInfo(info) {
+ let host = info.value.http.split(":")[0];
+ let port = info.value.http.split(":")[1];
+ if (port == "7644") {
+ var createBookmark = browser.bookmarks.create({
+ url: "about:I2p",
+ title: "I2P Home Page",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ } else {
+ var createBookmark = browser.bookmarks.create({
+ url: browser.runtime.getURL("home.html"),
+ title: "I2P Home Page",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ }
+ console.log("(bookmarks) adding home page bookmark");
+ }
+ console.log(
+ "(bookmarks) checking if we're running in an I2P Browser"
+ );
+ var gettingInfo = browser.proxy.settings.get({});
+ gettingInfo.then(gotProxyInfo);
}
}
- console.log("(bookmarks) checking if we're running in an I2P Browser");
- var gettingInfo = browser.proxy.settings.get({});
- gettingInfo.then(gotProxyInfo);
- }
- }
- function bookMail(bookmarkItems) {
- if (!bookmarkItems.length) {
- function gotProxyInfo(info) {
- let host = info.value.http.split(":")[0];
- let port = info.value.http.split(":")[1];
- if (port == "7644") {
- var createBookmark = browser.bookmarks.create({
- url: "http://localhost:7647/webmail",
- title: "Web Mail",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
- } else {
- var createBookmark = browser.bookmarks.create({
- url: "http://localhost:7657/webmail",
- title: "Web Mail",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
+ function bookTorrent(bookmarkItems) {
+ if (!bookmarkItems.length) {
+ function gotProxyInfo(info) {
+ let host = info.value.http.split(":")[0];
+ let port = info.value.http.split(":")[1];
+ if (port == "7644") {
+ var createBookmark = browser.bookmarks.create({
+ url: "http://localhost:7647/i2psnark",
+ title: "Bittorrent",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ } else {
+ var createBookmark = browser.bookmarks.create({
+ url: "http://localhost:7657/i2psnark",
+ title: "Bittorrent",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ }
+ }
+ console.log(
+ "(bookmarks) checking if we're running in an I2P Browser"
+ );
+ var gettingInfo = browser.proxy.settings.get({});
+ gettingInfo.then(gotProxyInfo);
}
- console.log("(bookmarks) adding webmail bookmark");
}
- console.log("(bookmarks) checking if we're running in an I2P Browser");
- var gettingInfo = browser.proxy.settings.get({});
- gettingInfo.then(gotProxyInfo);
- }
- }
- function bookI2PTunnel(bookmarkItems) {
- if (!bookmarkItems.length) {
- function gotProxyInfo(info) {
- let host = info.value.http.split(":")[0];
- let port = info.value.http.split(":")[1];
- if (port == "7644") {
- var createBookmark = browser.bookmarks.create({
- url: "http://localhost:7647/i2ptunnelmgr",
- title: "Hidden Services Manager",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
- } else {
- var createBookmark = browser.bookmarks.create({
- url: "http://localhost:7657/i2ptunnelmgr",
- title: "Hidden Services Manager",
- parentId: bookmarkToolbar[0].id
- });
- createBookmark.then(onCreated);
+ function bookMail(bookmarkItems) {
+ if (!bookmarkItems.length) {
+ function gotProxyInfo(info) {
+ let host = info.value.http.split(":")[0];
+ let port = info.value.http.split(":")[1];
+ if (port == "7644") {
+ var createBookmark = browser.bookmarks.create({
+ url: "http://localhost:7647/webmail",
+ title: "Web Mail",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ } else {
+ var createBookmark = browser.bookmarks.create({
+ url: "http://localhost:7657/webmail",
+ title: "Web Mail",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ }
+ console.log("(bookmarks) adding webmail bookmark");
+ }
+ console.log(
+ "(bookmarks) checking if we're running in an I2P Browser"
+ );
+ var gettingInfo = browser.proxy.settings.get({});
+ gettingInfo.then(gotProxyInfo);
}
- console.log("(bookmarks) adding i2ptunnel bookmark");
}
- console.log("(bookmarks) checking if we're running in an I2P Browser");
- var gettingInfo = browser.proxy.settings.get({});
- gettingInfo.then(gotProxyInfo);
+ function bookI2PTunnel(bookmarkItems) {
+ if (!bookmarkItems.length) {
+ function gotProxyInfo(info) {
+ let host = info.value.http.split(":")[0];
+ let port = info.value.http.split(":")[1];
+ if (port == "7644") {
+ var createBookmark = browser.bookmarks.create({
+ url: "http://localhost:7647/i2ptunnelmgr",
+ title: "Hidden Services Manager",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ } else {
+ var createBookmark = browser.bookmarks.create({
+ url: "http://localhost:7657/i2ptunnelmgr",
+ title: "Hidden Services Manager",
+ parentId: bookmarkToolbar[0].id
+ });
+ createBookmark.then(onCreated);
+ }
+ console.log("(bookmarks) adding i2ptunnel bookmark");
+ }
+ console.log(
+ "(bookmarks) checking if we're running in an I2P Browser"
+ );
+ var gettingInfo = browser.proxy.settings.get({});
+ gettingInfo.then(gotProxyInfo);
+ }
+ }
+
+ function onRejected(error) {
+ console.log(`An error: ${error}`);
+ }
+ function onCreated(node) {
+ console.log("Bookmarked", node);
+ }
+
+ var b0 = browser.bookmarks.search({
+ title: "I2P Home Page"
+ });
+ b0.then(bookHome, onRejected);
+
+ var b1 = browser.bookmarks.search({
+ title: "Bittorrent"
+ });
+ b1.then(bookTorrent, onRejected);
+
+ var b2 = browser.bookmarks.search({
+ title: "Hidden Services Manager"
+ });
+ b2.then(bookI2PTunnel, onRejected);
+
+ var b3 = browser.bookmarks.search({
+ title: "Web Mail"
+ });
+ b3.then(bookMail, onRejected);
}
+
+ var bt = browser.bookmarks.search({
+ query: "Toolbar"
+ });
+
+ bt.then(bookmarks);
+
+ function handleCreated(id, bookmarkInfo) {
+ var propValue;
+ for (var propName in bookmarkInfo) {
+ propValue = bookmarkInfo[propName];
+ console.log(propName, propValue);
+ }
+ }
+
+ browser.bookmarks.onCreated.addListener(handleCreated);
}
-
- function onRejected(error) {
- console.log(`An error: ${error}`);
- }
- function onCreated(node) {
- console.log("Bookmarked", node);
- }
-
- var b0 = browser.bookmarks.search({
- title: "I2P Home Page"
- });
- b0.then(bookHome, onRejected);
-
- var b1 = browser.bookmarks.search({
- title: "Bittorrent"
- });
- b1.then(bookTorrent, onRejected);
-
- var b2 = browser.bookmarks.search({
- title: "Hidden Services Manager"
- });
- b2.then(bookI2PTunnel, onRejected);
-
- var b3 = browser.bookmarks.search({
- title: "Web Mail"
- });
- b3.then(bookMail, onRejected);
-}
-
-var bt = browser.bookmarks.search({
- query: "Toolbar"
});
-
-bt.then(bookmarks);
-
-function handleCreated(id, bookmarkInfo) {
- var propValue;
- for (var propName in bookmarkInfo) {
- propValue = bookmarkInfo[propName];
- console.log(propName, propValue);
- }
-}
-
-browser.bookmarks.onCreated.addListener(handleCreated);
From 2d17f4fb0fe58655c64843d105b37a3a8402bbed Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 04:28:14 -0500
Subject: [PATCH 03/37] Try some android stuff
---
proxy.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/proxy.js b/proxy.js
index 392c005..ad478cf 100644
--- a/proxy.js
+++ b/proxy.js
@@ -353,5 +353,11 @@ chrome.storage.local.get(function(got) {
// Theme all currently open windows
if (!isDroid()) {
- browser.windows.getAll().then(wins => wins.forEach(themeWindow));
}
+
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os != "android") {
+ browser.windows.getAll().then(wins => wins.forEach(themeWindow));
+ }
+});
From 25c24757d4625f9a19f1123400f11c1e52e706c7 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 04:32:35 -0500
Subject: [PATCH 04/37] Try some android stuff
---
background.js | 39 ++++++++++++++++++++++++++++++---------
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/background.js b/background.js
index bee4126..e1c644b 100644
--- a/background.js
+++ b/background.js
@@ -338,19 +338,36 @@ function setTitle(window) {
querying.then(logTabs, onError);
}
-browser.windows.onCreated.addListener(() => {
- /* var gettingStoredSettings = chrome.storage.local.get();
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os == "android") {
+ browser.tabs.onCreated.addListener(() => {
+ /* var gettingStoredSettings = chrome.storage.local.get();
gettingStoredSettings.then(setupProxy, onError); */
- chrome.storage.local.get(function(got) {
- setupProxy();
- });
+ chrome.storage.local.get(function(got) {
+ setupProxy();
+ });
+ });
+ } else {
+ browser.windows.onCreated.addListener(() => {
+ /* var gettingStoredSettings = chrome.storage.local.get();
+ gettingStoredSettings.then(setupProxy, onError); */
+ chrome.storage.local.get(function(got) {
+ setupProxy();
+ });
+ });
+ }
});
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
- console.log("Running in Android detected");
- return true;
+ browser.tabs.onCreated.addListener(() => {
+ var getting = browser.tabs.getCurrent({
+ populate: true
+ });
+ getting.then(setTitle, onError);
+ });
} else {
browser.tabs.onCreated.addListener(() => {
var getting = browser.windows.getCurrent({
@@ -364,8 +381,12 @@ gettingInfo.then(got => {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
- console.log("Running in Android detected");
- return true;
+ browser.tabs.onActivated.addListener(() => {
+ var getting = browser.tabs.getCurrent({
+ populate: true
+ });
+ getting.then(setTitle, onError);
+ });
} else {
browser.tabs.onActivated.addListener(() => {
var getting = browser.windows.getCurrent({
From 049b79753e03b290ab1ae6e7b51878f413fbcb6d Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 04:54:28 -0500
Subject: [PATCH 05/37] Try some android stuff
---
background.js | 2 --
proxy.js | 87 +++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 81 insertions(+), 8 deletions(-)
diff --git a/background.js b/background.js
index e1c644b..458afc8 100644
--- a/background.js
+++ b/background.js
@@ -87,8 +87,6 @@ browser.contextualIdentities.query({}).then(onGot, onError);
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
- console.log("Running in Android detected");
- return true;
} else {
browser.windows.onCreated.addListener(themeWindow);
browser.windows.onFocusChanged.addListener(themeWindow);
diff --git a/proxy.js b/proxy.js
index ad478cf..7f0d809 100644
--- a/proxy.js
+++ b/proxy.js
@@ -325,6 +325,76 @@ function checkStoredSettings(storedSettings) {
gettingInfo.then(gotProxyInfo);
}
+function checkAndroidStoredSettings(storedSettings) {
+ let defaultSettings = {};
+ let host = "";
+ let port = "";
+ console.log("proxy", "'" + host + "'", ":", port);
+ if (!storedSettings.proxy_scheme) {
+ defaultSettings["proxy_scheme"] = "http";
+ }
+ if (!storedSettings.proxy_host) {
+ if (host == "") {
+ defaultSettings["proxy_host"] = "127.0.0.1";
+ } else {
+ defaultSettings["proxy_host"] = host;
+ }
+ } else {
+ if (host != "") {
+ defaultSettings["proxy_host"] = host;
+ } else {
+ defaultSettings["proxy_host"] = storedSettings.proxy_host;
+ }
+ }
+ if (!storedSettings.proxy_port) {
+ if (port == undefined) {
+ defaultSettings["proxy_port"] = 4444;
+ } else {
+ defaultSettings["proxy_port"] = port;
+ }
+ } else {
+ if (port != undefined) {
+ defaultSettings["proxy_port"] = port;
+ } else {
+ defaultSettings["proxy_port"] = storedSettings.proxy_port;
+ }
+ }
+ if (!storedSettings.control_host) {
+ if (host == "") {
+ defaultSettings["control_host"] = "127.0.0.1";
+ } else {
+ defaultSettings["control_host"] = host;
+ }
+ } else {
+ if (host != "") {
+ defaultSettings["control_host"] = host;
+ } else {
+ defaultSettings["control_host"] = storedSettings.control_host;
+ }
+ }
+ if (!storedSettings.control_port) {
+ if (port == undefined) {
+ defaultSettings["control_port"] = 4444;
+ } else {
+ defaultSettings["control_port"] = port;
+ }
+ } else {
+ if (port != undefined) {
+ defaultSettings["control_port"] = port;
+ } else {
+ defaultSettings["control_port"] = storedSettings.control_port;
+ }
+ }
+ console.log("(browserinfo) NATIVE PROXYSETTINGS", info.value);
+ console.log(
+ defaultSettings["proxy_host"],
+ defaultSettings["proxy_port"],
+ defaultSettings["control_host"],
+ defaultSettings["control_port"]
+ );
+ chrome.storage.local.set(defaultSettings);
+}
+
//function gotProxyInfo(info) {
//console.log("(browserinfo)", info.value);
//}
@@ -345,12 +415,6 @@ function update(restoredSettings) {
console.log("restoring control port:", control_port);
}
-chrome.storage.local.get(function(got) {
- checkStoredSettings(got);
- update(got);
- setupProxy();
-});
-
// Theme all currently open windows
if (!isDroid()) {
}
@@ -359,5 +423,16 @@ var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os != "android") {
browser.windows.getAll().then(wins => wins.forEach(themeWindow));
+ chrome.storage.local.get(function(got) {
+ checkStoredSettings(got);
+ update(got);
+ setupProxy();
+ });
+ } else {
+ chrome.storage.local.get(function(got) {
+ checkAndroidStoredSettings(got);
+ update(got);
+ setupProxy();
+ });
}
});
From 32035348c1412d7d101d5ed6eafff89da2787989 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 04:55:39 -0500
Subject: [PATCH 06/37] Try some android stuff
---
proxy.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/proxy.js b/proxy.js
index 7f0d809..cac2f96 100644
--- a/proxy.js
+++ b/proxy.js
@@ -385,7 +385,6 @@ function checkAndroidStoredSettings(storedSettings) {
defaultSettings["control_port"] = storedSettings.control_port;
}
}
- console.log("(browserinfo) NATIVE PROXYSETTINGS", info.value);
console.log(
defaultSettings["proxy_host"],
defaultSettings["proxy_port"],
From 5c7a80997f0b2bc612bfe00bcdb2e429a014436b Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 05:21:56 -0500
Subject: [PATCH 07/37] fix android maybe
---
info.js | 10 ----------
scrub.js | 37 +++++++++++++------------------------
2 files changed, 13 insertions(+), 34 deletions(-)
diff --git a/info.js b/info.js
index d7ae4cd..9380641 100644
--- a/info.js
+++ b/info.js
@@ -1,8 +1,4 @@
document.addEventListener("click", e => {
- function getCurrentWindow() {
- return browser.windows.getCurrent();
- }
-
if (e.target.id === "window-create-help-panel") {
let createData = {
type: "panel",
@@ -34,12 +30,6 @@ document.addEventListener("click", e => {
}
RefreshIdentity();
} else if (e.target.id === "window-preface-title") {
- getCurrentWindow().then(currentWindow => {
- let updateInfo = {
- titlePreface: "I2P Help | "
- };
- browser.windows.update(currentWindow.id, updateInfo);
- });
} else if (e.target.id === "window-visit-homepage") {
console.log("attempting to create homepage tab");
goHome();
diff --git a/scrub.js b/scrub.js
index 689f855..a2c12d8 100644
--- a/scrub.js
+++ b/scrub.js
@@ -123,7 +123,6 @@ var contextSetup = async function(requestDetails) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab", window);
browser.tabs.remove(tabId.id);
- browser.tabs.remove(window.tabs[0].id);
}
function onError(error) {
console.log(`Error: ${error}`);
@@ -131,12 +130,11 @@ var contextSetup = async function(requestDetails) {
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
- url: requestDetails.url,
- windowId: window.id
+ url: requestDetails.url
});
created.then(onCreated, onError);
}
- var getting = browser.windows.getCurrent();
+ var getting = browser.tabs.getCurrent();
getting.then(Create);
return tabId;
}
@@ -169,12 +167,12 @@ var contextSetup = async function(requestDetails) {
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
- url: requestDetails.url,
- windowId: window.id
+ url: requestDetails.url
+ //windowId: window.id
});
created.then(onCreated, onError);
}
- var getting = browser.windows.getCurrent();
+ var getting = browser.tabs.getCurrent();
getting.then(Create);
return tabId;
}
@@ -199,9 +197,6 @@ var contextSetup = async function(requestDetails) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
- if (window != undefined) {
- browser.tabs.remove(window.tabs[0].id);
- }
}
function onError(error) {
console.log(`Error: ${error}`);
@@ -209,12 +204,12 @@ var contextSetup = async function(requestDetails) {
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
- url: requestDetails.url,
- windowId: window.id
+ url: requestDetails.url
+ //windowId: window.id
});
created.then(onCreated, onError);
}
- var getting = browser.windows.getCurrent();
+ var getting = browser.tabs.getCurrent();
getting.then(Create);
return tabId;
}
@@ -239,7 +234,6 @@ var contextSetup = async function(requestDetails) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
- browser.tabs.remove(window.tabs[0].id);
}
function onError(error) {
console.log(`Error: ${error}`);
@@ -247,12 +241,11 @@ var contextSetup = async function(requestDetails) {
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
- url: requestDetails.url,
- windowId: window.id
+ url: requestDetails.url
});
created.then(onCreated, onError);
}
- var getting = browser.windows.getCurrent();
+ var getting = browser.tabs.getCurrent();
getting.then(Create);
return tabId;
}
@@ -277,7 +270,6 @@ var contextSetup = async function(requestDetails) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
- browser.tabs.remove(window.tabs[0].id);
}
function onError(error) {
console.log(`Error: ${error}`);
@@ -285,12 +277,11 @@ var contextSetup = async function(requestDetails) {
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
- url: requestDetails.url,
- windowId: window.id
+ url: requestDetails.url
});
created.then(onCreated, onError);
}
- var getting = browser.windows.getCurrent();
+ var getting = browser.tabs.getCurrent();
getting.then(Create);
return tabId;
}
@@ -320,7 +311,6 @@ var contextSetup = async function(requestDetails) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
- browser.tabs.remove(window.tabs[0].id);
}
function onError(error) {
console.log(`Error: ${error}`);
@@ -328,8 +318,7 @@ var contextSetup = async function(requestDetails) {
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
- url: requestDetails.url,
- windowId: window.id
+ url: requestDetails.url
});
created.then(onCreated, onError);
}
From cb5fa75616bc9692c9fb9a2bc107bcb25864a953 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 05:29:19 -0500
Subject: [PATCH 08/37] fix android maybe
---
background.js | 19 -------------------
1 file changed, 19 deletions(-)
diff --git a/background.js b/background.js
index 458afc8..aa0145a 100644
--- a/background.js
+++ b/background.js
@@ -339,13 +339,6 @@ function setTitle(window) {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
- browser.tabs.onCreated.addListener(() => {
- /* var gettingStoredSettings = chrome.storage.local.get();
- gettingStoredSettings.then(setupProxy, onError); */
- chrome.storage.local.get(function(got) {
- setupProxy();
- });
- });
} else {
browser.windows.onCreated.addListener(() => {
/* var gettingStoredSettings = chrome.storage.local.get();
@@ -360,12 +353,6 @@ gettingInfo.then(got => {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
- browser.tabs.onCreated.addListener(() => {
- var getting = browser.tabs.getCurrent({
- populate: true
- });
- getting.then(setTitle, onError);
- });
} else {
browser.tabs.onCreated.addListener(() => {
var getting = browser.windows.getCurrent({
@@ -379,12 +366,6 @@ gettingInfo.then(got => {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
- browser.tabs.onActivated.addListener(() => {
- var getting = browser.tabs.getCurrent({
- populate: true
- });
- getting.then(setTitle, onError);
- });
} else {
browser.tabs.onActivated.addListener(() => {
var getting = browser.windows.getCurrent({
From b2184119f72dbe8e8f982e84e81cab48acc08e0a Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 05:41:45 -0500
Subject: [PATCH 09/37] fix android maybe
---
scrub.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scrub.js b/scrub.js
index a2c12d8..c17f626 100644
--- a/scrub.js
+++ b/scrub.js
@@ -73,7 +73,8 @@ var contextScrub = async function(requestDetails) {
let tabInfo = await browser.tabs.get(tabId);
return tabInfo;
} catch (error) {
- console.log("(scrub)Tab error", error);
+ let tabInfo = await browser.tabs.getCurrent();
+ return tabInfo;
}
};
if (requestDetails.tabId > 0) {
From 875fe8b86d6dfc8f12d885a14213391d4b858014 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 05:50:06 -0500
Subject: [PATCH 10/37] fix android maybe
---
scrub.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/scrub.js b/scrub.js
index c17f626..49355bc 100644
--- a/scrub.js
+++ b/scrub.js
@@ -85,7 +85,6 @@ var contextScrub = async function(requestDetails) {
console.log("(Proxy)I2P URL detected, ");
tab = tabGet(requestDetails.tabId);
var mtab = tab.then(tabFind);
- requestDetails.tabId = mtab;
context = mtab.then(contextGet);
req = await context.then(headerScrub);
console.log("(scrub)Scrubbing I2P Request", req);
@@ -326,7 +325,7 @@ var contextSetup = async function(requestDetails) {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
- var getting = browser.tabs.getCurrent();
+ var getting = browser.windows.getCurrent();
getting.then(Create);
return tabId;
} else {
From 2bbeed83856a60c96bfaf0078476f134655add9c Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 17:14:43 -0500
Subject: [PATCH 11/37] reuse less function names
---
background.js | 20 ++++++++++++++------
privacy.js | 12 ++++++------
2 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/background.js b/background.js
index aa0145a..e424aee 100644
--- a/background.js
+++ b/background.js
@@ -11,7 +11,7 @@ var torrentprefpriv = chrome.i18n.getMessage("torrentPrefacePrivate");
var tunnelpref = chrome.i18n.getMessage("i2ptunnelPreface");
var tunnelprefpriv = chrome.i18n.getMessage("i2ptunnelPrefacePrivate");
-function onGot(contexts) {
+function onContextsGot(contexts) {
var ids = [];
for (let context of contexts) {
console.log(`Name: ${context.name}`);
@@ -82,7 +82,15 @@ function onError(e) {
console.error(e);
}
-browser.contextualIdentities.query({}).then(onGot, onError);
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os == "android") {
+ } else {
+ browser.windows.onCreated.addListener(() => {
+ browser.contextualIdentities.query({}).then(onContextsGot, onError);
+ });
+ }
+});
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
@@ -120,7 +128,7 @@ function themeWindowByTab(tabId) {
function themeWindow(window) {
// Check if the window is in private browsing
function logTabs(tabInfo) {
- function onGot(context) {
+ function onContextGotTheme(context) {
if (context.name == titlepref) {
console.log("Active in I2P window");
if (window.incognito) {
@@ -217,7 +225,7 @@ function themeWindow(window) {
) {
browser.contextualIdentities
.get(tabInfo[0].cookieStoreId)
- .then(onGot, onError);
+ .then(onContextGotTheme, onError);
} else {
browser.theme.reset(window.id);
}
@@ -234,7 +242,7 @@ function setTitle(window) {
function logTabs(tabInfo) {
console.log(tabInfo);
- function onGot(context) {
+ function onContextGotTitle(context) {
if (context.name == titlepref) {
console.log("Active in I2P window");
@@ -315,7 +323,7 @@ function setTitle(window) {
) {
browser.contextualIdentities
.get(tabInfo[0].cookieStoreId)
- .then(onGot, onError);
+ .then(onContextGotTitle, onError);
} else {
if (window.incognito) {
browser.windows.update(window.id, {
diff --git a/privacy.js b/privacy.js
index e064050..e3e6036 100644
--- a/privacy.js
+++ b/privacy.js
@@ -256,28 +256,28 @@ function forgetBrowsingData(storedSettings) {
hostnames: [i2pHostName(item.url)],
since
})
- .then(onGot);
+ .then(onContextGotLog);
console.log("cleared Passwords");
browser.browsingData
.removeDownloads({
hostnames: [i2pHostName(item.url)],
since
})
- .then(onGot);
+ .then(onContextGotLog);
console.log("cleared Downloads");
browser.browsingData
.removeFormData({
hostnames: [i2pHostName(item.url)],
since
})
- .then(onGot);
+ .then(onContextGotLog);
console.log("cleared Form Data");
browser.browsingData
.removeLocalStorage({
hostnames: [i2pHostName(item.url)],
since
})
- .then(onGot);
+ .then(onContextGotLog);
console.log("cleared Local Storage");
contexts = browser.contextualIdentities.query({
@@ -291,7 +291,7 @@ function forgetBrowsingData(storedSettings) {
name: cookie.name,
url: item.url
});
- removing.then(onGot, onError);
+ removing.then(onContextGotLog, onError);
}
console.log("Cleared cookies");
}
@@ -338,7 +338,7 @@ function i2pHost(url) {
return hostname.endsWith(".i2p");
}
-function onGot(contexts) {
+function onContextGotLog(contexts) {
if (contexts != null) {
for (let context of contexts) {
console.log(context);
From 9987325f1a32b03703d115237d2296245bd3281e Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 17:24:34 -0500
Subject: [PATCH 12/37] reuse less function names
---
background.js | 4 ----
scrub.js | 18 ------------------
2 files changed, 22 deletions(-)
diff --git a/background.js b/background.js
index e424aee..8cbe2c0 100644
--- a/background.js
+++ b/background.js
@@ -78,10 +78,6 @@ function onCreated(context) {
console.log(`New identity's ID: ${context.cookieStoreId}.`);
}
-function onError(e) {
- console.error(e);
-}
-
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
diff --git a/scrub.js b/scrub.js
index 49355bc..13308d7 100644
--- a/scrub.js
+++ b/scrub.js
@@ -124,9 +124,6 @@ var contextSetup = async function(requestDetails) {
console.log("(isolate) Closing old, un-isolated tab", window);
browser.tabs.remove(tabId.id);
}
- function onError(error) {
- console.log(`Error: ${error}`);
- }
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
@@ -161,9 +158,6 @@ var contextSetup = async function(requestDetails) {
browser.tabs.remove(tabId.id);
browser.tabs.remove(window.tabs[0].id);
}
- function onError(error) {
- console.log(`Error: ${error}`);
- }
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
@@ -198,9 +192,6 @@ var contextSetup = async function(requestDetails) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
}
- function onError(error) {
- console.log(`Error: ${error}`);
- }
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
@@ -235,9 +226,6 @@ var contextSetup = async function(requestDetails) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
}
- function onError(error) {
- console.log(`Error: ${error}`);
- }
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
@@ -271,9 +259,6 @@ var contextSetup = async function(requestDetails) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
}
- function onError(error) {
- console.log(`Error: ${error}`);
- }
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
@@ -312,9 +297,6 @@ var contextSetup = async function(requestDetails) {
console.log("(isolate) Closing old, un-isolated tab");
browser.tabs.remove(tabId.id);
}
- function onError(error) {
- console.log(`Error: ${error}`);
- }
var created = browser.tabs.create({
active: true,
cookieStoreId: context[0].cookieStoreId,
From 070955225df38010ee222c00104c4f8ce3640375 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 17:28:58 -0500
Subject: [PATCH 13/37] reuse less function names
---
scrub.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scrub.js b/scrub.js
index 13308d7..5054972 100644
--- a/scrub.js
+++ b/scrub.js
@@ -338,7 +338,7 @@ var contextSetup = async function(requestDetails) {
url: requestDetails.url,
secure: true
});
- setcookie.then(onGot, onError);
+ setcookie.then(onContextGotLog, onError);
return requestDetails;
}
if (i2pHost(requestDetails.url)) {
@@ -347,7 +347,7 @@ var contextSetup = async function(requestDetails) {
url: requestDetails.url,
secure: true
});
- setcookie.then(onGot, onError);
+ setcookie.then(onContextGotLog, onError);
var tab = tabGet(requestDetails.tabId);
var mtab = tab.then(tabFind);
return requestDetails;
From 8d14c945f3ea86eead64f96a6d7ae09fd927977a Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 17:43:43 -0500
Subject: [PATCH 14/37] reuse less function names
---
scrub.js | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/scrub.js b/scrub.js
index 5054972..82c7b5c 100644
--- a/scrub.js
+++ b/scrub.js
@@ -304,18 +304,9 @@ var contextSetup = async function(requestDetails) {
});
created.then(onCreated, onError);
}
- var gettingInfo = browser.runtime.getPlatformInfo();
- gettingInfo.then(got => {
- if (got.os == "android") {
- var getting = browser.windows.getCurrent();
- getting.then(Create);
- return tabId;
- } else {
- var getting = browser.windows.getCurrent();
- getting.then(Create);
- return tabId;
- }
- });
+ var getting = browser.tabs.getCurrent();
+ getting.then(Create);
+ return tabId;
}
}
} catch (error) {
From 6f4536369250f82e2b7b29a22df9c3814eb92cdd Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 18:04:58 -0500
Subject: [PATCH 15/37] reuse less function names
---
scrub.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/scrub.js b/scrub.js
index 82c7b5c..8c652c8 100644
--- a/scrub.js
+++ b/scrub.js
@@ -61,7 +61,13 @@ var contextScrub = async function(requestDetails) {
name: titlepref
});
tabId.cookieStoreId = context[0].cookieStoreId;
- console.log("(scrub) forcing context", tabId.cookieStoreId);
+ console.log(
+ "(scrub) forcing context",
+ titlepref,
+ tabId.cookieStoreId,
+ "=>",
+ context[0].cookieStoreId
+ );
return tabId;
} catch (error) {
console.log("(scrub)Context Error", error);
From 4c10cd2855e6886d61ce5619c2426f74d595ad09 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 18:13:34 -0500
Subject: [PATCH 16/37] try and figure out why it works on Desktop but not
Android still
---
proxy.js | 13 ++++++++++++-
scrub.js | 2 +-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/proxy.js b/proxy.js
index cac2f96..1a51794 100644
--- a/proxy.js
+++ b/proxy.js
@@ -1,3 +1,4 @@
+var titlepref = chrome.i18n.getMessage("titlePreface");
var webpref = chrome.i18n.getMessage("webPreface");
var webprefpriv = chrome.i18n.getMessage("webPrefacePrivate");
var routerpref = chrome.i18n.getMessage("routerPreface");
@@ -126,7 +127,17 @@ var handleContextProxyRequest = async function(requestDetails) {
};
var tabFind = async function(tabId) {
try {
- console.log("(proxy) forcing context", tabId.cookieStoreId);
+ context = await browser.contextualIdentities.query({
+ name: titlepref
+ });
+ console.log(
+ "(scrub) forcing context",
+ titlepref,
+ tabId.cookieStoreId,
+ "=>",
+ context[0].cookieStoreId
+ );
+ tabId.cookieStoreId = context[0].cookieStoreId;
return tabId;
} catch (error) {
console.log("(proxy)Context Error", error);
diff --git a/scrub.js b/scrub.js
index 8c652c8..79d9f6c 100644
--- a/scrub.js
+++ b/scrub.js
@@ -60,7 +60,6 @@ var contextScrub = async function(requestDetails) {
context = await browser.contextualIdentities.query({
name: titlepref
});
- tabId.cookieStoreId = context[0].cookieStoreId;
console.log(
"(scrub) forcing context",
titlepref,
@@ -68,6 +67,7 @@ var contextScrub = async function(requestDetails) {
"=>",
context[0].cookieStoreId
);
+ tabId.cookieStoreId = context[0].cookieStoreId;
return tabId;
} catch (error) {
console.log("(scrub)Context Error", error);
From c7af1a0d72ffd65ddfe95a3135cac61012969d00 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 18:15:38 -0500
Subject: [PATCH 17/37] try and figure out why it works on Desktop but not
Android still
---
proxy.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/proxy.js b/proxy.js
index 1a51794..961ffd8 100644
--- a/proxy.js
+++ b/proxy.js
@@ -131,7 +131,7 @@ var handleContextProxyRequest = async function(requestDetails) {
name: titlepref
});
console.log(
- "(scrub) forcing context",
+ "(proxy) forcing context",
titlepref,
tabId.cookieStoreId,
"=>",
From 870eaa6e3e6604188079187da68c1589ffa80dc3 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 19:47:33 -0500
Subject: [PATCH 18/37] try and figure out why it works on Desktop but not
Android still
---
home.css | 2 +-
options/options.js | 91 ++++++++++++++++++++++++++++++++++++++++++++--
privacy.js | 4 +-
scrub.js | 2 +-
4 files changed, 91 insertions(+), 8 deletions(-)
diff --git a/home.css b/home.css
index f2bdefe..197cea7 100644
--- a/home.css
+++ b/home.css
@@ -283,7 +283,7 @@ img.readyness {
height: 100%;
width: auto
}
-@media only screen and (max-width: 768px) {
+@media only screen and (min-width: 768px) {
.application-info {
display: none
}
diff --git a/options/options.js b/options/options.js
index 55ac6a8..2544079 100644
--- a/options/options.js
+++ b/options/options.js
@@ -23,7 +23,7 @@ function SetControlHostText() {
var controlhostid = document.getElementById("controlHostText");
controlhostid.textContent = chrome.i18n.getMessage("controlHostText");
}
-
+/*
var handleContextProxyRequest = async function(requestDetails) {
console.log("(proxy)Searching for proxy by context");
try {
@@ -183,14 +183,13 @@ function setupProxy() {
var Port = getPort();
var Scheme = getScheme();
- /**/
console.log("Setting up Firefox WebExtension proxy");
browser.proxy.onRequest.addListener(handleContextProxyRequest, {
urls: [""]
});
console.log("i2p settings created for WebExtension Proxy");
- /**/
}
+*/
function SetControlPortText() {
var controlportid = document.getElementById("controlPortText");
@@ -324,6 +323,75 @@ function checkStoredSettings(storedSettings) {
gettingInfo.then(gotProxyInfo);
}
+function checkAndroidStoredSettings(storedSettings) {
+ let defaultSettings = {};
+ let host = "";
+ let port = "";
+ console.log("proxy", "'" + host + "'", ":", port);
+ if (!storedSettings.proxy_scheme) {
+ defaultSettings["proxy_scheme"] = "http";
+ }
+ if (!storedSettings.proxy_host) {
+ if (host == "") {
+ defaultSettings["proxy_host"] = "127.0.0.1";
+ } else {
+ defaultSettings["proxy_host"] = host;
+ }
+ } else {
+ if (host != "") {
+ defaultSettings["proxy_host"] = host;
+ } else {
+ defaultSettings["proxy_host"] = storedSettings.proxy_host;
+ }
+ }
+ if (!storedSettings.proxy_port) {
+ if (port == undefined) {
+ defaultSettings["proxy_port"] = 4444;
+ } else {
+ defaultSettings["proxy_port"] = port;
+ }
+ } else {
+ if (port != undefined) {
+ defaultSettings["proxy_port"] = port;
+ } else {
+ defaultSettings["proxy_port"] = storedSettings.proxy_port;
+ }
+ }
+ if (!storedSettings.control_host) {
+ if (host == "") {
+ defaultSettings["control_host"] = "127.0.0.1";
+ } else {
+ defaultSettings["control_host"] = host;
+ }
+ } else {
+ if (host != "") {
+ defaultSettings["control_host"] = host;
+ } else {
+ defaultSettings["control_host"] = storedSettings.control_host;
+ }
+ }
+ if (!storedSettings.control_port) {
+ if (port == undefined) {
+ defaultSettings["control_port"] = 4444;
+ } else {
+ defaultSettings["control_port"] = port;
+ }
+ } else {
+ if (port != undefined) {
+ defaultSettings["control_port"] = port;
+ } else {
+ defaultSettings["control_port"] = storedSettings.control_port;
+ }
+ }
+ console.log(
+ defaultSettings["proxy_host"],
+ defaultSettings["proxy_port"],
+ defaultSettings["control_host"],
+ defaultSettings["control_port"]
+ );
+ chrome.storage.local.set(defaultSettings);
+}
+
function onError(e) {
console.error(e);
}
@@ -383,7 +451,22 @@ function onError(e) {
}
chrome.storage.local.get(function(got) {
checkStoredSettings(got);
- updateUI(got);
+});
+
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os != "android") {
+ browser.windows.getAll().then(wins => wins.forEach(themeWindow));
+ chrome.storage.local.get(function(got) {
+ checkStoredSettings(got);
+ updateUI(got);
+ });
+ } else {
+ chrome.storage.local.get(function(got) {
+ checkAndroidStoredSettings(got);
+ updateUI(got);
+ });
+ }
});
const saveButton = document.querySelector("#save-button");
diff --git a/privacy.js b/privacy.js
index e3e6036..aaafee9 100644
--- a/privacy.js
+++ b/privacy.js
@@ -86,7 +86,7 @@ function disableReferrers() {
// enable fingerprinting resistent features(letterboxing and stuff)
function enableResistFingerprinting() {
- var setting = browser.privacy.websites.referrersEnabled.set({
+ var setting = browser.privacy.websites.resistFingerprinting.set({
value: true
});
console.log("Enabling resist fingerprinting/val=", {
@@ -146,7 +146,7 @@ function ResetPeerConnection() {
value: false
});
chrome.privacy.network.webRTCIPHandlingPolicy.set({
- value: "disable_non_proxied_udp"
+ value: "proxy_only"
});
console.log("Re-disabled WebRTC");
}
diff --git a/scrub.js b/scrub.js
index 79d9f6c..0ed6c77 100644
--- a/scrub.js
+++ b/scrub.js
@@ -52,7 +52,7 @@ var contextScrub = async function(requestDetails) {
context = await browser.contextualIdentities.get(tabInfo.cookieStoreId);
return context;
} catch (error) {
- console.log("(scrub)Conext Error", error);
+ console.log("(scrub)Context Error", error);
}
};
var tabFind = async function(tabId) {
From f0b4a0a849d0b870653c2b8da3c284d0d106ed24 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 19:49:47 -0500
Subject: [PATCH 19/37] try and figure out why it works on Desktop but not
Android still
---
options/options.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/options/options.js b/options/options.js
index 2544079..3acd5b0 100644
--- a/options/options.js
+++ b/options/options.js
@@ -414,7 +414,6 @@ function storeSettings() {
console.log("storing proxy port:", proxy_port);
console.log("storing control host:", control_host);
console.log("storing control port:", control_port);
- setupProxy();
}
function updateUI(restoredSettings) {
@@ -443,7 +442,6 @@ function updateUI(restoredSettings) {
SetControlHostText();
SetControlPortText();
SetControlHelpText();
- setupProxy();
}
function onError(e) {
From 749ff30b5b3de46e9d7691e8f59334c42c58a5c9 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 20:43:17 -0500
Subject: [PATCH 20/37] Bring some sanity to the settings section
---
options/options.js | 179 -------------------------------
proxy.js | 260 ++++++++++++++-------------------------------
2 files changed, 78 insertions(+), 361 deletions(-)
diff --git a/options/options.js b/options/options.js
index 3acd5b0..bd699ab 100644
--- a/options/options.js
+++ b/options/options.js
@@ -1,14 +1,3 @@
-function isDroid() {
- var gettingInfo = browser.runtime.getPlatformInfo();
- gettingInfo.then(got => {
- if (got.os == "android") {
- return true;
- } else {
- return false;
- }
- });
-}
-
function SetHostText() {
var hostid = document.getElementById("hostText");
hostid.textContent = chrome.i18n.getMessage("hostText");
@@ -23,173 +12,6 @@ function SetControlHostText() {
var controlhostid = document.getElementById("controlHostText");
controlhostid.textContent = chrome.i18n.getMessage("controlHostText");
}
-/*
-var handleContextProxyRequest = async function(requestDetails) {
- console.log("(proxy)Searching for proxy by context");
- try {
- var handleProxyRequest = function(context) {
- proxy = {
- failoverTimeout: 0,
- proxyDns: false
- };
- if (context != undefined) {
- if (context.name == "i2pbrowser") {
- proxy = {
- type: getScheme(),
- host: getHost(),
- port: getPort()
- };
- console.log(
- "(proxy)",
- context.name,
- "Using",
- proxy.type,
- "proxy ",
- proxy.host + ":" + proxy.port
- );
- return proxy;
- } else if (context.name == "routerconsole") {
- if (routerHost(requestDetails.url)) {
- return proxy;
- } else if (!routerHost(requestDetails.url)) {
- proxy = {
- type: "http",
- host: "localhost",
- port: "65535"
- };
- }
- proxy = {
- type: getScheme(),
- host: getHost(),
- port: getPort()
- };
- console.log(
- "(proxy)",
- context.name,
- "Using",
- proxy.type,
- "proxy ",
- proxy.host + ":" + proxy.port
- );
- return proxy;
- } else if (context.name == "fenced-default") {
- if (localHost(requestDetails.url)) {
- if (!routerHost(requestDetails.url)) {
- proxy = {
- type: "http",
- host: "localhost",
- port: "65535"
- };
- }
- }
- console.log(
- "(proxy)",
- context.name,
- "Using",
- proxy.type,
- "proxy ",
- proxy.host + ":" + proxy.port
- );
- return proxy;
- }
- }
- if (!routerHost(requestDetails.url)) {
- proxy = {
- type: "http",
- host: "localhost",
- port: "65535"
- };
- } else if (i2pHost(requestDetails.url)) {
- proxy = {
- type: getScheme(),
- host: getHost(),
- port: getPort()
- };
- }
- return proxy;
- };
- var contextGet = async function(tabInfo) {
- try {
- console.log("(proxy)Tab info from Function", tabInfo);
- context = await browser.contextualIdentities.get(tabInfo.cookieStoreId);
- return context;
- } catch (error) {
- console.log("(proxy)Context Error", error);
- }
- };
- var tabFind = async function(tabId) {
- try {
- context = await browser.contextualIdentities.query({
- name: "i2pbrowser"
- });
- tabId.cookieStoreId = context[0].cookieStoreId;
- console.log("(proxy) forcing context", tabId.cookieStoreId);
- return tabId;
- } catch (error) {
- console.log("(proxy)Context Error", error);
- }
- };
- var tabGet = async function(tabId) {
- try {
- console.log("(proxy)Tab ID from Request", tabId);
- let tabInfo = await browser.tabs.get(tabId);
- return tabInfo;
- } catch (error) {
- console.log("(proxy)Tab error", error);
- }
- };
-
- if (requestDetails.tabId > 0) {
- if (proxyHost(requestDetails.url)) {
- console.log("(Proxy)I2P Proxy test URL detected, ", requestDetails.url);
- return {
- type: getScheme(),
- host: getHost(),
- port: getPort()
- };
- } else if (i2pHost(requestDetails.url)) {
- console.log("(Proxy)I2P URL detected, ");
- var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(tabFind);
- requestDetails.tabId = mtab;
- var context = mtab.then(contextGet);
- var proxy = await context.then(handleProxyRequest);
- console.log("(proxy)Returning I2P Proxy", proxy);
- return proxy;
- } else {
- var tab = tabGet(requestDetails.tabId);
- var context = tab.then(contextGet);
- var proxy = await context.then(handleProxyRequest);
- console.log("(proxy)Returning I2P Proxy", proxy);
- return proxy;
- }
- proxy = {
- type: getScheme(),
- host: getHost(),
- port: getPort()
- };
- console.log("(proxy)Returning I2P Proxy", proxy);
- return proxy;
- }
- } catch (error) {
- console.log("(proxy)Not using I2P Proxy.", error);
- }
-};
-
-function setupProxy() {
- var controlHost = getControlHost();
- var controlPort = getControlPort();
- var Host = getHost();
- var Port = getPort();
- var Scheme = getScheme();
-
- console.log("Setting up Firefox WebExtension proxy");
- browser.proxy.onRequest.addListener(handleContextProxyRequest, {
- urls: [""]
- });
- console.log("i2p settings created for WebExtension Proxy");
-}
-*/
function SetControlPortText() {
var controlportid = document.getElementById("controlPortText");
@@ -454,7 +276,6 @@ chrome.storage.local.get(function(got) {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os != "android") {
- browser.windows.getAll().then(wins => wins.forEach(themeWindow));
chrome.storage.local.get(function(got) {
checkStoredSettings(got);
updateUI(got);
diff --git a/proxy.js b/proxy.js
index 961ffd8..e99740a 100644
--- a/proxy.js
+++ b/proxy.js
@@ -188,6 +188,63 @@ var handleContextProxyRequest = async function(requestDetails) {
};
var proxy_scheme = "HTTP";
+var proxy_host = "127.0.0.1";
+var proxy_port = "4444";
+var control_host = "127.0.0.1";
+var control_port = "4444";
+
+function SetupSettings() {
+ console.log("Initialising Settings");
+ //
+ function checkSchemeStoredSettings(storedSettings) {
+ console.log("Initialising Proxy Scheme", storedSettings.proxy_scheme);
+ proxy_scheme = storedSettings.proxy_scheme;
+ }
+ var gettingSchemeStoredSettings = browser.storage.local.get("proxy_scheme");
+ gettingSchemeStoredSettings.then(checkSchemeStoredSettings, onError);
+
+ //
+ function checkHostStoredSettings(storedSettings) {
+ console.log("Initialising Host", storedSettings.proxy_host);
+ proxy_host = storedSettings.proxy_host;
+ }
+ var gettingHostStoredSettings = browser.storage.local.get("proxy_host");
+ gettingHostStoredSettings.then(checkHostStoredSettings, onError);
+
+ //
+ function checkPortStoredSettings(storedSettings) {
+ console.log("Initialising Port", storedSettings.proxy_port);
+ proxy_port = storedSettings.proxy_port;
+ }
+ var gettingPortStoredSettings = browser.storage.local.get("proxy_port");
+ gettingPortStoredSettings.then(checkPortStoredSettings, onError);
+
+ //
+ function checkControlHostStoredSettings(storedSettings) {
+ console.log("Initialising Control Host", storedSettings.control_host);
+ proxy_host = storedSettings.control_host;
+ }
+ var gettingControlHostStoredSettings = browser.storage.local.get(
+ "control_host"
+ );
+ gettingControlHostStoredSettings.then(
+ checkControlHostStoredSettings,
+ onError
+ );
+
+ //
+ function checkControlPortStoredSettings(storedSettings) {
+ console.log("Initialising Control Port", storedSettings.control_port);
+ proxy_port = storedSettings.control_port;
+ }
+ var gettingControlPortStoredSettings = browser.storage.local.get(
+ "control_port"
+ );
+ gettingControlPortStoredSettings.then(
+ checkControlPortStoredSettings,
+ onError
+ );
+}
function getScheme() {
if (proxy_scheme == undefined) {
@@ -206,13 +263,6 @@ function getScheme() {
return proxy_scheme;
}
-/*
-var proxy_host = "127.0.0.1";
-var proxy_port = "4444";
-var control_host = "127.0.0.1";
-var control_port = "4444";
-*/
-
function getHost() {
if (proxy_host == undefined) {
proxy_host = "127.0.0.1";
@@ -262,187 +312,33 @@ function setupProxy() {
/**/
}
-function checkStoredSettings(storedSettings) {
- function gotProxyInfo(info) {
- let defaultSettings = {};
- let host = info.value.http.split(":")[0];
- let port = info.value.http.split(":")[1];
- console.log("proxy", "'" + host + "'", ":", port);
- if (!storedSettings.proxy_scheme) {
- defaultSettings["proxy_scheme"] = "http";
- }
- if (!storedSettings.proxy_host) {
- if (host == "") {
- defaultSettings["proxy_host"] = "127.0.0.1";
- } else {
- defaultSettings["proxy_host"] = host;
- }
- } else {
- if (host != "") {
- defaultSettings["proxy_host"] = host;
- } else {
- defaultSettings["proxy_host"] = storedSettings.proxy_host;
- }
- }
- if (!storedSettings.proxy_port) {
- if (port == undefined) {
- defaultSettings["proxy_port"] = 4444;
- } else {
- defaultSettings["proxy_port"] = port;
- }
- } else {
- if (port != undefined) {
- defaultSettings["proxy_port"] = port;
- } else {
- defaultSettings["proxy_port"] = storedSettings.proxy_port;
- }
- }
- if (!storedSettings.control_host) {
- if (host == "") {
- defaultSettings["control_host"] = "127.0.0.1";
- } else {
- defaultSettings["control_host"] = host;
- }
- } else {
- if (host != "") {
- defaultSettings["control_host"] = host;
- } else {
- defaultSettings["control_host"] = storedSettings.control_host;
- }
- }
- if (!storedSettings.control_port) {
- if (port == undefined) {
- defaultSettings["control_port"] = 4444;
- } else {
- defaultSettings["control_port"] = port;
- }
- } else {
- if (port != undefined) {
- defaultSettings["control_port"] = port;
- } else {
- defaultSettings["control_port"] = storedSettings.control_port;
- }
- }
- console.log("(browserinfo) NATIVE PROXYSETTINGS", info.value);
- console.log(
- defaultSettings["proxy_host"],
- defaultSettings["proxy_port"],
- defaultSettings["control_host"],
- defaultSettings["control_port"]
- );
- chrome.storage.local.set(defaultSettings);
- }
- var gettingInfo = browser.proxy.settings.get({});
- gettingInfo.then(gotProxyInfo);
-}
-
-function checkAndroidStoredSettings(storedSettings) {
- let defaultSettings = {};
- let host = "";
- let port = "";
- console.log("proxy", "'" + host + "'", ":", port);
- if (!storedSettings.proxy_scheme) {
- defaultSettings["proxy_scheme"] = "http";
- }
- if (!storedSettings.proxy_host) {
- if (host == "") {
- defaultSettings["proxy_host"] = "127.0.0.1";
- } else {
- defaultSettings["proxy_host"] = host;
- }
- } else {
- if (host != "") {
- defaultSettings["proxy_host"] = host;
- } else {
- defaultSettings["proxy_host"] = storedSettings.proxy_host;
- }
- }
- if (!storedSettings.proxy_port) {
- if (port == undefined) {
- defaultSettings["proxy_port"] = 4444;
- } else {
- defaultSettings["proxy_port"] = port;
- }
- } else {
- if (port != undefined) {
- defaultSettings["proxy_port"] = port;
- } else {
- defaultSettings["proxy_port"] = storedSettings.proxy_port;
- }
- }
- if (!storedSettings.control_host) {
- if (host == "") {
- defaultSettings["control_host"] = "127.0.0.1";
- } else {
- defaultSettings["control_host"] = host;
- }
- } else {
- if (host != "") {
- defaultSettings["control_host"] = host;
- } else {
- defaultSettings["control_host"] = storedSettings.control_host;
- }
- }
- if (!storedSettings.control_port) {
- if (port == undefined) {
- defaultSettings["control_port"] = 4444;
- } else {
- defaultSettings["control_port"] = port;
- }
- } else {
- if (port != undefined) {
- defaultSettings["control_port"] = port;
- } else {
- defaultSettings["control_port"] = storedSettings.control_port;
- }
- }
- console.log(
- defaultSettings["proxy_host"],
- defaultSettings["proxy_port"],
- defaultSettings["control_host"],
- defaultSettings["control_port"]
- );
- chrome.storage.local.set(defaultSettings);
-}
-
-//function gotProxyInfo(info) {
-//console.log("(browserinfo)", info.value);
-//}
-
-//var gettingInfo = browser.proxy.settings.get({});
-//gettingInfo.then(gotProxyInfo);
-
-function update(restoredSettings) {
- proxy_scheme = restoredSettings.proxy_scheme;
+function update() {
console.log("restoring proxy scheme:", proxy_scheme);
- proxy_host = restoredSettings.proxy_host;
console.log("restoring proxy host:", proxy_host);
- proxy_port = restoredSettings.proxy_port;
console.log("restoring proxy port:", proxy_port);
- control_host = restoredSettings.control_host;
console.log("restoring control host:", control_host);
- control_port = restoredSettings.control_port;
console.log("restoring control port:", control_port);
}
-// Theme all currently open windows
-if (!isDroid()) {
+function updateFromStorage() {
+ console.log("updating settings from storage");
+ var gettingInfo = browser.runtime.getPlatformInfo();
+ gettingInfo.then(got => {
+ if (got.os != "android") {
+ browser.windows.getAll().then(wins => wins.forEach(themeWindow));
+ chrome.storage.local.get(function(got) {
+ SetupSettings();
+ update();
+ setupProxy();
+ });
+ } else {
+ chrome.storage.local.get(function(got) {
+ SetupSettings();
+ update();
+ setupProxy();
+ });
+ }
+ });
}
-var gettingInfo = browser.runtime.getPlatformInfo();
-gettingInfo.then(got => {
- if (got.os != "android") {
- browser.windows.getAll().then(wins => wins.forEach(themeWindow));
- chrome.storage.local.get(function(got) {
- checkStoredSettings(got);
- update(got);
- setupProxy();
- });
- } else {
- chrome.storage.local.get(function(got) {
- checkAndroidStoredSettings(got);
- update(got);
- setupProxy();
- });
- }
-});
+browser.storage.onChanged.addListener(updateFromStorage);
From 2fab8e042f23b8d5a5d337adec2a63a4ba03345f Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 20:57:41 -0500
Subject: [PATCH 21/37] pretty sure that'll fix it
---
background.js | 1 +
context.js | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/background.js b/background.js
index 8cbe2c0..f697ade 100644
--- a/background.js
+++ b/background.js
@@ -81,6 +81,7 @@ function onCreated(context) {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
if (got.os == "android") {
+ browser.contextualIdentities.query({}).then(onContextsGot, onError);
} else {
browser.windows.onCreated.addListener(() => {
browser.contextualIdentities.query({}).then(onContextsGot, onError);
diff --git a/context.js b/context.js
index 5df468b..b1712dc 100644
--- a/context.js
+++ b/context.js
@@ -1,4 +1,5 @@
//var windowIds = []
+var titlepref = chrome.i18n.getMessage("titlePreface");
function onError(error) {
console.log(`Error: ${error}`);
@@ -51,7 +52,7 @@ if (browser.contextualIdentities === undefined) {
} else {
browser.contextualIdentities
.query({
- name: "I2P Browser"
+ name: titlepref
})
.then(identities => {
if (!identities.length) {
From 232ada5ed357b81f246135cf4c2888e65f41ef29 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 22:18:27 -0500
Subject: [PATCH 22/37] no but closer
---
scrub.js | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/scrub.js b/scrub.js
index 0ed6c77..e24527d 100644
--- a/scrub.js
+++ b/scrub.js
@@ -16,7 +16,7 @@ var contextScrub = async function(requestDetails) {
try {
var headerScrub = function(context) {
if (!context) {
- console.error("Context not found");
+ console.error("Context not found", context);
} else if (context.name == titlepref) {
var ua = "MYOB/6.66 (AN/ON)";
if (i2pHost(requestDetails.url)) {
@@ -122,7 +122,6 @@ var contextSetup = async function(requestDetails) {
"(isolate) forcing I2P Browsing",
requestDetails.url,
" context",
- tabId.cookieStoreId,
context[0].cookieStoreId
);
function Create(window) {
@@ -155,7 +154,6 @@ var contextSetup = async function(requestDetails) {
"(isolate) forcing Router Console",
requestDetails.url,
" context",
- tabId.cookieStoreId,
context[0].cookieStoreId
);
function Create(window) {
@@ -190,7 +188,6 @@ var contextSetup = async function(requestDetails) {
"(isolate) forcing HSM context",
requestDetails.url,
" context",
- tabId.cookieStoreId,
context[0].cookieStoreId
);
function Create(window) {
@@ -224,7 +221,6 @@ var contextSetup = async function(requestDetails) {
"(isolate) forcing Bittorrent",
requestDetails.url,
" context",
- tabId.cookieStoreId,
context[0].cookieStoreId
);
function Create(window) {
@@ -257,7 +253,6 @@ var contextSetup = async function(requestDetails) {
"(isolate) forcing Web Mail",
requestDetails.url,
" context",
- tabId.cookieStoreId,
context[0].cookieStoreId
);
function Create(window) {
@@ -295,7 +290,6 @@ var contextSetup = async function(requestDetails) {
"(isolate) forcing Web Browsing",
requestDetails.url,
" context",
- tabId.cookieStoreId,
context[0].cookieStoreId
);
function Create(window) {
From 5b6224f9ce19b289899369e8b6c94152bec32fd6 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 22:23:13 -0500
Subject: [PATCH 23/37] no but closer
---
scrub.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/scrub.js b/scrub.js
index e24527d..24cfcb6 100644
--- a/scrub.js
+++ b/scrub.js
@@ -63,7 +63,6 @@ var contextScrub = async function(requestDetails) {
console.log(
"(scrub) forcing context",
titlepref,
- tabId.cookieStoreId,
"=>",
context[0].cookieStoreId
);
From b23b90baa1d0c737a32d56646347c54a166adee5 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 22:32:12 -0500
Subject: [PATCH 24/37] no but closer
---
scrub.js | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/scrub.js b/scrub.js
index 24cfcb6..5ee2cae 100644
--- a/scrub.js
+++ b/scrub.js
@@ -89,15 +89,15 @@ var contextScrub = async function(requestDetails) {
if (i2pHost(requestDetails.url)) {
console.log("(Proxy)I2P URL detected, ");
tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(tabFind);
- context = mtab.then(contextGet);
- req = await context.then(headerScrub);
+ var mtab = tab.then(tabFind, onError);
+ context = mtab.then(contextGet, onError);
+ req = await context.then(headerScrub, onError);
console.log("(scrub)Scrubbing I2P Request", req);
return req;
} else if (routerHost(requestDetails.url)) {
tab = tabGet(requestDetails.tabId);
- context = tab.then(contextGet);
- req = await context.then(headerScrub);
+ context = tab.then(contextGet, onError);
+ req = await context.then(headerScrub, onError);
console.log("(scrub)Scrubbing non-I2P Request", req);
return req;
}
@@ -136,7 +136,7 @@ var contextSetup = async function(requestDetails) {
created.then(onCreated, onError);
}
var getting = browser.tabs.getCurrent();
- getting.then(Create);
+ getting.then(Create, onError);
return tabId;
}
} catch (error) {
@@ -170,7 +170,7 @@ var contextSetup = async function(requestDetails) {
created.then(onCreated, onError);
}
var getting = browser.tabs.getCurrent();
- getting.then(Create);
+ getting.then(Create, onError);
return tabId;
}
} catch (error) {
@@ -203,7 +203,7 @@ var contextSetup = async function(requestDetails) {
created.then(onCreated, onError);
}
var getting = browser.tabs.getCurrent();
- getting.then(Create);
+ getting.then(Create, onError);
return tabId;
}
} catch (error) {
@@ -235,7 +235,7 @@ var contextSetup = async function(requestDetails) {
created.then(onCreated, onError);
}
var getting = browser.tabs.getCurrent();
- getting.then(Create);
+ getting.then(Create, onError);
return tabId;
}
} catch (error) {
@@ -267,7 +267,7 @@ var contextSetup = async function(requestDetails) {
created.then(onCreated, onError);
}
var getting = browser.tabs.getCurrent();
- getting.then(Create);
+ getting.then(Create, onError);
return tabId;
}
} catch (error) {
@@ -304,7 +304,7 @@ var contextSetup = async function(requestDetails) {
created.then(onCreated, onError);
}
var getting = browser.tabs.getCurrent();
- getting.then(Create);
+ getting.then(Create, onError);
return tabId;
}
}
@@ -339,31 +339,31 @@ var contextSetup = async function(requestDetails) {
});
setcookie.then(onContextGotLog, onError);
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(tabFind);
+ var mtab = tab.then(tabFind, onError);
return requestDetails;
}
let routerhost = routerHost(requestDetails.url);
if (routerhost) {
if (routerhost === "i2ptunnelmgr") {
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(i2ptunnelTabFind);
+ var mtab = tab.then(i2ptunnelTabFind, onError);
return requestDetails;
} else if (routerhost === "i2psnark") {
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(snarkTabFind);
+ var mtab = tab.then(snarkTabFind, onError);
return requestDetails;
} else if (routerhost === "webmail") {
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(mailTabFind);
+ var mtab = tab.then(mailTabFind, onError);
return requestDetails;
} else if (routerhost === "routerconsole") {
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(routerTabFind);
+ var mtab = tab.then(routerTabFind, onError);
return requestDetails;
}
} else {
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(anyTabFind);
+ var mtab = tab.then(anyTabFind, onError);
return requestDetails;
}
}
From bd4c9c0658086e6b5ec5fe0d77f3e79198ff64d4 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 22:43:50 -0500
Subject: [PATCH 25/37] no but closer
---
scrub.js | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/scrub.js b/scrub.js
index 5ee2cae..48cab32 100644
--- a/scrub.js
+++ b/scrub.js
@@ -126,7 +126,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab", window);
- browser.tabs.remove(tabId.id);
+ browser.tabs.remove(window.id);
}
var created = browser.tabs.create({
active: true,
@@ -158,8 +158,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
- browser.tabs.remove(window.tabs[0].id);
+ browser.tabs.remove(window.id);
}
var created = browser.tabs.create({
active: true,
@@ -192,7 +191,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ browser.tabs.remove(window.id);
}
var created = browser.tabs.create({
active: true,
@@ -225,7 +224,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ browser.tabs.remove(window.id);
}
var created = browser.tabs.create({
active: true,
@@ -257,7 +256,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ browser.tabs.remove(window.id);
}
var created = browser.tabs.create({
active: true,
@@ -294,7 +293,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ browser.tabs.remove(window.id);
}
var created = browser.tabs.create({
active: true,
From b06facacb03795da29b5db9e836e13d108e155a8 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 22:50:43 -0500
Subject: [PATCH 26/37] no but closer
---
scrub.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/scrub.js b/scrub.js
index 48cab32..fe6e1d7 100644
--- a/scrub.js
+++ b/scrub.js
@@ -126,7 +126,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab", window);
- browser.tabs.remove(window.id);
+ browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -158,7 +158,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(window.id);
+ browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -191,7 +191,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(window.id);
+ browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -224,7 +224,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(window.id);
+ browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -256,7 +256,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(window.id);
+ browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -293,7 +293,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(window.id);
+ browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
From a33afc52d39cce89f67bce326bc41257efb314db Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 22:59:50 -0500
Subject: [PATCH 27/37] no but closer
---
scrub.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/scrub.js b/scrub.js
index fe6e1d7..81b3535 100644
--- a/scrub.js
+++ b/scrub.js
@@ -66,7 +66,6 @@ var contextScrub = async function(requestDetails) {
"=>",
context[0].cookieStoreId
);
- tabId.cookieStoreId = context[0].cookieStoreId;
return tabId;
} catch (error) {
console.log("(scrub)Context Error", error);
From 77f57d7f1ec506c7007841243c550764308ef2ac Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 23:04:49 -0500
Subject: [PATCH 28/37] no but closer
---
proxy.js | 11 -----------
scrub.js | 9 ---------
2 files changed, 20 deletions(-)
diff --git a/proxy.js b/proxy.js
index e99740a..c1bcb1d 100644
--- a/proxy.js
+++ b/proxy.js
@@ -127,17 +127,6 @@ var handleContextProxyRequest = async function(requestDetails) {
};
var tabFind = async function(tabId) {
try {
- context = await browser.contextualIdentities.query({
- name: titlepref
- });
- console.log(
- "(proxy) forcing context",
- titlepref,
- tabId.cookieStoreId,
- "=>",
- context[0].cookieStoreId
- );
- tabId.cookieStoreId = context[0].cookieStoreId;
return tabId;
} catch (error) {
console.log("(proxy)Context Error", error);
diff --git a/scrub.js b/scrub.js
index 81b3535..4c37899 100644
--- a/scrub.js
+++ b/scrub.js
@@ -57,15 +57,6 @@ var contextScrub = async function(requestDetails) {
};
var tabFind = async function(tabId) {
try {
- context = await browser.contextualIdentities.query({
- name: titlepref
- });
- console.log(
- "(scrub) forcing context",
- titlepref,
- "=>",
- context[0].cookieStoreId
- );
return tabId;
} catch (error) {
console.log("(scrub)Context Error", error);
From 89523390de984c209894bb2ed081c7da96c68c2d Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 23:14:01 -0500
Subject: [PATCH 29/37] no but closer
---
proxy.js | 3 ++-
scrub.js | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/proxy.js b/proxy.js
index c1bcb1d..b5b8f61 100644
--- a/proxy.js
+++ b/proxy.js
@@ -129,7 +129,8 @@ var handleContextProxyRequest = async function(requestDetails) {
try {
return tabId;
} catch (error) {
- console.log("(proxy)Context Error", error);
+ let tabInfo = await browser.tabs.getCurrent();
+ return tabInfo;
}
};
var tabGet = async function(tabId) {
diff --git a/scrub.js b/scrub.js
index 4c37899..74e160d 100644
--- a/scrub.js
+++ b/scrub.js
@@ -59,7 +59,8 @@ var contextScrub = async function(requestDetails) {
try {
return tabId;
} catch (error) {
- console.log("(scrub)Context Error", error);
+ let tabInfo = await browser.tabs.getCurrent();
+ return tabInfo;
}
};
var tabGet = async function(tabId) {
From 94f0124f0fa85e7a5a446639f7aae2bdda0fd7e3 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 23:16:48 -0500
Subject: [PATCH 30/37] no but closer
---
scrub.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/scrub.js b/scrub.js
index 74e160d..4c37899 100644
--- a/scrub.js
+++ b/scrub.js
@@ -59,8 +59,7 @@ var contextScrub = async function(requestDetails) {
try {
return tabId;
} catch (error) {
- let tabInfo = await browser.tabs.getCurrent();
- return tabInfo;
+ console.log("(scrub)Context Error", error);
}
};
var tabGet = async function(tabId) {
From acd7adc9c123710fc34a05c286be4c499e359120 Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 23:29:06 -0500
Subject: [PATCH 31/37] remove tabfind. Never create a window, ever.
---
proxy.js | 13 ++-----------
scrub.js | 15 ++++-----------
2 files changed, 6 insertions(+), 22 deletions(-)
diff --git a/proxy.js b/proxy.js
index b5b8f61..68a0bbd 100644
--- a/proxy.js
+++ b/proxy.js
@@ -125,14 +125,6 @@ var handleContextProxyRequest = async function(requestDetails) {
console.log("(proxy)Context Error", error);
}
};
- var tabFind = async function(tabId) {
- try {
- return tabId;
- } catch (error) {
- let tabInfo = await browser.tabs.getCurrent();
- return tabInfo;
- }
- };
var tabGet = async function(tabId) {
try {
console.log("(proxy)Tab ID from Request", tabId);
@@ -155,9 +147,8 @@ var handleContextProxyRequest = async function(requestDetails) {
} else if (i2pHost(requestDetails.url)) {
console.log("(Proxy)I2P URL detected, ");
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(tabFind);
- requestDetails.tabId = mtab;
- var context = mtab.then(contextGet);
+ requestDetails.tabId = tab;
+ var context = tab.then(contextGet);
var proxy = await context.then(handleProxyRequest);
console.log("(proxy)Returning I2P Proxy", proxy);
return proxy;
diff --git a/scrub.js b/scrub.js
index 4c37899..aac024d 100644
--- a/scrub.js
+++ b/scrub.js
@@ -55,19 +55,13 @@ var contextScrub = async function(requestDetails) {
console.log("(scrub)Context Error", error);
}
};
- var tabFind = async function(tabId) {
- try {
- return tabId;
- } catch (error) {
- console.log("(scrub)Context Error", error);
- }
- };
var tabGet = async function(tabId) {
try {
console.log("(scrub)Tab ID from Request", tabId);
let tabInfo = await browser.tabs.get(tabId);
return tabInfo;
} catch (error) {
+ console.log("(scrub)Context Error", error);
let tabInfo = await browser.tabs.getCurrent();
return tabInfo;
}
@@ -79,8 +73,7 @@ var contextScrub = async function(requestDetails) {
if (i2pHost(requestDetails.url)) {
console.log("(Proxy)I2P URL detected, ");
tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(tabFind, onError);
- context = mtab.then(contextGet, onError);
+ context = tab.then(contextGet, onError);
req = await context.then(headerScrub, onError);
console.log("(scrub)Scrubbing I2P Request", req);
return req;
@@ -101,7 +94,7 @@ var contextScrub = async function(requestDetails) {
var contextSetup = async function(requestDetails) {
console.log("(isolate)Forcing I2P requests into context");
try {
- var tabFind = async function(tabId) {
+ var i2pTabFind = async function(tabId) {
try {
var context = await browser.contextualIdentities.query({
name: titlepref
@@ -328,7 +321,7 @@ var contextSetup = async function(requestDetails) {
});
setcookie.then(onContextGotLog, onError);
var tab = tabGet(requestDetails.tabId);
- var mtab = tab.then(tabFind, onError);
+ var mtab = tab.then(i2pTabFind, onError);
return requestDetails;
}
let routerhost = routerHost(requestDetails.url);
From 4e00c72d5ff5adf24c1882420ad05f1668d62def Mon Sep 17 00:00:00 2001
From: idk
Date: Sun, 24 Nov 2019 23:44:33 -0500
Subject: [PATCH 32/37] remove tabfind. Never create a window, ever.
---
scrub.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scrub.js b/scrub.js
index aac024d..fe98a5c 100644
--- a/scrub.js
+++ b/scrub.js
@@ -62,8 +62,8 @@ var contextScrub = async function(requestDetails) {
return tabInfo;
} catch (error) {
console.log("(scrub)Context Error", error);
- let tabInfo = await browser.tabs.getCurrent();
- return tabInfo;
+ //let tabInfo = await browser.tabs.getCurrent();
+ //return tabInfo;
}
};
if (requestDetails.tabId > 0) {
From ab7774ea29c0d6140d4615c79e6310bb59bc32e8 Mon Sep 17 00:00:00 2001
From: idk
Date: Mon, 25 Nov 2019 20:19:44 -0500
Subject: [PATCH 33/37] enable-disable history, don't try to kill undefined
tabs
---
home.css | 24 +++++-------
home.html | 18 ++++-----
home.js | 16 ++++++++
info.js | 93 +++++++++++++++++++++++++++-------------------
options/options.js | 3 --
platform.js | 39 +++++++++++++------
privacy.js | 86 +++++++++++++++++++++++++++++-------------
proxy.js | 56 +++++++++++++++++++++++++---
scrub.js | 12 +++---
window.html | 15 +++++---
10 files changed, 245 insertions(+), 117 deletions(-)
diff --git a/home.css b/home.css
index 197cea7..1f4f934 100644
--- a/home.css
+++ b/home.css
@@ -76,8 +76,10 @@ p {
border: 1px solid #d9d9d6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff,0 0 1px #ccc;
- background: #f8f8ff
+ background: #f8f8ff;
+ min-width: 95%
}
+.application-info,
.extended-info {
min-height: 3rem;
padding: 1rem;
@@ -87,17 +89,7 @@ p {
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff,0 0 1px #ccc;
background: #f8f8ff;
- min-width: 50%
-}
-.application-info {
- min-height: 3rem;
- padding: 1rem;
- margin-top: 1.5rem;
- display: inline-block;
- border: 1px solid #d9d9d6;
- border-radius: 2px;
- box-shadow: inset 0 0 0 1px #fff,0 0 1px #ccc;
- background: #f8f8ff
+ min-width: 95%
}
h1 {
margin-right: auto;
@@ -269,11 +261,15 @@ li {
}
.onboardingContent {
font-size: .8rem!important;
- text-align: left
+ text-align: left;
+ display: none
}
#proxy-check {
visibility: hidden
}
+#info-content {
+ display: none
+}
.consoleOn:hover #proxy-check,
.proxyReady:hover #proxy-check {
visibility: visible;
@@ -283,7 +279,7 @@ img.readyness {
height: 100%;
width: auto
}
-@media only screen and (min-width: 768px) {
+@media only screen and (max-width: 399px) {
.application-info {
display: none
}
diff --git a/home.html b/home.html
index 5eb40f1..8099a37 100644
--- a/home.html
+++ b/home.html
@@ -32,15 +32,15 @@
New to I2P? Learn more here.
-
Protect your Privacy
+
Protect your Privacy
I2P Browser allows you to surf the internet using the private and secure I2P network. When using it, you are protected against tracking, surveillance, and censorship as a first-class participant in the I2P network. I2P Browser isolates cookies and deletes your browser history after your session. These modifications ensure your privacy and security are protected in the browser.
-
Configure your Experience
+
Configure your Experience
We also provide you with additional settings for bumping up your browser security. Our Security Settings allow you to block elements that could be used to attack your computer. Click below to see what the different options do. Note: By default, NoScript and HTTPS Everywhere are not included on the toolbar, but you can customize your toolbar to add them. With all the security and privacy features provided by I2P, your experience while browsing the internet may be a little different. Things may be a bit slower, and depending on your security level, some elements may not work or load. You may also be asked to prove you are a human and not a robot.
-
Share Files
+
Share Files
I2P is capable of using peer-to-peer applications like BitTorrent, protecting your identity when you share files. Our anonymous bittorrent client is available in the browser.
-
Hidden e-mail
+
Hidden e-mail
There is also an anonymous e-mail service available inside of I2P, which is accessible from our browser via the menu directly below.
-
Experience Tips
+
Experience Tips
With all the security and privacy features provided by I2P, your experience while browsing the internet may be a little different. Things may be a bit slower, and depending on your security level, some elements may not work or load. You may also be asked to prove you are a human and not a robot.
@@ -49,17 +49,17 @@
Applications
These applications use I2P to provide them with security and privacy.
-
Links
+
Links
If you want to get more information about I2P, you can visit these links.
diff --git a/home.js b/home.js
index 5d1e8fb..d77c141 100644
--- a/home.js
+++ b/home.js
@@ -1,3 +1,19 @@
+document.addEventListener("click", e => {
+ if (e.target.id === "onboardingButtonZero") {
+ flipVisibility("onboardingContentZero");
+ } else if (e.target.id === "onboardingButtonOne") {
+ flipVisibility("onboardingContentOne");
+ } else if (e.target.id === "onboardingButtonTwo") {
+ flipVisibility("onboardingContentTwo");
+ } else if (e.target.id === "onboardingButtonThree") {
+ flipVisibility("onboardingContentThree");
+ } else if (e.target.id === "onboardingButtonFour") {
+ flipVisibility("onboardingContentFour");
+ } else if (e.target.id === "fliplinks") {
+ flipVisibility("info-content");
+ }
+});
+
function flipVisibility(div) {
var x = document.getElementById(div);
if (x.style.display === "none") {
diff --git a/info.js b/info.js
index 9380641..86eed14 100644
--- a/info.js
+++ b/info.js
@@ -1,3 +1,25 @@
+function checkPeerConnection() {
+ var getting = browser.privacy.network.peerConnectionEnabled.get({});
+ getting.then(got => {
+ webrtc = got.value;
+ console.log("checking webrtc", webrtc);
+ document.getElementById("enable-web-rtc").checked = webrtc;
+ });
+}
+
+checkPeerConnection();
+
+function checkHistory() {
+ var getting = browser.storage.local.get("disable_history");
+ getting.then(got => {
+ disable_history = got.disable_history;
+ console.log("checking history", disable_history);
+ document.getElementById("disable-history").checked = disable_history;
+ });
+}
+
+checkHistory();
+
document.addEventListener("click", e => {
if (e.target.id === "window-create-help-panel") {
let createData = {
@@ -52,6 +74,15 @@ document.addEventListener("click", e => {
} else {
browser.runtime.sendMessage({ rtc: "disableWebRTC" });
}
+ //checkPeerConnection()
+ return;
+ } else if (e.target.id === "disable-history") {
+ if (e.target.checked) {
+ browser.runtime.sendMessage({ history: "disableHistory" });
+ } else {
+ browser.runtime.sendMessage({ history: "enableHistory" });
+ }
+ //checkHistory()
return;
}
@@ -62,6 +93,8 @@ function proxyReadiness() {
console.log(this.responseText);
}
+browser.history.onVisited.addListener(onVisited);
+
function goHome() {
function gotProxyInfo(info) {
let host = info.value.http.split(":")[0];
@@ -109,44 +142,26 @@ function goSnark() {
console.log("visiting homepage");
let creating = browser.tabs.create(createData);
}
-/*
-//document.addEventListener("onpageshow", e => {
-console.log("(Check) Checking Proxy Readiness");
-const Http = new XMLHttpRequest();
-Http.addEventListener("load", proxyReadiness);
-const url = "http://proxy.i2p"; ///themes/console/images/favicon.ico";
-Http.open("GET", url);
-Http.send();
-//});
-function transferComplete(evt) {
- console.log(
- "The transfer is complete.",
- this.status,
- this.statusText,
- this.responseText
- );
+function onVisited(historyItem) {
+ function onCleaned(results) {
+ if (!results.length) {
+ console.log(" was removed");
+ } else {
+ console.log(" was not removed");
+ }
+ }
+
+ function onRemoved() {
+ var searching = browser.history.search({
+ text: historyItem.url,
+ startTime: 0
+ });
+ searching.then(onCleaned);
+ }
+ if (!history) {
+ if (i2pHost(historyItem.url))
+ var deletingUrl = browser.history.deleteUrl(historyItem.url);
+ deletingUrl.then(onRemoved);
+ }
}
-
-function transferFailed(evt) {
- console.log(
- "An error occurred while transferring the file.",
- this.status,
- this.statusText,
- this.responseText
- );
-}
-
-function transferCanceled(evt) {
- console.log(
- "The transfer has been canceled by the user.",
- this.status,
- this.statusText,
- this.responseText
- );
-}
-
-Http.addEventListener("load", transferComplete);
-Http.addEventListener("error", transferFailed);
-Http.addEventListener("abort", transferCanceled);
-*/
diff --git a/options/options.js b/options/options.js
index bd699ab..21b8ad5 100644
--- a/options/options.js
+++ b/options/options.js
@@ -269,9 +269,6 @@ function updateUI(restoredSettings) {
function onError(e) {
console.error(e);
}
-chrome.storage.local.get(function(got) {
- checkStoredSettings(got);
-});
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then(got => {
diff --git a/platform.js b/platform.js
index a298fa5..9108c80 100644
--- a/platform.js
+++ b/platform.js
@@ -1,13 +1,30 @@
+var titlepref = chrome.i18n.getMessage("titlePreface");
+var titleprefpriv = chrome.i18n.getMessage("titlePrefacePrivate");
+var webpref = chrome.i18n.getMessage("webPreface");
+var webprefpriv = chrome.i18n.getMessage("webPrefacePrivate");
+var routerpref = chrome.i18n.getMessage("routerPreface");
+var routerprefpriv = chrome.i18n.getMessage("routerPrefacePrivate");
+var mailpref = chrome.i18n.getMessage("mailPreface");
+var mailprefpriv = chrome.i18n.getMessage("mailPrefacePrivate");
+var torrentpref = chrome.i18n.getMessage("torrentPreface");
+var torrentprefpriv = chrome.i18n.getMessage("torrentPrefacePrivate");
+var tunnelpref = chrome.i18n.getMessage("i2ptunnelPreface");
+var tunnelprefpriv = chrome.i18n.getMessage("i2ptunnelPrefacePrivate");
+
+var android = false;
+
+var gettingInfo = browser.runtime.getPlatformInfo();
+gettingInfo.then(got => {
+ if (got.os == "android") {
+ console.log("Running in Android detected");
+ android = true;
+ return true;
+ } else {
+ console.log("Running in Desktop detected");
+ return false;
+ }
+});
+
function isDroid() {
- var gettingInfo = browser.runtime.getPlatformInfo();
- gettingInfo.then(got => {
- if (got.os == "android") {
- console.log("Running in Android detected");
- return true;
- } else {
- console.log("Running in Desktop detected");
- return false;
- }
- });
- return false;
+ return android;
}
diff --git a/privacy.js b/privacy.js
index aaafee9..6cdaf96 100644
--- a/privacy.js
+++ b/privacy.js
@@ -139,32 +139,40 @@ function setAllPrivacy() {
setAllPrivacy();
function ResetPeerConnection() {
- browser.privacy.network.peerConnectionEnabled.set({
- value: false
- });
- browser.privacy.network.networkPredictionEnabled.set({
- value: false
- });
- chrome.privacy.network.webRTCIPHandlingPolicy.set({
- value: "proxy_only"
+ var webrtc = false;
+ var rtc = browser.privacy.network.peerConnectionEnabled.set({
+ value: webrtc
});
+ rtc.then(AssurePeerConnection);
console.log("Re-disabled WebRTC");
}
function EnablePeerConnection() {
- browser.privacy.network.peerConnectionEnabled.set({
- value: true
- });
- browser.privacy.network.networkPredictionEnabled.set({
- value: false
- });
- chrome.privacy.network.webRTCIPHandlingPolicy.set({
- value: "disable_non_proxied_udp"
+ var webrtc = true;
+ rtc = browser.privacy.network.peerConnectionEnabled.set({
+ value: webrtc
});
+ rtc.then(AssurePeerConnection);
console.log("Enabled WebRTC");
}
-ResetPeerConnection();
+function AssurePeerConnection() {
+ function assure(webrtc) {
+ browser.privacy.network.peerConnectionEnabled.set({
+ value: webrtc.value
+ });
+ browser.privacy.network.networkPredictionEnabled.set({
+ value: false
+ });
+ chrome.privacy.network.webRTCIPHandlingPolicy.set({
+ value: "proxy_only"
+ });
+ }
+ rtc = browser.privacy.network.peerConnectionEnabled.get({});
+ rtc.then(assure);
+}
+
+AssurePeerConnection();
function ResetDisableSavePasswords() {
browser.privacy.services.passwordSavingEnabled.set({
@@ -196,13 +204,6 @@ function onError(e) {
console.error(e);
}
-function checkStoredSettings(storedSettings) {
- chrome.storage.local.set(appSettings);
-}
-
-const gettingStoredSettings = browser.storage.local.get();
-gettingStoredSettings.then(checkStoredSettings, onError);
-
function clearCookiesContext(cookieStoreId) {}
function forgetBrowsingData(storedSettings) {
@@ -348,13 +349,48 @@ function onContextGotLog(contexts) {
browser.runtime.onMessage.addListener(message);
+function enableHistory() {
+ function checkStoredSettings(storedSettings) {
+ storedSettings["disable_history"] = false;
+ console.log(storedSettings);
+ function enablehistory(settings) {
+ console.log("Store History:", storedSettings);
+ }
+ var setting = browser.storage.local.set(storedSettings);
+ setting.then(enablehistory);
+ }
+ const gettingStoredSettings = browser.storage.local.get();
+ gettingStoredSettings.then(checkStoredSettings, onError);
+}
+
+function disableHistory() {
+ function checkStoredSettings(storedSettings) {
+ storedSettings["disable_history"] = true;
+ console.log(storedSettings);
+ function enablehistory(settings) {
+ console.log("Store History:", storedSettings);
+ }
+ var setting = browser.storage.local.set(storedSettings);
+ setting.then(enablehistory);
+ }
+ const gettingStoredSettings = browser.storage.local.get();
+ gettingStoredSettings.then(checkStoredSettings, onError);
+}
+
function message(message) {
console.log(message);
if (message.rtc === "enableWebRTC") {
console.log("enableWebRTC");
EnablePeerConnection();
- } else {
+ } else if (message.rtc === "disableWebRTC") {
console.log("disableWebRTC");
ResetPeerConnection();
}
+ if (message.history === "enableHistory") {
+ console.log("enableHistory");
+ enableHistory();
+ } else if (message.history === "disableHistory") {
+ console.log("disableHistory");
+ disableHistory();
+ }
}
diff --git a/proxy.js b/proxy.js
index 68a0bbd..f61c34b 100644
--- a/proxy.js
+++ b/proxy.js
@@ -1,4 +1,5 @@
var titlepref = chrome.i18n.getMessage("titlePreface");
+var titleprefpriv = chrome.i18n.getMessage("titlePrefacePrivate");
var webpref = chrome.i18n.getMessage("webPreface");
var webprefpriv = chrome.i18n.getMessage("webPrefacePrivate");
var routerpref = chrome.i18n.getMessage("routerPreface");
@@ -173,37 +174,58 @@ var proxy_host = "127.0.0.1";
var proxy_port = "4444";
var control_host = "127.0.0.1";
var control_port = "4444";
+var disable_history = false;
function SetupSettings() {
console.log("Initialising Settings");
//
function checkSchemeStoredSettings(storedSettings) {
+ if (storedSettings.proxy_scheme != undefined) {
+ proxy_scheme = storedSettings.proxy_scheme;
+ } else {
+ proxy_scheme = "http";
+ storedSettings.proxy_scheme = proxy_scheme;
+ }
console.log("Initialising Proxy Scheme", storedSettings.proxy_scheme);
- proxy_scheme = storedSettings.proxy_scheme;
}
var gettingSchemeStoredSettings = browser.storage.local.get("proxy_scheme");
gettingSchemeStoredSettings.then(checkSchemeStoredSettings, onError);
//
function checkHostStoredSettings(storedSettings) {
+ if (storedSettings.proxy_host != undefined) {
+ proxy_host = storedSettings.proxy_host;
+ } else {
+ proxy_host = "127.0.0.1";
+ storedSettings.proxy_host = proxy_host;
+ }
console.log("Initialising Host", storedSettings.proxy_host);
- proxy_host = storedSettings.proxy_host;
}
var gettingHostStoredSettings = browser.storage.local.get("proxy_host");
gettingHostStoredSettings.then(checkHostStoredSettings, onError);
//
function checkPortStoredSettings(storedSettings) {
+ if (storedSettings.proxy_port != undefined) {
+ proxy_port = storedSettings.proxy_port;
+ } else {
+ proxy_port = "4444";
+ storedSettings.proxy_port = proxy_port;
+ }
console.log("Initialising Port", storedSettings.proxy_port);
- proxy_port = storedSettings.proxy_port;
}
var gettingPortStoredSettings = browser.storage.local.get("proxy_port");
gettingPortStoredSettings.then(checkPortStoredSettings, onError);
//
function checkControlHostStoredSettings(storedSettings) {
+ if (storedSettings.control_host != undefined) {
+ control_host = storedSettings.control_host;
+ } else {
+ control_host = "127.0.0.1";
+ storedSettings.control_host = control_host;
+ }
console.log("Initialising Control Host", storedSettings.control_host);
- proxy_host = storedSettings.control_host;
}
var gettingControlHostStoredSettings = browser.storage.local.get(
"control_host"
@@ -215,8 +237,13 @@ function SetupSettings() {
//
function checkControlPortStoredSettings(storedSettings) {
+ if (storedSettings.control_port != undefined) {
+ contro_port = storedSettings.control_port;
+ } else {
+ control_port = "4445";
+ storedSettings.control_port = control_port;
+ }
console.log("Initialising Control Port", storedSettings.control_port);
- proxy_port = storedSettings.control_port;
}
var gettingControlPortStoredSettings = browser.storage.local.get(
"control_port"
@@ -225,6 +252,24 @@ function SetupSettings() {
checkControlPortStoredSettings,
onError
);
+
+ //
+ function checkHistoryStoredSettings(storedSettings) {
+ if (storedSettings.disable_history != undefined) {
+ disable_history = storedSettings.disable_history;
+ } else {
+ disable_history = false;
+ storedSettings.disable_history = disable_history;
+ }
+ console.log(
+ "Initialising Disabled History",
+ storedSettings.disable_history
+ );
+ }
+ var gettingHistoryStoredSettings = browser.storage.local.get(
+ "disable_history"
+ );
+ gettingHistoryStoredSettings.then(checkHistoryStoredSettings, onError);
}
function getScheme() {
@@ -323,3 +368,4 @@ function updateFromStorage() {
}
browser.storage.onChanged.addListener(updateFromStorage);
+SetupSettings();
diff --git a/scrub.js b/scrub.js
index fe98a5c..afc778d 100644
--- a/scrub.js
+++ b/scrub.js
@@ -109,7 +109,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab", window);
- browser.tabs.remove(tabId.id);
+ if (tabId != undefined) browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -141,7 +141,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ if (tabId != undefined) browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -174,7 +174,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ if (tabId != undefined) browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -207,7 +207,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ if (tabId != undefined) browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -239,7 +239,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ if (tabId != undefined) browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
@@ -276,7 +276,7 @@ var contextSetup = async function(requestDetails) {
function Create(window) {
function onCreated(tab) {
console.log("(isolate) Closing old, un-isolated tab");
- browser.tabs.remove(tabId.id);
+ if (tabId != undefined) browser.tabs.remove(tabId.id);
}
var created = browser.tabs.create({
active: true,
diff --git a/window.html b/window.html
index 6029685..ba3d7ea 100644
--- a/window.html
+++ b/window.html
@@ -39,13 +39,18 @@
Enable WebRTC with Proxy?
- For more information about this extension, go here:
+ WebRTC is disabled by default, but can be enabled by checking this box.
+
+
+ Disable History in I2P Tabs
+ History is automatically cleared when your I2P tabs are closed. If you want to clear history as you go, check this box.
+
@@ -56,16 +61,16 @@
Applications
These applications use I2P to provide them with security and privacy.
-
+
Home Page For more information about this extension, go here:
-
+
Hidden Services Manager I2P has a web-based interface for configuring .i2p services like web sites, to set up your own web sites, go here:
-
+
E-Mail I2P also bundles a webmail client which can be used to access in-I2P e-mail. To use it, go here:
-
+
BitTorrent I2P is capable of anonymous Peer-to-Peer file sharing, to use the built-in bittorrent client go here:
From 352d71af267b0d45d942b0a157b9e8cc312e8ff6 Mon Sep 17 00:00:00 2001
From: idk
Date: Mon, 25 Nov 2019 20:20:27 -0500
Subject: [PATCH 34/37] enable-disable history, don't try to kill undefined
tabs
---
.../i2p_in_private_browsing-0.49-an+fx.xpi | Bin 0 -> 4383743 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 web-ext-artifacts/i2p_in_private_browsing-0.49-an+fx.xpi
diff --git a/web-ext-artifacts/i2p_in_private_browsing-0.49-an+fx.xpi b/web-ext-artifacts/i2p_in_private_browsing-0.49-an+fx.xpi
new file mode 100644
index 0000000000000000000000000000000000000000..9a197cb85aa31f059cc1055e016a75ab67474420
GIT binary patch
literal 4383743
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