Skip to content

Instantly share code, notes, and snippets.

@jscher2000
Last active March 27, 2024 09:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jscher2000/623eb8e9fb0167a139e2c089523f83c9 to your computer and use it in GitHub Desktop.
Save jscher2000/623eb8e9fb0167a139e2c089523f83c9 to your computer and use it in GitHub Desktop.
Export Current Tab Titles/URLs to CSV - Script for Firefox's Browser Console
/* Export Current Tab Titles/URLs to CSV - Script for the Browser Console
NOTE: BEFORE RUNNING THIS SCRIPT, CHECK THIS SETTING:
Type or paste about:config into the address bar and press Enter
Click the button promising to be careful
In the search box type devt and pause while Firefox filters the list
If devtools.chrome.enabled is false, double-click it to toggle to true
Paste this entire script into the command line at the bottom of the Browser Console (Windows: Ctrl+Shift+j)
Then press Enter to run the script. A save dialog should promptly open.
*/
ssj = JSON.parse(SessionStore.getBrowserState()); // get Current Session State
if(ssj && ssj.windows && ssj.windows.length > 0){
// Build tab list
var out = '"Win","Tab","Title","URL"\n';
var wins = ssj.windows;
for (var w=0; w<wins.length; w++){
var tabs = wins[w].tabs;
for (t=0; t<tabs.length; t++){
var tab = tabs[t].entries[tabs[t].index - 1];
out += (w+1) + ',' + (t+1) + ',"' + (tab.title ? tab.title.replace(/\"/g, "'") : "") + '","' + tab.url + '"\n';
}
}
// Set up Save As dialog
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("CSV Files", "*.csv");
fp.defaultString = "sessionstore-current-tabs.csv";
// Call Save As dialog
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 {
alert('Could not get session data!');
}
@hugolpz
Copy link

hugolpz commented Feb 4, 2024

Just for informations, I get Uncaught ReferenceError: SessionStore is not defined. Firefox 122.0 (64-bit), Ubuntu.

@jscher2000
Copy link
Author

Just for informations, I get Uncaught ReferenceError: SessionStore is not defined. Firefox 122.0 (64-bit), Ubuntu.

Thank you for reporting this. I'm not seeing the error in the Browser Console (global level console, Ctrl+Shift+J) on Windows, but I do see it in the Web Console (tab level console, Ctrl+Shift+K). Do you see it in both?

@hugolpz
Copy link

hugolpz commented Feb 6, 2024

It solve the issue indeed. My apologize.

@rafal-1990
Copy link

rafal-1990 commented Feb 9, 2024

Thank you very much for this script and your explanation. 👍 I wasn't aware of the Browser Console.

I had indeed a few tabs without title and got the error:
Uncaught TypeError: tabs[t].entries[(tabs[t].index - 1)].title is undefined

Furthermore, I had trouble with the double quotes. If a title ends with a double quotation mark, the CSV file was not displayed correctly in LibreOffice Calc. So I replace them with single quotation marks.

Here is my customized version of the script:

ssj = JSON.parse(SessionStore.getBrowserState()); // get Current Session State
if(ssj && ssj.windows && ssj.windows.length > 0){
	// Build tab list
	var out = '"Win","Tab","Title","URL"\n';
	var wins = ssj.windows;
	for (var w=0; w<wins.length; w++){
		var tabs = wins[w].tabs;
		for (t=0; t<tabs.length; t++){
			var tab=tabs[t].entries[tabs[t].index - 1];
			out += (w+1) + ',' + (t+1) + ',"' + (tab.title?tab.title.replace(/\"/g, "'"):"") + '","' + tab.url + '"\n';
		}
	}
	// Set up Save As dialog
	var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
	fp.init(window, "Open File", Components.interfaces.nsIFilePicker.modeSave);
	fp.appendFilter("CSV Files", "*.csv");
	fp.defaultString = "sessionstore-current-tabs.csv";
	// Call Save As dialog
	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 {
	alert('Could not get session data!');
}

Feel free to take over this adaptation.

By the way, it turns out that I have 233 open tabs. 😉

@jscher2000
Copy link
Author

I had indeed a few tabs without title and got the error: Uncaught TypeError: tabs[t].entries[(tabs[t].index - 1)].title is undefined

Furthermore, I had trouble with the double quotes. If a title ends with a double quotation mark, the CSV file was not displayed correctly in LibreOffice Calc. So I replace them with single quotation marks.

Feel free to take over this adaptation.

I've adopted that for now, although single quotation marks may well break with apostrophes so I need to test.

More urgently:

Try/catch added for Firefox 125 (currently in Nightly), at lines 25-27, 29.

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