Compare commits

...

121 Commits

Author SHA1 Message Date
Danny Colin 6594a061d6 Merge pull request #2460 from mozilla/version-bump-package-json
version bump package json
2022-11-29 12:05:29 -05:00
Danny Colin 65a36ee5be Merge pull request #2428 from dannycolin/radio-hover-css
Fix broken radio focus styling in light mode
2022-11-29 12:05:10 -05:00
Maxx Crawford 00fd9b7aab Merge pull request #2432 from dannycolin/update-l10n
update l10n to get the missing strings in 8.1.0 build
2022-11-29 10:14:07 -06:00
Maxx Crawford 4d1acc1d8e Generate package-lock.json locally with correct versions of node, npm 2022-11-29 10:09:32 -06:00
Danny Colin 2f99ec4613 Merge pull request #2450 from dannycolin/revert-2231
Backout #2231 from 8.1.0
2022-11-29 10:47:59 -05:00
Maxx Crawford 0070f9c942 Bump version number to 8.1.1 2022-11-29 09:44:07 -06:00
Maxx Crawford 00beddc4cd Add package-lock.json to tracked files 2022-11-29 09:43:50 -06:00
Danny Colin 8e7d9f7574 Revert "Excluding containers from sync with RegExp"
This reverts commit bf31fa9196.
2022-11-18 23:40:58 -05:00
Danny Colin 06c897583b Revert "Fix empty sync exclude regexp behavior (#2383)"
This reverts commit e5fa98d69e.
2022-11-18 23:40:46 -05:00
Danny Colin f41139402e update l10n 2022-10-26 13:55:06 -04:00
Danny Colin c4b0823526 bump version to 8.1.1 2022-10-20 17:58:06 -04:00
Danny Colin 5ccf55cbd1 Fix broken radio focus styling in light mode 2022-10-20 14:57:18 -04:00
Danny Colin a7aaacd82c Merge pull request #2422 from dannycolin/issue-2421
Fix #2421 - Truncate text to ensure the delete icon is visible
2022-10-13 11:07:23 -04:00
Danny Colin 638524ad67 Merge pull request #2424 from eemeli/bug-1794329
Account for moved aboutNetError.css in Firefox 107
2022-10-11 09:25:14 -04:00
Danny Colin 4e91a86072 Keep both files 2022-10-11 09:22:48 -04:00
Eemeli Aro 9597c1bdab Account for moved aboutNetError.css in Firefox 107 2022-10-10 10:18:06 +03:00
Danny Colin 441f6c6c34 Fix #2421 - Truncate text to ensure the delete icon is visible 2022-10-06 19:29:23 -04:00
Danny Colin 80970dbe02 Merge pull request #2410 from mozilla/bump-version-to-8.1.0
bump version to 8.1.0
2022-08-31 14:27:21 -04:00
luke crouch e8baa00935 bump version to 8.1.0 2022-08-31 11:14:12 -05:00
luke crouch d642f132fc Merge pull request #2405 from dannycolin/update-deps
Update minimal version of web-ext
2022-08-10 15:52:57 -05:00
Danny Colin 233c2a5498 Update minimal version of web-ext
This removes all the critical and high vulnerabilities
2022-08-10 16:21:45 -04:00
luke crouch 54a2254763 Merge pull request #2403 from dannycolin/update-bug-template
Make Troubleshooting Information optional
2022-08-04 09:05:29 -05:00
Danny Colin 3d5785df4b Make Troubleshooting Information optional 2022-08-04 09:47:06 -04:00
luke crouch 4508c940ae Merge pull request #2391 from dannycolin/issue-2168
Fix #2168 Use a different l10n string for sites opened in no container
2022-08-01 09:08:46 -05:00
Danny Colin 222d4e7d37 Fix #2168 Use a different l10n string for sites opened in no container 2022-07-27 19:48:39 -04:00
Danny Colin b69b839fa4 Merge pull request #2390 from dannycolin/issue-1103
Add ability to filter the container list
2022-07-27 12:48:17 -04:00
Danny Colin 47062d2bea add ability to filter the container list 2022-07-21 17:30:16 -04:00
Danny Colin 12dd2ee05c Merge pull request #2389 from polarn/fix-contrib-submodule-doc
fix git submodule command doc
2022-07-18 19:37:26 -04:00
Marcus Johansson 8dcb561468 fix git submodule command doc 2022-07-18 15:35:28 +02:00
stoically 2f32c915a9 Merge pull request #1141 from stoically/delete-identitystate
Remove identityState when deleting containers
2022-07-15 20:12:03 +02:00
Danny Colin 7dee05ec1f Merge pull request #2384 from dannycolin/clean-documentation
Update documentation and templates
2022-07-08 18:21:05 -04:00
stoically e5fa98d69e Fix empty sync exclude regexp behavior (#2383) 2022-07-07 01:39:58 +02:00
Danny Colin ee3ead965f Use local web-ext for the dev environment 2022-07-05 13:32:26 -04:00
Danny Colin b66e0fa6a3 Update CONTRIBUTING.md
Co-authored-by: Maxx Crawford <maxx.crawford@gmail.com>
2022-07-05 12:26:27 -04:00
Danny Colin 78423a17af update contributing section 2022-06-24 17:16:30 -04:00
Danny Colin 6b02da4dc1 add pull request template 2022-06-24 16:55:03 -04:00
Danny Colin ecaee4bcf9 Update documentation 2022-06-24 16:51:15 -04:00
Danny Colin a399f8452b Merge pull request #2231 from stoically/stoically/feat/sync-exclude-regexp
Excluding containers from sync with RegExp
2022-06-23 14:27:26 -04:00
stoically 76d5b36563 Remove identityState when deleting containers
Fixes #1140
2022-06-23 01:46:02 +02:00
stoically bf31fa9196 Excluding containers from sync with RegExp 2022-06-23 00:28:54 +02:00
Danny Colin 66b90006bd Merge pull request #2380 from dannycolin/issue-2377
Fix #2377 Tooltip renders off viewport when hovering over a container assigned to VPN.
2022-06-21 15:57:28 -04:00
Danny Colin c64df9f260 Use browser builtin tooltip
If the containers list is too long, the tooltip is rendered outside the visible area. Using the builtin tooltip ensures that it is always rendered on top of all the items and so it prevents it to be hidden if the list overflow.
2022-06-21 11:29:06 -04:00
Danny Colin af73c1a401 Merge pull request #2374 from dannycolin/add-bug-template
Fix rendering for Troubleshooting info section
2022-06-09 16:39:59 -04:00
Danny Colin a55f7411f8 Fix rendering for Troubleshooting info section 2022-06-08 18:57:00 -04:00
luke crouch 27401a5678 Merge pull request #2367 from dannycolin/add-bug-template
Update issue menu
2022-05-20 12:36:43 -05:00
Danny Colin 73e690a559 Update issue menu
- Remove en-US in SUMO URLs so it redirects the user to right locales
- Make it clearer that Ask a question is about support questions
2022-05-19 19:47:09 -04:00
luke crouch cdc014e3ee Merge pull request #2366 from dannycolin/add-bug-template
Update the "new issue" template
2022-05-19 07:38:48 -05:00
Danny Colin 352131a8f9 Delete deprecated bug template 2022-05-18 19:50:54 -04:00
Danny Colin da942a8def Add a "new issue" menu
This menu offers different options to redirect the user to the right resources for their issue.
2022-05-18 19:50:10 -04:00
Danny Colin ce63dc2f6b Add a new bug template 2022-05-18 19:48:50 -04:00
Danny Colin adeab46229 Merge pull request #1964 from dannycolin/issue-1948
fix #1948 Add option to select a light/dark theme
2022-05-11 17:08:57 -04:00
Andrea Marchesini e47b26698f Merge pull request #2355 from rodcul/hyphens-in-proxy
Also allow hyphens in proxy username/password
2022-05-11 15:08:51 -04:00
Danny Colin aaef0fd4a6 Fix elements styling to follow the Proton Design System more closely
This includes fixes for the hover, active and focus states of all the
elements that didn't have one.
2022-05-10 20:51:34 -04:00
Rodney Cullen 931e0a4c13 Also allow hyphens in proxy username/password 2022-05-09 14:10:14 +01:00
Andrea Marchesini 873ba0ab09 Merge pull request #2346 from mozilla/order
Fix the tab sorting for custom container ordering - MAC-710
2022-05-02 16:15:20 +02:00
Andrea Marchesini beb6a40231 Merge pull request #2347 from ranjan-purbey/main
Make "default container" entry keyboard navigable
2022-05-02 12:13:46 +02:00
Ranjan Purbey a8f22944b9 Make "default container" entry kbd navigable
Allows selecting "default container" in "reopen this site in" identity picker
 using keyboard
2022-04-30 00:59:58 +05:30
Andrea Marchesini d6c6ce6e67 Fix the tab sorting for custom container ordering - MAC-710 2022-04-29 01:29:54 +02:00
Andrea Marchesini ba5c58ccbb Merge pull request #2343 from flodolo/gh_test
Use GitHub Actions for testing
2022-04-27 17:26:16 +02:00
Francesco Lodolo [:flod] fd1200fcfe Use GitHub Actions for testing 2022-04-27 16:25:57 +02:00
Andrea Marchesini 847fba26a9 Merge pull request #2340 from mozilla/MAC709
Refresh the UI even when there are no proxy settings - MAC-709
2022-04-26 07:39:23 +02:00
Andrea Marchesini d4e9502e94 Merge pull request #2333 from eladyn/proxy_proxyDNS_fix
enable proxyDNS only for supported proxies (SOCKS4/5)
2022-04-25 19:52:48 +02:00
Andrea Marchesini 5d7b970f1c Refresh the UI even when there are no proxy settings - MAC-709 2022-04-25 09:10:41 +02:00
eladyn 0b869a139a improve proxy type matching
Co-authored-by: nekno <nekno@users.noreply.github.com>
2022-04-21 14:09:38 +02:00
eladyn 0ef50dd2f0 enable proxyDNS only for supported proxies (SOCKS4/5) 2022-04-19 16:21:56 +02:00
Andrea Marchesini 26457f4c3f Merge pull request #2296 from Caligatio/proxy-limit-fix
Remove maxlength from proxy settings
2022-04-06 18:15:34 +02:00
Andrea Marchesini d4291c5e0d Merge pull request #2325 from mozilla/version-bump
Bump version to 8.0.7
2022-04-06 18:14:48 +02:00
Lesley Norton e6a2e34740 Bump version to 8.0.7 2022-04-06 10:58:43 -05:00
Andrea Marchesini 7af82ad54d Merge pull request #2323 from strseb/basti/fixInitDelay
Handle any response as signal that the mvpn-bridge is present
2022-04-05 20:28:20 +02:00
Sebastian Streich 338bd1e6ac Handle any response as signal that the mvpn-bridge is present 2022-04-05 17:45:08 +02:00
Brian Turek a9e3014652 Remove maxlength from proxy settings
The proxy settings input needs to be able to accept input in the of
form of type://username:password@hostname:port which can exceed 50
characters.
2022-02-21 22:07:43 +00:00
luke crouch cdd8ebc66a Merge pull request #2285 from mozilla/version-bump-8.0.6
Bump version number to 8.0.6
2022-02-10 15:52:53 -06:00
luke crouch 916151482c Merge pull request #2283 from mozilla/fix-advanced-proxy-2278
return single ProxyInfo object when advanced proxy
2022-02-10 15:52:37 -06:00
Lesley Norton e013fae815 Bump version number to 8.0.6 2022-02-09 19:32:19 -06:00
luke crouch a3e978338a return single ProxyInfo object when advanced proxy 2022-02-09 14:47:59 -06:00
luke crouch 81258abfa8 Merge pull request #2243 from mozilla/update-readme-fx-req
Update required Firefox version number to 91.1.0
2022-02-09 14:22:21 -06:00
Lesley Norton e4a7658a33 Merge pull request #2275 from mozilla/8.0.5
Bump extension version number to 8.0.5
2022-01-24 15:03:51 -06:00
Lesley Norton 8e68707706 Bump extension version number to 8.0.5 2022-01-24 14:55:25 -06:00
Lesley Norton 83b7f5819b Merge pull request #2267 from mozilla/remove-delete-warning
Remove delete container warning
2022-01-19 08:52:36 -08:00
Lesley Norton e8ca2065b1 Use localized "Enable" string 2022-01-19 10:45:47 -06:00
Lesley Norton 1fe887bab3 Merge pull request #2270 from mozilla/server-list-scrollbars
Remove unusable scrollbars on Mozilla VNP server list (Windows)
2022-01-18 16:22:00 -08:00
Lesley Norton 6ba77014bc Fix server list scroll bars 2022-01-17 10:39:50 -08:00
Lesley Norton 6a1723b415 Remove delete container warning 2022-01-17 11:11:09 -06:00
Andrea Marchesini cb31410dd9 Merge pull request #2258 from mozilla/proxy-dns-2248
fix #2248: proxy DNS too
2022-01-01 21:47:31 +01:00
luke crouch 53e9d24d40 fix #2248: proxy DNS too 2022-01-01 11:01:41 -06:00
Lesley Norton 3df8750c6c Update required Firefox version number to 91.1.0 2021-12-16 22:43:08 -06:00
Andrea Marchesini 3b00ade521 Reintroduce all the languages for the next release 2021-12-15 21:09:14 +01:00
Andrea Marchesini 19600a6f2d Merge pull request #2242 from mozilla/bump-version
Bump version number to 8.0.4
2021-12-14 18:19:17 +00:00
Lesley Norton f4df97f9b0 Bump version number to 8.0.4 2021-12-14 12:14:37 -06:00
Andrea Marchesini 4651126fc1 Merge pull request #2225 from mozilla/make-proxy/nativeMessaging-optional
Make proxy & nativeMessaging permissions optional
2021-12-14 18:09:05 +00:00
Andrea Marchesini f544f41145 Fix travis builds 2021-12-14 19:06:17 +01:00
Lesley Norton 478a6dbdc5 Address review comment 2021-12-14 11:46:44 -06:00
Lesley Norton e87be3df2a Fix MAC-689
This prevents permission prompts from getting lost when multiple permission checkboxes are checked before their corresponding prompts are accepted or declined and one of the permissions requires a reboot when enabled (Jira ticket MAC-689)
2021-12-10 11:49:31 -06:00
Lesley Norton cbcae353a3 Use 'inline-size' instead of 'width' 2021-12-08 18:07:08 -06:00
Lesley Norton 29d586353c Fix onboarding panel buttons on Windows 2021-12-08 17:57:55 -06:00
Lesley Norton c91409646a Use localized string 2021-12-08 17:52:26 -06:00
Lesley Norton 2361fc7899 Fix Windows UI edge cases (Jira - 683) 2021-12-08 14:59:04 -08:00
Lesley Norton dc7b5ca396 Add sumo link to options page 2021-12-08 15:58:30 -06:00
Lesley Norton 1f5245b0bc Update options page when permissions change (Jira 682, 686, 680) 2021-12-08 15:57:18 -06:00
Lesley Norton 8e51ea0134 Add ability to enable permissions from Mozilla VPN + Proxy onboarding panel 2021-12-07 10:22:51 -06:00
Lesley Norton 567a284196 Update options page to latest UX 2021-12-07 10:22:51 -06:00
Lesley Norton 2fbb3e0087 Hide Mozilla VPN proxy flags when proxy permission is disabled 2021-12-07 10:22:50 -06:00
Lesley Norton 396411f8b3 Update panel
- Badge the Options icon when proxy and/or nativeMessaging permissions are disabled. Remove on click, don't show again.
- Use localized strings
- Refactors + cleanup
2021-12-07 10:22:50 -06:00
Lesley Norton 3c3b5ae705 Add Mozilla VPN & Proxy permissions block to options.html 2021-12-07 10:22:50 -06:00
Andrea Marchesini 07d7b0cad4 Make the linter happy again 2021-12-07 10:22:50 -06:00
Andrea Marchesini ca861e2727 Permission handlers triggered on add and on remove 2021-12-07 10:22:50 -06:00
Andrea Marchesini c146a0bd11 Move the permission observers in the background scripts 2021-12-07 10:22:49 -06:00
Lesley Norton 1b165aebb5 Handle proxy and nativeMessaging permission disabling + enabling 2021-12-07 10:22:49 -06:00
Lesley Norton ed63f18cf1 Lint roll 2021-12-07 10:22:49 -06:00
Lesley Norton 5a2e631ed3 Gate MozillaVPN tout on enabled permissions in edit container panels 2021-12-07 10:22:49 -06:00
Lesley Norton ef662cdc72 Show permission warning in advanced proxy panel 2021-12-07 10:22:49 -06:00
Lesley Norton 66359941bf Start updates to to options.html 2021-12-07 10:22:49 -06:00
Lesley Norton 09d9b05a93 Make nativeMessaging and proxy permissions optional 2021-12-07 10:22:48 -06:00
Andrea Marchesini e3772b28b9 Disable languages again for 8.0.3 2021-11-30 10:58:52 +01:00
Andrea Marchesini 9aeb80e6ab Merge pull request #2223 from mozilla/proxy
Use an empty object for no-proxy requests
2021-11-30 07:04:10 +01:00
Andrea Marchesini aae1fc0016 Merge pull request #2224 from mozilla/version8.0.3
Version bump: 8.0.3
2021-11-30 07:01:40 +01:00
Andrea Marchesini 64cf810c30 Version bump: 8.0.3 2021-11-29 23:29:11 +01:00
Andrea Marchesini 8bde28a4ac Use an empty object for no-proxy requests 2021-11-29 16:21:36 +01:00
luke crouch ac98046a65 Merge pull request #2215 from Exagone313/confirm-page-autofocus-confirm
Automatically focus confirm button on confirm page
2021-11-28 08:47:15 -06:00
Elouan Martinet cd8e1ea0f7 Automatically focus confirm button on confirm page (#2214)
This is a regression introduced in commit:
05dc48eac2

The autofocus attribute was removed unexpectedly in a localization
change.
2021-11-25 18:31:50 +01:00
Andrea Marchesini 80393ceb04 Include all the languages 2021-11-25 08:12:00 +01:00
38 changed files with 28035 additions and 843 deletions
+1
View File
@@ -19,6 +19,7 @@ module.exports = {
"OS": true, "OS": true,
"ADDON_UNINSTALL": true, "ADDON_UNINSTALL": true,
"ADDON_DISABLE": true, "ADDON_DISABLE": true,
"CONTAINER_ORDER_STORAGE_KEY": true,
"proxifiedContainers": true, "proxifiedContainers": true,
"MozillaVPN": true, "MozillaVPN": true,
"MozillaVPN_Background": true "MozillaVPN_Background": true
-27
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
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: 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
- type: textarea
id: about_support
attributes:
label: "Provide a copy of Troubleshooting Information page (optional)"
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."
render: "plain text"
validations:
required: false
+17
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"
@@ -0,0 +1,24 @@
**Before submitting your pull request**
- [ ] I agree to license my code under the [MPL 2.0 license](https://www.mozilla.org/en-US/MPL/2.0/).
- [ ] I rebased my work on top of the main branch.
- [ ] I ran `npm test` and all tests passed.
- [ ] I added test coverages if relevant.
# Description
*Please include a summary of the changes including relevant motivation and context.*
## Type of change
*Select all that apply.*
- [ ] Bug fix
- [ ] New feature
- [ ] Major change (fix or feature that would cause existing functionality to work differently than in the current version)
Tag issues related to this pull request:
*
*
*
+4 -4
View File
@@ -9,16 +9,16 @@ on:
- main - main
- production - production
schedule: schedule:
- cron: '0 2 * * *' # Daily at 2AM UTC - cron: '0 2 * * *' # Daily at 2AM UTC
jobs: jobs:
builds: builds:
name: Builds name: Builds
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Create the package - name: Create the package
shell: bash shell: bash
@@ -26,7 +26,7 @@ jobs:
./bin/build-addon.sh nightly.xpi ./bin/build-addon.sh nightly.xpi
- name: Uploading - name: Uploading
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v3
with: with:
name: ${{matrix.config.name}} Build name: ${{matrix.config.name}} Build
path: src/web-ext-artifacts path: src/web-ext-artifacts
+28
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
-1
View File
@@ -1,5 +1,4 @@
.DS_Store .DS_Store
package-lock.json
node_modules node_modules
README.html README.html
*.xpi *.xpi
-7
View File
@@ -1,7 +0,0 @@
language: node_js
node_js:
- "lts/*"
notifications:
irc:
- "ircs://irc.mozilla.org:6697/#testpilot-containers-bots"
+27 -24
View File
@@ -1,35 +1,38 @@
# Contributing # Contributing
Everyone is welcome to contribute to containers. Reach out to team members if you have questions: ## Requirements
- Matrix chat: [#containers:mozilla.org](https://matrix.to/#/#containers:mozilla.org) * Firefox 91.1.0+
- Email: containers@mozilla.com * Git 2.13+
* Node 7+
## Filing bugs ## Getting Started
If you find a bug with containers, please file a issue. 1. Follow the instructions on [How to fork a repository][fork]
2. Fetch the locales:
Check first if the bug might already exist: https://github.com/mozilla/multi-account-containers/issues ```
cd multi-account-containers
git submodule update --init
```
3. Install the project dependencies
```
npm install --legacy-peer-deps
```
4. Run `npm run dev`.
[Open an issue](https://github.com/mozilla/multi-account-containers/issues/new) ## Translations
1. Visit about:support The translations are located in `src/_locales`. This directory is a git
2. Click "Copy raw data to clipboard" and paste into the bug. Alternatively copy the following sections into the issue: repository like any other. Before editing files in this folder, you need to:
- Application Basics
- Nightly Features (if you are in nightly)
- Extensions
- Experimental Features
3. Include clear steps to reproduce the issue you have experienced.
4. Include screenshots if possible.
## Sending Pull Requests 1. `cd src/_locales/`
2. `git checkout -b message-updates-yyyymmdd`
3. `git push -u origin message-updates-yyyymmdd`
Patches should be submitted as pull requests. When submitting patches as PRs: You can then [open a pull request][pr] on [the l10n repository][l10n].
- You agree to license your code under the project's open source license (MPL 2.0). [fork]: https://docs.github.com/en/get-started/quickstart/fork-a-repo
- Base your branch off the current master (see below for an example workflow). [l10n]: https://github.com/mozilla-l10n/multi-account-containers-l10n/
- Add both your code and new tests if relevant. [pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests
- Run npm test to make sure all tests still pass. [web-ext]: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext
- Please do not include merge commits in pull requests; include only commits with the new relevant code.
See the main [README](./README.md) for information on prerequisites, installing, running and testing.
View File
+21 -98
View File
@@ -1,109 +1,32 @@
# Multi-Account Containers # Multi-Account Containers
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/) [![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)
[Available on addons.mozilla.org](https://addons.mozilla.org/firefox/addon/multi-account-containers/) 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!
For more info, see: Learn more about Multi-Account Containers in
[our end-user documentation][enduser].
* [Test Pilot Product Hypothesis Document](https://docs.google.com/document/d/1WQdHTVXROk7dYkSFluc6_hS44tqZjIrG9I-uPyzevE8/edit#) ## Contributing
* [Shield Product Hypothesis Document](https://docs.google.com/document/d/1vMD-fH_5hGDDqNvpRZk12_RhCN2WAe4_yaBamaNdtik/edit#)
Everyone is welcome to contribute to Multi-Account Containers. To learn how
to contribute a patch to Multi-Account Container, please
[read our contributing guide][contributing].
## Requirements You can also chat with us on [our Matrix room][matrix] or [our forum][forum].
* node 7+ (for jpm) This repository is governed by Mozilla's code of conduct and etiquette
* Firefox 57+ guidelines. For more details, [please read the Mozilla Community Participation Guidelines][cpg].
### License
## Development 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 https://mozilla.org/MPL/2.0/.
### Running Locally <!-- Please keep the list in alphabetical order -->
[contributing]: CONTRIBUTING.md
#### Via WebExtensions API (web-ext) [cpg]: https://www.mozilla.org/about/governance/policies/participation/
[enduser]: https://support.mozilla.org/en-US/kb/containers
1. Fetch the locales updating the git-submodules: `git submodule init && git submodule update --remote --depth 1 src/_locales` [forum]: https://discourse.mozilla.org/c/containers/223
2. Install the [web-ext](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext) tool. [matrix]: https://matrix.to/#/#containers:mozilla.org
3. Run `web-ext run -s src/`. This launches Firefox and installs the extension automatically.
This tool provides some additional development features, such as [automatic reloading](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext#Automatic_extension_reloading).
#### Via about:debugging in Firefox
1. Fetch the locales updating the git-submodules: `git submodule init && git submodule update --remote --depth 1 src/_locales`
2. Open the `about:debugging` page in Firefox.
3. Click on `This Firefox`.
4. Click on [Load Temporary Add-on](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox).
5. Select `src/manifest.json`.
Here is a [video](https://www.youtube.com/watch?v=cer9EUKegG4) that demonstrates how to do this.
### Testing
* Install dependencies:
```
npm install
```
* Run all tests:
```
npm run test
```
* Only run the linter:
```
npm run lint
```
There is a timeout test that sometimes fails on certain machines, so make sure to run the tests on your clone before you make any changes to see if you have this problem.
#### Add/update messages for translation
The `src/_locales` directory is a git repository like any other, so to make changes to the messages:
1. Make whatever changes you need in `src/_locales/en` as you work.
2. `cd src/_locales/en`
3. `git branch message-updates-yyyymmdd`
4. `git push -u origin message-updates-yyyymmdd`
You can then open a pull request from the `message-updates-yyyymmdd` branch to
[the l10n repo](https://github.com/mozilla-l10n/multi-account-containers-l10n/) `main` branch.
### Distributing
#### Make the new version
1. Bump the version number in `package.json` and `manifest.json`
2. Commit the version number bump
3. Create a git tag for the version: `git tag <version>`
4. Push the tag up to GitHub: `git push --tags`
#### Publish to AMO
1. `./bin/build-addon.sh`
2. [Upload the `.zip` to AMO](https://addons.mozilla.org/developers/addon/multi-account-containers/versions/submit/)
#### Publish to GitHub
Finally, we also publish the release to GitHub for those followers.
1. Download the signed `.xpi` from [the addon versions page](https://addons.mozilla.org/developers/addon/multi-account-containers/versions)
2. [Make the new release on
GitHub](https://github.com/mozilla/multi-account-containers/releases/new)
* Use the version number for "Tag version" and "Release title"
* Release notes: copy the output of `git log --no-merges --pretty=format:"%h %s" <previous-version>..<new-version>`
* Attach binaries: select the signed `.xpi` file
### Links
Facebook & Twitter icons CC-Attrib https://fairheadcreative.com.
- [License](./LICENSE.txt)
- [Contributing](./CONTRIBUTING.md)
- [Code Of Conduct](./CODE_OF_CONDUCT.md)
+2 -3
View File
@@ -11,7 +11,7 @@ git submodule init || die
git submodule update --remote --depth 1 src/_locales || die git submodule update --remote --depth 1 src/_locales || die
print Y "Installing dependencies..." print Y "Installing dependencies..."
npm install || die npm install --legacy-peer-deps || die
print Y "Running tests..." print Y "Running tests..."
npm test npm test
@@ -23,5 +23,4 @@ if [[ $# -gt 0 ]]; then
EXTRA_PARAMS="--filename $1" EXTRA_PARAMS="--filename $1"
fi fi
# Let's include just 'en' for this release $(npm bin)/web-ext build --overwrite-dest $EXTRA_PARAMS || die
$(npm bin)/web-ext build --overwrite-dest $EXTRA_PARAMS --ignore-files $(find _locales/* | grep \/en -v) $(find _locales/* | grep en_) || die
-31
View File
@@ -1,31 +0,0 @@
# Acceptance Criteria
## User Experience
- [ ] It should place a containers button on the users browser toolbar
- [ ] It should include all containers management UI inside a door hanger from this toolbar button
- [ ] It should provide a set of default container choices for users to pick from (work, home, travel etc.)
- [ ] Each container type should have a color, icon and name
- [ ] It should allow users to create new containers
- [ ] It should allow users to delete containers
- [ ] It should allow users to open container tabs
- [ ] each container tab should be clearly demarcated by color/icon etc.
- [ ] It should provide a control to show/hide all open tabs of one container type
- [ ] It should provide a control to sort tabs by container type
- [ ] It should provide a control to allow users to open containers in new tab or new window by default
## User Experience Non-Requirements (out of scope)
- [ ] It should not show any UI in browser settings
- [ ] It should not effect the awesome bar
- [ ] It should not effect the Firefox Library
- [ ] It should not make any changes to sync functionality
## Measurements
- [ ] It should measure container tab creations per session
- [ ] It should measure the type of container tab created
- [ ] It should measure container tab creations
- [ ] It should measure new container creations
- [ ] It should measure container deletes
- [ ] It should measure container sorts
- [ ] It should measure container hides
- [ ] It should report URIs accessed across multiple containers
- [ ] It should measure the % of tab-based vs windows-based containers
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

+31
View File
@@ -0,0 +1,31 @@
# Release a new version
## Make the new version
1. Bump the version number in `package.json` and `manifest.json`
2. Commit the version number bump
3. Create a git tag for the version: `git tag <version>`
4. Push the tag up to GitHub: `git push --tags`
## Publish to AMO
1. Run `./bin/build-addon.sh`
2. [Upload the zip file to AMO][amo-upload]
## Publish to GitHub
Finally, we also publish the release to GitHub.
1. Download the signed `.xpi` from [the addon versions page][addon-page]
2. [Create a new release on GitHub][gh-release]
* For *Tag version* and *Release title*, use the version number
* For *Release notes*, copy the output of:
```
git log --no-merges \
--pretty=format:"%h %s" <previous-version>..<new-version>
```
* For the *Attach binaries*, select the signed `.xpi` file
[addon-page]: https://addons.mozilla.org/developers/addon/multi-account-containers/versions
[amo-upload]: https://addons.mozilla.org/developers/addon/multi-account-containers/versions/submit/
[gh-release]: https://github.com/mozilla/multi-account-containers/releases/new
+26514
View File
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -2,19 +2,19 @@
"name": "testpilot-containers", "name": "testpilot-containers",
"title": "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.", "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.2", "version": "8.1.1",
"author": "Andrea Marchesini, Luke Crouch, Lesley Norton, Kendall Werts, Maxx Crawford, Jonathan Kingston", "author": "Andrea Marchesini, Luke Crouch, Lesley Norton, Kendall Werts, Maxx Crawford, Jonathan Kingston",
"bugs": { "bugs": {
"url": "https://github.com/mozilla/multi-account-containers/issues" "url": "https://github.com/mozilla/multi-account-containers/issues"
}, },
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"addons-linter": "^1.3.2", "addons-linter": "^3.23.0",
"ajv": "^6.6.3", "ajv": "^6.6.3",
"chai": "^4.2.0", "chai": "^4.2.0",
"eslint": "^6.6.0", "eslint": "^7.32.0",
"eslint-plugin-no-unsanitized": "^2.0.0", "eslint-plugin-no-unsanitized": "^4.0.0",
"eslint-plugin-promise": "^3.4.0", "eslint-plugin-promise": "^5.2.0",
"htmllint-cli": "0.0.7", "htmllint-cli": "0.0.7",
"json": ">=10.0.0", "json": ">=10.0.0",
"mocha": "^6.2.2", "mocha": "^6.2.2",
@@ -25,7 +25,7 @@
"stylelint": "^13.5.0", "stylelint": "^13.5.0",
"stylelint-config-standard": "^20.0.0", "stylelint-config-standard": "^20.0.0",
"stylelint-order": "^4.0.0", "stylelint-order": "^4.0.0",
"web-ext": "^5.4.1", "web-ext": "^7.1.1",
"webextensions-jsdom": "^1.2.1" "webextensions-jsdom": "^1.2.1"
}, },
"homepage": "https://github.com/mozilla/multi-account-containers#readme", "homepage": "https://github.com/mozilla/multi-account-containers#readme",
@@ -36,7 +36,7 @@
"url": "git+https://github.com/mozilla/multi-account-containers.git" "url": "git+https://github.com/mozilla/multi-account-containers.git"
}, },
"scripts": { "scripts": {
"webext": "web-ext run -s src/", "dev": "web-ext run -s src/",
"lint": "npm-run-all lint:*", "lint": "npm-run-all lint:*",
"lint:addon": "./bin/addons-linter.sh", "lint:addon": "./bin/addons-linter.sh",
"lint:css": "stylelint src/css/*.css", "lint:css": "stylelint src/css/*.css",
+16 -2
View File
@@ -3,6 +3,7 @@
<meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta http-equiv="content-type" content="text/html; charset=utf-8">
<title data-i18n-message-id="confirmNavigationTitle"></title> <title data-i18n-message-id="confirmNavigationTitle"></title>
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" /> <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" />
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="chrome://global/skin/aboutNetError.css" type="text/css" media="all" />
<script type="text/javascript" src="./js/i18n.js"></script> <script type="text/javascript" src="./js/i18n.js"></script>
<link rel="stylesheet" href="/css/confirm-page.css" /> <link rel="stylesheet" href="/css/confirm-page.css" />
</head> </head>
@@ -23,8 +24,21 @@
</label> </label>
<br /> <br />
<div class="button-container"> <div class="button-container">
<button id="deny" class="button" data-message-id="openInContainer" data-message-arg="current-container-name"></button> <button id="deny"
<button id="confirm" class="button primary" data-message-id="openInContainer" data-message-arg="container-name"></button> class="button"
data-message-id="openInContainer"
data-message-arg="current-container-name">
</button>
<button id="deny-no-container"
class="button"
data-message-id="openInNoContainer">
</button>
<button id="confirm"
class="button primary"
autofocus
data-message-id="openInContainer"
data-message-arg="container-name">
</button>
</div> </div>
</form> </form>
</main> </main>
+104 -11
View File
@@ -1,29 +1,122 @@
body { body {
background: #fff; --grey10: #e7e7e7;
color: #202023;
}
h3 { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
margin-block-start: 2.5rem; background: #fff;
color: rgb(74, 74, 79);
font-size: 13px;
overflow: hidden;
} }
h3:first-of-type { h3:first-of-type {
margin-block-start: 1rem; margin-block-start: 2.5rem;
} }
p,
label { label {
color: rgb(74, 74, 79); display: flex;
align-items: center;
font-size: 14px;
}
label > span {
padding-inline-end: 4px;
}
.settings-group {
margin-block-end: 16px;
}
form {
display: flex;
flex-direction: column;
padding-block-end: 1rem;
}
.settings-group p {
margin-inline-start: 24px;
margin-block: 4px 8px;
}
input[type="checkbox"] {
margin-inline: 0 8px;
margin-block: 1px auto;
inline-size: 16px;
block-size: 16px;
}
button {
margin-inline: 0 auto;
}
.keyboard-shortcut {
display: flex;
flex-direction: row;
justify-content: space-between;
max-inline-size: 70%;
align-items: center;
}
.bold {
font-weight: 600;
}
.moz-vpn-proxy-permissions {
margin-block: 0 2rem;
padding-block-end: 1rem;
border-block-end: 1px solid var(--grey10);
display: flex;
flex-direction: column;
}
h3.moz-vpn-proxy-permissions-title {
margin-block-start: 0;
position: relative;
display: flex;
align-items: center;
}
.warning-icon {
display: flex;
align-items: center;
}
.warning-icon.show-warning::before {
background-image: url("/img/warning.svg");
background-size: 24px;
background-repeat: no-repeat;
background-position: center;
content: "";
display: block;
block-size: 24px;
inline-size: 24px;
margin-inline-end: 0.5rem;
}
.moz-vpn-proxy-permissions-title::before,
.moz-vpn-proxy-permissions-title::after {
background-color: var(--grey10);
content: "";
height: 1px;
flex: 1 1 0%;
}
h3.moz-vpn-proxy-permissions-title::before {
margin-inline-end: 2rem;
margin-inline-start: -50%;
}
h3.moz-vpn-proxy-permissions-title::after {
margin-inline-start: 2rem;
margin-inline-end: -50%;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
body { body {
background: #202023; background: #23212a;
color: #fff; color: #fff;
} }
p, p {
label {
color: rgb(177, 177, 179); color: rgb(177, 177, 179);
} }
} }
+640 -451
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.6929 16.0119L13.7399 6.10586C13.5739 5.77358 13.3185 5.49411 13.0025 5.29878C12.6866 5.10346 12.3224 5 11.9509 5C11.5795 5 11.2153 5.10346 10.8993 5.29878C10.5834 5.49411 10.328 5.77358 10.1619 6.10586L5.20894 16.0159C5.0575 16.3206 4.98633 16.659 5.00217 16.999C5.01801 17.3389 5.12033 17.6692 5.29946 17.9586C5.47858 18.2479 5.72858 18.4868 6.0258 18.6526C6.32302 18.8183 6.65762 18.9055 6.99794 18.9059H16.9029C17.2439 18.906 17.5792 18.819 17.8771 18.6531C18.1749 18.4872 18.4255 18.2479 18.6048 17.9579C18.7842 17.668 18.8864 17.337 18.9018 16.9964C18.9172 16.6557 18.8453 16.3169 18.6929 16.0119V16.0119ZM10.9509 8.90586C10.9509 8.64065 11.0563 8.38629 11.2438 8.19876C11.4314 8.01122 11.6857 7.90586 11.9509 7.90586C12.2162 7.90586 12.4705 8.01122 12.658 8.19876C12.8456 8.38629 12.9509 8.64065 12.9509 8.90586V12.9059C12.9509 13.1711 12.8456 13.4254 12.658 13.613C12.4705 13.8005 12.2162 13.9059 11.9509 13.9059C11.6857 13.9059 11.4314 13.8005 11.2438 13.613C11.0563 13.4254 10.9509 13.1711 10.9509 12.9059V8.90586ZM11.9509 17.1559C11.7037 17.1559 11.462 17.0826 11.2565 16.9452C11.0509 16.8078 10.8907 16.6126 10.7961 16.3842C10.7015 16.1558 10.6767 15.9045 10.725 15.662C10.7732 15.4195 10.8922 15.1968 11.0671 15.022C11.2419 14.8472 11.4646 14.7281 11.7071 14.6799C11.9496 14.6317 12.2009 14.6564 12.4293 14.751C12.6577 14.8456 12.8529 15.0058 12.9903 15.2114C13.1276 15.417 13.2009 15.6586 13.2009 15.9059C13.2009 16.2374 13.0692 16.5553 12.8348 16.7897C12.6004 17.0242 12.2825 17.1559 11.9509 17.1559V17.1559Z" fill="#FF4F5E" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+15 -3
View File
@@ -102,6 +102,7 @@ window.assignManager = {
async deleteContainer(userContextId) { async deleteContainer(userContextId) {
const sitesByContainer = await this.getAssignedSites(userContextId); const sitesByContainer = await this.getAssignedSites(userContextId);
this.area.remove(Object.keys(sitesByContainer)); this.area.remove(Object.keys(sitesByContainer));
identityState.storageArea.remove(backgroundLogic.cookieStoreId(userContextId));
}, },
async getAssignedSites(userContextId = null) { async getAssignedSites(userContextId = null) {
@@ -188,13 +189,18 @@ window.assignManager = {
// The following blocks potentially dangerous requests for privacy that come without a tabId // The following blocks potentially dangerous requests for privacy that come without a tabId
if(requestInfo.tabId === -1) { if(requestInfo.tabId === -1) {
return {type: "direct"}; return {};
} }
const tab = await browser.tabs.get(requestInfo.tabId); const tab = await browser.tabs.get(requestInfo.tabId);
const result = await proxifiedContainers.retrieve(tab.cookieStoreId); const result = await proxifiedContainers.retrieve(tab.cookieStoreId);
if (!result || !result.proxy) { if (!result || !result.proxy) {
return {type: "direct"}; return {};
}
// proxyDNS only works for SOCKS proxies
if (["socks", "socks4"].includes(result.proxy.type)) {
result.proxy.proxyDNS = true;
} }
if (!result.proxy.mozProxyEnabled) { if (!result.proxy.mozProxyEnabled) {
@@ -382,6 +388,12 @@ window.assignManager = {
return currentContainerState && currentContainerState.isIsolated; return currentContainerState && currentContainerState.isIsolated;
}, },
maybeAddProxyListeners() {
if (browser.proxy) {
browser.proxy.onRequest.addListener(this.handleProxifiedRequest, {urls: ["<all_urls>"]});
}
},
init() { init() {
browser.contextMenus.onClicked.addListener((info, tab) => { browser.contextMenus.onClicked.addListener((info, tab) => {
info.bookmarkId ? info.bookmarkId ?
@@ -390,7 +402,7 @@ window.assignManager = {
}); });
// Before anything happens we decide if the request should be proxified // Before anything happens we decide if the request should be proxified
browser.proxy.onRequest.addListener(this.handleProxifiedRequest, {urls: ["<all_urls>"]}); this.maybeAddProxyListeners();
// Before a request is handled by the browser we decide if we should // Before a request is handled by the browser we decide if we should
// route through a different container // route through a different container
+45 -8
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 DEFAULT_TAB = "about:newtab";
const backgroundLogic = { const backgroundLogic = {
NEW_TAB_PAGES: new Set([ NEW_TAB_PAGES: new Set([
"about:startpage", "about:startpage",
@@ -19,6 +24,28 @@ const backgroundLogic = {
} }
} }
}); });
browser.permissions.onAdded.addListener(permissions => this.resetPermissions(permissions));
browser.permissions.onRemoved.addListener(permissions => this.resetPermissions(permissions));
},
resetPermissions(permissions) {
permissions.permissions.forEach(async permission => {
switch (permission) {
case "bookmarks":
assignManager.resetBookmarksMenuItem();
break;
case "nativeMessaging":
await MozillaVPN_Background.removeMozillaVpnProxies();
await browser.runtime.reload();
break;
case "proxy":
assignManager.maybeAddProxyListeners();
break;
}
});
}, },
async getExtensionInfo() { async getExtensionInfo() {
@@ -146,7 +173,7 @@ const backgroundLogic = {
if ("isIsolated" in containerState || remove) { if ("isIsolated" in containerState || remove) {
delete containerState.isIsolated; delete containerState.isIsolated;
} else { } else {
containerState.isIsolated = "locked"; containerState.isIsolated = "locked";
} }
return await identityState.storageArea.set(cookieStoreId, containerState); return await identityState.storageArea.set(cookieStoreId, containerState);
} catch (error) { } catch (error) {
@@ -295,19 +322,29 @@ const backgroundLogic = {
continue; continue;
} }
const userContextId = backgroundLogic.getUserContextIdFromCookieStoreId(tab.cookieStoreId); if (!map.has(tab.cookieStoreId)) {
if (!map.has(userContextId)) { const userContextId = backgroundLogic.getUserContextIdFromCookieStoreId(tab.cookieStoreId);
map.set(userContextId, []); 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. // 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. // Let's move tabs.
sortMap.forEach(tabs => { sortMap.forEach(obj => {
for (const tab of tabs) { for (const tab of obj.tabs) {
++pos; ++pos;
browser.tabs.move(tab.id, { browser.tabs.move(tab.id, {
windowId: windowObj.id, windowId: windowObj.id,
-3
View File
@@ -20,9 +20,6 @@ const messageHandler = {
case "resetSync": case "resetSync":
response = sync.resetSync(); response = sync.resetSync();
break; break;
case "resetBookmarksContext":
response = assignManager.resetBookmarksMenuItem();
break;
case "deleteContainer": case "deleteContainer":
response = backgroundLogic.deleteContainer(m.message.userContextId); response = backgroundLogic.deleteContainer(m.message.userContextId);
break; break;
+14 -1
View File
@@ -66,11 +66,11 @@ const MozillaVPN_Background = {
// Handle responses from MozillaVPN client // Handle responses from MozillaVPN client
async handleResponse(response) { async handleResponse(response) {
MozillaVPN_Background._installed = true;
if (response.error && response.error === "vpn-client-down") { if (response.error && response.error === "vpn-client-down") {
MozillaVPN_Background._connected = false; MozillaVPN_Background._connected = false;
return; return;
} }
MozillaVPN_Background._installed = true;
if (response.servers) { if (response.servers) {
const servers = response.servers.countries; const servers = response.servers.countries;
browser.storage.local.set({ [MozillaVPN_Background.MOZILLA_VPN_SERVERS_KEY]: servers}); browser.storage.local.set({ [MozillaVPN_Background.MOZILLA_VPN_SERVERS_KEY]: servers});
@@ -100,6 +100,19 @@ const MozillaVPN_Background = {
get isolationKey() { get isolationKey() {
return this._isolationKey; return this._isolationKey;
}, },
async removeMozillaVpnProxies() {
const proxies = await proxifiedContainers.retrieveAll();
if (!proxies) {
return;
}
for (const proxyObj of proxies) {
const { proxy } = proxyObj;
if (proxy.countryCode !== undefined) {
await proxifiedContainers.delete(proxyObj.cookieStoreId);
}
}
},
}; };
MozillaVPN_Background.init(); MozillaVPN_Background.init();
+19 -2
View File
@@ -12,22 +12,39 @@ async function load() {
denySubmit(redirectUrl); denySubmit(redirectUrl);
}); });
document.getElementById("deny-no-container").addEventListener("click", (e) => {
e.preventDefault();
denySubmit(redirectUrl);
});
const container = await browser.contextualIdentities.get(cookieStoreId); const container = await browser.contextualIdentities.get(cookieStoreId);
const currentContainer = currentCookieStoreId ? await browser.contextualIdentities.get(currentCookieStoreId) : null; const currentContainer = currentCookieStoreId ? await browser.contextualIdentities.get(currentCookieStoreId) : null;
const currentContainerName = currentContainer ? currentContainer.name : ""; const currentContainerName = currentContainer ? setDenyButton(currentContainer.name) : setDenyButton("");
document.querySelectorAll("[data-message-id]").forEach(el => { document.querySelectorAll("[data-message-id]").forEach(el => {
const elementData = el.dataset; const elementData = el.dataset;
const containerName = elementData.messageArg === "container-name" ? container.name : currentContainerName; const containerName = elementData.messageArg === "container-name" ? container.name : currentContainerName;
el.textContent = browser.i18n.getMessage(elementData.messageId, containerName); el.textContent = browser.i18n.getMessage(elementData.messageId, containerName);
}); });
document.getElementById("confirm").addEventListener("click", (e) => { document.getElementById("confirm").addEventListener("click", (e) => {
e.preventDefault(); e.preventDefault();
confirmSubmit(redirectUrl, cookieStoreId); confirmSubmit(redirectUrl, cookieStoreId);
}); });
} }
function setDenyButton(currentContainerName) {
const buttonDeny = document.getElementById("deny");
const buttonDenyNoContainer = document.getElementById("deny-no-container");
if (currentContainerName) {
buttonDenyNoContainer.style.display = "none";
return currentContainerName;
}
buttonDeny.style.display = "none";
return;
}
function appendFavicon(pageUrl, redirectUrlElement) { function appendFavicon(pageUrl, redirectUrlElement) {
const origin = new URL(pageUrl).origin; const origin = new URL(pageUrl).origin;
const favIconElement = Utils.createFavIconElement(`${origin}/favicon.ico`); const favIconElement = Utils.createFavIconElement(`${origin}/favicon.ico`);
+13 -10
View File
@@ -5,6 +5,11 @@ const MozillaVPN = {
const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" });
this.handleStatusIndicatorsInContainerLists(mozillaVpnInstalled); this.handleStatusIndicatorsInContainerLists(mozillaVpnInstalled);
const permissionsEnabled = await this.bothPermissionsEnabled();
if (!permissionsEnabled) {
return;
}
const proxies = await this.getProxies(identities); const proxies = await this.getProxies(identities);
if (Object.keys(proxies).length === 0) { if (Object.keys(proxies).length === 0) {
return; return;
@@ -29,11 +34,8 @@ const MozillaVPN = {
} }
if (!mozillaVpnConnected && proxy.mozProxyEnabled) { if (!mozillaVpnConnected && proxy.mozProxyEnabled) {
flag.classList.add("proxy-unavailable"); flag.classList.add("proxy-unavailable");
const tooltip = el.querySelector(".tooltip.proxy-unavailable");
if (tooltip) {
tooltip.textContent = tooltipProxyWarning;
}
const menuItemName = el.querySelector(".menu-item-name"); const menuItemName = el.querySelector(".menu-item-name");
menuItemName.setAttribute("title", tooltipProxyWarning);
if (menuItemName) { if (menuItemName) {
el.querySelector(".menu-item-name").dataset.mozProxyWarning = "proxy-unavailable"; el.querySelector(".menu-item-name").dataset.mozProxyWarning = "proxy-unavailable";
} }
@@ -63,14 +65,11 @@ const MozillaVPN = {
const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" });
const connectionStatusStringId = mozillaVpnConnected ? "moz-vpn-connected" : "moz-vpn-disconnected"; const connectionStatusStringId = mozillaVpnConnected ? "moz-vpn-connected" : "moz-vpn-disconnected";
const connectionStatusLocalizedString = browser.i18n.getMessage(connectionStatusStringId); const connectionStatusLocalizedString = browser.i18n.getMessage(connectionStatusStringId);
const connectionStatusTooltip = document.querySelector(".vpn-status-container-list");
connectionStatusTooltip.setAttribute("title", connectionStatusLocalizedString);
statusIconEls.forEach(el => { statusIconEls.forEach(el => {
el.style.backgroundImage = mozillaVpnConnected ? connectedIndicatorSrc : disconnectedIndicatorSrc; el.style.backgroundImage = mozillaVpnConnected ? connectedIndicatorSrc : disconnectedIndicatorSrc;
if (el.querySelector(".tooltip")) {
el.querySelector(".tooltip").textContent = connectionStatusLocalizedString;
} else {
el.textContent = connectionStatusLocalizedString;
}
}); });
}, },
@@ -156,6 +155,10 @@ const MozillaVPN = {
}; };
}, },
async bothPermissionsEnabled() {
return await browser.permissions.contains({ permissions: ["proxy", "nativeMessaging"] });
},
async getProxyWarnings(proxyObj) { async getProxyWarnings(proxyObj) {
if (!proxyObj) { if (!proxyObj) {
@@ -245,7 +248,7 @@ const MozillaVPN = {
randomInteger = (randomInteger - server.weight); randomInteger = (randomInteger - server.weight);
} }
return nextServer; return nextServer;
} },
}; };
window.MozillaVPN = MozillaVPN; window.MozillaVPN = MozillaVPN;
+75 -17
View File
@@ -1,17 +1,45 @@
const NUMBER_OF_KEYBOARD_SHORTCUTS = 10; const NUMBER_OF_KEYBOARD_SHORTCUTS = 10;
async function requestPermissions() { async function setUpCheckBoxes() {
const checkbox = document.querySelector("#bookmarksPermissions"); document.querySelectorAll("[data-permission-id]").forEach(async(el) => {
if (checkbox.checked) { const permissionId = el.dataset.permissionId;
const granted = await browser.permissions.request({permissions: ["bookmarks"]}); const permissionEnabled = await browser.permissions.contains({ permissions: [permissionId] });
if (!granted) { el.checked = !!permissionEnabled;
checkbox.checked = false; });
}
function disablePermissionsInputs() {
document.querySelectorAll("[data-permission-id").forEach(el => {
el.disabled = true;
});
}
function enablePermissionsInputs() {
document.querySelectorAll("[data-permission-id").forEach(el => {
el.disabled = false;
});
}
document.querySelectorAll("[data-permission-id").forEach(async(el) => {
const permissionId = el.dataset.permissionId;
el.addEventListener("change", async() => {
if (el.checked) {
disablePermissionsInputs();
const granted = await browser.permissions.request({ permissions: [permissionId] });
if (!granted) {
el.checked = false;
enablePermissionsInputs();
}
return; return;
} }
} else { await browser.permissions.remove({ permissions: [permissionId] });
await browser.permissions.remove({permissions: ["bookmarks"]}); });
} });
browser.runtime.sendMessage({ method: "resetBookmarksContext" });
async function maybeShowPermissionsWarningIcon() {
const bothMozillaVpnPermissionsEnabled = await MozillaVPN.bothPermissionsEnabled();
const permissionsWarningEl = document.querySelector(".warning-icon");
permissionsWarningEl.classList.toggle("show-warning", !bothMozillaVpnPermissionsEnabled);
} }
async function enableDisableSync() { async function enableDisableSync() {
@@ -25,15 +53,20 @@ async function enableDisableReplaceTab() {
await browser.storage.local.set({replaceTabEnabled: !!checkbox.checked}); await browser.storage.local.set({replaceTabEnabled: !!checkbox.checked});
} }
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() { async function setupOptions() {
const hasPermission = await browser.permissions.contains({permissions: ["bookmarks"]});
const { syncEnabled } = await browser.storage.local.get("syncEnabled"); const { syncEnabled } = await browser.storage.local.get("syncEnabled");
const { replaceTabEnabled } = await browser.storage.local.get("replaceTabEnabled"); const { replaceTabEnabled } = await browser.storage.local.get("replaceTabEnabled");
if (hasPermission) { const { currentThemeId } = await browser.storage.local.get("currentThemeId");
document.querySelector("#bookmarksPermissions").checked = true;
}
document.querySelector("#syncCheck").checked = !!syncEnabled; document.querySelector("#syncCheck").checked = !!syncEnabled;
document.querySelector("#replaceTabCheck").checked = !!replaceTabEnabled; document.querySelector("#replaceTabCheck").checked = !!replaceTabEnabled;
document.querySelector("#changeTheme").selectedIndex = currentThemeId;
setupContainerShortcutSelects(); setupContainerShortcutSelects();
} }
@@ -78,13 +111,38 @@ function resetOnboarding() {
browser.storage.local.set({"onboarding-stage": 0}); browser.storage.local.set({"onboarding-stage": 0});
} }
async function resetPermissionsUi() {
await maybeShowPermissionsWarningIcon();
await setUpCheckBoxes();
enablePermissionsInputs();
}
browser.permissions.onAdded.addListener(resetPermissionsUi);
browser.permissions.onRemoved.addListener(resetPermissionsUi);
document.addEventListener("DOMContentLoaded", setupOptions); document.addEventListener("DOMContentLoaded", setupOptions);
document.querySelector("#bookmarksPermissions").addEventListener( "change", requestPermissions);
document.querySelector("#syncCheck").addEventListener( "change", enableDisableSync); document.querySelector("#syncCheck").addEventListener( "change", enableDisableSync);
document.querySelector("#replaceTabCheck").addEventListener( "change", enableDisableReplaceTab); document.querySelector("#replaceTabCheck").addEventListener( "change", enableDisableReplaceTab);
document.querySelector("button").addEventListener("click", resetOnboarding); document.querySelector("#changeTheme").addEventListener( "change", changeTheme);
maybeShowPermissionsWarningIcon();
for (let i=0; i < NUMBER_OF_KEYBOARD_SHORTCUTS; i++) { for (let i=0; i < NUMBER_OF_KEYBOARD_SHORTCUTS; i++) {
document.querySelector("#open_container_"+i) document.querySelector("#open_container_"+i)
.addEventListener("change", storeShortcutChoice); .addEventListener("change", storeShortcutChoice);
} }
document.querySelectorAll("[data-btn-id]").forEach(btn => {
btn.addEventListener("click", () => {
switch (btn.dataset.btnId) {
case "reset-onboarding":
resetOnboarding();
break;
case "moz-vpn-learn-more":
browser.tabs.create({
url: MozillaVPN.attachUtmParameters("https://support.mozilla.org/kb/protect-your-container-tabs-mozilla-vpn", "options-learn-more")
});
break;
}
});
});
resetPermissionsUi();
+3
View File
@@ -32,6 +32,9 @@ async function init() {
list.appendChild(fragment); list.appendChild(fragment);
MozillaVPN.handleContainerList(identities); MozillaVPN.handleContainerList(identities);
// Set the theme
Utils.applyTheme();
} }
init(); init();
+171 -73
View File
@@ -10,7 +10,6 @@ const DEFAULT_ICON = "circle";
const NEW_CONTAINER_ID = "new"; const NEW_CONTAINER_ID = "new";
const ONBOARDING_STORAGE_KEY = "onboarding-stage"; const ONBOARDING_STORAGE_KEY = "onboarding-stage";
const CONTAINER_ORDER_STORAGE_KEY = "container-order";
const CONTAINER_DRAG_DATA_TYPE = "firefox-container"; const CONTAINER_DRAG_DATA_TYPE = "firefox-container";
// List of panels // List of panels
@@ -66,6 +65,9 @@ const Logic = {
method: "MozillaVPN_attemptPort" method: "MozillaVPN_attemptPort"
}), }),
// Set the theme
Utils.applyTheme();
// Remove browserAction "upgraded" badge when opening panel // Remove browserAction "upgraded" badge when opening panel
this.clearBrowserActionBadge(); this.clearBrowserActionBadge();
@@ -462,6 +464,23 @@ const Logic = {
default: default:
break; break;
} }
},
filterContainerList() {
const pattern = /^\s+|\s+$/g;
const list = Array.from(document.querySelectorAll("#identities-list tr"));
const search = document.querySelector("#search-terms").value.replace(pattern, "").toLowerCase();
for (const i in list) {
const text = list[i].querySelector("td div span");
if (text.innerText.replace(pattern, "").toLowerCase().includes(search) ||
!search) {
list[i].style.display = "block";
} else {
list[i].style.display = "none";
}
}
} }
}; };
@@ -643,14 +662,29 @@ Logic.registerPanel(P_ONBOARDING_8, {
// This method is called when the object is registered. // This method is called when the object is registered.
initialize() { initialize() {
Utils.addEnterHandler(document.querySelector("#onboarding-done-btn"), async () => { document.querySelectorAll(".onboarding-done").forEach(el => {
await Logic.setOnboardingStage(8); Utils.addEnterHandler(el, async () => {
Logic.showPanel(P_CONTAINERS_LIST); await Logic.setOnboardingStage(8);
Logic.showPanel(P_CONTAINERS_LIST);
});
}); });
}, },
// This method is called when the panel is shown. // This method is called when the panel is shown.
prepare() { async prepare() {
const mozillaVpnPermissionsEnabled = await MozillaVPN.bothPermissionsEnabled();
if (!mozillaVpnPermissionsEnabled) {
const panel = document.querySelector(".onboarding-panel-8");
panel.classList.add("optional-permissions-disabled");
Utils.addEnterHandler(panel.querySelector("#onboarding-enable-permissions"), async () => {
const granted = await browser.permissions.request({ permissions: ["proxy", "nativeMessaging"] });
if (granted) {
await Logic.setOnboardingStage(8);
}
});
}
return Promise.resolve(null); return Promise.resolve(null);
}, },
}); });
@@ -662,24 +696,7 @@ 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() {
const mozillaVpnToutName = "moz-tout-main-panel";
await browser.runtime.sendMessage({ method: "MozillaVPN_queryStatus" }); await browser.runtime.sendMessage({ method: "MozillaVPN_queryStatus" });
Utils.addEnterHandler(document.querySelector("#moz-vpn-learn-more"), () => {
MozillaVPN.handleMozillaCtaClick("mac-main-panel-btn");
window.close();
});
Utils.addEnterHandler(document.querySelector(".dismiss-moz-vpn-tout"), async() => {
const { mozillaVpnHiddenToutsList } = await browser.storage.local.get("mozillaVpnHiddenToutsList");
if (typeof(mozillaVpnHiddenToutsList) === "undefined") {
await browser.storage.local.set({ "mozillaVpnHiddenToutsList": [] });
}
document.querySelector("#moz-vpn-tout").classList.add("disappear");
mozillaVpnHiddenToutsList.push({
name: mozillaVpnToutName
});
await browser.storage.local.set({ mozillaVpnHiddenToutsList });
});
Utils.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(MANAGE_CONTAINERS_PICKER); Logic.showPanel(MANAGE_CONTAINERS_PICKER);
@@ -694,9 +711,6 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
Utils.addEnterHandler(document.querySelector("#always-open-in"), () => { Utils.addEnterHandler(document.querySelector("#always-open-in"), () => {
Logic.showPanel(ALWAYS_OPEN_IN_PICKER); Logic.showPanel(ALWAYS_OPEN_IN_PICKER);
}); });
Utils.addEnterHandler(document.querySelector("#info-icon"), () => {
browser.runtime.openOptionsPage();
});
Utils.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({
@@ -708,16 +722,58 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
} }
}); });
const mozillaVpnToutName = "moz-tout-main-panel";
const mozillaVpnPermissionsWarningDotName = "moz-permissions-warning-dot";
let { mozillaVpnHiddenToutsList } = await browser.storage.local.get("mozillaVpnHiddenToutsList");
if (typeof(mozillaVpnHiddenToutsList) === "undefined") {
await browser.storage.local.set({ "mozillaVpnHiddenToutsList": [] });
mozillaVpnHiddenToutsList = [];
}
// Decide whether to show Mozilla VPN tout
const mozVpnTout = document.getElementById("moz-vpn-tout"); const mozVpnTout = document.getElementById("moz-vpn-tout");
const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" });
if (mozillaVpnInstalled) { const mozillaVpnToutShouldBeHidden = mozillaVpnHiddenToutsList.find(tout => tout.name === mozillaVpnToutName);
return mozVpnTout.remove(); if (mozillaVpnInstalled || mozillaVpnToutShouldBeHidden) {
mozVpnTout.remove();
} }
const { mozillaVpnHiddenToutsList } = await browser.storage.local.get("mozillaVpnHiddenToutsList");
const mozillaVpnToutShouldBeHidden = mozillaVpnHiddenToutsList && mozillaVpnHiddenToutsList.find(tout => tout.name === mozillaVpnToutName); // Add handlers if tout is visible
if (mozillaVpnToutShouldBeHidden) { const mozVpnDismissTout = document.querySelector(".dismiss-moz-vpn-tout");
return mozVpnTout.remove(); if (mozVpnDismissTout) {
Utils.addEnterHandler((mozVpnDismissTout), async() => {
mozVpnTout.remove();
mozillaVpnHiddenToutsList.push({
name: mozillaVpnToutName
});
await browser.storage.local.set({ mozillaVpnHiddenToutsList });
});
Utils.addEnterHandler(document.querySelector("#moz-vpn-learn-more"), () => {
MozillaVPN.handleMozillaCtaClick("mac-main-panel-btn");
window.close();
});
} }
// Badge Options icon if both nativeMessaging and/or proxy permissions are disabled
const bothMozillaVpnPermissionsEnabled = await MozillaVPN.bothPermissionsEnabled();
const warningDotShouldBeHidden = mozillaVpnHiddenToutsList.find(tout => tout.name === mozillaVpnPermissionsWarningDotName);
const optionsIcon = document.getElementById("info-icon");
if (optionsIcon && !bothMozillaVpnPermissionsEnabled && !warningDotShouldBeHidden) {
optionsIcon.classList.add("info-icon-alert");
}
Utils.addEnterHandler((document.querySelector("#info-icon")), async() => {
browser.runtime.openOptionsPage();
if (!mozillaVpnHiddenToutsList.find(tout => tout.name === mozillaVpnPermissionsWarningDotName)) {
optionsIcon.classList.remove("info-icon-alert");
mozillaVpnHiddenToutsList.push({
name: mozillaVpnPermissionsWarningDotName
});
}
await browser.storage.local.set({ mozillaVpnHiddenToutsList });
});
}, },
unregister() { unregister() {
@@ -749,7 +805,6 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
</div> </div>
</div> </div>
<span class="menu-text">${identity.name}</span> <span class="menu-text">${identity.name}</span>
<span class="tooltip proxy-unavailable"></span>
</div> </div>
<span class="menu-right-float"> <span class="menu-right-float">
<img alt="" class="always-open-in-flag flag-img" src="/img/flags/.png"/> <img alt="" class="always-open-in-flag flag-img" src="/img/flags/.png"/>
@@ -799,7 +854,6 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
Utils.addEnterHandler(showPanelButton, () => { Utils.addEnterHandler(showPanelButton, () => {
Logic.showPanel(P_CONTAINER_INFO, identity); Logic.showPanel(P_CONTAINER_INFO, identity);
}); });
} }
const list = document.querySelector("#identities-list"); const list = document.querySelector("#identities-list");
@@ -809,6 +863,7 @@ Logic.registerPanel(P_CONTAINERS_LIST, {
document.addEventListener("keydown", Logic.keyboardNavListener); document.addEventListener("keydown", Logic.keyboardNavListener);
document.addEventListener("keydown", Logic.shortcutListener); document.addEventListener("keydown", Logic.shortcutListener);
document.addEventListener("input", Logic.filterContainerList);
MozillaVPN.handleContainerList(identities); MozillaVPN.handleContainerList(identities);
@@ -1208,6 +1263,7 @@ Logic.registerPanel(REOPEN_IN_CONTAINER_PICKER, {
if (currentTab.cookieStoreId !== "firefox-default") { if (currentTab.cookieStoreId !== "firefox-default") {
const tr = document.createElement("tr"); const tr = document.createElement("tr");
tr.classList.add("menu-item", "hover-highlight", "keyboard-nav"); tr.classList.add("menu-item", "hover-highlight", "keyboard-nav");
tr.setAttribute("tabindex", "0");
const td = document.createElement("td"); const td = document.createElement("td");
td.innerHTML = Utils.escaped` td.innerHTML = Utils.escaped`
@@ -1371,7 +1427,7 @@ Logic.registerPanel(P_CONTAINER_ASSIGNMENTS, {
trElement.innerHTML = Utils.escaped` trElement.innerHTML = Utils.escaped`
<td> <td>
<div class="favicon"></div> <div class="favicon"></div>
<span title="${site.hostname}" class="menu-text">${site.hostname}</span> <span title="${site.hostname}" class="menu-text truncate-text">${site.hostname}</span>
<img class="trash-button delete-assignment" src="/img/container-delete.svg" /> <img class="trash-button delete-assignment" src="/img/container-delete.svg" />
</td>`; </td>`;
trElement.getElementsByClassName("favicon")[0].appendChild(Utils.createFavIconElement(assumedUrl)); trElement.getElementsByClassName("favicon")[0].appendChild(Utils.createFavIconElement(assumedUrl));
@@ -1438,18 +1494,25 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
async connectedCallback() { async connectedCallback() {
const { mozillaVpnHiddenToutsList } = await browser.storage.local.get("mozillaVpnHiddenToutsList"); const { mozillaVpnHiddenToutsList } = await browser.storage.local.get("mozillaVpnHiddenToutsList");
const mozillaVpnCollapseEditContainerTout = mozillaVpnHiddenToutsList && mozillaVpnHiddenToutsList.find(tout => tout.name === this.toutName); const mozillaVpnCollapseEditContainerTout = mozillaVpnHiddenToutsList && mozillaVpnHiddenToutsList.find(tout => tout.name === this.toutName);
const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" });
this.hideShowButton.addEventListener("click", this); this.hideShowButton.addEventListener("click", this);
if (mozillaVpnCollapseEditContainerTout) { if (mozillaVpnCollapseEditContainerTout && !mozillaVpnInstalled) {
this.collapseUi(); this.collapseUi();
} }
// Add listeners // Add listeners
if (!this.classList.contains("has-attached-listeners")) { if (!this.classList.contains("has-attached-listeners")) {
this.primaryCta.addEventListener("click", () => { const bothMozillaVpnPermissionsEnabled = await MozillaVPN.bothPermissionsEnabled();
MozillaVPN.handleMozillaCtaClick("mac-edit-container-panel-btn"); this.primaryCta.addEventListener("click", async() => {
if (!bothMozillaVpnPermissionsEnabled && mozillaVpnInstalled) {
await browser.permissions.request({ permissions: ["proxy", "nativeMessaging"] });
} else {
MozillaVPN.handleMozillaCtaClick("mac-edit-container-panel-btn");
}
}); });
this.switch.addEventListener("click", async() => { this.switch.addEventListener("click", async() => {
@@ -1502,9 +1565,9 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
await proxifiedContainers.set(id.cookieStoreId, proxy); await proxifiedContainers.set(id.cookieStoreId, proxy);
this.switch.checked = true; this.switch.checked = true;
this.updateProxyDependentUi(proxy); this.updateProxyDependentUi(proxy);
} else { } else {
this.switch.checked = false; this.switch.checked = false;
this.updateProxyDependentUi({});
return; return;
} }
}); });
@@ -1518,24 +1581,35 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" });
const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" });
if (!mozillaVpnInstalled) { this.subtitle.textContent = browser.i18n.getMessage("integrateContainers");
this.hideEls(this.switch, this.switchLabel, this.currentServerButton); const bothMozillaVpnPermissionsEnabled = await MozillaVPN.bothPermissionsEnabled();
this.subtitle.textContent = browser.i18n.getMessage("protectThisContainer");
this.primaryCta.addEventListener("click", this);
} else { if (mozillaVpnInstalled && !bothMozillaVpnPermissionsEnabled) {
this.subtitle.style.flex = "1 1 100%";
// Mozilla VPN installed... this.classList.remove("show-server-button");
this.subtitle.textContent = browser.i18n.getMessage("additionalPermissionNeeded");
this.hideEls(this.hideShowButton, this.switch, this.switchLabel, this.currentServerButton);
this.primaryCta.style.display = "block";
this.primaryCta.textContent = browser.i18n.getMessage("enable");
return;
}
if (mozillaVpnInstalled) {
// Hide cta and hide/show button // Hide cta and hide/show button
this.hideEls(this.primaryCta, this.hideShowButton); this.hideEls(this.primaryCta, this.hideShowButton);
// Update subtitle // Update subtitle
this.subtitle.textContent = mozillaVpnConnected ? browser.i18n.getMessage("useCustomLocation") : browser.i18n.getMessage("mozillaVpnMustBeOn"); this.subtitle.textContent = mozillaVpnConnected ? browser.i18n.getMessage("useCustomLocation") : browser.i18n.getMessage("mozillaVpnMustBeOn");
this.subtitle.style.flex = "1 1 80%";
this.currentServerButton.style.display = "flex";
} }
if (!mozillaVpnConnected) { if (mozillaVpnConnected) {
[this.switchLabel, this.switch].forEach(el => {
el.style.display = "inline-block";
});
} else {
this.hideEls(this.switch, this.switchLabel, this.currentServerButton); this.hideEls(this.switch, this.switchLabel, this.currentServerButton);
this.switch.checked = false; this.switch.checked = false;
} }
@@ -1582,17 +1656,15 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
this.mozProxyEnabledInput.value = proxyInfo.mozProxyEnabled; this.mozProxyEnabledInput.value = proxyInfo.mozProxyEnabled;
this.proxyAddressInput.value = `${proxyInfo.type}://${proxyInfo.host}:${proxyInfo.port}`; this.proxyAddressInput.value = `${proxyInfo.type}://${proxyInfo.host}:${proxyInfo.port}`;
if (typeof(proxyInfo.countryCode) === "undefined" && proxyInfo.type !== "direct") { if (typeof(proxyInfo.countryCode) === "undefined" && proxyInfo.type) {
// Set custom proxy URL below 'Advanced proxy settings' button label // Set custom proxy URL below 'Advanced proxy settings' button label
this.advancedProxyAddress.textContent = `${proxyInfo.type}://${proxyInfo.host}:${proxyInfo.port}`; this.advancedProxyAddress.textContent = `${proxyInfo.type}://${proxyInfo.host}:${proxyInfo.port}`;
} }
} }
async updateProxyDependentUi(proxyInfo) { async updateProxyDependentUi(proxyInfo) {
const containerHasProxy = typeof(proxyInfo) !== "undefined";
const mozillaVpnProxyLocationAvailable = (proxy) => { const mozillaVpnProxyLocationAvailable = (proxy) => {
return typeof(proxy.countryCode) !== "undefined" && typeof(proxyInfo.cityName) !== "undefined"; return typeof(proxy) !== "undefined" && typeof(proxy.countryCode) !== "undefined" && typeof(proxy.cityName) !== "undefined";
}; };
const mozillaVpnProxyIsEnabled = (proxy) => { const mozillaVpnProxyIsEnabled = (proxy) => {
@@ -1605,7 +1677,7 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" });
if ( if (
!containerHasProxy || !proxyInfo ||
!mozillaVpnProxyLocationAvailable(proxyInfo) || !mozillaVpnProxyLocationAvailable(proxyInfo) ||
!mozillaVpnConnected !mozillaVpnConnected
) { ) {
@@ -1620,23 +1692,20 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
} }
// Populate inputs and server button with current or previously stored mozilla vpn proxy // Populate inputs and server button with current or previously stored mozilla vpn proxy
if(containerHasProxy && mozillaVpnProxyLocationAvailable(proxyInfo)) { if(proxyInfo && mozillaVpnProxyLocationAvailable(proxyInfo)) {
this.currentCountryFlag.style.backgroundImage = `url("./img/flags/${proxyInfo.countryCode.toUpperCase()}.png")`; this.currentCountryFlag.style.backgroundImage = `url("./img/flags/${proxyInfo.countryCode.toUpperCase()}.png")`;
this.currentCountryFlag.style.backgroundImage = proxyInfo.countryCode + ".png"; this.currentCountryFlag.style.backgroundImage = proxyInfo.countryCode + ".png";
this.currentCityName.textContent = proxyInfo.cityName; this.currentCityName.textContent = proxyInfo.cityName;
this.countryCode = proxyInfo.countryCode; this.countryCode = proxyInfo.countryCode;
} }
return;
} }
expandUi() { expandUi() {
this.classList.add("expanded"); this.classList.add("expanded");
this.style.maxHeight = 500 + "px";
} }
collapseUi() { collapseUi() {
this.classList.remove("expanded"); this.classList.remove("expanded");
this.style.maxHeight = 56 + "px";
} }
hideEls(...els) { hideEls(...els) {
@@ -1673,6 +1742,10 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
customElements.define("moz-vpn-container-ui", MozVpnContainerUi); customElements.define("moz-vpn-container-ui", MozVpnContainerUi);
const mozillaVpnUi = document.querySelector("moz-vpn-container-ui"); const mozillaVpnUi = document.querySelector("moz-vpn-container-ui");
mozillaVpnUi.updateMozVpnStatusDependentUi(); mozillaVpnUi.updateMozVpnStatusDependentUi();
browser.permissions.onAdded.addListener(() => { mozillaVpnUi.updateMozVpnStatusDependentUi(); });
browser.permissions.onRemoved.addListener(() => { mozillaVpnUi.updateMozVpnStatusDependentUi(); });
const advancedProxySettingsButton = document.querySelector(".advanced-proxy-settings-btn"); const advancedProxySettingsButton = document.querySelector(".advanced-proxy-settings-btn");
Utils.addEnterHandler(advancedProxySettingsButton, () => { Utils.addEnterHandler(advancedProxySettingsButton, () => {
Logic.showPanel(P_ADVANCED_PROXY_SETTINGS, this.getEditInProgressIdentity(), false, false); Logic.showPanel(P_ADVANCED_PROXY_SETTINGS, this.getEditInProgressIdentity(), false, false);
@@ -1835,23 +1908,23 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
return; return;
} }
const proxyData = await proxifiedContainers.retrieve(identity.cookieStoreId); const proxyPermissionEnabled = await browser.permissions.contains({ permissions: ["proxy"] });
if (proxyData) { if (proxyPermissionEnabled) {
if (proxyData.proxy && proxyData.proxy.mozProxyEnabled && !mozillaVpnConnected) { const proxyData = await proxifiedContainers.retrieve(identity.cookieStoreId);
if (proxyData && proxyData.proxy.mozProxyEnabled && !mozillaVpnConnected) {
mozillaVpnUi.updateProxyDependentUi({});
return; return;
} }
mozillaVpnUi.updateProxyDependentUi(proxyData.proxy); const proxy = proxyData ? proxyData.proxy : {};
return; mozillaVpnUi.updateProxyDependentUi(proxy);
} }
mozillaVpnUi.updateProxyDependentUi({});
}, },
}); });
Logic.registerPanel(P_ADVANCED_PROXY_SETTINGS, { Logic.registerPanel(P_ADVANCED_PROXY_SETTINGS, {
panelSelector: "#advanced-proxy-settings-panel", panelSelector: "#advanced-proxy-settings-panel",
initialize(){ async initialize() {
this._proxyForm = document.querySelector(".advanced-proxy-panel-content"); this._proxyForm = document.querySelector(".advanced-proxy-panel-content");
this._advancedProxyInput = this._proxyForm.querySelector("#edit-advanced-proxy-input"); this._advancedProxyInput = this._proxyForm.querySelector("#edit-advanced-proxy-input");
const clearAdvancedProxyInput = this._proxyForm.querySelector("#clear-advanced-proxy-input"); const clearAdvancedProxyInput = this._proxyForm.querySelector("#clear-advanced-proxy-input");
@@ -1931,6 +2004,40 @@ Logic.registerPanel(P_ADVANCED_PROXY_SETTINGS, {
const identity = Logic.currentIdentity(); const identity = Logic.currentIdentity();
const advancedProxyInput = document.getElementById("edit-advanced-proxy-input"); const advancedProxyInput = document.getElementById("edit-advanced-proxy-input");
const proxyPermissionEnabled = await browser.permissions.contains({ permissions: ["proxy"] });
if (!proxyPermissionEnabled) {
// Restrict tabbing inside advanced proxy panel to proxy permissions ui
const panel = document.getElementById("advanced-proxy-settings-panel");
const clickableEls = panel.querySelectorAll("button, a, input");
clickableEls.forEach(el => {
if (!el.dataset.tabGroup && el.id !== "advanced-proxy-settings-return") {
el.setAttribute("tabindex", "-1");
el.disabled = true;
}
});
// Show proxy permission overlay
const permissionsOverlay = document.getElementById("permissions-overlay");
permissionsOverlay.style.display = "flex";
// Add "enable" button handling
const enableProxyPermissionsButton = document.getElementById("enable-proxy-permissions");
enableProxyPermissionsButton.addEventListener("click", async() => {
const granted = await browser.permissions.request({ permissions: ["proxy"] });
if (granted) {
permissionsOverlay.style.display = "none";
// restore normal panel tabbing
clickableEls.forEach(el => {
el.tabindex = "0";
el.disabled = false;
});
}
});
}
// reset input // reset input
const resetProxyInput = () => { const resetProxyInput = () => {
if (!advancedProxyInput) { if (!advancedProxyInput) {
@@ -1948,7 +2055,7 @@ Logic.registerPanel(P_ADVANCED_PROXY_SETTINGS, {
}; };
const edit_proxy_dom = function(proxy) { const edit_proxy_dom = function(proxy) {
if (proxy.type === "direct" || typeof proxy.type === "undefined" || MozillaVPN.proxyIsDisabled(proxy)) { if (!proxy.type || MozillaVPN.proxyIsDisabled(proxy)) {
resetProxyInput(); resetProxyInput();
return; return;
} }
@@ -2157,15 +2264,6 @@ Logic.registerPanel(P_CONTAINER_DELETE, {
// Populating the panel: name, icon, and warning message // Populating the panel: name, icon, and warning message
document.getElementById("container-delete-title").textContent = identity.name; 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); return Promise.resolve(null);
}, },
}); });
+2 -2
View File
@@ -44,14 +44,14 @@ proxifiedContainers = {
// Parses a proxy description string of the format type://host[:port] or type://username:password@host[:port] (port is optional) // 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) { 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); const matches = proxyRegexp.exec(proxy_str);
if (!matches) { if (!matches) {
return false; return false;
} }
if (mozillaVpnData && mozillaVpnData.mozProxyEnabled === undefined) { if (mozillaVpnData && mozillaVpnData.mozProxyEnabled === undefined) {
matches.groups.type = "direct"; matches.groups.type = null;
} }
if (!mozillaVpnData) { if (!mozillaVpnData) {
+23
View File
@@ -2,6 +2,9 @@
const DEFAULT_FAVICON = "/img/blank-favicon.svg"; 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 // TODO use export here instead of globals
const Utils = { const Utils = {
@@ -166,6 +169,26 @@ const Utils = {
false 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; window.Utils = Utils;
+5 -5
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "Firefox Multi-Account Containers", "name": "Firefox Multi-Account Containers",
"version": "8.0.2", "version": "8.1.1",
"incognito": "not_allowed", "incognito": "not_allowed",
"description": "__MSG_extensionDescription__", "description": "__MSG_extensionDescription__",
"icons": { "icons": {
@@ -18,16 +18,16 @@
"history", "history",
"idle", "idle",
"management", "management",
"nativeMessaging",
"storage", "storage",
"unlimitedStorage", "unlimitedStorage",
"tabs", "tabs",
"webRequestBlocking", "webRequestBlocking",
"webRequest", "webRequest"
"proxy"
], ],
"optional_permissions": [ "optional_permissions": [
"bookmarks" "bookmarks",
"nativeMessaging",
"proxy"
], ],
"browser_specific_settings": { "browser_specific_settings": {
"gecko": { "gecko": {
+79 -27
View File
@@ -4,85 +4,137 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<script type="text/javascript" src="./js/i18n.js"></script> <script type="text/javascript" src="./js/i18n.js"></script>
<script type="text/javascript" src="./js/mozillaVpn.js"></script>
<script type="text/javascript" src="./js/proxified-containers.js"></script>
<link rel="stylesheet" href="css/options.css"> <link rel="stylesheet" href="css/options.css">
</head> </head>
<body> <body>
<form> <form>
<h3 data-i18n-message-id="optionalPermissions"></h3> <h3 data-i18n-message-id="optionalPermissions"></h3>
<label > <div class="settings-group">
<input type="checkbox" id="bookmarksPermissions"> <label class="permission">
<span data-i18n-message-id="enableBookMarkMenus"></span> <input type="checkbox" data-permission-id="bookmarks" id="bookmarksPermissions">
<span class="bold" data-i18n-message-id="enableBookMarkMenus"></span>
</label> </label>
<p><em data-i18n-message-id="enableBookMarkMenusDescription"></em></p> <p><em data-i18n-message-id="enableBookMarkMenusDescription"></em></p>
</div>
<div id="moz-vpn-proxy-permissions" class="moz-vpn-proxy-permissions">
<h3 class="moz-vpn-proxy-permissions-title">
<span data-i18n-message-id="mozillaVpnAndProxyPermissionsTitle" class="warning-icon"></span>
</h3>
<div class="moz-vpn-proxy-permissions-content">
<div class="settings-group">
<label class="permission">
<input type="checkbox" data-permission-id="nativeMessaging">
<span class="bold" data-i18n-message-id="nativeMessagingPermissionTitle"></span>
</label>
<p><em data-i18n-message-id="nativeMessagingPermissionDescription"></em></p>
</div>
<div class="settings-group">
<label class="permission">
<input type="checkbox" data-permission-id="proxy">
<span class="bold" data-i18n-message-id="proxyPermissionTitle"></span>
</label>
<p><em data-i18n-message-id="proxyPermissionDescription"></em></p>
</div>
</div>
</div>
<h3 data-i18n-message-id="firefoxAccountsSync"></h3> <h3 data-i18n-message-id="firefoxAccountsSync"></h3>
<label> <div class="settings-group">
<input type="checkbox" id="syncCheck"> <label>
<span data-i18n-message-id="enableSync"></span> <input type="checkbox" id="syncCheck">
</label> <span class="bold" data-i18n-message-id="enableSync"></span>
<p><em data-i18n-message-id="enableSyncDescription"></em></p> </label>
<p><em data-i18n-message-id="enableSyncDescription"></em></p>
</div>
<h3 data-i18n-message-id="tabBehavior"></h3> <h3 data-i18n-message-id="tabBehavior"></h3>
<label>
<input type="checkbox" id="replaceTabCheck"> <div class="settings-group">
<span data-i18n-message-id="replaceTab"></span> <label>
</label> <input type="checkbox" id="replaceTabCheck">
<p><em data-i18n-message-id="replaceTabDescription"></em></p> <span class="bold" data-i18n-message-id="replaceTab"></span>
</label>
<p><em data-i18n-message-id="replaceTabDescription"></em></p>
</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> <h3 data-i18n-message-id="keyboardShortCuts"></h3>
<p><em data-i18n-message-id="editWhichContainer"></em></p> <p><em data-i18n-message-id="editWhichContainer"></em></p>
<p><label>
<p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="1"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="1"></span>
<select id="open_container_0"> <select id="open_container_0">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="2"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="2"></span>
<select id="open_container_1"> <select id="open_container_1">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="3"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="3"></span>
<select id="open_container_2"> <select id="open_container_2">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="4"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="4"></span>
<select id="open_container_3"> <select id="open_container_3">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="5"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="5"></span>
<select id="open_container_4"> <select id="open_container_4">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="6"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="6"></span>
<select id="open_container_5"> <select id="open_container_5">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="7"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="7"></span>
<select id="open_container_6"> <select id="open_container_6">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="8"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="8"></span>
<select id="open_container_7"> <select id="open_container_7">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="9"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="9"></span>
<select id="open_container_8"> <select id="open_container_8">
</select> </select>
</label></p> </label></p>
<p><label> <p><label class="keyboard-shortcut">
<span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="10"></span> <span data-i18n-message-id="keyboardShortCut" data-i18n-placeholder="10"></span>
<select id="open_container_9"> <select id="open_container_9">
</select> </select>
</label></p> </label></p>
<h3 data-i18n-message-id="onboarding"></h3> <h3 data-i18n-message-id="onboarding"></h3>
<button data-i18n-message-id="resetOnboardingPanels"></button> <button data-btn-id="reset-onboarding" data-i18n-message-id="resetOnboardingPanels"></button>
<p><em data-i18n-message-id="onboardingToggle"></em></p> <p><em data-i18n-message-id="onboardingToggle"></em></p>
<h3>Mozilla VPN</h3>
<button data-btn-id="moz-vpn-learn-more" data-i18n-message-id="learnMore"></button>
</form> </form>
<script src="js/options.js"></script> <script src="js/options.js"></script>
</body> </body>
+51 -25
View File
@@ -1,4 +1,4 @@
<html> <html data-theme="auto">
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Multi-Account Containers</title> <title>Multi-Account Containers</title>
@@ -62,11 +62,22 @@
</div> </div>
<div class="panel onboarding onboarding-panel-8 hide" id="onboarding-panel-8"> <div class="panel onboarding onboarding-panel-8 hide" id="onboarding-panel-8">
<img class="onboarding-img" alt="" src="/img/moz-vpn-onboarding.svg" /> <div class="moz-vpn-onboarding-content">
<h3 class="onboarding-title" data-i18n-message-id="proxyNowAvailable"></h3> <img class="onboarding-img" alt="" src="/img/moz-vpn-onboarding.svg" />
<p data-i18n-message-id="onboarding-8-description"></p> <h3 class="onboarding-title" data-i18n-message-id="proxyNowAvailable"></h3>
<div class="half-button-wrapper"> <p data-i18n-message-id="onboarding-8-description"></p>
<a href="#" id="onboarding-done-btn" class="half-onboarding-button keyboard-nav" tabindex="0" data-i18n-message-id="done"></a> </div>
<div id="moz-vpn-fw-onboarding-done" class="half-button-wrapper">
<a id="moz-vpn-fw-onboarding-done" href="#" class="half-onboarding-button keyboard-nav onboarding-done" tabindex="0" data-i18n-message-id="done"></a>
</div>
<div class="moz-vpn-permissions">
<div class="moz-vpn-permissions-copy">
<span data-i18n-message-id="mozillaVpnRequiresAdditionalPermissions"></span>
</div>
<div class="half-button-wrapper">
<a href="#" id="permissions-not-now" class="half-onboarding-button grey-button keyboard-nav onboarding-done" tabindex="0" data-i18n-message-id="notNow"></a>
<a href="#" id="onboarding-enable-permissions" class="half-onboarding-button keyboard-nav" tabindex="0" data-i18n-message-id="enable"></a>
</div>
</div> </div>
</div> </div>
@@ -98,7 +109,7 @@
<div class="panel menu-panel container-panel hide" id="container-panel"> <div class="panel menu-panel container-panel hide" id="container-panel">
<h3 class="title">Multi-Account Containers</h3> <h3 class="title">Multi-Account Containers</h3>
<a href="#" class="info-icon" id="info-icon" tabindex="10"> <a href="#" class="info-icon" id="info-icon" tabindex="10">
<img data-i18n-attribute-message-id="info" data-i18n-attribute="alt" alt="" ="info" src="/img/info.svg" / > <img data-i18n-attribute-message-id="info" data-i18n-attribute="alt" alt="" src="/img/info.svg" / >
</a> </a>
<hr> <hr>
<table class="menu"> <table class="menu">
@@ -143,11 +154,22 @@
<div class="sub-header" data-i18n-message-id="containers"></div> <div class="sub-header" data-i18n-message-id="containers"></div>
<h4 class="moz-vpn-logotype vpn-status-container-list display-none">Mozilla VPN <h4 class="moz-vpn-logotype vpn-status-container-list display-none">Mozilla VPN
<span class="moz-vpn-connection-status-indicator container-list-status-icon"> <span class="moz-vpn-connection-status-indicator container-list-status-icon">
<span class="tooltip"></span>
</span> </span>
</h4> </h4>
</div> </div>
<div class="scrollable identities-list"> <div class="scrollable identities-list">
<div class="searchbar">
<label for="search-terms"
class="hide-label"
data-i18n-message-id="filterInputLabel">
</label>
<input type="text"
id="search-terms"
name="search-terms"
placeholder="Search container name"
data-i18n-attribute="placeholder"
data-i18n-attribute-message-id="filterInputPlaceholder">
</div>
<table class="menu" id="identities-list"> <table class="menu" id="identities-list">
<tr class="menu-item hover-highlight"> <tr class="menu-item hover-highlight">
<td> <td>
@@ -170,18 +192,18 @@
</table> </table>
</div> </div>
<div id="moz-vpn-tout" class="moz-vpn-content expanded"> <div id="moz-vpn-tout" class="moz-vpn-content expanded">
<div class="flx-row button-wrapper"> <div class="flx-row button-wrapper">
<h4 class="moz-vpn-logo">Mozilla VPN</h4> <h4 class="moz-vpn-logo">Mozilla VPN</h4>
<button class="controller dismiss-moz-vpn-tout" tab-index="0"></button> <button class="controller dismiss-moz-vpn-tout" tab-index="0"></button>
</div>
<div class="collapsible-content flx-col controller-collapsible-content">
<div class="flx-row flx-space-between">
<span class="moz-vpn-subtitle" data-i18n-message-id="protectYourContainers"></span>
</div>
<button id="moz-vpn-learn-more" class="moz-vpn-cta primary-cta" data-i18n-message-id="learnMore"></button>
</div>
</div> </div>
<v-padding-hack-footer></v-padding-hack-footer> <!--presents last container from getting covered up by the 'manage containers button' when list is long--> <div class="collapsible-content flx-col controller-collapsible-content">
<div class="flx-row flx-space-between">
<span class="moz-vpn-subtitle" data-i18n-message-id="integrateContainers"></span>
</div>
<button id="moz-vpn-learn-more" class="moz-vpn-cta primary-cta" data-i18n-message-id="getMozillaVpn"></button>
</div>
</div>
<v-padding-hack-footer></v-padding-hack-footer> <!--prevents last container from getting covered up by the 'manage containers button' when list is long-->
<div class="bottom-btn keyboard-nav controller" id="manage-containers-link" tabindex="0" data-i18n-message-id="manageContainers"></div> <div class="bottom-btn keyboard-nav controller" id="manage-containers-link" tabindex="0" data-i18n-message-id="manageContainers"></div>
</div> </div>
@@ -240,7 +262,7 @@
</table> </table>
</div> </div>
<v-padding-hack-footer></v-padding-hack-footer> <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> </div>
@@ -288,7 +310,7 @@
<legend class="form-header" data-i18n-message-id="icon"></legend> <legend class="form-header" data-i18n-message-id="icon"></legend>
</fieldset> </fieldset>
<fieldset class="proxies"> <!---- PROXIES --> <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="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="country-code" id="country-code-input" maxlength="5" hidden/>
<input type="text" class="proxies" name="city-name" id="city-name-input" maxlength="5" hidden/> <input type="text" class="proxies" name="city-name" id="city-name-input" maxlength="5" hidden/>
@@ -324,17 +346,18 @@
<span class="slider round"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
<button id="get-mozilla-vpn" class="moz-vpn-cta primary-cta" data-i18n-message-id="learnMore"></button> <button id="get-mozilla-vpn" class="moz-vpn-cta primary-cta" data-i18n-message-id="getMozillaVpn"></button>
<button id="moz-vpn-current-server" class="controller"> <button id="moz-vpn-current-server" class="controller">
<span class="current-country-flag"></span> <span class="current-country-flag"></span>
<span class="current-city-name"></span> <span class="current-city-name"></span>
</button> </button>
</div> </div>
</moz-vpn-container-ui> </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 class="advanced-proxy-settings-btn-label" data-i18n-message-id="advancedProxySettings"></span>
<span id="advanced-proxy-address"></span> <span id="advanced-proxy-address"></span>
</button> </button>
<hr>
<button class="delete-container delete-btn alert-text" id="delete-container-button" data-i18n-message-id="deleteThisContainer"></button> <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 --> <!-- TODO get UX / CONTENT on how to message about unavailable proxies -->
@@ -383,7 +406,6 @@
<hr> <hr>
<div class="panel-content delete-container-confirm"> <div class="panel-content delete-container-confirm">
<h4 class="delete-container-confirm-title" data-i18n-message-id="removeThisContainer"></h4> <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> <p class="delete-warning" data-i18n-message-id="removeThisContainerConfirmation"></p>
</div> </div>
<div class="panel-footer"> <div class="panel-footer">
@@ -430,13 +452,17 @@
<form class="advanced-proxy-panel-content"> <form class="advanced-proxy-panel-content">
<label class="advanced-proxy-input-label" for="container-proxy" data-i18n-message-id="advancedProxySettings"></label> <label class="advanced-proxy-input-label" for="container-proxy" data-i18n-message-id="advancedProxySettings"></label>
<div class="advanced-proxy-input-wrapper"> <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> <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> <span class="proxy-validity" data-i18n-message-id="invalidProxyAlert"></span>
</div> </div>
<button id="submit-advanced-proxy" class="primary-cta apply-to-container" data-i18n-message-id="applyToContainer"></button> <button id="submit-advanced-proxy" class="primary-cta apply-to-container" data-i18n-message-id="applyToContainer"></button>
<a id="advanced-proxy-settings-learn-more" href="" class="blue-link" data-i18n-message-id="learnMore"></a> <a id="advanced-proxy-settings-learn-more" href="" class="blue-link" data-i18n-message-id="learnMore"></a>
</form> </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" data-i18n-message-id="enable"></button>
</div>
</div> </div>
<script src="js/utils.js"></script> <script src="js/utils.js"></script>
<script src="js/popup.js"></script> <script src="js/popup.js"></script>
+27
View File
@@ -0,0 +1,27 @@
const { sinon, nextTick, buildBackgroundDom } = require("../common");
describe("#1140", () => {
beforeEach(async () => {
this.background = await buildBackgroundDom();
});
describe("removing containers", () => {
beforeEach(async () => {
this.background.browser.contextualIdentities.onRemoved.addListener = sinon.stub();
const [promise] = this.background.browser.runtime.onMessage.addListener.yield({
method: "deleteContainer",
message: {
userContextId: "1"
}
});
await promise;
await nextTick();
});
it("should remove the identitystate from storage as well", async () => {
this.background.browser.storage.local.remove.should.have.been.calledWith([
"identitiesState@@_firefox-container-1"
]);
});
});
});