From 0a58786936a6874f1dbe2bca499121584765e81b Mon Sep 17 00:00:00 2001 From: baku Date: Fri, 24 Feb 2017 08:17:30 +0100 Subject: [PATCH 1/9] This addon should work when tabCenter is installed - issue #258 --- index.js | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index 228edd7..8e1c054 100644 --- a/index.js +++ b/index.js @@ -1101,14 +1101,16 @@ ContainerWindow.prototype = { }, _configurePlusButtonMenuElement(buttonElement) { - // Let's remove the tooltip because it can go over our panel. - this._tooltipCache.set(buttonElement, buttonElement.getAttribute("tooltip")); - buttonElement.setAttribute("tooltip", ""); - this._disableElement(buttonElement); + if (buttonElement) { + // Let's remove the tooltip because it can go over our panel. + this._tooltipCache.set(buttonElement, buttonElement.getAttribute("tooltip")); + buttonElement.setAttribute("tooltip", ""); + this._disableElement(buttonElement); - buttonElement.addEventListener("mouseover", this); - buttonElement.addEventListener("click", this); - buttonElement.addEventListener("mouseout", this); + buttonElement.addEventListener("mouseover", this); + buttonElement.addEventListener("click", this); + buttonElement.addEventListener("mouseout", this); + } }, _configurePlusButtonMenu() { @@ -1318,12 +1320,14 @@ ContainerWindow.prototype = { }, _shutDownPlusButtonMenuElement(buttonElement) { - this._shutdownElement(buttonElement); - buttonElement.setAttribute("tooltip", this._tooltipCache.get(buttonElement)); + if (buttonElement) { + this._shutdownElement(buttonElement); + buttonElement.setAttribute("tooltip", this._tooltipCache.get(buttonElement)); - buttonElement.removeEventListener("mouseover", this); - buttonElement.removeEventListener("click", this); - buttonElement.removeEventListener("mouseout", this); + buttonElement.removeEventListener("mouseover", this); + buttonElement.removeEventListener("click", this); + buttonElement.removeEventListener("mouseout", this); + } }, _shutdownPlusButtonMenu() { From e013625710b5c0bcd15ae69896494060e76e52c3 Mon Sep 17 00:00:00 2001 From: baku Date: Fri, 24 Feb 2017 08:42:45 +0100 Subject: [PATCH 2/9] Default Containers re-created if the addon is installed/enabled - issue #255 --- index.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/index.js b/index.js index 228edd7..40b35c3 100644 --- a/index.js +++ b/index.js @@ -139,6 +139,17 @@ const ContainerService = { identity.color); } } + + // Let's create the default containers in case there are none. + if (prefService.get("privacy.userContext.enabled") !== true && + ss.storage.savedConfiguration.preInstalledIdentities.length === 0) { + // Note: we have to create them in this way because there is no way to + // reuse the same ID and the localized strings. + ContextualIdentityService.create("Personal", "fingerprint", "blue"); + ContextualIdentityService.create("Work", "briefcase", "orange"); + ContextualIdentityService.create("Finance", "dollar", "green"); + ContextualIdentityService.create("Shopping", "cart", "pink"); + } } // Enabling preferences From c81851e3bd57451a8f17ac620c5de9353d917745 Mon Sep 17 00:00:00 2001 From: groovecoder Date: Fri, 24 Feb 2017 08:52:57 -0800 Subject: [PATCH 3/9] 0.9.5 --- package.json | 2 +- webextension/manifest.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d8abfac..450064d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "testpilot-containers", "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.", - "version": "0.9.4", + "version": "0.9.5", "author": "Andrea Marchesini, Luke Crouch and Jonathan Kingston", "bugs": { "url": "https://github.com/mozilla/testpilot-containers/issues" diff --git a/webextension/manifest.json b/webextension/manifest.json index da48e73..05d358c 100644 --- a/webextension/manifest.json +++ b/webextension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Containers Experiment", - "version": "0.9.4", + "version": "0.9.5", "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": { From 4ec371df6c9d740980c682ae25eafbec4b047112 Mon Sep 17 00:00:00 2001 From: baku Date: Fri, 24 Feb 2017 08:29:34 +0100 Subject: [PATCH 4/9] Move to new window should show hidden tabs as well - issue #257 --- index.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 458983e..1680f8d 100644 --- a/index.js +++ b/index.js @@ -684,6 +684,11 @@ const ContainerService = { return; } + this._remapTabsIfMissing(args.userContextId); + if (!this._isKnownContainer(args.userContextId)) { + return Promise.resolve(null); + } + this.sendTelemetryPayload({ "event": "move-tabs-to-window", "userContextId": args.userContextId, @@ -697,7 +702,8 @@ const ContainerService = { }); // Nothing to do - if (list.length === 0) { + if (list.length === 0 && + this._identitiesState[args.userContextId].hiddenTabs.length === 0) { resolve(null); return; } @@ -713,6 +719,13 @@ const ContainerService = { newBrowserWindow.gBrowser.adoptTab(viewFor(tab), pos++, false); } + // Let's show the hidden tabs. + for (let object of this._identitiesState[args.userContextId].hiddenTabs) { // eslint-disable-line prefer-const + newBrowserWindow.gBrowser.addTab(object.url || DEFAULT_TAB, { userContextId: args.userContextId }); + } + + this._identitiesState[args.userContextId].hiddenTabs = []; + // Let's close all the normal tab in the new window. In theory it // should be only the first tab, but maybe there are addons doing // crazy stuff. From 32bb73f661f0208ae1cbc701828f79089b3bfe83 Mon Sep 17 00:00:00 2001 From: Jonathan Kingston Date: Mon, 27 Feb 2017 20:36:19 +0000 Subject: [PATCH 5/9] Add overflow for container name to prevent UI from overflowing. Fixes #240 --- data/usercontext.css | 9 ++++++++- webextension/css/popup.css | 7 +++++++ webextension/popup.html | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/data/usercontext.css b/data/usercontext.css index 562a4ee..6c57db3 100644 --- a/data/usercontext.css +++ b/data/usercontext.css @@ -105,16 +105,23 @@ value, or chrome url path as an alternate selector mitiages this bug.*/ #userContext-indicator { height: 16px; list-style-image: none !important; + vertical-align: middle; width: 16px; } #userContext-label { - margin-inline-end: 5px; color: var(--identity-tab-color) !important; + margin-inline-end: 5px; + max-inline-size: 75px; + text-overflow: ellipsis; + white-space: nowrap; } #userContext-icons { -moz-box-align: center; + align-items: center; + display: flex; + max-inline-size: 120px; } .userContext-icon, diff --git a/webextension/css/popup.css b/webextension/css/popup.css index 3b0498b..b35efda 100644 --- a/webextension/css/popup.css +++ b/webextension/css/popup.css @@ -416,6 +416,13 @@ span ~ .panel-header-text { } /* Container info list */ +#container-info-name { + margin-inline-end: 0.5rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + #container-info-hideorshow { margin-block-start: 4px; } diff --git a/webextension/popup.html b/webextension/popup.html index e87f0e0..fafc66d 100644 --- a/webextension/popup.html +++ b/webextension/popup.html @@ -99,7 +99,7 @@
Name - +
Choose a color From 3fb697640118ffcf30e79948ba05a6081a037e69 Mon Sep 17 00:00:00 2001 From: groovecoder Date: Mon, 27 Feb 2017 10:30:15 -0600 Subject: [PATCH 6/9] for #242: disable move when incompatible add-ons detected --- index.js | 19 ++++++++++++++++++- webextension/css/popup.css | 8 +++++++- webextension/js/popup.js | 37 ++++++++++++++++++++++++++++++------- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 458983e..354885e 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,12 @@ const DEFAULT_TAB = "about:newtab"; const SHOW_MENU_TIMEOUT = 100; const HIDE_MENU_TIMEOUT = 300; +const INCOMPATIBLE_ADDON_IDS = [ + "pulse@mozilla.com", + "snoozetabs@mozilla.com", + "jid1-NeEaf3sAHdKHPA@jetpack" // PageShot +]; + const IDENTITY_COLORS = [ { name: "blue", color: "#00a7e0" }, { name: "turquoise", color: "#01bdad" }, @@ -40,6 +46,7 @@ const PREFS = [ [ "privacy.usercontext.about_newtab_segregation.enabled", true ], ]; +const { AddonManager } = require("resource://gre/modules/AddonManager.jsm"); const { attachTo, detachFrom } = require("sdk/content/mod"); const { Cu } = require("chrome"); const { ContextualIdentityService } = require("resource://gre/modules/ContextualIdentityService.jsm"); @@ -181,7 +188,8 @@ const ContainerService = { "removeIdentity", "updateIdentity", "getPreference", - "sendTelemetryPayload" + "sendTelemetryPayload", + "checkIncompatibleAddons" ]; // Map of identities. @@ -488,6 +496,15 @@ const ContainerService = { this._sendEvent(payload); }, + checkIncompatibleAddons() { + return new Promise(resolve => { + AddonManager.getAddonsByIDs(INCOMPATIBLE_ADDON_IDS, (addons) => { + addons = addons.filter((a) => a && a.isActive); + resolve(addons.length !== 0); + }); + }); + }, + // Tabs management hideTabs(args) { diff --git a/webextension/css/popup.css b/webextension/css/popup.css index 3b0498b..ff99edd 100644 --- a/webextension/css/popup.css +++ b/webextension/css/popup.css @@ -420,7 +420,13 @@ span ~ .panel-header-text { margin-block-start: 4px; } -.container-info-tab-row:not(.clickable) { +#container-info-movetabs-incompat { + font-size: 10px; + opacity: 0.3; +} + +.container-info-tab-row:not(.clickable), +.select-row:not(.clickable) { opacity: 0.3; } diff --git a/webextension/js/popup.js b/webextension/js/popup.js index b8f982c..c75985c 100644 --- a/webextension/js/popup.js +++ b/webextension/js/popup.js @@ -302,13 +302,36 @@ Logic.registerPanel(P_CONTAINER_INFO, { }); }); - document.querySelector("#container-info-movetabs").addEventListener("click", () => { - return browser.runtime.sendMessage({ - method: "moveTabsToWindow", - userContextId: Logic.currentIdentity().userContextId, - }).then(() => { - window.close(); - }); + // Check if the user has incompatible add-ons installed + browser.runtime.sendMessage({ + method: "checkIncompatibleAddons" + }).then(incompatible => { + const moveTabsEl = document.querySelector("#container-info-movetabs"); + if (incompatible) { + const fragment = document.createDocumentFragment(); + const incompatEl = document.createElement("div"); + + moveTabsEl.classList.remove("clickable"); + moveTabsEl.setAttribute("title", "Moving container tabs is incompatible with Pulse, PageShot, and SnoozeTabs."); + + fragment.appendChild(incompatEl); + incompatEl.setAttribute("id", "container-info-movetabs-incompat"); + incompatEl.innerText = "Incompatible with other Experiments."; + incompatEl.classList.add("container-info-tab-row"); + + moveTabsEl.parentNode.insertBefore(fragment, moveTabsEl.nextSibling); + } else { + moveTabsEl.addEventListener("click", () => { + return browser.runtime.sendMessage({ + method: "moveTabsToWindow", + userContextId: Logic.currentIdentity().userContextId, + }).then(() => { + window.close(); + }); + }); + } + }).catch(() => { + throw new Error("Could not check for incompatible add-ons."); }); }, From 4db04e1df5bef620887922d6805d498c881e3bc3 Mon Sep 17 00:00:00 2001 From: groovecoder Date: Mon, 27 Feb 2017 15:37:04 -0600 Subject: [PATCH 7/9] fix #272: add event telemetry for incompat addons --- docs/metrics.md | 9 +++++++++ index.js | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/metrics.md b/docs/metrics.md index 50e9728..3a0bb86 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -169,6 +169,15 @@ of a `testpilottest` telemetry ping for each scenario. } ``` +* When a user encounters the disabled "move" feature because of incompatible add-ons + +```js + { + "uuid": , + "event": "incompatible-addons-detected" + } +``` + ### A Redshift schema for the payload: ```lua diff --git a/index.js b/index.js index 878236b..c9784cd 100644 --- a/index.js +++ b/index.js @@ -500,7 +500,13 @@ const ContainerService = { return new Promise(resolve => { AddonManager.getAddonsByIDs(INCOMPATIBLE_ADDON_IDS, (addons) => { addons = addons.filter((a) => a && a.isActive); - resolve(addons.length !== 0); + const incompatibleAddons = addons.length !== 0; + if (incompatibleAddons) { + this.sendTelemetryPayload({ + "event": "incompatible-addons-detected" + }); + } + resolve(incompatibleAddons); }); }); }, From 6874d64ce74c640e4090e3c3e49b0abeabc25a42 Mon Sep 17 00:00:00 2001 From: baku Date: Fri, 24 Feb 2017 19:45:02 +0100 Subject: [PATCH 8/9] Do not close container tabs in nightly - issue #241 --- index.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 878236b..fcf91d0 100644 --- a/index.js +++ b/index.js @@ -112,6 +112,7 @@ const ContextualIdentityProxy = { const ContainerService = { _identitiesState: {}, _windowMap: new Map(), + _containerWasEnabled: false, init(installation) { // If we are just been installed, we must store some information for the @@ -159,6 +160,10 @@ const ContainerService = { } } + // Let's see if containers were enabled before this addon. + this._containerWasEnabled = + ss.storage.savedConfiguration.prefs["privacy.userContext.enabled"]; + // Enabling preferences PREFS.forEach((pref) => { @@ -1005,16 +1010,16 @@ const ContainerService = { for (let window of windows.browserWindows) { // eslint-disable-line prefer-const // Let's close all the container tabs. - // Note 1: we don't care if containers are supported but the current FF - // version. - // Note 2: We cannot use _closeTabs() because at this point tab.window is - // null. - for (let tab of window.tabs) { // eslint-disable-line prefer-const - if (this._getUserContextIdFromTab(tab)) { - tab.close(); - try { - SessionStore.forgetClosedTab(viewFor(window), 0); - } catch(e) {} // eslint-disable-line no-empty + // Note: We cannot use _closeTabs() because at this point tab.window is + // null. + if (!this._containerWasEnabled) { + for (let tab of window.tabs) { // eslint-disable-line prefer-const + if (this._getUserContextIdFromTab(tab)) { + tab.close(); + try { + SessionStore.forgetClosedTab(viewFor(window), 0); + } catch(e) {} // eslint-disable-line no-empty + } } } From 1ed3c739b1c154ebdff757d17bdbe4255b868bf9 Mon Sep 17 00:00:00 2001 From: groovecoder Date: Mon, 27 Feb 2017 16:03:12 -0600 Subject: [PATCH 9/9] 1.0 :tada: --- package.json | 2 +- webextension/manifest.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 450064d..aba4883 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "testpilot-containers", "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.", - "version": "0.9.5", + "version": "1.0.0", "author": "Andrea Marchesini, Luke Crouch and Jonathan Kingston", "bugs": { "url": "https://github.com/mozilla/testpilot-containers/issues" diff --git a/webextension/manifest.json b/webextension/manifest.json index 05d358c..414a7bf 100644 --- a/webextension/manifest.json +++ b/webextension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Containers Experiment", - "version": "0.9.5", + "version": "1.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.", "icons": {