Inject early on when reloading-and-profiling

This commit is contained in:
Brian Vaughn
2019-04-01 07:48:04 -07:00
parent 37ed5a7175
commit 2c14f3e88e
10 changed files with 107 additions and 20 deletions

View File

@@ -27,7 +27,12 @@
"devtools_page": "main.html",
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"web_accessible_resources": ["main.html", "panel.html", "build/backend.js"],
"web_accessible_resources": [
"main.html",
"panel.html",
"build/backend.js",
"build/renderer.js"
],
"background": {
"scripts": ["build/background.js"],

View File

@@ -33,7 +33,12 @@
"devtools_page": "main.html",
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"web_accessible_resources": ["main.html", "panel.html", "build/backend.js"],
"web_accessible_resources": [
"main.html",
"panel.html",
"build/backend.js",
"build/renderer.js"
],
"background": {
"scripts": ["build/background.js"],

View File

@@ -2,13 +2,24 @@
import nullthrows from 'nullthrows';
import { installHook } from 'src/hook';
import { RELOAD_AND_PROFILE_KEY } from 'src/constants';
function injectCode(code) {
const script = document.createElement('script');
script.textContent = code;
// This script runs before the <head> element is created,
// so we add the script to <html> instead.
nullthrows(document.documentElement).appendChild(script);
nullthrows(script.parentNode).removeChild(script);
}
let lastDetectionResult;
// We want to detect when a renderer attaches, and notify the "background
// page" (which is shared between tabs and can highlight the React icon).
// Currently we are in "content script" context, so we can't listen
// to the hook directly (it will be injected directly into the page).
// We want to detect when a renderer attaches, and notify the "background page"
// (which is shared between tabs and can highlight the React icon).
// Currently we are in "content script" context, so we can't listen to the hook directly
// (it will be injected directly into the page).
// So instead, the hook will use postMessage() to pass message to us here.
// And when this happens, we'll send a message to the "background page".
window.addEventListener('message', function(evt) {
@@ -51,14 +62,27 @@ window.__REACT_DEVTOOLS_GLOBAL_HOOK__.nativeWeakMap = WeakMap;
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.nativeSet = Set;
`;
// If we have just reloaded to profile, we need to inject the renderer interface before the app loads.
if (localStorage.getItem(RELOAD_AND_PROFILE_KEY) === 'true') {
const rendererURL = chrome.runtime.getURL('build/renderer.js');
let rendererCode;
// We need to inject in time to catch the initial mount.
// This means we need to synchronously read the renderer code itself,
// and synchronously inject it into the page.
// There are very few ways to actually do this.
// This seems to be the best approach.
const request = new XMLHttpRequest();
request.addEventListener('load', function() {
rendererCode = this.responseText;
});
request.open('GET', rendererURL, false);
request.send();
injectCode(rendererCode);
}
// Inject a `__REACT_DEVTOOLS_GLOBAL_HOOK__` global so that React can detect that the
// devtools are installed (and skip its suggestion to install the devtools).
const js =
';(' + installHook.toString() + '(window))' + saveNativeValues + detectReact;
// This script runs before the <head> element is created, so we add the script
// to <html> instead.
const script = document.createElement('script');
script.textContent = js;
nullthrows(document.documentElement).appendChild(script);
nullthrows(script.parentNode).removeChild(script);
injectCode(
';(' + installHook.toString() + '(window))' + saveNativeValues + detectReact
);

View File

@@ -0,0 +1,21 @@
/**
* Install the hook on window, which is an event emitter.
* Note because Chrome content scripts cannot directly modify the window object,
* we are evaling this function by inserting a script tag.
* That's why we have to inline the whole event emitter implementation here.
*
* @flow
*/
import { attach } from 'src/backend/renderer';
Object.defineProperty(
window,
'__REACT_DEVTOOLS_ATTACH__',
({
enumerable: false,
get() {
return attach;
},
}: Object)
);

View File

@@ -18,6 +18,7 @@ module.exports = {
inject: './src/GlobalHook.js',
main: './src/main.js',
panel: './src/panel.js',
renderer: './src/renderer.js',
},
output: {
path: __dirname + '/build',