Compare commits

...

30 Commits

Author SHA1 Message Date
groovecoder adadb98482 bump version to 4.0.3 2017-09-29 18:04:53 +01:00
luke crouch 25e760cd64 Merge pull request #879 from jonathanKingston/fix-disable-notice
Clean up disabled Private Mode notice. Fixes #878
2017-09-29 11:24:24 -05:00
luke crouch 0ff8e17005 Merge pull request #870 from jonathanKingston/delete-non-existent-container
Fix assignment of stale containers. Fixes #803
2017-09-29 11:06:03 -05:00
Jonathan Kingston c433c6b39e Clean up disabled Private Mode notice. Fixes #878 2017-09-29 16:59:51 +01:00
Jonathan Kingston 1c09c29104 Fix assignment of stale containers. Fixes #803 Fixes #827 2017-09-27 13:51:40 +01:00
luke crouch c1e9cc3c56 Merge pull request #859 from jonathanKingston/prevent-enter-handler-calling-click
Preventing default on enter handler as it seems to call click handler…
2017-09-26 10:46:53 -05:00
luke crouch 27296d24c5 Merge pull request #857 from jonathanKingston/change-wording
Change delete title to remove. Fixes #700
2017-09-26 10:38:57 -05:00
luke crouch 030e635417 Merge pull request #853 from jonathanKingston/bump-version-and-min-ff-version
Add strict min version and extension id and bump version to 4.0.2. Fixes
2017-09-26 10:37:21 -05:00
Jonathan Kingston 07711aaecc Preventing default on enter handler as it seems to call click handlers now. Fixes #856 2017-09-26 11:16:58 +01:00
Jonathan Kingston 16ed8992e2 Change delete title to remove. Fixes #700 2017-09-26 02:50:10 +01:00
Jonathan Kingston 88e6dc7a05 Add strict min version and extension id and bump version to 4.0.2. Fixes #692. Fixes #852 2017-09-23 23:36:24 +01:00
luke crouch 28e8d46743 Merge pull request #834 from jonathanKingston/storage-clean
Store only one of the current version opened. Fixes #833
2017-09-20 15:47:06 -05:00
Jonathan Kingston 77ba1b723f Store only one of the current version opened. Fixes #833 2017-09-20 02:26:50 +01:00
Jonathan Kingston b0cc6e7c2f Merge pull request #818 from jonathanKingston/update-readme-launch-notice
Minor README edit
2017-09-15 00:17:42 +01:00
Jonathan Kingston e84e482130 Minor README edit 2017-09-15 00:17:05 +01:00
Jonathan Kingston b5ae20b874 Merge pull request #817 from jonathanKingston/update-readme-launch-notice
Add launch notice in README
2017-09-14 23:16:55 +01:00
Jonathan Kingston 3ec81e3d1f Add launch notice in README 2017-09-14 23:15:01 +01:00
luke crouch fb5436c287 Merge pull request #815 from jonathanKingston/blob-image
Fix dumping UUID image into the page. Fixes #812
2017-09-13 20:04:05 -05:00
Jonathan Kingston 01a628822b Fix dumping UUID image into the page. Fixes #812 2017-09-14 01:48:32 +01:00
Jonathan Kingston 66e2c8e297 Merge pull request #811 from mozilla/bump-version-4.0.2
bump version to 4.0.2
2017-09-13 22:32:54 +01:00
groovecoder 80661d68f2 fix #809: use "Containers" for name for context menu 2017-09-13 16:16:43 -05:00
groovecoder ef8aa3be75 bump version to 4.0.2 2017-09-13 10:07:56 -05:00
luke crouch 6bc056e019 Merge pull request #794 from jonathanKingston/hide-button-in-queue
Add show button to use showing queue to prevent dupes. Fixes #793
2017-09-07 14:28:47 -05:00
Jonathan Kingston 75deab139b Fix a moving hidden tabs to a new window. Fixes #797 2017-09-07 12:03:28 -07:00
Jonathan Kingston ae79f0a303 Ignore non permissible urls when hiding as we can't open them which causes issues. Fixes #793 2017-09-07 10:12:25 -07:00
Jonathan Kingston 9b83068234 Add show button to use showing queue to prevent dupes. Fixes #791 2017-09-07 09:25:13 -07:00
luke crouch fec2be9429 Merge pull request #789 from jonathanKingston/encode-url-fix
Encode non conforming chars that break moz-extension urls. Fixes #787
2017-09-07 09:05:16 -05:00
luke crouch 9f1b06ddd3 Merge pull request #790 from jonathanKingston/jpm-ignore-more
Ignore more files with .jpmignore
2017-09-06 14:46:45 -05:00
Jonathan Kingston ad2198e8b5 Encode non conforming chars that break moz-extension urls. Fixes #787 2017-09-05 17:10:07 -07:00
Jonathan Kingston 1791fdf0ef Ignore more files with .jpmignore 2017-09-05 17:09:36 -07:00
16 changed files with 151 additions and 126 deletions
+2
View File
@@ -3,6 +3,7 @@ docs/
test/
.npm/
node_modules/
bin/
.env
.eslintrc.js
@@ -14,6 +15,7 @@ node_modules/
.stylelintrc
.travis.yml
*.xpi
*.md
.vimrc
.DS_Store
.gdb_history
+5 -5
View File
@@ -1,11 +1,11 @@
# Firefox Multi-Account Containers
# Multi-Account Containers
[![Available on Test Pilot](https://img.shields.io/badge/available_on-Test_Pilot-0996F8.svg)](https://testpilot.firefox.com/experiments/containers)
[Embedded Web Extension](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Embedded_WebExtensions) to build [Containers](https://blog.mozilla.org/tanvi/2016/06/16/contextual-identities-on-the-web/) as a Firefox [Test Pilot](https://testpilot.firefox.com/) Experiment and [Shield Study](https://wiki.mozilla.org/Firefox/Shield/Shield_Studies) to learn:
The Firefox Multi-Account Containers extension lets you carve out a separate box for each of your online lives no more opening a different browser just to check your work email! [Learn More Here](https://blog.mozilla.org/firefox/introducing-firefox-multi-account-containers/)
* Will a general Firefox audience understand the Containers feature?
* Is the UI as currently implemented in Nightly clear or discoverable?
[Available on addons.mozilla.org](https://addons.mozilla.org/en-GB/firefox/addon/multi-account-containers/)
**Note:** Firefox 57 + 58 users should Install from our [latest GitHub Release](https://github.com/mozilla/testpilot-containers/releases/latest)
For more info, see:
+3 -3
View File
@@ -7,16 +7,16 @@
<em:bootstrap>true</em:bootstrap>
<em:multiprocessCompatible>true</em:multiprocessCompatible>
<em:hasEmbeddedWebExtension>true</em:hasEmbeddedWebExtension>
<em:name>Firefox Multi-Account Containers</em:name>
<em:name>Multi-Account Containers</em:name>
<em:description>Containers helps you keep all the parts of your online life contained in different tabs. Custom labels and color-coded tabs help keep different activities — like online shopping, travel planning, or checking work email — separate.</em:description>
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!--Firefox-->
<em:minVersion>51.0a1</em:minVersion>
<em:minVersion>53.0</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
<em:version>4.0.1</em:version>
<em:version>4.0.3</em:version>
<em:unpack>false</em:unpack>
</Description>
</RDF>
+2 -2
View File
@@ -1,8 +1,8 @@
{
"name": "testpilot-containers",
"title": "Firefox Multi-Account Containers",
"title": "Multi-Account Containers",
"description": "Containers helps you keep all the parts of your online life contained in different tabs. Custom labels and color-coded tabs help keep different activities — like online shopping, travel planning, or checking work email — separate.",
"version": "4.0.1",
"version": "4.0.3",
"author": "Andrea Marchesini, Luke Crouch and Jonathan Kingston",
"bugs": {
"url": "https://github.com/mozilla/testpilot-containers/issues"
+1 -1
View File
@@ -1,7 +1,7 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Firefox Multi-Account Containers Confirm Navigation</title>
<title>Multi-Account Containers Confirm Navigation</title>
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" />
<link rel="stylesheet" href="/css/confirm-page.css" />
</head>
+33 -11
View File
@@ -113,21 +113,29 @@ const assignManager = {
return true;
},
init() {
browser.contextMenus.onClicked.addListener((info, tab) => {
this._onClickedHandler(info, tab);
});
// Before a request is handled by the browser we decide if we should route through a different container
browser.webRequest.onBeforeRequest.addListener((options) => {
async onBeforeRequest(options) {
if (options.frameId !== 0 || options.tabId === -1) {
return {};
}
this.removeContextMenu();
return Promise.all([
const [tab, siteSettings] = await Promise.all([
browser.tabs.get(options.tabId),
this.storageArea.get(options.url)
]).then(([tab, siteSettings]) => {
]);
let container;
try {
container = await browser.contextualIdentities.get(backgroundLogic.cookieStoreId(siteSettings.userContextId));
} catch (e) {
container = false;
}
// The container we have in the assignment map isn't present any more so lets remove it
// then continue the existing load
if (!container) {
this.deleteContainer(siteSettings.userContextId);
return {};
}
const userContextId = this.getUserContextIdFromCookieStore(tab);
if (!siteSettings
|| userContextId === siteSettings.userContextId
@@ -158,9 +166,16 @@ const assignManager = {
return {
cancel: true,
};
}).catch((e) => {
throw e;
},
init() {
browser.contextMenus.onClicked.addListener((info, tab) => {
this._onClickedHandler(info, tab);
});
// Before a request is handled by the browser we decide if we should route through a different container
browser.webRequest.onBeforeRequest.addListener((options) => {
return this.onBeforeRequest(options);
},{urls: ["<all_urls>"], types: ["main_frame"]}, ["blocking"]);
},
@@ -328,6 +343,13 @@ const assignManager = {
});
},
encodeURLProperty(url) {
return encodeURIComponent(url).replace(/[!'()*]/g, (c) => {
const charCode = c.charCodeAt(0).toString(16);
return `%${charCode}`;
});
},
reloadPageInContainer(url, currentUserContextId, userContextId, index, neverAsk = false) {
const cookieStoreId = backgroundLogic.cookieStoreId(userContextId);
const loadPage = browser.extension.getURL("confirm-page.html");
@@ -336,7 +358,7 @@ const assignManager = {
if (neverAsk) {
browser.tabs.create({url, cookieStoreId, index});
} else {
let confirmUrl = `${loadPage}?url=${encodeURIComponent(url)}&cookieStoreId=${cookieStoreId}`;
let confirmUrl = `${loadPage}?url=${this.encodeURLProperty(url)}&cookieStoreId=${cookieStoreId}`;
let currentCookieStoreId;
if (currentUserContextId) {
currentCookieStoreId = backgroundLogic.cookieStoreId(currentUserContextId);
+34 -7
View File
@@ -63,8 +63,7 @@ const backgroundLogic = {
url = undefined;
}
// We can't open these we just have to throw them away
if (new URL(url).protocol === "about:") {
if (!this.isPermissibleURL(url)) {
return;
}
@@ -76,6 +75,17 @@ const backgroundLogic = {
});
},
isPermissibleURL(url) {
const protocol = new URL(url).protocol;
// We can't open these we just have to throw them away
if (protocol === "about:"
|| protocol === "chrome:"
|| protocol === "moz-extension:") {
return false;
}
return true;
},
checkArgs(requiredArguments, options, methodName) {
requiredArguments.forEach((argument) => {
if (!(argument in options)) {
@@ -118,20 +128,37 @@ const backgroundLogic = {
containerState.hiddenTabs.length === 0) {
return;
}
const newWindowObj = await browser.windows.create({
let newWindowObj;
let hiddenDefaultTabToClose;
if (list.length) {
newWindowObj = await browser.windows.create({
tabId: list.shift().id
});
browser.tabs.move(list.map((tab) => tab.id), {
windowId: newWindowObj.id,
index: -1
});
} else {
//As we get a blank tab here we will need to await the tabs creation
newWindowObj = await browser.windows.create({
});
hiddenDefaultTabToClose = true;
}
const showHiddenPromises = [];
// Let's show the hidden tabs.
for (let object of containerState.hiddenTabs) { // eslint-disable-line prefer-const
browser.tabs.create(object.url || DEFAULT_TAB, {
showHiddenPromises.push(browser.tabs.create({
url: object.url || DEFAULT_TAB,
windowId: newWindowObj.id,
cookieStoreId
});
}));
}
if (hiddenDefaultTabToClose) {
// Lets wait for hidden tabs to show before closing the others
await showHiddenPromises;
}
containerState.hiddenTabs = [];
@@ -139,9 +166,9 @@ const backgroundLogic = {
// 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.
const tabs = browser.tabs.query({windowId: newWindowObj.id});
const tabs = await browser.tabs.query({windowId: newWindowObj.id});
for (let tab of tabs) { // eslint-disable-line prefer-const
if (tabs.cookieStoreId !== cookieStoreId) {
if (tab.cookieStoreId !== cookieStoreId) {
browser.tabs.remove(tab.id);
}
}
+7 -6
View File
@@ -4,12 +4,13 @@ const badge = {
const currentWindow = await browser.windows.getCurrent();
this.displayBrowserActionBadge(currentWindow.incognito);
},
async displayBrowserActionBadge(disable) {
if (disable) {
browser.browserAction.disable();
} else {
browser.browserAction.enable();
}
disableAddon(tabId) {
browser.browserAction.disable(tabId);
browser.browserAction.setTitle({ tabId, title: "Containers disabled in Private Browsing Mode" });
},
async displayBrowserActionBadge() {
const extensionInfo = await backgroundLogic.getExtensionInfo();
const storage = await browser.storage.local.get({browserActionBadgesClicked: []});
@@ -41,6 +41,9 @@ const identityState = {
const tabsByContainer = await browser.tabs.query({cookieStoreId, windowId});
tabsByContainer.forEach((tab) => {
const tabObject = this._createTabObject(tab);
if (!backgroundLogic.isPermissibleURL(tab.url)) {
return;
}
// This tab is going to be closed. Let's mark this tabObject as
// non-active.
tabObject.active = false;
-2
View File
@@ -11,7 +11,6 @@
"js/background/badge.js",
"js/background/identityState.js",
"js/background/messageHandler.js",
"js/backdround/init.js"
]
-->
<script type="text/javascript" src="backgroundLogic.js"></script>
@@ -19,6 +18,5 @@
<script type="text/javascript" src="badge.js"></script>
<script type="text/javascript" src="identityState.js"></script>
<script type="text/javascript" src="messageHandler.js"></script>
<script type="text/javascript" src="init.js"></script>
</body>
</html>
-27
View File
@@ -1,27 +0,0 @@
browser.runtime.sendMessage({
method: "getPreference",
pref: "browser.privatebrowsing.autostart"
}).then(pbAutoStart => {
// We don't want to disable the addon if we are in auto private-browsing.
if (!pbAutoStart) {
browser.tabs.onCreated.addListener(tab => {
if (tab.incognito) {
disableAddon(tab.id);
}
});
browser.tabs.query({}).then(tabs => {
for (let tab of tabs) { // eslint-disable-line prefer-const
if (tab.incognito) {
disableAddon(tab.id);
}
}
}).catch(() => {});
}
}).catch(() => {});
function disableAddon(tabId) {
browser.browserAction.disable(tabId);
browser.browserAction.setTitle({ tabId, title: "Containers disabled in Private Browsing Mode" });
}
+5 -3
View File
@@ -39,7 +39,7 @@ const messageHandler = {
backgroundLogic.sortTabs();
break;
case "showTabs":
backgroundLogic.showTabs({cookieStoreId: m.cookieStoreId});
this.unhideContainer(m.cookieStoreId);
break;
case "hideTabs":
backgroundLogic.hideTabs({
@@ -106,6 +106,9 @@ const messageHandler = {
}, {urls: ["<all_urls>"], types: ["main_frame"]});
browser.tabs.onCreated.addListener((tab) => {
if (tab.incognito) {
badge.disableAddon(tab.id);
}
// lets remember the last tab created so we can close it if it looks like a redirect
this.lastCreatedTab = tab;
if (tab.cookieStoreId) {
@@ -130,12 +133,11 @@ const messageHandler = {
async onFocusChangedCallback(windowId) {
assignManager.removeContextMenu();
const currentWindow = await browser.windows.getCurrent();
// browserAction loses background color in new windows ...
// https://bugzil.la/1314674
// https://github.com/mozilla/testpilot-containers/issues/608
// ... so re-call displayBrowserActionBadge on window changes
badge.displayBrowserActionBadge(currentWindow.incognito);
badge.displayBrowserActionBadge();
browser.tabs.query({active: true, windowId}).then((tabs) => {
if (tabs && tabs[0]) {
assignManager.calculateContextMenu(tabs[0]);
+6 -2
View File
@@ -20,11 +20,15 @@ async function doAnimation(element, property, value) {
async function addMessage(message) {
const divElement = document.createElement("div");
divElement.classList.add("container-notification");
// For the eager eyed, this is an experiment. It is however likely that a website will know it is "contained" anyway
// Ideally we would use https://bugzilla.mozilla.org/show_bug.cgi?id=1340930 when this is available
divElement.innerText = message.text;
const imageElement = document.createElement("img");
imageElement.src = browser.extension.getURL("/img/container-site-d-24.png");
const imagePath = browser.extension.getURL("/img/container-site-d-24.png");
const response = await fetch(imagePath);
const blob = await response.blob();
const objectUrl = URL.createObjectURL(blob);
imageElement.src = objectUrl;
divElement.prepend(imageElement);
document.body.appendChild(divElement);
+7 -13
View File
@@ -93,18 +93,7 @@ const Logic = {
const data = await browser.storage.local.get([ONBOARDING_STORAGE_KEY]);
let onboarded = data[ONBOARDING_STORAGE_KEY];
if (!onboarded) {
// Legacy local storage used before panel 5
if (localStorage.getItem("onboarded4")) {
onboarded = 4;
} else if (localStorage.getItem("onboarded3")) {
onboarded = 3;
} else if (localStorage.getItem("onboarded2")) {
onboarded = 2;
} else if (localStorage.getItem("onboarded1")) {
onboarded = 1;
} else {
onboarded = 0;
}
this.setOnboardingStage(onboarded);
}
@@ -144,7 +133,11 @@ const Logic = {
browser.browserAction.setBadgeBackgroundColor({color: ""});
browser.browserAction.setBadgeText({text: ""});
storage.browserActionBadgesClicked.push(extensionInfo.version);
browser.storage.local.set({browserActionBadgesClicked: storage.browserActionBadgesClicked});
// use set and spread to create a unique array
const browserActionBadgesClicked = [...new Set(storage.browserActionBadgesClicked)];
browser.storage.local.set({
browserActionBadgesClicked
});
},
async identity(cookieStoreId) {
@@ -168,6 +161,7 @@ const Logic = {
});
element.addEventListener("keydown", (e) => {
if (e.keyCode === 13) {
e.preventDefault();
handler(e);
}
});
@@ -802,7 +796,7 @@ Logic.registerPanel(P_CONTAINERS_EDIT, {
</td>`;
tr.querySelector(".container-name").textContent = identity.name;
tr.querySelector(".edit-container").setAttribute("title", `Edit ${identity.name} container`);
tr.querySelector(".remove-container").setAttribute("title", `Delete ${identity.name} container`);
tr.querySelector(".remove-container").setAttribute("title", `Remove ${identity.name} container`);
Logic.addEnterHandler(tr, e => {
+4 -5
View File
@@ -1,9 +1,9 @@
{
"manifest_version": 2,
"name": "Firefox Multi-Account Containers",
"version": "4.0.1",
"version": "4.0.3",
"description": "Firefox Multi-Account Containers helps you keep all the parts of your online life contained in different tabs. Custom labels and color-coded tabs help keep different activities — like online shopping, travel planning, or checking work email — separate.",
"description": "Multi-Account Containers helps you keep all the parts of your online life contained in different tabs. Custom labels and color-coded tabs help keep different activities — like online shopping, travel planning, or checking work email — separate.",
"icons": {
"48": "img/container-site-d-48.png",
"96": "img/container-site-d-96.png"
@@ -11,8 +11,7 @@
"applications": {
"gecko": {
"strict_min_version": "51.0",
"update_url": "https://testpilot.firefox.com/files/@testpilot-containers/updates.json"
"strict_min_version": "53.0"
}
},
@@ -45,7 +44,7 @@
"browser_action": {
"browser_style": true,
"default_icon": "img/container-site.svg",
"default_title": "Firefox Multi-Account Containers",
"default_title": "Multi-Account Containers",
"default_popup": "popup.html"
},
+1 -1
View File
@@ -1,7 +1,7 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Firefox Multi-Account Containers</title>
<title>Multi-Account Containers</title>
<link rel="stylesheet" href="/css/popup.css">
</head>