This commit is contained in:
luke crouch 2017-02-27 22:00:30 +00:00 committed by GitHub
commit e0ed6b0281
8 changed files with 144 additions and 36 deletions

View file

@ -105,16 +105,23 @@ value, or chrome url path as an alternate selector mitiages this bug.*/
#userContext-indicator { #userContext-indicator {
height: 16px; height: 16px;
list-style-image: none !important; list-style-image: none !important;
vertical-align: middle;
width: 16px; width: 16px;
} }
#userContext-label { #userContext-label {
margin-inline-end: 5px;
color: var(--identity-tab-color) !important; color: var(--identity-tab-color) !important;
margin-inline-end: 5px;
max-inline-size: 75px;
text-overflow: ellipsis;
white-space: nowrap;
} }
#userContext-icons { #userContext-icons {
-moz-box-align: center; -moz-box-align: center;
align-items: center;
display: flex;
max-inline-size: 120px;
} }
.userContext-icon, .userContext-icon,

View file

@ -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": <uuid>,
"event": "incompatible-addons-detected"
}
```
### A Redshift schema for the payload: ### A Redshift schema for the payload:
```lua ```lua

104
index.js
View file

@ -8,6 +8,12 @@ const DEFAULT_TAB = "about:newtab";
const SHOW_MENU_TIMEOUT = 100; const SHOW_MENU_TIMEOUT = 100;
const HIDE_MENU_TIMEOUT = 300; const HIDE_MENU_TIMEOUT = 300;
const INCOMPATIBLE_ADDON_IDS = [
"pulse@mozilla.com",
"snoozetabs@mozilla.com",
"jid1-NeEaf3sAHdKHPA@jetpack" // PageShot
];
const IDENTITY_COLORS = [ const IDENTITY_COLORS = [
{ name: "blue", color: "#00a7e0" }, { name: "blue", color: "#00a7e0" },
{ name: "turquoise", color: "#01bdad" }, { name: "turquoise", color: "#01bdad" },
@ -40,6 +46,7 @@ const PREFS = [
[ "privacy.usercontext.about_newtab_segregation.enabled", true ], [ "privacy.usercontext.about_newtab_segregation.enabled", true ],
]; ];
const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
const { attachTo, detachFrom } = require("sdk/content/mod"); const { attachTo, detachFrom } = require("sdk/content/mod");
const { Cu } = require("chrome"); const { Cu } = require("chrome");
const { ContextualIdentityService } = require("resource://gre/modules/ContextualIdentityService.jsm"); const { ContextualIdentityService } = require("resource://gre/modules/ContextualIdentityService.jsm");
@ -105,6 +112,7 @@ const ContextualIdentityProxy = {
const ContainerService = { const ContainerService = {
_identitiesState: {}, _identitiesState: {},
_windowMap: new Map(), _windowMap: new Map(),
_containerWasEnabled: false,
init(installation) { init(installation) {
// 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
@ -139,8 +147,23 @@ const ContainerService = {
identity.color); 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");
}
} }
// Let's see if containers were enabled before this addon.
this._containerWasEnabled =
ss.storage.savedConfiguration.prefs["privacy.userContext.enabled"];
// Enabling preferences // Enabling preferences
PREFS.forEach((pref) => { PREFS.forEach((pref) => {
@ -170,7 +193,8 @@ const ContainerService = {
"removeIdentity", "removeIdentity",
"updateIdentity", "updateIdentity",
"getPreference", "getPreference",
"sendTelemetryPayload" "sendTelemetryPayload",
"checkIncompatibleAddons"
]; ];
// Map of identities. // Map of identities.
@ -477,6 +501,21 @@ const ContainerService = {
this._sendEvent(payload); this._sendEvent(payload);
}, },
checkIncompatibleAddons() {
return new Promise(resolve => {
AddonManager.getAddonsByIDs(INCOMPATIBLE_ADDON_IDS, (addons) => {
addons = addons.filter((a) => a && a.isActive);
const incompatibleAddons = addons.length !== 0;
if (incompatibleAddons) {
this.sendTelemetryPayload({
"event": "incompatible-addons-detected"
});
}
resolve(incompatibleAddons);
});
});
},
// Tabs management // Tabs management
hideTabs(args) { hideTabs(args) {
@ -673,6 +712,11 @@ const ContainerService = {
return; return;
} }
this._remapTabsIfMissing(args.userContextId);
if (!this._isKnownContainer(args.userContextId)) {
return Promise.resolve(null);
}
this.sendTelemetryPayload({ this.sendTelemetryPayload({
"event": "move-tabs-to-window", "event": "move-tabs-to-window",
"userContextId": args.userContextId, "userContextId": args.userContextId,
@ -686,7 +730,8 @@ const ContainerService = {
}); });
// Nothing to do // Nothing to do
if (list.length === 0) { if (list.length === 0 &&
this._identitiesState[args.userContextId].hiddenTabs.length === 0) {
resolve(null); resolve(null);
return; return;
} }
@ -702,6 +747,13 @@ const ContainerService = {
newBrowserWindow.gBrowser.adoptTab(viewFor(tab), pos++, false); 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 // 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 // should be only the first tab, but maybe there are addons doing
// crazy stuff. // crazy stuff.
@ -964,16 +1016,16 @@ const ContainerService = {
for (let window of windows.browserWindows) { // eslint-disable-line prefer-const for (let window of windows.browserWindows) { // eslint-disable-line prefer-const
// Let's close all the container tabs. // Let's close all the container tabs.
// Note 1: we don't care if containers are supported but the current FF // Note: We cannot use _closeTabs() because at this point tab.window is
// version. // null.
// Note 2: We cannot use _closeTabs() because at this point tab.window is if (!this._containerWasEnabled) {
// null. 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(); try {
try { SessionStore.forgetClosedTab(viewFor(window), 0);
SessionStore.forgetClosedTab(viewFor(window), 0); } catch(e) {} // eslint-disable-line no-empty
} catch(e) {} // eslint-disable-line no-empty }
} }
} }
@ -1101,14 +1153,16 @@ ContainerWindow.prototype = {
}, },
_configurePlusButtonMenuElement(buttonElement) { _configurePlusButtonMenuElement(buttonElement) {
// Let's remove the tooltip because it can go over our panel. if (buttonElement) {
this._tooltipCache.set(buttonElement, buttonElement.getAttribute("tooltip")); // Let's remove the tooltip because it can go over our panel.
buttonElement.setAttribute("tooltip", ""); this._tooltipCache.set(buttonElement, buttonElement.getAttribute("tooltip"));
this._disableElement(buttonElement); buttonElement.setAttribute("tooltip", "");
this._disableElement(buttonElement);
buttonElement.addEventListener("mouseover", this); buttonElement.addEventListener("mouseover", this);
buttonElement.addEventListener("click", this); buttonElement.addEventListener("click", this);
buttonElement.addEventListener("mouseout", this); buttonElement.addEventListener("mouseout", this);
}
}, },
_configurePlusButtonMenu() { _configurePlusButtonMenu() {
@ -1318,12 +1372,14 @@ ContainerWindow.prototype = {
}, },
_shutDownPlusButtonMenuElement(buttonElement) { _shutDownPlusButtonMenuElement(buttonElement) {
this._shutdownElement(buttonElement); if (buttonElement) {
buttonElement.setAttribute("tooltip", this._tooltipCache.get(buttonElement)); this._shutdownElement(buttonElement);
buttonElement.setAttribute("tooltip", this._tooltipCache.get(buttonElement));
buttonElement.removeEventListener("mouseover", this); buttonElement.removeEventListener("mouseover", this);
buttonElement.removeEventListener("click", this); buttonElement.removeEventListener("click", this);
buttonElement.removeEventListener("mouseout", this); buttonElement.removeEventListener("mouseout", this);
}
}, },
_shutdownPlusButtonMenu() { _shutdownPlusButtonMenu() {

View file

@ -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": "0.9.4", "version": "0.9.5",
"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"

View file

@ -416,11 +416,24 @@ span ~ .panel-header-text {
} }
/* Container info list */ /* Container info list */
#container-info-name {
margin-inline-end: 0.5rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#container-info-hideorshow { #container-info-hideorshow {
margin-block-start: 4px; 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; opacity: 0.3;
} }

View file

@ -302,13 +302,36 @@ Logic.registerPanel(P_CONTAINER_INFO, {
}); });
}); });
document.querySelector("#container-info-movetabs").addEventListener("click", () => { // Check if the user has incompatible add-ons installed
return browser.runtime.sendMessage({ browser.runtime.sendMessage({
method: "moveTabsToWindow", method: "checkIncompatibleAddons"
userContextId: Logic.currentIdentity().userContextId, }).then(incompatible => {
}).then(() => { const moveTabsEl = document.querySelector("#container-info-movetabs");
window.close(); 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.");
}); });
}, },

View file

@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "Containers Experiment", "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.", "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": {

View file

@ -99,7 +99,7 @@
<form id="edit-container-panel-form"> <form id="edit-container-panel-form">
<fieldset> <fieldset>
<legend>Name</legend> <legend>Name</legend>
<input type="text" name="container-name" id="edit-container-panel-name-input"/> <input type="text" name="container-name" id="edit-container-panel-name-input" maxlength="25"/>
</fieldset> </fieldset>
<fieldset id="edit-container-panel-choose-color"> <fieldset id="edit-container-panel-choose-color">
<legend>Choose a color</legend> <legend>Choose a color</legend>