Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 1e0e341

Browse files
committed
Bug 1975403 - Telemetry for containers, r=tabbrowser-reviewers,chutten,sthompson
Differential Revision: https://phabricator.services.mozilla.com/D255934
1 parent 05f8ee9 commit 1e0e341

9 files changed

Lines changed: 407 additions & 0 deletions

File tree

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# This Source Code Form is subject to the terms of the Mozilla Public
2+
# License, v. 2.0. If a copy of the MPL was not distributed with this
3+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
# Adding a new metric? We have docs for that!
6+
# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html
7+
8+
---
9+
$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
10+
$tags:
11+
- 'Core :: DOM: Security'
12+
13+
containers:
14+
containers_enabled:
15+
type: event
16+
description: >
17+
Recorded when the container feature is enabled or disabled (pref privacy.userContext.enabled).
18+
bugs:
19+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
20+
data_reviews:
21+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
22+
notification_emails:
23+
- amarchesini@mozilla.com
24+
expires: never
25+
data_sensitivity:
26+
- interaction
27+
extra_keys:
28+
enabled:
29+
description: |
30+
True if the feature is enabled.
31+
type: boolean
32+
33+
container_profile_loaded:
34+
type: event
35+
description: >
36+
Recorded when the user profile is loaded and container definitions are read.
37+
bugs:
38+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
39+
data_reviews:
40+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
41+
notification_emails:
42+
- amarchesini@mozilla.com
43+
expires: never
44+
data_sensitivity:
45+
- interaction
46+
extra_keys:
47+
containers:
48+
description: |
49+
The number of container configurations read from the user profile.
50+
type: quantity
51+
52+
container_tab_opened:
53+
type: event
54+
description: >
55+
Recorded when a container tab is opened.
56+
bugs:
57+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
58+
data_reviews:
59+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
60+
notification_emails:
61+
- amarchesini@mozilla.com
62+
expires: never
63+
data_sensitivity:
64+
- interaction
65+
extra_keys:
66+
container_id:
67+
description: The ID of the container.
68+
type: string
69+
70+
container_tab_closed:
71+
type: event
72+
description: >
73+
Recorded when a container tab is closed.
74+
bugs:
75+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
76+
data_reviews:
77+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
78+
notification_emails:
79+
- amarchesini@mozilla.com
80+
expires: never
81+
data_sensitivity:
82+
- interaction
83+
extra_keys:
84+
container_id:
85+
description: The ID of the closed container.
86+
type: string
87+
88+
tab_assigned_container:
89+
type: event
90+
description: >
91+
Recorded when a tab is moved into a container.
92+
bugs:
93+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
94+
data_reviews:
95+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
96+
notification_emails:
97+
- amarchesini@mozilla.com
98+
expires: never
99+
data_sensitivity:
100+
- interaction
101+
extra_keys:
102+
from_container_id:
103+
description: The source container id, or "0" if the tab wasn't in a container
104+
type: string
105+
to_container_id:
106+
description: The destination container id, or "0" if the tab wasn't in a container
107+
type: string
108+
109+
container_created:
110+
type: event
111+
description: >
112+
Recorded when a user creates a new container.
113+
bugs:
114+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
115+
data_reviews:
116+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
117+
notification_emails:
118+
- amarchesini@mozilla.com
119+
expires: never
120+
data_sensitivity:
121+
- interaction
122+
extra_keys:
123+
container_id:
124+
description: The ID of the newly created container.
125+
type: string
126+
127+
container_modified:
128+
type: event
129+
description: >
130+
Recorded when a user edits a container (e.g. changes name, icon, or color).
131+
bugs:
132+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
133+
data_reviews:
134+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
135+
notification_emails:
136+
- amarchesini@mozilla.com
137+
expires: never
138+
data_sensitivity:
139+
- interaction
140+
extra_keys:
141+
container_id:
142+
description: The ID of the modified container.
143+
type: string
144+
145+
container_deleted:
146+
type: event
147+
description: >
148+
Recorded when a user deletes a container.
149+
bugs:
150+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
151+
data_reviews:
152+
- https://bugzilla.mozilla.org/show_bug.cgi?id=1975403
153+
notification_emails:
154+
- containers-telemetry@mozilla.com
155+
expires: never
156+
data_sensitivity:
157+
- interaction
158+
extra_keys:
159+
container_id:
160+
description: The ID of the deleted container.
161+
type: string

