commit 25a82acbe0eb363dd18a79568cebb12a9928dd77
parent 6b06723196a8d53591e3c9799f4933dced19c3a1
Author: Rebecca King <rking@mozilla.com>
Date: Thu, 18 Dec 2025 14:31:47 +0000
Bug 2004964 - Add capability for warning type messages in Firefox VPN panel - r=ip-protection-reviewers,fluent-reviewers,bolsson,kpatenio
Differential Revision: https://phabricator.services.mozilla.com/D275867
Diffstat:
5 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/browser/components/ipprotection/IPProtectionPanel.sys.mjs b/browser/components/ipprotection/IPProtectionPanel.sys.mjs
@@ -129,6 +129,7 @@ export class IPProtectionPanel {
isAlpha: lazy.IPPEnrollAndEntitleManager.isAlpha,
hasUpgraded: lazy.IPPEnrollAndEntitleManager.hasUpgraded,
onboardingMessage: "",
+ bandwidthWarning: "",
};
if (window) {
diff --git a/browser/components/ipprotection/content/ipprotection-content.mjs b/browser/components/ipprotection/content/ipprotection-content.mjs
@@ -188,6 +188,7 @@ export default class IPProtectionContentElement extends MozLitElement {
this._showMessageBar = false;
this._messageDismissed = true;
this.state.error = "";
+ this.state.bandwidthWarning = false;
}
}
@@ -204,11 +205,17 @@ export default class IPProtectionContentElement extends MozLitElement {
let messageId;
let messageLink;
let messageLinkl10nId;
+ let messageType = "info";
// If there are errors, the error message should take precedence
if (this.#hasErrors) {
messageId = "ipprotection-message-generic-error";
+ messageType = ERRORS.GENERIC;
+ } else if (this.state.bandwidthWarning) {
+ messageId = "ipprotection-message-bandwidth-warning";
+ messageType = "warning";
} else if (this.state.onboardingMessage) {
messageId = this.state.onboardingMessage;
+ messageType = "info";
switch (this.state.onboardingMessage) {
case "ipprotection-message-continuous-onboarding-intro":
@@ -227,7 +234,7 @@ export default class IPProtectionContentElement extends MozLitElement {
return html`
<ipprotection-message-bar
class="vpn-top-content"
- type=${this.#hasErrors ? ERRORS.GENERIC : "info"}
+ type=${messageType}
.messageId=${ifDefined(messageId)}
.messageLink=${ifDefined(messageLink)}
.messageLinkl10nId=${ifDefined(messageLinkl10nId)}
@@ -292,7 +299,9 @@ export default class IPProtectionContentElement extends MozLitElement {
render() {
if (
- (this.#hasErrors || this.state.onboardingMessage) &&
+ (this.#hasErrors ||
+ this.state.onboardingMessage ||
+ this.state.bandwidthWarning) &&
!this._messageDismissed
) {
this._showMessageBar = true;
diff --git a/browser/components/ipprotection/content/ipprotection-message-bar.mjs b/browser/components/ipprotection/content/ipprotection-message-bar.mjs
@@ -22,6 +22,7 @@ export default class IPProtectionMessageBarElement extends MozLitElement {
["generic-error", () => this.genericErrorTemplate()],
["info", () => this.infoMessageTemplate()],
+ ["warning", () => this.warningMessageTemplate()],
]);
DISMISS_EVENT = "ipprotection-message-bar:user-dismissed";
@@ -49,6 +50,13 @@ export default class IPProtectionMessageBarElement extends MozLitElement {
disconnectedCallback() {
super.disconnectedCallback();
+
+ if (this.mozMessageBarEl) {
+ this.mozMessageBarEl.removeEventListener(
+ "message-bar:user-dismissed",
+ this.handleDismiss
+ );
+ }
}
handleDismiss() {
@@ -87,6 +95,17 @@ export default class IPProtectionMessageBarElement extends MozLitElement {
`;
}
+ warningMessageTemplate() {
+ return html`
+ <moz-message-bar
+ type="warning"
+ data-l10n-id=${ifDefined(this.messageId)}
+ dismissable
+ >
+ </moz-message-bar>
+ `;
+ }
+
firstUpdated() {
this.mozMessageBarEl.addEventListener(
"message-bar:user-dismissed",
diff --git a/browser/components/ipprotection/tests/browser/browser_ipprotection_message_bar.js b/browser/components/ipprotection/tests/browser/browser_ipprotection_message_bar.js
@@ -50,6 +50,49 @@ add_task(async function test_generic_error() {
});
/**
+ * Tests the warning message bar
+ */
+add_task(async function test_warning_message() {
+ let content = await openPanel({
+ isSignedOut: false,
+ error: "",
+ });
+
+ let messageBar = content.shadowRoot.querySelector("ipprotection-message-bar");
+
+ Assert.ok(!messageBar, "Message bar should not be present");
+
+ let messageBarLoadedPromise = BrowserTestUtils.waitForMutationCondition(
+ content.shadowRoot,
+ { childList: true, subtree: true },
+ () => content.shadowRoot.querySelector("ipprotection-message-bar")
+ );
+
+ await setPanelState({
+ isSignedOut: false,
+ error: "",
+ bandwidthWarning: true,
+ });
+ await messageBarLoadedPromise;
+
+ messageBar = content.shadowRoot.querySelector("ipprotection-message-bar");
+
+ Assert.ok(messageBar, "Message bar should be present");
+ Assert.ok(
+ messageBar.mozMessageBarEl,
+ "Wrapped moz-message-bar should be present"
+ );
+ Assert.equal(messageBar.type, "warning", "Message bar should be warning");
+ Assert.equal(
+ messageBar.messageId,
+ "ipprotection-message-bandwidth-warning",
+ "Warning message id should match"
+ );
+
+ await closePanel();
+});
+
+/**
* Tests that dismissing the message bar dispatches the expected events and
* removes it from the DOM.
*/
diff --git a/browser/locales-preview/ipProtection.ftl b/browser/locales-preview/ipProtection.ftl
@@ -90,6 +90,10 @@ ipprotection-message-generic-error =
.heading = Couldn’t connect to VPN
.message = Try again in a few minutes.
+ipprotection-message-bandwidth-warning =
+ .heading = You’re almost at your bandwidth limit
+ .message = You have 1 GB of the allocated 150 GB left this month.
+
ipprotection-message-continuous-onboarding-intro = Turn on VPN to hide your location and add extra encryption to your browsing.
ipprotection-message-continuous-onboarding-autostart = <a data-l10n-name="setting-link">Set VPN to turn on</a> every time you open { -brand-short-name } for an extra layer of protection.
ipprotection-message-continuous-onboarding-site-settings = { -brand-short-name } will remember which websites you’ve set to use VPN. Update these in <a data-l10n-name="setting-link">settings</a> anytime.