refactor(ext): rewrite ext. totally-broken -> still-broken; THIS IS NOT WORKING
This commit is contained in:
@@ -1,82 +1,51 @@
|
||||
/**
|
||||
* Background Script (Service Worker) - Stateless Message Relay
|
||||
*
|
||||
* MV3 COMPLIANT: This script is completely stateless.
|
||||
* It only relays messages between contexts:
|
||||
* - SidePanel ↔ ContentScript (RPC for PageController)
|
||||
* - ContentScript → SidePanel (queries like shouldShowMask)
|
||||
* - Tab events → SidePanel (chrome.tabs API events)
|
||||
*
|
||||
* NO agent logic, NO state, NO long-running operations.
|
||||
* Completely stateless. Only two responsibilities:
|
||||
* 1. Relay AGENT_TO_PAGE messages from SidePanel to ContentScript
|
||||
* 2. Broadcast TAB_CHANGE events to all extension pages
|
||||
*/
|
||||
import {
|
||||
type CSQueryMessage,
|
||||
type CSRPCMessage,
|
||||
type ExtensionMessage,
|
||||
type QueryResponseMessage,
|
||||
type RPCCallMessage,
|
||||
type TabEventMessage,
|
||||
generateMessageId,
|
||||
type AgentToPageMessage,
|
||||
type TabChangeMessage,
|
||||
isExtensionMessage,
|
||||
} from '../agent/protocol'
|
||||
|
||||
// ============================================================================
|
||||
// Message Relay Handlers
|
||||
// Message Relay
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Handle messages from SidePanel and ContentScript
|
||||
*/
|
||||
chrome.runtime.onMessage.addListener(
|
||||
(
|
||||
message: unknown,
|
||||
sender: chrome.runtime.MessageSender,
|
||||
_sender: chrome.runtime.MessageSender,
|
||||
sendResponse: (response?: unknown) => void
|
||||
): boolean => {
|
||||
if (!isExtensionMessage(message)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const msg = message as ExtensionMessage
|
||||
|
||||
switch (msg.type) {
|
||||
case 'rpc:call':
|
||||
// SidePanel → SW: Forward RPC to content script, return result via sendResponse
|
||||
handleRPCCall(msg as RPCCallMessage, sendResponse)
|
||||
return true // Async response
|
||||
|
||||
case 'cs:query':
|
||||
// ContentScript → SW: Forward query to sidepanel
|
||||
handleCSQuery(msg as CSQueryMessage, sender)
|
||||
return false
|
||||
|
||||
default:
|
||||
return false
|
||||
if (message.type === 'AGENT_TO_PAGE') {
|
||||
handleAgentToPage(message as AgentToPageMessage, sendResponse)
|
||||
return true // Async response
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Forward RPC call from SidePanel to ContentScript
|
||||
* Uses sendResponse to return result directly (MV3 compliant)
|
||||
*/
|
||||
async function handleRPCCall(
|
||||
msg: RPCCallMessage,
|
||||
async function handleAgentToPage(
|
||||
msg: AgentToPageMessage,
|
||||
sendResponse: (response: { success: boolean; result?: unknown; error?: string }) => void
|
||||
): Promise<void> {
|
||||
const { tabId, method, args } = msg
|
||||
|
||||
// Create message for content script
|
||||
const csMessage: CSRPCMessage = {
|
||||
type: 'cs:rpc',
|
||||
id: msg.id,
|
||||
method,
|
||||
args,
|
||||
}
|
||||
|
||||
try {
|
||||
// Send to content script and wait for response
|
||||
const result = await chrome.tabs.sendMessage(tabId, csMessage)
|
||||
// Forward directly to content script, same message format
|
||||
const result = await chrome.tabs.sendMessage(tabId, msg)
|
||||
sendResponse({ success: true, result })
|
||||
} catch (error) {
|
||||
sendResponse({
|
||||
@@ -86,122 +55,59 @@ async function handleRPCCall(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward query from ContentScript to SidePanel
|
||||
*/
|
||||
async function handleCSQuery(
|
||||
msg: CSQueryMessage,
|
||||
sender: chrome.runtime.MessageSender
|
||||
): Promise<void> {
|
||||
const { id, queryType, tabId } = msg
|
||||
// ============================================================================
|
||||
// Tab Event Broadcasting
|
||||
// ============================================================================
|
||||
|
||||
// For shouldShowMask, we need to ask the sidepanel
|
||||
// Since sidepanel may not be open, we'll use a timeout approach
|
||||
// The sidepanel registers a listener for these queries
|
||||
|
||||
try {
|
||||
// Broadcast to sidepanel (it will respond via query:response)
|
||||
const response = await chrome.runtime.sendMessage(msg)
|
||||
|
||||
// Forward response back to content script
|
||||
if (sender.tab?.id) {
|
||||
const queryResponse: QueryResponseMessage = {
|
||||
type: 'query:response',
|
||||
id,
|
||||
result: response,
|
||||
}
|
||||
await chrome.tabs.sendMessage(sender.tab.id, queryResponse)
|
||||
}
|
||||
} catch (error) {
|
||||
// Sidepanel not open or no response, return default
|
||||
if (sender.tab?.id) {
|
||||
const queryResponse: QueryResponseMessage = {
|
||||
type: 'query:response',
|
||||
id,
|
||||
result: queryType === 'shouldShowMask' ? false : null,
|
||||
}
|
||||
await chrome.tabs.sendMessage(sender.tab.id, queryResponse).catch(() => {})
|
||||
}
|
||||
}
|
||||
function broadcastTabChange(message: TabChangeMessage): void {
|
||||
chrome.runtime.sendMessage(message).catch(() => {
|
||||
// No listeners (sidepanel not open)
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tab Event Forwarding
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Forward tab removed events to sidepanel
|
||||
*/
|
||||
chrome.tabs.onRemoved.addListener((tabId) => {
|
||||
const message: TabEventMessage = {
|
||||
type: 'tab:event',
|
||||
id: generateMessageId(),
|
||||
broadcastTabChange({
|
||||
type: 'TAB_CHANGE',
|
||||
eventType: 'removed',
|
||||
tabId,
|
||||
}
|
||||
chrome.runtime.sendMessage(message).catch(() => {
|
||||
// Sidepanel may not be open
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Forward tab updated events to sidepanel
|
||||
*/
|
||||
chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
|
||||
// Only forward loading/complete status changes
|
||||
if (!changeInfo.status) return
|
||||
|
||||
const message: TabEventMessage = {
|
||||
type: 'tab:event',
|
||||
id: generateMessageId(),
|
||||
broadcastTabChange({
|
||||
type: 'TAB_CHANGE',
|
||||
eventType: 'updated',
|
||||
tabId,
|
||||
data: {
|
||||
status: changeInfo.status,
|
||||
url: changeInfo.url,
|
||||
},
|
||||
}
|
||||
chrome.runtime.sendMessage(message).catch(() => {
|
||||
// Sidepanel may not be open
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Forward tab activated events to sidepanel (user switches tabs)
|
||||
*/
|
||||
chrome.tabs.onActivated.addListener((activeInfo) => {
|
||||
const message: TabEventMessage = {
|
||||
type: 'tab:event',
|
||||
id: generateMessageId(),
|
||||
broadcastTabChange({
|
||||
type: 'TAB_CHANGE',
|
||||
eventType: 'activated',
|
||||
tabId: activeInfo.tabId,
|
||||
data: {
|
||||
windowId: activeInfo.windowId,
|
||||
},
|
||||
}
|
||||
chrome.runtime.sendMessage(message).catch(() => {
|
||||
// Sidepanel may not be open
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Forward window focus changed events to sidepanel
|
||||
*/
|
||||
chrome.windows.onFocusChanged.addListener((windowId) => {
|
||||
// windowId is chrome.windows.WINDOW_ID_NONE (-1) when all windows lose focus
|
||||
const focused = windowId !== chrome.windows.WINDOW_ID_NONE
|
||||
const message: TabEventMessage = {
|
||||
type: 'tab:event',
|
||||
id: generateMessageId(),
|
||||
broadcastTabChange({
|
||||
type: 'TAB_CHANGE',
|
||||
eventType: 'windowFocusChanged',
|
||||
tabId: -1, // Not applicable for window focus events
|
||||
tabId: -1,
|
||||
data: {
|
||||
windowId: focused ? windowId : undefined,
|
||||
focused,
|
||||
},
|
||||
}
|
||||
chrome.runtime.sendMessage(message).catch(() => {
|
||||
// Sidepanel may not be open
|
||||
})
|
||||
})
|
||||
|
||||
@@ -210,10 +116,7 @@ chrome.windows.onFocusChanged.addListener((windowId) => {
|
||||
// ============================================================================
|
||||
|
||||
export default defineBackground(() => {
|
||||
console.log('[Background] Service Worker started (stateless relay mode)')
|
||||
console.log('[Background] Service Worker started')
|
||||
|
||||
// Open sidepanel on action click
|
||||
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {
|
||||
// Side panel may not be supported
|
||||
})
|
||||
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user