browser/components/contextualidentity/test/browser/browser.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ support-files = [
7878

7979
["browser_tab_color_update.js"]
8080

81+
["browser_telemetry.js"]
82+
https_first_disabled = true
83+
skip-if = [
84+
"os == 'mac' && os_version == '11.20' && arch == 'aarch64'", # Bug 1783491
85+
"os == 'mac' && os_version == '15.30' && arch == 'aarch64'", # Bug 1783491
86+
]
87+
8188
["browser_usercontext.js"]
8289

8390
["browser_usercontextid_new_window.js"]
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
*/
5+
6+
"use strict";
7+
8+
const TEST_HOST = "example.com";
9+
10+
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
11+
const TEST_URL = "http://" + TEST_HOST;
12+
13+
const TEST_URL_FULL =
14+
TEST_URL + "/browser/browser/components/contextualidentity/test/browser/";
15+
16+
async function openTabMenuFor(tab) {
17+
let tabMenu = tab.ownerDocument.getElementById("tabContextMenu");
18+
19+
let tabMenuShown = BrowserTestUtils.waitForEvent(tabMenu, "popupshown");
20+
EventUtils.synthesizeMouseAtCenter(
21+
tab,
22+
{ type: "contextmenu" },
23+
tab.ownerGlobal
24+
);
25+
await tabMenuShown;
26+
27+
return tabMenu;
28+
}
29+
30+
async function openReopenMenuForTab(tab) {
31+
await openTabMenuFor(tab);
32+
33+
let reopenItem = tab.ownerDocument.getElementById(
34+
"context_reopenInContainer"
35+
);
36+
ok(!reopenItem.hidden, "Reopen in Container item should be shown");
37+
38+
let reopenMenu = reopenItem.getElementsByTagName("menupopup")[0];
39+
let reopenMenuShown = BrowserTestUtils.waitForEvent(reopenMenu, "popupshown");
40+
reopenItem.openMenu(true);
41+
await reopenMenuShown;
42+
43+
return reopenMenu;
44+
}
45+
46+
function openTabInContainer(gBrowser, reopenMenu, id) {
47+
let tabPromise = BrowserTestUtils.waitForNewTab(
48+
gBrowser,
49+
TEST_URL_FULL,
50+
true
51+
);
52+
let menuitem = reopenMenu.querySelector(
53+
`menuitem[data-usercontextid="${id}"]`
54+
);
55+
reopenMenu.activateItem(menuitem);
56+
return tabPromise;
57+
}
58+
59+
add_task(async function testTelemetry() {
60+
Services.telemetry.clearEvents();
61+
Services.fog.testResetFOG();
62+
63+
const userContextId = 1;
64+
65+
await SpecialPowers.pushPrefEnv({
66+
set: [["privacy.userContext.enabled", true]],
67+
});
68+
69+
const tab = BrowserTestUtils.addTab(gBrowser, TEST_URL_FULL, {
70+
userContextId,
71+
});
72+
await BrowserTestUtils.browserLoaded(gBrowser.getBrowserForTab(tab));
73+
74+
let tabOpenedEvent = Glean.containers.containerTabOpened.testGetValue();
75+
Assert.ok(Array.isArray(tabOpenedEvent), "container_tab_opened must exist");
76+
Assert.equal(tabOpenedEvent.length, 1);
77+
Assert.equal(tabOpenedEvent[0].extra.container_id, 1);
78+
79+
const reopenMenu = await openReopenMenuForTab(tab);
80+
const tab2 = await openTabInContainer(gBrowser, reopenMenu, "2");
81+
82+
tabOpenedEvent = Glean.containers.containerTabOpened.testGetValue();
83+
Assert.ok(Array.isArray(tabOpenedEvent), "container_tab_opened must exist");
84+
Assert.equal(tabOpenedEvent.length, 2);
85+
Assert.equal(tabOpenedEvent[0].extra.container_id, 1);
86+
Assert.equal(tabOpenedEvent[1].extra.container_id, 2);
87+
88+
const tabAssignedEvent = Glean.containers.tabAssignedContainer.testGetValue();
89+
Assert.ok(Array.isArray(tabAssignedEvent), "tab_assigned_container exists");
90+
Assert.equal(tabAssignedEvent.length, 1);
91+
Assert.equal(tabAssignedEvent[0].extra.from_container_id, 1);
92+
Assert.equal(tabAssignedEvent[0].extra.to_container_id, 2);
93+
94+
BrowserTestUtils.removeTab(tab);
95+
96+
let tabClosedEvent = Glean.containers.containerTabClosed.testGetValue();
97+
Assert.ok(Array.isArray(tabClosedEvent), "container_tab_closed must exist");
98+
Assert.equal(tabClosedEvent.length, 1);
99+
Assert.equal(tabClosedEvent[0].extra.container_id, 1);
100+
101+
BrowserTestUtils.removeTab(tab2);
102+
103+
tabClosedEvent = Glean.containers.containerTabClosed.testGetValue();
104+
Assert.ok(Array.isArray(tabClosedEvent), "container_tab_closed must exist");
105+
Assert.equal(tabClosedEvent.length, 2);
106+
Assert.equal(tabClosedEvent[0].extra.container_id, 1);
107+
Assert.equal(tabClosedEvent[1].extra.container_id, 2);
108+
});

browser/components/tabbrowser/content/tabbrowser.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9448,6 +9448,11 @@ var TabContextMenu = {
94489448
triggeringPrincipal,
94499449
});
94509450

