Skip to content

Commit f51b2a5

Browse files
committed
Bug 2011449 - Part 4: Add documentation for newtab activation window mechanism. r=home-newtab-reviewers,nbarrett
Differential Revision: https://phabricator.services.mozilla.com/D280831
1 parent ee8077d commit f51b2a5

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Activation Window Feature
2+
3+
## Overview
4+
5+
The Activation Window feature allows the browser to experiment with the first hours of a new profile's lifetime by temporarily setting different defaults during a configurable time period (typically 48 hours). This enables:
6+
7+
- Hiding or showing specific content sections (top sites, top stories) during the activation window
8+
- Displaying messaging when entering or exiting the activation window
9+
- Reverting to normal defaults after the activation window expires
10+
- Preserving user preference changes made during the activation window
11+
12+
The feature is controlled via Nimbus experiments using the `newtabTrainhop` feature with `type: "activationWindowBehavior"`.
13+
14+
## How It Works
15+
16+
### High-level Architecture
17+
18+
1. **Profile Creation Time Tracking** (`AboutNewTab.sys.mjs`)
19+
- The browser computes the profile creation instant on startup using `ProfileAge.sys.mjs`
20+
- The `createdInstant` is cached on the ActivityStream instance for the session
21+
22+
2. **Activation Window Evaluation** (`PrefsFeed.sys.mjs`)
23+
- `checkForActivationWindow()` runs on:
24+
- PrefsFeed initialization (startup)
25+
- Each NEW_TAB_STATE_REQUEST action (when opening a new tab)
26+
- It compares the current time against the profile age to determine if we're within the activation window
27+
- Enters or exits activation window state as needed
28+
29+
3. **Default Pref Manipulation**
30+
- When entering the activation window: Sets default branch prefs for top sites/stories to experiment values
31+
- When exiting the activation window: Restores default branch prefs to original values
32+
- User pref values _always_ override defaults, even after enabling and then re-disabling.
33+
34+
4. **User Preference Tracking**
35+
- Tracks user preference changes during the activation window
36+
- On exit, ensures that any user changes are persisted
37+
38+
5. **State Broadcasting**
39+
- Pref changes are broadcast to all content processes
40+
- StartupCacheInit queues changes for the cached about:home page if it exists
41+
42+
6. **Messaging Integration**
43+
- PrefsFeed sets message ID prefs on enter/exit: `activationWindow.enterMessageID` and `activationWindow.exitMessageID`
44+
- ASRouter messages can target these prefs using JEXL expressions
45+
- The `ActivationWindowMessage` component renders messages with bespoke UI (card layout with image, heading, message, and buttons)
46+
47+
## Configuration
48+
49+
### Nimbus Configuration Schema
50+
51+
The activation window is configured via Nimbus using the `newtabTrainhop` feature:
52+
53+
```javascript
54+
{
55+
featureId: "newtabTrainhop",
56+
value: {
57+
type: "activationWindowBehavior",
58+
payload: {
59+
enabled: true,
60+
maxProfileAgeInHours: 48,
61+
disableTopSites: true,
62+
disableTopStories: true,
63+
variant: "a",
64+
enterActivationWindowMessageID: "ACTIVATION_WINDOW_WELCOME_V1",
65+
exitActivationWindowMessageID: "ACTIVATION_WINDOW_EXIT_V1"
66+
}
67+
}
68+
}
69+
```
70+
71+
#### Configuration Fields
72+
73+
- **`enabled`** (boolean, default: false): Whether the activation window feature is active
74+
- **`maxProfileAgeInHours`** (number, default: 48): Duration of the activation window in hours
75+
- **`disableTopSites`** (boolean, default: false): Hide top sites section during activation window
76+
- **`disableTopStories`** (boolean, default: false): Hide top stories section during activation window
77+
- **`variant`** (string, default: ""): Experiment variant identifier
78+
- **`enterActivationWindowMessageID`** (string, default: ""): Message ID to show when entering the window
79+
- **`exitActivationWindowMessageID`** (string, default: ""): Message ID to show when exiting the window
80+
81+
### Message Structure
82+
83+
Messages for the activation window use the `ActivationWindowMessage` component and follow this schema:
84+
85+
```javascript
86+
{
87+
id: "MESSAGE_ID",
88+
template: "newtab_message",
89+
content: {
90+
messageType: "ActivationWindowMessage",
91+
92+
// Heading: plain string or Fluent ID
93+
heading: "Welcome to Your New Tab!",
94+
// OR
95+
heading: { string_id: "activation-window-welcome-heading-fluent-id" },
96+
97+
// Message: plain string or Fluent ID
98+
message: "We've personalized your experience...",
99+
// OR
100+
message: { string_id: "activation-window-welcome-message-fluent-id" },
101+
102+
// Image (optional, defaults to kit-in-circle.svg if not provided)
103+
imageSrc: "chrome://newtab/content/data/content/assets/kit.png",
104+
105+
primaryButton: {
106+
// Plain text label (for tests)
107+
label: "Learn More",
108+
// OR Fluent ID label (for production)
109+
label: { string_id: "activation-window-primary-button-fluent-id" },
110+
111+
action: {
112+
type: "SHOW_PERSONALIZE"
113+
}
114+
},
115+
116+
secondaryButton: {
117+
label: "Dismiss",
118+
// OR
119+
label: { string_id: "activation-window-secondary-button-fluent-id" },
120+
121+
action: { dismiss: true }
122+
}
123+
},
124+
trigger: { id: "newtabMessageCheck" },
125+
targeting: `'browser.newtabpage.activity-stream.activationWindow.enterMessageID' | preferenceValue == 'MESSAGE_ID'`,
126+
groups: []
127+
}
128+
```
129+
130+
#### Message Content Fields
131+
132+
- **`messageType`** (string, required): Must be `"ActivationWindowMessage"`
133+
- **`heading`** (string or object, optional): Heading text
134+
- Plain string: `"Welcome to Firefox"`
135+
- Fluent ID: `{ string_id: "activation-window-heading-fluent-id" }`
136+
- **`message`** (string or object, optional): Message text
137+
- Plain string: `"We've personalized your experience"`
138+
- Fluent ID: `{ string_id: "activation-window-message-fluent-id" }`
139+
- **`imageSrc`** (string, optional): Chrome URL to image displayed in the message. If not provided, defaults to `"chrome://newtab/content/data/content/assets/kit-in-circle.svg"`
140+
- **`primaryButton`** (object, optional): Configuration for primary button.
141+
- **`secondaryButton`** (object, optional): Configuration for secondary button
142+
143+
#### Button Configuration
144+
145+
Each button object has:
146+
147+
- **`label`** (string or object, required):
148+
- Plain string for test messages: `"Click Me"`
149+
- Fluent object for production: `{ string_id: "button-label-id-fluent-id" }`
150+
- **`action`** (object, required): ASRouter action specification
151+
- `{ dismiss: true }` - Dismiss and block the message
152+
- `{ type: "SHOW_PERSONALIZE" }` - Open personalization panel
153+
- More actions may be added in the future.
154+
155+
## Testing Locally
156+
157+
### Using PanelTestProvider
158+
159+
Test messages are available in `browser/components/asrouter/modules/PanelTestProvider.sys.mjs`:
160+
161+
- `TEST_ACTIVATION_WINDOW_ENTER_MESSAGE`
162+
- `TEST_ACTIVATION_WINDOW_EXIT_MESSAGE`
163+
164+
To test these messages:
165+
166+
1. Open `about:newtab#asrouter` in Firefox
167+
2. Find either the enter or exit message in the message list
168+
3. Modify any of the parameters in the message as you'd like
169+
4. Click "Show" or "Modify" to display the message
170+
5. Open a new tab

0 commit comments

Comments
 (0)