Skip to content

Commit faae234

Browse files
authored
refactor: migrate to manifest v3 (#2136)
1 parent e275579 commit faae234

File tree

7 files changed

+143
-134
lines changed

7 files changed

+143
-134
lines changed

packages/shell-chrome/manifest.json

+25-12
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
"version": "6.5.1",
44
"version_name": "6.5.1",
55
"description": "Browser DevTools extension for debugging Vue.js applications.",
6-
"manifest_version": 2,
6+
"manifest_version": 3,
77
"icons": {
88
"16": "icons/16.png",
99
"48": "icons/48.png",
1010
"128": "icons/128.png"
1111
},
12-
"browser_action": {
12+
"action": {
1313
"default_icon": {
1414
"16": "icons/16-gray.png",
1515
"48": "icons/48-gray.png",
@@ -19,20 +19,31 @@
1919
"default_popup": "popups/not-found.html"
2020
},
2121
"web_accessible_resources": [
22-
"devtools.html",
23-
"devtools-background.html",
24-
"build/backend.js"
22+
{
23+
"resources": [
24+
"devtools.html",
25+
"devtools-background.html",
26+
"build/backend.js",
27+
"build/proxy.js",
28+
"build/hook-exec.js",
29+
"build/detector-exec.js"
30+
],
31+
"matches": [
32+
"<all_urls>"
33+
],
34+
"extension_ids": []
35+
}
2536
],
2637
"devtools_page": "devtools-background.html",
2738
"background": {
28-
"scripts": [
29-
"build/background.js"
30-
],
31-
"persistent": true
39+
"service_worker": "build/service-worker.js"
3240
},
3341
"permissions": [
34-
"<all_urls>",
35-
"storage"
42+
"storage",
43+
"scripting"
44+
],
45+
"host_permissions": [
46+
"<all_urls>"
3647
],
3748
"content_scripts": [
3849
{
@@ -54,5 +65,7 @@
5465
"run_at": "document_idle"
5566
}
5667
],
57-
"content_security_policy": "script-src 'self'; object-src 'self'"
68+
"content_security_policy": {
69+
"extension_pages": "script-src 'self'; object-src 'self'"
70+
}
5871
}
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { installToast } from '@back/toast'
2+
3+
function sendMessage (message) {
4+
window.postMessage({
5+
key: '_vue-devtools-send-message',
6+
message,
7+
})
8+
}
9+
10+
function detect () {
11+
let delay = 1000
12+
let detectRemainingTries = 10
13+
14+
function runDetect () {
15+
// Method 1: Check Nuxt.js
16+
const nuxtDetected = !!(window.__NUXT__ || window.$nuxt)
17+
18+
if (nuxtDetected) {
19+
let Vue
20+
21+
if (window.$nuxt) {
22+
Vue = window.$nuxt.$root && window.$nuxt.$root.constructor
23+
}
24+
25+
sendMessage({
26+
devtoolsEnabled: (/* Vue 2 */ Vue && Vue.config.devtools) ||
27+
(/* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled),
28+
vueDetected: true,
29+
nuxtDetected: true,
30+
}, '*')
31+
32+
return
33+
}
34+
35+
// Method 2: Check Vue 3
36+
const vueDetected = !!(window.__VUE__)
37+
if (vueDetected) {
38+
sendMessage({
39+
devtoolsEnabled: /* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled,
40+
vueDetected: true,
41+
}, '*')
42+
43+
return
44+
}
45+
46+
// Method 3: Scan all elements inside document
47+
const all = document.querySelectorAll('*')
48+
let el
49+
for (let i = 0; i < all.length; i++) {
50+
if (all[i].__vue__) {
51+
el = all[i]
52+
break
53+
}
54+
}
55+
if (el) {
56+
let Vue = Object.getPrototypeOf(el.__vue__).constructor
57+
while (Vue.super) {
58+
Vue = Vue.super
59+
}
60+
sendMessage({
61+
devtoolsEnabled: Vue.config.devtools,
62+
vueDetected: true,
63+
}, '*')
64+
return
65+
}
66+
67+
if (detectRemainingTries > 0) {
68+
detectRemainingTries--
69+
setTimeout(() => {
70+
runDetect()
71+
}, delay)
72+
delay *= 5
73+
}
74+
}
75+
76+
setTimeout(() => {
77+
runDetect()
78+
}, 100)
79+
}
80+
81+
// inject the hook
82+
if (document instanceof HTMLDocument) {
83+
detect()
84+
installToast()
85+
}

packages/shell-chrome/src/detector.js

+9-96
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,12 @@
1-
import { installToast } from '@back/toast'
2-
import { isFirefox } from '@vue-devtools/shared-utils'
3-
4-
window.addEventListener('message', e => {
5-
if (e.source === window && e.data.vueDetected) {
6-
chrome.runtime.sendMessage(e.data)
7-
}
8-
})
9-
10-
function detect (win) {
11-
let delay = 1000
12-
let detectRemainingTries = 10
13-
14-
function runDetect () {
15-
// Method 1: Check Nuxt
16-
const nuxtDetected = !!(window.__NUXT__ || window.$nuxt)
17-
18-
if (nuxtDetected) {
19-
let Vue
20-
21-
if (window.$nuxt) {
22-
Vue = window.$nuxt.$root && window.$nuxt.$root.constructor
23-
}
24-
25-
win.postMessage({
26-
devtoolsEnabled: (/* Vue 2 */ Vue && Vue.config.devtools) ||
27-
(/* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled),
28-
vueDetected: true,
29-
nuxtDetected: true,
30-
}, '*')
31-
32-
return
33-
}
34-
35-
// Method 2: Check Vue 3
36-
const vueDetected = !!(window.__VUE__)
37-
if (vueDetected) {
38-
win.postMessage({
39-
devtoolsEnabled: /* Vue 3.2.14+ */ window.__VUE_DEVTOOLS_GLOBAL_HOOK__ && window.__VUE_DEVTOOLS_GLOBAL_HOOK__.enabled,
40-
vueDetected: true,
41-
}, '*')
42-
43-
return
44-
}
45-
46-
// Method 3: Scan all elements inside document
47-
const all = document.querySelectorAll('*')
48-
let el
49-
for (let i = 0; i < all.length; i++) {
50-
if (all[i].__vue__) {
51-
el = all[i]
52-
break
53-
}
54-
}
55-
if (el) {
56-
let Vue = Object.getPrototypeOf(el.__vue__).constructor
57-
while (Vue.super) {
58-
Vue = Vue.super
59-
}
60-
win.postMessage({
61-
devtoolsEnabled: Vue.config.devtools,
62-
vueDetected: true,
63-
}, '*')
64-
return
65-
}
66-
67-
if (detectRemainingTries > 0) {
68-
detectRemainingTries--
69-
setTimeout(() => {
70-
runDetect()
71-
}, delay)
72-
delay *= 5
73-
}
1+
window.addEventListener('message', function (event) {
2+
if (event.data.key === '_vue-devtools-send-message') {
3+
chrome.runtime.sendMessage(event.data.message)
744
}
5+
}, false)
756

76-
setTimeout(() => {
77-
runDetect()
78-
}, 100)
79-
}
80-
81-
// inject the hook
82-
if (document instanceof HTMLDocument) {
83-
installScript(detect)
84-
installScript(installToast)
85-
}
86-
87-
function installScript (fn) {
88-
const source = ';(' + fn.toString() + ')(window)'
89-
90-
if (isFirefox) {
91-
// eslint-disable-next-line no-eval
92-
window.eval(source) // in Firefox, this evaluates on the content window
93-
} else {
94-
const script = document.createElement('script')
95-
script.textContent = source
96-
document.documentElement.appendChild(script)
97-
script.parentNode.removeChild(script)
98-
}
7+
const script = document.createElement('script')
8+
script.src = chrome.runtime.getURL('build/detector-exec.js')
9+
script.onload = () => {
10+
script.remove()
9911
}
12+
;(document.head || document.documentElement).appendChild(script)
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { installHook } from '@back/hook'
2+
3+
installHook(window)

packages/shell-chrome/src/hook.js

+5-17
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
1-
// This script is injected into every page.
2-
import { installHook } from '@back/hook'
3-
import { isFirefox } from '@vue-devtools/shared-utils'
4-
5-
// inject the hook
6-
if (document instanceof HTMLDocument) {
7-
const source = ';(' + installHook.toString() + ')(window)'
8-
9-
if (isFirefox) {
10-
// eslint-disable-next-line no-eval
11-
window.eval(source) // in Firefox, this evaluates on the content window
12-
} else {
13-
const script = document.createElement('script')
14-
script.textContent = source
15-
document.documentElement.appendChild(script)
16-
script.parentNode.removeChild(script)
17-
}
1+
const script = document.createElement('script')
2+
script.src = chrome.runtime.getURL('build/hook-exec.js')
3+
script.onload = () => {
4+
script.remove()
185
}
6+
;(document.head || document.documentElement).appendChild(script)

packages/shell-chrome/src/background.js renamed to packages/shell-chrome/src/service-worker.js

+13-8
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ function isNumeric (str) {
3333
}
3434

3535
function installProxy (tabId) {
36-
chrome.tabs.executeScript(tabId, {
37-
file: '/build/proxy.js',
36+
chrome.scripting.executeScript({
37+
target: { tabId },
38+
files: ['build/proxy.js'],
3839
}, function (res) {
3940
if (!res) {
4041
ports[tabId].devtools.postMessage('proxy-fail')
@@ -95,17 +96,21 @@ chrome.runtime.onMessage.addListener((req, sender) => {
9596
if (sender.tab && req.vueDetected) {
9697
const suffix = req.nuxtDetected ? '.nuxt' : ''
9798

98-
chrome.browserAction.setIcon({
99+
chrome.action.setIcon({
99100
tabId: sender.tab.id,
100101
path: {
101-
16: `icons/16${suffix}.png`,
102-
48: `icons/48${suffix}.png`,
103-
128: `icons/128${suffix}.png`,
102+
16: chrome.runtime.getURL(`icons/16${suffix}.png`),
103+
48: chrome.runtime.getURL(`icons/48${suffix}.png`),
104+
128: chrome.runtime.getURL(`icons/128${suffix}.png`),
104105
},
106+
}, () => {
107+
// noop
105108
})
106-
chrome.browserAction.setPopup({
109+
chrome.action.setPopup({
107110
tabId: sender.tab.id,
108-
popup: req.devtoolsEnabled ? `popups/enabled${suffix}.html` : `popups/disabled${suffix}.html`,
111+
popup: chrome.runtime.getURL(req.devtoolsEnabled ? `popups/enabled${suffix}.html` : `popups/disabled${suffix}.html`),
112+
}, () => {
113+
// noop
109114
})
110115
}
111116

packages/shell-chrome/webpack.config.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ const { createConfig } = require('@vue-devtools/build-tools')
44
module.exports = createConfig({
55
entry: {
66
hook: './src/hook.js',
7+
'hook-exec': './src/hook-exec.js',
78
devtools: './src/devtools.js',
8-
background: './src/background.js',
9+
'service-worker': './src/service-worker.js',
910
'devtools-background': './src/devtools-background.js',
1011
backend: './src/backend.js',
1112
proxy: './src/proxy.js',
1213
detector: './src/detector.js',
14+
'detector-exec': './src/detector-exec.js',
1315
},
1416
output: {
1517
path: path.join(__dirname, 'build'),

0 commit comments

Comments
 (0)