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.
Medium because unbounded badge update frequency drains battery and CPU continuously, but the impact is gradual and not immediately catastrophic.
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.
ID: extension-ux-performance.badge-notifications.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 webRequest event, every onMessage, every tabs.onUpdated, or on a very short polling interval (under 5 seconds). Each chrome.action.setBadgeText call 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
}