9451+
Glean.containers.tabAssignedContainer.record({
9452+
from_container_id: tab.getAttribute("usercontextid"),
9453+
to_container_id: userContextId,
9454+
});
9455+
94519456
if (gBrowser.selectedTab == tab) {
94529457
gBrowser.selectedTab = newTab;
94539458
}

browser/modules/BrowserUsageTelemetry.sys.mjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,13 @@ export let BrowserUsageTelemetry = {
12631263
Glean.tabgroup.tabInteractions.new.add();
12641264
}
12651265

1266+
const userContextId = event?.target?.getAttribute("usercontextid");
1267+
if (userContextId) {
1268+
Glean.containers.containerTabOpened.record({
1269+
container_id: String(userContextId),
1270+
});
1271+
}
1272+
12661273
// In the case of opening multiple tabs at once, avoid enumerating all open
12671274
// tabs and windows each time a tab opens.
12681275
this._onTabsOpenedTask.disarm();
@@ -1297,6 +1304,13 @@ export let BrowserUsageTelemetry = {
12971304
}
12981305
}
12991306

1307+
const userContextId = event?.target?.getAttribute("usercontextid");
1308+
if (userContextId) {
1309+
Glean.containers.containerTabClosed.record({
1310+
container_id: String(userContextId),
1311+
});
1312+
}
1313+
13001314
if (event.target?.pinned) {
13011315
const pinnedTabs = getPinnedTabsCount();
13021316
this.recordPinnedTabsCount(pinnedTabs - 1);

toolkit/components/contextualidentity/ContextualIdentityService.sys.mjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ _ContextualIdentityService.prototype = {
159159
this.notifyAllContainersCleared();
160160
this.resetDefault();
161161
}
162+
163+
Glean.containers.containersEnabled.record({
164+
enabled: contextualIdentitiesEnabled,
165+
});
162166
}
163167
},
164168

@@ -180,6 +184,11 @@ _ContextualIdentityService.prototype = {
180184
this.loadError(error);
181185
}
182186
);
187+
188+
Glean.containers.containerProfileLoaded.record({
189+
containers: this.getPublicUserContextIds().length,
190+
});
191+
183192
Services.obs.notifyObservers(
184193
null,
185194
"contextual-identity-service-load-finished"
@@ -297,6 +306,10 @@ _ContextualIdentityService.prototype = {
297306
"contextual-identity-created"
298307
);
299308

309+
Glean.containers.containerCreated.record({
310+
container_id: userContextId.toString(),
311+
});
312+
300313
return Cu.cloneInto(identity, {});
301314
},
302315

@@ -326,6 +339,10 @@ _ContextualIdentityService.prototype = {
326339
);
327340
}
328341

342+
Glean.containers.containerModified.record({
343+
container_id: userContextId.toString(),
344+
});
345+
329346
return !!identity;
330347
},
331348

@@ -381,6 +398,10 @@ _ContextualIdentityService.prototype = {
381398
this.saveSoon();
382399
Services.obs.notifyObservers(deletedOutput, "contextual-identity-deleted");
383400

401+
Glean.containers.containerDeleted.record({
402+
container_id: userContextId.toString(),
403+
});
404+
384405
return true;
385406
},
386407

0 commit comments

Comments
 (0)