extension-develop 2.0.4 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/add-content-script-wrapper.js +24 -12
- package/dist/add-hmr-accept-code.js +1 -0
- package/dist/develop-lib/config-types.d.ts +1 -0
- package/dist/develop-lib/get-project-path.d.ts +1 -1
- package/dist/develop-lib/messages.d.ts +1 -0
- package/dist/extensions/chrome-manager-extension/background.js +40 -14
- package/dist/extensions/chrome-manager-extension/reload-service.js +24 -2
- package/dist/extensions/chromium-based-manager-extension/background.js +40 -14
- package/dist/extensions/chromium-based-manager-extension/reload-service.js +24 -2
- package/dist/extensions/edge-manager-extension/background.js +38 -14
- package/dist/extensions/edge-manager-extension/reload-service.js +24 -2
- package/dist/extensions/firefox-manager-extension/reload-service.js +12 -2
- package/dist/extensions/gecko-based-manager-extension/background.js +10 -0
- package/dist/extensions/gecko-based-manager-extension/reload-service.js +15 -2
- package/dist/module.js +807 -665
- package/dist/webpack/plugin-browsers/browsers-lib/instance-manager.d.ts +2 -0
- package/dist/webpack/plugin-browsers/browsers-lib/messages.d.ts +3 -0
- package/package.json +3 -2
|
@@ -125,13 +125,17 @@ class ReactContentScriptWrapper {
|
|
|
125
125
|
// Create shadow root for style isolation
|
|
126
126
|
this.shadowRoot = this.rootElement.attachShadow({ mode: 'open' })
|
|
127
127
|
|
|
128
|
+
// Create a host element inside the shadow root for rendering
|
|
129
|
+
const host = document.createElement('div')
|
|
130
|
+
this.shadowRoot.appendChild(host)
|
|
131
|
+
|
|
128
132
|
// Inject styles FIRST
|
|
129
133
|
console.log('[Extension.js] About to inject styles')
|
|
130
134
|
await this.injectStyles()
|
|
131
135
|
|
|
132
136
|
// Render React content
|
|
133
137
|
console.log('[Extension.js] About to render React content')
|
|
134
|
-
const result = this.renderFunction(
|
|
138
|
+
const result = this.renderFunction(host)
|
|
135
139
|
if (typeof result === 'function') {
|
|
136
140
|
this.unmountFunction = result
|
|
137
141
|
}
|
|
@@ -198,8 +202,8 @@ class ReactContentScriptWrapper {
|
|
|
198
202
|
// Check if we have hardcoded content for this stylesheet
|
|
199
203
|
if (cssContentMap[stylesheet]) {
|
|
200
204
|
const cssContent = cssContentMap[stylesheet]
|
|
201
|
-
allCSS += cssContent + '
|
|
202
|
-
console.log(
|
|
205
|
+
allCSS += cssContent + '\n'
|
|
206
|
+
console.log('[Extension.js] Successfully injected React', stylesheet, 'content')
|
|
203
207
|
continue
|
|
204
208
|
}
|
|
205
209
|
|
|
@@ -208,7 +212,7 @@ class ReactContentScriptWrapper {
|
|
|
208
212
|
const response = await fetch(cssUrl)
|
|
209
213
|
const text = await response.text()
|
|
210
214
|
if (response.ok) {
|
|
211
|
-
allCSS += text + '
|
|
215
|
+
allCSS += text + '\n'
|
|
212
216
|
console.log('[Extension.js] Successfully fetched stylesheet:', stylesheet)
|
|
213
217
|
} else {
|
|
214
218
|
console.warn('[Extension.js] Failed to fetch CSS:', stylesheet)
|
|
@@ -405,13 +409,17 @@ class VueContentScriptWrapper {
|
|
|
405
409
|
// Create shadow root for style isolation
|
|
406
410
|
this.shadowRoot = this.rootElement.attachShadow({ mode: 'open' })
|
|
407
411
|
|
|
412
|
+
// Create a host element inside the shadow root for rendering
|
|
413
|
+
const host = document.createElement('div')
|
|
414
|
+
this.shadowRoot.appendChild(host)
|
|
415
|
+
|
|
408
416
|
// Inject styles FIRST
|
|
409
417
|
console.log('[Extension.js] About to inject styles')
|
|
410
418
|
await this.injectStyles()
|
|
411
419
|
|
|
412
420
|
// Render Vue content
|
|
413
421
|
console.log('[Extension.js] About to render Vue content')
|
|
414
|
-
const result = this.renderFunction(
|
|
422
|
+
const result = this.renderFunction(host)
|
|
415
423
|
if (typeof result === 'function') {
|
|
416
424
|
this.unmountFunction = result
|
|
417
425
|
}
|
|
@@ -478,8 +486,8 @@ class VueContentScriptWrapper {
|
|
|
478
486
|
// Check if we have hardcoded content for this stylesheet
|
|
479
487
|
if (cssContentMap[stylesheet]) {
|
|
480
488
|
const cssContent = cssContentMap[stylesheet]
|
|
481
|
-
allCSS += cssContent + '
|
|
482
|
-
console.log(
|
|
489
|
+
allCSS += cssContent + '\n'
|
|
490
|
+
console.log('[Extension.js] Successfully injected Vue', stylesheet, 'content')
|
|
483
491
|
continue
|
|
484
492
|
}
|
|
485
493
|
|
|
@@ -488,7 +496,7 @@ class VueContentScriptWrapper {
|
|
|
488
496
|
const response = await fetch(cssUrl)
|
|
489
497
|
const text = await response.text()
|
|
490
498
|
if (response.ok) {
|
|
491
|
-
allCSS += text + '
|
|
499
|
+
allCSS += text + '\n'
|
|
492
500
|
console.log('[Extension.js] Successfully fetched stylesheet:', stylesheet)
|
|
493
501
|
} else {
|
|
494
502
|
console.warn('[Extension.js] Failed to fetch CSS:', stylesheet)
|
|
@@ -683,13 +691,17 @@ class SvelteContentScriptWrapper {
|
|
|
683
691
|
// Create shadow root for style isolation
|
|
684
692
|
this.shadowRoot = this.rootElement.attachShadow({ mode: 'open' })
|
|
685
693
|
|
|
694
|
+
// Create a host element inside the shadow root for rendering
|
|
695
|
+
const host = document.createElement('div')
|
|
696
|
+
this.shadowRoot.appendChild(host)
|
|
697
|
+
|
|
686
698
|
// Inject styles FIRST
|
|
687
699
|
console.log('[Extension.js] About to inject styles')
|
|
688
700
|
await this.injectStyles()
|
|
689
701
|
|
|
690
702
|
// Render Svelte content
|
|
691
703
|
console.log('[Extension.js] About to render Svelte content')
|
|
692
|
-
const result = this.renderFunction(
|
|
704
|
+
const result = this.renderFunction(host)
|
|
693
705
|
if (typeof result === 'function') {
|
|
694
706
|
this.unmountFunction = result
|
|
695
707
|
}
|
|
@@ -756,8 +768,8 @@ class SvelteContentScriptWrapper {
|
|
|
756
768
|
// Check if we have hardcoded content for this stylesheet
|
|
757
769
|
if (cssContentMap[stylesheet]) {
|
|
758
770
|
const cssContent = cssContentMap[stylesheet]
|
|
759
|
-
allCSS += cssContent + '
|
|
760
|
-
console.log(
|
|
771
|
+
allCSS += cssContent + '\n'
|
|
772
|
+
console.log('[Extension.js] Successfully injected Svelte', stylesheet, 'content')
|
|
761
773
|
continue
|
|
762
774
|
}
|
|
763
775
|
|
|
@@ -766,7 +778,7 @@ class SvelteContentScriptWrapper {
|
|
|
766
778
|
const response = await fetch(cssUrl)
|
|
767
779
|
const text = await response.text()
|
|
768
780
|
if (response.ok) {
|
|
769
|
-
allCSS += text + '
|
|
781
|
+
allCSS += text + '\n'
|
|
770
782
|
console.log('[Extension.js] Successfully fetched stylesheet:', stylesheet)
|
|
771
783
|
} else {
|
|
772
784
|
console.warn('[Extension.js] Failed to fetch CSS:', stylesheet)
|
|
@@ -64,6 +64,7 @@ function add_hmr_accept_code(source) {
|
|
|
64
64
|
name: "scripts:add-hmr-accept-code",
|
|
65
65
|
baseDataPath: 'options'
|
|
66
66
|
});
|
|
67
|
+
if (source.includes('import.meta.webpackHot')) return source;
|
|
67
68
|
const url = (0, external_loader_utils_namespaceObject.urlToRequest)(this.resourcePath);
|
|
68
69
|
const reloadCode = `
|
|
69
70
|
// TODO: cezaraugusto re-visit this
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export interface ProjectStructure {
|
|
2
2
|
manifestPath: string;
|
|
3
|
-
packageJsonPath
|
|
3
|
+
packageJsonPath?: string;
|
|
4
4
|
}
|
|
5
5
|
export declare function getProjectPath(pathOrRemoteUrl: string | undefined): Promise<string>;
|
|
6
6
|
export declare function getProjectStructure(pathOrRemoteUrl: string | undefined): Promise<ProjectStructure>;
|
|
@@ -25,6 +25,7 @@ export declare function downloadingText(url: string): string;
|
|
|
25
25
|
export declare function unpackagingExtension(zipFilePath: string): string;
|
|
26
26
|
export declare function unpackagedSuccessfully(): string;
|
|
27
27
|
export declare function failedToDownloadOrExtractZIPFileError(error: any): string;
|
|
28
|
+
export declare function invalidRemoteZip(url: string, contentType: string): string;
|
|
28
29
|
export declare function isUsingExperimentalConfig(integration: any): string;
|
|
29
30
|
export declare function installingDependencies(): string;
|
|
30
31
|
export declare function installingDependenciesFailed(gitCommand: string, gitArgs: string[], code: number | null): string;
|
|
@@ -4,9 +4,14 @@ import {connect, disconnect, keepAlive} from './reload-service.js'
|
|
|
4
4
|
function bgGreen(str) {
|
|
5
5
|
return `background: transparent; color: #0971fe; ${str}`
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
|
|
8
|
+
async function initManagerUI() {
|
|
9
|
+
try {
|
|
10
|
+
chrome.tabs.query({active: true, currentWindow: true}, async (tabs) => {
|
|
11
|
+
const initialTab = Array.isArray(tabs) ? tabs[0] : undefined
|
|
12
|
+
|
|
13
|
+
console.log(
|
|
14
|
+
`%c
|
|
10
15
|
██████████████████████████████████████████████████████████
|
|
11
16
|
██████████████████████████████████████████████████████████
|
|
12
17
|
████████████████████████████ ██████████████████████████
|
|
@@ -32,22 +37,43 @@ chrome.tabs.query({active: true}, async ([initialTab]) => {
|
|
|
32
37
|
██████████████████████████████████████████████████████████
|
|
33
38
|
MIT (c) ${new Date().getFullYear()} - Cezar Augusto and the Extension.js Authors.
|
|
34
39
|
`,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
bgGreen('')
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!initialTab) {
|
|
44
|
+
try {
|
|
45
|
+
await handleFirstRun()
|
|
46
|
+
} catch {
|
|
47
|
+
try {
|
|
48
|
+
chrome.tabs.create({url: 'chrome://extensions/'})
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
initialTab.url === 'chrome://newtab/' ||
|
|
56
|
+
initialTab.url === 'chrome://welcome/'
|
|
57
|
+
) {
|
|
58
|
+
await handleFirstRun()
|
|
59
|
+
} else {
|
|
60
|
+
createExtensionsPageTab(initialTab, 'chrome://extensions/')
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
} catch {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Guard tab access and run after startup
|
|
67
|
+
chrome.runtime.onStartup.addListener(async () => {
|
|
68
|
+
await initManagerUI()
|
|
46
69
|
})
|
|
47
70
|
|
|
48
71
|
chrome.runtime.onInstalled.addListener(async () => {
|
|
49
72
|
let isConnected = false
|
|
50
73
|
|
|
74
|
+
// Ensure UI setup also runs on install (first run)
|
|
75
|
+
await initManagerUI()
|
|
76
|
+
|
|
51
77
|
if (isConnected) {
|
|
52
78
|
disconnect()
|
|
53
79
|
} else {
|
|
@@ -20,7 +20,12 @@ export async function connect() {
|
|
|
20
20
|
const maxBackoffMs = 5000
|
|
21
21
|
|
|
22
22
|
const establish = () => {
|
|
23
|
-
|
|
23
|
+
try {
|
|
24
|
+
webSocket = new WebSocket(`ws://127.0.0.1:${port}`)
|
|
25
|
+
} catch (err) {
|
|
26
|
+
webSocket = null
|
|
27
|
+
return
|
|
28
|
+
}
|
|
24
29
|
|
|
25
30
|
webSocket.onerror = (_event) => {
|
|
26
31
|
try {
|
|
@@ -37,7 +42,12 @@ export async function connect() {
|
|
|
37
42
|
|
|
38
43
|
let reloadDebounce
|
|
39
44
|
webSocket.onmessage = async (event) => {
|
|
40
|
-
|
|
45
|
+
let message = null
|
|
46
|
+
try {
|
|
47
|
+
message = JSON.parse(event.data)
|
|
48
|
+
} catch {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
41
51
|
|
|
42
52
|
// Only process messages for this instance
|
|
43
53
|
if (message.instanceId && message.instanceId !== instanceId) {
|
|
@@ -77,6 +87,18 @@ export function disconnect() {
|
|
|
77
87
|
}
|
|
78
88
|
}
|
|
79
89
|
|
|
90
|
+
// Ensure sockets are closed when the worker is suspended
|
|
91
|
+
try {
|
|
92
|
+
chrome.runtime.onSuspend.addListener(() => {
|
|
93
|
+
if (webSocket) {
|
|
94
|
+
try {
|
|
95
|
+
webSocket.close()
|
|
96
|
+
} catch {}
|
|
97
|
+
webSocket = null
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
} catch {}
|
|
101
|
+
|
|
80
102
|
async function requestInitialLoadData() {
|
|
81
103
|
const devExtensions = await getDevExtensions()
|
|
82
104
|
|
|
@@ -4,9 +4,14 @@ import {connect, disconnect, keepAlive} from './reload-service.js'
|
|
|
4
4
|
function bgGreen(str) {
|
|
5
5
|
return `background: transparent; color: #0971fe; ${str}`
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
|
|
8
|
+
async function initManagerUI() {
|
|
9
|
+
try {
|
|
10
|
+
chrome.tabs.query({active: true, currentWindow: true}, async (tabs) => {
|
|
11
|
+
const initialTab = Array.isArray(tabs) ? tabs[0] : undefined
|
|
12
|
+
|
|
13
|
+
console.log(
|
|
14
|
+
`%c
|
|
10
15
|
██████████████████████████████████████████████████████████
|
|
11
16
|
██████████████████████████████████████████████████████████
|
|
12
17
|
████████████████████████████ ██████████████████████████
|
|
@@ -32,22 +37,43 @@ chrome.tabs.query({active: true}, async ([initialTab]) => {
|
|
|
32
37
|
██████████████████████████████████████████████████████████
|
|
33
38
|
MIT (c) ${new Date().getFullYear()} - Cezar Augusto and the Extension.js Authors.
|
|
34
39
|
`,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
bgGreen('')
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!initialTab) {
|
|
44
|
+
try {
|
|
45
|
+
await handleFirstRun()
|
|
46
|
+
} catch {
|
|
47
|
+
try {
|
|
48
|
+
chrome.tabs.create({url: 'chrome://extensions/'})
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
initialTab.url === 'chrome://newtab/' ||
|
|
56
|
+
initialTab.url === 'chrome://welcome/'
|
|
57
|
+
) {
|
|
58
|
+
await handleFirstRun()
|
|
59
|
+
} else {
|
|
60
|
+
createExtensionsPageTab(initialTab, 'chrome://extensions/')
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
} catch {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Guard tab access and run after startup
|
|
67
|
+
chrome.runtime.onStartup.addListener(async () => {
|
|
68
|
+
await initManagerUI()
|
|
46
69
|
})
|
|
47
70
|
|
|
48
71
|
chrome.runtime.onInstalled.addListener(async () => {
|
|
49
72
|
let isConnected = false
|
|
50
73
|
|
|
74
|
+
// Ensure UI setup also runs on install (first run)
|
|
75
|
+
await initManagerUI()
|
|
76
|
+
|
|
51
77
|
if (isConnected) {
|
|
52
78
|
disconnect()
|
|
53
79
|
} else {
|
|
@@ -17,7 +17,12 @@ export async function connect() {
|
|
|
17
17
|
const maxBackoffMs = 5000
|
|
18
18
|
|
|
19
19
|
const establish = () => {
|
|
20
|
-
|
|
20
|
+
try {
|
|
21
|
+
webSocket = new WebSocket(`ws://127.0.0.1:${port}`)
|
|
22
|
+
} catch (err) {
|
|
23
|
+
webSocket = null
|
|
24
|
+
return
|
|
25
|
+
}
|
|
21
26
|
|
|
22
27
|
webSocket.onerror = (_event) => {
|
|
23
28
|
try {
|
|
@@ -34,7 +39,12 @@ export async function connect() {
|
|
|
34
39
|
|
|
35
40
|
let reloadDebounce
|
|
36
41
|
webSocket.onmessage = async (event) => {
|
|
37
|
-
|
|
42
|
+
let message = null
|
|
43
|
+
try {
|
|
44
|
+
message = JSON.parse(event.data)
|
|
45
|
+
} catch {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
38
48
|
|
|
39
49
|
if (message.status === 'serverReady') {
|
|
40
50
|
await requestInitialLoadData()
|
|
@@ -69,6 +79,18 @@ export function disconnect() {
|
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
|
|
82
|
+
// Ensure sockets are closed when the worker is suspended
|
|
83
|
+
try {
|
|
84
|
+
chrome.runtime.onSuspend.addListener(() => {
|
|
85
|
+
if (webSocket) {
|
|
86
|
+
try {
|
|
87
|
+
webSocket.close()
|
|
88
|
+
} catch {}
|
|
89
|
+
webSocket = null
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
} catch {}
|
|
93
|
+
|
|
72
94
|
async function getDevExtensions() {
|
|
73
95
|
const allExtensions = await new Promise((resolve) => {
|
|
74
96
|
chrome.management.getAll(resolve)
|
|
@@ -4,9 +4,14 @@ import {connect, disconnect, keepAlive} from './reload-service.js'
|
|
|
4
4
|
function bgGreen(str) {
|
|
5
5
|
return `background: transparent; color: #0971fe; ${str}`
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
|
|
8
|
+
async function initManagerUI() {
|
|
9
|
+
try {
|
|
10
|
+
chrome.tabs.query({active: true, currentWindow: true}, async (tabs) => {
|
|
11
|
+
const initialTab = Array.isArray(tabs) ? tabs[0] : undefined
|
|
12
|
+
|
|
13
|
+
console.log(
|
|
14
|
+
`%c
|
|
10
15
|
██████████████████████████████████████████████████████████
|
|
11
16
|
██████████████████████████████████████████████████████████
|
|
12
17
|
████████████████████████████ ██████████████████████████
|
|
@@ -32,22 +37,41 @@ chrome.tabs.query({active: true}, async ([initialTab]) => {
|
|
|
32
37
|
██████████████████████████████████████████████████████████
|
|
33
38
|
MIT (c) ${new Date().getFullYear()} - Cezar Augusto and the Extension.js Authors.
|
|
34
39
|
`,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
bgGreen('')
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!initialTab) {
|
|
44
|
+
try {
|
|
45
|
+
await handleFirstRun()
|
|
46
|
+
} catch {
|
|
47
|
+
try {
|
|
48
|
+
chrome.tabs.create({url: 'chrome://extensions/'})
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
initialTab.url === 'chrome://newtab/' ||
|
|
56
|
+
initialTab.url === 'chrome://welcome/'
|
|
57
|
+
) {
|
|
58
|
+
await handleFirstRun()
|
|
59
|
+
} else {
|
|
60
|
+
createExtensionsPageTab(initialTab, 'chrome://extensions/')
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
} catch {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
chrome.runtime.onStartup.addListener(async () => {
|
|
67
|
+
await initManagerUI()
|
|
46
68
|
})
|
|
47
69
|
|
|
48
70
|
chrome.runtime.onInstalled.addListener(async () => {
|
|
49
71
|
let isConnected = false
|
|
50
72
|
|
|
73
|
+
await initManagerUI()
|
|
74
|
+
|
|
51
75
|
if (isConnected) {
|
|
52
76
|
disconnect()
|
|
53
77
|
} else {
|
|
@@ -20,7 +20,12 @@ export async function connect() {
|
|
|
20
20
|
const maxBackoffMs = 5000
|
|
21
21
|
|
|
22
22
|
const establish = () => {
|
|
23
|
-
|
|
23
|
+
try {
|
|
24
|
+
webSocket = new WebSocket(`ws://127.0.0.1:${port}`)
|
|
25
|
+
} catch (err) {
|
|
26
|
+
webSocket = null
|
|
27
|
+
return
|
|
28
|
+
}
|
|
24
29
|
|
|
25
30
|
webSocket.onerror = (_event) => {
|
|
26
31
|
try {
|
|
@@ -37,7 +42,12 @@ export async function connect() {
|
|
|
37
42
|
|
|
38
43
|
let reloadDebounce
|
|
39
44
|
webSocket.onmessage = async (event) => {
|
|
40
|
-
|
|
45
|
+
let message = null
|
|
46
|
+
try {
|
|
47
|
+
message = JSON.parse(event.data)
|
|
48
|
+
} catch {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
41
51
|
|
|
42
52
|
// Only process messages for this instance
|
|
43
53
|
if (message.instanceId && message.instanceId !== instanceId) {
|
|
@@ -77,6 +87,18 @@ export function disconnect() {
|
|
|
77
87
|
}
|
|
78
88
|
}
|
|
79
89
|
|
|
90
|
+
// Ensure sockets are closed when the worker is suspended
|
|
91
|
+
try {
|
|
92
|
+
chrome.runtime.onSuspend.addListener(() => {
|
|
93
|
+
if (webSocket) {
|
|
94
|
+
try {
|
|
95
|
+
webSocket.close()
|
|
96
|
+
} catch {}
|
|
97
|
+
webSocket = null
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
} catch {}
|
|
101
|
+
|
|
80
102
|
async function requestInitialLoadData() {
|
|
81
103
|
const devExtensions = await getDevExtensions()
|
|
82
104
|
|
|
@@ -17,7 +17,12 @@ async function connect() {
|
|
|
17
17
|
const maxBackoffMs = 5000
|
|
18
18
|
|
|
19
19
|
const connectTo = (url) => {
|
|
20
|
-
|
|
20
|
+
try {
|
|
21
|
+
webSocket = new WebSocket(url)
|
|
22
|
+
} catch (err) {
|
|
23
|
+
webSocket = null
|
|
24
|
+
return
|
|
25
|
+
}
|
|
21
26
|
|
|
22
27
|
webSocket.onerror = (_event) => {
|
|
23
28
|
try {
|
|
@@ -38,7 +43,12 @@ async function connect() {
|
|
|
38
43
|
|
|
39
44
|
let reloadDebounce
|
|
40
45
|
webSocket.onmessage = async (event) => {
|
|
41
|
-
|
|
46
|
+
let message = null
|
|
47
|
+
try {
|
|
48
|
+
message = JSON.parse(event.data)
|
|
49
|
+
} catch {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
42
52
|
|
|
43
53
|
// Only process messages for this instance
|
|
44
54
|
if (message.instanceId && message.instanceId !== instanceId) {
|
|
@@ -55,3 +55,13 @@ browser.runtime.onInstalled.addListener(async () => {
|
|
|
55
55
|
isConnected = true
|
|
56
56
|
}
|
|
57
57
|
})
|
|
58
|
+
|
|
59
|
+
// Also initialize on browser startup for parity with Chromium behavior
|
|
60
|
+
browser.runtime.onStartup.addListener(async () => {
|
|
61
|
+
try {
|
|
62
|
+
await handleTabOnExtensionLoad()
|
|
63
|
+
} catch {}
|
|
64
|
+
try {
|
|
65
|
+
await connect()
|
|
66
|
+
} catch {}
|
|
67
|
+
})
|
|
@@ -15,7 +15,12 @@ export async function connect() {
|
|
|
15
15
|
const maxBackoffMs = 5000
|
|
16
16
|
|
|
17
17
|
const connectTo = (url) => {
|
|
18
|
-
|
|
18
|
+
try {
|
|
19
|
+
webSocket = new WebSocket(url)
|
|
20
|
+
} catch (err) {
|
|
21
|
+
webSocket = null
|
|
22
|
+
return
|
|
23
|
+
}
|
|
19
24
|
|
|
20
25
|
webSocket.onerror = (_event) => {
|
|
21
26
|
try {
|
|
@@ -36,12 +41,20 @@ export async function connect() {
|
|
|
36
41
|
|
|
37
42
|
let reloadDebounce
|
|
38
43
|
webSocket.onmessage = async (event) => {
|
|
39
|
-
|
|
44
|
+
let message = null
|
|
45
|
+
try {
|
|
46
|
+
message = JSON.parse(event.data)
|
|
47
|
+
} catch {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
40
50
|
|
|
41
51
|
if (message.status === 'serverReady') {
|
|
42
52
|
console.info(
|
|
43
53
|
`[Extension.js] Server ready. Requesting initial load data...`
|
|
44
54
|
)
|
|
55
|
+
try {
|
|
56
|
+
await requestInitialLoadData()
|
|
57
|
+
} catch {}
|
|
45
58
|
}
|
|
46
59
|
|
|
47
60
|
if (message.changedFile) {
|