Skip to content

Commit 7158a38

Browse files
committed
fix[dynamic-scripts-injection]: unregister content scripts before registration
1 parent 559e83a commit 7158a38

File tree

1 file changed

+40
-31
lines changed

1 file changed

+40
-31
lines changed

packages/react-devtools-extensions/src/background.js

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,47 @@ import {IS_FIREFOX, EXTENSION_CONTAINED_VERSIONS} from './utils';
66

77
const ports = {};
88

9-
if (!IS_FIREFOX) {
10-
// equivalent logic for Firefox is in prepareInjection.js
11-
// Manifest V3 method of injecting content scripts (not yet supported in Firefox)
12-
// Note: the "world" option in registerContentScripts is only available in Chrome v102+
13-
// It's critical since it allows us to directly run scripts on the "main" world on the page
14-
// "document_start" allows it to run before the page's scripts
15-
// so the hook can be detected by react reconciler
16-
chrome.scripting.registerContentScripts(
17-
[
18-
{
19-
id: 'hook',
20-
matches: ['<all_urls>'],
21-
js: ['build/installHook.js'],
22-
runAt: 'document_start',
23-
world: chrome.scripting.ExecutionWorld.MAIN,
24-
},
25-
{
26-
id: 'renderer',
27-
matches: ['<all_urls>'],
28-
js: ['build/renderer.js'],
29-
runAt: 'document_start',
30-
world: chrome.scripting.ExecutionWorld.MAIN,
31-
},
32-
],
33-
function () {
34-
// When the content scripts are already registered, an error will be thrown.
35-
// It happens when the service worker process is incorrectly duplicated.
36-
if (chrome.runtime.lastError) {
37-
console.error(chrome.runtime.lastError);
38-
}
9+
async function dynamicallyInjectContentScripts() {
10+
const contentScriptsToInject = [
11+
{
12+
id: 'hook',
13+
matches: ['<all_urls>'],
14+
js: ['build/installHook.js'],
15+
runAt: 'document_start',
16+
world: chrome.scripting.ExecutionWorld.MAIN,
3917
},
40-
);
18+
{
19+
id: 'renderer',
20+
matches: ['<all_urls>'],
21+
js: ['build/renderer.js'],
22+
runAt: 'document_start',
23+
world: chrome.scripting.ExecutionWorld.MAIN,
24+
},
25+
];
26+
27+
try {
28+
// For some reason dynamically injected scripts might be already registered
29+
// Registering them again will fail, which will result into
30+
// __REACT_DEVTOOLS_GLOBAL_HOOK__ hook not being injected
31+
await chrome.scripting.unregisterContentScripts({
32+
ids: contentScriptsToInject.map(s => s.id),
33+
});
34+
35+
// equivalent logic for Firefox is in prepareInjection.js
36+
// Manifest V3 method of injecting content script
37+
// TODO(hoxyq): migrate Firefox to V3 manifests
38+
// Note: the "world" option in registerContentScripts is only available in Chrome v102+
39+
// It's critical since it allows us to directly run scripts on the "main" world on the page
40+
// "document_start" allows it to run before the page's scripts
41+
// so the hook can be detected by react reconciler
42+
await chrome.scripting.registerContentScripts(contentScriptsToInject);
43+
} catch (error) {
44+
console.error(error);
45+
}
46+
}
47+
48+
if (!IS_FIREFOX) {
49+
dynamicallyInjectContentScripts();
4150
}
4251

4352
chrome.runtime.onConnect.addListener(function (port) {

0 commit comments

Comments
 (0)