File size: 2,792 Bytes
4d70170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// this script is called when the VueDevtools panel is activated.

import { initDevTools, setAppConnected } from '@front'
import { Bridge, BridgeEvents } from '@vue-devtools/shared-utils'

let disconnected = false
let connectCount = 0
let retryConnectTimer

initDevTools({

  /**
   * Inject backend, connect to background, and send back the bridge.
   *
   * @param {Function} cb
   */

  connect(cb) {
    // 1. inject backend code into page
    injectScript(chrome.runtime.getURL('build/backend.js'), () => {
      // 2. connect to background to setup proxy
      let port

      const onMessageHandlers = []

      function connect() {
        try {
          clearTimeout(retryConnectTimer)
          connectCount++
          port = chrome.runtime.connect({
            name: `${chrome.devtools.inspectedWindow.tabId}`,
          })
          disconnected = false
          port.onDisconnect.addListener(() => {
            disconnected = true
            setAppConnected(false)

            // Retry
            retryConnectTimer = setTimeout(connect, 500)
          })

          if (connectCount > 1) {
            onMessageHandlers.forEach(fn => port.onMessage.addListener(fn))
          }
        }
        catch (e) {
          console.error(e)
          disconnected = true
          setAppConnected(false)

          // Retry
          retryConnectTimer = setTimeout(connect, 1000)
        }
      }
      connect()

      const bridge = new Bridge({
        listen(fn) {
          port.onMessage.addListener(fn)
          onMessageHandlers.push(fn)
        },
        send(data) {
          if (!disconnected) {
            // if (process.env.NODE_ENV !== 'production') {
            //   console.log('[chrome] devtools -> backend', data)
            // }
            port.postMessage(data)
          }
        },
      })

      bridge.on(BridgeEvents.TO_FRONT_RECONNECTED, () => {
        setAppConnected(true)
      })

      // 3. send a proxy API to the panel
      cb(bridge)
    })
  },

  /**
   * Register a function to reload the devtools app.
   *
   * @param {Function} reloadFn
   */

  onReload(reloadFn) {
    chrome.devtools.network.onNavigated.addListener(reloadFn)
  },
})

/**
 * Inject a globally evaluated script, in the same context with the actual
 * user app.
 *
 * @param {string} scriptName
 * @param {Function} cb
 */

function injectScript(scriptName, cb) {
  const src = `
    (function() {
      var script = document.constructor.prototype.createElement.call(document, 'script');
      script.src = "${scriptName}";
      document.documentElement.appendChild(script);
      script.parentNode.removeChild(script);
    })()
  `
  chrome.devtools.inspectedWindow.eval(src, (res, err) => {
    if (err) {
      console.error(err)
    }
    cb()
  })
}