commit
e3daf2e842
5 changed files with 58 additions and 46 deletions
|
@ -16,7 +16,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"promise",
|
"promise",
|
||||||
"unsafe-property-assignment"
|
"no-unescaped"
|
||||||
],
|
],
|
||||||
"root": true,
|
"root": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
|
@ -29,8 +29,8 @@ module.exports = {
|
||||||
"promise/no-promise-in-callback": "warn",
|
"promise/no-promise-in-callback": "warn",
|
||||||
"promise/no-return-wrap": "error",
|
"promise/no-return-wrap": "error",
|
||||||
"promise/param-names": "error",
|
"promise/param-names": "error",
|
||||||
"unsafe-property-assignment/no-key-assignment": ["error"],
|
"no-unescaped/no-key-assignment": "error",
|
||||||
"unsafe-property-assignment/enforce-tagged-template-protection": ["error"],
|
"no-unescaped/enforce": "error",
|
||||||
|
|
||||||
"eqeqeq": "error",
|
"eqeqeq": "error",
|
||||||
"indent": ["error", 2],
|
"indent": ["error", 2],
|
||||||
|
|
63
index.js
63
index.js
|
@ -119,11 +119,12 @@ const ContainerService = {
|
||||||
_containerWasEnabled: false,
|
_containerWasEnabled: false,
|
||||||
_onThemeChangedCallback: null,
|
_onThemeChangedCallback: null,
|
||||||
|
|
||||||
init(installation) {
|
init(installation, reason) {
|
||||||
// If we are just been installed, we must store some information for the
|
// If we are just been installed, we must store some information for the
|
||||||
// uninstallation. This object contains also a version number, in case we
|
// uninstallation. This object contains also a version number, in case we
|
||||||
// need to implement a migration in the future.
|
// need to implement a migration in the future.
|
||||||
if (installation) {
|
// In 1.1.1 and less we deleted savedConfiguration on upgrade so we need to rebuild
|
||||||
|
if (installation && (reason !== "upgrade" || !ss.storage.savedConfiguration)) {
|
||||||
let preInstalledIdentities = []; // eslint-disable-line prefer-const
|
let preInstalledIdentities = []; // eslint-disable-line prefer-const
|
||||||
ContextualIdentityProxy.getIdentities().forEach(identity => {
|
ContextualIdentityProxy.getIdentities().forEach(identity => {
|
||||||
preInstalledIdentities.push(identity.userContextId);
|
preInstalledIdentities.push(identity.userContextId);
|
||||||
|
@ -286,13 +287,17 @@ const ContainerService = {
|
||||||
return identity;
|
return identity;
|
||||||
};
|
};
|
||||||
|
|
||||||
this._oldGetIdentityFromId = ContextualIdentityService.getIdentityFromId;
|
if (!this._oldGetIdentityFromId) {
|
||||||
|
this._oldGetIdentityFromId = ContextualIdentityService.getIdentityFromId;
|
||||||
|
}
|
||||||
ContextualIdentityService.getIdentityFromId = function(userContextId) {
|
ContextualIdentityService.getIdentityFromId = function(userContextId) {
|
||||||
return this.workaroundForCookieManager(ContainerService._oldGetIdentityFromId, userContextId);
|
return this.workaroundForCookieManager(ContainerService._oldGetIdentityFromId, userContextId);
|
||||||
};
|
};
|
||||||
|
|
||||||
if ("getPublicIdentityFromId" in ContextualIdentityService) {
|
if ("getPublicIdentityFromId" in ContextualIdentityService) {
|
||||||
this._oldGetPublicIdentityFromId = ContextualIdentityService.getPublicIdentityFromId;
|
if (!this._oldGetPublicIdentityFromId) {
|
||||||
|
this._oldGetPublicIdentityFromId = ContextualIdentityService.getPublicIdentityFromId;
|
||||||
|
}
|
||||||
ContextualIdentityService.getPublicIdentityFromId = function(userContextId) {
|
ContextualIdentityService.getPublicIdentityFromId = function(userContextId) {
|
||||||
return this.workaroundForCookieManager(ContainerService._oldGetPublicIdentityFromId, userContextId);
|
return this.workaroundForCookieManager(ContainerService._oldGetPublicIdentityFromId, userContextId);
|
||||||
};
|
};
|
||||||
|
@ -1076,7 +1081,7 @@ const ContainerService = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Uninstallation
|
// Uninstallation
|
||||||
uninstall() {
|
uninstall(reason) {
|
||||||
const data = ss.storage.savedConfiguration;
|
const data = ss.storage.savedConfiguration;
|
||||||
if (!data) {
|
if (!data) {
|
||||||
throw new DOMError("ERROR - No saved configuration!!");
|
throw new DOMError("ERROR - No saved configuration!!");
|
||||||
|
@ -1086,11 +1091,13 @@ const ContainerService = {
|
||||||
throw new DOMError("ERROR - Unknown version!!");
|
throw new DOMError("ERROR - Unknown version!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
PREFS.forEach(pref => {
|
if (reason !== "upgrade") {
|
||||||
if (pref[0] in data.prefs) {
|
PREFS.forEach(pref => {
|
||||||
prefService.set(pref[0], data.prefs[pref[0]]);
|
if (pref[0] in data.prefs) {
|
||||||
}
|
prefService.set(pref[0], data.prefs[pref[0]]);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Note: We cannot go back renaming the Finance identity back to Banking:
|
// Note: We cannot go back renaming the Finance identity back to Banking:
|
||||||
// the locale system doesn't work with renamed containers.
|
// the locale system doesn't work with renamed containers.
|
||||||
|
@ -1105,7 +1112,7 @@ const ContainerService = {
|
||||||
// Let's close all the container tabs.
|
// Let's close all the container tabs.
|
||||||
// Note: We cannot use _closeTabs() because at this point tab.window is
|
// Note: We cannot use _closeTabs() because at this point tab.window is
|
||||||
// null.
|
// null.
|
||||||
if (!this._containerWasEnabled) {
|
if (!this._containerWasEnabled && reason !== "upgrade") {
|
||||||
for (let tab of window.tabs) { // eslint-disable-line prefer-const
|
for (let tab of window.tabs) { // eslint-disable-line prefer-const
|
||||||
if (this._getUserContextIdFromTab(tab)) {
|
if (this._getUserContextIdFromTab(tab)) {
|
||||||
tab.close();
|
tab.close();
|
||||||
|
@ -1122,22 +1129,24 @@ const ContainerService = {
|
||||||
// all the configuration must go away now.
|
// all the configuration must go away now.
|
||||||
this._windowMap = new Map();
|
this._windowMap = new Map();
|
||||||
|
|
||||||
// Let's forget all the previous closed tabs.
|
if (reason !== "upgrade") {
|
||||||
this._forgetIdentity();
|
// Let's forget all the previous closed tabs.
|
||||||
|
this._forgetIdentity();
|
||||||
|
|
||||||
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);
|
ContextualIdentityProxy.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",
|
||||||
JSON.stringify({ userContextId: identity.userContextId }));
|
JSON.stringify({ userContextId: identity.userContextId }));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Let's delete the configuration.
|
// Let's delete the configuration.
|
||||||
delete ss.storage.savedConfiguration;
|
delete ss.storage.savedConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
// Begin-Of-Hack
|
// Begin-Of-Hack
|
||||||
if (this._oldGetIdentityFromId) {
|
if (this._oldGetIdentityFromId) {
|
||||||
|
@ -1557,7 +1566,7 @@ exports.main = function (options) {
|
||||||
options.loadReason === "upgrade";
|
options.loadReason === "upgrade";
|
||||||
|
|
||||||
// Let's start :)
|
// Let's start :)
|
||||||
ContainerService.init(installation);
|
ContainerService.init(installation, options.loadReason);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.onUnload = function (reason) {
|
exports.onUnload = function (reason) {
|
||||||
|
@ -1565,6 +1574,6 @@ exports.onUnload = function (reason) {
|
||||||
reason === "downgrade" ||
|
reason === "downgrade" ||
|
||||||
reason === "uninstall" ||
|
reason === "uninstall" ||
|
||||||
reason === "upgrade") {
|
reason === "upgrade") {
|
||||||
ContainerService.uninstall();
|
ContainerService.uninstall(reason);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "testpilot-containers",
|
"name": "testpilot-containers",
|
||||||
"title": "Containers Experiment",
|
"title": "Containers Experiment",
|
||||||
"description": "Containers works by isolating cookie jars using separate origin-attributes defined visually by colored ‘Container Tabs’. This add-on is a modified version of the containers feature for Firefox Test Pilot.",
|
"description": "Containers works by isolating cookie jars using separate origin-attributes defined visually by colored ‘Container Tabs’. This add-on is a modified version of the containers feature for Firefox Test Pilot.",
|
||||||
"version": "1.1.1",
|
"version": "2.0.0",
|
||||||
"author": "Andrea Marchesini, Luke Crouch and Jonathan Kingston",
|
"author": "Andrea Marchesini, Luke Crouch and Jonathan Kingston",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/mozilla/testpilot-containers/issues"
|
"url": "https://github.com/mozilla/testpilot-containers/issues"
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
"addons-linter": "^0.15.14",
|
"addons-linter": "^0.15.14",
|
||||||
"deploy-txp": "^1.0.7",
|
"deploy-txp": "^1.0.7",
|
||||||
"eslint": "^3.17.1",
|
"eslint": "^3.17.1",
|
||||||
|
"eslint-plugin-no-unescaped": "^1.1.0",
|
||||||
"eslint-plugin-promise": "^3.4.0",
|
"eslint-plugin-promise": "^3.4.0",
|
||||||
"eslint-plugin-unsafe-property-assignment": "^1.0.2",
|
|
||||||
"htmllint-cli": "^0.0.5",
|
"htmllint-cli": "^0.0.5",
|
||||||
"jpm": "^1.2.2",
|
"jpm": "^1.2.2",
|
||||||
"npm-run-all": "^4.0.0",
|
"npm-run-all": "^4.0.0",
|
||||||
|
|
|
@ -19,15 +19,15 @@ const P_CONTAINER_EDIT = "containerEdit";
|
||||||
const P_CONTAINER_DELETE = "containerDelete";
|
const P_CONTAINER_DELETE = "containerDelete";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escapes any occurances of &, ", < or > with XML entities.
|
* Escapes any occurances of &, ", <, > or / with XML entities.
|
||||||
*
|
*
|
||||||
* @param {string} str
|
* @param {string} str
|
||||||
* The string to escape.
|
* The string to escape.
|
||||||
* @return {string} The escaped string.
|
* @return {string} The escaped string.
|
||||||
*/
|
*/
|
||||||
function escapeXML(str) {
|
function escapeXML(str) {
|
||||||
const replacements = {"&": "&", "\"": """, "'": "'", "<": "<", ">": ">"};
|
const replacements = {"&": "&", "\"": """, "'": "'", "<": "<", ">": ">", "/": "/"};
|
||||||
return String(str).replace(/[&"''<>]/g, m => replacements[m]);
|
return String(str).replace(/[&"'<>/]/g, m => replacements[m]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -278,7 +278,8 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
|
||||||
data-identity-color="${identity.color}">
|
data-identity-color="${identity.color}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-name">${identity.name}</div>`;
|
<div class="container-name"></div>`;
|
||||||
|
context.querySelector(".container-name").textContent = identity.name;
|
||||||
manage.innerHTML = "<img src='/img/container-arrow.svg' class='show-tabs pop-button-image-small' />";
|
manage.innerHTML = "<img src='/img/container-arrow.svg' class='show-tabs pop-button-image-small' />";
|
||||||
|
|
||||||
fragment.appendChild(tr);
|
fragment.appendChild(tr);
|
||||||
|
@ -353,7 +354,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
|
|
||||||
fragment.appendChild(incompatEl);
|
fragment.appendChild(incompatEl);
|
||||||
incompatEl.setAttribute("id", "container-info-movetabs-incompat");
|
incompatEl.setAttribute("id", "container-info-movetabs-incompat");
|
||||||
incompatEl.innerText = "Incompatible with other Experiments.";
|
incompatEl.textContent = "Incompatible with other Experiments.";
|
||||||
incompatEl.classList.add("container-info-tab-row");
|
incompatEl.classList.add("container-info-tab-row");
|
||||||
|
|
||||||
moveTabsEl.parentNode.insertBefore(fragment, moveTabsEl.nextSibling);
|
moveTabsEl.parentNode.insertBefore(fragment, moveTabsEl.nextSibling);
|
||||||
|
@ -377,7 +378,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
const identity = Logic.currentIdentity();
|
const identity = Logic.currentIdentity();
|
||||||
|
|
||||||
// Populating the panel: name and icon
|
// Populating the panel: name and icon
|
||||||
document.getElementById("container-info-name").innerText = 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.image);
|
||||||
|
@ -392,7 +393,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
hideShowIcon.src = identity.hasHiddenTabs ? CONTAINER_UNHIDE_SRC : CONTAINER_HIDE_SRC;
|
hideShowIcon.src = identity.hasHiddenTabs ? CONTAINER_UNHIDE_SRC : CONTAINER_HIDE_SRC;
|
||||||
|
|
||||||
const hideShowLabel = document.getElementById("container-info-hideorshow-label");
|
const hideShowLabel = document.getElementById("container-info-hideorshow-label");
|
||||||
hideShowLabel.innerText = identity.hasHiddenTabs ? "Show this container" : "Hide this container";
|
hideShowLabel.textContent = identity.hasHiddenTabs ? "Show this container" : "Hide this container";
|
||||||
|
|
||||||
// Let's remove all the previous tabs.
|
// Let's remove all the previous tabs.
|
||||||
const table = document.getElementById("container-info-table");
|
const table = document.getElementById("container-info-table");
|
||||||
|
@ -466,21 +467,23 @@ Logic.registerPanel(P_CONTAINERS_EDIT, {
|
||||||
data-identity-color="${identity.color}">
|
data-identity-color="${identity.color}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-name">${identity.name}</div>
|
<div class="container-name"></div>
|
||||||
</td>
|
</td>
|
||||||
<td class="edit-container pop-button edit-container-icon">
|
<td class="edit-container pop-button edit-container-icon">
|
||||||
<img
|
<img
|
||||||
title="Edit ${identity.name} container"
|
|
||||||
src="/img/container-edit.svg"
|
src="/img/container-edit.svg"
|
||||||
class="pop-button-image" />
|
class="pop-button-image" />
|
||||||
</td>
|
</td>
|
||||||
<td class="remove-container pop-button delete-container-icon" >
|
<td class="remove-container pop-button delete-container-icon" >
|
||||||
<img
|
<img
|
||||||
title="Remove ${identity.name} container"
|
|
||||||
class="pop-button-image"
|
class="pop-button-image"
|
||||||
src="/img/container-delete.svg"
|
src="/img/container-delete.svg"
|
||||||
/>
|
/>
|
||||||
</td>`;
|
</td>`;
|
||||||
|
tr.querySelector(".container-name").textContent = identity.name;
|
||||||
|
tr.querySelector(".edit-container .pop-button-image").setAttribute("title", `Edit ${identity.name} container`);
|
||||||
|
tr.querySelector(".remove-container .pop-button-image").setAttribute("title", `Edit ${identity.name} container`);
|
||||||
|
|
||||||
|
|
||||||
tr.addEventListener("click", e => {
|
tr.addEventListener("click", e => {
|
||||||
if (e.target.matches(".edit-container-icon") || e.target.parentNode.matches(".edit-container-icon")) {
|
if (e.target.matches(".edit-container-icon") || e.target.parentNode.matches(".edit-container-icon")) {
|
||||||
|
@ -552,7 +555,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
const colorRadioFieldset = document.getElementById("edit-container-panel-choose-color");
|
const colorRadioFieldset = document.getElementById("edit-container-panel-choose-color");
|
||||||
colors.forEach((containerColor) => {
|
colors.forEach((containerColor) => {
|
||||||
const templateInstance = document.createElement("span");
|
const templateInstance = document.createElement("span");
|
||||||
// eslint-disable-next-line unsafe-property-assignment/enforce-tagged-template-protection
|
// eslint-disable-next-line no-unescaped/enforce
|
||||||
templateInstance.innerHTML = colorRadioTemplate(containerColor);
|
templateInstance.innerHTML = colorRadioTemplate(containerColor);
|
||||||
colorRadioFieldset.appendChild(templateInstance);
|
colorRadioFieldset.appendChild(templateInstance);
|
||||||
});
|
});
|
||||||
|
@ -565,7 +568,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
const iconRadioFieldset = document.getElementById("edit-container-panel-choose-icon");
|
const iconRadioFieldset = document.getElementById("edit-container-panel-choose-icon");
|
||||||
icons.forEach((containerIcon) => {
|
icons.forEach((containerIcon) => {
|
||||||
const templateInstance = document.createElement("span");
|
const templateInstance = document.createElement("span");
|
||||||
// eslint-disable-next-line unsafe-property-assignment/enforce-tagged-template-protection
|
// eslint-disable-next-line no-unescaped/enforce
|
||||||
templateInstance.innerHTML = iconRadioTemplate(containerIcon);
|
templateInstance.innerHTML = iconRadioTemplate(containerIcon);
|
||||||
iconRadioFieldset.appendChild(templateInstance);
|
iconRadioFieldset.appendChild(templateInstance);
|
||||||
});
|
});
|
||||||
|
@ -618,7 +621,7 @@ Logic.registerPanel(P_CONTAINER_DELETE, {
|
||||||
const identity = Logic.currentIdentity();
|
const identity = Logic.currentIdentity();
|
||||||
|
|
||||||
// Populating the panel: name and icon
|
// Populating the panel: name and icon
|
||||||
document.getElementById("delete-container-name").innerText = 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.image);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Containers Experiment",
|
"name": "Containers Experiment",
|
||||||
"version": "1.1.1",
|
"version": "2.0.0",
|
||||||
|
|
||||||
"description": "Containers works by isolating cookie jars using separate origin-attributes defined visually by colored ‘Container Tabs’. This add-on is a modified version of the containers feature for Firefox Test Pilot.",
|
"description": "Containers works by isolating cookie jars using separate origin-attributes defined visually by colored ‘Container Tabs’. This add-on is a modified version of the containers feature for Firefox Test Pilot.",
|
||||||
"icons": {
|
"icons": {
|
||||||
|
|
Loading…
Add table
Reference in a new issue