Skip to content

Commit c3d5d2c

Browse files
fix: prevent favicon data retention in heartbeat debug logs
The console.debug calls passed entire Tab objects, which in Firefox include favIconUrl as base64 data URIs. Browser console buffers retain references to logged objects, so over thousands of heartbeats this accumulated hundreds of MBs of duplicate favicon data in memory. Fix: destructure only needed fields from Tab objects before use, and log only the URL string instead of the full Tab object. This addresses the favicon accumulation half of ActivityWatch#222 (the AbortController leak is being fixed in aw-client-js via ActivityWatch/aw-client-js#50).
1 parent a3e3b9b commit c3d5d2c

1 file changed

Lines changed: 14 additions & 9 deletions

File tree

src/background/heartbeat.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,22 @@ async function heartbeat(
2727
return
2828
}
2929

30+
// Extract only the fields we need so we don't retain references to the
31+
// full Tab object (which includes favIconUrl — a potentially large base64
32+
// data URI). Over thousands of heartbeats the retained Tab references
33+
// cause unbounded memory growth (see #222).
34+
const { url, title, audible, incognito } = tab
3035
const now = new Date()
3136
const data: IEvent['data'] = {
32-
url: tab.url,
33-
title: tab.title,
34-
audible: tab.audible ?? false,
35-
incognito: tab.incognito,
37+
url,
38+
title,
39+
audible: audible ?? false,
40+
incognito,
3641
tabCount: tabCount,
3742
}
3843
const previousData = await getHeartbeatData()
3944
if (previousData && !deepEqual(previousData, data)) {
40-
console.debug('Sending heartbeat for previous data', previousData)
45+
console.debug('Sending heartbeat for previous data')
4146
await sendHeartbeat(
4247
client,
4348
await getBucketId(),
@@ -46,7 +51,7 @@ async function heartbeat(
4651
config.heartbeat.intervalInSeconds + 20,
4752
)
4853
}
49-
console.debug('Sending heartbeat', data)
54+
console.debug('Sending heartbeat', url)
5055
await sendHeartbeat(
5156
client,
5257
await getBucketId(),
@@ -60,7 +65,7 @@ async function heartbeat(
6065
export const sendInitialHeartbeat = async (client: AWClient) => {
6166
const activeWindowTab = await getActiveWindowTab()
6267
const tabs = await getTabs()
63-
console.debug('Sending initial heartbeat', activeWindowTab)
68+
console.debug('Sending initial heartbeat', activeWindowTab?.url)
6469
await heartbeat(client, activeWindowTab, tabs.length)
6570
}
6671

@@ -70,7 +75,7 @@ export const heartbeatAlarmListener =
7075
const activeWindowTab = await getActiveWindowTab()
7176
if (!activeWindowTab) return
7277
const tabs = await getTabs()
73-
console.debug('Sending heartbeat for alarm', activeWindowTab)
78+
console.debug('Sending heartbeat for alarm', activeWindowTab.url)
7479
await heartbeat(client, activeWindowTab, tabs.length)
7580
}
7681

@@ -79,6 +84,6 @@ export const tabActivatedListener =
7984
async (activeInfo: browser.Tabs.OnActivatedActiveInfoType) => {
8085
const tab = await getTab(activeInfo.tabId)
8186
const tabs = await getTabs()
82-
console.debug('Sending heartbeat for tab activation', tab)
87+
console.debug('Sending heartbeat for tab activation', tab.url)
8388
await heartbeat(client, tab, tabs.length)
8489
}

0 commit comments

Comments
 (0)