#!/usr/bin/python # # Taken in part from https://gist.github.com/ssokolow/35097553e5173935e597 import glob, json, os, re def get_tab_metadata(tab): grp_id = None grp_data = tab.get('extData', {}).get('tabview-tab', {}) if grp_data: grp_data = json.loads(grp_data) if grp_data: grp_id = grp_data.get('groupID', None) del grp_data content = tab['entries'][-1] # -1 is most recent return { 'index' : tab.get('index'), 'group' : grp_id, 'title' : content.get('title', content.get('url')), 'url' : content.get('url'), 'pinned': tab.get('pinned', False) } def get_tabgroups(data): windows = [] for window in data['windows']: grp_names = json.loads(window.get('extData', {}).get( 'tabview-group', '{}')) grp_names = {int(x): grp_names[x]['title'] for x in grp_names.keys()} tabs = [] for tab in window['tabs']: tabs.append(get_tab_metadata(tab)) # Group the tabs by group ID and then replace the IDs with the # group names without risking naming collisions groups = {} for tab in tabs: groups.setdefault(tab['group'], []).append(tab) groups = [(grp_names.get(k, None), v) for k, v in groups.items()] groups.sort() # TODO: Sort case-insensitively windows.append(groups) return windows def print_tabs(groups): for pos, window in enumerate(groups): #print 'Window ' + str(pos+1) for group, tabs in window: if not group and all(x.get('pinned') for x in tabs): grp_name = 'Window ' + str(pos+1) + ' | Pinned Tabs' else: grp_name = group or 'Unnamed' print 'Window ' + str(pos+1) + ' | Group: ' + grp_name for x in tabs: print '\t' + x['title'] print '\t' + x['url'] print filenames = glob.glob(os.path.expanduser('~/.mozilla/firefox/*/sessionstore-backups/recovery.js')) for filename in filenames: with open(filename, 'r') as fobj: data = json.load(fobj) groups = get_tabgroups(data) print_tabs(groups) # vim: expandtab shiftwidth=4 softtabstop=4 tw=500