Skip to content

Commit 0edb7c3

Browse files
author
Niklas Baumgardner
committed
Bug 1990551 - Send tabs to other profiles from context menu. r=profiles-reviewers,fluent-reviewers,bolsson,jhirsch,sthompson
Differential Revision: https://phabricator.services.mozilla.com/D269856
1 parent 8446a43 commit 0edb7c3

14 files changed

+316
-13
lines changed

browser/base/content/browser-profiles.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ var gProfiles = {
194194
});
195195
},
196196

197+
async openTabsInProfile(aEvent, tabsToOpen) {
198+
let profile = await SelectableProfileService.getProfile(
199+
aEvent.target.getAttribute("profileid")
200+
);
201+
SelectableProfileService.launchInstance(
202+
profile,
203+
tabsToOpen.map(tab => tab.linkedBrowser.currentURI.spec)
204+
);
205+
},
206+
197207
async handleCommand(aEvent) {
198208
switch (aEvent.target.id) {
199209
/* App menu button events */
@@ -247,6 +257,16 @@ var gProfiles = {
247257
this.launchProfile(aEvent.sourceEvent);
248258
break;
249259
}
260+
case "Profiles:MoveTabsToProfile": {
261+
let tabs;
262+
if (TabContextMenu.contextTab.multiselected) {
263+
tabs = gBrowser.selectedTabs;
264+
} else {
265+
tabs = [TabContextMenu.contextTab];
266+
}
267+
this.openTabsInProfile(aEvent.sourceEvent, tabs);
268+
break;
269+
}
250270
}
251271
/* Subpanel profile events that may be triggered in FxA menu or app menu */
252272
if (aEvent.target.classList.contains("profile-item")) {
@@ -427,4 +447,50 @@ var gProfiles = {
427447
profilesList.appendChild(button);
428448
}
429449
},
450+
451+
async populateMoveTabMenu(menuPopup) {
452+
if (!SelectableProfileService.initialized) {
453+
return;
454+
}
455+
456+
const profiles = await SelectableProfileService.getAllProfiles();
457+
const currentProfile = SelectableProfileService.currentProfile;
458+
459+
const separator = document.getElementById("moveTabSeparator");
460+
separator.hidden = profiles.length < 2;
461+
462+
let existingItems = [
463+
...menuPopup.querySelectorAll(":scope > menuitem[profileid]"),
464+
];
465+
466+
for (let profile of profiles) {
467+
if (profile.id === currentProfile.id) {
468+
continue;
469+
}
470+
471+
let menuitem = existingItems.shift();
472+
let isNewItem = !menuitem;
473+
if (isNewItem) {
474+
menuitem = document.createXULElement("menuitem");
475+
menuitem.setAttribute("tbattr", "tabbrowser-multiple-visible");
476+
menuitem.setAttribute("data-l10n-id", "move-to-new-profile");
477+
menuitem.setAttribute("command", "Profiles:MoveTabsToProfile");
478+
}
479+
480+
menuitem.disabled = false;
481+
menuitem.setAttribute("profileid", profile.id);
482+
menuitem.setAttribute(
483+
"data-l10n-args",
484+
JSON.stringify({ profileName: profile.name })
485+
);
486+
487+
if (isNewItem) {
488+
menuPopup.appendChild(menuitem);
489+
}
490+
}
491+
// If there's any old item to remove, do so now.
492+
for (let remaining of existingItems) {
493+
remaining.remove();
494+
}
495+
},
430496
};

browser/base/content/browser-sets.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
<command id="Profiles:CreateProfile" />
7979
<command id="Profiles:ManageProfiles" />
8080
<command id="Profiles:LaunchProfile" />
81+
<command id="Profiles:MoveTabsToProfile" />
8182
<command id="Browser:NextTab" />
8283
<command id="Browser:PrevTab" />
8384
<command id="Browser:ShowAllTabs" />

