1- const DAEMON_PORT = 19825 ;
2- const DAEMON_HOST = "localhost" ;
3- const DAEMON_WS_URL = `ws://${ DAEMON_HOST } :${ DAEMON_PORT } /ext` ;
4- const DAEMON_PING_URL = `http://${ DAEMON_HOST } :${ DAEMON_PORT } /ping` ;
1+ const DEFAULT_DAEMON_HOST = "localhost" ;
2+ const DEFAULT_DAEMON_PORT = 19825 ;
3+ function buildDaemonEndpoints ( host , port ) {
4+ const h = ( host || DEFAULT_DAEMON_HOST ) . trim ( ) || DEFAULT_DAEMON_HOST ;
5+ const p = Number . isFinite ( port ) && port >= 1 && port <= 65535 ? port : DEFAULT_DAEMON_PORT ;
6+ const hostPart = h . includes ( ":" ) && ! h . startsWith ( "[" ) ? `[${ h } ]` : h ;
7+ return {
8+ ping : `http://${ hostPart } :${ p } /ping` ,
9+ ws : `ws://${ hostPart } :${ p } /ext`
10+ } ;
11+ }
512const WS_RECONNECT_BASE_DELAY = 2e3 ;
613const WS_RECONNECT_MAX_DELAY = 5e3 ;
714
@@ -210,9 +217,22 @@ function registerListeners() {
210217 } ) ;
211218}
212219
220+ const STORAGE_KEYS = { host : "daemonHost" , port : "daemonPort" } ;
213221let ws = null ;
222+ let activeWsUrl = null ;
223+ let pendingWsUrl = null ;
214224let reconnectTimer = null ;
215225let reconnectAttempts = 0 ;
226+ async function getDaemonSettings ( ) {
227+ const result = await chrome . storage . local . get ( {
228+ [ STORAGE_KEYS . host ] : DEFAULT_DAEMON_HOST ,
229+ [ STORAGE_KEYS . port ] : DEFAULT_DAEMON_PORT
230+ } ) ;
231+ let host = result [ STORAGE_KEYS . host ] ?. trim ( ) || DEFAULT_DAEMON_HOST ;
232+ let port = typeof result [ STORAGE_KEYS . port ] === "number" ? result [ STORAGE_KEYS . port ] : DEFAULT_DAEMON_PORT ;
233+ if ( ! Number . isFinite ( port ) || port < 1 || port > 65535 ) port = DEFAULT_DAEMON_PORT ;
234+ return { host, port } ;
235+ }
216236const _origLog = console . log . bind ( console ) ;
217237const _origWarn = console . warn . bind ( console ) ;
218238const _origError = console . error . bind ( console ) ;
@@ -237,21 +257,37 @@ console.error = (...args) => {
237257 forwardLog ( "error" , args ) ;
238258} ;
239259async function connect ( ) {
240- if ( ws ?. readyState === WebSocket . OPEN || ws ?. readyState === WebSocket . CONNECTING ) return ;
260+ const { host, port } = await getDaemonSettings ( ) ;
261+ const { ping : pingUrl , ws : wsUrl } = buildDaemonEndpoints ( host , port ) ;
262+ if ( ws ) {
263+ if ( ws . readyState === WebSocket . OPEN && activeWsUrl === wsUrl ) return ;
264+ if ( ws . readyState === WebSocket . CONNECTING && pendingWsUrl === wsUrl ) return ;
265+ try {
266+ ws . close ( ) ;
267+ } catch {
268+ }
269+ ws = null ;
270+ activeWsUrl = null ;
271+ pendingWsUrl = null ;
272+ }
241273 try {
242- const res = await fetch ( DAEMON_PING_URL , { signal : AbortSignal . timeout ( 1e3 ) } ) ;
274+ const res = await fetch ( pingUrl , { signal : AbortSignal . timeout ( 1e3 ) } ) ;
243275 if ( ! res . ok ) return ;
244276 } catch {
245277 return ;
246278 }
247279 try {
248- ws = new WebSocket ( DAEMON_WS_URL ) ;
280+ pendingWsUrl = wsUrl ;
281+ ws = new WebSocket ( wsUrl ) ;
249282 } catch {
283+ pendingWsUrl = null ;
250284 scheduleReconnect ( ) ;
251285 return ;
252286 }
253287 ws . onopen = ( ) => {
254288 console . log ( "[opencli] Connected to daemon" ) ;
289+ pendingWsUrl = null ;
290+ activeWsUrl = wsUrl ;
255291 reconnectAttempts = 0 ;
256292 if ( reconnectTimer ) {
257293 clearTimeout ( reconnectTimer ) ;
@@ -271,6 +307,8 @@ async function connect() {
271307 ws . onclose = ( ) => {
272308 console . log ( "[opencli] Disconnected from daemon" ) ;
273309 ws = null ;
310+ activeWsUrl = null ;
311+ pendingWsUrl = null ;
274312 scheduleReconnect ( ) ;
275313 } ;
276314 ws . onerror = ( ) => {
@@ -364,12 +402,30 @@ chrome.runtime.onStartup.addListener(() => {
364402chrome . alarms . onAlarm . addListener ( ( alarm ) => {
365403 if ( alarm . name === "keepalive" ) void connect ( ) ;
366404} ) ;
405+ chrome . storage . onChanged . addListener ( ( changes , area ) => {
406+ if ( area !== "local" ) return ;
407+ if ( ! changes [ STORAGE_KEYS . host ] && ! changes [ STORAGE_KEYS . port ] ) return ;
408+ try {
409+ ws ?. close ( ) ;
410+ } catch {
411+ }
412+ ws = null ;
413+ activeWsUrl = null ;
414+ pendingWsUrl = null ;
415+ reconnectAttempts = 0 ;
416+ void connect ( ) ;
417+ } ) ;
367418chrome . runtime . onMessage . addListener ( ( msg , _sender , sendResponse ) => {
368419 if ( msg ?. type === "getStatus" ) {
369- sendResponse ( {
370- connected : ws ?. readyState === WebSocket . OPEN ,
371- reconnecting : reconnectTimer !== null
420+ void getDaemonSettings ( ) . then ( ( { host, port } ) => {
421+ sendResponse ( {
422+ connected : ws ?. readyState === WebSocket . OPEN ,
423+ reconnecting : reconnectTimer !== null ,
424+ host,
425+ port
426+ } ) ;
372427 } ) ;
428+ return true ;
373429 }
374430 return false ;
375431} ) ;
0 commit comments