如何在兼容Edge/Firefox/Chrome的扩展内容脚本中实现消息传递回调
Hey there! Let's break down solutions for your two key challenges: debugging Edge 2018 (Edge Legacy) on your Windows 7 workstation, and fixing the message passing callback inconsistencies across browsers.
1. Debugging Edge 2018 (Edge Legacy) Without a Win10 VM
Since you can't spin up a Win10 VM, remote debugging is your best bet. Here are two solid approaches:
Option 1: Remote Debug via Chrome DevTools
- Grab a Windows 10 machine (could be a colleague's or a spare device) and install Edge Legacy (if it's been upgraded to Chromium Edge, you can download the old Edge Legacy installer from Microsoft's archive).
- Open Edge Legacy, type
about:flagsin the address bar, enable Enable remote debugging, then restart the browser. - On your Windows 7 dev machine, open Chrome and navigate to
chrome://inspect. Click Configure, add the Win10 machine's IP address plus port 9222 (e.g.,http://192.168.1.100:9222), and save. - Refresh the
chrome://inspectpage—you'll see the Edge Legacy instance running on the Win10 machine. Click Inspect to launch DevTools and debug your extension just like you would locally.
Option 2: VS Code Remote Debugging
- Install the Debugger for Edge extension in VS Code.
- Create a
.vscode/launch.jsonfile with this configuration (adjust theremoteRootto match where your extension is stored on the Win10 machine):{ "version": "0.2.0", "configurations": [ { "type": "edge", "request": "attach", "name": "Attach to Remote Edge Legacy", "port": 9222, "url": "http://localhost/*", "webRoot": "${workspaceFolder}/src", "remoteRoot": "C:\\Users\\YourUser\\Documents\\YourExtension" } ] } - Follow the steps from Option 1 to enable remote debugging on the Win10 Edge Legacy instance, then start the debug session in VS Code. You'll be able to set breakpoints and inspect your extension code directly.
2. Unified Message Passing with Promise-Based Compatibility
The callback/Promise inconsistency between browsers is a common pain point—let's replace your IndexedDB hack with a clean, reliable wrapper that standardizes the API to use Promises everywhere.
First: Reliable Browser Detection
Instead of relying on window.msBrowser (which can be unreliable), use API-based checks and user agent filtering to identify each browser:
// Check if we're running in Firefox async function isFirefox() { if (typeof browser !== 'undefined' && browser.runtime?.getBrowserInfo) { try { const info = await browser.runtime.getBrowserInfo(); return info.name === 'Firefox'; } catch (err) { return false; } } return false; } // Check if we're running in Edge Legacy (2018) function isEdgeLegacy() { return typeof browser !== 'undefined' && navigator.userAgent.includes('Edge') && !navigator.userAgent.includes('Chrome'); } // Check if we're running in Chrome function isChrome() { return typeof chrome !== 'undefined' && navigator.userAgent.includes('Chrome') && !navigator.userAgent.includes('Edge'); }
Second: Wrapper for sendGlobalMessage
This function will abstract away the browser-specific API differences and return a Promise every time:
async function sendGlobalMessage(message, options = {}) { const ff = await isFirefox(); const edgeLegacy = isEdgeLegacy(); const chromeBrowser = isChrome(); return new Promise((resolve, reject) => { if (ff) { // Firefox uses native Promises for browser.runtime.sendMessage browser.runtime.sendMessage(message, options) .then(resolve) .catch(reject); } else if (edgeLegacy) { // Edge Legacy uses callbacks—handle lastError properly browser.runtime.sendMessage(message, options, (response) => { if (browser.runtime.lastError) { reject(new Error(browser.runtime.lastError.message)); } else { resolve(response); } }); } else if (chromeBrowser) { // Chrome uses callbacks—handle lastError properly chrome.runtime.sendMessage(message, options, (response) => { if (chrome.runtime.lastError) { reject(new Error(chrome.runtime.lastError.message)); } else { resolve(response); } }); } else { reject(new Error('Unsupported browser environment')); } }); }
How to Use It
Now you can call sendGlobalMessage anywhere in your code without worrying about browser differences:
// Example: Send a message and handle the response sendGlobalMessage({ action: 'fetchUserData', userId: 123 }) .then((response) => { console.log('Got user data:', response); // Do something with the response }) .catch((error) => { console.error('Message failed to send:', error); // Handle errors });
This approach is cleaner than the IndexedDB hack, keeps your codebase consistent, and makes it easy to maintain across all three browsers.
内容的提问来源于stack exchange,提问作者tom_mai78101

