Skip to content

Commit 4a4e53e

Browse files
author
Niklas Baumgardner
committed
Bug 1876200 - Add keep closed shopping message bar. r=shopping-reviewers,fluent-reviewers,desktop-theme-reviewers,flod,kpatenio,jules
Differential Revision: https://phabricator.services.mozilla.com/D199743
1 parent 4a0a5a0 commit 4a4e53e

13 files changed

+768
-7
lines changed

browser/app/profile/firefox.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,12 @@ pref("browser.shopping.experience2023.autoOpen.enabled", false);
790790
// Opens the shopping sidebar automatically when viewing a PDP.
791791
pref("browser.shopping.experience2023.autoOpen.userEnabled", true);
792792

793+
// Number of times the sidebar has been closed in a session
794+
pref("browser.shopping.experience2023.sidebarClosedCount", 0);
795+
796+
// When conditions are met, shows a prompt on the shopping sidebar asking users if they want to disable auto-open behavior
797+
pref("browser.shopping.experience2023.showKeepSidebarClosedMessage", true);
798+
793799
// Enables the display of the Mozilla VPN banner in private browsing windows
794800
pref("browser.privatebrowsing.vpnpromourl", "https://vpn.mozilla.org/?utm_source=firefox-browser&utm_medium=firefox-%CHANNEL%-browser&utm_campaign=private-browsing-vpn-link");
795801

browser/components/BrowserGlue.sys.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ let JSWINDOWACTORS = {
761761
ReportProductAvailable: { wantUntrusted: true },
762762
AdClicked: { wantUntrusted: true },
763763
AdImpression: { wantUntrusted: true },
764+
ShowCallout4: { wantUntrusted: true },
764765
},
765766
},
766767
matches: ["about:shoppingsidebar"],

browser/components/shopping/ShoppingSidebarChild.sys.mjs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,29 @@ export class ShoppingSidebarChild extends RemotePageChild {
9191
let uri = url ? Services.io.newURI(url) : null;
9292
// If we're going from null to null, bail out:
9393
if (!this.#productURI && !uri) {
94-
return;
94+
return null;
9595
}
9696

9797
// If we haven't reloaded, check if the URIs represent the same product
9898
// as sites might change the URI after they have loaded (Bug 1852099).
9999
if (!isReload && this.isSameProduct(uri, this.#productURI)) {
100-
return;
100+
return null;
101101
}
102102

103103
this.#productURI = uri;
104104
this.updateContent({ haveUpdatedURI: true });
105105
break;
106+
case "ShoppingSidebar:ShowKeepClosedMessage":
107+
this.sendToContent("ShowKeepClosedMessage");
108+
break;
109+
case "ShoppingSidebar:HideKeepClosedMessage":
110+
this.sendToContent("HideKeepClosedMessage");
111+
break;
112+
case "ShoppingSidebar:IsKeepClosedMessageShowing":
113+
return !!this.document.querySelector("shopping-container")
114+
?.wrappedJSObject.showingKeepClosedMessage;
106115
}
116+
return null;
107117
}
108118

109119
isSameProduct(newURI, currentURI) {
@@ -155,6 +165,11 @@ export class ShoppingSidebarChild extends RemotePageChild {
155165
ShoppingProduct.sendAttributionEvent("impression", aid);
156166
Glean.shopping.surfaceAdsImpression.record();
157167
break;
168+
case "ShowCallout4":
169+
this.sendAsyncMessage("Shopping:SendTrigger", {
170+
id: "shoppingAutoOpenUserDisabled", // TODO: update this in bug 1874949
171+
});
172+
break;
158173
}
159174
}
160175

