Badge updates do not trigger excessive background CPU usage
Why it matters
Badge update calls fired on every high-frequency browser event — webRequest.onCompleted, tabs.onUpdated, or sub-5-second polling — create continuous background CPU load even when the user is doing nothing extension-related. ISO 25010:2011 performance-efficiency.resource-utilisation treats unnecessary background CPU consumption as a defect. On laptops, this translates directly to battery drain; on lower-end hardware it causes system-wide slowdown. Chrome surfaces extensions that abuse background resources in its Task Manager, leading to removal.
Severity rationale
Medium because unbounded badge update frequency drains battery and CPU continuously, but the impact is gradual and not immediately catastrophic.
Remediation
Debounce badge updates so high-frequency trigger events coalesce into at most one update per 500ms, and skip the setBadgeText call entirely when the value has not changed.
let currentBadgeText = '';
let badgeUpdateTimer = null;
function scheduleBadgeUpdate() {
clearTimeout(badgeUpdateTimer);
badgeUpdateTimer = setTimeout(async () => {
const count = await computeCount();
const newText = count > 0 ? String(count) : '';
if (newText !== currentBadgeText) {
currentBadgeText = newText;
chrome.action.setBadgeText({ text: newText });
}
}, 500);
}
For polling patterns, use chrome.alarms with a minimum 30-second interval and add idle detection via chrome.idle to pause updates when the system is idle.
Detection
-
ID:
badge-cpu-usage -
Severity:
medium -
What to look for: Examine how frequently the badge is updated. Look for patterns that update the badge on very high-frequency events: every
webRequestevent, everyonMessage, everytabs.onUpdated, or on a very short polling interval (under 5 seconds). Eachchrome.action.setBadgeTextcall has overhead. Check for redundant badge updates — setting the badge to the same value it already has. Count all instances found and enumerate each. -
Pass criteria: Badge updates are infrequent relative to their trigger events. High-frequency events are debounced before triggering badge updates. No unnecessary updates when the value has not changed. Polling intervals for badge-relevant data are reasonable (30 seconds or more). At least 1 implementation must be confirmed.
-
Fail criteria: Badge update logic fires on every high-frequency event without debouncing. Badge is updated with the same value it already has (no change check before calling
setBadgeText). Polling interval for badge data is shorter than 5 seconds with no idle detection. -
Skip (N/A) when: The extension does not use the badge API.
-
Detail on fail: Describe the frequency issue. Example:
"setBadgeText called on every chrome.webRequest.onCompleted event — fires 50-200 times per minute during normal browsing"or"Background polls for badge data every 2 seconds with no idle detection or caching." -
Remediation: Debounce badge updates and skip redundant calls:
let currentBadgeText = ''; let badgeUpdateTimer = null; function scheduleBadgeUpdate() { clearTimeout(badgeUpdateTimer); badgeUpdateTimer = setTimeout(async () => { const count = await computeCount(); const newText = count > 0 ? String(count) : ''; if (newText !== currentBadgeText) { currentBadgeText = newText; chrome.action.setBadgeText({ text: newText }); } }, 500); // Debounce: update at most every 500ms }
External references
- iso-25010:2011 · performance-efficiency.resource-utilization
Taxons
History
- 2026-04-18·v1.0.0·Initial import from extension-ux-performance·automated