зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1620358: Gather telemetry on toolbar state. r=Gijs,zombie
Differential Revision: https://phabricator.services.mozilla.com/D78393
This commit is contained in:
Родитель
778747ede9
Коммит
e07f989e6c
|
@ -144,7 +144,7 @@
|
|||
<menupopup id="menu_viewPopup"
|
||||
onpopupshowing="updateCharacterEncodingMenuState();">
|
||||
<menu id="viewToolbarsMenu" data-l10n-id="menu-view-toolbars-menu">
|
||||
<menupopup onpopupshowing="onViewToolbarsPopupShowing(event);">
|
||||
<menupopup id="view-menu-popup" onpopupshowing="onViewToolbarsPopupShowing(event);">
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_customizeToolbars"
|
||||
command="cmd_CustomizeToolbars" data-l10n-id="menu-view-customize-toolbar"/>
|
||||
|
|
|
@ -956,6 +956,11 @@ var BrowserPageActions = {
|
|||
this._contextAction = null;
|
||||
|
||||
action.pinnedToUrlbar = !action.pinnedToUrlbar;
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
action.id,
|
||||
action.pinnedToUrlbar ? "page-action-buttons" : null,
|
||||
"pageaction-context"
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1431,11 +1431,16 @@ var BookmarkingUI = {
|
|||
);
|
||||
},
|
||||
|
||||
toggleBookmarksToolbar() {
|
||||
toggleBookmarksToolbar(reason) {
|
||||
CustomizableUI.setToolbarVisibility(
|
||||
"PersonalToolbar",
|
||||
document.getElementById("PersonalToolbar").collapsed
|
||||
);
|
||||
BrowserUsageTelemetry.recordToolbarVisibility(
|
||||
"PersonalToolbar",
|
||||
document.getElementById("PersonalToolbar").collapsed,
|
||||
reason
|
||||
);
|
||||
},
|
||||
|
||||
attachPlacesView(event, node) {
|
||||
|
@ -1924,9 +1929,19 @@ var BookmarkingUI = {
|
|||
}
|
||||
|
||||
CustomizableUI.addWidgetToArea(this.BOOKMARK_BUTTON_ID, area, pos);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
this.BOOKMARK_BUTTON_ID,
|
||||
area,
|
||||
"bookmark-tools"
|
||||
);
|
||||
} else {
|
||||
// Move it back to the palette.
|
||||
CustomizableUI.removeWidgetFromArea(this.BOOKMARK_BUTTON_ID);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
this.BOOKMARK_BUTTON_ID,
|
||||
null,
|
||||
"bookmark-tools"
|
||||
);
|
||||
}
|
||||
triggerNode.setAttribute("checked", !placement);
|
||||
updateToggleControlLabel(triggerNode);
|
||||
|
|
|
@ -6403,9 +6403,11 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
|
|||
|
||||
function onViewToolbarCommand(aEvent) {
|
||||
let node = aEvent.originalTarget;
|
||||
let menuId = node.parentNode.id;
|
||||
let toolbarId = node.getAttribute("toolbarId");
|
||||
let isVisible = node.getAttribute("checked") == "true";
|
||||
CustomizableUI.setToolbarVisibility(toolbarId, isVisible);
|
||||
BrowserUsageTelemetry.recordToolbarVisibility(toolbarId, isVisible, menuId);
|
||||
updateToggleControlLabel(node);
|
||||
}
|
||||
|
||||
|
|
|
@ -419,7 +419,7 @@
|
|||
contexttype="toolbaritem"
|
||||
class="customize-context-reportExtension"/>
|
||||
<menuseparator/>
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode, 'toolbar-context-menu')"
|
||||
data-lazy-l10n-id="toolbar-context-menu-pin-to-overflow-menu"
|
||||
contexttype="toolbaritem"
|
||||
class="customize-context-moveToPanel"/>
|
||||
|
@ -428,7 +428,7 @@
|
|||
type="checkbox"
|
||||
data-lazy-l10n-id="toolbar-context-menu-auto-hide-downloads-button"
|
||||
contexttype="toolbaritem"/>
|
||||
<menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
|
||||
<menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode, 'toolbar-context-menu')"
|
||||
data-lazy-l10n-id="toolbar-context-menu-remove-from-toolbar"
|
||||
contexttype="toolbaritem"
|
||||
class="customize-context-removeFromToolbar"/>
|
||||
|
@ -1341,7 +1341,7 @@
|
|||
class="menuitem-iconic subviewbutton"
|
||||
label-show="&viewBookmarksToolbar.label;"
|
||||
label-hide="&hideBookmarksToolbar.label;"
|
||||
oncommand="BookmarkingUI.toggleBookmarksToolbar();"/>
|
||||
oncommand="BookmarkingUI.toggleBookmarksToolbar('bookmarks-widget');"/>
|
||||
<menuseparator/>
|
||||
<!-- Bookmarks toolbar items -->
|
||||
</menupopup>
|
||||
|
|
|
@ -21,6 +21,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
PanelMultiView: "resource:///modules/PanelMultiView.jsm",
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
||||
ShortcutUtils: "resource://gre/modules/ShortcutUtils.jsm",
|
||||
BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gWidgetsBundle", function() {
|
||||
|
@ -4388,6 +4389,9 @@ var CustomizableUI = {
|
|||
if (!item.hasAttribute("onclick")) {
|
||||
subviewItem.addEventListener("click", event => {
|
||||
let newEvent = new doc.defaultView.MouseEvent(event.type, event);
|
||||
|
||||
// Telemetry should only pay attention to the original event.
|
||||
BrowserUsageTelemetry.ignoreEvent(newEvent);
|
||||
item.dispatchEvent(newEvent);
|
||||
});
|
||||
}
|
||||
|
@ -4408,6 +4412,9 @@ var CustomizableUI = {
|
|||
event.sourceEvent,
|
||||
0
|
||||
);
|
||||
|
||||
// Telemetry should only pay attention to the original event.
|
||||
BrowserUsageTelemetry.ignoreEvent(newEvent);
|
||||
item.dispatchEvent(newEvent);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -54,6 +54,11 @@ ChromeUtils.defineModuleGetter(
|
|||
"BrowserUtils",
|
||||
"resource://gre/modules/BrowserUtils.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"BrowserUsageTelemetry",
|
||||
"resource:///modules/BrowserUsageTelemetry.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"SessionStore",
|
||||
|
@ -668,7 +673,7 @@ CustomizeMode.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
async addToToolbar(aNode) {
|
||||
async addToToolbar(aNode, aReason) {
|
||||
aNode = this._getCustomizableChildForNode(aNode);
|
||||
if (aNode.localName == "toolbarpaletteitem" && aNode.firstElementChild) {
|
||||
aNode = aNode.firstElementChild;
|
||||
|
@ -690,6 +695,10 @@ CustomizeMode.prototype = {
|
|||
}
|
||||
|
||||
CustomizableUI.addWidgetToArea(widgetToAdd, CustomizableUI.AREA_NAVBAR);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
widgetToAdd,
|
||||
CustomizableUI.AREA_NAVBAR
|
||||
);
|
||||
if (!this._customizing) {
|
||||
CustomizableUI.dispatchToolboxEvent("customizationchange");
|
||||
}
|
||||
|
@ -707,7 +716,7 @@ CustomizeMode.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
async addToPanel(aNode) {
|
||||
async addToPanel(aNode, aReason) {
|
||||
aNode = this._getCustomizableChildForNode(aNode);
|
||||
if (aNode.localName == "toolbarpaletteitem" && aNode.firstElementChild) {
|
||||
aNode = aNode.firstElementChild;
|
||||
|
@ -720,6 +729,7 @@ CustomizeMode.prototype = {
|
|||
|
||||
let panel = CustomizableUI.AREA_FIXED_OVERFLOW_PANEL;
|
||||
CustomizableUI.addWidgetToArea(aNode.id, panel);
|
||||
BrowserUsageTelemetry.recordWidgetChange(aNode.id, panel, aReason);
|
||||
if (!this._customizing) {
|
||||
CustomizableUI.dispatchToolboxEvent("customizationchange");
|
||||
}
|
||||
|
@ -754,7 +764,7 @@ CustomizeMode.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
async removeFromArea(aNode) {
|
||||
async removeFromArea(aNode, aReason) {
|
||||
aNode = this._getCustomizableChildForNode(aNode);
|
||||
if (aNode.localName == "toolbarpaletteitem" && aNode.firstElementChild) {
|
||||
aNode = aNode.firstElementChild;
|
||||
|
@ -766,6 +776,7 @@ CustomizeMode.prototype = {
|
|||
}
|
||||
|
||||
CustomizableUI.removeWidgetFromArea(aNode.id);
|
||||
BrowserUsageTelemetry.recordWidgetChange(aNode.id, null, aReason);
|
||||
if (!this._customizing) {
|
||||
CustomizableUI.dispatchToolboxEvent("customizationchange");
|
||||
}
|
||||
|
@ -2089,7 +2100,8 @@ CustomizeMode.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
CustomizableUI.removeWidgetFromArea(aDraggedItemId);
|
||||
CustomizableUI.removeWidgetFromArea(aDraggedItemId, "drag");
|
||||
BrowserUsageTelemetry.recordWidgetChange(aDraggedItemId, null, "drag");
|
||||
// Special widgets are removed outright, we can return here:
|
||||
if (CustomizableUI.isSpecialWidget(aDraggedItemId)) {
|
||||
return;
|
||||
|
@ -2148,6 +2160,11 @@ CustomizeMode.prototype = {
|
|||
// widget to the end of the area.
|
||||
if (aTargetNode == areaCustomizationTarget) {
|
||||
CustomizableUI.addWidgetToArea(aDraggedItemId, aTargetArea.id);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
aDraggedItemId,
|
||||
aTargetArea.id,
|
||||
"drag"
|
||||
);
|
||||
this._onDragEnd(aEvent);
|
||||
return;
|
||||
}
|
||||
|
@ -2196,8 +2213,18 @@ CustomizeMode.prototype = {
|
|||
// that the widget is moving within a customizable area.
|
||||
if (aTargetArea == aOriginArea) {
|
||||
CustomizableUI.moveWidgetWithinArea(aDraggedItemId, position);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
aDraggedItemId,
|
||||
aTargetArea.id,
|
||||
"drag"
|
||||
);
|
||||
} else {
|
||||
CustomizableUI.addWidgetToArea(aDraggedItemId, aTargetArea.id, position);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
aDraggedItemId,
|
||||
aTargetArea.id,
|
||||
"drag"
|
||||
);
|
||||
}
|
||||
|
||||
this._onDragEnd(aEvent);
|
||||
|
@ -2639,6 +2666,11 @@ CustomizeMode.prototype = {
|
|||
"nav-bar",
|
||||
insertionPoint
|
||||
);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
"downloads-button",
|
||||
"nav-bar",
|
||||
"move-downloads"
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -21,6 +21,11 @@ ChromeUtils.defineModuleGetter(
|
|||
"CustomizableUI",
|
||||
"resource:///modules/CustomizableUI.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"BrowserUsageTelemetry",
|
||||
"resource:///modules/BrowserUsageTelemetry.jsm"
|
||||
);
|
||||
|
||||
const WIDGET_ID = "search-container";
|
||||
const PREF_NAME = "browser.search.widget.inNavBar";
|
||||
|
@ -85,8 +90,14 @@ const SearchWidgetTracker = {
|
|||
CustomizableUI.AREA_NAVBAR,
|
||||
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1
|
||||
);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
WIDGET_ID,
|
||||
CustomizableUI.AREA_NAVBAR,
|
||||
"searchpref"
|
||||
);
|
||||
} else {
|
||||
CustomizableUI.removeWidgetFromArea(WIDGET_ID);
|
||||
BrowserUsageTelemetry.recordWidgetChange(WIDGET_ID, null, "searchpref");
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -43,18 +43,18 @@
|
|||
contexttype="toolbaritem"
|
||||
class="customize-context-reportExtension"/>
|
||||
<menuseparator/>
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode, 'panelitem-context')"
|
||||
id="customizationPanelItemContextMenuPin"
|
||||
data-lazy-l10n-id="toolbar-context-menu-pin-to-overflow-menu"
|
||||
closemenu="single"
|
||||
class="customize-context-moveToPanel"/>
|
||||
<menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode)"
|
||||
<menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode, 'panelitem-context')"
|
||||
id="customizationPanelItemContextMenuUnpin"
|
||||
closemenu="single"
|
||||
class="customize-context-moveToToolbar"
|
||||
accesskey="&customizeMenu.unpinFromOverflowMenu.accesskey;"
|
||||
label="&customizeMenu.unpinFromOverflowMenu.label;"/>
|
||||
<menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
|
||||
<menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode, 'panelitem-context')"
|
||||
closemenu="single"
|
||||
class="customize-context-removeFromPanel"
|
||||
data-lazy-l10n-id="toolbar-context-menu-remove-from-toolbar"/>
|
||||
|
@ -179,11 +179,11 @@
|
|||
<html:template id="customModeWrapper">
|
||||
<menupopup id="customizationPaletteItemContextMenu"
|
||||
onpopupshowing="gCustomizeMode.onPaletteContextMenuShowing(event)">
|
||||
<menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode)"
|
||||
<menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode, 'palette-context')"
|
||||
class="customize-context-addToToolbar"
|
||||
accesskey="&customizeMenu.addToToolbar.accesskey;"
|
||||
label="&customizeMenu.addToToolbar.label;"/>
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode, 'palette-context')"
|
||||
class="customize-context-addToPanel"
|
||||
accesskey="&customizeMenu.addToOverflowMenu.accesskey;"
|
||||
label="&customizeMenu.addToOverflowMenu.label;"/>
|
||||
|
@ -222,7 +222,7 @@
|
|||
descriptionheightworkaround="true">
|
||||
<vbox class="panel-subview-body">
|
||||
<vbox id="appMenu-addon-banners"/>
|
||||
<toolbarbutton class="panel-banner-item"
|
||||
<toolbarbutton id="appMenu-update-banner" class="panel-banner-item"
|
||||
label-update-available="&updateAvailable.panelUI.label;"
|
||||
label-update-manual="&updateManual.panelUI.label;"
|
||||
label-update-unsupported="&updateUnsupported.panelUI.label;"
|
||||
|
@ -530,6 +530,7 @@
|
|||
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.tabsnotsyncing.label;</label>
|
||||
<hbox pack="center">
|
||||
<toolbarbutton class="PanelUI-remotetabs-button"
|
||||
id="PanelUI-remotetabs-tabsdisabledpane-button"
|
||||
label="&appMenuRemoteTabs.opensyncprefs.label;"
|
||||
oncommand="gSync.openPrefs('synced-tabs');"/>
|
||||
</hbox>
|
||||
|
@ -565,6 +566,7 @@
|
|||
<image class="fxaSyncIllustration"/>
|
||||
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.welcome.label;</label>
|
||||
<toolbarbutton class="PanelUI-remotetabs-button"
|
||||
id="PanelUI-remotetabs-setupsync-button"
|
||||
label="&appMenuRemoteTabs.signintosync.label;"
|
||||
oncommand="gSync.openPrefs('synced-tabs');"/>
|
||||
</vbox>
|
||||
|
@ -577,6 +579,7 @@
|
|||
<image class="fxaSyncIllustration"/>
|
||||
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.welcome.label;</label>
|
||||
<toolbarbutton class="PanelUI-remotetabs-button"
|
||||
id="PanelUI-remotetabs-syncdisabled-button"
|
||||
label="&appMenuRemoteTabs.turnonsync.label;"
|
||||
oncommand="gSync.openPrefs('synced-tabs');"/>
|
||||
</vbox>
|
||||
|
@ -589,6 +592,7 @@
|
|||
<image class="fxaSyncIllustrationIssue"/>
|
||||
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.welcome.label;</label>
|
||||
<toolbarbutton class="PanelUI-remotetabs-button"
|
||||
id="PanelUI-remotetabs-reauthsync-button"
|
||||
label="&appMenuRemoteTabs.signintosync.label;"
|
||||
oncommand="gSync.openPrefs('synced-tabs');"/>
|
||||
</vbox>
|
||||
|
@ -601,6 +605,7 @@
|
|||
<image class="fxaSyncIllustrationIssue"/>
|
||||
<label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.unverified.label;</label>
|
||||
<toolbarbutton class="PanelUI-remotetabs-button"
|
||||
id="PanelUI-remotetabs-unverified-button"
|
||||
label="&appMenuRemoteTabs.opensyncprefs.label;"
|
||||
oncommand="gSync.openPrefs('synced-tabs');"/>
|
||||
</vbox>
|
||||
|
@ -699,7 +704,7 @@
|
|||
<!-- The rest of the values get dynamically inserted. The "presetsbuilt"
|
||||
attribute will get updated to "true" once the presets have been
|
||||
built. -->
|
||||
<menuitem label="Custom" value="custom"/>
|
||||
<menuitem id="PanelUI-profiler-presets-custom" label="Custom" value="custom"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<!-- The following description gets inserted dynamically. -->
|
||||
|
@ -963,7 +968,7 @@
|
|||
class="subviewbutton subviewbutton-iconic"
|
||||
label-show="&viewBookmarksToolbar.label;"
|
||||
label-hide="&hideBookmarksToolbar.label;"
|
||||
oncommand="BookmarkingUI.toggleBookmarksToolbar();"/>
|
||||
oncommand="BookmarkingUI.toggleBookmarksToolbar('bookmark-tools');"/>
|
||||
</vbox>
|
||||
</panelview>
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"url": "chrome://browser/content/parent/ext-browserAction.js",
|
||||
"schema": "chrome://extensions/content/schemas/browser_action.json",
|
||||
"scopes": ["addon_parent"],
|
||||
"events": ["update", "uninstall", "disable"],
|
||||
"manifest": ["browser_action"],
|
||||
"paths": [
|
||||
["browserAction"]
|
||||
|
@ -143,6 +144,7 @@
|
|||
"url": "chrome://browser/content/parent/ext-pageAction.js",
|
||||
"schema": "chrome://extensions/content/schemas/page_action.json",
|
||||
"scopes": ["addon_parent"],
|
||||
"events": ["update", "uninstall", "disable"],
|
||||
"manifest": ["page_action"],
|
||||
"paths": [
|
||||
["pageAction"]
|
||||
|
|
|
@ -31,6 +31,11 @@ ChromeUtils.defineModuleGetter(
|
|||
"ViewPopup",
|
||||
"resource:///modules/ExtensionPopups.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"BrowserUsageTelemetry",
|
||||
"resource:///modules/BrowserUsageTelemetry.jsm"
|
||||
);
|
||||
|
||||
var { DefaultWeakMap } = ExtensionUtils;
|
||||
|
||||
|
@ -57,6 +62,10 @@ XPCOMUtils.defineLazyGetter(this, "browserAreas", () => {
|
|||
};
|
||||
});
|
||||
|
||||
function actionWidgetId(widgetId) {
|
||||
return `${widgetId}-browser-action`;
|
||||
}
|
||||
|
||||
class BrowserAction extends BrowserActionBase {
|
||||
constructor(extension, buttonDelegate) {
|
||||
let tabContext = new TabContext(target => {
|
||||
|
@ -122,7 +131,7 @@ this.browserAction = class extends ExtensionAPI {
|
|||
);
|
||||
|
||||
let widgetId = makeWidgetId(extension.id);
|
||||
this.id = `${widgetId}-browser-action`;
|
||||
this.id = actionWidgetId(widgetId);
|
||||
this.viewId = `PanelUI-webext-${widgetId}-browser-action-view`;
|
||||
this.widget = null;
|
||||
|
||||
|
@ -138,6 +147,37 @@ this.browserAction = class extends ExtensionAPI {
|
|||
this.build();
|
||||
}
|
||||
|
||||
static onUpdate(id, manifest) {
|
||||
if (!("browser_action" in manifest)) {
|
||||
// If the new version has no browser action then mark this widget as
|
||||
// hidden in the telemetry. If it is already marked hidden then this will
|
||||
// do nothing.
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
actionWidgetId(makeWidgetId(id)),
|
||||
null,
|
||||
"addon"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static onDisable(id) {
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
actionWidgetId(makeWidgetId(id)),
|
||||
null,
|
||||
"addon"
|
||||
);
|
||||
}
|
||||
|
||||
static onUninstall(id) {
|
||||
// If the telemetry already has this widget as hidden then this will not
|
||||
// record anything.
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
actionWidgetId(makeWidgetId(id)),
|
||||
null,
|
||||
"addon"
|
||||
);
|
||||
}
|
||||
|
||||
onShutdown() {
|
||||
browserActionMap.delete(this.extension);
|
||||
this.action.onShutdown();
|
||||
|
@ -268,6 +308,19 @@ this.browserAction = class extends ExtensionAPI {
|
|||
},
|
||||
});
|
||||
|
||||
if (this.extension.startupReason != "APP_STARTUP") {
|
||||
// Make sure the browser telemetry has the correct state for this widget.
|
||||
// Defer loading BrowserUsageTelemetry until after startup is complete.
|
||||
ExtensionParent.browserStartupPromise.then(() => {
|
||||
let placement = CustomizableUI.getPlacementOfWidget(widget.id);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
widget.id,
|
||||
placement?.area || null,
|
||||
"addon"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
this.widget = widget;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,17 @@ ChromeUtils.defineModuleGetter(
|
|||
"PanelPopup",
|
||||
"resource:///modules/ExtensionPopups.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"BrowserUsageTelemetry",
|
||||
"resource:///modules/BrowserUsageTelemetry.jsm"
|
||||
);
|
||||
|
||||
var { DefaultWeakMap } = ExtensionUtils;
|
||||
|
||||
var { ExtensionParent } = ChromeUtils.import(
|
||||
"resource://gre/modules/ExtensionParent.jsm"
|
||||
);
|
||||
var { PageActionBase } = ChromeUtils.import(
|
||||
"resource://gre/modules/ExtensionActions.jsm"
|
||||
);
|
||||
|
@ -55,6 +63,25 @@ this.pageAction = class extends ExtensionAPI {
|
|||
return pageActionMap.get(extension);
|
||||
}
|
||||
|
||||
static onUpdate(id, manifest) {
|
||||
if (!("page_action" in manifest)) {
|
||||
// If the new version has no page action then mark this widget as hidden
|
||||
// in the telemetry. If it is already marked hidden then this will do
|
||||
// nothing.
|
||||
BrowserUsageTelemetry.recordWidgetChange(makeWidgetId(id), null, "addon");
|
||||
}
|
||||
}
|
||||
|
||||
static onDisable(id) {
|
||||
BrowserUsageTelemetry.recordWidgetChange(makeWidgetId(id), null, "addon");
|
||||
}
|
||||
|
||||
static onUninstall(id) {
|
||||
// If the telemetry already has this widget as hidden then this will not
|
||||
// record anything.
|
||||
BrowserUsageTelemetry.recordWidgetChange(makeWidgetId(id), null, "addon");
|
||||
}
|
||||
|
||||
async onManifestEntry(entryName) {
|
||||
let { extension } = this;
|
||||
let options = extension.manifest.page_action;
|
||||
|
@ -127,6 +154,20 @@ this.pageAction = class extends ExtensionAPI {
|
|||
})
|
||||
);
|
||||
|
||||
if (this.extension.startupReason != "APP_STARTUP") {
|
||||
// Make sure the browser telemetry has the correct state for this widget.
|
||||
// Defer loading BrowserUsageTelemetry until after startup is complete.
|
||||
ExtensionParent.browserStartupPromise.then(() => {
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
widgetId,
|
||||
this.browserPageAction.pinnedToUrlbar
|
||||
? "page-action-buttons"
|
||||
: null,
|
||||
"addon"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// If the page action is only enabled in some URLs, do pattern matching in
|
||||
// the active tabs and update the button if necessary.
|
||||
if (this.action.getProperty(null, "enabled") === undefined) {
|
||||
|
|
|
@ -59,6 +59,11 @@ ChromeUtils.defineModuleGetter(
|
|||
"UpdateUtils",
|
||||
"resource://gre/modules/UpdateUtils.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"BrowserUsageTelemetry",
|
||||
"resource:///modules/BrowserUsageTelemetry.jsm"
|
||||
);
|
||||
|
||||
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
|
||||
const PREF_LOG_LEVEL = "browser.uitour.loglevel";
|
||||
|
@ -2003,6 +2008,11 @@ var UITour = {
|
|||
aTarget.widgetName,
|
||||
CustomizableUI.AREA_NAVBAR
|
||||
);
|
||||
BrowserUsageTelemetry.recordWidgetChange(
|
||||
aTarget.widgetName,
|
||||
CustomizableUI.AREA_NAVBAR,
|
||||
"uitour"
|
||||
);
|
||||
this.sendPageCallback(aBrowser, aCallbackID);
|
||||
},
|
||||
|
||||
|
|
|
@ -1889,6 +1889,7 @@ class UrlbarInput {
|
|||
}
|
||||
|
||||
let pasteAndGo = this.document.createXULElement("menuitem");
|
||||
pasteAndGo.id = "paste-and-go";
|
||||
let label = Services.strings
|
||||
.createBundle("chrome://browser/locale/browser.properties")
|
||||
.GetStringFromName("pasteAndGo.label");
|
||||
|
|
|
@ -16,9 +16,9 @@ As the transition to the ``BrowserUsageTelemetry`` happens, the ``recordSearch``
|
|||
|
||||
A list of the components recording search Telemetry can be found using the following `DXR search <https://dxr.mozilla.org/mozilla-central/search?q=recordSearchInTelemetry>`_.
|
||||
|
||||
Measured interactions
|
||||
=====================
|
||||
The usage telemetry module currently measures these interactions with the browser:
|
||||
Tab and window interactions
|
||||
===========================
|
||||
The usage telemetry module currently measures these interactions with the browser's tabs and windows:
|
||||
|
||||
- *tab and window engagement*: counts the number of non-private tabs and windows opened in a subsession, after the session is restored (see e.g. ``browser.engagement.max_concurrent_tab_count``);
|
||||
- *URI loads*: counts the number of page loads (doesn't track and send the addresses, just the counts) directly triggered by the users (see ``browser.engagement.total_uri_count``);
|
||||
|
@ -26,3 +26,96 @@ The usage telemetry module currently measures these interactions with the browse
|
|||
|
||||
|
||||
Please see `Scalars.yaml <https://dxr.mozilla.org/mozilla-central/source/toolkit/components/telemetry/Scalars.yaml>`_ for the full list of tracked interactions.
|
||||
|
||||
Customizable UI
|
||||
===============
|
||||
|
||||
This telemetry records information about the positions of toolbar items and when
|
||||
the user interacts with them. It is submitted as scalar values along with the
|
||||
normal telemetry ping. There are a number of different parts to this telemetry:
|
||||
|
||||
UI Areas
|
||||
--------
|
||||
|
||||
For the purposes of this telemetry a set of areas are defined:
|
||||
|
||||
* In the main browser UI:
|
||||
|
||||
* ``menu-bar`` - The main menu.
|
||||
* ``menu-toolbar`` - The normally hidden toolbar that holds the main menu.
|
||||
* ``drag-space`` - The optional drag space.
|
||||
* ``titlebar`` - The optional title bar.
|
||||
* ``tabs-bar`` - The area where tabs are displayed.
|
||||
* ``bookmarks-bar`` - The bookmarks toolbar.
|
||||
* ``app-menu`` - The main application (hamburger) menu.
|
||||
* ``tabs-context`` - The context menu shown from right-clicking a tab.
|
||||
* ``content-context`` - The context menu shown from right-clicking the web page.
|
||||
* ``widget-overflow-list`` - Items that have overflowed the available space.
|
||||
* ``pinned-overflow-menu`` - Items that the user has pinned to the toolbar overflow menu.
|
||||
* ``pageaction-urlbar`` - Page actions buttons in the address bar.
|
||||
* ``pageaction-panel`` - The page action (meatball) menu.
|
||||
* ``nav-bar-start`` - The area of the navigation toolbar before the address bar.
|
||||
* ``nav-bar-end`` - The area of the navigastion toolbar after the address bar.
|
||||
|
||||
* In ``about:preferences`` the different cagtegories are used:
|
||||
|
||||
* ``preferences-paneGeneral``
|
||||
* ``preferences-paneHome``
|
||||
* ``preferences-panePrivacy``
|
||||
* ``preferences-paneSearch``
|
||||
* ``preferences-paneSearchResults``
|
||||
* ``preferences-paneSync``
|
||||
* ``preferences-paneContainers``
|
||||
|
||||
Widget Identifiers
|
||||
------------------
|
||||
|
||||
In order to uniquely identify a visual element a set of heuristics are used:
|
||||
|
||||
#. If the element is one of the customizable toolbar items then that item's ID
|
||||
is used.
|
||||
#. If the DOM element has an ID set then that is used.
|
||||
#. If the DOM element's class contains one of ``bookmark-item``,
|
||||
``tab-icon-sound`` or ``tab-close-button`` then that is used.
|
||||
#. If the DOM element has a ``preference`` ``key``, ``command``, ``observes`` or
|
||||
``data-l10n-id`` attribute then that is used.
|
||||
#. If there is still no identifier then this is repeated for the DOM element's
|
||||
parent element.
|
||||
|
||||
Widget Locations
|
||||
----------------
|
||||
|
||||
The keyed scalar ``browser.ui.toolbar_widgets`` records the position of widgets in
|
||||
the UI. At startup the positions of widgets are collected and recorded by
|
||||
setting the scalar key ``<widget id>_pinned_<area>`` to true. The widget ID are
|
||||
the IDs of the elements in the DOM. The area is one of the areas listed above
|
||||
from the browser UI that can be customised.
|
||||
|
||||
For the areas that can be controlled the scalar keys ``<area>_<off/on>`` are set.
|
||||
|
||||
Widget Customization
|
||||
--------------------
|
||||
|
||||
The scalar ``browser.ui.customized_widgets`` records whenever the user moves a
|
||||
widget around the toolbars or shows or hides some of the areas. When a change
|
||||
occurs the scalar with the key ``<widget id>_<action>_<old area>_<new area>_<reason>``
|
||||
is incremented. The action can be one of ``move``, ``add`` or ``remove``. Old
|
||||
area and new area are the previous and now locations of the widget. In the case
|
||||
of ``add`` or ``remove`` actions one of the areas will be ``na``. For areas that
|
||||
can be shown or hidden the areas will be ``off`` or ``on``. The reason is a simple
|
||||
string that indicates what caused the move to happen (drag, context menu, etc.).
|
||||
|
||||
UI Interactions
|
||||
---------------
|
||||
|
||||
The scalars ``browser.ui.interaction.<area>`` record how often the use
|
||||
interacts with the browser. The area is one of those above with the addition of
|
||||
``keyboard`` for keyboard shortcuts.
|
||||
|
||||
When an interaction occurs the widget's identifier is used as the key and the
|
||||
scalar is incremented. If the widget is provided by an add-on then the add-on
|
||||
identifier is dropped and an identifier of the form ``addonX`` is used where X
|
||||
is a number. The number used is stable for a single session. Everytime the user
|
||||
moves or interacts with an add-on the same number is used but then the numbers
|
||||
for each add-on may change after Firefox has been restarted.
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
CustomizableUI: "resource:///modules/CustomizableUI.jsm",
|
||||
PageActions: "resource:///modules/PageActions.jsm",
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
||||
SearchTelemetry: "resource:///modules/SearchTelemetry.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
|
@ -118,6 +121,80 @@ const URLBAR_SELECTED_RESULT_METHODS = {
|
|||
|
||||
const MINIMUM_TAB_COUNT_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes, in ms
|
||||
|
||||
// The elements we consider to be interactive.
|
||||
const UI_TARGET_ELEMENTS = [
|
||||
"menuitem",
|
||||
"toolbarbutton",
|
||||
"key",
|
||||
"command",
|
||||
"checkbox",
|
||||
"input",
|
||||
"button",
|
||||
"image",
|
||||
"radio",
|
||||
"richlistitem",
|
||||
];
|
||||
|
||||
// The containers of interactive elements that we care about and their pretty
|
||||
// names. These should be listed in order of most-specific to least-specific,
|
||||
// when iterating JavaScript will guarantee that ordering and so we will find
|
||||
// the most specific area first.
|
||||
const BROWSER_UI_CONTAINER_IDS = {
|
||||
"toolbar-menubar": "menu-bar",
|
||||
TabsToolbar: "tabs-bar",
|
||||
PersonalToolbar: "bookmarks-bar",
|
||||
"appMenu-popup": "app-menu",
|
||||
tabContextMenu: "tabs-context",
|
||||
contentAreaContextMenu: "content-context",
|
||||
"widget-overflow-list": "overflow-menu",
|
||||
"widget-overflow-fixed-list": "pinned-overflow-menu",
|
||||
"page-action-buttons": "pageaction-urlbar",
|
||||
pageActionPanel: "pageaction-panel",
|
||||
|
||||
// This should appear last as some of the above are inside the nav bar.
|
||||
"nav-bar": "nav-bar",
|
||||
};
|
||||
|
||||
const IGNORABLE_EVENTS = new WeakMap();
|
||||
|
||||
const KNOWN_ADDONS = [];
|
||||
|
||||
function telemetryId(widgetId, obscureAddons = true) {
|
||||
// Add-on IDs need to be obscured.
|
||||
function addonId(id) {
|
||||
if (!obscureAddons) {
|
||||
return id;
|
||||
}
|
||||
|
||||
let pos = KNOWN_ADDONS.indexOf(id);
|
||||
if (pos < 0) {
|
||||
pos = KNOWN_ADDONS.length;
|
||||
KNOWN_ADDONS.push(id);
|
||||
}
|
||||
return `addon${pos}`;
|
||||
}
|
||||
|
||||
if (widgetId.endsWith("-browser-action")) {
|
||||
widgetId = addonId(
|
||||
widgetId.substring(0, widgetId.length - "-browser-action".length)
|
||||
);
|
||||
} else if (widgetId.startsWith("pageAction-")) {
|
||||
let actionId;
|
||||
if (widgetId.startsWith("pageAction-urlbar-")) {
|
||||
actionId = widgetId.substring("pageAction-urlbar-".length);
|
||||
} else if (widgetId.startsWith("pageAction-panel-")) {
|
||||
actionId = widgetId.substring("pageAction-panel-".length);
|
||||
}
|
||||
|
||||
if (actionId) {
|
||||
let action = PageActions.actionForID(actionId);
|
||||
widgetId = action?._isMozillaAction ? actionId : addonId(actionId);
|
||||
}
|
||||
}
|
||||
|
||||
return widgetId.replace(/_/g, "-");
|
||||
}
|
||||
|
||||
function getOpenTabsAndWinsCounts() {
|
||||
let loadedTabCount = 0;
|
||||
let tabCount = 0;
|
||||
|
@ -337,6 +414,18 @@ let BrowserUsageTelemetry = {
|
|||
this._lastRecordLoadedTabCount = 0;
|
||||
this._setupAfterRestore();
|
||||
this._inited = true;
|
||||
|
||||
Services.prefs.addObserver("browser.tabs.extraDragSpace", this);
|
||||
Services.prefs.addObserver("browser.tabs.drawInTitlebar", this);
|
||||
|
||||
this._recordUITelemetry();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the masked add-on identifiers. Only for use in tests.
|
||||
*/
|
||||
_resetAddonIds() {
|
||||
KNOWN_ADDONS.length = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -381,6 +470,28 @@ let BrowserUsageTelemetry = {
|
|||
case TELEMETRY_SUBSESSIONSPLIT_TOPIC:
|
||||
this.afterSubsessionSplit();
|
||||
break;
|
||||
case "nsPref:changed":
|
||||
switch (data) {
|
||||
case "browser.tabs.extraDragSpace":
|
||||
this._recordWidgetChange(
|
||||
"drag-space",
|
||||
Services.prefs.getBoolPref("browser.tabs.extraDragSpace")
|
||||
? "on"
|
||||
: "off",
|
||||
"pref"
|
||||
);
|
||||
break;
|
||||
case "browser.tabs.drawInTitlebar":
|
||||
this._recordWidgetChange(
|
||||
"titlebar",
|
||||
Services.prefs.getBoolPref("browser.tabs.drawInTitlebar")
|
||||
? "off"
|
||||
: "on",
|
||||
"pref"
|
||||
);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -669,10 +780,367 @@ let BrowserUsageTelemetry = {
|
|||
);
|
||||
},
|
||||
|
||||
_buildWidgetPositions() {
|
||||
let widgetMap = new Map();
|
||||
|
||||
const toolbarState = nodeId => {
|
||||
let value = Services.xulStore.getValue(
|
||||
AppConstants.BROWSER_CHROME_URL,
|
||||
nodeId,
|
||||
"collapsed"
|
||||
);
|
||||
if (value) {
|
||||
return value == "true" ? "off" : "on";
|
||||
}
|
||||
return "off";
|
||||
};
|
||||
|
||||
widgetMap.set(
|
||||
BROWSER_UI_CONTAINER_IDS.PersonalToolbar,
|
||||
toolbarState("PersonalToolbar")
|
||||
);
|
||||
|
||||
let menuBarHidden =
|
||||
Services.xulStore.getValue(
|
||||
AppConstants.BROWSER_CHROME_URL,
|
||||
"toolbar-menubar",
|
||||
"autohide"
|
||||
) != "false";
|
||||
|
||||
widgetMap.set("menu-toolbar", menuBarHidden ? "off" : "on");
|
||||
|
||||
widgetMap.set(
|
||||
"drag-space",
|
||||
Services.prefs.getBoolPref("browser.tabs.extraDragSpace") ? "on" : "off"
|
||||
);
|
||||
|
||||
// Drawing in the titlebar means not showing the titlebar, hence the negation.
|
||||
widgetMap.set(
|
||||
"titlebar",
|
||||
Services.prefs.getBoolPref("browser.tabs.drawInTitlebar", true)
|
||||
? "off"
|
||||
: "on"
|
||||
);
|
||||
|
||||
for (let area of CustomizableUI.areas) {
|
||||
if (!(area in BROWSER_UI_CONTAINER_IDS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let position = BROWSER_UI_CONTAINER_IDS[area];
|
||||
if (area == "nav-bar") {
|
||||
position = `${BROWSER_UI_CONTAINER_IDS[area]}-start`;
|
||||
}
|
||||
|
||||
let widgets = CustomizableUI.getWidgetsInArea(area);
|
||||
|
||||
for (let widget of widgets) {
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (widget.id.startsWith("customizableui-special-")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (area == "nav-bar" && widget.id == "urlbar-container") {
|
||||
position = `${BROWSER_UI_CONTAINER_IDS[area]}-end`;
|
||||
continue;
|
||||
}
|
||||
|
||||
widgetMap.set(widget.id, position);
|
||||
}
|
||||
}
|
||||
|
||||
let actions = PageActions.actions;
|
||||
for (let action of actions) {
|
||||
if (action.pinnedToUrlbar) {
|
||||
widgetMap.set(action.id, "pageaction-urlbar");
|
||||
}
|
||||
}
|
||||
|
||||
return widgetMap;
|
||||
},
|
||||
|
||||
_getWidgetID(node) {
|
||||
// We want to find a sensible ID for this element.
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// See if this is a customizable widget.
|
||||
if (node.ownerDocument.URL == AppConstants.BROWSER_CHROME_URL) {
|
||||
// First find if it is inside one of the customizable areas.
|
||||
for (let area of CustomizableUI.areas) {
|
||||
if (node.closest(`#${area}`)) {
|
||||
for (let widget of CustomizableUI.getWidgetIdsInArea(area)) {
|
||||
if (
|
||||
// We care about the buttons on the tabs themselves.
|
||||
widget == "tabbrowser-tabs" ||
|
||||
// We care about the page action and other buttons in here.
|
||||
widget == "urlbar-container" ||
|
||||
// We care about individual bookmarks here.
|
||||
widget == "personal-bookmarks"
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.closest(`#${widget}`)) {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.id) {
|
||||
return node.id;
|
||||
}
|
||||
|
||||
// A couple of special cases in the tabs.
|
||||
for (let cls of ["bookmark-item", "tab-icon-sound", "tab-close-button"]) {
|
||||
if (node.classList.contains(cls)) {
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
|
||||
// One of these will at least let us know what the widget is for.
|
||||
for (let idAttribute of [
|
||||
"preference",
|
||||
"key",
|
||||
"command",
|
||||
"observes",
|
||||
"data-l10n-id",
|
||||
]) {
|
||||
if (node.hasAttribute(idAttribute)) {
|
||||
return node.getAttribute(idAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
return this._getWidgetID(node.parentElement);
|
||||
},
|
||||
|
||||
_getWidgetContainer(node) {
|
||||
if (node.localName == "key") {
|
||||
return "keyboard";
|
||||
}
|
||||
|
||||
if (node.ownerDocument.URL == AppConstants.BROWSER_CHROME_URL) {
|
||||
// Find the container holding this element.
|
||||
for (let containerId of Object.keys(BROWSER_UI_CONTAINER_IDS)) {
|
||||
let container = node.ownerDocument.getElementById(containerId);
|
||||
if (container && container.contains(node)) {
|
||||
return BROWSER_UI_CONTAINER_IDS[containerId];
|
||||
}
|
||||
}
|
||||
} else if (node.ownerDocument.URL.startsWith("about:preferences")) {
|
||||
// Find the element's category.
|
||||
let container = node.closest("[data-category]");
|
||||
if (!container) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `preferences_${container.getAttribute("data-category")}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
lastClickTarget: null,
|
||||
|
||||
ignoreEvent(event) {
|
||||
IGNORABLE_EVENTS.set(event, true);
|
||||
},
|
||||
|
||||
_recordCommand(event) {
|
||||
if (IGNORABLE_EVENTS.get(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let types = [event.type];
|
||||
let sourceEvent = event;
|
||||
while (sourceEvent.sourceEvent) {
|
||||
sourceEvent = sourceEvent.sourceEvent;
|
||||
types.push(sourceEvent.type);
|
||||
}
|
||||
|
||||
let lastTarget = this.lastClickTarget?.get();
|
||||
if (
|
||||
lastTarget &&
|
||||
sourceEvent.type == "command" &&
|
||||
sourceEvent.target.contains(lastTarget)
|
||||
) {
|
||||
// Ignore a command event triggered by a click.
|
||||
this.lastClickTarget = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastClickTarget = null;
|
||||
|
||||
if (sourceEvent.type == "click") {
|
||||
// Only care about main button clicks.
|
||||
if (sourceEvent.button != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This click may trigger a command event so retain the target to be able
|
||||
// to dedupe that event.
|
||||
this.lastClickTarget = Cu.getWeakReference(sourceEvent.target);
|
||||
}
|
||||
|
||||
// We should never see events from web content as they are fired in a
|
||||
// content process, but let's be safe.
|
||||
let url = sourceEvent.target.ownerDocument.documentURIObject;
|
||||
if (!url.schemeIs("chrome") && !url.schemeIs("about")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is what events targetted at content will actually look like.
|
||||
if (sourceEvent.target.localName == "browser") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the actual element we're interested in.
|
||||
let node = sourceEvent.target;
|
||||
while (!UI_TARGET_ELEMENTS.includes(node.localName)) {
|
||||
node = node.parentNode;
|
||||
if (!node) {
|
||||
// A click on a space or label or something we're not interested in.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let item = this._getWidgetID(node);
|
||||
let source = this._getWidgetContainer(node);
|
||||
|
||||
if (item && source) {
|
||||
let scalar = `browser.ui.interaction.${source.replace("-", "_")}`;
|
||||
Services.telemetry.keyedScalarAdd(scalar, telemetryId(item), 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens for UI interactions in the window.
|
||||
*/
|
||||
_addUsageListeners(win) {
|
||||
// Listen for command events from the UI.
|
||||
win.addEventListener("command", event => this._recordCommand(event), true);
|
||||
win.addEventListener("click", event => this._recordCommand(event), true);
|
||||
},
|
||||
|
||||
/**
|
||||
* A public version of the private method to take care of the `nav-bar-start`,
|
||||
* `nav-bar-end` thing that callers shouldn't have to care about. It also
|
||||
* accepts the DOM ids for the areas rather than the cleaner ones we report
|
||||
* to telemetry.
|
||||
*/
|
||||
recordWidgetChange(widgetId, newPos, reason) {
|
||||
try {
|
||||
if (newPos) {
|
||||
newPos = BROWSER_UI_CONTAINER_IDS[newPos];
|
||||
}
|
||||
|
||||
if (newPos == "nav-bar") {
|
||||
let { position } = CustomizableUI.getPlacementOfWidget(widgetId);
|
||||
let { position: urlPosition } = CustomizableUI.getPlacementOfWidget(
|
||||
"urlbar-container"
|
||||
);
|
||||
newPos = newPos + (urlPosition > position ? "-start" : "-end");
|
||||
}
|
||||
|
||||
this._recordWidgetChange(widgetId, newPos, reason);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
|
||||
recordToolbarVisibility(toolbarId, newState, reason) {
|
||||
this._recordWidgetChange(
|
||||
BROWSER_UI_CONTAINER_IDS[toolbarId],
|
||||
newState ? "on" : "off",
|
||||
reason
|
||||
);
|
||||
},
|
||||
|
||||
_recordWidgetChange(widgetId, newPos, reason) {
|
||||
// In some cases (like when add-ons are detected during startup) this gets
|
||||
// called before we've reported the initial positions. Ignore such cases.
|
||||
if (!this.widgetMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (widgetId == "urlbar-container") {
|
||||
// We don't report the position of the url bar, it is after nav-bar-start
|
||||
// and before nav-bar-end. But moving it means the widgets around it have
|
||||
// effectively moved so update those.
|
||||
let position = "nav-bar-start";
|
||||
let widgets = CustomizableUI.getWidgetsInArea("nav-bar");
|
||||
|
||||
for (let widget of widgets) {
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (widget.id.startsWith("customizableui-special-")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (widget.id == "urlbar-container") {
|
||||
position = "nav-bar-end";
|
||||
continue;
|
||||
}
|
||||
|
||||
// This will do nothing if the position hasn't changed.
|
||||
this._recordWidgetChange(widget.id, position, reason);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let oldPos = this.widgetMap.get(widgetId);
|
||||
if (oldPos == newPos) {
|
||||
return;
|
||||
}
|
||||
|
||||
let action = "move";
|
||||
|
||||
if (!oldPos) {
|
||||
action = "add";
|
||||
} else if (!newPos) {
|
||||
action = "remove";
|
||||
}
|
||||
|
||||
let key = `${telemetryId(widgetId, false)}_${action}_${oldPos ??
|
||||
"na"}_${newPos ?? "na"}_${reason}`;
|
||||
Services.telemetry.keyedScalarAdd("browser.ui.customized_widgets", key, 1);
|
||||
|
||||
if (newPos) {
|
||||
this.widgetMap.set(widgetId, newPos);
|
||||
} else {
|
||||
this.widgetMap.delete(widgetId);
|
||||
}
|
||||
},
|
||||
|
||||
_recordUITelemetry() {
|
||||
this.widgetMap = this._buildWidgetPositions();
|
||||
|
||||
for (let [widgetId, position] of this.widgetMap.entries()) {
|
||||
let key = `${telemetryId(widgetId, false)}_pinned_${position}`;
|
||||
Services.telemetry.keyedScalarSet(
|
||||
"browser.ui.toolbar_widgets",
|
||||
key,
|
||||
true
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds listeners to a single chrome window.
|
||||
*/
|
||||
_registerWindow(win) {
|
||||
this._addUsageListeners(win);
|
||||
|
||||
win.addEventListener("unload", this);
|
||||
win.addEventListener("TabOpen", this, true);
|
||||
win.addEventListener("TabPinned", this, true);
|
||||
|
|
|
@ -41,8 +41,10 @@ skip-if = fission && !webrender # Two startup notifications, this confuses the t
|
|||
skip-if = (os == "mac") || (!debug && os == "linux" && bits == 64 && os_version == "18.04") # Bug 1528429
|
||||
[browser_UsageTelemetry.js]
|
||||
[browser_UsageTelemetry_domains.js]
|
||||
[browser_UsageTelemetry_interaction.js]
|
||||
[browser_UsageTelemetry_private_and_restore.js]
|
||||
skip-if = verify && debug
|
||||
[browser_UsageTelemetry_toolbars.js]
|
||||
[browser_UsageTelemetry_uniqueOriginsVisitedInPast24Hours.js]
|
||||
[browser_UsageTelemetry_urlbar_extension.js]
|
||||
[browser_UsageTelemetry_urlbar_places.js]
|
||||
|
|
|
@ -0,0 +1,399 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
gReduceMotionOverride = true;
|
||||
|
||||
const AREAS = [
|
||||
"keyboard",
|
||||
"menu_bar",
|
||||
"tabs_bar",
|
||||
"nav_bar",
|
||||
"bookmarks_bar",
|
||||
"app_menu",
|
||||
"tabs_context",
|
||||
"content_context",
|
||||
"overflow_menu",
|
||||
"pinned_overflow_menu",
|
||||
"pageaction_urlbar",
|
||||
"pageaction_panel",
|
||||
|
||||
"preferences_paneHome",
|
||||
"preferences_paneGeneral",
|
||||
"preferences_panePrivacy",
|
||||
"preferences_paneSearch",
|
||||
"preferences_paneSearchResults",
|
||||
"preferences_paneSync",
|
||||
"preferences_paneContainers",
|
||||
];
|
||||
|
||||
// Checks that the correct number of clicks are registered against the correct
|
||||
// keys in the scalars.
|
||||
function assertInteractionScalars(expectedAreas) {
|
||||
let processScalars =
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true)?.parent ?? {};
|
||||
|
||||
for (let source of AREAS) {
|
||||
let scalars = processScalars?.[`browser.ui.interaction.${source}`] ?? {};
|
||||
|
||||
let expected = expectedAreas[source] ?? {};
|
||||
|
||||
let expectedKeys = new Set(
|
||||
Object.keys(scalars).concat(Object.keys(expected))
|
||||
);
|
||||
for (let key of expectedKeys) {
|
||||
Assert.equal(
|
||||
scalars[key],
|
||||
expected[key],
|
||||
`Expected to see the correct value for ${key} in ${source}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const elem = id => document.getElementById(id);
|
||||
const click = el => {
|
||||
if (typeof el == "string") {
|
||||
el = elem(el);
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(el, {}, window);
|
||||
};
|
||||
|
||||
add_task(async function toolbarButtons() {
|
||||
await BrowserTestUtils.withNewTab("http://example.com", async () => {
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true);
|
||||
|
||||
let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
|
||||
let tabClose = BrowserTestUtils.waitForTabClosing(newTab);
|
||||
|
||||
let transition = BrowserTestUtils.waitForTransition(
|
||||
elem("PersonalToolbar")
|
||||
);
|
||||
CustomizableUI.setToolbarVisibility("PersonalToolbar", true);
|
||||
registerCleanupFunction(() => {
|
||||
CustomizableUI.setToolbarVisibility("PersonalToolbar", false);
|
||||
});
|
||||
await transition;
|
||||
|
||||
let tabs = elem("tabbrowser-tabs");
|
||||
if (!tabs.hasAttribute("overflow")) {
|
||||
tabs.setAttribute("overflow", "true");
|
||||
registerCleanupFunction(() => {
|
||||
tabs.removeAttribute("overflow");
|
||||
});
|
||||
}
|
||||
|
||||
click("stop-reload-button");
|
||||
click("back-button");
|
||||
click("back-button");
|
||||
|
||||
// Make sure the all tabs panel is in the document.
|
||||
gTabsPanel.initElements();
|
||||
let view = elem("allTabsMenu-allTabsView");
|
||||
let shown = BrowserTestUtils.waitForEvent(view, "ViewShown");
|
||||
click("alltabs-button");
|
||||
await shown;
|
||||
|
||||
let hidden = BrowserTestUtils.waitForEvent(view, "ViewHiding");
|
||||
gTabsPanel.hideAllTabsPanel();
|
||||
await hidden;
|
||||
|
||||
click(newTab.querySelector(".tab-close-button"));
|
||||
await tabClose;
|
||||
click(document.querySelector("#PlacesToolbarItems .bookmark-item"));
|
||||
|
||||
let pagePanel = elem("pageActionPanel");
|
||||
shown = BrowserTestUtils.waitForEvent(pagePanel, "popupshown");
|
||||
click("pageActionButton");
|
||||
await shown;
|
||||
|
||||
hidden = BrowserTestUtils.waitForEvent(pagePanel, "popuphidden");
|
||||
click("pageAction-panel-copyURL");
|
||||
await hidden;
|
||||
|
||||
assertInteractionScalars({
|
||||
nav_bar: {
|
||||
"stop-reload-button": 1,
|
||||
"back-button": 2,
|
||||
},
|
||||
tabs_bar: {
|
||||
"alltabs-button": 1,
|
||||
"tab-close-button": 1,
|
||||
},
|
||||
bookmarks_bar: {
|
||||
"bookmark-item": 1,
|
||||
},
|
||||
pageaction_urlbar: {
|
||||
pageActionButton: 1,
|
||||
},
|
||||
pageaction_panel: {
|
||||
copyURL: 1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function contextMenu() {
|
||||
await BrowserTestUtils.withNewTab("http://example.com", async browser => {
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true);
|
||||
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
let context = elem("tabContextMenu");
|
||||
let shown = BrowserTestUtils.waitForEvent(context, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
tab,
|
||||
{ type: "contextmenu", button: 2 },
|
||||
window
|
||||
);
|
||||
await shown;
|
||||
|
||||
let hidden = BrowserTestUtils.waitForEvent(context, "popuphidden");
|
||||
click("context_toggleMuteTab");
|
||||
await hidden;
|
||||
|
||||
assertInteractionScalars({
|
||||
tabs_context: {
|
||||
"context-toggleMuteTab": 1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function appMenu() {
|
||||
await BrowserTestUtils.withNewTab("http://example.com", async browser => {
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true);
|
||||
|
||||
let shown = BrowserTestUtils.waitForEvent(
|
||||
elem("appMenu-popup"),
|
||||
"popupshown"
|
||||
);
|
||||
click("PanelUI-menu-button");
|
||||
await shown;
|
||||
|
||||
let hidden = BrowserTestUtils.waitForEvent(
|
||||
elem("appMenu-popup"),
|
||||
"popuphidden"
|
||||
);
|
||||
click("appMenu-find-button");
|
||||
await hidden;
|
||||
|
||||
assertInteractionScalars({
|
||||
nav_bar: {
|
||||
"PanelUI-menu-button": 1,
|
||||
},
|
||||
app_menu: {
|
||||
"appMenu-find-button": 1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function devtools() {
|
||||
await BrowserTestUtils.withNewTab("http://example.com", async browser => {
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true);
|
||||
|
||||
let shown = BrowserTestUtils.waitForEvent(
|
||||
elem("appMenu-popup"),
|
||||
"popupshown"
|
||||
);
|
||||
click("PanelUI-menu-button");
|
||||
await shown;
|
||||
|
||||
shown = BrowserTestUtils.waitForEvent(
|
||||
elem("PanelUI-developer"),
|
||||
"ViewShown"
|
||||
);
|
||||
click("appMenu-developer-button");
|
||||
await shown;
|
||||
|
||||
let tabOpen = BrowserTestUtils.waitForNewTab(gBrowser);
|
||||
let hidden = BrowserTestUtils.waitForEvent(
|
||||
elem("appMenu-popup"),
|
||||
"popuphidden"
|
||||
);
|
||||
click(
|
||||
document.querySelector(
|
||||
"#PanelUI-developer toolbarbutton[key='key_viewSource']"
|
||||
)
|
||||
);
|
||||
await hidden;
|
||||
|
||||
let tab = await tabOpen;
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
|
||||
// Note that item ID's have '_' converted to '-'.
|
||||
assertInteractionScalars({
|
||||
nav_bar: {
|
||||
"PanelUI-menu-button": 1,
|
||||
},
|
||||
app_menu: {
|
||||
"appMenu-developer-button": 1,
|
||||
"key-viewSource": 1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function webextension() {
|
||||
BrowserUsageTelemetry._resetAddonIds();
|
||||
|
||||
await BrowserTestUtils.withNewTab("http://example.com", async browser => {
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true);
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
version: "1",
|
||||
applications: {
|
||||
gecko: { id: "random_addon@example.com" },
|
||||
},
|
||||
browser_action: {
|
||||
default_icon: "default.png",
|
||||
default_title: "Hello",
|
||||
},
|
||||
page_action: {
|
||||
default_icon: "default.png",
|
||||
default_title: "Hello",
|
||||
show_matches: ["http://example.com/*"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
// As the first add-on interacted with this should show up as `addon0`.
|
||||
|
||||
click("random_addon_example_com-browser-action");
|
||||
assertInteractionScalars({
|
||||
nav_bar: {
|
||||
addon0: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for the element to show up.
|
||||
await TestUtils.waitForCondition(() =>
|
||||
elem("pageAction-urlbar-random_addon_example_com")
|
||||
);
|
||||
|
||||
click("pageAction-urlbar-random_addon_example_com");
|
||||
assertInteractionScalars({
|
||||
pageaction_urlbar: {
|
||||
addon0: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const extension2 = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
version: "1",
|
||||
applications: {
|
||||
gecko: { id: "random_addon2@example.com" },
|
||||
},
|
||||
browser_action: {
|
||||
default_icon: "default.png",
|
||||
default_title: "Hello",
|
||||
},
|
||||
page_action: {
|
||||
default_icon: "default.png",
|
||||
default_title: "Hello",
|
||||
show_matches: ["http://example.com/*"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await extension2.startup();
|
||||
|
||||
// A second extension should be `addon1`.
|
||||
|
||||
click("random_addon2_example_com-browser-action");
|
||||
assertInteractionScalars({
|
||||
nav_bar: {
|
||||
addon1: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for the element to show up.
|
||||
await TestUtils.waitForCondition(() =>
|
||||
elem("pageAction-urlbar-random_addon2_example_com")
|
||||
);
|
||||
|
||||
click("pageAction-urlbar-random_addon2_example_com");
|
||||
assertInteractionScalars({
|
||||
pageaction_urlbar: {
|
||||
addon1: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// The first should have retained its ID.
|
||||
click("random_addon_example_com-browser-action");
|
||||
assertInteractionScalars({
|
||||
nav_bar: {
|
||||
addon0: 1,
|
||||
},
|
||||
});
|
||||
|
||||
click("pageAction-urlbar-random_addon_example_com");
|
||||
assertInteractionScalars({
|
||||
pageaction_urlbar: {
|
||||
addon0: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await extension.unload();
|
||||
|
||||
// The second should retain its ID.
|
||||
click("random_addon2_example_com-browser-action");
|
||||
click("random_addon2_example_com-browser-action");
|
||||
assertInteractionScalars({
|
||||
nav_bar: {
|
||||
addon1: 2,
|
||||
},
|
||||
});
|
||||
|
||||
click("pageAction-urlbar-random_addon2_example_com");
|
||||
assertInteractionScalars({
|
||||
pageaction_urlbar: {
|
||||
addon1: 1,
|
||||
},
|
||||
});
|
||||
|
||||
await extension2.unload();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function preferences() {
|
||||
let initialized = BrowserTestUtils.waitForEvent(gBrowser, "Initialized");
|
||||
await BrowserTestUtils.withNewTab("about:preferences", async browser => {
|
||||
await initialized;
|
||||
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true);
|
||||
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter(
|
||||
"#browserRestoreSession",
|
||||
{},
|
||||
gBrowser.selectedBrowser.browsingContext
|
||||
);
|
||||
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter(
|
||||
"#category-search",
|
||||
{},
|
||||
gBrowser.selectedBrowser.browsingContext
|
||||
);
|
||||
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter(
|
||||
"#searchBarShownRadio",
|
||||
{},
|
||||
gBrowser.selectedBrowser.browsingContext
|
||||
);
|
||||
|
||||
assertInteractionScalars({
|
||||
preferences_paneGeneral: {
|
||||
browserRestoreSession: 1,
|
||||
},
|
||||
preferences_paneSearch: {
|
||||
searchBarShownRadio: 1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,642 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
gReduceMotionOverride = true;
|
||||
|
||||
function enterCustomizationMode(win = window) {
|
||||
let customizationReadyPromise = BrowserTestUtils.waitForEvent(
|
||||
win.gNavToolbox,
|
||||
"customizationready"
|
||||
);
|
||||
win.gCustomizeMode.enter();
|
||||
return customizationReadyPromise;
|
||||
}
|
||||
|
||||
function leaveCustomizationMode(win = window) {
|
||||
let customizationDonePromise = BrowserTestUtils.waitForEvent(
|
||||
win.gNavToolbox,
|
||||
"aftercustomization"
|
||||
);
|
||||
win.gCustomizeMode.exit();
|
||||
return customizationDonePromise;
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref("browser.uiCustomization.skipSourceNodeCheck", true);
|
||||
registerCleanupFunction(() =>
|
||||
Services.prefs.clearUserPref("browser.uiCustomization.skipSourceNodeCheck")
|
||||
);
|
||||
|
||||
// Stolen from browser/components/customizableui/tests/browser/head.js
|
||||
function simulateItemDrag(aToDrag, aTarget, aEvent = {}, aOffset = 2) {
|
||||
let ev = aEvent;
|
||||
if (ev == "end" || ev == "start") {
|
||||
let win = aTarget.ownerGlobal;
|
||||
const dwu = win.windowUtils;
|
||||
let bounds = dwu.getBoundsWithoutFlushing(aTarget);
|
||||
if (ev == "end") {
|
||||
ev = {
|
||||
clientX: bounds.right - aOffset,
|
||||
clientY: bounds.bottom - aOffset,
|
||||
};
|
||||
} else {
|
||||
ev = { clientX: bounds.left + aOffset, clientY: bounds.top + aOffset };
|
||||
}
|
||||
}
|
||||
ev._domDispatchOnly = true;
|
||||
EventUtils.synthesizeDrop(
|
||||
aToDrag.parentNode,
|
||||
aTarget,
|
||||
null,
|
||||
null,
|
||||
aToDrag.ownerGlobal,
|
||||
aTarget.ownerGlobal,
|
||||
ev
|
||||
);
|
||||
// Ensure dnd suppression is cleared.
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
aTarget,
|
||||
{ type: "mouseup" },
|
||||
aTarget.ownerGlobal
|
||||
);
|
||||
}
|
||||
|
||||
function organizeToolbars(state = {}) {
|
||||
// Set up the defaults for the state.
|
||||
let targetState = Object.assign(
|
||||
{
|
||||
// Areas where widgets can be placed, set to an array of widget IDs.
|
||||
"toolbar-menubar": undefined,
|
||||
PersonalToolbar: undefined,
|
||||
TabsToolbar: ["tabbrowser-tabs", "alltabs-button"],
|
||||
"widget-overflow-fixed-list": undefined,
|
||||
"nav-bar": ["back-button", "forward-button", "urlbar-container"],
|
||||
|
||||
// The page action's that should be in the URL bar.
|
||||
pageActionsInUrlBar: [],
|
||||
|
||||
// Areas to show or hide.
|
||||
dragSpaceVisible: false,
|
||||
titlebarVisible: false,
|
||||
menubarVisible: false,
|
||||
personalToolbarVisible: false,
|
||||
},
|
||||
state
|
||||
);
|
||||
|
||||
for (let area of CustomizableUI.areas) {
|
||||
// Clear out anything there already.
|
||||
for (let widgetId of CustomizableUI.getWidgetIdsInArea(area)) {
|
||||
CustomizableUI.removeWidgetFromArea(widgetId);
|
||||
}
|
||||
|
||||
if (targetState[area]) {
|
||||
// We specify the position explicitly to support the toolbars that have
|
||||
// fixed widgets.
|
||||
let position = 0;
|
||||
for (let widgetId of targetState[area]) {
|
||||
CustomizableUI.addWidgetToArea(widgetId, area, position++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomizableUI.setToolbarVisibility(
|
||||
"toolbar-menubar",
|
||||
targetState.menubarVisible
|
||||
);
|
||||
CustomizableUI.setToolbarVisibility(
|
||||
"PersonalToolbar",
|
||||
targetState.personalToolbarVisible
|
||||
);
|
||||
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.tabs.extraDragSpace",
|
||||
!targetState.titlebarVisible && targetState.dragSpaceVisible
|
||||
);
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.tabs.drawInTitlebar",
|
||||
!targetState.titlebarVisible
|
||||
);
|
||||
|
||||
for (let action of PageActions.actions) {
|
||||
action.pinnedToUrlbar = targetState.pageActionsInUrlBar.includes(action.id);
|
||||
}
|
||||
|
||||
// Clear out the existing telemetry.
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true);
|
||||
}
|
||||
|
||||
function assertVisibilityScalars(expected) {
|
||||
let scalars =
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true)?.parent?.[
|
||||
"browser.ui.toolbar_widgets"
|
||||
] ?? {};
|
||||
|
||||
// Only some platforms have the menubar items.
|
||||
if (AppConstants.MENUBAR_CAN_AUTOHIDE) {
|
||||
expected.push("menubar-items_pinned_menu-bar");
|
||||
}
|
||||
|
||||
let keys = new Set(expected.concat(Object.keys(scalars)));
|
||||
for (let key of keys) {
|
||||
Assert.ok(expected.includes(key), `Scalar key ${key} was unexpected.`);
|
||||
Assert.ok(scalars[key], `Expected to see see scalar key ${key} be true.`);
|
||||
}
|
||||
}
|
||||
|
||||
function assertCustomizeScalars(expected) {
|
||||
let scalars =
|
||||
Services.telemetry.getSnapshotForKeyedScalars("main", true)?.parent?.[
|
||||
"browser.ui.customized_widgets"
|
||||
] ?? {};
|
||||
|
||||
let keys = new Set(Object.keys(expected).concat(Object.keys(scalars)));
|
||||
for (let key of keys) {
|
||||
Assert.equal(
|
||||
scalars[key],
|
||||
expected[key],
|
||||
`Expected to see the correct value for scalar ${key}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function widgetPositions() {
|
||||
organizeToolbars();
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"back-button_pinned_nav-bar-start",
|
||||
]);
|
||||
|
||||
organizeToolbars({
|
||||
PersonalToolbar: [
|
||||
"fxa-toolbar-menu-button",
|
||||
"new-tab-button",
|
||||
"developer-button",
|
||||
],
|
||||
|
||||
TabsToolbar: [
|
||||
"stop-reload-button",
|
||||
"tabbrowser-tabs",
|
||||
"personal-bookmarks",
|
||||
],
|
||||
|
||||
"nav-bar": [
|
||||
"home-button",
|
||||
"forward-button",
|
||||
"downloads-button",
|
||||
"urlbar-container",
|
||||
"back-button",
|
||||
"library-button",
|
||||
],
|
||||
|
||||
dragSpaceVisible: true,
|
||||
personalToolbarVisible: true,
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_on",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_on",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"stop-reload-button_pinned_tabs-bar",
|
||||
"personal-bookmarks_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"home-button_pinned_nav-bar-start",
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"downloads-button_pinned_nav-bar-start",
|
||||
"back-button_pinned_nav-bar-end",
|
||||
"library-button_pinned_nav-bar-end",
|
||||
|
||||
"fxa-toolbar-menu-button_pinned_bookmarks-bar",
|
||||
"new-tab-button_pinned_bookmarks-bar",
|
||||
"developer-button_pinned_bookmarks-bar",
|
||||
]);
|
||||
|
||||
CustomizableUI.reset();
|
||||
});
|
||||
|
||||
add_task(async function customizeMode() {
|
||||
// Create a default state.
|
||||
organizeToolbars({
|
||||
PersonalToolbar: ["personal-bookmarks"],
|
||||
|
||||
TabsToolbar: ["tabbrowser-tabs", "new-tab-button"],
|
||||
|
||||
"nav-bar": [
|
||||
"back-button",
|
||||
"forward-button",
|
||||
"stop-reload-button",
|
||||
"urlbar-container",
|
||||
"home-button",
|
||||
"library-button",
|
||||
],
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"new-tab-button_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"back-button_pinned_nav-bar-start",
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"stop-reload-button_pinned_nav-bar-start",
|
||||
"home-button_pinned_nav-bar-end",
|
||||
"library-button_pinned_nav-bar-end",
|
||||
|
||||
"personal-bookmarks_pinned_bookmarks-bar",
|
||||
]);
|
||||
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
await enterCustomizationMode(win);
|
||||
|
||||
let toolbarButton = win.document.getElementById(
|
||||
"customization-toolbar-visibility-button"
|
||||
);
|
||||
let toolbarPopup = win.document.getElementById("customization-toolbar-menu");
|
||||
let popupShown = BrowserTestUtils.waitForEvent(toolbarPopup, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(toolbarButton, {}, win);
|
||||
await popupShown;
|
||||
|
||||
let popupHidden = BrowserTestUtils.waitForEvent(toolbarPopup, "popuphidden");
|
||||
let barButton = win.document.getElementById("toggle_PersonalToolbar");
|
||||
EventUtils.synthesizeMouseAtCenter(barButton, {}, win);
|
||||
await popupHidden;
|
||||
|
||||
let navbar = CustomizableUI.getCustomizationTarget(
|
||||
win.document.getElementById("nav-bar")
|
||||
);
|
||||
let bookmarksBar = CustomizableUI.getCustomizationTarget(
|
||||
win.document.getElementById("PersonalToolbar")
|
||||
);
|
||||
let tabBar = CustomizableUI.getCustomizationTarget(
|
||||
win.document.getElementById("TabsToolbar")
|
||||
);
|
||||
|
||||
simulateItemDrag(win.document.getElementById("home-button"), navbar, "start");
|
||||
simulateItemDrag(win.document.getElementById("library-button"), bookmarksBar);
|
||||
simulateItemDrag(win.document.getElementById("stop-reload-button"), tabBar);
|
||||
simulateItemDrag(
|
||||
win.document.getElementById("stop-reload-button"),
|
||||
navbar,
|
||||
"start"
|
||||
);
|
||||
simulateItemDrag(win.document.getElementById("stop-reload-button"), tabBar);
|
||||
|
||||
await leaveCustomizationMode(win);
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
|
||||
assertCustomizeScalars({
|
||||
"home-button_move_nav-bar-end_nav-bar-start_drag": 1,
|
||||
"library-button_move_nav-bar-end_bookmarks-bar_drag": 1,
|
||||
"stop-reload-button_move_nav-bar-start_tabs-bar_drag": 2,
|
||||
"stop-reload-button_move_tabs-bar_nav-bar-start_drag": 1,
|
||||
"bookmarks-bar_move_off_on_customization-toolbar-menu": 1,
|
||||
});
|
||||
|
||||
CustomizableUI.reset();
|
||||
});
|
||||
|
||||
add_task(async function contextMenus() {
|
||||
// Create a default state.
|
||||
organizeToolbars({
|
||||
PersonalToolbar: ["personal-bookmarks"],
|
||||
|
||||
TabsToolbar: ["tabbrowser-tabs", "new-tab-button"],
|
||||
|
||||
"nav-bar": [
|
||||
"back-button",
|
||||
"forward-button",
|
||||
"stop-reload-button",
|
||||
"urlbar-container",
|
||||
"home-button",
|
||||
"library-button",
|
||||
],
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"new-tab-button_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"back-button_pinned_nav-bar-start",
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"stop-reload-button_pinned_nav-bar-start",
|
||||
"home-button_pinned_nav-bar-end",
|
||||
"library-button_pinned_nav-bar-end",
|
||||
|
||||
"personal-bookmarks_pinned_bookmarks-bar",
|
||||
]);
|
||||
|
||||
let menu = document.getElementById("toolbar-context-menu");
|
||||
let popupShown = BrowserTestUtils.waitForEvent(menu, "popupshown");
|
||||
let button = document.getElementById("stop-reload-button");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
button,
|
||||
{ type: "contextmenu", button: 2 },
|
||||
window
|
||||
);
|
||||
await popupShown;
|
||||
|
||||
let popupHidden = BrowserTestUtils.waitForEvent(menu, "popuphidden");
|
||||
let barButton = document.getElementById("toggle_PersonalToolbar");
|
||||
EventUtils.synthesizeMouseAtCenter(barButton, {}, window);
|
||||
await popupHidden;
|
||||
|
||||
popupShown = BrowserTestUtils.waitForEvent(menu, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
button,
|
||||
{ type: "contextmenu", button: 2 },
|
||||
window
|
||||
);
|
||||
await popupShown;
|
||||
|
||||
popupHidden = BrowserTestUtils.waitForEvent(menu, "popuphidden");
|
||||
let removeButton = document.querySelector(
|
||||
"#toolbar-context-menu .customize-context-removeFromToolbar"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(removeButton, {}, window);
|
||||
await popupHidden;
|
||||
|
||||
assertCustomizeScalars({
|
||||
"bookmarks-bar_move_off_on_toolbar-context-menu": 1,
|
||||
"stop-reload-button_remove_nav-bar-start_na_toolbar-context-menu": 1,
|
||||
});
|
||||
|
||||
CustomizableUI.reset();
|
||||
});
|
||||
|
||||
add_task(async function pageActions() {
|
||||
// The page action button is only visible when a page is loaded.
|
||||
await BrowserTestUtils.withNewTab("http://example.com", async () => {
|
||||
// Create a default state.
|
||||
organizeToolbars({
|
||||
PersonalToolbar: ["personal-bookmarks"],
|
||||
|
||||
TabsToolbar: ["tabbrowser-tabs", "new-tab-button"],
|
||||
|
||||
"nav-bar": [
|
||||
"back-button",
|
||||
"forward-button",
|
||||
"stop-reload-button",
|
||||
"urlbar-container",
|
||||
"home-button",
|
||||
"library-button",
|
||||
],
|
||||
|
||||
pageActionsInUrlBar: ["emailLink", "pinTab"],
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"new-tab-button_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"back-button_pinned_nav-bar-start",
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"stop-reload-button_pinned_nav-bar-start",
|
||||
"home-button_pinned_nav-bar-end",
|
||||
"library-button_pinned_nav-bar-end",
|
||||
|
||||
"emailLink_pinned_pageaction-urlbar",
|
||||
"pinTab_pinned_pageaction-urlbar",
|
||||
|
||||
"personal-bookmarks_pinned_bookmarks-bar",
|
||||
]);
|
||||
|
||||
let panel = document.getElementById("pageActionPanel");
|
||||
let button = document.getElementById("pageActionButton");
|
||||
let context = document.getElementById("pageActionContextMenu");
|
||||
|
||||
let popupShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {}, window);
|
||||
await popupShown;
|
||||
|
||||
popupShown = BrowserTestUtils.waitForEvent(context, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
document.getElementById("pageAction-panel-copyURL"),
|
||||
{ type: "contextmenu", button: 2 },
|
||||
window
|
||||
);
|
||||
await popupShown;
|
||||
|
||||
let popupHidden = BrowserTestUtils.waitForEvent(context, "popuphidden");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
document.querySelector(".pageActionContextMenuItem.builtInUnpinned"),
|
||||
{},
|
||||
window
|
||||
);
|
||||
await popupHidden;
|
||||
|
||||
popupHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {}, window);
|
||||
await popupHidden;
|
||||
|
||||
popupShown = BrowserTestUtils.waitForEvent(context, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
document.getElementById("pageAction-urlbar-emailLink"),
|
||||
{ type: "contextmenu", button: 2 },
|
||||
window
|
||||
);
|
||||
await popupShown;
|
||||
|
||||
popupHidden = BrowserTestUtils.waitForEvent(context, "popuphidden");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
document.querySelector(".pageActionContextMenuItem.builtInPinned"),
|
||||
{},
|
||||
window
|
||||
);
|
||||
await popupHidden;
|
||||
|
||||
assertCustomizeScalars({
|
||||
"copyURL_add_na_pageaction-urlbar_pageaction-context": 1,
|
||||
"emailLink_remove_pageaction-urlbar_na_pageaction-context": 1,
|
||||
});
|
||||
|
||||
CustomizableUI.reset();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function extensions() {
|
||||
// The page action button is only visible when a page is loaded.
|
||||
await BrowserTestUtils.withNewTab("http://example.com", async () => {
|
||||
organizeToolbars();
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
useAddonManager: "temporary",
|
||||
manifest: {
|
||||
version: "1",
|
||||
applications: {
|
||||
gecko: { id: "random_addon@example.com" },
|
||||
},
|
||||
browser_action: {
|
||||
default_icon: "default.png",
|
||||
default_title: "Hello",
|
||||
},
|
||||
page_action: {
|
||||
default_icon: "default.png",
|
||||
default_title: "Hello",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
assertCustomizeScalars({
|
||||
"random-addon-example-com_add_na_nav-bar-end_addon": 1,
|
||||
"random-addon-example-com_add_na_pageaction-urlbar_addon": 1,
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"back-button_pinned_nav-bar-start",
|
||||
|
||||
"random-addon-example-com_pinned_nav-bar-end",
|
||||
|
||||
"random-addon-example-com_pinned_pageaction-urlbar",
|
||||
]);
|
||||
|
||||
let addon = await AddonManager.getAddonByID(extension.id);
|
||||
await addon.disable();
|
||||
|
||||
assertCustomizeScalars({
|
||||
"random-addon-example-com_remove_nav-bar-end_na_addon": 1,
|
||||
"random-addon-example-com_remove_pageaction-urlbar_na_addon": 1,
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"back-button_pinned_nav-bar-start",
|
||||
]);
|
||||
|
||||
await addon.enable();
|
||||
|
||||
assertCustomizeScalars({
|
||||
"random-addon-example-com_add_na_nav-bar-end_addon": 1,
|
||||
"random-addon-example-com_add_na_pageaction-urlbar_addon": 1,
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"back-button_pinned_nav-bar-start",
|
||||
|
||||
"random-addon-example-com_pinned_nav-bar-end",
|
||||
|
||||
"random-addon-example-com_pinned_pageaction-urlbar",
|
||||
]);
|
||||
|
||||
await addon.reload();
|
||||
|
||||
assertCustomizeScalars({});
|
||||
|
||||
await enterCustomizationMode();
|
||||
|
||||
let navbar = CustomizableUI.getCustomizationTarget(
|
||||
document.getElementById("nav-bar")
|
||||
);
|
||||
|
||||
simulateItemDrag(
|
||||
document.getElementById("random_addon_example_com-browser-action"),
|
||||
navbar,
|
||||
"start"
|
||||
);
|
||||
|
||||
await leaveCustomizationMode();
|
||||
|
||||
assertCustomizeScalars({
|
||||
"random-addon-example-com_move_nav-bar-end_nav-bar-start_drag": 1,
|
||||
});
|
||||
|
||||
await extension.unload();
|
||||
|
||||
assertCustomizeScalars({
|
||||
"random-addon-example-com_remove_nav-bar-start_na_addon": 1,
|
||||
"random-addon-example-com_remove_pageaction-urlbar_na_addon": 1,
|
||||
});
|
||||
|
||||
BrowserUsageTelemetry._recordUITelemetry();
|
||||
|
||||
assertVisibilityScalars([
|
||||
"drag-space_pinned_off",
|
||||
"menu-toolbar_pinned_off",
|
||||
"titlebar_pinned_off",
|
||||
"bookmarks-bar_pinned_off",
|
||||
|
||||
"tabbrowser-tabs_pinned_tabs-bar",
|
||||
"alltabs-button_pinned_tabs-bar",
|
||||
|
||||
"forward-button_pinned_nav-bar-start",
|
||||
"back-button_pinned_nav-bar-start",
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -2089,6 +2089,51 @@ var BrowserTestUtils = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Waits for CSS transitions to complete for an element. Tracks any
|
||||
* transitions that start after this function is called and resolves once all
|
||||
* started transitions complete.
|
||||
*
|
||||
* @param element (Element)
|
||||
* The element that will transition.
|
||||
* @param timeout (number)
|
||||
* The maximum time to wait in milliseconds. Defaults to 5 seconds.
|
||||
* @return Promise
|
||||
* Resolves when transitions complete or rejects if the timeout is hit.
|
||||
*/
|
||||
waitForTransition(element, timeout = 5000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let cleanup = () => {
|
||||
element.removeEventListener("transitionrun", listener);
|
||||
element.removeEventListener("transitionend", listener);
|
||||
};
|
||||
|
||||
let timer = element.ownerGlobal.setTimeout(() => {
|
||||
cleanup();
|
||||
reject();
|
||||
}, timeout);
|
||||
|
||||
let transitionCount = 0;
|
||||
|
||||
let listener = event => {
|
||||
if (event.type == "transitionrun") {
|
||||
transitionCount++;
|
||||
} else {
|
||||
transitionCount--;
|
||||
if (transitionCount == 0) {
|
||||
cleanup();
|
||||
element.ownerGlobal.clearTimeout(timer);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
element.addEventListener("transitionrun", listener);
|
||||
element.addEventListener("transitionend", listener);
|
||||
element.addEventListener("transitioncancel", listener);
|
||||
});
|
||||
},
|
||||
|
||||
_knownAboutPages: new Set(),
|
||||
_loadedAboutContentScript: false,
|
||||
/**
|
||||
|
|
|
@ -561,6 +561,389 @@ browser.input:
|
|||
- 'main'
|
||||
- 'content'
|
||||
|
||||
browser.ui:
|
||||
toolbar_widgets:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
The widgets in the toolbars.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: boolean
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
customized_widgets:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records when widgets are added, removed or moved in the UI.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
browser.ui.interaction:
|
||||
keyboard:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with keyboard shortcuts.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
menu_bar:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the menu bar.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
tabs_bar:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the tab bar.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
nav_bar:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the nav bar.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
bookmarks_bar:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the bookmarks bar.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
app_menu:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the app menu.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
tabs_context:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the tab context menu.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
content_context:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the content context menu.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
overflow_menu:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the overflow menu.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
pinned_overflow_menu:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with items in the pinned area of the
|
||||
overflow menu.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
pageaction_urlbar:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with page action items in the url bar.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
pageaction_panel:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records a count of interactions with page action items in the panel.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
preferences_paneHome:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records the items interacted with in the Home section of preferences.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
preferences_paneGeneral:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records the items interacted with in the General section of preferences.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
preferences_panePrivacy:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records the items interacted with in the Privacy section of preferences.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
preferences_paneSearch:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records the items interacted with in the Search section of preferences.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
preferences_paneSearchResults:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records the items interacted with in the Search results section of
|
||||
preferences.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
preferences_paneSync:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records the items interacted with in the Sync section of preferences.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
preferences_paneContainers:
|
||||
bug_numbers:
|
||||
- 1620358
|
||||
description: >
|
||||
Records the items interacted with in the Containers section of
|
||||
preferences.
|
||||
See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/data/ecosystem-telemetry.html
|
||||
expires: never
|
||||
kind: uint
|
||||
keyed: true
|
||||
notification_emails:
|
||||
- shong@mozilla.com
|
||||
- dtownsend@mozilla.com
|
||||
release_channel_collection: opt-out
|
||||
products:
|
||||
- 'firefox'
|
||||
record_in_processes:
|
||||
- 'main'
|
||||
|
||||
gecko:
|
||||
version:
|
||||
bug_numbers:
|
||||
|
|
Загрузка…
Ссылка в новой задаче