browser/components/shopping/ShoppingSidebarParent.sys.mjs

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,26 @@ ChromeUtils.defineESModuleGetters(lazy, {
1414

1515
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
1616

17+
XPCOMUtils.defineLazyPreferenceGetter(
18+
lazy,
19+
"AUTO_OPEN_SIDEBAR_ENABLED",
20+
"browser.shopping.experience2023.autoOpen.enabled",
21+
true
22+
);
23+
XPCOMUtils.defineLazyPreferenceGetter(
24+
lazy,
25+
"AUTO_OPEN_SIDEBAR_USER_ENABLED",
26+
"browser.shopping.experience2023.autoOpen.userEnabled",
27+
true
28+
);
29+
1730
export class ShoppingSidebarParent extends JSWindowActorParent {
1831
static SHOPPING_ACTIVE_PREF = "browser.shopping.experience2023.active";
1932
static SHOPPING_OPTED_IN_PREF = "browser.shopping.experience2023.optedIn";
33+
static SIDEBAR_CLOSED_COUNT_PREF =
34+
"browser.shopping.experience2023.sidebarClosedCount";
35+
static SHOW_KEEP_SIDEBAR_CLOSED_MESSAGE_PREF =
36+
"browser.shopping.experience2023.showKeepSidebarClosedMessage";
2037

2138
updateProductURL(uri, flags) {
2239
this.sendAsyncMessage("ShoppingSidebar:UpdateProductURL", {
@@ -34,17 +51,74 @@ export class ShoppingSidebarParent extends JSWindowActorParent {
3451
"browser[messagemanagergroup=browsers]"
3552
);
3653
return associatedTabbedBrowser.currentURI?.spec ?? null;
54+
case "Shopping:SendTrigger":
55+
let trigger = message.data;
56+
if (!trigger.browser) {
57+
trigger.browser =
58+
this.browsingContext.topChromeWindow.gBrowser.selectedBrowser;
59+
}
60+
lazy.ShoppingUtils.sendTrigger(message.data);
3761
}
3862
return null;
3963
}
4064

4165
/**
4266
* Called when the user clicks the URL bar button.
4367
*/
44-
static urlbarButtonClick(event) {
68+
static async urlbarButtonClick(event) {
4569
if (event.button > 0) {
4670
return;
4771
}
72+
73+
if (
74+
lazy.AUTO_OPEN_SIDEBAR_ENABLED &&
75+
lazy.AUTO_OPEN_SIDEBAR_USER_ENABLED &&
76+
event.target.getAttribute("shoppingsidebaropen") === "true"
77+
) {
78+
let gBrowser = event.target.ownerGlobal.gBrowser;
79+
let shoppingBrowser = gBrowser
80+
.getPanel(gBrowser.selectedBrowser)
81+
.querySelector(".shopping-sidebar");
82+
let actor =
83+
shoppingBrowser.browsingContext.currentWindowGlobal.getActor(
84+
"ShoppingSidebar"
85+
);
86+
87+
let isKeepClosedMessageShowing = await actor.sendQuery(
88+
"ShoppingSidebar:IsKeepClosedMessageShowing"
89+
);
90+
91+
let sidebarClosedCount = Services.prefs.getIntPref(
92+
ShoppingSidebarParent.SIDEBAR_CLOSED_COUNT_PREF,
93+
0
94+
);
95+
if (
96+
!isKeepClosedMessageShowing &&
97+
sidebarClosedCount >= 4 &&
98+
Services.prefs.getBoolPref(
99+
ShoppingSidebarParent.SHOW_KEEP_SIDEBAR_CLOSED_MESSAGE_PREF,
100+
true
101+
)
102+
) {
103+
actor.sendAsyncMessage("ShoppingSidebar:ShowKeepClosedMessage");
104+
return;
105+
}
106+
107+
actor.sendAsyncMessage("ShoppingSidebar:HideKeepClosedMessage");
108+
109+
if (sidebarClosedCount >= 6) {
110+
Services.prefs.setBoolPref(
111+
ShoppingSidebarParent.SHOW_KEEP_SIDEBAR_CLOSED_MESSAGE_PREF,
112+
false
113+
);
114+
}
115+
116+
Services.prefs.setIntPref(
117+
ShoppingSidebarParent.SIDEBAR_CLOSED_COUNT_PREF,
118+
sidebarClosedCount + 1
119+
);
120+
}
121+
48122
this.toggleAllSidebars("urlBar");
49123
}
50124

browser/components/shopping/ShoppingUtils.sys.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ const AUTO_OPEN_ENABLED_PREF =
2727
"browser.shopping.experience2023.autoOpen.enabled";
2828
const AUTO_OPEN_USER_ENABLED_PREF =
2929
"browser.shopping.experience2023.autoOpen.userEnabled";
30+
const SIDEBAR_CLOSED_COUNT_PREF =
31+
"browser.shopping.experience2023.sidebarClosedCount";
3032

3133
const CFR_FEATURES_PREF =
3234
"browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features";
@@ -90,6 +92,8 @@ export const ShoppingUtils = {
9092
}
9193
Services.prefs.addObserver(ACTIVE_PREF, this.onActiveUpdate);
9294

95+
Services.prefs.setIntPref(SIDEBAR_CLOSED_COUNT_PREF, 0);
96+
9397
this.initialized = true;
9498
},
9599

browser/components/shopping/content/shopping-container.mjs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ import "chrome://browser/content/shopping/recommended-ad.mjs";
2828
// top of the sidebar to show the header box shadow.
2929
const HEADER_SCROLL_PIXEL_OFFSET = 8;
3030

31+
const SIDEBAR_CLOSED_COUNT_PREF =
32+
"browser.shopping.experience2023.sidebarClosedCount";
33+
const SHOW_KEEP_SIDEBAR_CLOSED_MESSAGE_PREF =
34+
"browser.shopping.experience2023.showKeepSidebarClosedMessage";
35+
const SHOPPING_SIDEBAR_ACTIVE_PREF = "browser.shopping.experience2023.active";
36+
3137
export class ShoppingContainer extends MozLitElement {
3238
static properties = {
3339
data: { type: Object },
@@ -44,6 +50,7 @@ export class ShoppingContainer extends MozLitElement {
4450
isOverflow: { type: Boolean },
4551
autoOpenEnabled: { type: Boolean },
4652
autoOpenEnabledByUser: { type: Boolean },
53+
showingKeepClosedMessage: { type: Boolean },
4754
};
4855

4956
static get queries() {
@@ -58,6 +65,7 @@ export class ShoppingContainer extends MozLitElement {
5865
recommendedAdEl: "recommended-ad",
5966
loadingEl: "#loading-wrapper",
6067
closeButtonEl: "#close-button",
68+
keepClosedMessageBarEl: "#keep-closed-message-bar",
6169
};
6270
}
6371

@@ -77,6 +85,8 @@ export class ShoppingContainer extends MozLitElement {
7785
window.document.addEventListener("UpdateRecommendations", this);
7886
window.document.addEventListener("UpdateAnalysisProgress", this);
7987
window.document.addEventListener("autoOpenEnabledByUserChanged", this);
88+
window.document.addEventListener("ShowKeepClosedMessage", this);
89+
window.document.addEventListener("HideKeepClosedMessage", this);
8090

8191
window.dispatchEvent(
8292
new CustomEvent("ContentReady", {
@@ -175,6 +185,12 @@ export class ShoppingContainer extends MozLitElement {
175185
case "autoOpenEnabledByUserChanged":
176186
this.autoOpenEnabledByUser = event.detail?.autoOpenEnabledByUser;
177187
break;
188+
case "ShowKeepClosedMessage":
189+
this.showingKeepClosedMessage = true;
190+
break;
191+
case "HideKeepClosedMessage":
192+
this.showingKeepClosedMessage = false;
193+
break;
178194
}
179195
}
180196

@@ -358,12 +374,13 @@ export class ShoppingContainer extends MozLitElement {
358374
id="close-button"
359375
class="ghost-button shopping-button"
360376
data-l10n-id="shopping-close-button"
361-
@click=${this.handleClick}
377+
@click=${this.handleCloseButtonClick}
362378
></button>
363379
</div>
364380
<div id="content" aria-live="polite" aria-busy=${!this.data}>
365381
<slot name="multi-stage-message-slot"></slot>
366-
${sidebarContent} ${!hideFooter ? this.getFooterTemplate() : null}
382+
${this.keepClosedMessageTemplate()}${sidebarContent}
383+
${!hideFooter ? this.getFooterTemplate() : null}
367384
</div>
368385
</div>`;
369386
}
@@ -385,6 +402,21 @@ export class ShoppingContainer extends MozLitElement {
385402
`;
386403
}
387404

405+
keepClosedMessageTemplate() {
406+
if (
407+
this.autoOpenEnabled &&
408+
this.autoOpenEnabledByUser &&
409+
this.showingKeepClosedMessage &&
410+
RPMGetBoolPref(SHOW_KEEP_SIDEBAR_CLOSED_MESSAGE_PREF, true)
411+
) {
412+
return html`<shopping-message-bar
413+
id="keep-closed-message-bar"
414+
type="keep-closed"
415+
></shopping-message-bar>`;
416+
}
417+
return null;
418+
}
419+
388420
render() {
389421
let content;
390422
let hideFooter;
@@ -410,8 +442,28 @@ export class ShoppingContainer extends MozLitElement {
410442
return this.renderContainer(content, hideFooter);
411443
}
412444

413-
handleClick() {
414-
RPMSetPref("browser.shopping.experience2023.active", false);
445+
handleCloseButtonClick() {
446+
if (this.autoOpenEnabled && this.autoOpenEnabledByUser) {
447+
let sidebarClosedCount = RPMGetIntPref(SIDEBAR_CLOSED_COUNT_PREF, 0);
448+
if (
449+
!this.showingKeepClosedMessage &&
450+
sidebarClosedCount >= 4 &&
451+
RPMGetBoolPref(SHOW_KEEP_SIDEBAR_CLOSED_MESSAGE_PREF, true)
452+
) {
453+
this.showingKeepClosedMessage = true;
454+
return;
455+
}
456+
457+
this.showingKeepClosedMessage = false;
458+
459+
if (sidebarClosedCount >= 6) {
460+
RPMSetPref(SHOW_KEEP_SIDEBAR_CLOSED_MESSAGE_PREF, false);
461+
}
462+
463+
RPMSetPref(SIDEBAR_CLOSED_COUNT_PREF, sidebarClosedCount + 1);
464+
}
465+
466+
RPMSetPref(SHOPPING_SIDEBAR_ACTIVE_PREF, false);
415467
Glean.shopping.surfaceClosed.record({ source: "closeButton" });
416468
}
417469
}

0 commit comments

Comments
 (0)