Force Paster is a browser extension that lets you paste text into any input field or text area — even on sites that have deliberately blocked pasting. One click enables it; one click turns it back off.
- Force paste anywhere — overrides paste-blocking for
<input>,<textarea>, and supportedcontenteditableeditors (including rich text and images where the site allows it) - One-click toggle — click the extension icon to enable or disable; the toolbar badge shows the current state (
on/off) - Keyboard shortcut — toggle with Alt+Shift+P on desktop (remappable per browser)
- Right-click context menu — on desktop: toggle, open the dashboard, manage shortcuts, rate the extension, or report a bug from the toolbar icon
- Dashboard — a tabbed settings page (Settings / What's new / More); open it via the context menu or the browser’s extension options
- Dark & light icons — the toolbar icon automatically follows your system theme
- Cross-browser — Chrome, Brave, Edge, Firefox desktop (121+), and Firefox for Android (toggle via extensions menu or options; no keyboard shortcuts / context menus on Android)
| Browser | Link |
|---|---|
| Chrome / Brave / Edge | Chrome Web Store |
| Firefox (desktop & Android) | Firefox Add-ons |
- Clone the repository:
git clone https://github.com/prvashisht/force-paster.git
- Chrome / Brave / Edge — navigate to
chrome://extensions/, enable Developer mode, click Load unpacked, and select the cloned folder. - Firefox desktop — navigate to
about:debugging#/runtime/this-firefox, click Load Temporary Add-on, and selectmanifest.jsoninside the cloned folder. - Firefox for Android — use
web-extwith USB debugging (see Mozilla’s guide), e.g.npx web-ext run -t firefox-android --adb-device <id> --firefox-apk org.mozilla.firefox.
Chrome load-unpacked note: loading the raw repo folder may show a warning about Firefox-only manifest fields (
browser_specific_settings,background.scripts). That is expected for the shared source tree. For a Chromium-clean package, run./build.shand load the contents of the Chrome zip fromdist/.
Note (Chrome): loading the folder unpacked shows a harmless warning —
'background.scripts' requires manifest version of 2 or lower.This is expected.manifest.jsonis shared across browsers (Firefox usesbackground.scripts, Chrome usesbackground.service_worker), andbuild.shstrips the key that doesn't apply to each target when packaging. The extension still loads and works normally.
User clicks icon / presses Alt+Shift+P / uses context menu / options toggle
│
▼
service_worker.js ←─ action.onClicked / _execute_action / contextMenus (desktop) / messages
• toggles isPasteEnabled in storage.local
• updates badge text ("on" / "off") and badge colour
• syncs the context menu checkbox when that API exists (skipped on Android)
• dispatches analytics events (fp_toggle, fp_menu_click, etc.)
│
▼ storage.onChanged
content.js (injected into every page / frame)
• document-level capture-phase `paste` listener (runs before site handlers)
• when isPasteEnabled: stops the site from blocking paste, then:
– input/textarea: native value setter + input/change events
– contenteditable: synthetic ClipboardEvent (MIME types + files), with fallbacks
• reports paste completion back to the background via runtime messages
• watches prefers-color-scheme and notifies the background for icon variants
│
▼ (options page)
options.html / options.js
• standalone dashboard — reads state from storage.local
• toggle sends a "setenabled" message (with storage fallback)
• on Android: hides shortcuts / pin helper; shows a short platform note
• shows paste count, toggle count, and (on desktop) the keyboard shortcut
All Chromium/Firefox API differences are centralised in webext.js. The service worker and options page use webext.* throughout; content.js and analytics.js use the chrome namespace, which Firefox MV3 also exposes in those contexts. Context menus and keyboard commands are desktop-only; the background script detects missing APIs so Firefox for Android still loads cleanly.
| Path | Description |
|---|---|
manifest.json |
Extension manifest (MV3) — permissions, icons, content scripts, keyboard command, options page, gecko / gecko_android |
webext.js |
Browser adapter — Chromium vs Firefox, unified webext helpers |
content.js |
Content script — capture-phase paste engine for inputs and contenteditable |
service_worker.js |
Background — toggle state, badge, context menus (when available), analytics |
options.html / options.js |
Dashboard UI and logic |
release-notes.json |
Bundled “What’s new” notes (must match manifest version at build time) |
analytics.js |
GA4 proxy helper |
build.sh |
Builds Chromium and Firefox zips under dist/ |
scripts/lint-firefox.sh |
Builds the Firefox zip and lints it with the same engine AMO uses |
test-fixtures/ |
Local pages for manual testing (e.g. paste-blocked demo) |
PRIVACY_POLICY.md |
Privacy policy |
Events are sent anonymously via the generic Cloud Functions GA proxy, identified as Force Paster with X-Extension-App: forcepaster. Existing install token, client ID, and session storage keys are retained for continuity. Analytics failures are logged and do not block extension behavior.
| Event | When | Key params |
|---|---|---|
fp_extension_installed |
First install | reason, platform info, locale |
fp_extension_updated |
Extension update | reason, platform info, locale |
fp_toggle |
Enable/disable toggled | enabled, source (action_icon / context_menu / options_page) |
fp_paste |
Paste completed | tag (element type), domain |
fp_menu_click |
Context menu item clicked (non-toggle) | item (shortcuts / options / rate / bug) |
fp_options_open |
Dashboard page opened | — |
fp_options_click |
Link clicked on dashboard | item (rate / bug / github / bmc / app_* / footer_author) |
fp_rating_prompt |
User responded to the rating toast | choice (rate / later / never) |
- Node.js is not required to run the extension — it is plain JavaScript with no app build step.
- Node/
npxis only needed for packaging helpers (./build.shversion checks,./scripts/lint-firefox.sh).
- Make your changes to the source files.
- In Chrome, go to
chrome://extensions/and click the reload icon on the Force Paster card to pick up changes. - In Firefox, go to
about:debugging#/runtime/this-firefoxand click Reload next to Force Paster. - Test on a paste-blocking page. A local demo is in
test-fixtures/paste-blocked.html(serve it overhttp://localhostso content scripts inject).
./build.sh # Chromium + Firefox zips in dist/
./scripts/lint-firefox.sh # build Firefox zip, then addons-linter via web-extFix errors before submitting to AMO. Notices/warnings (for example future data_collection_permissions) should be reviewed but may already be known.
You don't need this to develop, but to produce the distributable zips locally, run ./build.sh. It writes dist/force-paster-chrome-v*.zip and dist/force-paster-firefox-v*.zip, and requires Node.js and zip. The build fails if the manifest.json and release-notes.json versions don't match.
- Chrome / Brave / Edge —
chrome://extensions/shortcuts - Firefox desktop —
about:addons→ Extensions → Force Paster → Manage - Firefox Android — not supported by the platform
- Bump
"version"inmanifest.json. - Update
"version"and"notes"inrelease-notes.jsonto match — the build will fail if they differ. - Merge to
main. Therelease.ymlworkflow triggers automatically, builds both zips, creates a GitHub release with auto-generated notes, and attaches the zips as assets. This in turn triggersstore-deploy.yml, which publishes automatically to the Chrome Web Store and Firefox Add-ons. - Edge — upload
force-paster-chrome-v*.zipfrom the GitHub release manually at Microsoft Partner Center. The Chrome zip is compatible with Chromium browsers such as Brave and Edge; Firefox-only manifest fields are stripped by the build script.
Checklist every release:
manifest.jsonversion bumpedrelease-notes.jsonversion and notes updated- README features/structure updated if new things were added
./scripts/lint-firefox.shclean of errors (especially if Firefox/Android packaging changed)- Edge Add-ons updated manually via Partner Center
Contributions are welcome! Please read CONTRIBUTING.md and follow the Code of Conduct before opening a pull request.