browser/base/content/browser-sets.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ document.addEventListener(
203203
case "Profiles:CreateProfile":
204204
case "Profiles:ManageProfiles":
205205
case "Profiles:LaunchProfile":
206+
case "Profiles:MoveTabsToProfile":
206207
gProfiles.handleCommand(event);
207208
break;
208209
case "Tools:Search":

browser/base/content/main-popupset.inc.xhtml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
tbattr="tabbrowser-multiple-visible"/>
7676
<menuitem id="context_openTabInWindow" data-lazy-l10n-id="move-to-new-window"
7777
tbattr="tabbrowser-multiple-visible"/>
78+
<menuseparator id="moveTabSeparator" hidden="true"/>
7879
</menupopup>
7980
</menu>
8081
<menu id="context_sendTabToDevice"

browser/base/content/main-popupset.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,9 @@ document.addEventListener(
532532
case "tabContextMenu":
533533
TabContextMenu.addNewBadge();
534534
break;
535+
case "moveTabOptionsMenu":
536+
gProfiles.populateMoveTabMenu(event.target);
537+
break;
535538
}
536539
});
537540

browser/components/backup/BackupService.sys.mjs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,8 +3235,10 @@ export class BackupService extends EventTarget {
32353235
profile,
32363236
// Using URL Search Params on this about: page didn't work because
32373237
// the RPM communication so we use the hash and parse that instead.
3238-
"about:editprofile" +
3239-
(copiedProfile ? `#copiedProfileName=${copiedProfile.name}` : "")
3238+
[
3239+
"about:editprofile" +
3240+
(copiedProfile ? `#copiedProfileName=${copiedProfile.name}` : ""),
3241+
]
32403242
);
32413243
}
32423244

browser/components/profiles/SelectableProfileService.sys.mjs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -631,13 +631,17 @@ class SelectableProfileServiceClass extends EventEmitter {
631631
* Launch a new Firefox instance using the given selectable profile.
632632
*
633633
* @param {SelectableProfile} aProfile The profile to launch
634-
* @param {string} aUrl A url to open in launched profile
634+
* @param {Array<string>} aUrls An array of urls to open in launched profile
635635
*/
636-
launchInstance(aProfile, aUrl) {
636+
launchInstance(aProfile, aUrls) {
637637
let args = [];
638638

639-
if (aUrl) {
640-
args.push("-url", aUrl);
639+
if (aUrls?.length) {
640+
// See https://wiki.mozilla.org/Firefox/CommandLineOptions#-url_URL
641+
// Use '-new-tab' instead of '-url' because when opening multiple URLs,
642+
// Firefox always opens them as tabs in a new window and we want to
643+
// attempt opening these tabs in an existing window.
644+
args.push(...aUrls.flatMap(url => ["-new-tab", url]));
641645
} else {
642646
args.push(`--${COMMAND_LINE_ACTIVATE}`);
643647
}
@@ -1452,7 +1456,7 @@ class SelectableProfileServiceClass extends EventEmitter {
14521456

14531457
let profile = await this.#createProfile();
14541458
if (launchProfile) {
1455-
this.launchInstance(profile, "about:newprofile");
1459+
this.launchInstance(profile, ["about:newprofile"]);
14561460
}
14571461
return profile;
14581462
}

browser/components/profiles/content/profile-selector.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export class ProfileSelector extends MozLitElement {
126126
await this.setLaunchArguments(profile, url ? ["-url", url] : []);
127127
await this.selectableProfileService.uninit();
128128
} else {
129-
this.selectableProfileService.launchInstance(profile, url);
129+
this.selectableProfileService.launchInstance(profile, url ? [url] : []);
130130
}
131131

132132
window.close();

browser/components/profiles/tests/browser/browser.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ skip-if = [
4545
["browser_menubar_profiles.js"]
4646
head = "../unit/head.js head.js"
4747

48+
["browser_moveTabToProfile.js"]
49+
4850
["browser_notify_changes.js"]
4951
run-if = ["os != 'linux'"] # Linux clients cannot remote themselves.
5052
skip-if = ["os == 'mac' && os_version == '15.30' && arch == 'aarch64' && opt && !socketprocess_networking"] # Bug 1929273

0 commit comments

Comments
 (0)