Skip to content

Conversation

@hamidi-dev
Copy link

Changes

Manifest V3 Migration (src/manifest.json)

  • Updated manifest_version from 2 to 3
  • Changed browser_action to action
  • Migrated background.scripts to background.service_worker
  • Added host_permissions array for required permissions
  • Updated web_accessible_resources to MV3 object format

Service Worker Compatibility (src/background.ts)

  • Replaced window.crypto with globalThis.crypto for service worker compatibility
  • Changed all window references to globalThis to work in service worker context
  • Updated browser.browserAction.setIcon() to browser.action.setIcon() for MV3 API

Browser Detection Fix (src/utils/utils.ts)

  • Fixed "window is not defined" error in service workers by making browser detection lazy
  • Added service worker fallback using browser.runtime.getBrowserInfo instead of window.location
  • Previously top-level code accessed window.location at module load time, breaking service workers

Icon Generation Dual-Path (src/utils/utils.ts)

  • Service workers use OffscreenCanvas with PNG since createImageBitmap() doesn't support SVG
  • DOM contexts continue using regular canvas with SVG (unchanged)
  • Runtime detection via typeof window === 'undefined' || typeof document === 'undefined'

Canvas Performance Optimization (src/utils/utils.ts, src/renderer.ts)

  • Added { willReadFrequently: true } to all canvas context creation to fix Chrome performance warnings

Webpack Configuration (webpack.config.js)

  • Chrome builds use service_worker for background
  • Firefox builds explicitly override to use scripts: ["background.js"] (Firefox MV3 still supports background scripts)
  • Updated Firefox minimum version to 109.0
  • Fixed CSP format for MV3 testing builds

Why This Approach

Firefox Compatibility: Firefox MV3 background scripts retain window/document access, so webpack explicitly configures Firefox to use scripts mode. The runtime detection ensures the existing SVG code path is taken.

Chrome Service Workers: Chrome MV3 requires true service workers without DOM access, so we use OffscreenCanvas with a pre-generated PNG for icon generation.

closes #1674

…upport

- Update manifest.json to MV3 format with service_worker, action, and
host_permissions
- Replace window/document references with globalThis for service worker
compatibility
- Implement lazy browser detection to avoid module-load-time window
access
- Add dual-path icon generation: OffscreenCanvas+PNG for service
workers, DOM+SVG for regular contexts
- Configure webpack to build Chrome with service_worker and Firefox with
background scripts
- Firefox behavior remains unchanged, using MV3 background scripts with
DOM access
- Add willReadFrequently hint to canvas contexts for better performance
- Resolves Canvas2D performance warning by setting willReadFrequently
attribute when creating 2D contexts for icon generation in both service worker and
DOM paths.
- Add willReadFrequently to renderer canvas context to optimize Neovim
display
- Change unhandled page request from error to debug level since messages
may be broadcast to multiple listeners and this is expected behavior
@glacambre
Copy link
Owner

Hi, thanks for taking the time to open an MR. Someone already did this (also with AI!) here: #1692 , I just haven't taken the time to properly review it. Your MR seems to do a lot less than theirs, do you know why?

@hamidi-dev
Copy link
Author

hamidi-dev commented Nov 19, 2025

Hi!

Yes, I can explain the scope difference:

The key architectural difference:

  • My approach (chrome: migrate Chrome extension to Manifest V3 with service worker support #1700): Keeps the existing preloaded Neovim instance and funcName-based RPC system. I focused on making minimal changes to get Chrome working with MV3 service workers by using globalThis instead of window, adding lazy browser detection, and creating a dual-path for icon generation (OffscreenCanvas for service workers, DOM for regular contexts).

  • Testing farzadmf's mv3 MR #1692 approach: Removes the preloaded instance entirely (creating Neovim on-demand), refactors the entire message passing system with a typed MessageType enum, migrates all state to browser.storage.session API, and brings both Chrome AND Firefox to MV3. It's a much more comprehensive migration.

Why I took the simpler approach:

When I read your earlier comment about how "Manifest v3 disallows long-lived processes, so a lot of refactoring may have to happen," I wanted to first see if we could get Chrome working without that major refactor. In my testing, the preloaded instance actually works fine in Chrome's service worker environment.

Potential path forward:

My thinking was this could serve as an intermediate solution to unblock Chrome users quickly while you have time to properly review and test the more comprehensive refactor. Chrome support has been broken for a while, so getting something working sooner might be valuable to users—even if it's not the final architecture.

The other approach is definitely more thorough and addresses the architectural concerns more completely. It's really a question of whether you'd prefer:

  1. Ship mine quickly as a stopgap → users have working Chrome extension → later review/merge the comprehensive refactor at your pace
  2. Take time to properly review the comprehensive approach → merge that directly → Chrome users wait longer but get the better architecture

Either way is fine with me! I'm just trying to help unblock the situation.

In the meantime I will continue using my fork until the situation is resolved :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chrome extension no longer supported

2 participants