Page action assigns site to a container and simultaneously reopens site in container.
This commit is contained in:
parent
dd6f084ad1
commit
00f1be774c
9 changed files with 235 additions and 117 deletions
|
@ -46,7 +46,7 @@ module.exports = {
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
"escape": {
|
"escape": {
|
||||||
"taggedTemplates": ["escaped"]
|
"taggedTemplates": ["escaped", "Utils.escaped"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -8,6 +8,7 @@ module.exports = {
|
||||||
"backgroundLogic": true,
|
"backgroundLogic": true,
|
||||||
"identityState": true,
|
"identityState": true,
|
||||||
"messageHandler": true,
|
"messageHandler": true,
|
||||||
"sync": true
|
"sync": true,
|
||||||
|
"Utils": true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -474,6 +474,7 @@ window.assignManager = {
|
||||||
},
|
},
|
||||||
|
|
||||||
async _setOrRemoveAssignment(tabId, pageUrl, userContextId, remove) {
|
async _setOrRemoveAssignment(tabId, pageUrl, userContextId, remove) {
|
||||||
|
console.log(userContextId)
|
||||||
let actionName;
|
let actionName;
|
||||||
|
|
||||||
// https://github.com/mozilla/testpilot-containers/issues/626
|
// https://github.com/mozilla/testpilot-containers/issues/626
|
||||||
|
|
|
@ -73,6 +73,16 @@ const messageHandler = {
|
||||||
case "exemptContainerAssignment":
|
case "exemptContainerAssignment":
|
||||||
response = assignManager._exemptTab(m);
|
response = assignManager._exemptTab(m);
|
||||||
break;
|
break;
|
||||||
|
case "reloadInContainer":
|
||||||
|
response = assignManager.reloadPageInContainer(
|
||||||
|
m.url,
|
||||||
|
m.currentUserContextId,
|
||||||
|
m.newUserContextId,
|
||||||
|
m.tabIndex,
|
||||||
|
m.active,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
|
51
src/js/pageAction.js
Normal file
51
src/js/pageAction.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
async function init() {
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
|
const identities = await browser.contextualIdentities.query({});
|
||||||
|
|
||||||
|
identities.forEach(identity => {
|
||||||
|
const tr = document.createElement("tr");
|
||||||
|
tr.classList.add("menu-item");
|
||||||
|
const td = document.createElement("td");
|
||||||
|
|
||||||
|
td.innerHTML = Utils.escaped`
|
||||||
|
<div class="menu-icon">
|
||||||
|
<div class="usercontext-icon"
|
||||||
|
data-identity-icon="${identity.icon}"
|
||||||
|
data-identity-color="${identity.color}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="menu-text">${identity.name}</span>`;
|
||||||
|
|
||||||
|
fragment.appendChild(tr);
|
||||||
|
|
||||||
|
tr.appendChild(td);
|
||||||
|
|
||||||
|
Utils.addEnterHandler(tr, async () => {
|
||||||
|
const currentTab = await Utils.currentTab();
|
||||||
|
const assignedUserContextId = Utils.userContextId(identity.cookieStoreId);
|
||||||
|
Utils.setOrRemoveAssignment(
|
||||||
|
currentTab.id,
|
||||||
|
currentTab.url,
|
||||||
|
assignedUserContextId,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
console.log(currentTab);
|
||||||
|
Utils.reloadInContainer(
|
||||||
|
currentTab.url,
|
||||||
|
false,
|
||||||
|
assignedUserContextId,
|
||||||
|
currentTab.index + 1,
|
||||||
|
currentTab.active
|
||||||
|
);
|
||||||
|
window.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const list = document.querySelector("#picker-identities-list");
|
||||||
|
|
||||||
|
list.innerHTML = "";
|
||||||
|
list.appendChild(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
157
src/js/popup.js
157
src/js/popup.js
|
@ -30,41 +30,6 @@ const P_CONTAINER_EDIT = "containerEdit";
|
||||||
const P_CONTAINER_DELETE = "containerDelete";
|
const P_CONTAINER_DELETE = "containerDelete";
|
||||||
const P_CONTAINERS_ACHIEVEMENT = "containersAchievement";
|
const P_CONTAINERS_ACHIEVEMENT = "containersAchievement";
|
||||||
|
|
||||||
/**
|
|
||||||
* Escapes any occurances of &, ", <, > or / with XML entities.
|
|
||||||
*
|
|
||||||
* @param {string} str
|
|
||||||
* The string to escape.
|
|
||||||
* @return {string} The escaped string.
|
|
||||||
*/
|
|
||||||
function escapeXML(str) {
|
|
||||||
const replacements = { "&": "&", "\"": """, "'": "'", "<": "<", ">": ">", "/": "/" };
|
|
||||||
return String(str).replace(/[&"'<>/]/g, m => replacements[m]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A tagged template function which escapes any XML metacharacters in
|
|
||||||
* interpolated values.
|
|
||||||
*
|
|
||||||
* @param {Array<string>} strings
|
|
||||||
* An array of literal strings extracted from the templates.
|
|
||||||
* @param {Array} values
|
|
||||||
* An array of interpolated values extracted from the template.
|
|
||||||
* @returns {string}
|
|
||||||
* The result of the escaped values interpolated with the literal
|
|
||||||
* strings.
|
|
||||||
*/
|
|
||||||
function escaped(strings, ...values) {
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
for (const [i, string] of strings.entries()) {
|
|
||||||
result.push(string);
|
|
||||||
if (i < values.length)
|
|
||||||
result.push(escapeXML(values[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getExtensionInfo() {
|
async function getExtensionInfo() {
|
||||||
const manifestPath = browser.extension.getURL("manifest.json");
|
const manifestPath = browser.extension.getURL("manifest.json");
|
||||||
|
@ -201,31 +166,6 @@ const Logic = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
addEnterHandler(element, handler) {
|
|
||||||
element.addEventListener("click", (e) => {
|
|
||||||
handler(e);
|
|
||||||
});
|
|
||||||
element.addEventListener("keydown", (e) => {
|
|
||||||
if (e.keyCode === 13) {
|
|
||||||
e.preventDefault();
|
|
||||||
handler(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
userContextId(cookieStoreId = "") {
|
|
||||||
const userContextId = cookieStoreId.replace("firefox-container-", "");
|
|
||||||
return (userContextId !== cookieStoreId) ? Number(userContextId) : false;
|
|
||||||
},
|
|
||||||
|
|
||||||
async currentTab() {
|
|
||||||
const activeTabs = await browser.tabs.query({ active: true, windowId: browser.windows.WINDOW_ID_CURRENT });
|
|
||||||
if (activeTabs.length > 0) {
|
|
||||||
return activeTabs[0];
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
async numTabs() {
|
async numTabs() {
|
||||||
const activeTabs = await browser.tabs.query({ windowId: browser.windows.WINDOW_ID_CURRENT });
|
const activeTabs = await browser.tabs.query({ windowId: browser.windows.WINDOW_ID_CURRENT });
|
||||||
return activeTabs.length;
|
return activeTabs.length;
|
||||||
|
@ -338,7 +278,7 @@ const Logic = {
|
||||||
|
|
||||||
currentUserContextId() {
|
currentUserContextId() {
|
||||||
const identity = Logic.currentIdentity();
|
const identity = Logic.currentIdentity();
|
||||||
return Logic.userContextId(identity.cookieStoreId);
|
return Utils.userContextId(identity.cookieStoreId);
|
||||||
},
|
},
|
||||||
|
|
||||||
currentCookieStoreId() {
|
currentCookieStoreId() {
|
||||||
|
@ -374,16 +314,6 @@ const Logic = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setOrRemoveAssignment(tabId, url, userContextId, value) {
|
|
||||||
return browser.runtime.sendMessage({
|
|
||||||
method: "setOrRemoveAssignment",
|
|
||||||
tabId,
|
|
||||||
url,
|
|
||||||
userContextId,
|
|
||||||
value
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
generateIdentityName() {
|
generateIdentityName() {
|
||||||
const defaultName = "Container #";
|
const defaultName = "Container #";
|
||||||
const ids = [];
|
const ids = [];
|
||||||
|
@ -423,7 +353,7 @@ Logic.registerPanel(P_ONBOARDING_1, {
|
||||||
initialize() {
|
initialize() {
|
||||||
// Let's move to the next panel.
|
// Let's move to the next panel.
|
||||||
[...document.querySelectorAll(".onboarding-start-button")].forEach(startElement => {
|
[...document.querySelectorAll(".onboarding-start-button")].forEach(startElement => {
|
||||||
Logic.addEnterHandler(startElement, async () => {
|
Utils.addEnterHandler(startElement, async () => {
|
||||||
await Logic.setOnboardingStage(1);
|
await Logic.setOnboardingStage(1);
|
||||||
Logic.showPanel(P_ONBOARDING_2);
|
Logic.showPanel(P_ONBOARDING_2);
|
||||||
});
|
});
|
||||||
|
@ -447,7 +377,7 @@ Logic.registerPanel(P_ONBOARDING_2, {
|
||||||
initialize() {
|
initialize() {
|
||||||
// Let's move to the containers list panel.
|
// Let's move to the containers list panel.
|
||||||
[...document.querySelectorAll(".onboarding-next-button")].forEach(nextElement => {
|
[...document.querySelectorAll(".onboarding-next-button")].forEach(nextElement => {
|
||||||
Logic.addEnterHandler(nextElement, async () => {
|
Utils.addEnterHandler(nextElement, async () => {
|
||||||
await Logic.setOnboardingStage(2);
|
await Logic.setOnboardingStage(2);
|
||||||
Logic.showPanel(P_ONBOARDING_3);
|
Logic.showPanel(P_ONBOARDING_3);
|
||||||
});
|
});
|
||||||
|
@ -471,7 +401,7 @@ Logic.registerPanel(P_ONBOARDING_3, {
|
||||||
initialize() {
|
initialize() {
|
||||||
// Let's move to the containers list panel.
|
// Let's move to the containers list panel.
|
||||||
[...document.querySelectorAll(".onboarding-almost-done-button")].forEach(almostElement => {
|
[...document.querySelectorAll(".onboarding-almost-done-button")].forEach(almostElement => {
|
||||||
Logic.addEnterHandler(almostElement, async () => {
|
Utils.addEnterHandler(almostElement, async () => {
|
||||||
await Logic.setOnboardingStage(3);
|
await Logic.setOnboardingStage(3);
|
||||||
Logic.showPanel(P_ONBOARDING_4);
|
Logic.showPanel(P_ONBOARDING_4);
|
||||||
});
|
});
|
||||||
|
@ -493,7 +423,7 @@ Logic.registerPanel(P_ONBOARDING_4, {
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
initialize() {
|
initialize() {
|
||||||
// Let's move to the containers list panel.
|
// Let's move to the containers list panel.
|
||||||
Logic.addEnterHandler(document.querySelector("#onboarding-done-button"), async () => {
|
Utils.addEnterHandler(document.querySelector("#onboarding-done-button"), async () => {
|
||||||
await Logic.setOnboardingStage(4);
|
await Logic.setOnboardingStage(4);
|
||||||
Logic.showPanel(P_ONBOARDING_5);
|
Logic.showPanel(P_ONBOARDING_5);
|
||||||
});
|
});
|
||||||
|
@ -514,7 +444,7 @@ Logic.registerPanel(P_ONBOARDING_5, {
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
initialize() {
|
initialize() {
|
||||||
// Let's move to the containers list panel.
|
// Let's move to the containers list panel.
|
||||||
Logic.addEnterHandler(document.querySelector("#onboarding-longpress-button"), async () => {
|
Utils.addEnterHandler(document.querySelector("#onboarding-longpress-button"), async () => {
|
||||||
await Logic.setOnboardingStage(5);
|
await Logic.setOnboardingStage(5);
|
||||||
Logic.showPanel(P_ONBOARDING_6);
|
Logic.showPanel(P_ONBOARDING_6);
|
||||||
});
|
});
|
||||||
|
@ -535,7 +465,7 @@ Logic.registerPanel(P_ONBOARDING_6, {
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
initialize() {
|
initialize() {
|
||||||
// Let's move to the containers list panel.
|
// Let's move to the containers list panel.
|
||||||
Logic.addEnterHandler(document.querySelector("#start-sync-button"), async () => {
|
Utils.addEnterHandler(document.querySelector("#start-sync-button"), async () => {
|
||||||
await Logic.setOnboardingStage(6);
|
await Logic.setOnboardingStage(6);
|
||||||
await browser.storage.local.set({syncEnabled: true});
|
await browser.storage.local.set({syncEnabled: true});
|
||||||
await browser.runtime.sendMessage({
|
await browser.runtime.sendMessage({
|
||||||
|
@ -543,7 +473,7 @@ Logic.registerPanel(P_ONBOARDING_6, {
|
||||||
});
|
});
|
||||||
Logic.showPanel(P_ONBOARDING_7);
|
Logic.showPanel(P_ONBOARDING_7);
|
||||||
});
|
});
|
||||||
Logic.addEnterHandler(document.querySelector("#no-sync"), async () => {
|
Utils.addEnterHandler(document.querySelector("#no-sync"), async () => {
|
||||||
await Logic.setOnboardingStage(7);
|
await Logic.setOnboardingStage(7);
|
||||||
await browser.storage.local.set({syncEnabled: false});
|
await browser.storage.local.set({syncEnabled: false});
|
||||||
await browser.runtime.sendMessage({
|
await browser.runtime.sendMessage({
|
||||||
|
@ -568,14 +498,14 @@ Logic.registerPanel(P_ONBOARDING_7, {
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
initialize() {
|
initialize() {
|
||||||
// Let's move to the containers list panel.
|
// Let's move to the containers list panel.
|
||||||
Logic.addEnterHandler(document.querySelector("#sign-in"), async () => {
|
Utils.addEnterHandler(document.querySelector("#sign-in"), async () => {
|
||||||
browser.tabs.create({
|
browser.tabs.create({
|
||||||
url: "https://accounts.firefox.com/?service=sync&action=email&context=fx_desktop_v3&entrypoint=multi-account-containers&utm_source=addon&utm_medium=panel&utm_campaign=container-sync",
|
url: "https://accounts.firefox.com/?service=sync&action=email&context=fx_desktop_v3&entrypoint=multi-account-containers&utm_source=addon&utm_medium=panel&utm_campaign=container-sync",
|
||||||
});
|
});
|
||||||
await Logic.setOnboardingStage(7);
|
await Logic.setOnboardingStage(7);
|
||||||
Logic.showPanel(P_CONTAINERS_LIST);
|
Logic.showPanel(P_CONTAINERS_LIST);
|
||||||
});
|
});
|
||||||
Logic.addEnterHandler(document.querySelector("#no-sign-in"), async () => {
|
Utils.addEnterHandler(document.querySelector("#no-sign-in"), async () => {
|
||||||
await Logic.setOnboardingStage(7);
|
await Logic.setOnboardingStage(7);
|
||||||
Logic.showPanel(P_CONTAINERS_LIST);
|
Logic.showPanel(P_CONTAINERS_LIST);
|
||||||
});
|
});
|
||||||
|
@ -594,21 +524,21 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
|
||||||
|
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
async initialize() {
|
async initialize() {
|
||||||
Logic.addEnterHandler(document.querySelector("#manage-containers-link"), (e) => {
|
Utils.addEnterHandler(document.querySelector("#manage-containers-link"), (e) => {
|
||||||
if (!e.target.classList.contains("disable-edit-containers")) {
|
if (!e.target.classList.contains("disable-edit-containers")) {
|
||||||
Logic.showPanel(P_CONTAINER_PICKER, null, MANAGE_CONTAINERS_PICKER);
|
Logic.showPanel(P_CONTAINER_PICKER, null, MANAGE_CONTAINERS_PICKER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Logic.addEnterHandler(document.querySelector("#open-new-tab-in"), () => {
|
Utils.addEnterHandler(document.querySelector("#open-new-tab-in"), () => {
|
||||||
Logic.showPanel(P_CONTAINER_PICKER, null, OPEN_NEW_CONTAINER_PICKER);
|
Logic.showPanel(P_CONTAINER_PICKER, null, OPEN_NEW_CONTAINER_PICKER);
|
||||||
});
|
});
|
||||||
Logic.addEnterHandler(document.querySelector("#reopen-site-in"), () => {
|
Utils.addEnterHandler(document.querySelector("#reopen-site-in"), () => {
|
||||||
Logic.showPanel(P_CONTAINER_PICKER, null, REOPEN_IN_CONTAINER);
|
Logic.showPanel(P_CONTAINER_PICKER, null, REOPEN_IN_CONTAINER);
|
||||||
});
|
});
|
||||||
Logic.addEnterHandler(document.querySelector("#always-open-in"), () => {
|
Utils.addEnterHandler(document.querySelector("#always-open-in"), () => {
|
||||||
Logic.showPanel(P_CONTAINER_PICKER, null, ALWAYS_OPEN_IN_PICKER);
|
Logic.showPanel(P_CONTAINER_PICKER, null, ALWAYS_OPEN_IN_PICKER);
|
||||||
});
|
});
|
||||||
Logic.addEnterHandler(document.querySelector("#sort-containers-link"), async () => {
|
Utils.addEnterHandler(document.querySelector("#sort-containers-link"), async () => {
|
||||||
try {
|
try {
|
||||||
await browser.runtime.sendMessage({
|
await browser.runtime.sendMessage({
|
||||||
method: "sortTabs"
|
method: "sortTabs"
|
||||||
|
@ -693,7 +623,7 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
|
||||||
const td = document.createElement("td");
|
const td = document.createElement("td");
|
||||||
const openTabs = identity.numberOfOpenTabs || "" ;
|
const openTabs = identity.numberOfOpenTabs || "" ;
|
||||||
|
|
||||||
td.innerHTML = escaped`
|
td.innerHTML = Utils.escaped`
|
||||||
<div class="menu-icon">
|
<div class="menu-icon">
|
||||||
<div class="usercontext-icon"
|
<div class="usercontext-icon"
|
||||||
data-identity-icon="${identity.icon}"
|
data-identity-icon="${identity.icon}"
|
||||||
|
@ -712,7 +642,7 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
|
||||||
|
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
|
|
||||||
Logic.addEnterHandler(tr, () => {
|
Utils.addEnterHandler(tr, () => {
|
||||||
Logic.showPanel(P_CONTAINER_INFO, identity);
|
Logic.showPanel(P_CONTAINER_INFO, identity);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -752,12 +682,12 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
const closeContEl = document.querySelector("#close-container-info-panel");
|
const closeContEl = document.querySelector("#close-container-info-panel");
|
||||||
closeContEl.setAttribute("tabindex", "0");
|
closeContEl.setAttribute("tabindex", "0");
|
||||||
closeContEl.classList.add("firstTabindex");
|
closeContEl.classList.add("firstTabindex");
|
||||||
Logic.addEnterHandler(closeContEl, () => {
|
Utils.addEnterHandler(closeContEl, () => {
|
||||||
Logic.showPreviousPanel();
|
Logic.showPreviousPanel();
|
||||||
});
|
});
|
||||||
const hideContEl = document.querySelector("#container-info-hideorshow");
|
const hideContEl = document.querySelector("#container-info-hideorshow");
|
||||||
hideContEl.setAttribute("tabindex", "0");
|
hideContEl.setAttribute("tabindex", "0");
|
||||||
Logic.addEnterHandler(hideContEl, async () => {
|
Utils.addEnterHandler(hideContEl, async () => {
|
||||||
const identity = Logic.currentIdentity();
|
const identity = Logic.currentIdentity();
|
||||||
try {
|
try {
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
|
@ -790,7 +720,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
Logic._disableMoveTabs("Cannot move a tab from a single-tab window.");
|
Logic._disableMoveTabs("Cannot move a tab from a single-tab window.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Logic.addEnterHandler(moveTabsEl, async () => {
|
Utils.addEnterHandler(moveTabsEl, async () => {
|
||||||
await browser.runtime.sendMessage({
|
await browser.runtime.sendMessage({
|
||||||
method: "moveTabsToWindow",
|
method: "moveTabsToWindow",
|
||||||
windowId: browser.windows.WINDOW_ID_CURRENT,
|
windowId: browser.windows.WINDOW_ID_CURRENT,
|
||||||
|
@ -844,7 +774,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
const tr = document.createElement("tr");
|
const tr = document.createElement("tr");
|
||||||
fragment.appendChild(tr);
|
fragment.appendChild(tr);
|
||||||
tr.classList.add("container-info-tab-row");
|
tr.classList.add("container-info-tab-row");
|
||||||
tr.innerHTML = escaped`
|
tr.innerHTML = Utils.escaped`
|
||||||
<td></td>
|
<td></td>
|
||||||
<td class="container-info-tab-title truncate-text" title="${tab.url}" ><div class="container-tab-title">${tab.title}</div></td>`;
|
<td class="container-info-tab-title truncate-text" title="${tab.url}" ><div class="container-tab-title">${tab.title}</div></td>`;
|
||||||
tr.querySelector("td").appendChild(Utils.createFavIconElement(tab.favIconUrl));
|
tr.querySelector("td").appendChild(Utils.createFavIconElement(tab.favIconUrl));
|
||||||
|
@ -871,14 +801,14 @@ Logic.registerPanel(P_CONTAINER_INFO, {
|
||||||
tr.addEventListener("mouseout", tabTitleHoverEvent);
|
tr.addEventListener("mouseout", tabTitleHoverEvent);
|
||||||
|
|
||||||
tr.classList.add("clickable");
|
tr.classList.add("clickable");
|
||||||
Logic.addEnterHandler(tr, async () => {
|
Utils.addEnterHandler(tr, async () => {
|
||||||
await browser.tabs.update(tab.id, { active: true });
|
await browser.tabs.update(tab.id, { active: true });
|
||||||
window.close();
|
window.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
const closeTab = document.getElementById(tab.id);
|
const closeTab = document.getElementById(tab.id);
|
||||||
if (closeTab) {
|
if (closeTab) {
|
||||||
Logic.addEnterHandler(closeTab, async (e) => {
|
Utils.addEnterHandler(closeTab, async (e) => {
|
||||||
await browser.tabs.remove(Number(e.target.id));
|
await browser.tabs.remove(Number(e.target.id));
|
||||||
window.close();
|
window.close();
|
||||||
});
|
});
|
||||||
|
@ -896,7 +826,7 @@ Logic.registerPanel(P_CONTAINER_PICKER, {
|
||||||
|
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
initialize() {
|
initialize() {
|
||||||
// Logic.addEnterHandler(document.querySelector("#exit-edit-mode-link"), () => {
|
// Utils.addEnterHandler(document.querySelector("#exit-edit-mode-link"), () => {
|
||||||
// Logic.showPanel(P_CONTAINERS_LIST);
|
// Logic.showPanel(P_CONTAINERS_LIST);
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
|
@ -938,13 +868,12 @@ Logic.registerPanel(P_CONTAINER_PICKER, {
|
||||||
case ALWAYS_OPEN_IN_PICKER:
|
case ALWAYS_OPEN_IN_PICKER:
|
||||||
default:
|
default:
|
||||||
pickedFunction = async function (identity) {
|
pickedFunction = async function (identity) {
|
||||||
const currentTab = await Logic.currentTab();
|
const userContextId = Utils.userContextId(identity.cookieStoreId);
|
||||||
console.log(identity.cookieStoreId)
|
const currentTab = await Utils.currentTab();
|
||||||
console.log(identity)
|
Utils.setOrRemoveAssignment(
|
||||||
Logic.setOrRemoveAssignment(
|
|
||||||
currentTab.id,
|
currentTab.id,
|
||||||
currentTab.url,
|
currentTab.url,
|
||||||
identity.cookieStoreId,
|
userContextId,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
window.close();
|
window.close();
|
||||||
|
@ -957,7 +886,7 @@ Logic.registerPanel(P_CONTAINER_PICKER, {
|
||||||
tr.classList.add("menu-item");
|
tr.classList.add("menu-item");
|
||||||
const td = document.createElement("td");
|
const td = document.createElement("td");
|
||||||
|
|
||||||
td.innerHTML = escaped`
|
td.innerHTML = Utils.escaped`
|
||||||
<div class="menu-icon">
|
<div class="menu-icon">
|
||||||
<div class="usercontext-icon"
|
<div class="usercontext-icon"
|
||||||
data-identity-icon="${identity.icon}"
|
data-identity-icon="${identity.icon}"
|
||||||
|
@ -970,7 +899,7 @@ Logic.registerPanel(P_CONTAINER_PICKER, {
|
||||||
|
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
|
|
||||||
Logic.addEnterHandler(tr, () => {
|
Utils.addEnterHandler(tr, () => {
|
||||||
pickedFunction(identity);
|
pickedFunction(identity);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -994,7 +923,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
initialize() {
|
initialize() {
|
||||||
this.initializeRadioButtons();
|
this.initializeRadioButtons();
|
||||||
|
|
||||||
Logic.addEnterHandler(document.querySelector("#edit-container-panel-back-arrow"), () => {
|
Utils.addEnterHandler(document.querySelector("#edit-container-panel-back-arrow"), () => {
|
||||||
const formValues = new FormData(this._editForm);
|
const formValues = new FormData(this._editForm);
|
||||||
if (formValues.get("container-id") !== NEW_CONTAINER_ID) {
|
if (formValues.get("container-id") !== NEW_CONTAINER_ID) {
|
||||||
this._submitForm();
|
this._submitForm();
|
||||||
|
@ -1003,13 +932,13 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Logic.addEnterHandler(document.querySelector("#edit-container-cancel-link"), () => {
|
Utils.addEnterHandler(document.querySelector("#edit-container-cancel-link"), () => {
|
||||||
Logic.showPreviousPanel();
|
Logic.showPreviousPanel();
|
||||||
});
|
});
|
||||||
|
|
||||||
this._editForm = document.getElementById("edit-container-panel-form");
|
this._editForm = document.getElementById("edit-container-panel-form");
|
||||||
const editLink = document.querySelector("#edit-container-ok-link");
|
const editLink = document.querySelector("#edit-container-ok-link");
|
||||||
Logic.addEnterHandler(editLink, () => {
|
Utils.addEnterHandler(editLink, () => {
|
||||||
this._submitForm();
|
this._submitForm();
|
||||||
});
|
});
|
||||||
editLink.addEventListener("submit", () => {
|
editLink.addEventListener("submit", () => {
|
||||||
|
@ -1061,7 +990,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
/* As we don't have the full or correct path the best we can assume is the path is HTTPS and then replace with a broken icon later if it doesn't load.
|
/* As we don't have the full or correct path the best we can assume is the path is HTTPS and then replace with a broken icon later if it doesn't load.
|
||||||
This is pending a better solution for favicons from web extensions */
|
This is pending a better solution for favicons from web extensions */
|
||||||
const assumedUrl = `https://${site.hostname}/favicon.ico`;
|
const assumedUrl = `https://${site.hostname}/favicon.ico`;
|
||||||
trElement.innerHTML = escaped`
|
trElement.innerHTML = Utils.escaped`
|
||||||
<div class="favicon"></div>
|
<div class="favicon"></div>
|
||||||
<div title="${site.hostname}" class="truncate-text hostname">
|
<div title="${site.hostname}" class="truncate-text hostname">
|
||||||
${site.hostname}
|
${site.hostname}
|
||||||
|
@ -1073,12 +1002,12 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
trElement.getElementsByClassName("favicon")[0].appendChild(Utils.createFavIconElement(assumedUrl));
|
trElement.getElementsByClassName("favicon")[0].appendChild(Utils.createFavIconElement(assumedUrl));
|
||||||
const deleteButton = trElement.querySelector(".delete-assignment");
|
const deleteButton = trElement.querySelector(".delete-assignment");
|
||||||
const that = this;
|
const that = this;
|
||||||
Logic.addEnterHandler(deleteButton, async () => {
|
Utils.addEnterHandler(deleteButton, async () => {
|
||||||
const userContextId = Logic.currentUserContextId();
|
const userContextId = Logic.currentUserContextId();
|
||||||
// Lets show the message to the current tab
|
// Lets show the message to the current tab
|
||||||
// TODO remove then when firefox supports arrow fn async
|
// TODO remove then when firefox supports arrow fn async
|
||||||
const currentTab = await Logic.currentTab();
|
const currentTab = await Utils.currentTab();
|
||||||
Logic.setOrRemoveAssignment(currentTab.id, assumedUrl, userContextId, true);
|
Utils.setOrRemoveAssignment(currentTab.id, assumedUrl, userContextId, true);
|
||||||
delete assignments[siteKey];
|
delete assignments[siteKey];
|
||||||
that.showAssignedContainers(assignments);
|
that.showAssignedContainers(assignments);
|
||||||
});
|
});
|
||||||
|
@ -1090,7 +1019,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
|
|
||||||
initializeRadioButtons() {
|
initializeRadioButtons() {
|
||||||
const colorRadioTemplate = (containerColor) => {
|
const colorRadioTemplate = (containerColor) => {
|
||||||
return escaped`<input type="radio" value="${containerColor}" name="container-color" id="edit-container-panel-choose-color-${containerColor}" />
|
return Utils.escaped`<input type="radio" value="${containerColor}" name="container-color" id="edit-container-panel-choose-color-${containerColor}" />
|
||||||
<label for="edit-container-panel-choose-color-${containerColor}" class="usercontext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="${containerColor}">`;
|
<label for="edit-container-panel-choose-color-${containerColor}" class="usercontext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="${containerColor}">`;
|
||||||
};
|
};
|
||||||
const colors = ["blue", "turquoise", "green", "yellow", "orange", "red", "pink", "purple"];
|
const colors = ["blue", "turquoise", "green", "yellow", "orange", "red", "pink", "purple"];
|
||||||
|
@ -1104,7 +1033,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
|
||||||
});
|
});
|
||||||
|
|
||||||
const iconRadioTemplate = (containerIcon) => {
|
const iconRadioTemplate = (containerIcon) => {
|
||||||
return escaped`<input type="radio" value="${containerIcon}" name="container-icon" id="edit-container-panel-choose-icon-${containerIcon}" />
|
return Utils.escaped`<input type="radio" value="${containerIcon}" name="container-icon" id="edit-container-panel-choose-icon-${containerIcon}" />
|
||||||
<label for="edit-container-panel-choose-icon-${containerIcon}" class="usercontext-icon choose-color-icon" data-identity-color="grey" data-identity-icon="${containerIcon}">`;
|
<label for="edit-container-panel-choose-icon-${containerIcon}" class="usercontext-icon choose-color-icon" data-identity-color="grey" data-identity-icon="${containerIcon}">`;
|
||||||
};
|
};
|
||||||
const icons = ["fingerprint", "briefcase", "dollar", "cart", "vacation", "gift", "food", "fruit", "pet", "tree", "chill", "circle"];
|
const icons = ["fingerprint", "briefcase", "dollar", "cart", "vacation", "gift", "food", "fruit", "pet", "tree", "chill", "circle"];
|
||||||
|
@ -1154,18 +1083,18 @@ Logic.registerPanel(P_CONTAINER_DELETE, {
|
||||||
|
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
initialize() {
|
initialize() {
|
||||||
Logic.addEnterHandler(document.querySelector("#delete-container-cancel-link"), () => {
|
Utils.addEnterHandler(document.querySelector("#delete-container-cancel-link"), () => {
|
||||||
Logic.showPreviousPanel();
|
Logic.showPreviousPanel();
|
||||||
});
|
});
|
||||||
|
|
||||||
Logic.addEnterHandler(document.querySelector("#delete-container-ok-link"), async () => {
|
Utils.addEnterHandler(document.querySelector("#delete-container-ok-link"), async () => {
|
||||||
/* This promise wont resolve if the last tab was removed from the window.
|
/* This promise wont resolve if the last tab was removed from the window.
|
||||||
as the message async callback stops listening, this isn't an issue for us however it might be in future
|
as the message async callback stops listening, this isn't an issue for us however it might be in future
|
||||||
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.
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
await Logic.removeIdentity(Logic.userContextId(Logic.currentIdentity().cookieStoreId));
|
await Logic.removeIdentity(Utils.userContextId(Logic.currentIdentity().cookieStoreId));
|
||||||
await Logic.refreshIdentities();
|
await Logic.refreshIdentities();
|
||||||
Logic.showPreviousPanel();
|
Logic.showPreviousPanel();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1206,7 +1135,7 @@ Logic.registerPanel(P_CONTAINERS_ACHIEVEMENT, {
|
||||||
// This method is called when the object is registered.
|
// This method is called when the object is registered.
|
||||||
initialize() {
|
initialize() {
|
||||||
// Set done and move to the containers list panel.
|
// Set done and move to the containers list panel.
|
||||||
Logic.addEnterHandler(document.querySelector("#achievement-done-button"), async () => {
|
Utils.addEnterHandler(document.querySelector("#achievement-done-button"), async () => {
|
||||||
await Logic.setAchievementDone("manyContainersOpened");
|
await Logic.setAchievementDone("manyContainersOpened");
|
||||||
Logic.showPanel(P_CONTAINERS_LIST);
|
Logic.showPanel(P_CONTAINERS_LIST);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const DEFAULT_FAVICON = "/img/blank-favicon.svg";
|
const DEFAULT_FAVICON = "/img/blank-favicon.svg";
|
||||||
|
|
||||||
// TODO use export here instead of globals
|
// TODO use export here instead of globals
|
||||||
window.Utils = {
|
const Utils = {
|
||||||
|
|
||||||
createFavIconElement(url) {
|
createFavIconElement(url) {
|
||||||
const imageElement = document.createElement("img");
|
const imageElement = document.createElement("img");
|
||||||
|
@ -18,6 +18,90 @@ window.Utils = {
|
||||||
imageElement.addEventListener("error", errorListener);
|
imageElement.addEventListener("error", errorListener);
|
||||||
imageElement.addEventListener("load", loadListener);
|
imageElement.addEventListener("load", loadListener);
|
||||||
return imageElement;
|
return imageElement;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Escapes any occurances of &, ", <, > or / with XML entities.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* The string to escape.
|
||||||
|
* @return {string} The escaped string.
|
||||||
|
*/
|
||||||
|
escapeXML(str) {
|
||||||
|
const replacements = { "&": "&", "\"": """, "'": "'", "<": "<", ">": ">", "/": "/" };
|
||||||
|
return String(str).replace(/[&"'<>/]/g, m => replacements[m]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tagged template function which escapes any XML metacharacters in
|
||||||
|
* interpolated values.
|
||||||
|
*
|
||||||
|
* @param {Array<string>} strings
|
||||||
|
* An array of literal strings extracted from the templates.
|
||||||
|
* @param {Array} values
|
||||||
|
* An array of interpolated values extracted from the template.
|
||||||
|
* @returns {string}
|
||||||
|
* The result of the escaped values interpolated with the literal
|
||||||
|
* strings.
|
||||||
|
*/
|
||||||
|
escaped(strings, ...values) {
|
||||||
|
const result = [];
|
||||||
|
|
||||||
|
for (const [i, string] of strings.entries()) {
|
||||||
|
result.push(string);
|
||||||
|
if (i < values.length)
|
||||||
|
result.push(this.escapeXML(values[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.join("");
|
||||||
|
},
|
||||||
|
|
||||||
|
async currentTab() {
|
||||||
|
const activeTabs = await browser.tabs.query({ active: true, windowId: browser.windows.WINDOW_ID_CURRENT });
|
||||||
|
if (activeTabs.length > 0) {
|
||||||
|
return activeTabs[0];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
addEnterHandler(element, handler) {
|
||||||
|
element.addEventListener("click", (e) => {
|
||||||
|
handler(e);
|
||||||
|
});
|
||||||
|
element.addEventListener("keydown", (e) => {
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
e.preventDefault();
|
||||||
|
handler(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
userContextId(cookieStoreId = "") {
|
||||||
|
const userContextId = cookieStoreId.replace("firefox-container-", "");
|
||||||
|
return (userContextId !== cookieStoreId) ? Number(userContextId) : false;
|
||||||
|
},
|
||||||
|
|
||||||
|
setOrRemoveAssignment(tabId, url, userContextId, value) {
|
||||||
|
return browser.runtime.sendMessage({
|
||||||
|
method: "setOrRemoveAssignment",
|
||||||
|
tabId,
|
||||||
|
url,
|
||||||
|
userContextId,
|
||||||
|
value
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
reloadInContainer(url, currentUserContextId, newUserContextId, tabIndex, active) {
|
||||||
|
return browser.runtime.sendMessage({
|
||||||
|
method: "reloadInContainer",
|
||||||
|
url,
|
||||||
|
currentUserContextId,
|
||||||
|
newUserContextId,
|
||||||
|
tabIndex,
|
||||||
|
active
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
window.Utils = Utils;
|
|
@ -66,6 +66,14 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"page_action": {
|
||||||
|
"browser_style": true,
|
||||||
|
"default_icon": "img/container-site.svg",
|
||||||
|
"default_title": "Always open this in a Container",
|
||||||
|
"default_popup": "pageActionPopup.html",
|
||||||
|
"pinned": false,
|
||||||
|
"show_matches": ["*://*/*"]
|
||||||
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"page": "js/background/index.html"
|
"page": "js/background/index.html"
|
||||||
},
|
},
|
||||||
|
|
34
src/pageActionPopup.html
Normal file
34
src/pageActionPopup.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
|
<title>Multi-Account Containers</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/popup.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="page-action-container-picker" id="container-picker-panel">
|
||||||
|
<h3 class="title">
|
||||||
|
Reopen and Always Open this Site in...
|
||||||
|
</h3>
|
||||||
|
<hr>
|
||||||
|
<div class="scrollable identities-list">
|
||||||
|
<table class="menu" id="picker-identities-list">
|
||||||
|
<tr class="menu-item">
|
||||||
|
<td>
|
||||||
|
<div class="menu-icon">
|
||||||
|
<div class="usercontext-icon"
|
||||||
|
data-identity-icon="pet"
|
||||||
|
data-identity-color="blue">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="menu-text">Default</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="js/utils.js"></script>
|
||||||
|
<script src="js/pageAction.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Reference in a new issue