commit 4baf54b7e96085bdb043f4f3b1ad79d9c18f76e2
parent f00627afacaa2a0488a832d8d1d2662914a95dee
Author: Rebecca King <rking@mozilla.com>
Date: Thu, 13 Nov 2025 20:23:00 +0000
Bug 1997328 - Update ipprotection-content element to show onboarding messages based on state - r=ip-protection-reviewers,fluent-reviewers,bolsson,kpatenio
Differential Revision: https://phabricator.services.mozilla.com/D270912
Diffstat:
5 files changed, 70 insertions(+), 13 deletions(-)
diff --git a/browser/components/ipprotection/IPProtectionPanel.sys.mjs b/browser/components/ipprotection/IPProtectionPanel.sys.mjs
@@ -78,6 +78,8 @@ export class IPProtectionPanel {
* True if we're running the Alpha variant, else false.
* @property {boolean} hasUpgraded
* True if a Mozilla VPN subscription is linked to the user's Mozilla account.
+ * @property {string} onboardingMessage
+ * Continuous onboarding message to display in-panel, empty string if none applicable
*/
/**
@@ -123,6 +125,7 @@ export class IPProtectionPanel {
error: "",
isAlpha: lazy.IPPEnrollAndEntitleManager.isAlpha,
hasUpgraded: lazy.IPPEnrollAndEntitleManager.hasUpgraded,
+ onboardingMessage: "",
};
if (window) {
diff --git a/browser/components/ipprotection/content/ipprotection-content.mjs b/browser/components/ipprotection/content/ipprotection-content.mjs
@@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
-import { html } from "chrome://global/content/vendor/lit.all.mjs";
+import { html, ifDefined } from "chrome://global/content/vendor/lit.all.mjs";
import {
LINKS,
ERRORS,
@@ -192,12 +192,36 @@ export default class IPProtectionContentElement extends MozLitElement {
}
messageBarTemplate() {
- // TODO: Set messageId based on state in Bug 1997328
+ let messageId;
+ let messageLink;
+ let messageLinkl10nId;
+ // If there are errors, the error message should take precedence
+ if (this.#hasErrors) {
+ messageId = "ipprotection-message-generic-error";
+ } else if (this.state.onboardingMessage) {
+ messageId = this.state.onboardingMessage;
+
+ switch (this.state.onboardingMessage) {
+ case "ipprotection-message-continuous-onboarding-intro":
+ break;
+ case "ipprotection-message-continuous-onboarding-autostart":
+ messageLink = "about:settings#privacy";
+ messageLinkl10nId = "setting-link";
+ break;
+ case "ipprotection-message-continuous-onboarding-site-settings":
+ messageLink = "about:settings#privacy";
+ messageLinkl10nId = "setting-link";
+ break;
+ }
+ }
+
return html`
<ipprotection-message-bar
class="vpn-top-content"
type=${this.#hasErrors ? ERRORS.GENERIC : "info"}
- messageId="ipprotection-message-continuous-onboarding-1"
+ .messageId=${ifDefined(messageId)}
+ .messageLink=${ifDefined(messageLink)}
+ .messageLinkl10nId=${ifDefined(messageLinkl10nId)}
></ipprotection-message-bar>
`;
}
@@ -265,17 +289,16 @@ export default class IPProtectionContentElement extends MozLitElement {
}
render() {
- // TODO: Set showContinuousOnboarding based on state Bug 1997328
if (
- (this.#hasErrors || this.showContinuousOnboarding) &&
+ (this.#hasErrors || this.state.onboardingMessage) &&
!this._messageDismissed
) {
this._showMessageBar = true;
}
const messageBar = this._showMessageBar ? this.messageBarTemplate() : null;
- //TODO: Check state to determine what position to add the message bar Bug 1997328
- const content = html`${messageBar}${this.mainContentTemplate()}`;
+
+ let content = html`${messageBar}${this.mainContentTemplate()}`;
// TODO: Conditionally render post-upgrade subview within #ipprotection-content-wrapper - Bug 1973813
return html`
diff --git a/browser/components/ipprotection/content/ipprotection-message-bar.mjs b/browser/components/ipprotection/content/ipprotection-message-bar.mjs
@@ -3,11 +3,17 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
-import { html } from "chrome://global/content/vendor/lit.all.mjs";
+import { html, ifDefined } from "chrome://global/content/vendor/lit.all.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://global/content/elements/moz-message-bar.mjs";
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ URILoadingHelper: "resource:///modules/URILoadingHelper.sys.mjs",
+});
+
/**
* A custom element that handles the message bar for IP Protection.
*/
@@ -26,12 +32,15 @@ export default class IPProtectionMessageBarElement extends MozLitElement {
static properties = {
type: { type: String },
messageId: { type: String },
+ messageLink: { type: String },
+ messageLinkl10nId: { type: String },
};
constructor() {
super();
this.handleDismiss = this.handleDismiss.bind(this);
+ this.handleClickSetingsLink = this.handleClickSettingsLink.bind(this);
}
connectedCallback() {
@@ -54,7 +63,7 @@ export default class IPProtectionMessageBarElement extends MozLitElement {
return html`
<moz-message-bar
type="error"
- data-l10n-id="ipprotection-message-generic-error"
+ data-l10n-id=${ifDefined(this.messageId)}
dismissable
>
</moz-message-bar>
@@ -63,7 +72,17 @@ export default class IPProtectionMessageBarElement extends MozLitElement {
infoMessageTemplate() {
return html`
- <moz-message-bar type="info" data-l10n-id=${this.messageId} dismissable>
+ <moz-message-bar type="info" dismissable>
+ <span
+ slot="message"
+ data-l10n-id=${ifDefined(this.messageId)}
+ @click=${this.handleClickSettingsLink}
+ >
+ <a
+ data-l10n-name=${ifDefined(this.messageLinkl10nId)}
+ href=${ifDefined(this.messageLink)}
+ ></a>
+ </span>
</moz-message-bar>
`;
}
@@ -78,6 +97,17 @@ export default class IPProtectionMessageBarElement extends MozLitElement {
);
}
+ handleClickSettingsLink(event) {
+ if (event.target.hasAttribute("href")) {
+ event.preventDefault();
+ lazy.URILoadingHelper.openTrustedLinkIn(window, this.messageLink, "tab");
+
+ this.dispatchEvent(
+ new CustomEvent("IPProtection:Close", { bubbles: true, composed: true })
+ );
+ }
+ }
+
render() {
let messageBarTemplate = this.#MESSAGE_TYPE_MAP.get(this.type)();
diff --git a/browser/components/ipprotection/tests/browser/browser_IPProtectionService.js b/browser/components/ipprotection/tests/browser/browser_IPProtectionService.js
@@ -347,7 +347,7 @@ add_task(async function test_IPProtectionService_retry_errors() {
// Mock a failure
IPPEnrollAndEntitleManager.resetEntitlement();
- IPPProxyManager.setErrorState();
+ IPPProxyManager.setErrorState(ERRORS.GENERIC);
let startedEventPromise = BrowserTestUtils.waitForEvent(
IPPProxyManager,
diff --git a/browser/locales-preview/ipProtection.ftl b/browser/locales-preview/ipProtection.ftl
@@ -74,8 +74,9 @@ ipprotection-message-generic-error =
.heading = Couldn’t connect to VPN
.message = Try again in a few minutes.
-ipprotection-message-continuous-onboarding-1 =
- .message = Turn on VPN to hide your location and add extra encryption to your browsing.
+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.
## IP Protection Settings