Bug 1938426: Record telemetry event when saving a tab group r=dwalker,tabbrowser-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D242984
This commit is contained in:
Jeremy Swinarton
2025-03-27 15:29:19 +00:00
parent f43005e0ba
commit 34d9e59418
9 changed files with 114 additions and 22 deletions

View File

@@ -2960,7 +2960,7 @@
* An optional argument that accepts a single tab, which, if passed, will
* cause the group to be inserted just before this tab in the tab strip. By
* default, the group will be created at the end of the tab strip.
* @param {boolean} [options.isUserCreated]
* @param {boolean} [options.isUserTriggered]
* Should be true if this group is being created in response to an
* explicit request from the user (as opposed to a group being created
* for technical reasons, such as when an already existing group
@@ -2976,7 +2976,7 @@
color = null,
label = "",
insertBefore = null,
isUserCreated = false,
isUserTriggered = false,
telemetryUserCreateSource = "unknown",
} = {}
) {
@@ -3009,7 +3009,7 @@
new CustomEvent("TabGroupCreate", {
bubbles: true,
detail: {
isUserCreated,
isUserTriggered,
telemetryUserCreateSource,
},
})
@@ -6879,7 +6879,7 @@
break;
}
case "TabGroupCreate":
if (aEvent.detail.isUserCreated) {
if (aEvent.detail.isUserTriggered) {
this.tabGroupMenu.openCreateModal(aEvent.target);
}
break;
@@ -9014,7 +9014,7 @@ var TabContextMenu = {
moveTabsToNewGroup() {
gBrowser.addTabGroup(this.contextTabs, {
insertBefore: this.contextTab,
isUserCreated: true,
isUserTriggered: true,
telemetryUserCreateSource: "tab_menu",
});

View File

@@ -90,7 +90,7 @@
data-l10n-id="tab-group-editor-action-ungroup">
</toolbarbutton>
</html:div>
<toolbarseparator class="tab-group-edit-mode-only" />
<html:div class="tab-group-edit-mode-only panel-body tab-group-delete">
@@ -234,9 +234,9 @@
/>
<toolbarseparator class="tab-group-edit-mode-only"/>
${this.editActions}
<toolbarseparator id="tab-group-suggestions-separator" hidden="true"/>
${this.suggestionsButton}
@@ -254,7 +254,7 @@
</html:div>
${this.defaultActions}
</html:div>
${this.loadingSection}
@@ -435,7 +435,7 @@
document
.getElementById("tabGroupEditor_saveAndCloseGroup")
.addEventListener("command", () => {
this.activeGroup.saveAndClose();
this.activeGroup.saveAndClose({ isUserTriggered: true });
});
document

View File

@@ -262,14 +262,24 @@
/**
* Save group data to session store.
*
* @param {object} [options]
* @param {boolean} [options.isUserTriggered]
* Whether or not the save operation was explicitly called by the user.
* Used for telemetry. Default is false.
*/
save() {
save({ isUserTriggered = false } = {}) {
SessionStore.addSavedTabGroup(this);
this.dispatchEvent(new CustomEvent("TabGroupSaved", { bubbles: true }));
this.dispatchEvent(
new CustomEvent("TabGroupSaved", {
bubbles: true,
detail: { isUserTriggered },
})
);
}
saveAndClose() {
this.save();
saveAndClose({ isUserTriggered } = {}) {
this.save({ isUserTriggered });
gBrowser.removeTabGroup(this);
}

View File

@@ -1246,7 +1246,7 @@
: [dropElement, ...movingTabs];
gBrowser.addTabGroup(tabsInGroup, {
insertBefore: dropElement,
isUserCreated: true,
isUserTriggered: true,
color: draggedTab._dragData.tabGroupCreationColor,
telemetryUserCreateSource: "drag",
});

View File

@@ -210,6 +210,29 @@ tabgroup:
- inside
- outside
save:
type: event
description: >
Recorded when the user saves a tab group
notification_emails:
- dao@mozilla.com
- jswinarton@mozilla.com
bugs:
- https://bugzil.la/1938426
data_reviews:
- https://bugzil.la/1938426
expires: never
extra_keys:
user_triggered:
description: >
Whether the user explicitly chose to save the tab group, or the group
was automatically saved as a result of browser operations (e.g. the
user closed a window that has open tab groups).
type: boolean
id:
description: The ID of the saved tab group
type: string
smart_tab_optin:
type: event
description: >

View File

@@ -10,7 +10,7 @@ async function openCreatePanel(tabgroupPanel, tab) {
let panelShown = BrowserTestUtils.waitForPopupEvent(tabgroupPanel, "shown");
gBrowser.addTabGroup([tab], {
color: "cyan",
isUserCreated: true,
isUserTriggered: true,
});
await panelShown;
}

View File

@@ -1673,7 +1673,7 @@ add_task(async function test_tabGroupCreatePanel() {
group = gBrowser.addTabGroup([tab], {
color: "cyan",
label: "Food",
isUserCreated: true,
isUserTriggered: true,
});
await panelShown;
};

View File

@@ -16,7 +16,7 @@ add_task(async function test_tabGroupTelemetry() {
await BrowserTestUtils.browserLoaded(group1tab.linkedBrowser);
let group1 = gBrowser.addTabGroup([group1tab], {
isUserCreated: true,
isUserTriggered: true,
telemetryUserCreateSource: "test-source",
});
gBrowser.tabGroupMenu.close();
@@ -84,7 +84,7 @@ add_task(async function test_tabGroupTelemetry() {
);
let group2 = gBrowser.addTabGroup(group2Tabs, {
isUserCreated: true,
isUserTriggered: true,
telemetryUserCreateSource: "test-source",
});
gBrowser.tabGroupMenu.close();
@@ -196,3 +196,49 @@ add_task(async function test_tabGroupTelemetry() {
await removeTabGroup(group1);
await removeTabGroup(group2);
});
add_task(async function test_tabGroupTelemetrySaveGroup() {
let tabGroupSaveTelemetry;
await resetTelemetry();
let group1tab = BrowserTestUtils.addTab(gBrowser, "https://example.com");
await BrowserTestUtils.browserLoaded(group1tab.linkedBrowser);
let group1 = gBrowser.addTabGroup([group1tab]);
group1.saveAndClose();
await BrowserTestUtils.waitForCondition(() => {
tabGroupSaveTelemetry = Glean.tabgroup.save.testGetValue();
return tabGroupSaveTelemetry?.length == 1;
}, "Wait for tabgroup.save event after tab group save");
Assert.deepEqual(
tabGroupSaveTelemetry[0].extra,
{
user_triggered: "false",
id: group1.id,
},
"tabgroup.save event extra_keys has correct values after tab group save"
);
await resetTelemetry();
let group2tab = BrowserTestUtils.addTab(gBrowser, "https://example.com");
await BrowserTestUtils.browserLoaded(group2tab.linkedBrowser);
let group2 = gBrowser.addTabGroup([group2tab]);
group2.saveAndClose({ isUserTriggered: true });
await BrowserTestUtils.waitForCondition(() => {
tabGroupSaveTelemetry = Glean.tabgroup.save.testGetValue();
return tabGroupSaveTelemetry?.length == 1;
}, "Wait for tabgroup.save event after tab group save with explicit user event");
Assert.deepEqual(
tabGroupSaveTelemetry[0].extra,
{
user_triggered: "true",
id: group2.id,
},
"tabgroup.save event extra_keys has correct values after tab group save by explicit user event"
);
});

View File

@@ -597,6 +597,9 @@ export let BrowserUsageTelemetry = {
case "TabGroupExpand":
this._onTabGroupExpandOrCollapse();
break;
case "TabGroupSaved":
this._onTabGroupSave(event);
break;
case "unload":
this._unregisterWindow(event.target);
break;
@@ -1149,6 +1152,7 @@ export let BrowserUsageTelemetry = {
win.addEventListener("TabUngrouped", this);
win.addEventListener("TabGroupCollapse", this);
win.addEventListener("TabGroupExpand", this);
win.addEventListener("TabGroupSaved", this);
win.gBrowser.tabContainer.addEventListener(TAB_RESTORING_TOPIC, this);
win.gBrowser.addTabsProgressListener(URICountListener);
@@ -1167,6 +1171,7 @@ export let BrowserUsageTelemetry = {
win.removeEventListener("TabUngrouped", this);
win.removeEventListener("TabGroupCollapse", this);
win.removeEventListener("TabGroupExpand", this);
win.removeEventListener("TabGroupSaved", this);
win.defaultView.gBrowser.tabContainer.removeEventListener(
TAB_RESTORING_TOPIC,
@@ -1218,7 +1223,7 @@ export let BrowserUsageTelemetry = {
},
_onTabGroupCreate(event) {
if (event.detail.isUserCreated) {
if (event.detail.isUserTriggered) {
Glean.tabgroup.createGroup.record({
id: event.target.id,
layout: lazy.sidebarVerticalTabs ? "vertical" : "horizontal",
@@ -1227,8 +1232,16 @@ export let BrowserUsageTelemetry = {
});
}
this._onTabGroupChangeTask.disarm();
this._onTabGroupChangeTask.arm();
this._onTabGroupChange();
},
_onTabGroupSave(event) {
Glean.tabgroup.save.record({
user_triggered: event.detail.isUserTriggered,
id: event.target.id,
});
this._onTabGroupChange();
},
_onTabGroupChange() {