Removal of more SDK code
This commit is contained in:
parent
4a97e07d43
commit
4d61fa190c
3 changed files with 201 additions and 163 deletions
247
index.js
247
index.js
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
const DEFAULT_TAB = "about:newtab";
|
const DEFAULT_TAB = "about:newtab";
|
||||||
|
const LOOKUP_KEY = "$ref";
|
||||||
|
|
||||||
const SHOW_MENU_TIMEOUT = 100;
|
const SHOW_MENU_TIMEOUT = 100;
|
||||||
const HIDE_MENU_TIMEOUT = 300;
|
const HIDE_MENU_TIMEOUT = 300;
|
||||||
|
@ -73,41 +74,43 @@ Cu.import("resource:///modules/CustomizableWidgets.jsm");
|
||||||
Cu.import("resource:///modules/sessionstore/SessionStore.jsm");
|
Cu.import("resource:///modules/sessionstore/SessionStore.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// ContextualIdentityProxy
|
// ContextualIdentityProxy
|
||||||
|
|
||||||
const ContextualIdentityProxy = {
|
const ContextualIdentityProxy = {
|
||||||
getIdentities() {
|
getIdentities() {
|
||||||
|
let response;
|
||||||
if ("getPublicIdentities" in ContextualIdentityService) {
|
if ("getPublicIdentities" in ContextualIdentityService) {
|
||||||
return ContextualIdentityService.getPublicIdentities();
|
response = ContextualIdentityService.getPublicIdentities();
|
||||||
|
} else {
|
||||||
|
response = ContextualIdentityService.getIdentities();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ContextualIdentityService.getIdentities();
|
return response.map((identity) => {
|
||||||
},
|
return this._convert(identity);
|
||||||
|
});
|
||||||
getUserContextLabel(userContextId) {
|
|
||||||
return ContextualIdentityService.getUserContextLabel(userContextId);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getIdentityFromId(userContextId) {
|
getIdentityFromId(userContextId) {
|
||||||
|
let response;
|
||||||
if ("getPublicIdentityFromId" in ContextualIdentityService) {
|
if ("getPublicIdentityFromId" in ContextualIdentityService) {
|
||||||
return ContextualIdentityService.getPublicIdentityFromId(userContextId);
|
response = ContextualIdentityService.getPublicIdentityFromId(userContextId);
|
||||||
|
} else {
|
||||||
|
response = ContextualIdentityService.getIdentityFromId(userContextId);
|
||||||
}
|
}
|
||||||
|
if (response) {
|
||||||
return ContextualIdentityService.getIdentityFromId(userContextId);
|
return this._convert(response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
},
|
},
|
||||||
|
|
||||||
create(name, icon, color) {
|
_convert(identity) {
|
||||||
return ContextualIdentityService.create(name, icon, color);
|
return {
|
||||||
|
name: ContextualIdentityService.getUserContextLabel(identity.userContextId),
|
||||||
|
icon: identity.icon,
|
||||||
|
color: identity.color,
|
||||||
|
userContextId: identity.userContextId,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
update(userContextId, name, icon, color) {
|
|
||||||
return ContextualIdentityService.update(userContextId, name, icon, color);
|
|
||||||
},
|
|
||||||
|
|
||||||
remove(userContextId) {
|
|
||||||
return ContextualIdentityService.remove(userContextId);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -149,7 +152,7 @@ const ContainerService = {
|
||||||
// Maybe rename the Banking container.
|
// Maybe rename the Banking container.
|
||||||
const identity = ContextualIdentityProxy.getIdentityFromId(3);
|
const identity = ContextualIdentityProxy.getIdentityFromId(3);
|
||||||
if (identity && identity.l10nID === "userContextBanking.label") {
|
if (identity && identity.l10nID === "userContextBanking.label") {
|
||||||
ContextualIdentityProxy.update(identity.userContextId,
|
ContextualIdentityService.update(identity.userContextId,
|
||||||
"Finance",
|
"Finance",
|
||||||
identity.icon,
|
identity.icon,
|
||||||
identity.color);
|
identity.color);
|
||||||
|
@ -167,6 +170,18 @@ const ContainerService = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TOCHECK should this run on all code
|
||||||
|
ContextualIdentityProxy.getIdentities().forEach(identity => {
|
||||||
|
const newIcon = this._fromIconToName(identity.icon);
|
||||||
|
const newColor = this._fromColorToName(identity.color);
|
||||||
|
if (newIcon !== identity.icon || newColor !== identity.color) {
|
||||||
|
ContextualIdentityService.update(identity.userContextId,
|
||||||
|
ContextualIdentityService.getUserContextLabel(identity.userContextId),
|
||||||
|
newIcon,
|
||||||
|
newColor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Let's see if containers were enabled before this addon.
|
// Let's see if containers were enabled before this addon.
|
||||||
this._containerWasEnabled =
|
this._containerWasEnabled =
|
||||||
ss.storage.savedConfiguration.prefs["privacy.userContext.enabled"];
|
ss.storage.savedConfiguration.prefs["privacy.userContext.enabled"];
|
||||||
|
@ -192,9 +207,8 @@ const ContainerService = {
|
||||||
"sortTabs",
|
"sortTabs",
|
||||||
"getTabs",
|
"getTabs",
|
||||||
"showTab",
|
"showTab",
|
||||||
"openTab",
|
|
||||||
"moveTabsToWindow",
|
"moveTabsToWindow",
|
||||||
"queryIdentities",
|
"queryIdentitiesState",
|
||||||
"getIdentity",
|
"getIdentity",
|
||||||
"getPreference",
|
"getPreference",
|
||||||
"sendTelemetryPayload",
|
"sendTelemetryPayload",
|
||||||
|
@ -308,7 +322,7 @@ const ContainerService = {
|
||||||
},
|
},
|
||||||
|
|
||||||
registerBackgroundConnection(api) {
|
registerBackgroundConnection(api) {
|
||||||
// This is only used for theme notifications
|
// This is only used for theme notifications and new tab
|
||||||
api.browser.runtime.onConnect.addListener((port) => {
|
api.browser.runtime.onConnect.addListener((port) => {
|
||||||
this._onBackgroundConnectCallback = (message, topic) => {
|
this._onBackgroundConnectCallback = (message, topic) => {
|
||||||
port.postMessage({
|
port.postMessage({
|
||||||
|
@ -396,18 +410,6 @@ const ContainerService = {
|
||||||
return containersCounts;
|
return containersCounts;
|
||||||
},
|
},
|
||||||
|
|
||||||
_convert(identity) {
|
|
||||||
// Let's convert the known colors to their color names.
|
|
||||||
return {
|
|
||||||
name: ContextualIdentityProxy.getUserContextLabel(identity.userContextId),
|
|
||||||
image: this._fromIconToName(identity.icon),
|
|
||||||
color: this._fromColorToName(identity.color),
|
|
||||||
userContextId: identity.userContextId,
|
|
||||||
hasHiddenTabs: !!this._identitiesState[identity.userContextId].hiddenTabs.length,
|
|
||||||
hasOpenTabs: !!this._identitiesState[identity.userContextId].openTabs
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
// In FF 50-51, the icon is the full path, in 52 and following
|
// In FF 50-51, the icon is the full path, in 52 and following
|
||||||
// releases, we have IDs to be used with a svg file. In this function
|
// releases, we have IDs to be used with a svg file. In this function
|
||||||
// we map URLs to svg IDs.
|
// we map URLs to svg IDs.
|
||||||
|
@ -433,10 +435,6 @@ const ContainerService = {
|
||||||
|
|
||||||
// Helper methods for converting icons to names and names to icons.
|
// Helper methods for converting icons to names and names to icons.
|
||||||
|
|
||||||
_fromNameToIcon(name) {
|
|
||||||
return this._fromNameOrIcon(name, "image", "");
|
|
||||||
},
|
|
||||||
|
|
||||||
_fromIconToName(icon) {
|
_fromIconToName(icon) {
|
||||||
return this._fromNameOrIcon(icon, "name", "circle");
|
return this._fromNameOrIcon(icon, "name", "circle");
|
||||||
},
|
},
|
||||||
|
@ -559,6 +557,29 @@ const ContainerService = {
|
||||||
};
|
};
|
||||||
Object.assign(payload, args);
|
Object.assign(payload, args);
|
||||||
|
|
||||||
|
/* This is to masage the data whilst it is still active in the SDK side */
|
||||||
|
const containersCounts = this._containersCounts();
|
||||||
|
Object.keys(payload).forEach((keyName) => {
|
||||||
|
let value = payload[keyName];
|
||||||
|
if (value === LOOKUP_KEY) {
|
||||||
|
switch (keyName) {
|
||||||
|
case "clickedContainerTabCount":
|
||||||
|
value = this._containerTabCount(payload.userContextId);
|
||||||
|
break;
|
||||||
|
case "shownContainersCount":
|
||||||
|
value = containersCounts.shown;
|
||||||
|
break;
|
||||||
|
case "hiddenContainersCount":
|
||||||
|
value = containersCounts.hidden;
|
||||||
|
break;
|
||||||
|
case "totalContainersCount":
|
||||||
|
value = containersCounts.total;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
payload[keyName] = value;
|
||||||
|
});
|
||||||
|
|
||||||
this._sendEvent(payload);
|
this._sendEvent(payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -593,10 +614,10 @@ const ContainerService = {
|
||||||
this.sendTelemetryPayload({
|
this.sendTelemetryPayload({
|
||||||
"event": "hide-tabs",
|
"event": "hide-tabs",
|
||||||
"userContextId": args.userContextId,
|
"userContextId": args.userContextId,
|
||||||
"clickedContainerTabCount": this._containerTabCount(args.userContextId),
|
"clickedContainerTabCount": LOOKUP_KEY,
|
||||||
"shownContainersCount": containersCounts.shown,
|
"shownContainersCount": LOOKUP_KEY,
|
||||||
"hiddenContainersCount": containersCounts.hidden,
|
"hiddenContainersCount": LOOKUP_KEY,
|
||||||
"totalContainersCount": containersCounts.total
|
"totalContainersCount": LOOKUP_KEY
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabsToClose = [];
|
const tabsToClose = [];
|
||||||
|
@ -633,14 +654,13 @@ const ContainerService = {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
const containersCounts = this._containersCounts();
|
|
||||||
this.sendTelemetryPayload({
|
this.sendTelemetryPayload({
|
||||||
"event": "show-tabs",
|
"event": "show-tabs",
|
||||||
"userContextId": args.userContextId,
|
"userContextId": args.userContextId,
|
||||||
"clickedContainerTabCount": this._containerTabCount(args.userContextId),
|
"clickedContainerTabCount": LOOKUP_KEY,
|
||||||
"shownContainersCount": containersCounts.shown,
|
"shownContainersCount": LOOKUP_KEY,
|
||||||
"hiddenContainersCount": containersCounts.hidden,
|
"hiddenContainersCount": LOOKUP_KEY,
|
||||||
"totalContainersCount": containersCounts.total
|
"totalContainersCount": LOOKUP_KEY
|
||||||
});
|
});
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
@ -653,7 +673,6 @@ const ContainerService = {
|
||||||
userContextId: args.userContextId,
|
userContextId: args.userContextId,
|
||||||
url: object.url,
|
url: object.url,
|
||||||
nofocus: args.nofocus || false,
|
nofocus: args.nofocus || false,
|
||||||
window: args.window || null,
|
|
||||||
pinned: object.pinned,
|
pinned: object.pinned,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -840,74 +859,37 @@ const ContainerService = {
|
||||||
},
|
},
|
||||||
|
|
||||||
openTab(args) {
|
openTab(args) {
|
||||||
return new Promise(resolve => {
|
return this.triggerBackgroundCallback(args, "open-tab");
|
||||||
if ("window" in args && args.window) {
|
|
||||||
resolve(args.window);
|
|
||||||
} else {
|
|
||||||
this._recentBrowserWindow().then(browserWin => {
|
|
||||||
resolve(browserWin);
|
|
||||||
}).catch(() => {});
|
|
||||||
}
|
|
||||||
}).then(browserWin => {
|
|
||||||
const userContextId = ("userContextId" in args) ? args.userContextId : 0;
|
|
||||||
const source = ("source" in args) ? args.source : null;
|
|
||||||
const nofocus = ("nofocus" in args) ? args.nofocus : false;
|
|
||||||
|
|
||||||
// Only send telemetry for tabs opened by UI - i.e., not via showTabs
|
|
||||||
if (source && userContextId) {
|
|
||||||
this.sendTelemetryPayload({
|
|
||||||
"event": "open-tab",
|
|
||||||
"eventSource": source,
|
|
||||||
"userContextId": userContextId,
|
|
||||||
"clickedContainerTabCount": this._containerTabCount(userContextId)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let promise;
|
|
||||||
if (userContextId) {
|
|
||||||
promise = this.showTabs(args);
|
|
||||||
} else {
|
|
||||||
promise = Promise.resolve(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise.then(() => {
|
|
||||||
const tab = browserWin.gBrowser.addTab(args.url || DEFAULT_TAB, { userContextId });
|
|
||||||
if (!nofocus) {
|
|
||||||
browserWin.gBrowser.selectedTab = tab;
|
|
||||||
browserWin.focusAndSelectUrlBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.pinned) {
|
|
||||||
browserWin.gBrowser.pinTab(tab);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}).catch(() => false);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Identities management
|
// Identities management
|
||||||
|
queryIdentitiesState() {
|
||||||
queryIdentities() {
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const identities = [];
|
const identities = {};
|
||||||
|
|
||||||
ContextualIdentityProxy.getIdentities().forEach(identity => {
|
ContextualIdentityProxy.getIdentities().forEach(identity => {
|
||||||
this._remapTabsIfMissing(identity.userContextId);
|
this._remapTabsIfMissing(identity.userContextId);
|
||||||
const convertedIdentity = this._convert(identity);
|
const convertedIdentity = {
|
||||||
identities.push(convertedIdentity);
|
hasHiddenTabs: !!this._identitiesState[identity.userContextId].hiddenTabs.length,
|
||||||
|
hasOpenTabs: !!this._identitiesState[identity.userContextId].openTabs
|
||||||
|
};
|
||||||
|
|
||||||
|
identities[identity.userContextId] = convertedIdentity;
|
||||||
});
|
});
|
||||||
|
|
||||||
resolve(identities);
|
resolve(identities);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getIdentity(args) {
|
queryIdentities() {
|
||||||
if (!("userContextId" in args)) {
|
return new Promise(resolve => {
|
||||||
return Promise.reject("getIdentity must be called with userContextId argument.");
|
const identities = ContextualIdentityProxy.getIdentities();
|
||||||
}
|
identities.forEach(identity => {
|
||||||
|
this._remapTabsIfMissing(identity.userContextId);
|
||||||
|
});
|
||||||
|
|
||||||
const identity = ContextualIdentityProxy.getIdentityFromId(args.userContextId);
|
resolve(identities);
|
||||||
return Promise.resolve(identity ? this._convert(identity) : null);
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
|
@ -974,26 +956,25 @@ const ContainerService = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const userContextId = ContainerService._getUserContextIdFromTab(tab);
|
const userContextId = ContainerService._getUserContextIdFromTab(tab);
|
||||||
return ContainerService.getIdentity({userContextId}).then(identity => {
|
const identity = ContextualIdentityProxy.getIdentityFromId(userContextId);
|
||||||
const hbox = viewFor(tab.window).document.getElementById("userContext-icons");
|
const hbox = viewFor(tab.window).document.getElementById("userContext-icons");
|
||||||
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
hbox.setAttribute("data-identity-color", "");
|
hbox.setAttribute("data-identity-color", "");
|
||||||
return;
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
hbox.setAttribute("data-identity-color", identity.color);
|
hbox.setAttribute("data-identity-color", identity.color);
|
||||||
|
|
||||||
const label = viewFor(tab.window).document.getElementById("userContext-label");
|
const label = viewFor(tab.window).document.getElementById("userContext-label");
|
||||||
label.setAttribute("value", identity.name);
|
label.setAttribute("value", identity.name);
|
||||||
label.style.color = ContainerService._fromNameToColor(identity.color);
|
label.style.color = ContainerService._fromNameToColor(identity.color);
|
||||||
|
|
||||||
const indicator = viewFor(tab.window).document.getElementById("userContext-indicator");
|
const indicator = viewFor(tab.window).document.getElementById("userContext-indicator");
|
||||||
indicator.setAttribute("data-identity-icon", identity.image);
|
indicator.setAttribute("data-identity-icon", identity.icon);
|
||||||
indicator.style.listStyleImage = "";
|
indicator.style.listStyleImage = "";
|
||||||
}).then(() => {
|
|
||||||
return this._restyleTab(tab);
|
return this._restyleTab(tab);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_restyleTab(tab) {
|
_restyleTab(tab) {
|
||||||
|
@ -1001,12 +982,11 @@ const ContainerService = {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
const userContextId = ContainerService._getUserContextIdFromTab(tab);
|
const userContextId = ContainerService._getUserContextIdFromTab(tab);
|
||||||
return ContainerService.getIdentity({userContextId}).then(identity => {
|
const identity = ContextualIdentityProxy.getIdentityFromId(userContextId);
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
return;
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
viewFor(tab).setAttribute("data-identity-color", identity.color);
|
return Promise.resolve(viewFor(tab).setAttribute("data-identity-color", identity.color));
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Uninstallation
|
// Uninstallation
|
||||||
|
@ -1065,7 +1045,7 @@ const ContainerService = {
|
||||||
const preInstalledIdentities = data.preInstalledIdentities;
|
const preInstalledIdentities = data.preInstalledIdentities;
|
||||||
ContextualIdentityProxy.getIdentities().forEach(identity => {
|
ContextualIdentityProxy.getIdentities().forEach(identity => {
|
||||||
if (!preInstalledIdentities.includes(identity.userContextId)) {
|
if (!preInstalledIdentities.includes(identity.userContextId)) {
|
||||||
ContextualIdentityProxy.remove(identity.userContextId);
|
ContextualIdentityService.remove(identity.userContextId);
|
||||||
} else {
|
} else {
|
||||||
// Let's cleanup all the cookies for this container.
|
// Let's cleanup all the cookies for this container.
|
||||||
Services.obs.notifyObservers(null, "clear-origin-attributes-data",
|
Services.obs.notifyObservers(null, "clear-origin-attributes-data",
|
||||||
|
@ -1237,14 +1217,13 @@ ContainerWindow.prototype = {
|
||||||
menuItemElement.className = "menuitem-iconic";
|
menuItemElement.className = "menuitem-iconic";
|
||||||
menuItemElement.setAttribute("label", identity.name);
|
menuItemElement.setAttribute("label", identity.name);
|
||||||
menuItemElement.setAttribute("data-usercontextid", identity.userContextId);
|
menuItemElement.setAttribute("data-usercontextid", identity.userContextId);
|
||||||
menuItemElement.setAttribute("data-identity-icon", identity.image);
|
menuItemElement.setAttribute("data-identity-icon", identity.icon);
|
||||||
menuItemElement.setAttribute("data-identity-color", identity.color);
|
menuItemElement.setAttribute("data-identity-color", identity.color);
|
||||||
|
|
||||||
menuItemElement.addEventListener("command", (e) => {
|
menuItemElement.addEventListener("command", (e) => {
|
||||||
ContainerService.openTab({
|
ContainerService.openTab({
|
||||||
userContextId: identity.userContextId,
|
userContextId: identity.userContextId,
|
||||||
source: "tab-bar",
|
source: "tab-bar"
|
||||||
window: this._window,
|
|
||||||
});
|
});
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
@ -1280,8 +1259,7 @@ ContainerWindow.prototype = {
|
||||||
const userContextId = parseInt(e.target.getAttribute("data-usercontextid"), 10);
|
const userContextId = parseInt(e.target.getAttribute("data-usercontextid"), 10);
|
||||||
ContainerService.openTab({
|
ContainerService.openTab({
|
||||||
userContextId: userContextId,
|
userContextId: userContextId,
|
||||||
source: "file-menu",
|
source: "file-menu"
|
||||||
window: this._window,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1296,8 +1274,7 @@ ContainerWindow.prototype = {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return ContainerService.openTab({
|
return ContainerService.openTab({
|
||||||
userContextId,
|
userContextId,
|
||||||
source: "alltabs-menu",
|
source: "alltabs-menu"
|
||||||
window: this._window,
|
|
||||||
});
|
});
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
});
|
});
|
||||||
|
@ -1399,7 +1376,7 @@ ContainerWindow.prototype = {
|
||||||
menuitem.classList.add("menuitem-iconic");
|
menuitem.classList.add("menuitem-iconic");
|
||||||
menuitem.setAttribute("data-usercontextid", identity.userContextId);
|
menuitem.setAttribute("data-usercontextid", identity.userContextId);
|
||||||
menuitem.setAttribute("data-identity-color", identity.color);
|
menuitem.setAttribute("data-identity-color", identity.color);
|
||||||
menuitem.setAttribute("data-identity-icon", identity.image);
|
menuitem.setAttribute("data-identity-icon", identity.icon);
|
||||||
fragment.appendChild(menuitem);
|
fragment.appendChild(menuitem);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
const MAJOR_VERSIONS = ["2.3.0"];
|
const MAJOR_VERSIONS = ["2.3.0"];
|
||||||
|
const LOOKUP_KEY = "$ref";
|
||||||
|
|
||||||
const assignManager = {
|
const assignManager = {
|
||||||
CLOSEABLE_WINDOWS: new Set([
|
|
||||||
"about:startpage",
|
|
||||||
"about:newtab",
|
|
||||||
"about:home",
|
|
||||||
"about:blank"
|
|
||||||
]),
|
|
||||||
MENU_ASSIGN_ID: "open-in-this-container",
|
MENU_ASSIGN_ID: "open-in-this-container",
|
||||||
MENU_REMOVE_ID: "remove-open-in-this-container",
|
MENU_REMOVE_ID: "remove-open-in-this-container",
|
||||||
storageArea: {
|
storageArea: {
|
||||||
|
@ -133,14 +128,14 @@ const assignManager = {
|
||||||
We aim to open the new assigned container tab / warning prompt in it's own tab:
|
We aim to open the new assigned container tab / warning prompt in it's own tab:
|
||||||
- As the history won't span from one container to another it seems most sane to not try and reopen a tab on history.back()
|
- As the history won't span from one container to another it seems most sane to not try and reopen a tab on history.back()
|
||||||
- When users open a new tab themselves we want to make sure we don't end up with three tabs as per: https://github.com/mozilla/testpilot-containers/issues/421
|
- When users open a new tab themselves we want to make sure we don't end up with three tabs as per: https://github.com/mozilla/testpilot-containers/issues/421
|
||||||
If we are coming from an internal url that are used for the new tab page (CLOSEABLE_WINDOWS), we can safely close as user is unlikely losing history
|
If we are coming from an internal url that are used for the new tab page (NEW_TAB_PAGES), we can safely close as user is unlikely losing history
|
||||||
Detecting redirects on "new tab" opening actions is pretty hard as we don't get tab history:
|
Detecting redirects on "new tab" opening actions is pretty hard as we don't get tab history:
|
||||||
- Redirects happen from Short URLs and tracking links that act as a gateway
|
- Redirects happen from Short URLs and tracking links that act as a gateway
|
||||||
- Extensions don't provide a way to history crawl for tabs, we could inject content scripts to do this
|
- Extensions don't provide a way to history crawl for tabs, we could inject content scripts to do this
|
||||||
however they don't run on about:blank so this would likely be just as hacky.
|
however they don't run on about:blank so this would likely be just as hacky.
|
||||||
We capture the time the tab was created and close if it was within the timeout to try to capture pages which haven't had user interaction or history.
|
We capture the time the tab was created and close if it was within the timeout to try to capture pages which haven't had user interaction or history.
|
||||||
*/
|
*/
|
||||||
if (this.CLOSEABLE_WINDOWS.has(tab.url)
|
if (backgroundLogic.NEW_TAB_PAGES.has(tab.url)
|
||||||
|| (messageHandler.lastCreatedTab
|
|| (messageHandler.lastCreatedTab
|
||||||
&& messageHandler.lastCreatedTab.id === tab.id)) {
|
&& messageHandler.lastCreatedTab.id === tab.id)) {
|
||||||
browser.tabs.remove(tab.id);
|
browser.tabs.remove(tab.id);
|
||||||
|
@ -218,7 +213,7 @@ const assignManager = {
|
||||||
const loadPage = browser.extension.getURL("confirm-page.html");
|
const loadPage = browser.extension.getURL("confirm-page.html");
|
||||||
// If the user has explicitly checked "Never Ask Again" on the warning page we will send them straight there
|
// If the user has explicitly checked "Never Ask Again" on the warning page we will send them straight there
|
||||||
if (neverAsk) {
|
if (neverAsk) {
|
||||||
browser.tabs.create({url, cookieStoreId: `firefox-container-${userContextId}`, index});
|
browser.tabs.create({url, cookieStoreId: backgroundLogic.cookieStoreId(userContextId), index});
|
||||||
backgroundLogic.sendTelemetryPayload({
|
backgroundLogic.sendTelemetryPayload({
|
||||||
event: "auto-reload-page-in-container",
|
event: "auto-reload-page-in-container",
|
||||||
userContextId: userContextId,
|
userContextId: userContextId,
|
||||||
|
@ -229,7 +224,7 @@ const assignManager = {
|
||||||
userContextId: userContextId,
|
userContextId: userContextId,
|
||||||
});
|
});
|
||||||
const confirmUrl = `${loadPage}?url=${url}`;
|
const confirmUrl = `${loadPage}?url=${url}`;
|
||||||
browser.tabs.create({url: confirmUrl, cookieStoreId: `firefox-container-${userContextId}`, index}).then(() => {
|
browser.tabs.create({url: confirmUrl, cookieStoreId: backgroundLogic.cookieStoreId(userContextId), index}).then(() => {
|
||||||
// We don't want to sync this URL ever nor clutter the users history
|
// We don't want to sync this URL ever nor clutter the users history
|
||||||
browser.history.deleteUrl({url: confirmUrl});
|
browser.history.deleteUrl({url: confirmUrl});
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
|
@ -241,6 +236,13 @@ const assignManager = {
|
||||||
|
|
||||||
|
|
||||||
const backgroundLogic = {
|
const backgroundLogic = {
|
||||||
|
NEW_TAB_PAGES: new Set([
|
||||||
|
"about:startpage",
|
||||||
|
"about:newtab",
|
||||||
|
"about:home",
|
||||||
|
"about:blank"
|
||||||
|
]),
|
||||||
|
|
||||||
deleteContainer(userContextId) {
|
deleteContainer(userContextId) {
|
||||||
this.sendTelemetryPayload({
|
this.sendTelemetryPayload({
|
||||||
event: "delete-container",
|
event: "delete-container",
|
||||||
|
@ -291,6 +293,41 @@ const backgroundLogic = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openTab(options) {
|
||||||
|
let url = options.url || undefined;
|
||||||
|
const userContextId = ("userContextId" in options) ? options.userContextId : 0;
|
||||||
|
const active = ("nofocus" in options) ? options.nofocus : true;
|
||||||
|
const source = ("source" in options) ? options.source : null;
|
||||||
|
|
||||||
|
// Only send telemetry for tabs opened by UI - i.e., not via showTabs
|
||||||
|
if (source && userContextId) {
|
||||||
|
this.sendTelemetryPayload({
|
||||||
|
"event": "open-tab",
|
||||||
|
"eventSource": source,
|
||||||
|
"userContextId": userContextId,
|
||||||
|
"clickedContainerTabCount": LOOKUP_KEY
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Autofocus url bar will happen in 54: https://bugzilla.mozilla.org/show_bug.cgi?id=1295072
|
||||||
|
|
||||||
|
// We can't open new tab pages, so open a blank tab. Used in tab un-hide
|
||||||
|
if (this.NEW_TAB_PAGES.has(url)) {
|
||||||
|
url = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unhide all hidden tabs
|
||||||
|
browser.runtime.sendMessage({
|
||||||
|
method: "showTabs",
|
||||||
|
userContextId: options.userContextId
|
||||||
|
});
|
||||||
|
return browser.tabs.create({
|
||||||
|
url,
|
||||||
|
active,
|
||||||
|
pinned: options.pinned || false,
|
||||||
|
cookieStoreId: backgroundLogic.cookieStoreId(options.userContextId)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
sendTelemetryPayload(message = {}) {
|
sendTelemetryPayload(message = {}) {
|
||||||
if (!message.event) {
|
if (!message.event) {
|
||||||
throw new Error("Missing event name for telemetry");
|
throw new Error("Missing event name for telemetry");
|
||||||
|
@ -317,6 +354,7 @@ const messageHandler = {
|
||||||
LAST_CREATED_TAB_TIMER: 2000,
|
LAST_CREATED_TAB_TIMER: 2000,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
// Handles messages from webextension/js/popup.js
|
||||||
browser.runtime.onMessage.addListener((m) => {
|
browser.runtime.onMessage.addListener((m) => {
|
||||||
let response;
|
let response;
|
||||||
|
|
||||||
|
@ -327,6 +365,10 @@ const messageHandler = {
|
||||||
case "createOrUpdateContainer":
|
case "createOrUpdateContainer":
|
||||||
response = backgroundLogic.createOrUpdateContainer(m.message);
|
response = backgroundLogic.createOrUpdateContainer(m.message);
|
||||||
break;
|
break;
|
||||||
|
case "openTab":
|
||||||
|
// Same as open-tab for index.js
|
||||||
|
response = backgroundLogic.openTab(m.message);
|
||||||
|
break;
|
||||||
case "neverAsk":
|
case "neverAsk":
|
||||||
assignManager._neverAsk(m);
|
assignManager._neverAsk(m);
|
||||||
break;
|
break;
|
||||||
|
@ -341,6 +383,9 @@ const messageHandler = {
|
||||||
case "lightweight-theme-changed":
|
case "lightweight-theme-changed":
|
||||||
themeManager.update(m.message);
|
themeManager.update(m.message);
|
||||||
break;
|
break;
|
||||||
|
case "open-tab":
|
||||||
|
backgroundLogic.openTab(m.message);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unhandled message type: ${m.message}`);
|
throw new Error(`Unhandled message type: ${m.message}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,13 +116,27 @@ const Logic = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
userContextId(cookieStoreId = "") {
|
||||||
|
const userContextId = cookieStoreId.replace("firefox-container-", "");
|
||||||
|
return (userContextId !== cookieStoreId) ? Number(userContextId) : false;
|
||||||
|
},
|
||||||
|
|
||||||
refreshIdentities() {
|
refreshIdentities() {
|
||||||
return browser.runtime.sendMessage({
|
return Promise.all([
|
||||||
method: "queryIdentities"
|
browser.contextualIdentities.query({}),
|
||||||
})
|
browser.runtime.sendMessage({
|
||||||
.then(identities => {
|
method: "queryIdentitiesState"
|
||||||
this._identities = identities;
|
})
|
||||||
});
|
]).then(([identities, state]) => {
|
||||||
|
this._identities = identities.map((identity) => {
|
||||||
|
const stateObject = state[Logic.userContextId(identity.cookieStoreId)];
|
||||||
|
if (stateObject) {
|
||||||
|
identity.hasOpenTabs = stateObject.hasOpenTabs;
|
||||||
|
identity.hasHiddenTabs = stateObject.hasHiddenTabs;
|
||||||
|
}
|
||||||
|
return identity;
|
||||||
|
});
|
||||||
|
}).catch((e) => {throw e;});
|
||||||
},
|
},
|
||||||
|
|
||||||
showPanel(panel, currentIdentity = null) {
|
showPanel(panel, currentIdentity = null) {
|
||||||
|
@ -371,7 +385,7 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
|
||||||
context.innerHTML = escaped`
|
context.innerHTML = escaped`
|
||||||
<div class="userContext-icon-wrapper open-newtab">
|
<div class="userContext-icon-wrapper open-newtab">
|
||||||
<div class="usercontext-icon"
|
<div class="usercontext-icon"
|
||||||
data-identity-icon="${identity.image}"
|
data-identity-icon="${identity.icon}"
|
||||||
data-identity-color="${identity.color}">
|
data-identity-color="${identity.color}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -393,8 +407,10 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
|
||||||
|| e.type === "keydown") {
|
|| e.type === "keydown") {
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
method: "openTab",
|
method: "openTab",
|
||||||
userContextId: identity.userContextId,
|
message: {
|
||||||
source: "pop-up"
|
userContextId: Logic.userContextId(identity.cookieStoreId),
|
||||||
|
source: "pop-up"
|
||||||
|
}
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
window.close();
|
window.close();
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
@ -437,7 +453,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
const identity = Logic.currentIdentity();
|
const identity = Logic.currentIdentity();
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
method: identity.hasHiddenTabs ? "showTabs" : "hideTabs",
|
method: identity.hasHiddenTabs ? "showTabs" : "hideTabs",
|
||||||
userContextId: identity.userContextId
|
userContextId: Logic.userContextId(identity.cookieStoreId)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
window.close();
|
window.close();
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
@ -467,7 +483,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
Logic.addEnterHandler(moveTabsEl, () => {
|
Logic.addEnterHandler(moveTabsEl, () => {
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
method: "moveTabsToWindow",
|
method: "moveTabsToWindow",
|
||||||
userContextId: Logic.currentIdentity().userContextId,
|
userContextId: Logic.userContextId(Logic.currentIdentity().cookieStoreId),
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
window.close();
|
window.close();
|
||||||
}).catch((e) => { throw e; });
|
}).catch((e) => { throw e; });
|
||||||
|
@ -486,7 +502,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
document.getElementById("container-info-name").textContent = identity.name;
|
document.getElementById("container-info-name").textContent = identity.name;
|
||||||
|
|
||||||
const icon = document.getElementById("container-info-icon");
|
const icon = document.getElementById("container-info-icon");
|
||||||
icon.setAttribute("data-identity-icon", identity.image);
|
icon.setAttribute("data-identity-icon", identity.icon);
|
||||||
icon.setAttribute("data-identity-color", identity.color);
|
icon.setAttribute("data-identity-color", identity.color);
|
||||||
|
|
||||||
// Show or not the has-tabs section.
|
// Show or not the has-tabs section.
|
||||||
|
@ -509,7 +525,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
// Let's retrieve the list of tabs.
|
// Let's retrieve the list of tabs.
|
||||||
return browser.runtime.sendMessage({
|
return browser.runtime.sendMessage({
|
||||||
method: "getTabs",
|
method: "getTabs",
|
||||||
userContextId: identity.userContextId,
|
userContextId: Logic.userContextId(identity.cookieStoreId),
|
||||||
}).then(this.buildInfoTable);
|
}).then(this.buildInfoTable);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -568,7 +584,7 @@ Logic.registerPanel(P_CONTAINERS_EDIT, {
|
||||||
<td class="userContext-wrapper">
|
<td class="userContext-wrapper">
|
||||||
<div class="userContext-icon-wrapper">
|
<div class="userContext-icon-wrapper">
|
||||||
<div class="usercontext-icon"
|
<div class="usercontext-icon"
|
||||||
data-identity-icon="${identity.image}"
|
data-identity-icon="${identity.icon}"
|
||||||
data-identity-color="${identity.color}">
|
data-identity-color="${identity.color}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -639,7 +655,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
return browser.runtime.sendMessage({
|
return browser.runtime.sendMessage({
|
||||||
method: "createOrUpdateContainer",
|
method: "createOrUpdateContainer",
|
||||||
message: {
|
message: {
|
||||||
userContextId: identity.userContextId || false,
|
userContextId: Logic.userContextId(identity.cookieStoreId) || false,
|
||||||
params: {
|
params: {
|
||||||
name: document.getElementById("edit-container-panel-name-input").value || Logic.generateIdentityName(),
|
name: document.getElementById("edit-container-panel-name-input").value || Logic.generateIdentityName(),
|
||||||
icon: formValues.get("container-icon") || DEFAULT_ICON,
|
icon: formValues.get("container-icon") || DEFAULT_ICON,
|
||||||
|
@ -691,7 +707,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
colorInput.checked = colorInput.value === identity.color;
|
colorInput.checked = colorInput.value === identity.color;
|
||||||
});
|
});
|
||||||
[...document.querySelectorAll("[name='container-icon']")].forEach(iconInput => {
|
[...document.querySelectorAll("[name='container-icon']")].forEach(iconInput => {
|
||||||
iconInput.checked = iconInput.value === identity.image;
|
iconInput.checked = iconInput.value === identity.icon;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
|
@ -717,7 +733,7 @@ Logic.registerPanel(P_CONTAINER_DELETE, {
|
||||||
if you want to do anything post delete do it in the background script.
|
if you want to do anything post delete do it in the background script.
|
||||||
Browser console currently warns about not listening also.
|
Browser console currently warns about not listening also.
|
||||||
*/
|
*/
|
||||||
Logic.removeIdentity(Logic.currentIdentity().userContextId).then(() => {
|
Logic.removeIdentity(Logic.userContextId(Logic.currentIdentity().cookieStoreId)).then(() => {
|
||||||
return Logic.refreshIdentities();
|
return Logic.refreshIdentities();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
Logic.showPreviousPanel();
|
Logic.showPreviousPanel();
|
||||||
|
@ -735,7 +751,7 @@ Logic.registerPanel(P_CONTAINER_DELETE, {
|
||||||
document.getElementById("delete-container-name").textContent = identity.name;
|
document.getElementById("delete-container-name").textContent = identity.name;
|
||||||
|
|
||||||
const icon = document.getElementById("delete-container-icon");
|
const icon = document.getElementById("delete-container-icon");
|
||||||
icon.setAttribute("data-identity-icon", identity.image);
|
icon.setAttribute("data-identity-icon", identity.icon);
|
||||||
icon.setAttribute("data-identity-color", identity.color);
|
icon.setAttribute("data-identity-color", identity.color);
|
||||||
|
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
|
|
Loading…
Add table
Reference in a new issue