Skip to content

Instantly share code, notes, and snippets.

@jscher2000
Last active April 9, 2024 07:10
Show Gist options
  • Star 39 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jscher2000/b7094b3e74b95e5ba9c26f1f685bda6e to your computer and use it in GitHub Desktop.
Save jscher2000/b7094b3e74b95e5ba9c26f1f685bda6e to your computer and use it in GitHub Desktop.
Export Synced Tabs List to "bookmarks.html" file (Browser Console script)
// Run code in Browser Console after enabling chrome debugging --
// about:config => devtools.chrome.enabled => true
// https://developer.mozilla.org/docs/Tools/Browser_Console
try {
var tabPromise = SyncedTabs._internal.getTabClients();
tabPromise.then((arrDevices) => {
if (arrDevices && arrDevices.length > 0){
// Generate a string with the format of a bookmark export file
var d, e, out = '<!DOCTYPE NETSCAPE-Bookmark-file-1>\n<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">\n<TITLE>Bookmarks</TITLE>\n<H1>Bookmarks Menu</H1>\n<DL><p>\n';
const escapeHtmlEntities = function(aText){return (aText || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')};
for (var j=0; j<arrDevices.length; j++){
// Create a folder for each device
d = new Date(arrDevices[j].lastModified);
e = Math.floor(d.getTime()/1000);
out += '<DT><H3 ADD_DATE="' + e + '" LAST_MODIFIED="' + e + '">Synced Tabs from ' + escapeHtmlEntities(arrDevices[j].name) + ' as of ' + d.toString() + '</H3>\n<DL><p>\n';
// Sort tabs by most recently used
var arrTabs = arrDevices[j].tabs;
arrTabs.sort(function(a, b){return b.lastUsed - a.lastUsed;});
for (var i=0; i<arrTabs.length; i++){
// Create a bookmark (link) for each tab
d = new Date(arrTabs[i].lastUsed * 1000);
e = Math.floor(d.getTime()/1000);
out += ' <DT><A HREF="' + arrTabs[i].url + '" ADD_DATE="' + e + '" LAST_MODIFIED="' + e + '">' + escapeHtmlEntities(arrTabs[i].title) + '</A>\n';
// Show last access date/time in a note (comment out or delete the next line if you don't want that)
out += ' <DD>Last acccessed: ' + d.toString() + '\n'
}
out += '</DL><p>\n';
}
out += '</DL><p>\n</DL>';
// Set up Save As dialog with proposed file name
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
try { // Fx125+
fp.init(window.browsingContext, 'Open File', Components.interfaces.nsIFilePicker.modeSave);
} catch(e) { // Fx124 and earlier
fp.init(window, 'Open File', Components.interfaces.nsIFilePicker.modeSave);
}
fp.appendFilter('HTML Files', '*.html');
d = new Date();
d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
var dt = d.toISOString().split('.')[0].replace(/-/g, '').replace(/:/g, '').replace(/T/, '_');
fp.defaultString = 'bookmarks-from-synced-tabs_' + dt + '.html';
// Call Save As dialog and (unless user cancels) write the file
fp.open((aResult) => {
if (aResult == Components.interfaces.nsIFilePicker.returnOK ||
aResult == Components.interfaces.nsIFilePicker.returnReplace) {
try {
IOUtils.writeUTF8(fp.file.path, out);
alert('Look for ' + fp.file.path);
} catch (err) {
alert(err);
}
} else {
alert('Okay, not saving');
}
});
} else {
console.log('NO SYNCED TABS RETRIEVED');
}
}).catch((err) => {
console.log('Problem reading or outputting synced tabs: '+err);
});
} catch (err) {
console.log('Problem reading or outputting synced tabs: '+err);
}
@jscher2000
Copy link
Author

Had to update from OS.File.writeAtomic() to IOUtils.writeUTF8() for Firefox 104.

@profucius
Copy link

profucius commented May 5, 2023

Hi, I found your script while looking for a method to extract tabs from my android firefox app. I've accumulated so many that I cannot use any method within android to extract them. I've tried using your script, but I am getting an error in the browser console. Do you know why this might be happening? Error below:

Problem reading or outputting synced tabs: ReferenceError: SyncedTabs is not defined | debugger eval code:59:13

I have devtools.chrome.enabled set to true and have the Synced Tabs sidebar loaded when I run the script. Using Firefox 106

@jscher2000
Copy link
Author

Error below:

Problem reading or outputting synced tabs: ReferenceError: SyncedTabs is not defined | debugger eval code:59:13

Make sure you are using the Browser Console (Ctrl+Shift+J as a stand-alone tool) rather than the Web Console (part of the tab dev tools panel).

@ReflextionsDev
Copy link

Came across this script on a Mozilla support thread, thanks!

@TheOnlyOnlyName
Copy link

Thank you!!

@sendiriaann
Copy link

sendiriaann commented Mar 17, 2024

thanks for the first script, it works well.
for this one tho the console sends out an error

Problem reading or outputting synced tabs: [Exception... "Could not convert JavaScript argument arg 0 [nsIFilePicker.init]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: debugger eval code :: <TOP_LEVEL> :: line 32" data: no]

something to do with the nsIFilePicker.init, I'm on latest firefox (nightly) version.

edit: for now removing that section would allow the script to work. had to manually copy+paste the result from console to a html file but from there it's been smooth sailing. thank you very much 🙏

@jscher2000
Copy link
Author

Thank you for reporting this.

I see something has changed with init in bug 1878401. I don't have Nightly on this computer, so I need to install and experiment.

@jscher2000
Copy link
Author

I think it's fixed with the try/catch (lines 32-34, 36) to support the newer syntax.

@sendiriaann
Copy link

confirmed, thank you so much for the quick fix

@nishyp
Copy link

nishyp commented Mar 20, 2024

I just wanted to say thank you for making this! Bookmarked every tab that was open (including inactive tabs!) from Firefox on iOS and closed them all, finally!

@colemickens
Copy link

  1. I cannot believe that this has to exist. It really bothers me that Firefox has 3+ ways of viewing synced tabs, none of which enable this. And Firefox Android has no way to migrate tabs or load them all from another synced device. Just... it really makes me wonder how product development is done on Firefox, and how effort is spent on things like Firefox View.

  2. This script gave me a way out of this frustration, and is seemingly the only easy, viable way to get Synced Tabs out of Firefox. It took me less than 30 seconds, and indeed, imported all of the open tabs. For that, I am immensely grateful. I'd love to send you a little thank you donation, if you let me know a method/contact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment