src/shells/webextension/backend.js
function waitForPing() {
  function pingListener(evt) {
    if (evt.data.source === 'mobx-devtools-content-script' && evt.data.payload === 'backend:ping') {
      debugConnection('[contentScript -> BACKEND]', evt);
      const contentScriptId = evt.data.contentScriptId;

      window.removeEventListener('message', pingListener);
      clearTimeout(handshakeFailedTimeout);

      const payload = 'contentScript:pong';
      debugConnection('[contentScript -> BACKEND]', payload);
      window.postMessage(
        { source: 'mobx-devtools-backend', payload, contentScriptId, backendId },
        '*'
      );

      const helloListener = (e) => {
        if (
          e.data.source === 'mobx-devtools-content-script' &&
          e.data.payload === 'backend:hello' &&
          e.data.contentScriptId === contentScriptId &&
          e.data.backendId === backendId
        ) {
          debugConnection('[contentScript -> BACKEND]', e);
          window.removeEventListener('message', helloListener);
          window.removeEventListener('message', failListener);
          // eslint-disable-next-line no-underscore-dangle
          handshake(window.__MOBX_DEVTOOLS_GLOBAL_HOOK__, contentScriptId);
        }
      };

      const failListener = (e) => {
        if (
          e.data.source === 'mobx-devtools-content-script' &&
          e.data.payload === 'backend:connection-failed' &&
          e.data.contentScriptId === contentScriptId &&
          e.data.backendId === backendId
        ) {
          debugConnection('[contentScript -> BACKEND]', e);
          window.removeEventListener('message', helloListener);
          window.removeEventListener('message', failListener);
          waitForPing();
        }
      };

      window.addEventListener('message', helloListener);
      window.addEventListener('message', failListener);
    }
  }

  const handshakeFailedTimeout = setTimeout(() => {
    debugConnection('[BACKEND] handshake failed (timeout)');
    window.removeEventListener('message', pingListener);
  }, 10000);

  window.addEventListener('message', pingListener);
}
function waitForPing() {
  function pingListener(evt) {
    if (evt.data.source === 'mobx-devtools-content-script' && evt.data.payload === 'backend:ping') {
      debugConnection('[contentScript -> BACKEND]', evt);
      const contentScriptId = evt.data.contentScriptId;

      window.removeEventListener('message', pingListener);
      clearTimeout(handshakeFailedTimeout);

      const payload = 'contentScript:pong';
      debugConnection('[contentScript -> BACKEND]', payload);
      window.postMessage(
        { source: 'mobx-devtools-backend', payload, contentScriptId, backendId },
        '*'
      );

      const helloListener = (e) => {
        if (
          e.data.source === 'mobx-devtools-content-script' &&
          e.data.payload === 'backend:hello' &&
          e.data.contentScriptId === contentScriptId &&
          e.data.backendId === backendId
        ) {
          debugConnection('[contentScript -> BACKEND]', e);
          window.removeEventListener('message', helloListener);
          window.removeEventListener('message', failListener);
          // eslint-disable-next-line no-underscore-dangle
          handshake(window.__MOBX_DEVTOOLS_GLOBAL_HOOK__, contentScriptId);
        }
      };

      const failListener = (e) => {
        if (
          e.data.source === 'mobx-devtools-content-script' &&
          e.data.payload === 'backend:connection-failed' &&
          e.data.contentScriptId === contentScriptId &&
          e.data.backendId === backendId
        ) {
          debugConnection('[contentScript -> BACKEND]', e);
          window.removeEventListener('message', helloListener);
          window.removeEventListener('message', failListener);
          waitForPing();
        }
      };

      window.addEventListener('message', helloListener);
      window.addEventListener('message', failListener);
    }
  }

  const handshakeFailedTimeout = setTimeout(() => {
    debugConnection('[BACKEND] handshake failed (timeout)');
    window.removeEventListener('message', pingListener);
  }, 10000);

  window.addEventListener('message', pingListener);
}
function waitForPing ( ) { function pingListener ( evt ) { if ( evt . data . source === 'mobx-devtools-content-script' && evt . data . payload === 'backend:ping' ) { debugConnection ( '[contentScript -> BACKEND]' , evt ) ; const contentScriptId = evt . data . contentScriptId ; window . removeEventListener ( 'message' , pingListener ) ; clearTimeout ( handshakeFailedTimeout ) ; const payload = 'contentScript:pong' ; debugConnection ( '[contentScript -> BACKEND]' , payload ) ; window . postMessage ( { source : 'mobx-devtools-backend' , payload , contentScriptId , backendId } , '*' ) ; const helloListener = ( e ) => { if ( e . data . source === 'mobx-devtools-content-script' && e . data . payload === 'backend:hello' && e . data . contentScriptId === contentScriptId && e . data . backendId === backendId ) { debugConnection ( '[contentScript -> BACKEND]' , e ) ; window . removeEventListener ( 'message' , helloListener ) ; window . removeEventListener ( 'message' , failListener ) ; // eslint-disable-next-line no-underscore-dangle handshake ( window . __MOBX_DEVTOOLS_GLOBAL_HOOK__ , contentScriptId ) ; } } ; const failListener = ( e ) => { if ( e . data . source === 'mobx-devtools-content-script' && e . data . payload === 'backend:connection-failed' && e . data . contentScriptId === contentScriptId && e . data . backendId === backendId ) { debugConnection ( '[contentScript -> BACKEND]' , e ) ; window . removeEventListener ( 'message' , helloListener ) ; window . removeEventListener ( 'message' , failListener ) ; waitForPing ( ) ; } } ; window . addEventListener ( 'message' , helloListener ) ; window . addEventListener ( 'message' , failListener ) ; } } const handshakeFailedTimeout = setTimeout ( ( ) => { debugConnection ( '[BACKEND] handshake failed (timeout)' ) ; window . removeEventListener ( 'message' , pingListener ) ; } , 10000 ) ; window . addEventListener ( 'message' , pingListener ) ; }
/*
This mechanism ensures that each content-script can be messaging with only one backend
and vice versa:
1. Wait for `ping`
2. As soon as pinged, stop listening to `ping` send `pong`,
start waiting for `hello`/`connection-fail`
3. If received `hello`, the connection is established,
if recieved `connection-fail`, then content-script is already busy, return to paragraph 1
/ * This mechanism ensures that each content - script can be messaging with only one backend and vice versa : 1 . Wait for ping 2 . As soon as pinged stop listening to ping send pong start waiting for hello / connection - fail 3 . If received hello the connection is established if recieved connection - fail then content - script is already busy return to paragraph 1