main-popupset.js (23273B)
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 document.addEventListener( 7 "DOMContentLoaded", 8 () => { 9 const lazy = {}; 10 ChromeUtils.defineESModuleGetters(lazy, { 11 TabMetrics: "moz-src:///browser/components/tabbrowser/TabMetrics.sys.mjs", 12 TabNotes: "moz-src:///browser/components/tabnotes/TabNotes.sys.mjs", 13 }); 14 let mainPopupSet = document.getElementById("mainPopupSet"); 15 // eslint-disable-next-line complexity 16 mainPopupSet.addEventListener("command", event => { 17 switch (event.target.id) { 18 // == tabContextMenu == 19 case "context_openANewTab": 20 gBrowser.addAdjacentNewTab(TabContextMenu.contextTab); 21 break; 22 case "context_moveTabToNewGroup": 23 TabContextMenu.moveTabsToNewGroup(); 24 break; 25 case "context_ungroupTab": 26 TabContextMenu.ungroupTabs(); 27 break; 28 case "context_moveSplitViewToNewGroup": 29 TabContextMenu.moveSplitViewToNewGroup(); 30 break; 31 case "context_ungroupSplitView": 32 TabContextMenu.ungroupSplitViews(); 33 break; 34 case "context_moveTabToSplitView": 35 TabContextMenu.moveTabsToSplitView(); 36 break; 37 case "context_separateSplitView": 38 TabContextMenu.unsplitTabs(); 39 break; 40 case "context_reloadTab": 41 gBrowser.reloadTab(TabContextMenu.contextTab); 42 break; 43 case "context_reloadSelectedTabs": 44 gBrowser.reloadMultiSelectedTabs(); 45 break; 46 case "context_playTab": 47 TabContextMenu.contextTab.resumeDelayedMedia(); 48 break; 49 case "context_playSelectedTabs": 50 gBrowser.resumeDelayedMediaOnMultiSelectedTabs( 51 TabContextMenu.contextTab 52 ); 53 break; 54 case "context_toggleMuteTab": 55 TabContextMenu.contextTab.toggleMuteAudio(); 56 break; 57 case "context_toggleMuteSelectedTabs": 58 gBrowser.toggleMuteAudioOnMultiSelectedTabs( 59 TabContextMenu.contextTab 60 ); 61 break; 62 case "context_pinTab": 63 gBrowser.pinTab(TabContextMenu.contextTab, { 64 telemetrySource: lazy.TabMetrics.METRIC_SOURCE.TAB_MENU, 65 }); 66 break; 67 case "context_unpinTab": 68 gBrowser.unpinTab(TabContextMenu.contextTab); 69 break; 70 case "context_pinSelectedTabs": 71 gBrowser.pinMultiSelectedTabs(); 72 break; 73 case "context_unpinSelectedTabs": 74 gBrowser.unpinMultiSelectedTabs(); 75 break; 76 case "context_duplicateTab": 77 duplicateTabIn(TabContextMenu.contextTab, "tab"); 78 break; 79 case "context_duplicateTabs": 80 TabContextMenu.duplicateSelectedTabs(); 81 break; 82 case "context_bookmarkSelectedTabs": 83 PlacesCommandHook.bookmarkTabs(gBrowser.selectedTabs); 84 break; 85 case "context_bookmarkTab": 86 PlacesCommandHook.bookmarkTabs([TabContextMenu.contextTab]); 87 break; 88 case "context_addNote": 89 case "context_editNote": 90 gBrowser.tabNoteMenu.openPanel(TabContextMenu.contextTab, { 91 telemetrySource: lazy.TabNotes.TELEMETRY_SOURCE.TAB_CONTEXT_MENU, 92 }); 93 break; 94 case "context_deleteNote": 95 TabContextMenu.deleteTabNotes(); 96 break; 97 case "context_moveToStart": 98 gBrowser.moveTabsToStart(TabContextMenu.contextTab); 99 break; 100 case "context_moveToEnd": 101 gBrowser.moveTabsToEnd(TabContextMenu.contextTab); 102 break; 103 case "context_openTabInWindow": 104 gBrowser.replaceTabsWithWindow(TabContextMenu.contextTab); 105 break; 106 case "context_selectAllTabs": 107 gBrowser.selectAllTabs(); 108 break; 109 case "context_closeTab": 110 TabContextMenu.closeContextTabs(); 111 break; 112 case "context_closeDuplicateTabs": 113 gBrowser.removeDuplicateTabs( 114 TabContextMenu.contextTab, 115 lazy.TabMetrics.userTriggeredContext() 116 ); 117 break; 118 case "context_closeTabsToTheStart": 119 gBrowser.removeTabsToTheStartFrom( 120 TabContextMenu.contextTab, 121 lazy.TabMetrics.userTriggeredContext() 122 ); 123 break; 124 case "context_closeTabsToTheEnd": 125 gBrowser.removeTabsToTheEndFrom( 126 TabContextMenu.contextTab, 127 lazy.TabMetrics.userTriggeredContext() 128 ); 129 break; 130 case "context_closeOtherTabs": 131 gBrowser.removeAllTabsBut( 132 TabContextMenu.contextTab, 133 lazy.TabMetrics.userTriggeredContext() 134 ); 135 break; 136 case "context_unloadTab": 137 TabContextMenu.explicitUnloadTabs(); 138 break; 139 case "context_fullscreenAutohide": 140 FullScreen.setAutohide(); 141 break; 142 case "context_fullscreenExit": 143 BrowserCommands.fullScreen(); 144 break; 145 146 // == open-tab-group-context-menu == 147 case "open-tab-group-context-menu_moveToNewWindow": 148 { 149 let { tabGroupId } = event.target.parentElement.triggerNode.dataset; 150 let tabGroup = gBrowser.getTabGroupById(tabGroupId); 151 tabGroup.ownerGlobal.gBrowser.replaceGroupWithWindow(tabGroup); 152 } 153 break; 154 case "open-tab-group-context-menu_moveToThisWindow": 155 { 156 let { tabGroupId } = event.target.parentElement.triggerNode.dataset; 157 let otherTabGroup = gBrowser.getTabGroupById(tabGroupId); 158 let adoptedTabGroup = gBrowser.adoptTabGroup(otherTabGroup, { 159 tabIndex: gBrowser.tabs.length, 160 }); 161 adoptedTabGroup.select(); 162 } 163 break; 164 case "open-tab-group-context-menu_delete": 165 { 166 let { tabGroupId } = event.target.parentElement.triggerNode.dataset; 167 let tabGroup = gBrowser.getTabGroupById(tabGroupId); 168 // Tabs need to be removed by their owning `Tabbrowser` or else 169 // there are errors. 170 tabGroup.ownerGlobal.gBrowser.removeTabGroup( 171 tabGroup, 172 lazy.TabMetrics.userTriggeredContext( 173 lazy.TabMetrics.METRIC_SOURCE.TAB_OVERFLOW_MENU 174 ) 175 ); 176 } 177 break; 178 179 // == saved-tab-group-context-menu == 180 case "saved-tab-group-context-menu_openInThisWindow": 181 { 182 let { tabGroupId } = event.target.parentElement.triggerNode.dataset; 183 SessionStore.openSavedTabGroup(tabGroupId, window, { 184 source: lazy.TabMetrics.METRIC_SOURCE.TAB_OVERFLOW_MENU, 185 }); 186 } 187 break; 188 case "saved-tab-group-context-menu_openInNewWindow": 189 { 190 // TODO Bug 1940112: "Open Group in New Window" should directly restore saved tab groups into a new window 191 let { tabGroupId } = event.target.parentElement.triggerNode.dataset; 192 let tabGroup = SessionStore.openSavedTabGroup(tabGroupId, window, { 193 source: lazy.TabMetrics.METRIC_SOURCE.TAB_OVERFLOW_MENU, 194 }); 195 gBrowser.replaceGroupWithWindow(tabGroup); 196 } 197 break; 198 case "saved-tab-group-context-menu_delete": 199 { 200 let { tabGroupId } = event.target.parentElement.triggerNode.dataset; 201 SessionStore.forgetSavedTabGroup(tabGroupId); 202 } 203 break; 204 // == editBookmarkPanel == 205 case "editBookmarkPanel_showForNewBookmarks": 206 StarUI.onShowForNewBookmarksCheckboxCommand(); 207 break; 208 case "editBookmarkPanelDoneButton": 209 StarUI.panel.hidePopup(); 210 break; 211 case "editBookmarkPanelRemoveButton": 212 StarUI.removeBookmarkButtonCommand(); 213 break; 214 215 // == sidebarMenu-popup == 216 case "sidebar-switcher-bookmarks": 217 SidebarController.show("viewBookmarksSidebar"); 218 break; 219 case "sidebar-switcher-history": 220 SidebarController.show("viewHistorySidebar"); 221 break; 222 case "sidebar-switcher-tabs": 223 SidebarController.show("viewTabsSidebar"); 224 break; 225 case "sidebar-reverse-position": 226 SidebarController.reversePosition(); 227 break; 228 case "sidebar-menu-close": 229 // Close the sidebar UI, but leave it otherwise in its current state 230 SidebarController.hide({ dismissPanel: false }); 231 break; 232 233 // == toolbar-context-menu == 234 case "toolbar-context-manage-extension": 235 ToolbarContextMenu.openAboutAddonsForContextAction( 236 event.target.parentElement 237 ); 238 break; 239 case "toolbar-context-remove-extension": 240 ToolbarContextMenu.removeExtensionForContextAction( 241 event.target.parentElement 242 ); 243 break; 244 case "toolbar-context-report-extension": 245 ToolbarContextMenu.reportExtensionForContextAction( 246 event.target.parentElement, 247 "toolbar_context_menu" 248 ); 249 break; 250 case "toolbar-context-move-to-panel": 251 gCustomizeMode.addToPanel( 252 event.target.parentNode.triggerNode, 253 "toolbar-context-menu" 254 ); 255 break; 256 case "toolbar-context-autohide-downloads-button": 257 ToolbarContextMenu.onDownloadsAutoHideChange(event); 258 break; 259 case "toolbar-context-always-show-extensions-button": 260 if (event.target.hasAttribute("checked")) { 261 gUnifiedExtensions.showExtensionsButtonInToolbar(); 262 } else { 263 gUnifiedExtensions.hideExtensionsButtonFromToolbar(); 264 } 265 break; 266 case "toolbar-context-remove-from-toolbar": 267 if ( 268 event.target.parentNode.triggerNode === gUnifiedExtensions.button 269 ) { 270 gUnifiedExtensions.hideExtensionsButtonFromToolbar(); 271 break; 272 } 273 gCustomizeMode.removeFromArea( 274 event.target.parentNode.triggerNode, 275 "toolbar-context-menu" 276 ); 277 break; 278 case "toolbar-context-pin-to-toolbar": 279 gUnifiedExtensions.onPinToToolbarChange( 280 event.target.parentElement, 281 event 282 ); 283 break; 284 case "toolbar-context-always-open-downloads-panel": 285 ToolbarContextMenu.onDownloadsAlwaysOpenPanelChange(event); 286 break; 287 case "toolbar-context-reloadSelectedTab": 288 case "toolbar-context-reloadSelectedTabs": 289 gBrowser.reloadMultiSelectedTabs(); 290 break; 291 case "toolbar-context-bookmarkSelectedTab": 292 case "toolbar-context-bookmarkSelectedTabs": 293 PlacesCommandHook.bookmarkTabs(gBrowser.selectedTabs); 294 break; 295 case "toolbar-context-selectAllTabs": 296 gBrowser.selectAllTabs(); 297 break; 298 case "toolbar-context-customize": 299 gCustomizeMode.enter(); 300 break; 301 case "toolbar-context-toggle-vertical-tabs": 302 SidebarController.toggleVerticalTabs(); 303 break; 304 case "toolbar-context-customize-sidebar": 305 SidebarController.show("viewCustomizeSidebar"); 306 break; 307 case "toolbar-context-full-screen-autohide": 308 FullScreen.setAutohide(); 309 break; 310 case "toolbar-context-full-screen-exit": 311 BrowserCommands.fullScreen(); 312 break; 313 314 // == pictureInPictureToggleContextMenu == 315 case "context_HidePictureInPictureToggle": 316 PictureInPicture.hideToggle(); 317 break; 318 case "context_MovePictureInPictureToggle": 319 PictureInPicture.moveToggle(); 320 break; 321 322 // == pageActionContextMenu == 323 case "pageActionContextMenuManageExtension": 324 BrowserPageActions.openAboutAddonsForContextAction(); 325 break; 326 case "pageActionContextMenuRemoveExtension": 327 BrowserPageActions.removeExtensionForContextAction(); 328 break; 329 330 // == SyncedTabsSidebarContext == 331 case "syncedTabsManageDevices": 332 gSync.openDevicesManagementPage("syncedtabs-sidebar"); 333 break; 334 335 // == unified-extensions-context-menu == 336 case "unified-extensions-context-menu-pin-to-toolbar": 337 gUnifiedExtensions.onPinToToolbarChange( 338 event.target.parentElement, 339 event 340 ); 341 break; 342 case "unified-extensions-context-menu-move-widget-up": 343 gUnifiedExtensions.moveWidget(event.target.parentElement, "up"); 344 break; 345 case "unified-extensions-context-menu-move-widget-down": 346 gUnifiedExtensions.moveWidget(event.target.parentElement, "down"); 347 break; 348 case "unified-extensions-context-menu-manage-extension": 349 gUnifiedExtensions.manageExtension(event.target.parentElement); 350 break; 351 case "unified-extensions-context-menu-remove-extension": 352 gUnifiedExtensions.removeExtension(event.target.parentElement); 353 break; 354 case "unified-extensions-context-menu-report-extension": 355 gUnifiedExtensions.reportExtension(event.target.parentElement); 356 break; 357 358 // == full-page-translations-panel-settings-menupopup == 359 case "translations-panel-settings-always-offer-translation": 360 FullPageTranslationsPanel.onAlwaysOfferTranslations(); 361 break; 362 case "translations-panel-settings-always-translate": 363 FullPageTranslationsPanel.onAlwaysTranslateLanguage(); 364 break; 365 case "translations-panel-settings-never-translate": 366 FullPageTranslationsPanel.onNeverTranslateLanguage(); 367 break; 368 case "translations-panel-settings-never-translate-site": 369 FullPageTranslationsPanel.onNeverTranslateSite(); 370 break; 371 case "translations-panel-manage-languages": 372 FullPageTranslationsPanel.openManageLanguages(); 373 break; 374 case "translations-panel-about": 375 FullPageTranslationsPanel.onAboutTranslations(); 376 break; 377 378 // == select-translations-panel-settings-menupopup == 379 case "select-translations-panel-open-settings-page-menuitem": 380 SelectTranslationsPanel.openTranslationsSettingsPage(); 381 break; 382 case "select-translations-panel-about-translations-menuitem": 383 SelectTranslationsPanel.onAboutTranslations(); 384 break; 385 386 // == customizationPanelItemContextMenu == 387 case "customizationPanelItemContextMenuManageExtension": 388 ToolbarContextMenu.openAboutAddonsForContextAction( 389 event.target.parentElement 390 ); 391 break; 392 393 case "customizationPanelItemContextMenuRemoveExtension": 394 ToolbarContextMenu.removeExtensionForContextAction( 395 event.target.parentElement 396 ); 397 break; 398 399 case "customizationPanelItemContextMenuReportExtension": 400 ToolbarContextMenu.reportExtensionForContextAction( 401 event.target.parentElement, 402 "toolbar_context_menu" 403 ); 404 break; 405 406 case "customizationPanelItemContextMenuPin": 407 gCustomizeMode.addToPanel( 408 event.target.parentNode.triggerNode, 409 "panelitem-context" 410 ); 411 break; 412 413 case "customizationPanelItemContextMenuUnpin": 414 gCustomizeMode.addToToolbar( 415 event.target.parentNode.triggerNode, 416 "panelitem-context" 417 ); 418 break; 419 420 case "customizationPanelItemContextMenuRemove": 421 gCustomizeMode.removeFromArea( 422 event.target.parentNode.triggerNode, 423 "panelitem-context" 424 ); 425 break; 426 427 // == sharing-tabs-warning-panel == 428 case "sharing-warning-proceed-to-tab": 429 gSharedTabWarning.allowSharedTabSwitch(); 430 break; 431 } 432 }); 433 434 const containerHistoryPopup = document.getElementById( 435 "sidebar-history-context-menu-container-popup" 436 ); 437 containerHistoryPopup.addEventListener("command", event => 438 PlacesUIUtils.openInContainerTab(event) 439 ); 440 containerHistoryPopup.addEventListener("popupshowing", event => 441 PlacesUIUtils.createContainerTabMenu(event) 442 ); 443 444 document 445 .getElementById("context_reopenInContainerPopupMenu") 446 .addEventListener("command", event => { 447 // Handle commands on the descendant <menuitem>s with different containers. 448 TabContextMenu.reopenInContainer(event); 449 }); 450 451 document 452 .getElementById("context_moveTabToGroupPopupMenu") 453 .addEventListener("command", event => { 454 if (event.target.id == "context_moveTabToGroupNewGroup") { 455 TabContextMenu.moveTabsToNewGroup(); 456 return; 457 } 458 459 const tabGroupId = event.target.getAttribute("tab-group-id"); 460 const group = gBrowser.getTabGroupById(tabGroupId); 461 if (group) { 462 TabContextMenu.moveTabsToGroup(group); 463 } 464 465 if (SessionStore.getSavedTabGroup(tabGroupId)) { 466 TabContextMenu.addTabsToSavedGroup(tabGroupId); 467 } 468 }); 469 470 document 471 .getElementById("backForwardMenu") 472 .addEventListener("command", event => { 473 // Handle commands on the descendant <menuitem>s with history entries. 474 // Note: See duplicate code in SetClickAndHoldHandlers. 475 BrowserCommands.gotoHistoryIndex(event); 476 // Prevent propagation to the back/forward button. 477 event.stopPropagation(); 478 }); 479 480 document 481 .getElementById("unified-extensions-context-menu") 482 .addEventListener("command", event => { 483 gUnifiedExtensions.onContextMenuCommand(event.currentTarget, event); 484 }); 485 486 document 487 .getElementById("webRTC-selectWindow-menulist") 488 .addEventListener("command", event => { 489 webrtcUI.updateWarningLabel(event.currentTarget); 490 }); 491 492 mainPopupSet.addEventListener("popupshowing", event => { 493 switch (event.target.id) { 494 case "context_sendTabToDevicePopupMenu": 495 gSync.populateSendTabToDevicesMenu( 496 event.target, 497 TabContextMenu.contextTab.linkedBrowser.currentURI, 498 TabContextMenu.contextTab.linkedBrowser.contentTitle, 499 TabContextMenu.contextTab.multiselected 500 ); 501 break; 502 case "context_reopenInContainerPopupMenu": 503 TabContextMenu.createReopenInContainerMenu(event); 504 break; 505 case "backForwardMenu": 506 FillHistoryMenu(event); 507 break; 508 case "new-tab-button-popup": 509 CreateContainerTabMenu(event); 510 break; 511 case "toolbar-context-menu": 512 ToolbarContextMenu.onViewToolbarsPopupShowing( 513 event, 514 document.getElementById("viewToolbarsMenuSeparator") 515 ); 516 ToolbarContextMenu.updateDownloadsAutoHide(event.target); 517 ToolbarContextMenu.updateDownloadsAlwaysOpenPanel(event.target); 518 ToolbarContextMenu.updateExtensionsButtonContextMenu(event.target); 519 ToolbarContextMenu.updateExtension(event.target); 520 521 // The following methods must be called last after updating the menu items above, 522 // as they may change which items are visible. 523 ToolbarContextMenu.updateCustomizationItemsVisibility(event.target); 524 ToolbarContextMenu.hideLeadingSeparatorIfNeeded(event.target); 525 break; 526 case "pageActionContextMenu": 527 BrowserPageActions.onContextMenuShowing(event, event.target); 528 break; 529 case "tabbrowser-tab-tooltip": 530 gBrowser.createTooltip(event); 531 break; 532 case "dynamic-shortcut-tooltip": 533 DynamicShortcutTooltip.updateText(event.target); 534 break; 535 case "SyncedTabsOpenSelectedInContainerTabMenu": 536 createUserContextMenu(event, { isContextMenu: true }); 537 break; 538 case "unified-extensions-context-menu": 539 gUnifiedExtensions.updateContextMenu(event.target, event); 540 break; 541 case "customizationPanelItemContextMenu": 542 gCustomizeMode.onPanelContextMenuShowing(event); 543 ToolbarContextMenu.updateExtension(event.target); 544 break; 545 case "bhTooltip": 546 BookmarksEventHandler.fillInBHTooltip(event.target, event); 547 break; 548 case "tabContextMenu": 549 TabContextMenu.addNewBadge(); 550 break; 551 case "moveTabOptionsMenu": 552 gProfiles.populateMoveTabMenu(event.target); 553 break; 554 } 555 }); 556 557 document 558 .getElementById("tabContextMenu") 559 .addEventListener("popupshowing", event => { 560 if (event.target.id == "tabContextMenu") { 561 TabContextMenu.updateContextMenu(event.target); 562 } 563 }); 564 565 // Enable/disable some `open-tab-group-context-menu` options based on the 566 // specific tab group context. 567 document 568 .getElementById("open-tab-group-context-menu") 569 .addEventListener("popupshowing", event => { 570 if (event.target.id == "open-tab-group-context-menu") { 571 // Disable "Move Group to This Window" menu option for tab groups 572 // that are open in the current window. 573 let { tabGroupId } = event.target.triggerNode.dataset; 574 let tabGroup = gBrowser.getTabGroupById(tabGroupId); 575 let tabGroupIsInThisWindow = tabGroup.ownerDocument == document; 576 event.target.querySelector( 577 "#open-tab-group-context-menu_moveToThisWindow" 578 ).disabled = tabGroupIsInThisWindow; 579 580 // Disable "Move Group to New Window" menu option for tab groups 581 // that are the only things in their respective window. 582 let groupAloneInWindow = 583 tabGroup.tabs.length == 584 tabGroup.ownerGlobal.gBrowser.openTabs.length; 585 event.target.querySelector( 586 "#open-tab-group-context-menu_moveToNewWindow" 587 ).disabled = groupAloneInWindow; 588 } 589 }); 590 591 mainPopupSet.addEventListener("popupshown", event => { 592 switch (event.target.id) { 593 case "sharing-tabs-warning-panel": 594 gSharedTabWarning.sharedTabWarningShown(); 595 break; 596 case "full-page-translations-panel-settings-menupopup": 597 FullPageTranslationsPanel.handleSettingsPopupShownEvent(); 598 break; 599 } 600 }); 601 602 mainPopupSet.addEventListener("popuphiding", event => { 603 switch (event.target.id) { 604 case "tabbrowser-tab-tooltip": 605 case "bhTooltip": 606 event.target.removeAttribute("position"); 607 break; 608 } 609 }); 610 611 mainPopupSet.addEventListener("popuphidden", event => { 612 switch (event.target.id) { 613 case "full-page-translations-panel-settings-menupopup": 614 FullPageTranslationsPanel.handleSettingsPopupHiddenEvent(); 615 break; 616 } 617 }); 618 }, 619 { once: true } 620 );