Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Check extension
on:
push:
pull_request:
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
- run: npm run package
- uses: actions/upload-artifact@v7
with:
name: tab-count-package
path: dist/*.zip
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist/
output/
node_modules/
.playwright-cli/
.DS_Store
29 changes: 29 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Tab Count privacy policy

Effective October 24, 2026

Tab Count is a Chrome extension by developerish that counts and manages open browser tabs. Your tab information stays in your browser. The extension does not transmit user data to the developer or any third party.

## Information used locally

Tab Count reads open-tab titles, URLs, window identifiers, and tab state to show tab counts and lists, switch to tabs, and close tabs at your request. It does not read the contents of web pages, passwords, form fields, or your browsing history.

If you enable duplicate notifications, Tab Count compares the URLs of open tabs. Pending notification actions contain tab identifiers and a URL in Chrome's session storage. This information is removed when the notification is handled or the duplicate tab is closed, and is cleared when the browser session ends or the extension is reloaded, disabled, or updated. It is not a persistent browsing record. Notification text does not include page titles or URLs.

If you enable automatic closing, Tab Count uses Chrome's last-accessed timestamps to identify unused tabs. It checks hourly and keeps active, pinned, playing, loading, incognito, and browser-internal tabs. It does not maintain a separate browsing-history database.

## Settings and retention

Your preferences are saved in Chrome's local extension storage on this device. Tab Count does not use Chrome sync storage. Preferences from older versions may be copied from the extension's local storage when you first open the popup or settings. Uninstalling the extension removes its stored settings and session data.

## Sharing and network activity

Tab Count contains no analytics, advertising, tracking, remote scripts, or network requests. It does not sell, share, or transfer user data. It does not load remote favicons. Chrome's own extension updates and any websites you open are governed by their respective privacy policies.

## Your choices

Duplicate detection and automatic closing are off by default. You can change these settings at any time or remove Tab Count in Chrome's extension settings. The extension does not request access to incognito browsing by default. If you allow that access in Chrome, counts and the tab list can include those tabs; duplicate detection and automatic closing skip incognito tabs.

## Contact and updates

For questions about this policy, [open an issue on GitHub](https://github.com/developerish/tab-count/issues). Do not include private URLs or other sensitive information in a public issue. This policy will be updated if the extension's data practices change.
65 changes: 61 additions & 4 deletions README
Original file line number Diff line number Diff line change
@@ -1,8 +1,65 @@
Tab Count Chrome Extension
==========================

This repository contains the source code for the **Tab Count** Chrome extension.
The extension displays the number of open tabs, lets you manage them, and now
uses Manifest V3 with a service worker background script.
Tab Count shows the number of open tabs in Chrome's toolbar and provides a
keyboard-accessible list for switching to and closing tabs. The badge and list
can each show the current window or all windows.

Chrome Web Store: <https://chrome.google.com/webstore/detail/cfokcacdaonnckdmopmcgeanhkebei>
Chrome Web Store: <https://chromewebstore.google.com/detail/tab-count/cfokcacdaonnckdmopmcgeanhkebeaio>

Development
-----------

Requires Chrome 121+ and Node 22+ for development. No runtime dependencies or
bundling step. Run `npm run check` for behavioral tests and JavaScript syntax
checks. Run `npm run package` to validate and produce the upload ZIP in `dist/`.
The packaging script requires the `zip` command (available on macOS and Linux).

To test manually, open chrome://extensions, enable Developer mode, choose
Load unpacked, and select `dist/extension` after packaging. Use a disposable
Chrome profile, especially when testing automatic closing. Reload the extension
after changing its files. See STORE.md for release and reviewer instructions.

Manifest V3 behavior
--------------------

All worker event listeners register synchronously. Chrome may stop the worker
when idle; no feature depends on an in-memory timer or activity-history object.

- `chrome.alarms` runs the optional unused-tab check hourly. The alarm is checked
on every worker start and removed when the setting is turned off.
- Unused-tab closing uses Chrome's `tabs.Tab.lastAccessed` timestamp (Chrome
121+) rather than maintaining a separate browsing record. It never closes
active, pinned, playing, loading, incognito, or browser-internal tabs. Unknown
or invalid timestamps are kept. The state is checked again before closing.
- Duplicate detection compares exact HTTP(S) URLs, supports more than two
matches, and skips incognito tabs. Pending actions live in session storage so
they survive worker suspension. Clicking a notification or its first button
switches to the existing tab and closes the unchanged duplicate. Dismissing
it or choosing Keep both keeps both tabs. Buttons depend on OS support; the
notification body is also actionable.
- Settings apply immediately without reloading the extension. Old MV2 settings
migrate when the popup or options page is first opened, preserving newer
preferences. Legacy auto-close is left off until explicitly enabled again.

Privacy and permissions
-----------------------

Tab information stays in the browser. No network requests, remote favicons,
analytics, content scripts, or host permissions. `tabs` supplies titles, URLs,
and state for the list and optional management features; `storage` saves local
preferences and session notification actions; `alarms` supports the hourly
check; `notifications` displays opt-in duplicate prompts. Both optional features
are off by default. Auto-close may lose unsaved work in otherwise eligible tabs.

See PRIVACY.md for the published privacy policy and STORE.md for the store's
single-purpose statement, permission justifications, and release procedure.

Related contributions
---------------------

Duplicate detection and unused-tab closing were originally contributed by
rgluga. lordvorp's PR #16 also identified service-worker lifecycle and legacy
storage migration problems: <https://github.com/developerish/tab-count/pull/16>.
This release addresses those problems in the existing js/background.js layout,
using Chrome's own last-accessed timestamps and adding regression coverage.
68 changes: 68 additions & 0 deletions STORE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Chrome Web Store release

Update the existing item **cfokcacdaonnckdmopmcgeanhkebeaio** rather than creating a new extension. This retains its identity and upgrade path.

## Build and upload

1. Run `npm run package` (Node 22 or later, plus `zip`). Upload `dist/tab-count-3.0.0.zip` using **Package → Upload new package** in the Chrome Web Store developer dashboard.
2. Check that version 3.0.0 is newer than every previously uploaded package. If necessary, increment both `manifest.json` and `package.json`, then regenerate the ZIP.
3. Update the store listing and privacy practices using the accurate, source-backed text below. Replace legacy screenshots with `store-assets/popup.jpg` (640×400) and `store-assets/settings.jpg` (1280×800), captured from the packaged extension in a clean Chrome for Testing profile. Both show disposable tabs. Keep the existing icon and promo tile.
4. Resolve any dashboard violations, account verification, contact-email, two-step verification, or developer/trader declarations. The account owner must supply personal or business identity facts and accept new legal terms.
5. Submit the existing item for review with public distribution and automatic publication after approval. Upload acceptance and review submission do not mean the item is live; verify the dashboard and public listing separately.

## Listing description

Tab Count shows how many tabs you have open and gives you a compact list for switching to or closing them.

- Choose whether the toolbar badge counts the current window or all windows.
- List tabs from the current window or all windows.
- Switch to a tab or close it from the popup.
- Optionally get notified when you open a page that is already open.
- Optionally close tabs unused for 1–30 days, with an hourly check. Active, pinned, playing, loading, incognito, and browser-internal tabs are kept.

Your tab information stays in your browser. No accounts, analytics, advertising, tracking, remote code, or data transmission. Duplicate detection and automatic closing are off by default. Automatic closing can lose unsaved work in otherwise eligible tabs.

Requires Chrome 121 or later.

## Single purpose

Count and manage open browser tabs, including listing, switching, closing, and optional duplicate and unused-tab management.

## Permission justifications

- **tabs:** Read open-tab titles and URLs for the tab list and exact duplicate detection. Read tab state and last-accessed timestamps to protect active, pinned, playing, and loading tabs during opt-in unused-tab closing. No page content or browsing-history access.
- **storage:** Save preferences locally and keep pending duplicate-notification actions in session storage so actions work after the Manifest V3 service worker stops. No sync or remote storage.
- **alarms:** Run the optional unused-tab check hourly using a wakeable Chrome alarm instead of a background timer.
- **notifications:** Show the optional duplicate-tab prompt. No page titles or URLs appear in notification text. Clicking switches to the existing tab and closes the unchanged duplicate; dismissing keeps both.
- **Host permissions:** None.
- **Remote code:** No. All executable code is bundled in the extension.

## Privacy policy URL

https://github.com/developerish/tab-count/blob/master/PRIVACY.md

Verify this URL is publicly accessible after pushing the release. The bundled `privacy.html` is the same policy for offline access from settings.

## Data-use disclosures

Disclose **Web history** to cover open-tab URLs/titles processed locally; the extension does not read the Chrome History database. Google requires disclosure of local-only data handling too. Other data categories are not used. No user data is transmitted, sold, or transferred to third parties. Confirm the limited-use statements only after verifying they remain true for the uploaded package.

## Reviewer test instructions

1. Load the extension with several disposable tabs in two normal Chrome windows. The badge initially shows the total count; the popup initially lists the current window.
2. Open Settings. Change the popup and badge scope. Both changes apply without reloading the extension. Switch windows and move a tab between them to verify the current-window count.
3. Use keyboard navigation to switch to a tab and close a disposable tab. Titles containing HTML markup must appear as literal text.
4. Enable duplicate notifications and open the same HTTP(S) URL twice. Clicking the notification or its first button switches to the existing tab and closes the duplicate. Dismiss it or choose Keep both to retain both. Three or more matching tabs are supported. OS notification settings can suppress visual prompts.
5. Close or navigate one tab before acting on a duplicate prompt: the other tab must be retained. Stop the service worker before clicking a still-pending prompt: the action must still work.
6. Enable unused-tab closing and inspect the `tabJanitor` hourly alarm. Disable it and confirm the alarm is removed. Run `npm test` for controlled stale-tab, navigation, and worker-restart cases without risking real work.

## Release notes: 3.0.0

Completed the Manifest V3 migration with reliable service-worker events, hourly alarms, safe duplicate actions, validated settings, keyboard-accessible tab controls, safe text rendering, and a local-only privacy policy. Uses Chrome's built-in tab last-accessed times instead of maintaining an activity-history database. Protects active, pinned, playing, loading, incognito, and browser-internal tabs from automatic closing.

## Release verification

- `npm run package`: 13 behavioral/package tests and syntax checks pass; upload archive contains only extension assets.
- Chrome for Testing 149: package loads without extension errors; current/all-window badge and list, switching across windows, closing a disposable tab, immediate preference changes, persisted settings, and invalid-day validation checked in the actual extension.
- Settings layout checked at 320 pixels, screenshots captured at store sizes, and extension-page console showed no messages. This is a desktop Chrome extension; Chrome on phones does not load it.
- Worker restart, pending notification actions, stale-tab safeguards, and legacy migration have deterministic regression coverage. OS notification presentation and action buttons vary by platform and remain subject to the user's notification settings.
Loading
Loading