Merge branch 'main' into backup-restore-containers

This commit is contained in:
Minigugus 2022-06-06 19:52:20 +02:00 committed by GitHub
commit 84f197dbd1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 746 additions and 511 deletions

View file

@ -19,6 +19,7 @@ module.exports = {
"OS": true,
"ADDON_UNINSTALL": true,
"ADDON_DISABLE": true,
"CONTAINER_ORDER_STORAGE_KEY": true,
"proxifiedContainers": true,
"MozillaVPN": true,
"MozillaVPN_Background": true

View file

@ -1,27 +0,0 @@
<!--
Feel free to ignore this Issue template if you just want to ask or suggest something. If you experience an Issue then please provide all asked information.
Also please make sure that:
- "Firefox will: Never remember history" in the Firefox Preferences/Options under "Privacy & Security > History" is NOT selected
- You are NOT using Firefox in a Private Window
- You can see a grayed out but ticked Checkbox with the description "Enable Container Tabs" in the Firefox Preferences/Options under "Tabs"
-->
- Multi-Account Containers Version:
- Operating System + Version:
- Firefox Version:
- Other installed Add-ons + Version + Enabled/Disabled-Status:
<!-- To be able to copy & paste the full list of your Add-ons navigate to "about:support" and scroll down to "Extensions" -->
### Actual behavior
### Expected behavior
### Steps to reproduce
1.
2.
3.
### Notes

53
.github/ISSUE_TEMPLATE/bug.yml vendored Normal file
View file

@ -0,0 +1,53 @@
name: Bug Report
description: Report a problem in Multi-Account Containers
labels: [bug]
body:
- type: checkboxes
id: before-bug-report
attributes:
label: Before submitting a bug report
options:
- label: "I updated to the latest version of Multi-Account Container and tested if I can reproduce the issue"
required: true
- label: "I searched for existing reports to see if it hasn\'t already been reported"
required: true
- type: textarea
id: about_support
attributes:
label: "Provide a copy of Troubleshooting Information page"
description: "To get a copy of the Troubleshooting Information page, type *about:support* in the address bar and click on the *Copy text to clipboard* button."
validations:
required: true
- type: textarea
id: step_to_reproduce
attributes:
label: "Step to reproduce"
description: "Provide a list of steps you did to trigger this bug"
placeholder: |
1. I opened ...
2. I clicked on ...
3. ...
validations:
required: true
- type: textarea
id: actual_behavior
attributes:
label: "Actual behavior"
description: "Provide a description of what is currently happening"
validations:
required: true
- type: textarea
id: expected_behavior
attributes:
label: "Expected behavior"
description: "Provide a description of what should happen"
validations:
required: true
- type: textarea
id: additional_informations
attributes:
label: "Additional informations"
description: "Provide any other information revelant to this issue"
validations:
required: false

17
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,17 @@
blank_issues_enabled: false
contact_links:
- name: "Explore our help articles"
url: "https://support.mozilla.org/kb/containers"
about: "Dig into the knowledge base, tips and tricks, troubleshooting, and so much more."
- name: "Ask a support question"
url: "https://support.mozilla.org/questions/new/desktop/form"
about: "Get support from our contributors or staff members."
- name: "Submit new ideas"
url: "https://connect.mozilla.org/t5/discussions/how-to-submit-a-great-idea-in-five-easy-steps/td-p/24"
about: "Have an idea for a new product feature? Share it with our community and staff members!"
- name: "Discussions"
url: "https://connect.mozilla.org/t5/discussions/bd-p/discussions"
about: "Give feedback and participate in meaningful conversations with the community and Mozilla employees"
- name: "Discover more awesome tools"
url: "https://www.mozilla.org/firefox/products/"
about: "Learn more about other products from Mozilla"

View file

@ -9,16 +9,16 @@ on:
- main
- production
schedule:
- cron: '0 2 * * *' # Daily at 2AM UTC
- cron: '0 2 * * *' # Daily at 2AM UTC
jobs:
builds:
name: Builds
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Create the package
shell: bash
@ -26,7 +26,7 @@ jobs:
./bin/build-addon.sh nightly.xpi
- name: Uploading
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v3
with:
name: ${{matrix.config.name}} Build
path: src/web-ext-artifacts

28
.github/workflows/test.yaml vendored Normal file
View file

@ -0,0 +1,28 @@
name: Test
on:
push:
branches:
- main
- production
pull_request:
branches:
jobs:
test:
name: Run tests
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Set up node
uses: actions/setup-node@v3
with:
node-version: lts/*
- name: Install dependencies
run: npm install --legacy-peer-deps
- name: Run tests
run: npm run test

View file

@ -1,10 +0,0 @@
language: node_js
node_js:
- "lts/*"
notifications:
irc:
- "ircs://irc.mozilla.org:6697/#testpilot-containers-bots"
install:
- npm install --legacy-peer-deps

View file

@ -1,10 +1,12 @@
# Multi-Account Containers
[![Test](https://github.com/mozilla/multi-account-containers/actions/workflows/test.yaml/badge.svg)](https://github.com/mozilla/multi-account-containers/actions/workflows/test.yaml)
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/)
[Available on addons.mozilla.org](https://addons.mozilla.org/firefox/addon/multi-account-containers/)
For more info, see:
For more info, see:
* [Test Pilot Product Hypothesis Document](https://docs.google.com/document/d/1WQdHTVXROk7dYkSFluc6_hS44tqZjIrG9I-uPyzevE8/edit#)
* [Shield Product Hypothesis Document](https://docs.google.com/document/d/1vMD-fH_5hGDDqNvpRZk12_RhCN2WAe4_yaBamaNdtik/edit#)
@ -13,7 +15,7 @@ For more info, see:
## Requirements
* node 7+ (for jpm)
* Firefox 57+
* Firefox 91.1.0+
## Development
@ -43,7 +45,7 @@ Here is a [video](https://www.youtube.com/watch?v=cer9EUKegG4) that demonstrates
* Install dependencies:
```
npm install
npm install --legacy-peer-deps
```
* Run all tests:

View file

@ -2,7 +2,7 @@
"name": "testpilot-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": "8.0.4",
"version": "8.0.7",
"author": "Andrea Marchesini, Luke Crouch, Lesley Norton, Kendall Werts, Maxx Crawford, Jonathan Kingston",
"bugs": {
"url": "https://github.com/mozilla/multi-account-containers/issues"

File diff suppressed because it is too large Load diff

View file

@ -197,12 +197,17 @@ window.assignManager = {
return {};
}
// proxyDNS only works for SOCKS proxies
if (["socks", "socks4"].includes(result.proxy.type)) {
result.proxy.proxyDNS = true;
}
if (!result.proxy.mozProxyEnabled) {
return [{ ...result.proxy, proxyDNS: true }];
return result.proxy;
}
// Let's add the isolation key.
return [{ ...result.proxy, connectionIsolationKey: "" + MozillaVPN_Background.isolationKey, proxyDNS: true }];
return [{ ...result.proxy, connectionIsolationKey: "" + MozillaVPN_Background.isolationKey }];
},
// Before a request is handled by the browser we decide if we should

View file

@ -1,4 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const DEFAULT_TAB = "about:newtab";
const backgroundLogic = {
NEW_TAB_PAGES: new Set([
"about:startpage",
@ -168,7 +173,7 @@ const backgroundLogic = {
if ("isIsolated" in containerState || remove) {
delete containerState.isIsolated;
} else {
containerState.isIsolated = "locked";
containerState.isIsolated = "locked";
}
return await identityState.storageArea.set(cookieStoreId, containerState);
} catch (error) {
@ -381,19 +386,29 @@ const backgroundLogic = {
continue;
}
const userContextId = backgroundLogic.getUserContextIdFromCookieStoreId(tab.cookieStoreId);
if (!map.has(userContextId)) {
map.set(userContextId, []);
if (!map.has(tab.cookieStoreId)) {
const userContextId = backgroundLogic.getUserContextIdFromCookieStoreId(tab.cookieStoreId);
map.set(tab.cookieStoreId, { order: userContextId, tabs: [] });
}
map.get(userContextId).push(tab);
map.get(tab.cookieStoreId).tabs.push(tab);
}
const containerOrderStorage = await browser.storage.local.get([CONTAINER_ORDER_STORAGE_KEY]);
const containerOrder =
containerOrderStorage && containerOrderStorage[CONTAINER_ORDER_STORAGE_KEY];
if (containerOrder) {
map.forEach((obj, key) => {
obj.order = (key in containerOrder) ? containerOrder[key] : -1;
});
}
// Let's sort the map.
const sortMap = new Map([...map.entries()].sort((a, b) => a[0] > b[0]));
const sortMap = new Map([...map.entries()].sort((a, b) => a[1].order > b[1].order));
// Let's move tabs.
sortMap.forEach(tabs => {
for (const tab of tabs) {
sortMap.forEach(obj => {
for (const tab of obj.tabs) {
++pos;
browser.tabs.move(tab.id, {
windowId: windowObj.id,

View file

@ -66,11 +66,11 @@ const MozillaVPN_Background = {
// Handle responses from MozillaVPN client
async handleResponse(response) {
MozillaVPN_Background._installed = true;
if (response.error && response.error === "vpn-client-down") {
MozillaVPN_Background._connected = false;
return;
}
MozillaVPN_Background._installed = true;
if (response.servers) {
const servers = response.servers.countries;
browser.storage.local.set({ [MozillaVPN_Background.MOZILLA_VPN_SERVERS_KEY]: servers});

View file

@ -103,11 +103,20 @@ async function restoreContainers(event) {
restoreInput.value = "";
}
async function changeTheme(event) {
const theme = event.currentTarget;
await browser.storage.local.set({currentTheme: theme.value});
await browser.storage.local.set({currentThemeId: theme.selectedIndex});
}
async function setupOptions() {
const { syncEnabled } = await browser.storage.local.get("syncEnabled");
const { replaceTabEnabled } = await browser.storage.local.get("replaceTabEnabled");
const { currentThemeId } = await browser.storage.local.get("currentThemeId");
document.querySelector("#syncCheck").checked = !!syncEnabled;
document.querySelector("#replaceTabCheck").checked = !!replaceTabEnabled;
document.querySelector("#changeTheme").selectedIndex = currentThemeId;
setupContainerShortcutSelects();
}
@ -165,6 +174,8 @@ document.addEventListener("DOMContentLoaded", setupOptions);
document.querySelector("#syncCheck").addEventListener( "change", enableDisableSync);
document.querySelector("#replaceTabCheck").addEventListener( "change", enableDisableReplaceTab);
document.querySelector("#containersRestoreInput").addEventListener( "change", restoreContainers);
document.querySelector("#changeTheme").addEventListener( "change", changeTheme);
maybeShowPermissionsWarningIcon();
for (let i=0; i < NUMBER_OF_KEYBOARD_SHORTCUTS; i++) {
document.querySelector("#open_container_"+i)

View file

@ -32,6 +32,9 @@ async function init() {
list.appendChild(fragment);
MozillaVPN.handleContainerList(identities);
// Set the theme
Utils.applyTheme();
}
init();

View file

@ -10,7 +10,6 @@ const DEFAULT_ICON = "circle";
const NEW_CONTAINER_ID = "new";
const ONBOARDING_STORAGE_KEY = "onboarding-stage";
const CONTAINER_ORDER_STORAGE_KEY = "container-order";
const CONTAINER_DRAG_DATA_TYPE = "firefox-container";
// List of panels
@ -52,6 +51,7 @@ async function getExtensionInfo() {
return extensionInfo;
}
// This object controls all the panels, identities and many other things.
const Logic = {
_identities: [],
@ -66,6 +66,9 @@ const Logic = {
method: "MozillaVPN_attemptPort"
}),
// Set the theme
Utils.applyTheme();
// Remove browserAction "upgraded" badge when opening panel
this.clearBrowserActionBadge();
@ -1244,6 +1247,7 @@ Logic.registerPanel(REOPEN_IN_CONTAINER_PICKER, {
if (currentTab.cookieStoreId !== "firefox-default") {
const tr = document.createElement("tr");
tr.classList.add("menu-item", "hover-highlight", "keyboard-nav");
tr.setAttribute("tabindex", "0");
const td = document.createElement("td");
td.innerHTML = Utils.escaped`
@ -1492,7 +1496,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
} else {
MozillaVPN.handleMozillaCtaClick("mac-edit-container-panel-btn");
}
});
this.switch.addEventListener("click", async() => {
@ -1547,6 +1551,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
this.updateProxyDependentUi(proxy);
} else {
this.switch.checked = false;
this.updateProxyDependentUi({});
return;
}
});
@ -1677,7 +1682,6 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
this.currentCityName.textContent = proxyInfo.cityName;
this.countryCode = proxyInfo.countryCode;
}
return;
}
expandUi() {
@ -1892,6 +1896,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
if (proxyPermissionEnabled) {
const proxyData = await proxifiedContainers.retrieve(identity.cookieStoreId);
if (proxyData && proxyData.proxy.mozProxyEnabled && !mozillaVpnConnected) {
mozillaVpnUi.updateProxyDependentUi({});
return;
}
const proxy = proxyData ? proxyData.proxy : {};
@ -2243,15 +2248,6 @@ Logic.registerPanel(P_CONTAINER_DELETE, {
// Populating the panel: name, icon, and warning message
document.getElementById("container-delete-title").textContent = identity.name;
const totalNumberOfTabs = identity.numberOfHiddenTabs + identity.numberOfOpenTabs;
let warningMessage = "";
if (totalNumberOfTabs > 0) {
const grammaticalNumTabs = totalNumberOfTabs > 1 ? "tabs" : "tab";
warningMessage = `If you remove this container now, ${totalNumberOfTabs} container ${grammaticalNumTabs} will be closed.`;
}
document.getElementById("delete-container-tab-warning").textContent = warningMessage;
return Promise.resolve(null);
},
});

View file

@ -44,7 +44,7 @@ proxifiedContainers = {
// Parses a proxy description string of the format type://host[:port] or type://username:password@host[:port] (port is optional)
parseProxy(proxy_str, mozillaVpnData = null) {
const proxyRegexp = /(?<type>(https?)|(socks4?)):\/\/(\b(?<username>\w+):(?<password>\w+)@)?(?<host>((?:\d{1,3}\.){3}\d{1,3}\b)|(\b([\w.-]+)+))(:(?<port>\d+))?/;
const proxyRegexp = /(?<type>(https?)|(socks4?)):\/\/(\b(?<username>[\w-]+):(?<password>[\w-]+)@)?(?<host>((?:\d{1,3}\.){3}\d{1,3}\b)|(\b([\w.-]+)+))(:(?<port>\d+))?/;
const matches = proxyRegexp.exec(proxy_str);
if (!matches) {
return false;

View file

@ -2,6 +2,9 @@
const DEFAULT_FAVICON = "/img/blank-favicon.svg";
// eslint-disable-next-line
const CONTAINER_ORDER_STORAGE_KEY = "container-order";
// TODO use export here instead of globals
const Utils = {
@ -166,6 +169,26 @@ const Utils = {
false
);
},
/* Theme helper
*
* First, we look if there's a theme already set in the local storage. If
* there isn't one, we set the theme based on `prefers-color-scheme`.
* */
getTheme(currentTheme, window) {
if (typeof currentTheme !== "undefined" && currentTheme !== "auto") {
return currentTheme;
}
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";
}
return "light";
},
async applyTheme() {
const { currentTheme } = await browser.storage.local.get("currentTheme");
const popup = document.getElementsByTagName("html")[0];
const theme = Utils.getTheme(currentTheme, window);
popup.setAttribute("data-theme", theme);
}
};
window.Utils = Utils;

