Files
tubestation/browser/components/customizableui/CustomizableWidgets.sys.mjs
Sandor Molnar 5095328e2d Backed out 5 changesets (bug 1918702) for causing bc failures @ browser_aaa_eventTelemetry_run_first.js CLOSED TREE
Backed out changeset f55480885aeb (bug 1918702)
Backed out changeset db1eaf09430d (bug 1918702)
Backed out changeset a9179f6e684d (bug 1918702)
Backed out changeset f9d3349e6fe3 (bug 1918702)
Backed out changeset 10d2957bbfe8 (bug 1918702)
2024-09-25 12:38:05 +03:00

693 lines
22 KiB
JavaScript

/* 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/. */
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
import { PrivateBrowsingUtils } from "resource://gre/modules/PrivateBrowsingUtils.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
CustomizableUI: "resource:///modules/CustomizableUI.sys.mjs",
LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
PanelMultiView: "resource:///modules/PanelMultiView.sys.mjs",
RecentlyClosedTabsAndWindowsMenuUtils:
"resource:///modules/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.sys.mjs",
Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs",
});
const kPrefCustomizationDebug = "browser.uiCustomization.debug";
const kPrefScreenshots = "extensions.screenshots.disabled";
ChromeUtils.defineLazyGetter(lazy, "log", () => {
let { ConsoleAPI } = ChromeUtils.importESModule(
"resource://gre/modules/Console.sys.mjs"
);
let debug = Services.prefs.getBoolPref(kPrefCustomizationDebug, false);
let consoleOptions = {
maxLogLevel: debug ? "all" : "log",
prefix: "CustomizableWidgets",
};
return new ConsoleAPI(consoleOptions);
});
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"screenshotsDisabled",
kPrefScreenshots,
false
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"SCREENSHOT_BROWSER_COMPONENT",
"screenshots.browser.component.enabled",
false
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"sidebarRevampEnabled",
"sidebar.revamp",
false
);
function setAttributes(aNode, aAttrs) {
let doc = aNode.ownerDocument;
for (let [name, value] of Object.entries(aAttrs)) {
if (!value) {
if (aNode.hasAttribute(name)) {
aNode.removeAttribute(name);
}
} else {
if (name == "shortcutId") {
continue;
}
if (name == "label" || name == "tooltiptext") {
let stringId = typeof value == "string" ? value : name;
let additionalArgs = [];
if (aAttrs.shortcutId) {
let shortcut = doc.getElementById(aAttrs.shortcutId);
if (shortcut) {
additionalArgs.push(lazy.ShortcutUtils.prettifyShortcut(shortcut));
}
}
value = lazy.CustomizableUI.getLocalizedProperty(
{ id: aAttrs.id },
stringId,
additionalArgs
);
}
aNode.setAttribute(name, value);
}
}
}
export const CustomizableWidgets = [
{
id: "history-panelmenu",
type: "view",
viewId: "PanelUI-history",
shortcutId: "key_gotoHistory",
tooltiptext: "history-panelmenu.tooltiptext2",
recentlyClosedTabsPanel: "appMenu-library-recentlyClosedTabs",
recentlyClosedWindowsPanel: "appMenu-library-recentlyClosedWindows",
handleEvent(event) {
switch (event.type) {
case "PanelMultiViewHidden":
this.onPanelMultiViewHidden(event);
break;
case "ViewShowing":
this.onSubViewShowing(event);
break;
case "unload":
this.onWindowUnload(event);
break;
case "command": {
let { target } = event;
let { PanelUI, PlacesCommandHook } = target.ownerGlobal;
if (target.id == "appMenuRecentlyClosedTabs") {
PanelUI.showSubView(this.recentlyClosedTabsPanel, target);
} else if (target.id == "appMenuRecentlyClosedWindows") {
PanelUI.showSubView(this.recentlyClosedWindowsPanel, target);
} else if (target.id == "appMenuSearchHistory") {
PlacesCommandHook.searchHistory();
} else if (target.id == "PanelUI-historyMore") {
PlacesCommandHook.showPlacesOrganizer("History");
lazy.CustomizableUI.hidePanelForNode(target);
}
break;
}
default:
throw new Error(`Unsupported event for '${this.id}'`);
}
},
onViewShowing(event) {
if (this._panelMenuView) {
return;
}
let panelview = event.target;
let document = panelview.ownerDocument;
let window = document.defaultView;
const closedTabCount = lazy.SessionStore.getClosedTabCount();
lazy.PanelMultiView.getViewNode(
document,
"appMenuRecentlyClosedTabs"
).disabled = closedTabCount == 0;
lazy.PanelMultiView.getViewNode(
document,
"appMenuRecentlyClosedWindows"
).disabled = lazy.SessionStore.getClosedWindowCount(window) == 0;
lazy.PanelMultiView.getViewNode(
document,
"appMenu-restoreSession"
).hidden = !lazy.SessionStore.canRestoreLastSession;
// We restrict the amount of results to 42. Not 50, but 42. Why? Because 42.
let query =
"place:queryType=" +
Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING +
"&maxResults=42&excludeQueries=1";
this._panelMenuView = new window.PlacesPanelview(
query,
document.getElementById("appMenu_historyMenu"),
panelview
);
// When either of these sub-subviews show, populate them with recently closed
// objects data.
lazy.PanelMultiView.getViewNode(
document,
this.recentlyClosedTabsPanel
).addEventListener("ViewShowing", this);
lazy.PanelMultiView.getViewNode(
document,
this.recentlyClosedWindowsPanel
).addEventListener("ViewShowing", this);
// When the popup is hidden (thus the panelmultiview node as well), make
// sure to stop listening to PlacesDatabase updates.
panelview.panelMultiView.addEventListener("PanelMultiViewHidden", this);
panelview.addEventListener("command", this);
window.addEventListener("unload", this);
},
onViewHiding() {
lazy.log.debug("History view is being hidden!");
},
onPanelMultiViewHidden(event) {
let panelMultiView = event.target;
let document = panelMultiView.ownerDocument;
if (this._panelMenuView) {
this._panelMenuView.uninit();
delete this._panelMenuView;
lazy.PanelMultiView.getViewNode(
document,
this.recentlyClosedTabsPanel
).removeEventListener("ViewShowing", this);
lazy.PanelMultiView.getViewNode(
document,
this.recentlyClosedWindowsPanel
).removeEventListener("ViewShowing", this);
lazy.PanelMultiView.getViewNode(
document,
this.viewId
).removeEventListener("command", this);
}
panelMultiView.removeEventListener("PanelMultiViewHidden", this);
},
onWindowUnload() {
if (this._panelMenuView) {
delete this._panelMenuView;
}
},
onSubViewShowing(event) {
let panelview = event.target;
let document = event.target.ownerDocument;
let window = document.defaultView;
this._panelMenuView.clearAllContents(panelview);
const utils = lazy.RecentlyClosedTabsAndWindowsMenuUtils;
const fragment =
panelview.id == this.recentlyClosedTabsPanel
? utils.getTabsFragment(window, "toolbarbutton", true)
: utils.getWindowsFragment(window, "toolbarbutton", true);
let elementCount = fragment.childElementCount;
this._panelMenuView._setEmptyPopupStatus(panelview, !elementCount);
if (!elementCount) {
return;
}
let body = document.createXULElement("vbox");
body.className = "panel-subview-body";
body.appendChild(fragment);
let separator = document.createXULElement("toolbarseparator");
let footer;
while (--elementCount >= 0) {
let element = body.children[elementCount];
lazy.CustomizableUI.addShortcut(element);
element.classList.add("subviewbutton");
if (element.classList.contains("restoreallitem")) {
footer = element;
element.classList.add("panel-subview-footer-button");
} else {
element.classList.add("subviewbutton-iconic", "bookmark-item");
}
}
panelview.appendChild(body);
panelview.appendChild(separator);
panelview.appendChild(footer);
},
},
{
id: "save-page-button",
l10nId: "toolbar-button-save-page",
shortcutId: "key_savePage",
onCreated(aNode) {
aNode.setAttribute("command", "Browser:SavePage");
},
},
{
id: "print-button",
l10nId: "navbar-print",
shortcutId: "printKb",
keepBroadcastAttributesWhenCustomizing: true,
onCreated(aNode) {
aNode.setAttribute("command", "cmd_printPreviewToggle");
},
},
{
id: "find-button",
shortcutId: "key_find",
tooltiptext: "find-button.tooltiptext3",
onCommand(aEvent) {
let win = aEvent.target.ownerGlobal;
if (win.gLazyFindCommand) {
win.gLazyFindCommand("onFindCommand");
}
},
},
{
id: "open-file-button",
l10nId: "toolbar-button-open-file",
shortcutId: "openFileKb",
onCreated(aNode) {
aNode.setAttribute("command", "Browser:OpenFile");
},
},
{
id: "sidebar-button",
tooltiptext: "sidebar-button.tooltiptext2",
defaultArea: "nav-bar",
_introducedByPref: "sidebar.revamp",
onCommand(aEvent) {
const { SidebarController } = aEvent.target.ownerGlobal;
if (lazy.sidebarRevampEnabled) {
SidebarController.handleToolbarButtonClick();
} else {
SidebarController.toggle();
}
},
onCreated(aNode) {
if (!lazy.sidebarRevampEnabled) {
// Add an observer so the button is checked while the sidebar is open
let doc = aNode.ownerDocument;
let obChecked = doc.createXULElement("observes");
obChecked.setAttribute("element", "sidebar-box");
obChecked.setAttribute("attribute", "checked");
let obPosition = doc.createXULElement("observes");
obPosition.setAttribute("element", "sidebar-box");
obPosition.setAttribute("attribute", "positionend");
aNode.appendChild(obChecked);
aNode.appendChild(obPosition);
}
},
},
{
id: "zoom-controls",
type: "custom",
tooltiptext: "zoom-controls.tooltiptext2",
onBuild(aDocument) {
let buttons = [
{
id: "zoom-out-button",
command: "cmd_fullZoomReduce",
label: true,
closemenu: "none",
tooltiptext: "tooltiptext2",
shortcutId: "key_fullZoomReduce",
class: "toolbarbutton-1 toolbarbutton-combined",
},
{
id: "zoom-reset-button",
command: "cmd_fullZoomReset",
closemenu: "none",
tooltiptext: "tooltiptext2",
shortcutId: "key_fullZoomReset",
class: "toolbarbutton-1 toolbarbutton-combined",
},
{
id: "zoom-in-button",
command: "cmd_fullZoomEnlarge",
closemenu: "none",
label: true,
tooltiptext: "tooltiptext2",
shortcutId: "key_fullZoomEnlarge",
class: "toolbarbutton-1 toolbarbutton-combined",
},
];
let node = aDocument.createXULElement("toolbaritem");
node.setAttribute("id", "zoom-controls");
node.setAttribute(
"label",
lazy.CustomizableUI.getLocalizedProperty(this, "label")
);
node.setAttribute(
"title",
lazy.CustomizableUI.getLocalizedProperty(this, "tooltiptext")
);
// Set this as an attribute in addition to the property to make sure we can style correctly.
node.setAttribute("removable", "true");
node.classList.add("chromeclass-toolbar-additional");
node.classList.add("toolbaritem-combined-buttons");
buttons.forEach(function (aButton, aIndex) {
if (aIndex != 0) {
node.appendChild(aDocument.createXULElement("separator"));
}
let btnNode = aDocument.createXULElement("toolbarbutton");
setAttributes(btnNode, aButton);
node.appendChild(btnNode);
});
return node;
},
},
{
id: "edit-controls",
type: "custom",
tooltiptext: "edit-controls.tooltiptext2",
onBuild(aDocument) {
let buttons = [
{
id: "cut-button",
command: "cmd_cut",
label: true,
tooltiptext: "tooltiptext2",
shortcutId: "key_cut",
class: "toolbarbutton-1 toolbarbutton-combined",
},
{
id: "copy-button",
command: "cmd_copy",
label: true,
tooltiptext: "tooltiptext2",
shortcutId: "key_copy",
class: "toolbarbutton-1 toolbarbutton-combined",
},
{
id: "paste-button",
command: "cmd_paste",
label: true,
tooltiptext: "tooltiptext2",
shortcutId: "key_paste",
class: "toolbarbutton-1 toolbarbutton-combined",
},
];
let node = aDocument.createXULElement("toolbaritem");
node.setAttribute("id", "edit-controls");
node.setAttribute(
"label",
lazy.CustomizableUI.getLocalizedProperty(this, "label")
);
node.setAttribute(
"title",
lazy.CustomizableUI.getLocalizedProperty(this, "tooltiptext")
);
// Set this as an attribute in addition to the property to make sure we can style correctly.
node.setAttribute("removable", "true");
node.classList.add("chromeclass-toolbar-additional");
node.classList.add("toolbaritem-combined-buttons");
buttons.forEach(function (aButton, aIndex) {
if (aIndex != 0) {
node.appendChild(aDocument.createXULElement("separator"));
}
let btnNode = aDocument.createXULElement("toolbarbutton");
setAttributes(btnNode, aButton);
node.appendChild(btnNode);
});
let listener = {
onWidgetInstanceRemoved: (aWidgetId, aDoc) => {
if (aWidgetId != this.id || aDoc != aDocument) {
return;
}
lazy.CustomizableUI.removeListener(listener);
},
onWidgetOverflow(aWidgetNode) {
if (aWidgetNode == node) {
node.ownerGlobal.updateEditUIVisibility();
}
},
onWidgetUnderflow(aWidgetNode) {
if (aWidgetNode == node) {
node.ownerGlobal.updateEditUIVisibility();
}
},
};
lazy.CustomizableUI.addListener(listener);
return node;
},
},
{
id: "characterencoding-button",
l10nId: "repair-text-encoding-button",
onCommand(aEvent) {
aEvent.view.BrowserCommands.forceEncodingDetection();
},
},
{
id: "email-link-button",
l10nId: "toolbar-button-email-link",
onCommand(aEvent) {
let win = aEvent.view;
win.MailIntegration.sendLinkForBrowser(win.gBrowser.selectedBrowser);
},
},
{
id: "logins-button",
l10nId: "toolbar-button-logins",
onCommand(aEvent) {
let window = aEvent.view;
lazy.LoginHelper.openPasswordManager(window, { entryPoint: "toolbar" });
},
},
];
if (Services.prefs.getBoolPref("identity.fxaccounts.enabled")) {
CustomizableWidgets.push({
id: "sync-button",
l10nId: "toolbar-button-synced-tabs",
type: "view",
viewId: "PanelUI-remotetabs",
onViewShowing(aEvent) {
let panelview = aEvent.target;
let doc = panelview.ownerDocument;
let syncNowBtn = panelview.querySelector(".syncnow-label");
let l10nId = syncNowBtn.getAttribute(
panelview.ownerGlobal.gSync._isCurrentlySyncing
? "syncing-data-l10n-id"
: "sync-now-data-l10n-id"
);
doc.l10n.setAttributes(syncNowBtn, l10nId);
let SyncedTabsPanelList = doc.defaultView.SyncedTabsPanelList;
panelview.syncedTabsPanelList = new SyncedTabsPanelList(
panelview,
lazy.PanelMultiView.getViewNode(doc, "PanelUI-remotetabs-deck"),
lazy.PanelMultiView.getViewNode(doc, "PanelUI-remotetabs-tabslist")
);
panelview.addEventListener("command", this);
let syncNowButton = lazy.PanelMultiView.getViewNode(
aEvent.target.ownerDocument,
"PanelUI-remotetabs-syncnow"
);
syncNowButton.addEventListener("mouseover", this);
},
onViewHiding(aEvent) {
let panelview = aEvent.target;
panelview.syncedTabsPanelList.destroy();
panelview.syncedTabsPanelList = null;
panelview.removeEventListener("command", this);
let syncNowButton = lazy.PanelMultiView.getViewNode(
aEvent.target.ownerDocument,
"PanelUI-remotetabs-syncnow"
);
syncNowButton.removeEventListener("mouseover", this);
},
handleEvent(aEvent) {
let button = aEvent.target;
let { gSync } = button.ownerGlobal;
switch (aEvent.type) {
case "mouseover":
gSync.refreshSyncButtonsTooltip();
break;
case "command": {
switch (button.id) {
case "PanelUI-remotetabs-syncnow":
gSync.doSync();
break;
case "PanelUI-remotetabs-view-managedevices":
gSync.openDevicesManagementPage("syncedtabs-menupanel");
break;
case "PanelUI-remotetabs-tabsdisabledpane-button":
case "PanelUI-remotetabs-setupsync-button":
case "PanelUI-remotetabs-syncdisabled-button":
case "PanelUI-remotetabs-reauthsync-button":
case "PanelUI-remotetabs-unverified-button":
gSync.openPrefs("synced-tabs");
break;
case "PanelUI-remotetabs-connect-device-button":
gSync.openConnectAnotherDevice("synced-tabs");
break;
}
}
}
},
});
}
if (!lazy.screenshotsDisabled) {
CustomizableWidgets.push({
id: "screenshot-button",
shortcutId: "key_screenshot",
l10nId: "screenshot-toolbarbutton",
onCommand(aEvent) {
if (lazy.SCREENSHOT_BROWSER_COMPONENT) {
Services.obs.notifyObservers(
aEvent.currentTarget.ownerGlobal,
"menuitem-screenshot",
"ToolbarButton"
);
} else {
Services.obs.notifyObservers(
null,
"menuitem-screenshot-extension",
"toolbar"
);
}
},
onCreated(aNode) {
aNode.ownerGlobal.MozXULElement.insertFTLIfNeeded(
"browser/screenshots.ftl"
);
Services.obs.addObserver(this, "toggle-screenshot-disable");
},
observe(subj, topic, data) {
let document = subj.document;
let button = document.getElementById("screenshot-button");
if (!button) {
return;
}
if (data == "true") {
button.setAttribute("disabled", "true");
} else {
button.removeAttribute("disabled");
}
},
});
}
let preferencesButton = {
id: "preferences-button",
l10nId: "toolbar-settings-button",
onCommand(aEvent) {
let win = aEvent.target.ownerGlobal;
win.openPreferences(undefined);
},
};
if (AppConstants.platform == "macosx") {
preferencesButton.shortcutId = "key_preferencesCmdMac";
}
CustomizableWidgets.push(preferencesButton);
if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) {
CustomizableWidgets.push({
id: "panic-button",
type: "view",
viewId: "PanelUI-panicView",
forgetButtonCalled(aEvent) {
let doc = aEvent.target.ownerDocument;
let group = doc.getElementById("PanelUI-panic-timeSpan");
let itemsToClear = [
"cookies",
"history",
"openWindows",
"formdata",
"sessions",
"cache",
"downloads",
"offlineApps",
];
let newWindowPrivateState = PrivateBrowsingUtils.isWindowPrivate(
doc.defaultView
)
? "private"
: "non-private";
let promise = lazy.Sanitizer.sanitize(itemsToClear, {
ignoreTimespan: false,
range: lazy.Sanitizer.getClearRange(+group.value),
privateStateForNewWindow: newWindowPrivateState,
});
promise.then(function () {
let otherWindow = Services.wm.getMostRecentWindow("navigator:browser");
if (otherWindow.closed) {
console.error("Got a closed window!");
}
if (otherWindow.PanicButtonNotifier) {
otherWindow.PanicButtonNotifier.notify();
} else {
otherWindow.PanicButtonNotifierShouldNotify = true;
}
});
},
handleEvent(aEvent) {
switch (aEvent.type) {
case "command":
this.forgetButtonCalled(aEvent);
break;
}
},
onViewShowing(aEvent) {
let win = aEvent.target.ownerGlobal;
let doc = win.document;
let eventBlocker = null;
eventBlocker = doc.l10n.translateElements([aEvent.target]);
let forgetButton = aEvent.target.querySelector(
"#PanelUI-panic-view-button"
);
let group = doc.getElementById("PanelUI-panic-timeSpan");
group.selectedItem = doc.getElementById("PanelUI-panic-5min");
forgetButton.addEventListener("command", this);
if (eventBlocker) {
aEvent.detail.addBlocker(eventBlocker);
}
},
onViewHiding(aEvent) {
let forgetButton = aEvent.target.querySelector(
"#PanelUI-panic-view-button"
);
forgetButton.removeEventListener("command", this);
},
});
}
if (PrivateBrowsingUtils.enabled) {
CustomizableWidgets.push({
id: "privatebrowsing-button",
l10nId: "toolbar-button-new-private-window",
shortcutId: "key_privatebrowsing",
onCommand(e) {
let win = e.target.ownerGlobal;
win.OpenBrowserWindow({ private: true });
},
});
}