@@ -3,7 +3,7 @@ import debugConnection from '../../utils/debugConnection';
33/*
44 * background.js
55 *
6- * Runs all the time and serves as a central message hub for panels, contentScript, backend
6+ * Runs as a service worker serves as a central message hub for panels, contentScript, backend
77 */
88
99if ( process . env . NODE_ENV === 'test' ) {
@@ -100,59 +100,27 @@ const installContentScript = tabId => {
100100 if ( err ) {
101101 handleInstallError ( tabId , err ) ;
102102 } else {
103- chrome . tabs . executeScript ( tabId , { file : '/contentScript .js' } , res => {
103+ chrome . scripting . executeScript ( { target : { tabId } , files : [ '/backend .js'] } , res => {
104104 const installError = chrome . runtime . lastError ;
105105 if ( err || ! res ) handleInstallError ( tabId , installError ) ;
106106 } ) ;
107107 }
108108 } ) ;
109109} ;
110110
111- function doublePipe ( one , two ) {
112- if ( ! one . $i ) {
113- one . $i = Math . random ( ) . toString ( 32 ) . slice ( 2 ) ;
114- }
115- if ( ! two . $i ) {
116- two . $i = Math . random ( ) . toString ( 32 ) . slice ( 2 ) ;
117- }
118-
119- debugConnection ( `BACKGORUND: connect ${ one . name } <-> ${ two . name } [${ one . $i } <-> ${ two . $i } ]` ) ;
120-
121- function lOne ( message ) {
122- debugConnection ( `${ one . name } -> BACKGORUND -> ${ two . name } [${ one . $i } -${ two . $i } ]` , message ) ;
123- try {
124- two . postMessage ( message ) ;
125- } catch ( e ) {
126- if ( __DEV__ ) console . error ( 'Unexpected disconnect, error' , e ) ; // eslint-disable-line no-console
127- shutdown ( ) ; // eslint-disable-line no-use-before-define
128- }
129- }
130- function lTwo ( message ) {
131- debugConnection ( `${ two . name } -> BACKGORUND -> ${ one . name } [${ two . $i } -${ one . $i } ]` , message ) ;
132- try {
133- one . postMessage ( message ) ;
134- } catch ( e ) {
135- if ( __DEV__ ) console . error ( 'Unexpected disconnect, error' , e ) ; // eslint-disable-line no-console
136- shutdown ( ) ; // eslint-disable-line no-use-before-define
137- }
138- }
139- one . onMessage . addListener ( lOne ) ;
140- two . onMessage . addListener ( lTwo ) ;
141- function shutdown ( ) {
142- debugConnection ( `SHUTDOWN ${ one . name } <-> ${ two . name } [${ one . $i } <-> ${ two . $i } ]` ) ;
143- one . onMessage . removeListener ( lOne ) ;
144- two . onMessage . removeListener ( lTwo ) ;
145- one . disconnect ( ) ;
146- two . disconnect ( ) ;
147- }
148- one . onDisconnect . addListener ( shutdown ) ;
149- two . onDisconnect . addListener ( shutdown ) ;
150- }
151-
152111if ( chrome . contextMenus ) {
153- // electron doesn't support this api
154- chrome . contextMenus . onClicked . addListener ( ( _ , contentWindow ) => {
155- openWindow ( contentWindow . id ) ;
112+ chrome . contextMenus . onClicked . addListener ( ( info , tab ) => {
113+ console . log ( 'Context menu clicked' , info , tab ) ;
114+ if ( info . menuItemId === 'mobx-devtools' ) {
115+ try {
116+ console . log ( 'Attempting to open window for tab' , tab . id ) ;
117+ window . contentTabId = tab . id ;
118+ installContentScript ( tab . id ) ;
119+ openWindow ( tab . id ) ;
120+ } catch ( err ) {
121+ console . error ( 'Error opening devtools window:' , err ) ;
122+ }
123+ }
156124 } ) ;
157125}
158126
@@ -176,54 +144,57 @@ if (chrome.browserAction) {
176144 } ) ;
177145}
178146
179- chrome . runtime . onInstalled . addListener ( ( ) => {
180- chrome . contextMenus . create ( {
181- id : 'mobx-devtools' ,
182- title : 'Open Mobx DevTools' ,
183- contexts : [ 'all' ] ,
184- } ) ;
147+ // Keep service worker alive
148+ chrome . runtime . onConnect . addListener ( port => {
149+ console . log ( 'Service worker connected to port:' , port . name ) ;
185150} ) ;
186151
152+ // Create a long-lived connection for the content script
153+ let contentScriptPorts = new Map ( ) ;
154+
187155chrome . runtime . onConnect . addListener ( port => {
188- let tab = null ;
189- let name = null ;
190- if ( isNumeric ( port . name ) ) {
191- tab = port . name ;
192- name = 'devtools' ;
193- installContentScript ( + port . name ) ;
194- } else {
195- tab = port . sender . tab . id ;
196- name = 'content-script' ;
197- }
156+ if ( port . name === 'content-script' ) {
157+ const tabId = port . sender . tab . id ;
158+ contentScriptPorts . set ( tabId , port ) ;
198159
199- if ( ! orphansByTabId [ tab ] ) {
200- orphansByTabId [ tab ] = [ ] ;
160+ port . onDisconnect . addListener ( ( ) => {
161+ contentScriptPorts . delete ( tabId ) ;
162+ } ) ;
201163 }
164+ } ) ;
202165
203- if ( name === 'content-script' ) {
204- const orphan = orphansByTabId [ tab ] . find ( t => t . name === 'devtools' ) ;
205- if ( orphan ) {
206- doublePipe ( orphan . port , port ) ;
207- orphansByTabId [ tab ] = orphansByTabId [ tab ] . filter ( t => t !== orphan ) ;
208- } else {
209- const newOrphan = { name, port } ;
210- orphansByTabId [ tab ] . push ( newOrphan ) ;
211- port . onDisconnect . addListener ( ( ) => {
212- if ( __DEV__ ) console . warn ( 'orphan devtools disconnected' ) ; // eslint-disable-line no-console
213- orphansByTabId [ tab ] = orphansByTabId [ tab ] . filter ( t => t !== newOrphan ) ;
166+ // Handle messages from panel
167+ chrome . runtime . onMessage . addListener ( ( message , sender , sendResponse ) => {
168+ if ( message . type === 'panel-to-backend' ) {
169+ // Use the existing port to send to content script
170+ const port = contentScriptPorts . get ( message . tabId ) ;
171+ if ( port ) {
172+ port . postMessage ( {
173+ type : 'panel-message' ,
174+ data : message . data ,
214175 } ) ;
215- }
216- } else if ( name === 'devtools' ) {
217- const orphan = orphansByTabId [ tab ] . find ( t => t . name === 'content-script' ) ;
218- if ( orphan ) {
219- orphansByTabId [ tab ] = orphansByTabId [ tab ] . filter ( t => t !== orphan ) ;
220176 } else {
221- const newOrphan = { name, port } ;
222- orphansByTabId [ tab ] . push ( newOrphan ) ;
223- port . onDisconnect . addListener ( ( ) => {
224- if ( __DEV__ ) console . warn ( 'orphan content-script disconnected' ) ; // eslint-disable-line no-console
225- orphansByTabId [ tab ] = orphansByTabId [ tab ] . filter ( t => t !== newOrphan ) ;
226- } ) ;
177+ console . error ( 'No connection to content script for tab:' , message . tabId ) ;
227178 }
228179 }
180+ // Return true to indicate we'll respond asynchronously
181+ return true ;
182+ } ) ;
183+
184+ // Handle messages from content script to panel
185+ chrome . runtime . onMessage . addListener ( ( message , sender ) => {
186+ if ( sender . tab && message . type === 'content-to-panel' ) {
187+ // Broadcast to all extension pages
188+ chrome . runtime
189+ . sendMessage ( {
190+ tabId : sender . tab . id ,
191+ data : message . data ,
192+ } )
193+ . catch ( err => {
194+ // Ignore errors about receiving end not existing
195+ if ( ! err . message . includes ( 'receiving end does not exist' ) ) {
196+ console . error ( 'Error sending message:' , err ) ;
197+ }
198+ } ) ;
199+ }
229200} ) ;
0 commit comments