View file

@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Firefox Multi-Account Containers",
"version": "8.0.4",
"version": "8.0.7",
"incognito": "not_allowed",
"description": "__MSG_extensionDescription__",
"icons": {

View file

@ -77,6 +77,24 @@
</fieldset>
</div>
<!--
TODO
- Add data-i18n
-->
<h3 data-i18n-message-id="theme"></h3>
<p><label class="keyboard-shortcut">
<span data-i18n-message-id="chooseTheme"></span>
<select id="changeTheme" name="changeTheme">
<option value="auto" selected data-i18n-message-id="themeAuto">
</option>
<option value="light" data-i18n-message-id="themeLight">
</option>
<option value="dark" data-i18n-message-id="themeDark">
</option>
</select>
</label></p>
<h3 data-i18n-message-id="keyboardShortCuts"></h3>
<p><em data-i18n-message-id="editWhichContainer"></em></p>

View file

@ -1,4 +1,4 @@
<html>
<html data-theme="auto">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Multi-Account Containers</title>
@ -251,7 +251,7 @@
</table>
</div>
<v-padding-hack-footer></v-padding-hack-footer>
<div class="bottom-btn keyboard-nav hover-highlight" id="manage-container-link" tabindex="0" data-i18n-message-id="manageThisContainer"></div>
<div class="bottom-btn keyboard-nav hover-highlight controller" id="manage-container-link" tabindex="0" data-i18n-message-id="manageThisContainer"></div>
</div>
@ -299,7 +299,7 @@
<legend class="form-header" data-i18n-message-id="icon"></legend>
</fieldset>
<fieldset class="proxies"> <!---- PROXIES -->
<input type="text" class="proxies" name="container-proxy" id="edit-container-panel-proxy" maxlength="50" placeholder="type://host:port" hidden/>
<input type="text" class="proxies" name="container-proxy" id="edit-container-panel-proxy" placeholder="type://host:port" hidden/>
<input type="text" class="proxies" name="moz-proxy-enabled" id="moz-proxy-enabled" maxlength="5" hidden/>
<input type="text" class="proxies" name="country-code" id="country-code-input" maxlength="5" hidden/>
<input type="text" class="proxies" name="city-name" id="city-name-input" maxlength="5" hidden/>
@ -342,10 +342,11 @@
</button>
</div>
</moz-vpn-container-ui>
<button id="advanced-proxy-settings-btn" class="proxy-section advanced-proxy-settings-btn controller">
<button id="advanced-proxy-settings-btn" class="proxy-section advanced-proxy-settings-btn">
<span class="advanced-proxy-settings-btn-label" data-i18n-message-id="advancedProxySettings"></span>
<span id="advanced-proxy-address"></span>
</button>
<hr>
<button class="delete-container delete-btn alert-text" id="delete-container-button" data-i18n-message-id="deleteThisContainer"></button>
<!-- TODO get UX / CONTENT on how to message about unavailable proxies -->
@ -394,7 +395,6 @@
<hr>
<div class="panel-content delete-container-confirm">
<h4 class="delete-container-confirm-title" data-i18n-message-id="removeThisContainer"></h4>
<p class="delete-warning" id="delete-container-tab-warning"></p>
<p class="delete-warning" data-i18n-message-id="removeThisContainerConfirmation"></p>
</div>
<div class="panel-footer">
@ -441,7 +441,7 @@
<form class="advanced-proxy-panel-content">
<label class="advanced-proxy-input-label" for="container-proxy" data-i18n-message-id="advancedProxySettings"></label>
<div class="advanced-proxy-input-wrapper">
<input id="edit-advanced-proxy-input" class="proxy-host primary-input" name="container-proxy" type="text" maxlength="50" placeholder="type://host:port" />
<input id="edit-advanced-proxy-input" class="proxy-host primary-input" name="container-proxy" type="text" placeholder="type://host:port" />
<button id="clear-advanced-proxy-input" class="controller" data-i18n-attribute="value" data-i18n-attribute-message-id="clearproxylabel"></button>
<span class="proxy-validity" data-i18n-message-id="invalidProxyAlert"></span>
</div>
@ -450,7 +450,7 @@
</form>
<div id="permissions-overlay" class="permissions-overlay" data-tab-group="proxy-disabled">
<p data-tab-group="proxy-disabled" data-i18n-message-id="additionalPermissionNeeded"></p>
<button id="enable-proxy-permissions" class="primary-cta" data-tab-group="proxy-disabled">Enable</button>
<button id="enable-proxy-permissions" class="primary-cta" data-tab-group="proxy-disabled" data-i18n-message-id="enable"></button>
</div>
</div>
<script src="js/utils.js"></script>