Remove BrowserUITelemetry from Basilisk application

This commit is contained in:
Gaming4JC 2018-06-21 20:09:48 -04:00 committed by Roy Tam
commit 5315d7c162
12 changed files with 0 additions and 1006 deletions

View file

@ -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"

View file

@ -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");
},
};

View file

@ -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);

View file

@ -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);

View file

@ -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");

View file

@ -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"

View file

@ -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;

View file

@ -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();

View file

@ -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.

View file

@ -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) {

View file

@ -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;
}

View file

@ -8,7 +8,6 @@ EXTRA_JS_MODULES += [
'AboutHome.jsm',
'AboutNewTab.jsm',
'AttributionCode.jsm',
'BrowserUITelemetry.jsm',
'BrowserUsageTelemetry.jsm',
'CastingApps.jsm',
'ContentClick.jsm',