ActionsProviderTabGroups.sys.mjs (4576B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 import { 6 ActionsProvider, 7 ActionsResult, 8 } from "moz-src:///browser/components/urlbar/ActionsProvider.sys.mjs"; 9 10 const lazy = {}; 11 ChromeUtils.defineESModuleGetters(lazy, { 12 BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs", 13 UrlbarPrefs: "moz-src:///browser/components/urlbar/UrlbarPrefs.sys.mjs", 14 UrlbarUtils: "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs", 15 SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs", 16 TabMetrics: "moz-src:///browser/components/tabbrowser/TabMetrics.sys.mjs", 17 }); 18 19 const MIN_SEARCH_PREF = "tabGroups.minSearchLength"; 20 21 /** 22 * A provider that matches the urlbar input to built in actions. 23 */ 24 class ProviderTabGroups extends ActionsProvider { 25 get name() { 26 return "ActionsProviderTabGroups"; 27 } 28 29 isActive(queryContext) { 30 return ( 31 queryContext.sapName == "urlbar" && 32 Services.prefs.getBoolPref("browser.tabs.groups.enabled") && 33 (!queryContext.restrictSource || 34 queryContext.restrictSource == lazy.UrlbarUtils.RESULT_SOURCE.TABS) && 35 queryContext.trimmedSearchString.length < 50 && 36 queryContext.trimmedSearchString.length >= 37 lazy.UrlbarPrefs.get(MIN_SEARCH_PREF) 38 ); 39 } 40 41 async queryActions(queryContext) { 42 // We need a non-private window here to call gBrowser.getAllTabGroups() 43 // on, and it's OK if it's not on the current workspace. 44 let window = lazy.BrowserWindowTracker.getTopWindow({ 45 allowFromInactiveWorkspace: true, 46 }); 47 if (!window) { 48 // We're likely running xpcshell tests if this happens in automation. 49 if (!Cu.isInAutomation) { 50 console.error("Couldn't find a browser window."); 51 } 52 return null; 53 } 54 let results = []; 55 let i = 0; 56 57 for (let group of window.gBrowser.getAllTabGroups({ 58 sortByLastSeenActive: true, 59 })) { 60 if ( 61 group.ownerGlobal == window && 62 window.gBrowser.selectedTab.group == group 63 ) { 64 // This group is already the active group, so don't offer switching to it. 65 continue; 66 } 67 if (!this.#matches(group.label, queryContext)) { 68 continue; 69 } 70 results.push( 71 this.#makeResult({ 72 key: `tabgroup-${i++}`, 73 l10nId: "urlbar-result-action-switch-to-tabgroup", 74 l10nArgs: { group: group.label }, 75 onPick: (_queryContext, _controller) => { 76 this.#switchToGroup(group); 77 }, 78 color: group.color, 79 }) 80 ); 81 } 82 83 if (queryContext.isPrivate) { 84 // Tab groups can't be saved or reopened in private windows. 85 return results; 86 } 87 88 for (let savedGroup of lazy.SessionStore.getSavedTabGroups()) { 89 if (!this.#matches(savedGroup.name, queryContext)) { 90 continue; 91 } 92 results.push( 93 this.#makeResult({ 94 key: `tabgroup-${i++}`, 95 l10nId: "urlbar-result-action-open-saved-tabgroup", 96 l10nArgs: { group: savedGroup.name }, 97 onPick: (_queryContext, _controller) => { 98 let group = lazy.SessionStore.openSavedTabGroup( 99 savedGroup.id, 100 window, 101 { 102 source: lazy.TabMetrics.METRIC_SOURCE.SUGGEST, 103 } 104 ); 105 this.#switchToGroup(group); 106 }, 107 color: savedGroup.color, 108 }) 109 ); 110 } 111 112 return results; 113 } 114 115 #matches(groupName, queryContext) { 116 groupName = groupName.toLowerCase(); 117 if (queryContext.trimmedLowerCaseSearchString.length == 1) { 118 return groupName.startsWith(queryContext.trimmedLowerCaseSearchString); 119 } 120 return queryContext.tokens.every(token => 121 groupName.includes(token.lowerCaseValue) 122 ); 123 } 124 125 #makeResult({ key, l10nId, l10nArgs, onPick, color }) { 126 return new ActionsResult({ 127 key, 128 l10nId, 129 l10nArgs, 130 onPick, 131 icon: "chrome://browser/skin/tabbrowser/tab-groups.svg", 132 dataset: { 133 style: { 134 "--tab-group-color": `var(--tab-group-color-${color})`, 135 "--tab-group-color-invert": `var(--tab-group-color-${color}-invert)`, 136 "--tab-group-color-pale": `var(--tab-group-color-${color}-pale)`, 137 }, 138 }, 139 }); 140 } 141 142 #switchToGroup(group) { 143 group.select(); 144 group.ownerGlobal.focus(); 145 } 146 } 147 148 export var ActionsProviderTabGroups = new ProviderTabGroups();