Bug 1961161: Additional metrics for closing tabs within groups r=dwalker,fxview-reviewers,tabbrowser-reviewers,nsharpley
Differential Revision: https://phabricator.services.mozilla.com/D248438
This commit is contained in:
committed by
jswinarton@mozilla.com
parent
44151f9298
commit
1f70d01002
@@ -396,7 +396,9 @@ var BrowserCommands = {
|
|||||||
|
|
||||||
// In a multi-select context, close all selected tabs
|
// In a multi-select context, close all selected tabs
|
||||||
if (gBrowser.multiSelectedTabsCount) {
|
if (gBrowser.multiSelectedTabsCount) {
|
||||||
gBrowser.removeMultiSelectedTabs();
|
gBrowser.removeMultiSelectedTabs(
|
||||||
|
gBrowser.TabMetrics.userTriggeredContext()
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +416,10 @@ var BrowserCommands = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the current tab is the last one, this will close the window.
|
// If the current tab is the last one, this will close the window.
|
||||||
gBrowser.removeCurrentTab({ animate: true });
|
gBrowser.removeCurrentTab({
|
||||||
|
animate: true,
|
||||||
|
...gBrowser.TabMetrics.userTriggeredContext(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
tryToCloseWindow(event) {
|
tryToCloseWindow(event) {
|
||||||
|
|||||||
@@ -88,16 +88,28 @@ document.addEventListener(
|
|||||||
TabContextMenu.closeContextTabs();
|
TabContextMenu.closeContextTabs();
|
||||||
break;
|
break;
|
||||||
case "context_closeDuplicateTabs":
|
case "context_closeDuplicateTabs":
|
||||||
gBrowser.removeDuplicateTabs(TabContextMenu.contextTab);
|
gBrowser.removeDuplicateTabs(
|
||||||
|
TabContextMenu.contextTab,
|
||||||
|
lazy.TabMetrics.userTriggeredContext()
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "context_closeTabsToTheStart":
|
case "context_closeTabsToTheStart":
|
||||||
gBrowser.removeTabsToTheStartFrom(TabContextMenu.contextTab);
|
gBrowser.removeTabsToTheStartFrom(
|
||||||
|
TabContextMenu.contextTab,
|
||||||
|
lazy.TabMetrics.userTriggeredContext()
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "context_closeTabsToTheEnd":
|
case "context_closeTabsToTheEnd":
|
||||||
gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab);
|
gBrowser.removeTabsToTheEndFrom(
|
||||||
|
TabContextMenu.contextTab,
|
||||||
|
lazy.TabMetrics.userTriggeredContext()
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "context_closeOtherTabs":
|
case "context_closeOtherTabs":
|
||||||
gBrowser.removeAllTabsBut(TabContextMenu.contextTab);
|
gBrowser.removeAllTabsBut(
|
||||||
|
TabContextMenu.contextTab,
|
||||||
|
lazy.TabMetrics.userTriggeredContext()
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "context_unloadTab":
|
case "context_unloadTab":
|
||||||
TabContextMenu.explicitUnloadTabs();
|
TabContextMenu.explicitUnloadTabs();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||||||
NonPrivateTabs: "resource:///modules/OpenTabs.sys.mjs",
|
NonPrivateTabs: "resource:///modules/OpenTabs.sys.mjs",
|
||||||
getTabsTargetForWindow: "resource:///modules/OpenTabs.sys.mjs",
|
getTabsTargetForWindow: "resource:///modules/OpenTabs.sys.mjs",
|
||||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
||||||
|
TabMetrics: "moz-src:///browser/components/tabbrowser/TabMetrics.sys.mjs",
|
||||||
});
|
});
|
||||||
|
|
||||||
ChromeUtils.defineLazyGetter(lazy, "fxAccounts", () => {
|
ChromeUtils.defineLazyGetter(lazy, "fxAccounts", () => {
|
||||||
@@ -503,7 +504,10 @@ class OpenTabsInViewCard extends ViewPageContent {
|
|||||||
|
|
||||||
closeTab(event) {
|
closeTab(event) {
|
||||||
const tab = event.originalTarget.tabElement;
|
const tab = event.originalTarget.tabElement;
|
||||||
tab?.ownerGlobal.gBrowser.removeTab(tab);
|
tab?.ownerGlobal.gBrowser.removeTab(
|
||||||
|
tab,
|
||||||
|
lazy.TabMetrics.userTriggeredContext()
|
||||||
|
);
|
||||||
|
|
||||||
Glean.firefoxviewNext.closeOpenTabTabs.record();
|
Glean.firefoxviewNext.closeOpenTabTabs.record();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ const METRIC_REOPEN_TYPE = Object.freeze({
|
|||||||
* @returns {TabMetricsContext}
|
* @returns {TabMetricsContext}
|
||||||
*/
|
*/
|
||||||
function userTriggeredContext(telemetrySource) {
|
function userTriggeredContext(telemetrySource) {
|
||||||
|
telemetrySource = telemetrySource || METRIC_SOURCE.UNKNOWN;
|
||||||
return {
|
return {
|
||||||
isUserTriggered: true,
|
isUserTriggered: true,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
|
|||||||
@@ -324,9 +324,12 @@ export class TabsPanel extends TabsListBase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (event.target.classList.contains("all-tabs-close-button")) {
|
if (event.target.classList.contains("all-tabs-close-button")) {
|
||||||
this.gBrowser.removeTab(event.target.tab, {
|
this.gBrowser.removeTab(
|
||||||
telemetrySource: lazy.TabMetrics.METRIC_SOURCE.TAB_OVERFLOW_MENU,
|
event.target.tab,
|
||||||
});
|
lazy.TabMetrics.userTriggeredContext(
|
||||||
|
lazy.TabMetrics.METRIC_SOURCE.TAB_OVERFLOW_MENU
|
||||||
|
)
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ("tabGroupId" in event.target.dataset) {
|
if ("tabGroupId" in event.target.dataset) {
|
||||||
|
|||||||
@@ -555,14 +555,18 @@
|
|||||||
|
|
||||||
if (event.target.classList.contains("tab-close-button")) {
|
if (event.target.classList.contains("tab-close-button")) {
|
||||||
if (this.multiselected) {
|
if (this.multiselected) {
|
||||||
gBrowser.removeMultiSelectedTabs({
|
gBrowser.removeMultiSelectedTabs(
|
||||||
telemetrySource: lazy.TabMetrics.METRIC_SOURCE.TAB_STRIP,
|
lazy.TabMetrics.userTriggeredContext(
|
||||||
});
|
lazy.TabMetrics.METRIC_SOURCE.TAB_STRIP
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
gBrowser.removeTab(this, {
|
gBrowser.removeTab(this, {
|
||||||
animate: true,
|
animate: true,
|
||||||
triggeringEvent: event,
|
triggeringEvent: event,
|
||||||
telemetrySource: lazy.TabMetrics.METRIC_SOURCE.TAB_STRIP,
|
...lazy.TabMetrics.userTriggeredContext(
|
||||||
|
lazy.TabMetrics.METRIC_SOURCE.TAB_STRIP
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// This enables double-click protection for the tab container
|
// This enables double-click protection for the tab container
|
||||||
|
|||||||
@@ -4139,15 +4139,16 @@
|
|||||||
return duplicateTabs;
|
return duplicateTabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
removeDuplicateTabs(aTab) {
|
removeDuplicateTabs(aTab, options) {
|
||||||
this._removeDuplicateTabs(
|
this._removeDuplicateTabs(
|
||||||
aTab,
|
aTab,
|
||||||
this.getDuplicateTabsToClose(aTab),
|
this.getDuplicateTabsToClose(aTab),
|
||||||
this.closingTabsEnum.DUPLICATES
|
this.closingTabsEnum.DUPLICATES,
|
||||||
|
options
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeDuplicateTabs(aConfirmationAnchor, tabs, aCloseTabs) {
|
_removeDuplicateTabs(aConfirmationAnchor, tabs, aCloseTabs, options) {
|
||||||
if (!tabs.length) {
|
if (!tabs.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4156,7 +4157,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removeTabs(tabs);
|
this.removeTabs(tabs, options);
|
||||||
ConfirmationHint.show(
|
ConfirmationHint.show(
|
||||||
aConfirmationAnchor,
|
aConfirmationAnchor,
|
||||||
"confirmation-hint-duplicate-tabs-closed",
|
"confirmation-hint-duplicate-tabs-closed",
|
||||||
@@ -4179,7 +4180,7 @@
|
|||||||
* In a multi-select context, the tabs (except pinned tabs) that are located to the
|
* In a multi-select context, the tabs (except pinned tabs) that are located to the
|
||||||
* left of the leftmost selected tab will be removed.
|
* left of the leftmost selected tab will be removed.
|
||||||
*/
|
*/
|
||||||
removeTabsToTheStartFrom(aTab) {
|
removeTabsToTheStartFrom(aTab, options) {
|
||||||
let tabs = this._getTabsToTheStartFrom(aTab);
|
let tabs = this._getTabsToTheStartFrom(aTab);
|
||||||
if (
|
if (
|
||||||
!this.warnAboutClosingTabs(tabs.length, this.closingTabsEnum.TO_START)
|
!this.warnAboutClosingTabs(tabs.length, this.closingTabsEnum.TO_START)
|
||||||
@@ -4187,14 +4188,14 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removeTabs(tabs);
|
this.removeTabs(tabs, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In a multi-select context, the tabs (except pinned tabs) that are located to the
|
* In a multi-select context, the tabs (except pinned tabs) that are located to the
|
||||||
* right of the rightmost selected tab will be removed.
|
* right of the rightmost selected tab will be removed.
|
||||||
*/
|
*/
|
||||||
removeTabsToTheEndFrom(aTab) {
|
removeTabsToTheEndFrom(aTab, options) {
|
||||||
let tabs = this._getTabsToTheEndFrom(aTab);
|
let tabs = this._getTabsToTheEndFrom(aTab);
|
||||||
if (
|
if (
|
||||||
!this.warnAboutClosingTabs(tabs.length, this.closingTabsEnum.TO_END)
|
!this.warnAboutClosingTabs(tabs.length, this.closingTabsEnum.TO_END)
|
||||||
@@ -4202,7 +4203,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removeTabs(tabs);
|
this.removeTabs(tabs, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4258,7 +4259,7 @@
|
|||||||
this.removeTabs(tabsToRemove, aParams);
|
this.removeTabs(tabsToRemove, aParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMultiSelectedTabs({ telemetrySource } = {}) {
|
removeMultiSelectedTabs({ isUserTriggered, telemetrySource } = {}) {
|
||||||
let selectedTabs = this.selectedTabs;
|
let selectedTabs = this.selectedTabs;
|
||||||
if (
|
if (
|
||||||
!this.warnAboutClosingTabs(
|
!this.warnAboutClosingTabs(
|
||||||
@@ -4269,7 +4270,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removeTabs(selectedTabs, { telemetrySource });
|
this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4313,6 +4314,7 @@
|
|||||||
skipPermitUnload,
|
skipPermitUnload,
|
||||||
skipRemoves,
|
skipRemoves,
|
||||||
skipSessionStore,
|
skipSessionStore,
|
||||||
|
isUserTriggered,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
@@ -4396,6 +4398,7 @@
|
|||||||
prewarmed: true,
|
prewarmed: true,
|
||||||
skipPermitUnload,
|
skipPermitUnload,
|
||||||
skipSessionStore,
|
skipSessionStore,
|
||||||
|
isUserTriggered,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -4509,6 +4512,7 @@
|
|||||||
* @param {boolean} [options.skipGroupCheck]
|
* @param {boolean} [options.skipGroupCheck]
|
||||||
* Skip separate processing of whole tab groups from the set of tabs.
|
* Skip separate processing of whole tab groups from the set of tabs.
|
||||||
* Used by removeTabGroup.
|
* Used by removeTabGroup.
|
||||||
|
* TODO add docs
|
||||||
*/
|
*/
|
||||||
removeTabs(
|
removeTabs(
|
||||||
tabs,
|
tabs,
|
||||||
@@ -4518,6 +4522,7 @@
|
|||||||
skipPermitUnload = false,
|
skipPermitUnload = false,
|
||||||
skipSessionStore = false,
|
skipSessionStore = false,
|
||||||
skipGroupCheck = false,
|
skipGroupCheck = false,
|
||||||
|
isUserTriggered = false,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
} = {}
|
} = {}
|
||||||
) {
|
) {
|
||||||
@@ -4553,6 +4558,8 @@
|
|||||||
animate,
|
animate,
|
||||||
skipSessionStore,
|
skipSessionStore,
|
||||||
skipPermitUnload,
|
skipPermitUnload,
|
||||||
|
isUserTriggered,
|
||||||
|
telemetrySource,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
tabs = leftoverTabs;
|
tabs = leftoverTabs;
|
||||||
@@ -4565,6 +4572,7 @@
|
|||||||
skipPermitUnload,
|
skipPermitUnload,
|
||||||
skipRemoves: false,
|
skipRemoves: false,
|
||||||
skipSessionStore,
|
skipSessionStore,
|
||||||
|
isUserTriggered,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -4589,6 +4597,8 @@
|
|||||||
prewarmed: true,
|
prewarmed: true,
|
||||||
skipPermitUnload,
|
skipPermitUnload,
|
||||||
skipSessionStore,
|
skipSessionStore,
|
||||||
|
isUserTriggered,
|
||||||
|
telemetrySource,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Now run again sequentially the beforeunload listeners that will result in a prompt.
|
// Now run again sequentially the beforeunload listeners that will result in a prompt.
|
||||||
@@ -4626,6 +4636,7 @@
|
|||||||
closeWindowWithLastTab,
|
closeWindowWithLastTab,
|
||||||
prewarmed,
|
prewarmed,
|
||||||
skipSessionStore,
|
skipSessionStore,
|
||||||
|
isUserTriggered,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
} = {}
|
} = {}
|
||||||
) {
|
) {
|
||||||
@@ -4664,6 +4675,7 @@
|
|||||||
closeWindowWithLastTab,
|
closeWindowWithLastTab,
|
||||||
prewarmed,
|
prewarmed,
|
||||||
skipSessionStore,
|
skipSessionStore,
|
||||||
|
isUserTriggered,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
@@ -4752,6 +4764,7 @@
|
|||||||
skipPermitUnload,
|
skipPermitUnload,
|
||||||
prewarmed,
|
prewarmed,
|
||||||
skipSessionStore = false,
|
skipSessionStore = false,
|
||||||
|
isUserTriggered,
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
} = {}
|
} = {}
|
||||||
) {
|
) {
|
||||||
@@ -4904,7 +4917,12 @@
|
|||||||
// inspect the tab that's about to close.
|
// inspect the tab that's about to close.
|
||||||
let evt = new CustomEvent("TabClose", {
|
let evt = new CustomEvent("TabClose", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
detail: { adoptedBy: adoptedByTab, skipSessionStore, telemetrySource },
|
detail: {
|
||||||
|
adoptedBy: adoptedByTab,
|
||||||
|
skipSessionStore,
|
||||||
|
isUserTriggered,
|
||||||
|
telemetrySource,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
aTab.dispatchEvent(evt);
|
aTab.dispatchEvent(evt);
|
||||||
|
|
||||||
@@ -9274,13 +9292,17 @@ var TabContextMenu = {
|
|||||||
|
|
||||||
closeContextTabs() {
|
closeContextTabs() {
|
||||||
if (this.contextTab.multiselected) {
|
if (this.contextTab.multiselected) {
|
||||||
gBrowser.removeMultiSelectedTabs({
|
gBrowser.removeMultiSelectedTabs(
|
||||||
telemetrySource: gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP,
|
gBrowser.TabMetrics.userTriggeredContext(
|
||||||
});
|
gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
gBrowser.removeTab(this.contextTab, {
|
gBrowser.removeTab(this.contextTab, {
|
||||||
animate: true,
|
animate: true,
|
||||||
telemetrySource: gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP,
|
...gBrowser.TabMetrics.userTriggeredContext(
|
||||||
|
gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -396,9 +396,11 @@ tabgroup:
|
|||||||
bugs:
|
bugs:
|
||||||
- https://bugzil.la/1938405
|
- https://bugzil.la/1938405
|
||||||
- https://bugzil.la/1960360
|
- https://bugzil.la/1960360
|
||||||
|
- https://bugzil.la/1961161
|
||||||
data_reviews:
|
data_reviews:
|
||||||
- https://bugzil.la/1938405
|
- https://bugzil.la/1938405
|
||||||
- https://bugzil.la/1960360
|
- https://bugzil.la/1960360
|
||||||
|
- https://bugzil.la/1961161
|
||||||
data_sensitivity:
|
data_sensitivity:
|
||||||
- interaction
|
- interaction
|
||||||
labels:
|
labels:
|
||||||
@@ -408,6 +410,7 @@ tabgroup:
|
|||||||
- new
|
- new
|
||||||
- close_tabstrip
|
- close_tabstrip
|
||||||
- close_tabmenu
|
- close_tabmenu
|
||||||
|
- close_tab_other
|
||||||
- reorder
|
- reorder
|
||||||
- remove_same_window
|
- remove_same_window
|
||||||
- remove_other_window
|
- remove_other_window
|
||||||
|
|||||||
@@ -514,6 +514,8 @@ tags = "vertical-tabs"
|
|||||||
["browser_tab_groups_keyboard_focus.js"]
|
["browser_tab_groups_keyboard_focus.js"]
|
||||||
tags = "vertical-tabs"
|
tags = "vertical-tabs"
|
||||||
|
|
||||||
|
["browser_tab_groups_tab_interactions_telemetry.js"]
|
||||||
|
|
||||||
["browser_tab_groups_telemetry.js"]
|
["browser_tab_groups_telemetry.js"]
|
||||||
|
|
||||||
["browser_tab_label_during_reload.js"]
|
["browser_tab_label_during_reload.js"]
|
||||||
|
|||||||
@@ -0,0 +1,393 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
const {
|
||||||
|
openFirefoxViewTab,
|
||||||
|
closeFirefoxViewTab,
|
||||||
|
init: FirefoxViewTestUtilsInit,
|
||||||
|
} = ChromeUtils.importESModule(
|
||||||
|
"resource://testing-common/FirefoxViewTestUtils.sys.mjs"
|
||||||
|
);
|
||||||
|
FirefoxViewTestUtilsInit(this);
|
||||||
|
|
||||||
|
const { TabStateFlusher } = ChromeUtils.importESModule(
|
||||||
|
"resource:///modules/sessionstore/TabStateFlusher.sys.mjs"
|
||||||
|
);
|
||||||
|
|
||||||
|
const { UrlbarTestUtils } = ChromeUtils.importESModule(
|
||||||
|
"resource://testing-common/UrlbarTestUtils.sys.mjs"
|
||||||
|
);
|
||||||
|
|
||||||
|
let resetTelemetry = async () => {
|
||||||
|
await Services.fog.testFlushAllChildren();
|
||||||
|
Services.fog.testResetFOG();
|
||||||
|
};
|
||||||
|
|
||||||
|
let assertMetricEmpty = async metricName => {
|
||||||
|
Assert.equal(
|
||||||
|
Glean.tabgroup.tabInteractions[metricName].testGetValue(),
|
||||||
|
null,
|
||||||
|
`tab_interactions.${metricName} starts empty`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let assertMetricFoundFor = async (metricName, count = 1) => {
|
||||||
|
await BrowserTestUtils.waitForCondition(() => {
|
||||||
|
return Glean.tabgroup.tabInteractions[metricName].testGetValue() == count;
|
||||||
|
}, `Wait for tab_interactions.${metricName} to be recorded`);
|
||||||
|
Assert.equal(
|
||||||
|
Glean.tabgroup.tabInteractions[metricName].testGetValue(),
|
||||||
|
count,
|
||||||
|
`tab_interactions.${metricName} was recorded`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let activateTabContextMenuItem = async (
|
||||||
|
selectedTab,
|
||||||
|
menuItemSelector,
|
||||||
|
submenuItemSelector
|
||||||
|
) => {
|
||||||
|
let submenuItem;
|
||||||
|
let submenuItemHiddenPromise;
|
||||||
|
|
||||||
|
const tabContextMenu = window.document.getElementById("tabContextMenu");
|
||||||
|
Assert.equal(
|
||||||
|
tabContextMenu.state,
|
||||||
|
"closed",
|
||||||
|
"context menu is initially closed"
|
||||||
|
);
|
||||||
|
const contextMenuShown = BrowserTestUtils.waitForEvent(
|
||||||
|
tabContextMenu,
|
||||||
|
"popupshown",
|
||||||
|
false,
|
||||||
|
ev => ev.target == tabContextMenu
|
||||||
|
);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(
|
||||||
|
selectedTab,
|
||||||
|
{ type: "contextmenu", button: 2 },
|
||||||
|
window
|
||||||
|
);
|
||||||
|
await contextMenuShown;
|
||||||
|
|
||||||
|
if (submenuItemSelector) {
|
||||||
|
submenuItem = tabContextMenu.querySelector(submenuItemSelector);
|
||||||
|
|
||||||
|
const submenuPopupPromise = BrowserTestUtils.waitForEvent(
|
||||||
|
submenuItem.menupopup,
|
||||||
|
"popupshown"
|
||||||
|
);
|
||||||
|
submenuItem.openMenu(true);
|
||||||
|
await submenuPopupPromise;
|
||||||
|
|
||||||
|
submenuItemHiddenPromise = BrowserTestUtils.waitForEvent(
|
||||||
|
submenuItem.menupopup,
|
||||||
|
"popuphidden"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contextMenuHidden = BrowserTestUtils.waitForEvent(
|
||||||
|
tabContextMenu,
|
||||||
|
"popuphidden",
|
||||||
|
false,
|
||||||
|
ev => ev.target == tabContextMenu
|
||||||
|
);
|
||||||
|
tabContextMenu.activateItem(tabContextMenu.querySelector(menuItemSelector));
|
||||||
|
await contextMenuHidden;
|
||||||
|
if (submenuItemSelector) {
|
||||||
|
await submenuItemHiddenPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.equal(tabContextMenu.state, "closed", "context menu is closed");
|
||||||
|
};
|
||||||
|
|
||||||
|
add_setup(async () => {
|
||||||
|
await SpecialPowers.pushPrefEnv({
|
||||||
|
set: [["browser.tabs.groups.enabled", true]],
|
||||||
|
});
|
||||||
|
window.gTabsPanel.init();
|
||||||
|
registerCleanupFunction(async () => {
|
||||||
|
await SpecialPowers.popPrefEnv();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_tabInteractionsBasic() {
|
||||||
|
let initialTab = window.gBrowser.tabs[0];
|
||||||
|
await resetTelemetry();
|
||||||
|
|
||||||
|
let tab = BrowserTestUtils.addTab(window.gBrowser, "https://example.com");
|
||||||
|
let group = window.gBrowser.addTabGroup([tab]);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that selecting a tab in a group records tab_interactions.activate"
|
||||||
|
);
|
||||||
|
await assertMetricEmpty("activate");
|
||||||
|
const tabSelectEvent = BrowserTestUtils.waitForEvent(window, "TabSelect");
|
||||||
|
window.gBrowser.selectTabAtIndex(1);
|
||||||
|
await tabSelectEvent;
|
||||||
|
await assertMetricFoundFor("activate");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that moving an existing tab into a tab group records tab_interactions.add"
|
||||||
|
);
|
||||||
|
let tab1 = BrowserTestUtils.addTab(window.gBrowser, "https://example.com");
|
||||||
|
await assertMetricEmpty("add");
|
||||||
|
window.gBrowser.moveTabToGroup(tab1, group, { isUserTriggered: true });
|
||||||
|
await assertMetricFoundFor("add");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that adding a new tab to a tab group records tab_interactions.new"
|
||||||
|
);
|
||||||
|
await assertMetricEmpty("new");
|
||||||
|
BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
tabGroup: group,
|
||||||
|
});
|
||||||
|
await assertMetricFoundFor("new");
|
||||||
|
|
||||||
|
info("Test that moving a tab within a group calls tab_interactions.reorder");
|
||||||
|
await assertMetricEmpty("reorder");
|
||||||
|
window.gBrowser.moveTabTo(group.tabs[0], {
|
||||||
|
tabIndex: 3,
|
||||||
|
isUserTriggered: true,
|
||||||
|
});
|
||||||
|
await assertMetricFoundFor("reorder");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that duplicating a tab within a group calls tab_interactions.duplicate"
|
||||||
|
);
|
||||||
|
await assertMetricEmpty("duplicate");
|
||||||
|
window.gBrowser.duplicateTab(group.tabs[0], true, { tabIndex: 2 });
|
||||||
|
await assertMetricFoundFor("duplicate");
|
||||||
|
|
||||||
|
window.gBrowser.removeAllTabsBut(initialTab);
|
||||||
|
await resetTelemetry();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_tabInteractionsClose() {
|
||||||
|
let initialTab = window.gBrowser.tabs[0];
|
||||||
|
await resetTelemetry();
|
||||||
|
FirefoxViewTestUtilsInit(this, window);
|
||||||
|
|
||||||
|
let tabs = Array.from({ length: 5 }, () => {
|
||||||
|
return BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let group = window.gBrowser.addTabGroup(tabs);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab using the tab's close button calls tab_interactions.close_tabstrip"
|
||||||
|
);
|
||||||
|
await assertMetricEmpty("close_tabstrip");
|
||||||
|
group.tabs.at(-1).querySelector(".tab-close-button").click();
|
||||||
|
await assertMetricFoundFor("close_tabstrip");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via the tab context menu calls tab_interactions.close_tabstrip"
|
||||||
|
);
|
||||||
|
await activateTabContextMenuItem(group.tabs[0], "#context_closeTab");
|
||||||
|
await assertMetricFoundFor("close_tabstrip", 2);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via the tab close keyboard shortcut calls tab_interactions.close_tab_other"
|
||||||
|
);
|
||||||
|
window.gBrowser.selectedTab = group.tabs.at(-1);
|
||||||
|
await assertMetricEmpty("close_tab_other");
|
||||||
|
EventUtils.synthesizeKey("w", { accelKey: true }, window);
|
||||||
|
await assertMetricFoundFor("close_tab_other");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via top menu calls tab_interactions.close_tab_other"
|
||||||
|
);
|
||||||
|
window.document.getElementById("cmd_close").doCommand();
|
||||||
|
await assertMetricFoundFor("close_tab_other", 2);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via firefox view calls tab_interactions.close_tab_other"
|
||||||
|
);
|
||||||
|
await openFirefoxViewTab(window).then(async viewTab => {
|
||||||
|
const openTabs = viewTab.linkedBrowser.contentDocument
|
||||||
|
.querySelector("named-deck > view-recentbrowsing view-opentabs")
|
||||||
|
.shadowRoot.querySelector("view-opentabs-card").tabList.rowEls;
|
||||||
|
const tabElement = Array.from(openTabs).find(t => t.__tabElement.group);
|
||||||
|
tabElement.shadowRoot.querySelector("moz-button.dismiss-button").click();
|
||||||
|
await assertMetricFoundFor("close_tab_other", 3);
|
||||||
|
});
|
||||||
|
await closeFirefoxViewTab(window);
|
||||||
|
|
||||||
|
window.gBrowser.removeAllTabsBut(initialTab);
|
||||||
|
await resetTelemetry();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_tabInteractionsCloseViaAnotherTabContext() {
|
||||||
|
let initialTab = window.gBrowser.tabs[0];
|
||||||
|
await resetTelemetry();
|
||||||
|
|
||||||
|
window.gBrowser.addTabGroup([
|
||||||
|
BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await assertMetricEmpty("close_tab_other");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via the tab context menu 'close other tabs' command calls tab_interactions.close_tab_other"
|
||||||
|
);
|
||||||
|
await activateTabContextMenuItem(
|
||||||
|
initialTab,
|
||||||
|
"#context_closeOtherTabs",
|
||||||
|
"#context_closeTabOptions"
|
||||||
|
);
|
||||||
|
await assertMetricFoundFor("close_tab_other");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via the tab context menu 'close tabs to left' command calls tab_interactions.close_tab_other"
|
||||||
|
);
|
||||||
|
window.gBrowser.addTabGroup([
|
||||||
|
BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
window.gBrowser.moveTabToEnd(initialTab);
|
||||||
|
await activateTabContextMenuItem(
|
||||||
|
initialTab,
|
||||||
|
"#context_closeTabsToTheStart",
|
||||||
|
"#context_closeTabOptions"
|
||||||
|
);
|
||||||
|
await assertMetricFoundFor("close_tab_other", 2);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via the tab context menu 'close tabs to right' command calls tab_interactions.close_tab_other"
|
||||||
|
);
|
||||||
|
window.gBrowser.addTabGroup([
|
||||||
|
BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
await activateTabContextMenuItem(
|
||||||
|
initialTab,
|
||||||
|
"#context_closeTabsToTheEnd",
|
||||||
|
"#context_closeTabOptions"
|
||||||
|
);
|
||||||
|
await assertMetricFoundFor("close_tab_other", 3);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab via the tab context menu 'close duplicate tabs' command calls tab_interactions.close_tab_other"
|
||||||
|
);
|
||||||
|
let duplicateTabs = [
|
||||||
|
BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
}),
|
||||||
|
BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
await Promise.all(
|
||||||
|
duplicateTabs.map(t => BrowserTestUtils.browserLoaded(t.linkedBrowser))
|
||||||
|
);
|
||||||
|
window.gBrowser.addTabGroup([duplicateTabs[1]]);
|
||||||
|
|
||||||
|
await activateTabContextMenuItem(
|
||||||
|
duplicateTabs[0],
|
||||||
|
"#context_closeDuplicateTabs",
|
||||||
|
"#context_closeTabOptions"
|
||||||
|
);
|
||||||
|
await assertMetricFoundFor("close_tab_other", 4);
|
||||||
|
|
||||||
|
window.gBrowser.removeAllTabsBut(initialTab);
|
||||||
|
await resetTelemetry();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_tabInteractionsCloseTabOverflowMenu() {
|
||||||
|
let initialTab = window.gBrowser.tabs[0];
|
||||||
|
await resetTelemetry();
|
||||||
|
FirefoxViewTestUtilsInit(this, window);
|
||||||
|
|
||||||
|
let tab = BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
});
|
||||||
|
window.gBrowser.addTabGroup([tab]);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that closing a tab from the tab overflow menu calls tab_interactions.close_tabmenu"
|
||||||
|
);
|
||||||
|
let viewShown = BrowserTestUtils.waitForEvent(
|
||||||
|
window.document.getElementById("allTabsMenu-allTabsView"),
|
||||||
|
"ViewShown"
|
||||||
|
);
|
||||||
|
window.document.getElementById("alltabs-button").click();
|
||||||
|
await viewShown;
|
||||||
|
|
||||||
|
await assertMetricEmpty("close_tabmenu");
|
||||||
|
window.document
|
||||||
|
.querySelector(".all-tabs-item.grouped .all-tabs-close-button")
|
||||||
|
.click();
|
||||||
|
await assertMetricFoundFor("close_tabmenu");
|
||||||
|
|
||||||
|
let panel = window.document
|
||||||
|
.getElementById("allTabsMenu-allTabsView")
|
||||||
|
.closest("panel");
|
||||||
|
if (!panel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let hidden = BrowserTestUtils.waitForPopupEvent(panel, "hidden");
|
||||||
|
panel.hidePopup();
|
||||||
|
await hidden;
|
||||||
|
|
||||||
|
window.gBrowser.removeAllTabsBut(initialTab);
|
||||||
|
await resetTelemetry();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_tabInteractionsRemoveFromGroup() {
|
||||||
|
let initialTab = window.gBrowser.tabs[0];
|
||||||
|
await resetTelemetry();
|
||||||
|
|
||||||
|
let tabs = Array.from({ length: 3 }, () => {
|
||||||
|
return BrowserTestUtils.addTab(window.gBrowser, "https://example.com", {
|
||||||
|
skipAnimation: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let group = window.gBrowser.addTabGroup(tabs);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that moving a tab out of a tab group calls tab_interactions.remove_same_window"
|
||||||
|
);
|
||||||
|
await assertMetricEmpty("remove_same_window");
|
||||||
|
window.gBrowser.moveTabTo(group.tabs[0], {
|
||||||
|
tabIndex: 0,
|
||||||
|
isUserTriggered: true,
|
||||||
|
});
|
||||||
|
await assertMetricFoundFor("remove_same_window");
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that moving a tab out of a tab group and into a different (existing) window calls tab_interactions.remove_other_window"
|
||||||
|
);
|
||||||
|
await assertMetricEmpty("remove_other_window");
|
||||||
|
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||||
|
newWin.gBrowser.adoptTab(group.tabs[0]);
|
||||||
|
await assertMetricFoundFor("remove_other_window");
|
||||||
|
await BrowserTestUtils.closeWindow(newWin);
|
||||||
|
|
||||||
|
info(
|
||||||
|
"Test that moving a tab out of a tab group and into a different (new) window calls tab_interactions.remove_new_window"
|
||||||
|
);
|
||||||
|
await assertMetricEmpty("remove_new_window");
|
||||||
|
let newWindowPromise = BrowserTestUtils.waitForNewWindow();
|
||||||
|
await EventUtils.synthesizePlainDragAndDrop({
|
||||||
|
srcElement: group.tabs[0],
|
||||||
|
srcWindow: window,
|
||||||
|
destElement: null,
|
||||||
|
// don't move horizontally because that could cause a tab move
|
||||||
|
// animation, and there's code to prevent a tab detaching if
|
||||||
|
// the dragged tab is released while the animation is running.
|
||||||
|
stepX: 0,
|
||||||
|
stepY: 100,
|
||||||
|
});
|
||||||
|
newWin = await newWindowPromise;
|
||||||
|
await assertMetricFoundFor("remove_new_window");
|
||||||
|
await BrowserTestUtils.closeWindow(newWin);
|
||||||
|
|
||||||
|
window.gBrowser.removeAllTabsBut(initialTab);
|
||||||
|
await resetTelemetry();
|
||||||
|
});
|
||||||
@@ -715,128 +715,6 @@ add_task(async function test_tabContextMenu_addTabsToGroup() {
|
|||||||
await resetTelemetry();
|
await resetTelemetry();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_tabInteractions() {
|
|
||||||
let assertMetricEmpty = async metricName => {
|
|
||||||
Assert.equal(
|
|
||||||
Glean.tabgroup.tabInteractions[metricName].testGetValue(),
|
|
||||||
null,
|
|
||||||
`tab_interactions.${metricName} starts empty`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let assertOneMetricFoundFor = async metricName => {
|
|
||||||
await BrowserTestUtils.waitForCondition(() => {
|
|
||||||
return Glean.tabgroup.tabInteractions[metricName].testGetValue() !== null;
|
|
||||||
}, `Wait for tab_interactions.${metricName} to be recorded`);
|
|
||||||
Assert.equal(
|
|
||||||
Glean.tabgroup.tabInteractions[metricName].testGetValue(),
|
|
||||||
1,
|
|
||||||
`tab_interactions.${metricName} was recorded`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let initialTab = win.gBrowser.tabs[0];
|
|
||||||
|
|
||||||
await resetTelemetry();
|
|
||||||
let group = await makeTabGroup();
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that selecting a tab in a group records tab_interactions.activate"
|
|
||||||
);
|
|
||||||
await assertMetricEmpty("activate");
|
|
||||||
const tabSelectEvent = BrowserTestUtils.waitForEvent(win, "TabSelect");
|
|
||||||
win.gBrowser.selectTabAtIndex(1);
|
|
||||||
await tabSelectEvent;
|
|
||||||
await assertOneMetricFoundFor("activate");
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that moving an existing tab into a tab group records tab_interactions.add"
|
|
||||||
);
|
|
||||||
let tab1 = BrowserTestUtils.addTab(win.gBrowser, "https://example.com");
|
|
||||||
await assertMetricEmpty("add");
|
|
||||||
win.gBrowser.moveTabToGroup(tab1, group, { isUserTriggered: true });
|
|
||||||
await assertOneMetricFoundFor("add");
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that adding a new tab to a tab group records tab_interactions.new"
|
|
||||||
);
|
|
||||||
await assertMetricEmpty("new");
|
|
||||||
BrowserTestUtils.addTab(win.gBrowser, "https://example.com", {
|
|
||||||
tabGroup: group,
|
|
||||||
});
|
|
||||||
await assertOneMetricFoundFor("new");
|
|
||||||
|
|
||||||
info("Test that moving a tab within a group calls tab_interactions.reorder");
|
|
||||||
await assertMetricEmpty("reorder");
|
|
||||||
win.gBrowser.moveTabTo(group.tabs[0], { tabIndex: 3, isUserTriggered: true });
|
|
||||||
await assertOneMetricFoundFor("reorder");
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that duplicating a tab within a group calls tab_interactions.duplicate"
|
|
||||||
);
|
|
||||||
await assertMetricEmpty("duplicate");
|
|
||||||
win.gBrowser.duplicateTab(group.tabs[0], true, { tabIndex: 2 });
|
|
||||||
await assertOneMetricFoundFor("duplicate");
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that closing a tab using the tab's close button calls tab_interactions.close_tabstrip"
|
|
||||||
);
|
|
||||||
await assertMetricEmpty("close_tabstrip");
|
|
||||||
group.tabs.at(-1).querySelector(".tab-close-button").click();
|
|
||||||
await assertOneMetricFoundFor("close_tabstrip");
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that closing a tab from the tab overflow menu calls tab_interactions.close_tabmenu"
|
|
||||||
);
|
|
||||||
await openTabsMenu();
|
|
||||||
await assertMetricEmpty("close_tabmenu");
|
|
||||||
win.document
|
|
||||||
.querySelector(".all-tabs-item.grouped .all-tabs-close-button")
|
|
||||||
.click();
|
|
||||||
await assertOneMetricFoundFor("close_tabmenu");
|
|
||||||
await closeTabsMenu();
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that moving a tab out of a tab group calls tab_interactions.remove_same_window"
|
|
||||||
);
|
|
||||||
await assertMetricEmpty("remove_same_window");
|
|
||||||
win.gBrowser.moveTabTo(group.tabs[0], { tabIndex: 0, isUserTriggered: true });
|
|
||||||
await assertOneMetricFoundFor("remove_same_window");
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that moving a tab out of a tab group and into a different (existing) window calls tab_interactions.remove_other_window"
|
|
||||||
);
|
|
||||||
await assertMetricEmpty("remove_other_window");
|
|
||||||
let tab2 = BrowserTestUtils.addTab(win.gBrowser, "https://example.com");
|
|
||||||
win.gBrowser.moveTabToGroup(tab2, group, { isUserTriggered: true });
|
|
||||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
|
||||||
newWin.gBrowser.adoptTab(tab2);
|
|
||||||
await assertOneMetricFoundFor("remove_other_window");
|
|
||||||
await BrowserTestUtils.closeWindow(newWin);
|
|
||||||
|
|
||||||
info(
|
|
||||||
"Test that moving a tab out of a tab group and into a different (new) window calls tab_interactions.remove_new_window"
|
|
||||||
);
|
|
||||||
await assertMetricEmpty("remove_new_window");
|
|
||||||
let newWindowPromise = BrowserTestUtils.waitForNewWindow();
|
|
||||||
await EventUtils.synthesizePlainDragAndDrop({
|
|
||||||
srcElement: group.tabs[0],
|
|
||||||
srcWindow: win,
|
|
||||||
destElement: null,
|
|
||||||
// don't move horizontally because that could cause a tab move
|
|
||||||
// animation, and there's code to prevent a tab detaching if
|
|
||||||
// the dragged tab is released while the animation is running.
|
|
||||||
stepX: 0,
|
|
||||||
stepY: 100,
|
|
||||||
});
|
|
||||||
newWin = await newWindowPromise;
|
|
||||||
await assertOneMetricFoundFor("remove_new_window");
|
|
||||||
await BrowserTestUtils.closeWindow(newWin);
|
|
||||||
|
|
||||||
win.gBrowser.removeAllTabsBut(initialTab);
|
|
||||||
await resetTelemetry();
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_groupInteractions() {
|
add_task(async function test_groupInteractions() {
|
||||||
await resetTelemetry();
|
await resetTelemetry();
|
||||||
let group = await makeTabGroup();
|
let group = await makeTabGroup();
|
||||||
|
|||||||
@@ -1269,13 +1269,16 @@ export let BrowserUsageTelemetry = {
|
|||||||
|
|
||||||
_onTabClosed(event) {
|
_onTabClosed(event) {
|
||||||
const group = event.target?.group;
|
const group = event.target?.group;
|
||||||
|
const isUserTriggered = event.detail?.isUserTriggered;
|
||||||
const source = event.detail?.telemetrySource;
|
const source = event.detail?.telemetrySource;
|
||||||
|
|
||||||
if (group) {
|
if (group && isUserTriggered) {
|
||||||
if (source == lazy.TabMetrics.METRIC_SOURCE.TAB_STRIP) {
|
if (source == lazy.TabMetrics.METRIC_SOURCE.TAB_STRIP) {
|
||||||
Glean.tabgroup.tabInteractions.close_tabstrip.add();
|
Glean.tabgroup.tabInteractions.close_tabstrip.add();
|
||||||
} else if (source == lazy.TabMetrics.METRIC_SOURCE.TAB_OVERFLOW_MENU) {
|
} else if (source == lazy.TabMetrics.METRIC_SOURCE.TAB_OVERFLOW_MENU) {
|
||||||
Glean.tabgroup.tabInteractions.close_tabmenu.add();
|
Glean.tabgroup.tabInteractions.close_tabmenu.add();
|
||||||
|
} else {
|
||||||
|
Glean.tabgroup.tabInteractions.close_tab_other.add();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user