Files
react/packages/react-devtools-extensions/src/background/messageHandlers.js
T
Ruslan Lesiutin 09285d5a7f refactor[devtools/extension]: refactored messaging logic across different parts of the extension (#27417)
1.
https://github.com/bvaughn/react/commit/9fc04eaf3fb701cdc14f57d5aed48f3126af6c94#diff-2c5e1f5e80e74154e65b2813cf1c3638f85034530e99dae24809ab4ad70d0143
introduced a vulnerability: we listen to `'fetch-file-with-cache'` event
from `window` to fetch sources of the file, in which we want to parse
hook names. We send this event via `window`, which means any page can
also use this and manipulate the extension to perform some `fetch()`
calls. With these changes, instead of transporting message via `window`,
we have a distinct content script, which is responsible for fetching
sources. It is notified via `chrome.runtime.sendMessage` api, so it
can't be manipulated.
2. Consistent structure of messages `{source: string, payload: object}`
in different parts of the extension
3. Added some wrappers around `chrome.scripting.executeScript` API in
`packages/react-devtools-extensions/src/background/executeScript.js`,
which support custom flow for Firefox, to simulate support of
`ExecutionWorld.MAIN`.
2023-09-25 12:02:13 -04:00

104 lines
2.6 KiB
JavaScript

/* global chrome */
import setExtensionIconAndPopup from './setExtensionIconAndPopup';
import {executeScriptInMainWorld} from './executeScript';
import {EXTENSION_CONTAINED_VERSIONS} from '../utils';
export function handleReactDevToolsHookMessage(message, sender) {
const {payload} = message;
switch (payload?.type) {
case 'react-renderer-attached': {
setExtensionIconAndPopup(payload.reactBuildType, sender.tab.id);
break;
}
}
}
export function handleBackendManagerMessage(message, sender) {
const {payload} = message;
switch (payload?.type) {
case 'require-backends': {
payload.versions.forEach(version => {
if (EXTENSION_CONTAINED_VERSIONS.includes(version)) {
executeScriptInMainWorld({
target: {tabId: sender.tab.id},
files: [`/build/react_devtools_backend_${version}.js`],
});
}
});
break;
}
}
}
export function handleDevToolsPageMessage(message) {
const {payload} = message;
switch (payload?.type) {
// Proxy this message from DevTools page to content script via chrome.tabs.sendMessage
case 'fetch-file-with-cache': {
const {
payload: {tabId, url},
} = message;
if (!tabId) {
throw new Error("Couldn't fetch file sources: tabId not specified");
}
if (!url) {
throw new Error("Couldn't fetch file sources: url not specified");
}
chrome.tabs.sendMessage(tabId, {
source: 'devtools-page',
payload: {
type: 'fetch-file-with-cache',
url,
},
});
break;
}
case 'inject-backend-manager': {
const {
payload: {tabId},
} = message;
if (!tabId) {
throw new Error("Couldn't inject backend manager: tabId not specified");
}
executeScriptInMainWorld({
target: {tabId},
files: ['/build/backendManager.js'],
});
break;
}
}
}
export function handleFetchResourceContentScriptMessage(message) {
const {payload} = message;
switch (payload?.type) {
case 'fetch-file-with-cache-complete':
case 'fetch-file-with-cache-error':
// Forward the result of fetch-in-page requests back to the DevTools page.
// We switch the source here because of inconsistency between Firefox and Chrome
// In Chromium this message will be propagated from content script to DevTools page
// For Firefox, only background script will get this message, so we need to forward it to DevTools page
chrome.runtime.sendMessage({
source: 'react-devtools-background',
payload,
});
break;
}
}