mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 17:31:47 +09:00
Remove BrowserUITelemetry from Basilisk application
This commit is contained in:
parent
c9632eecb5
commit
5315d7c162
12 changed files with 0 additions and 1006 deletions
|
|
@ -3,9 +3,6 @@
|
|||
# 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/.
|
||||
|
||||
# NB: IF YOU ADD ITEMS TO THIS FILE, PLEASE UPDATE THE WHITELIST IN
|
||||
# BrowserUITelemetry.jsm. SEE BUG 991757 FOR DETAILS.
|
||||
|
||||
<menugroup id="context-navigation">
|
||||
<menuitem id="context-back"
|
||||
class="menuitem-iconic"
|
||||
|
|
|
|||
|
|
@ -194,10 +194,6 @@ var SidebarUI = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.isOpen && commandID != this.currentID) {
|
||||
BrowserUITelemetry.countSidebarEvent(this.currentID, "hide");
|
||||
}
|
||||
|
||||
let broadcasters = document.getElementsByAttribute("group", "sidebar");
|
||||
for (let broadcaster of broadcasters) {
|
||||
// skip elements that observe sidebar broadcasters and random
|
||||
|
|
@ -260,7 +256,6 @@ var SidebarUI = {
|
|||
selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
|
||||
{commandID: commandID, isOpen: true}
|
||||
);
|
||||
BrowserUITelemetry.countSidebarEvent(commandID, "show");
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -298,7 +293,6 @@ var SidebarUI = {
|
|||
selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
|
||||
{commandID: commandID, isOpen: false}
|
||||
);
|
||||
BrowserUITelemetry.countSidebarEvent(commandID, "hide");
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
|
|||
["AboutHome", "resource:///modules/AboutHome.jsm"],
|
||||
["AddonWatcher", "resource://gre/modules/AddonWatcher.jsm"],
|
||||
["AppConstants", "resource://gre/modules/AppConstants.jsm"],
|
||||
["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
|
||||
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
|
||||
["BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"],
|
||||
["CastingApps", "resource:///modules/CastingApps.jsm"],
|
||||
|
|
@ -3729,18 +3728,6 @@ const BrowserSearch = {
|
|||
openUILinkIn(this.searchEnginesURL, where);
|
||||
},
|
||||
|
||||
_getSearchEngineId: function (engine) {
|
||||
if (engine && engine.identifier) {
|
||||
return engine.identifier;
|
||||
}
|
||||
|
||||
if (!engine || (engine.name === undefined) ||
|
||||
!Services.prefs.getBoolPref("toolkit.telemetry.enabled"))
|
||||
return "other";
|
||||
|
||||
return "other-" + engine.name;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to record a search with Telemetry.
|
||||
*
|
||||
|
|
@ -3759,7 +3746,6 @@ const BrowserSearch = {
|
|||
* selected it: {selection: {index: The selected index, kind: "key" or "mouse"}}
|
||||
*/
|
||||
recordSearchInTelemetry: function (engine, source, details={}) {
|
||||
BrowserUITelemetry.countSearchEvent(source, null, details.selection);
|
||||
try {
|
||||
BrowserUsageTelemetry.recordSearch(engine, source, details);
|
||||
} catch (ex) {
|
||||
|
|
@ -3783,8 +3769,6 @@ const BrowserSearch = {
|
|||
* (string) Where was the search link opened (e.g. new tab, current tab, ..).
|
||||
*/
|
||||
recordOneoffSearchInTelemetry: function (engine, source, type, where) {
|
||||
let id = this._getSearchEngineId(engine) + "." + source;
|
||||
BrowserUITelemetry.countOneoffSearchEvent(id, type, where);
|
||||
try {
|
||||
const details = {type, isOneOff: true};
|
||||
BrowserUsageTelemetry.recordSearch(engine, source, details);
|
||||
|
|
|
|||
|
|
@ -85,9 +85,6 @@ nsContextMenu.prototype = {
|
|||
|
||||
// Initialize (disable/remove) menu items.
|
||||
this.initItems();
|
||||
|
||||
// Register this opening of the menu with telemetry:
|
||||
this._checkTelemetryForMenu(aXulMenu);
|
||||
},
|
||||
|
||||
hiding: function CM_hiding() {
|
||||
|
|
@ -1782,65 +1779,6 @@ nsContextMenu.prototype = {
|
|||
menuItem.label = menuLabel;
|
||||
menuItem.accessKey = gNavigatorBundle.getString("contextMenuSearch.accesskey");
|
||||
},
|
||||
|
||||
_getTelemetryClickInfo: function(aXulMenu) {
|
||||
this._onPopupHiding = () => {
|
||||
aXulMenu.ownerDocument.removeEventListener("command", activationHandler, true);
|
||||
aXulMenu.removeEventListener("popuphiding", this._onPopupHiding, true);
|
||||
delete this._onPopupHiding;
|
||||
|
||||
let eventKey = [
|
||||
this._telemetryPageContext,
|
||||
this._telemetryHadCustomItems ? "withcustom" : "withoutcustom"
|
||||
];
|
||||
let target = this._telemetryClickID || "close-without-interaction";
|
||||
BrowserUITelemetry.registerContextMenuInteraction(eventKey, target);
|
||||
};
|
||||
let activationHandler = (e) => {
|
||||
// Deal with command events being routed to command elements; figure out
|
||||
// what triggered the event (which will have the right e.target)
|
||||
if (e.sourceEvent) {
|
||||
e = e.sourceEvent;
|
||||
}
|
||||
// Target should be in the menu (this catches using shortcuts for items
|
||||
// not in the menu while the menu is up)
|
||||
if (!aXulMenu.contains(e.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a page menu item:
|
||||
if (e.target.hasAttribute(PageMenuParent.GENERATEDITEMID_ATTR)) {
|
||||
this._telemetryClickID = "custom-page-item";
|
||||
} else {
|
||||
this._telemetryClickID = (e.target.id || "unknown").replace(/^context-/i, "");
|
||||
}
|
||||
};
|
||||
aXulMenu.ownerDocument.addEventListener("command", activationHandler, true);
|
||||
aXulMenu.addEventListener("popuphiding", this._onPopupHiding, true);
|
||||
},
|
||||
|
||||
_getTelemetryPageContextInfo: function() {
|
||||
let rv = [];
|
||||
for (let k of ["isContentSelected", "onLink", "onImage", "onCanvas", "onVideo", "onAudio",
|
||||
"onTextInput"]) {
|
||||
if (this[k]) {
|
||||
rv.push(k.replace(/^(?:is|on)(.)/, (match, firstLetter) => firstLetter.toLowerCase()));
|
||||
}
|
||||
}
|
||||
if (!rv.length) {
|
||||
rv.push('other');
|
||||
}
|
||||
|
||||
return JSON.stringify(rv);
|
||||
},
|
||||
|
||||
_checkTelemetryForMenu: function(aXulMenu) {
|
||||
this._telemetryClickID = null;
|
||||
this._telemetryPageContext = this._getTelemetryPageContextInfo();
|
||||
this._telemetryHadCustomItems = this.hasPageMenu;
|
||||
this._getTelemetryClickInfo(aXulMenu);
|
||||
},
|
||||
|
||||
createContainerMenu: function(aEvent) {
|
||||
return createUserContextMenu(aEvent, true,
|
||||
gContextMenuContentData.userContextId);
|
||||
|
|
|
|||
|
|
@ -6897,11 +6897,9 @@
|
|||
if (browser.audioMuted) {
|
||||
browser.unmute();
|
||||
this.removeAttribute("muted");
|
||||
BrowserUITelemetry.countTabMutingEvent("unmute", aMuteReason);
|
||||
} else {
|
||||
browser.mute();
|
||||
this.setAttribute("muted", "true");
|
||||
BrowserUITelemetry.countTabMutingEvent("mute", aMuteReason);
|
||||
}
|
||||
this.muteReason = aMuteReason || null;
|
||||
modifiedAttrs.push("muted");
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ Cu.import("resource:///modules/CustomizableUI.jsm");
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||
"resource:///modules/BrowserUITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils",
|
||||
|
|
@ -497,7 +495,6 @@ const CustomizableWidgets = [
|
|||
item.addEventListener("click", e => {
|
||||
doc.defaultView.openUILink(tabInfo.url, e);
|
||||
CustomizableUI.hidePanelForNode(item);
|
||||
BrowserUITelemetry.countSyncedTabEvent("open", "toolbarbutton-subview");
|
||||
});
|
||||
return item;
|
||||
},
|
||||
|
|
@ -1179,7 +1176,6 @@ if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) {
|
|||
this._ensureSanitizer();
|
||||
this._sanitizer.range = this._getSanitizeRange(doc);
|
||||
let group = doc.getElementById("PanelUI-panic-timeSpan");
|
||||
BrowserUITelemetry.countPanicEvent(group.selectedItem.id);
|
||||
group.selectedItem = doc.getElementById("PanelUI-panic-5min");
|
||||
let itemsToClear = [
|
||||
"cookies", "history", "openWindows", "formdata", "sessions", "cache", "downloads"
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@ Cu.import("resource://gre/modules/AppConstants.jsm");
|
|||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DragPositionManager",
|
||||
"resource:///modules/DragPositionManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||
"resource:///modules/BrowserUITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
|
||||
"resource://gre/modules/LightweightThemeManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
||||
|
|
@ -1119,7 +1117,6 @@ CustomizeMode.prototype = {
|
|||
this.resetting = true;
|
||||
// Disable the reset button temporarily while resetting:
|
||||
let btn = this.document.getElementById("customization-reset-button");
|
||||
BrowserUITelemetry.countCustomizationEvent("reset");
|
||||
btn.disabled = true;
|
||||
return Task.spawn(function*() {
|
||||
this._removePanelCustomizationPlaceholders();
|
||||
|
|
@ -1755,7 +1752,6 @@ CustomizeMode.prototype = {
|
|||
}
|
||||
|
||||
CustomizableUI.removeWidgetFromArea(aDraggedItemId);
|
||||
BrowserUITelemetry.countCustomizationEvent("remove");
|
||||
// Special widgets are removed outright, we can return here:
|
||||
if (CustomizableUI.isSpecialWidget(aDraggedItemId)) {
|
||||
return;
|
||||
|
|
@ -1797,7 +1793,6 @@ CustomizeMode.prototype = {
|
|||
this.wrapToolbarItem(aTargetNode, place);
|
||||
}
|
||||
this.wrapToolbarItem(draggedItem, place);
|
||||
BrowserUITelemetry.countCustomizationEvent("move");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1805,12 +1800,6 @@ CustomizeMode.prototype = {
|
|||
// widget to the end of the area.
|
||||
if (aTargetNode == aTargetArea.customizationTarget) {
|
||||
CustomizableUI.addWidgetToArea(aDraggedItemId, aTargetArea.id);
|
||||
// For the purposes of BrowserUITelemetry, we consider both moving a widget
|
||||
// within the same area, and adding a widget from one area to another area
|
||||
// as a "move". An "add" is only when we move an item from the palette into
|
||||
// an area.
|
||||
let custEventType = aOriginArea.id == kPaletteId ? "add" : "move";
|
||||
BrowserUITelemetry.countCustomizationEvent(custEventType);
|
||||
this._onDragEnd(aEvent);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1847,14 +1836,8 @@ CustomizeMode.prototype = {
|
|||
} else {
|
||||
CustomizableUI.addWidgetToArea(aDraggedItemId, aTargetArea.id, position);
|
||||
}
|
||||
|
||||
this._onDragEnd(aEvent);
|
||||
|
||||
// For BrowserUITelemetry, an "add" is only when we move an item from the palette
|
||||
// into an area. Otherwise, it's a move.
|
||||
let custEventType = aOriginArea.id == kPaletteId ? "add" : "move";
|
||||
BrowserUITelemetry.countCustomizationEvent(custEventType);
|
||||
|
||||
// If we dropped onto a skipintoolbarset item, manually correct the drop location:
|
||||
if (aTargetNode != itemForPlacement) {
|
||||
let draggedWrapper = draggedItem.parentNode;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s
|
|||
["AutoCompletePopup", "resource://gre/modules/AutoCompletePopup.jsm"],
|
||||
["BookmarkHTMLUtils", "resource://gre/modules/BookmarkHTMLUtils.jsm"],
|
||||
["BookmarkJSONUtils", "resource://gre/modules/BookmarkJSONUtils.jsm"],
|
||||
["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
|
||||
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
|
||||
["ContentClick", "resource:///modules/ContentClick.jsm"],
|
||||
["ContentPrefServiceParent", "resource://gre/modules/ContentPrefServiceParent.jsm"],
|
||||
|
|
@ -667,7 +666,6 @@ BrowserGlue.prototype = {
|
|||
|
||||
SessionStore.init();
|
||||
BrowserUsageTelemetry.init();
|
||||
BrowserUITelemetry.init();
|
||||
ContentSearch.init();
|
||||
FormValidationHandler.init();
|
||||
|
||||
|
|
|
|||
|
|
@ -1324,7 +1324,6 @@
|
|||
|
||||
<method name="showSettings">
|
||||
<body><![CDATA[
|
||||
BrowserUITelemetry.countSearchSettingsEvent(this.telemetryOrigin);
|
||||
openPreferences("paneSearch");
|
||||
// If the preference tab was already selected, the panel doesn't
|
||||
// close itself automatically.
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
let log = Cu.import("resource://gre/modules/Log.jsm", {})
|
||||
.Log.repository.getLogger("Sync.RemoteTabs");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||
"resource:///modules/BrowserUITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils",
|
||||
"resource:///modules/PlacesUIUtils.jsm");
|
||||
|
||||
|
|
@ -115,7 +113,6 @@ TabListComponent.prototype = {
|
|||
|
||||
onOpenTab(url, where, params) {
|
||||
this._window.openUILinkIn(url, where, params);
|
||||
BrowserUITelemetry.countSyncedTabEvent("open", "sidebar");
|
||||
},
|
||||
|
||||
onOpenTabs(urls, where) {
|
||||
|
|
@ -129,7 +126,6 @@ TabListComponent.prototype = {
|
|||
let loadInBackground = where == "tabshifted" ? true : false;
|
||||
this._getChromeWindow(this._window).gBrowser.loadTabs(urls, loadInBackground, false);
|
||||
}
|
||||
BrowserUITelemetry.countSyncedTabEvent("openmultiple", "sidebar");
|
||||
},
|
||||
|
||||
onCopyTabLocation(url) {
|
||||
|
|
|
|||
|
|
@ -1,888 +0,0 @@
|
|||
// 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/.
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["BrowserUITelemetry"];
|
||||
|
||||
const {interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
|
||||
"resource://gre/modules/UITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
||||
"resource:///modules/RecentWindow.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
|
||||
"resource:///modules/CustomizableUI.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "Timer", function() {
|
||||
let timer = {};
|
||||
Cu.import("resource://gre/modules/Timer.jsm", timer);
|
||||
return timer;
|
||||
});
|
||||
|
||||
const MS_SECOND = 1000;
|
||||
const MS_MINUTE = MS_SECOND * 60;
|
||||
const MS_HOUR = MS_MINUTE * 60;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DEFAULT_AREA_PLACEMENTS", function() {
|
||||
let result = {
|
||||
"PanelUI-contents": [
|
||||
"edit-controls",
|
||||
"zoom-controls",
|
||||
"new-window-button",
|
||||
"privatebrowsing-button",
|
||||
"save-page-button",
|
||||
"print-button",
|
||||
"history-panelmenu",
|
||||
"fullscreen-button",
|
||||
"find-button",
|
||||
"preferences-button",
|
||||
"add-ons-button",
|
||||
"sync-button",
|
||||
"developer-button",
|
||||
],
|
||||
"nav-bar": [
|
||||
"urlbar-container",
|
||||
"search-container",
|
||||
"bookmarks-menu-button",
|
||||
"pocket-button",
|
||||
"downloads-button",
|
||||
"home-button",
|
||||
],
|
||||
// It's true that toolbar-menubar is not visible
|
||||
// on OS X, but the XUL node is definitely present
|
||||
// in the document.
|
||||
"toolbar-menubar": [
|
||||
"menubar-items",
|
||||
],
|
||||
"TabsToolbar": [
|
||||
"tabbrowser-tabs",
|
||||
"new-tab-button",
|
||||
"alltabs-button",
|
||||
],
|
||||
"PersonalToolbar": [
|
||||
"personal-bookmarks",
|
||||
],
|
||||
};
|
||||
|
||||
let showCharacterEncoding = Services.prefs.getComplexValue(
|
||||
"browser.menu.showCharacterEncoding",
|
||||
Ci.nsIPrefLocalizedString
|
||||
).data;
|
||||
if (showCharacterEncoding == "true") {
|
||||
result["PanelUI-contents"].push("characterencoding-button");
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DEFAULT_AREAS", function() {
|
||||
return Object.keys(DEFAULT_AREA_PLACEMENTS);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "PALETTE_ITEMS", function() {
|
||||
let result = [
|
||||
"open-file-button",
|
||||
"developer-button",
|
||||
"feed-button",
|
||||
"email-link-button",
|
||||
"containers-panelmenu",
|
||||
];
|
||||
|
||||
let panelPlacements = DEFAULT_AREA_PLACEMENTS["PanelUI-contents"];
|
||||
if (panelPlacements.indexOf("characterencoding-button") == -1) {
|
||||
result.push("characterencoding-button");
|
||||
}
|
||||
|
||||
if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) {
|
||||
result.push("panic-button");
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DEFAULT_ITEMS", function() {
|
||||
let result = [];
|
||||
for (let [, buttons] of Object.entries(DEFAULT_AREA_PLACEMENTS)) {
|
||||
result = result.concat(buttons);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ALL_BUILTIN_ITEMS", function() {
|
||||
// These special cases are for click events on built-in items that are
|
||||
// contained within customizable items (like the navigation widget).
|
||||
const SPECIAL_CASES = [
|
||||
"back-button",
|
||||
"forward-button",
|
||||
"urlbar-stop-button",
|
||||
"urlbar-go-button",
|
||||
"urlbar-reload-button",
|
||||
"searchbar",
|
||||
"cut-button",
|
||||
"copy-button",
|
||||
"paste-button",
|
||||
"zoom-out-button",
|
||||
"zoom-reset-button",
|
||||
"zoom-in-button",
|
||||
"BMB_bookmarksPopup",
|
||||
"BMB_unsortedBookmarksPopup",
|
||||
"BMB_bookmarksToolbarPopup",
|
||||
"search-go-button",
|
||||
"soundplaying-icon",
|
||||
]
|
||||
return DEFAULT_ITEMS.concat(PALETTE_ITEMS)
|
||||
.concat(SPECIAL_CASES);
|
||||
});
|
||||
|
||||
const OTHER_MOUSEUP_MONITORED_ITEMS = [
|
||||
"PlacesChevron",
|
||||
"PlacesToolbarItems",
|
||||
"menubar-items",
|
||||
];
|
||||
|
||||
// Items that open arrow panels will often be overlapped by
|
||||
// the panel that they're opening by the time the mouseup
|
||||
// event is fired, so for these items, we monitor mousedown.
|
||||
const MOUSEDOWN_MONITORED_ITEMS = [
|
||||
"PanelUI-menu-button",
|
||||
];
|
||||
|
||||
// Weakly maps browser windows to objects whose keys are relative
|
||||
// timestamps for when some kind of session started. For example,
|
||||
// when a customization session started. That way, when the window
|
||||
// exits customization mode, we can determine how long the session
|
||||
// lasted.
|
||||
const WINDOW_DURATION_MAP = new WeakMap();
|
||||
|
||||
// Default bucket name, when no other bucket is active.
|
||||
const BUCKET_DEFAULT = "__DEFAULT__";
|
||||
// Bucket prefix, for named buckets.
|
||||
const BUCKET_PREFIX = "bucket_";
|
||||
// Standard separator to use between different parts of a bucket name, such
|
||||
// as primary name and the time step string.
|
||||
const BUCKET_SEPARATOR = "|";
|
||||
|
||||
this.BrowserUITelemetry = {
|
||||
init: function() {
|
||||
UITelemetry.addSimpleMeasureFunction("toolbars",
|
||||
this.getToolbarMeasures.bind(this));
|
||||
UITelemetry.addSimpleMeasureFunction("contextmenu",
|
||||
this.getContextMenuInfo.bind(this));
|
||||
UITelemetry.addSimpleMeasureFunction("syncstate",
|
||||
this.getSyncState.bind(this));
|
||||
|
||||
Services.obs.addObserver(this, "sessionstore-windows-restored", false);
|
||||
Services.obs.addObserver(this, "browser-delayed-startup-finished", false);
|
||||
Services.obs.addObserver(this, "autocomplete-did-enter-text", false);
|
||||
CustomizableUI.addListener(this);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "sessionstore-windows-restored":
|
||||
this._gatherFirstWindowMeasurements();
|
||||
break;
|
||||
case "browser-delayed-startup-finished":
|
||||
this._registerWindow(aSubject);
|
||||
break;
|
||||
case "autocomplete-did-enter-text":
|
||||
let input = aSubject.QueryInterface(Ci.nsIAutoCompleteInput);
|
||||
if (input && input.id == "urlbar" && !input.inPrivateContext &&
|
||||
input.popup.selectedIndex != -1) {
|
||||
this._logAwesomeBarSearchResult(input.textValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* For the _countableEvents object, constructs a chain of
|
||||
* Javascript Objects with the keys in aKeys, with the final
|
||||
* key getting the value in aEndWith. If the final key already
|
||||
* exists in the final object, its value is not set. In either
|
||||
* case, a reference to the second last object in the chain is
|
||||
* returned.
|
||||
*
|
||||
* Example - suppose I want to store:
|
||||
* _countableEvents: {
|
||||
* a: {
|
||||
* b: {
|
||||
* c: 0
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* And then increment the "c" value by 1, you could call this
|
||||
* function like this:
|
||||
*
|
||||
* let example = this._ensureObjectChain([a, b, c], 0);
|
||||
* example["c"]++;
|
||||
*
|
||||
* Subsequent repetitions of these last two lines would
|
||||
* simply result in the c value being incremented again
|
||||
* and again.
|
||||
*
|
||||
* @param aKeys the Array of keys to chain Objects together with.
|
||||
* @param aEndWith the value to assign to the last key.
|
||||
* @param aRoot the root object onto which we create/get the object chain
|
||||
* designated by aKeys.
|
||||
* @returns a reference to the second last object in the chain -
|
||||
* so in our example, that'd be "b".
|
||||
*/
|
||||
_ensureObjectChain: function(aKeys, aEndWith, aRoot) {
|
||||
let current = aRoot;
|
||||
let parent = null;
|
||||
aKeys.unshift(this._bucket);
|
||||
for (let [i, key] of aKeys.entries()) {
|
||||
if (!(key in current)) {
|
||||
if (i == aKeys.length - 1) {
|
||||
current[key] = aEndWith;
|
||||
} else {
|
||||
current[key] = {};
|
||||
}
|
||||
}
|
||||
parent = current;
|
||||
current = current[key];
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
|
||||
_countableEvents: {},
|
||||
_countEvent: function(aKeyArray, root=this._countableEvents) {
|
||||
let countObject = this._ensureObjectChain(aKeyArray, 0, root);
|
||||
let lastItemKey = aKeyArray[aKeyArray.length - 1];
|
||||
countObject[lastItemKey]++;
|
||||
},
|
||||
|
||||
_countMouseUpEvent: function(aCategory, aAction, aButton) {
|
||||
const BUTTONS = ["left", "middle", "right"];
|
||||
let buttonKey = BUTTONS[aButton];
|
||||
if (buttonKey) {
|
||||
this._countEvent([aCategory, aAction, buttonKey]);
|
||||
}
|
||||
},
|
||||
|
||||
_firstWindowMeasurements: null,
|
||||
_gatherFirstWindowMeasurements: function() {
|
||||
// We'll gather measurements as soon as the session has restored.
|
||||
// We do this here instead of waiting for UITelemetry to ask for
|
||||
// our measurements because at that point all browser windows have
|
||||
// probably been closed, since the vast majority of saved-session
|
||||
// pings are gathered during shutdown.
|
||||
let win = RecentWindow.getMostRecentBrowserWindow({
|
||||
private: false,
|
||||
allowPopups: false,
|
||||
});
|
||||
|
||||
Services.search.init(rv => {
|
||||
// If there are no such windows (or we've just about found one
|
||||
// but it's closed already), we're out of luck. :(
|
||||
let hasWindow = win && !win.closed;
|
||||
this._firstWindowMeasurements = hasWindow ? this._getWindowMeasurements(win, rv)
|
||||
: {};
|
||||
});
|
||||
},
|
||||
|
||||
_registerWindow: function(aWindow) {
|
||||
aWindow.addEventListener("unload", this);
|
||||
let document = aWindow.document;
|
||||
|
||||
for (let areaID of CustomizableUI.areas) {
|
||||
let areaNode = document.getElementById(areaID);
|
||||
if (areaNode) {
|
||||
(areaNode.customizationTarget || areaNode).addEventListener("mouseup", this);
|
||||
}
|
||||
}
|
||||
|
||||
for (let itemID of OTHER_MOUSEUP_MONITORED_ITEMS) {
|
||||
let item = document.getElementById(itemID);
|
||||
if (item) {
|
||||
item.addEventListener("mouseup", this);
|
||||
}
|
||||
}
|
||||
|
||||
for (let itemID of MOUSEDOWN_MONITORED_ITEMS) {
|
||||
let item = document.getElementById(itemID);
|
||||
if (item) {
|
||||
item.addEventListener("mousedown", this);
|
||||
}
|
||||
}
|
||||
|
||||
WINDOW_DURATION_MAP.set(aWindow, {});
|
||||
},
|
||||
|
||||
_unregisterWindow: function(aWindow) {
|
||||
aWindow.removeEventListener("unload", this);
|
||||
let document = aWindow.document;
|
||||
|
||||
for (let areaID of CustomizableUI.areas) {
|
||||
let areaNode = document.getElementById(areaID);
|
||||
if (areaNode) {
|
||||
(areaNode.customizationTarget || areaNode).removeEventListener("mouseup", this);
|
||||
}
|
||||
}
|
||||
|
||||
for (let itemID of OTHER_MOUSEUP_MONITORED_ITEMS) {
|
||||
let item = document.getElementById(itemID);
|
||||
if (item) {
|
||||
item.removeEventListener("mouseup", this);
|
||||
}
|
||||
}
|
||||
|
||||
for (let itemID of MOUSEDOWN_MONITORED_ITEMS) {
|
||||
let item = document.getElementById(itemID);
|
||||
if (item) {
|
||||
item.removeEventListener("mousedown", this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "unload":
|
||||
this._unregisterWindow(aEvent.currentTarget);
|
||||
break;
|
||||
case "mouseup":
|
||||
this._handleMouseUp(aEvent);
|
||||
break;
|
||||
case "mousedown":
|
||||
this._handleMouseDown(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_handleMouseUp: function(aEvent) {
|
||||
let targetID = aEvent.currentTarget.id;
|
||||
|
||||
switch (targetID) {
|
||||
case "PlacesToolbarItems":
|
||||
this._PlacesToolbarItemsMouseUp(aEvent);
|
||||
break;
|
||||
case "PlacesChevron":
|
||||
this._PlacesChevronMouseUp(aEvent);
|
||||
break;
|
||||
case "menubar-items":
|
||||
this._menubarMouseUp(aEvent);
|
||||
break;
|
||||
default:
|
||||
this._checkForBuiltinItem(aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
_handleMouseDown: function(aEvent) {
|
||||
if (aEvent.currentTarget.id == "PanelUI-menu-button") {
|
||||
// _countMouseUpEvent expects a detail for the second argument,
|
||||
// but we don't really have any details to give. Just passing in
|
||||
// "button" is probably simpler than trying to modify
|
||||
// _countMouseUpEvent for this particular case.
|
||||
this._countMouseUpEvent("click-menu-button", "button", aEvent.button);
|
||||
}
|
||||
},
|
||||
|
||||
_PlacesChevronMouseUp: function(aEvent) {
|
||||
let target = aEvent.originalTarget;
|
||||
let result = target.id == "PlacesChevron" ? "chevron" : "overflowed-item";
|
||||
this._countMouseUpEvent("click-bookmarks-bar", result, aEvent.button);
|
||||
},
|
||||
|
||||
_PlacesToolbarItemsMouseUp: function(aEvent) {
|
||||
let target = aEvent.originalTarget;
|
||||
// If this isn't a bookmark-item, we don't care about it.
|
||||
if (!target.classList.contains("bookmark-item")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let result = target.hasAttribute("container") ? "container" : "item";
|
||||
this._countMouseUpEvent("click-bookmarks-bar", result, aEvent.button);
|
||||
},
|
||||
|
||||
_menubarMouseUp: function(aEvent) {
|
||||
let target = aEvent.originalTarget;
|
||||
let tag = target.localName
|
||||
let result = (tag == "menu" || tag == "menuitem") ? tag : "other";
|
||||
this._countMouseUpEvent("click-menubar", result, aEvent.button);
|
||||
},
|
||||
|
||||
_bookmarksMenuButtonMouseUp: function(aEvent) {
|
||||
let bookmarksWidget = CustomizableUI.getWidget("bookmarks-menu-button");
|
||||
if (bookmarksWidget.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
// In the menu panel, only the star is visible, and that opens up the
|
||||
// bookmarks subview.
|
||||
this._countMouseUpEvent("click-bookmarks-menu-button", "in-panel",
|
||||
aEvent.button);
|
||||
} else {
|
||||
let clickedItem = aEvent.originalTarget;
|
||||
// Did we click on the star, or the dropmarker? The star
|
||||
// has an anonid of "button". If we don't find that, we'll
|
||||
// assume we clicked on the dropmarker.
|
||||
let action = "menu";
|
||||
if (clickedItem.getAttribute("anonid") == "button") {
|
||||
// We clicked on the star - now we just need to record
|
||||
// whether or not we're adding a bookmark or editing an
|
||||
// existing one.
|
||||
let bookmarksMenuNode =
|
||||
bookmarksWidget.forWindow(aEvent.target.ownerGlobal).node;
|
||||
action = bookmarksMenuNode.hasAttribute("starred") ? "edit" : "add";
|
||||
}
|
||||
this._countMouseUpEvent("click-bookmarks-menu-button", action,
|
||||
aEvent.button);
|
||||
}
|
||||
},
|
||||
|
||||
_checkForBuiltinItem: function(aEvent) {
|
||||
let item = aEvent.originalTarget;
|
||||
|
||||
// We don't want to count clicks on the private browsing
|
||||
// button for privacy reasons. See bug 1176391.
|
||||
if (item.id == "privatebrowsing-button") {
|
||||
return;
|
||||
}
|
||||
|
||||
// We special-case the bookmarks-menu-button, since we want to
|
||||
// monitor more than just clicks on it.
|
||||
if (item.id == "bookmarks-menu-button" ||
|
||||
getIDBasedOnFirstIDedAncestor(item) == "bookmarks-menu-button") {
|
||||
this._bookmarksMenuButtonMouseUp(aEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perhaps we're seeing one of the default toolbar items
|
||||
// being clicked.
|
||||
if (ALL_BUILTIN_ITEMS.indexOf(item.id) != -1) {
|
||||
// Base case - we clicked directly on one of our built-in items,
|
||||
// and we can go ahead and register that click.
|
||||
this._countMouseUpEvent("click-builtin-item", item.id, aEvent.button);
|
||||
return;
|
||||
}
|
||||
|
||||
// If not, we need to check if the item's anonid is in our list
|
||||
// of built-in items to check.
|
||||
if (ALL_BUILTIN_ITEMS.indexOf(item.getAttribute("anonid")) != -1) {
|
||||
this._countMouseUpEvent("click-builtin-item", item.getAttribute("anonid"), aEvent.button);
|
||||
return;
|
||||
}
|
||||
|
||||
// If not, we need to check if one of the ancestors of the clicked
|
||||
// item is in our list of built-in items to check.
|
||||
let candidate = getIDBasedOnFirstIDedAncestor(item);
|
||||
if (ALL_BUILTIN_ITEMS.indexOf(candidate) != -1) {
|
||||
this._countMouseUpEvent("click-builtin-item", candidate, aEvent.button);
|
||||
}
|
||||
},
|
||||
|
||||
_getWindowMeasurements: function(aWindow, searchResult) {
|
||||
let document = aWindow.document;
|
||||
let result = {};
|
||||
|
||||
// Determine if the window is in the maximized, normal or
|
||||
// fullscreen state.
|
||||
result.sizemode = document.documentElement.getAttribute("sizemode");
|
||||
|
||||
// Determine if the Bookmarks bar is currently visible
|
||||
let bookmarksBar = document.getElementById("PersonalToolbar");
|
||||
result.bookmarksBarEnabled = bookmarksBar && !bookmarksBar.collapsed;
|
||||
|
||||
// Determine if the menubar is currently visible. On OS X, the menubar
|
||||
// is never shown, despite not having the collapsed attribute set.
|
||||
let menuBar = document.getElementById("toolbar-menubar");
|
||||
result.menuBarEnabled =
|
||||
menuBar && Services.appinfo.OS != "Darwin"
|
||||
&& menuBar.getAttribute("autohide") != "true";
|
||||
|
||||
// Determine if the titlebar is currently visible.
|
||||
result.titleBarEnabled = !Services.prefs.getBoolPref("browser.tabs.drawInTitlebar");
|
||||
|
||||
// Examine all customizable areas and see what default items
|
||||
// are present and missing.
|
||||
let defaultKept = [];
|
||||
let defaultMoved = [];
|
||||
let nondefaultAdded = [];
|
||||
|
||||
for (let areaID of CustomizableUI.areas) {
|
||||
let items = CustomizableUI.getWidgetIdsInArea(areaID);
|
||||
for (let item of items) {
|
||||
// Is this a default item?
|
||||
if (DEFAULT_ITEMS.indexOf(item) != -1) {
|
||||
// Ok, it's a default item - but is it in its default
|
||||
// toolbar? We use Array.isArray instead of checking for
|
||||
// toolbarID in DEFAULT_AREA_PLACEMENTS because an add-on might
|
||||
// be clever and give itself the id of "toString" or something.
|
||||
if (Array.isArray(DEFAULT_AREA_PLACEMENTS[areaID]) &&
|
||||
DEFAULT_AREA_PLACEMENTS[areaID].indexOf(item) != -1) {
|
||||
// The item is in its default toolbar
|
||||
defaultKept.push(item);
|
||||
} else {
|
||||
defaultMoved.push(item);
|
||||
}
|
||||
} else if (PALETTE_ITEMS.indexOf(item) != -1) {
|
||||
// It's a palette item that's been moved into a toolbar
|
||||
nondefaultAdded.push(item);
|
||||
}
|
||||
// else, it's provided by an add-on, and we won't record it.
|
||||
}
|
||||
}
|
||||
|
||||
// Now go through the items in the palette to see what default
|
||||
// items are in there.
|
||||
let paletteItems =
|
||||
CustomizableUI.getUnusedWidgets(aWindow.gNavToolbox.palette);
|
||||
let defaultRemoved = [];
|
||||
for (let item of paletteItems) {
|
||||
if (DEFAULT_ITEMS.indexOf(item.id) != -1) {
|
||||
defaultRemoved.push(item.id);
|
||||
}
|
||||
}
|
||||
|
||||
result.defaultKept = defaultKept;
|
||||
result.defaultMoved = defaultMoved;
|
||||
result.nondefaultAdded = nondefaultAdded;
|
||||
result.defaultRemoved = defaultRemoved;
|
||||
|
||||
// Next, determine how many add-on provided toolbars exist.
|
||||
let addonToolbars = 0;
|
||||
let toolbars = document.querySelectorAll("toolbar[customizable=true]");
|
||||
for (let toolbar of toolbars) {
|
||||
if (DEFAULT_AREAS.indexOf(toolbar.id) == -1) {
|
||||
addonToolbars++;
|
||||
}
|
||||
}
|
||||
result.addonToolbars = addonToolbars;
|
||||
|
||||
// Find out how many open tabs we have in each window
|
||||
let winEnumerator = Services.wm.getEnumerator("navigator:browser");
|
||||
let visibleTabs = [];
|
||||
let hiddenTabs = [];
|
||||
while (winEnumerator.hasMoreElements()) {
|
||||
let someWin = winEnumerator.getNext();
|
||||
if (someWin.gBrowser) {
|
||||
let visibleTabsNum = someWin.gBrowser.visibleTabs.length;
|
||||
visibleTabs.push(visibleTabsNum);
|
||||
hiddenTabs.push(someWin.gBrowser.tabs.length - visibleTabsNum);
|
||||
}
|
||||
}
|
||||
result.visibleTabs = visibleTabs;
|
||||
result.hiddenTabs = hiddenTabs;
|
||||
|
||||
if (Components.isSuccessCode(searchResult)) {
|
||||
result.currentSearchEngine = Services.search.currentEngine.name;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
getToolbarMeasures: function() {
|
||||
let result = this._firstWindowMeasurements || {};
|
||||
result.countableEvents = this._countableEvents;
|
||||
result.durations = this._durations;
|
||||
return result;
|
||||
},
|
||||
|
||||
getSyncState: function() {
|
||||
let result = {};
|
||||
for (let sub of ["desktop", "mobile"]) {
|
||||
let count = 0;
|
||||
try {
|
||||
count = Services.prefs.getIntPref("services.sync.clients.devices." + sub);
|
||||
} catch (ex) {}
|
||||
result[sub] = count;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
countCustomizationEvent: function(aEventType) {
|
||||
this._countEvent(["customize", aEventType]);
|
||||
},
|
||||
|
||||
countSearchEvent: function(source, query, selection) {
|
||||
this._countEvent(["search", source]);
|
||||
if ((/^[a-zA-Z]+:[^\/\\]/).test(query)) {
|
||||
this._countEvent(["search", "urlbar-keyword"]);
|
||||
}
|
||||
if (selection) {
|
||||
this._countEvent(["search", "selection", source, selection.index, selection.kind]);
|
||||
}
|
||||
},
|
||||
|
||||
countOneoffSearchEvent: function(id, type, where) {
|
||||
this._countEvent(["search-oneoff", id, type, where]);
|
||||
},
|
||||
|
||||
countSearchSettingsEvent: function(source) {
|
||||
this._countEvent(["click-builtin-item", source, "search-settings"]);
|
||||
},
|
||||
|
||||
countPanicEvent: function(timeId) {
|
||||
this._countEvent(["forget-button", timeId]);
|
||||
},
|
||||
|
||||
countTabMutingEvent: function(action, reason) {
|
||||
this._countEvent(["tab-audio-control", action, reason || "no reason given"]);
|
||||
},
|
||||
|
||||
countSyncedTabEvent: function(what, where) {
|
||||
// "what" will be, eg, "open"
|
||||
// "where" will be "toolbarbutton-subview" or "sidebar"
|
||||
this._countEvent(["synced-tabs", what, where]);
|
||||
},
|
||||
|
||||
countSidebarEvent: function(sidebarID, action) {
|
||||
// sidebarID is the ID of the sidebar (duh!)
|
||||
// action will be "hide" or "show"
|
||||
this._countEvent(["sidebar", sidebarID, action]);
|
||||
},
|
||||
|
||||
_logAwesomeBarSearchResult: function (url) {
|
||||
let spec = Services.search.parseSubmissionURL(url);
|
||||
if (spec.engine) {
|
||||
let matchedEngine = "default";
|
||||
if (spec.engine.name !== Services.search.currentEngine.name) {
|
||||
matchedEngine = "other";
|
||||
}
|
||||
this.countSearchEvent("autocomplete-" + matchedEngine);
|
||||
}
|
||||
},
|
||||
|
||||
_durations: {
|
||||
customization: [],
|
||||
},
|
||||
|
||||
onCustomizeStart: function(aWindow) {
|
||||
this._countEvent(["customize", "start"]);
|
||||
let durationMap = WINDOW_DURATION_MAP.get(aWindow);
|
||||
if (!durationMap) {
|
||||
durationMap = {};
|
||||
WINDOW_DURATION_MAP.set(aWindow, durationMap);
|
||||
}
|
||||
|
||||
durationMap.customization = {
|
||||
start: aWindow.performance.now(),
|
||||
bucket: this._bucket,
|
||||
};
|
||||
},
|
||||
|
||||
onCustomizeEnd: function(aWindow) {
|
||||
let durationMap = WINDOW_DURATION_MAP.get(aWindow);
|
||||
if (durationMap && "customization" in durationMap) {
|
||||
let duration = aWindow.performance.now() - durationMap.customization.start;
|
||||
this._durations.customization.push({
|
||||
duration: duration,
|
||||
bucket: durationMap.customization.bucket,
|
||||
});
|
||||
delete durationMap.customization;
|
||||
}
|
||||
},
|
||||
|
||||
_contextMenuItemWhitelist: new Set([
|
||||
"close-without-interaction", // for closing the menu without clicking it.
|
||||
"custom-page-item", // The ID we use for page-provided items
|
||||
"unknown", // The bucket for stuff with no id.
|
||||
// Everything we know of so far (which will exclude add-on items):
|
||||
"navigation", "back", "forward", "reload", "stop", "bookmarkpage",
|
||||
"spell-no-suggestions", "spell-add-to-dictionary",
|
||||
"spell-undo-add-to-dictionary", "openlinkincurrent", "openlinkintab",
|
||||
"openlink",
|
||||
// "openlinkprivate" intentionally omitted for privacy reasons. See bug 1176391.
|
||||
"bookmarklink", "savelink",
|
||||
"marklinkMenu", "copyemail", "copylink", "media-play", "media-pause",
|
||||
"media-mute", "media-unmute", "media-playbackrate",
|
||||
"media-playbackrate-050x", "media-playbackrate-100x",
|
||||
"media-playbackrate-125x", "media-playbackrate-150x", "media-playbackrate-200x",
|
||||
"media-showcontrols", "media-hidecontrols",
|
||||
"video-fullscreen", "leave-dom-fullscreen",
|
||||
"reloadimage", "viewimage", "viewvideo", "copyimage-contents", "copyimage",
|
||||
"copyvideourl", "copyaudiourl", "saveimage", "sendimage",
|
||||
"setDesktopBackground", "viewimageinfo", "viewimagedesc", "savevideo",
|
||||
"saveaudio", "video-saveimage", "sendvideo", "sendaudio",
|
||||
"ctp-play", "ctp-hide", "savepage", "pocket", "markpageMenu",
|
||||
"viewbgimage", "undo", "cut", "copy", "paste", "delete", "selectall",
|
||||
"keywordfield", "searchselect", "frame", "showonlythisframe",
|
||||
"openframeintab", "openframe", "reloadframe", "bookmarkframe", "saveframe",
|
||||
"printframe", "viewframesource", "viewframeinfo",
|
||||
"viewpartialsource-selection", "viewpartialsource-mathml",
|
||||
"viewsource", "viewinfo", "spell-check-enabled",
|
||||
"spell-add-dictionaries-main", "spell-dictionaries",
|
||||
"spell-dictionaries-menu", "spell-add-dictionaries",
|
||||
"bidi-text-direction-toggle", "bidi-page-direction-toggle", "inspect",
|
||||
"media-eme-learn-more"
|
||||
]),
|
||||
|
||||
_contextMenuInteractions: {},
|
||||
|
||||
registerContextMenuInteraction: function(keys, itemID) {
|
||||
if (itemID) {
|
||||
if (itemID == "openlinkprivate") {
|
||||
// Don't record anything, not even an other-item count
|
||||
// if the user chose to open in a private window. See
|
||||
// bug 1176391.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._contextMenuItemWhitelist.has(itemID)) {
|
||||
itemID = "other-item";
|
||||
}
|
||||
keys.push(itemID);
|
||||
}
|
||||
|
||||
this._countEvent(keys, this._contextMenuInteractions);
|
||||
},
|
||||
|
||||
getContextMenuInfo: function() {
|
||||
return this._contextMenuInteractions;
|
||||
},
|
||||
|
||||
_bucket: BUCKET_DEFAULT,
|
||||
_bucketTimer: null,
|
||||
|
||||
/**
|
||||
* Default bucket name, when no other bucket is active.
|
||||
*/
|
||||
get BUCKET_DEFAULT() {
|
||||
return BUCKET_DEFAULT;
|
||||
},
|
||||
|
||||
/**
|
||||
* Bucket prefix, for named buckets.
|
||||
*/
|
||||
get BUCKET_PREFIX() {
|
||||
return BUCKET_PREFIX;
|
||||
},
|
||||
|
||||
/**
|
||||
* Standard separator to use between different parts of a bucket name, such
|
||||
* as primary name and the time step string.
|
||||
*/
|
||||
get BUCKET_SEPARATOR() {
|
||||
return BUCKET_SEPARATOR;
|
||||
},
|
||||
|
||||
get currentBucket() {
|
||||
return this._bucket;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a named bucket for all countable events and select durections to be
|
||||
* put into.
|
||||
*
|
||||
* @param aName Name of bucket, or null for default bucket name (__DEFAULT__)
|
||||
*/
|
||||
setBucket: function(aName) {
|
||||
if (this._bucketTimer) {
|
||||
Timer.clearTimeout(this._bucketTimer);
|
||||
this._bucketTimer = null;
|
||||
}
|
||||
|
||||
if (aName)
|
||||
this._bucket = BUCKET_PREFIX + aName;
|
||||
else
|
||||
this._bucket = BUCKET_DEFAULT;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a bucket that expires at the rate of a given series of time steps.
|
||||
* Once the bucket expires, the current bucket will automatically revert to
|
||||
* the default bucket. While the bucket is expiring, it's name is postfixed
|
||||
* by '|' followed by a short string representation of the time step it's
|
||||
* currently in.
|
||||
* If any other bucket (expiring or normal) is set while an expiring bucket is
|
||||
* still expiring, the old expiring bucket stops expiring and the new bucket
|
||||
* immediately takes over.
|
||||
*
|
||||
* @param aName Name of bucket.
|
||||
* @param aTimeSteps An array of times in milliseconds to count up to before
|
||||
* reverting back to the default bucket. The array of times
|
||||
* is expected to be pre-sorted in ascending order.
|
||||
* For example, given a bucket name of 'bucket', the times:
|
||||
* [60000, 300000, 600000]
|
||||
* will result in the following buckets:
|
||||
* * bucket|1m - for the first 1 minute
|
||||
* * bucket|5m - for the following 4 minutes
|
||||
* (until 5 minutes after the start)
|
||||
* * bucket|10m - for the following 5 minutes
|
||||
* (until 10 minutes after the start)
|
||||
* * __DEFAULT__ - until a new bucket is set
|
||||
* @param aTimeOffset Time offset, in milliseconds, from which to start
|
||||
* counting. For example, if the first time step is 1000ms,
|
||||
* and the time offset is 300ms, then the next time step
|
||||
* will become active after 700ms. This affects all
|
||||
* following time steps also, meaning they will also all be
|
||||
* timed as though they started expiring 300ms before
|
||||
* setExpiringBucket was called.
|
||||
*/
|
||||
setExpiringBucket: function(aName, aTimeSteps, aTimeOffset = 0) {
|
||||
if (aTimeSteps.length === 0) {
|
||||
this.setBucket(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._bucketTimer) {
|
||||
Timer.clearTimeout(this._bucketTimer);
|
||||
this._bucketTimer = null;
|
||||
}
|
||||
|
||||
// Make a copy of the time steps array, so we can safely modify it without
|
||||
// modifying the original array that external code has passed to us.
|
||||
let steps = [...aTimeSteps];
|
||||
let msec = steps.shift();
|
||||
let postfix = this._toTimeStr(msec);
|
||||
this.setBucket(aName + BUCKET_SEPARATOR + postfix);
|
||||
|
||||
this._bucketTimer = Timer.setTimeout(() => {
|
||||
this._bucketTimer = null;
|
||||
this.setExpiringBucket(aName, steps, aTimeOffset + msec);
|
||||
}, msec - aTimeOffset);
|
||||
},
|
||||
|
||||
/**
|
||||
* Formats a time interval, in milliseconds, to a minimal non-localized string
|
||||
* representation. Format is: 'h' for hours, 'm' for minutes, 's' for seconds,
|
||||
* 'ms' for milliseconds.
|
||||
* Examples:
|
||||
* 65 => 65ms
|
||||
* 1000 => 1s
|
||||
* 60000 => 1m
|
||||
* 61000 => 1m01s
|
||||
*
|
||||
* @param aTimeMS Time in milliseconds
|
||||
*
|
||||
* @return Minimal string representation.
|
||||
*/
|
||||
_toTimeStr: function(aTimeMS) {
|
||||
let timeStr = "";
|
||||
|
||||
function reduce(aUnitLength, aSymbol) {
|
||||
if (aTimeMS >= aUnitLength) {
|
||||
let units = Math.floor(aTimeMS / aUnitLength);
|
||||
aTimeMS = aTimeMS - (units * aUnitLength)
|
||||
timeStr += units + aSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
reduce(MS_HOUR, "h");
|
||||
reduce(MS_MINUTE, "m");
|
||||
reduce(MS_SECOND, "s");
|
||||
reduce(1, "ms");
|
||||
|
||||
return timeStr;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the id of the first ancestor of aNode that has an id. If aNode
|
||||
* has no parent, or no ancestor has an id, returns null.
|
||||
*
|
||||
* @param aNode the node to find the first ID'd ancestor of
|
||||
*/
|
||||
function getIDBasedOnFirstIDedAncestor(aNode) {
|
||||
while (!aNode.id) {
|
||||
aNode = aNode.parentNode;
|
||||
if (!aNode) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return aNode.id;
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ EXTRA_JS_MODULES += [
|
|||
'AboutHome.jsm',
|
||||
'AboutNewTab.jsm',
|
||||
'AttributionCode.jsm',
|
||||
'BrowserUITelemetry.jsm',
|
||||
'BrowserUsageTelemetry.jsm',
|
||||
'CastingApps.jsm',
|
||||
'ContentClick.jsm',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue