Repository navigation
Closed
Description
Rebuild Messaging System for Chrome Extension (Side Panel ↔ Background ↔ Content)
Description:
Our current Chrome extension has messaging flows between the side panel, background script, and content script, but there are bugs and stability issues. We need to reconstruct the messaging layer to ensure it is reliable, maintainable, and resilient.
This new system should:
- Establish a solid connection between the side panel, background, and content scripts.
- Maintain that connection reliably across user sessions.
- Re-establish the connection if it drops (e.g., background reloads, tab reloads, extension restart).
- Provide a well-structured set of components or helper functions to manage sending and receiving messages across all systems.
- Standardize message formats and routing (e.g., typed events, handlers).
Example Flow (to illustrate intent):
- The side panel sends a request to the content script for user profiles.
- The content script relays that request to a JS tag injected into the DOM.
- The DOM script performs the necessary work, gathers data, and sends it back to the content script.
- The content script passes the result back to the background or side panel, where it can be stored or displayed.
- This pattern should be reusable for other actions (e.g., triggering events in the DOM, syncing data back to the extension).
Acceptance Criteria:
- Implement a standardized messaging API (
sendMessage,onMessage, etc.) available to all three systems. - Ensure reconnection logic exists (retry + re-establish on reloads).
- Provide clear utility functions/components for developers to extend messaging (e.g.,
registerHandler("GET_PROFILES", callback)). - Demonstrate with one working example (e.g.,
GET_PROFILES) where the side panel requests profiles, content retrieves them, and results return back to the extension. - Document the message structure and usage guidelines.
Priority: High – foundation work needed for all extension features.
Existing example of listener:
dev-center-extension/src/pages/content/ui/app.tsx
Lines 49 to 60 in 773041e
| // chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { | |
| chrome.runtime.onMessage.addListener((message, _, sendResponse) => { | |
| if (message.action == 'getConfig') { | |
| window.postMessage({ action: 'getConfig' }, '*'); | |
| } | |
| if (message.action == 'getEntity') { | |
| window.postMessage({ action: 'getEntity' }, '*'); | |
| } | |
| sendResponse(); | |
| }); |
Existing example of establishing connection and listener (background):
dev-center-extension/src/pages/panel/Panel.tsx
Lines 6 to 37 in 773041e
| const Panel: React.FC = () => { | |
| // Initialize a state variable to store the received message | |
| const [message, setMessage] = useState<string | null>(null); | |
| useEffect(() => { | |
| // Create a connection to the background script | |
| const backgroundConnection = chrome.runtime.connect({ | |
| name: 'devtools-panel', | |
| }); | |
| EmitLog({ name: 'panel', payload: { msg: 'Devtools panel connected.' } }); | |
| // Listen for messages from the background script | |
| backgroundConnection.onMessage.addListener(receivedMessage => { | |
| setMessage(receivedMessage.message); | |
| }); | |
| // Cleanup the connection when the component unmounts | |
| return () => { | |
| EmitLog({ name: 'panel', payload: { msg: 'Devtools panel disconnected.' } }); | |
| backgroundConnection.disconnect(); | |
| }; | |
| }, []); // Empty dependency array to run the effect once on component mount | |
| return ( | |
| <Box className="container"> | |
| <Typography variant="h1">Dev Tools Panel</Typography> | |
| <Button>test</Button> | |
| <Box>{message ? <div>{message}</div> : <div>No message received yet.</div>}</Box> | |
| </Box> | |
| ); | |
| }; |
Example of sending message to get the config:
dev-center-extension/src/pages/sidepanel/SidePanel.tsx
Lines 117 to 123 in 773041e
| chrome.tabs.sendMessage(tabs[0].id, { action: 'getConfig' }, response => { | |
| if (chrome.runtime.lastError) { | |
| // console.error('Error:', chrome.runtime.lastError.message); | |
| } else if (response) { | |
| EmitLog({ name: 'sidepanel', payload: { msg: 'Config response.', data: response } }); | |
| } | |
| }); |
Metadata
Metadata
Assignees
Labels
No labels
Activity