Skip to content

Commit

Permalink
Only inject hook.js script for Firefox. Use ExecutionWorld.MAIN for…
Browse files Browse the repository at this point in the history
… Chrome (#1232)
  • Loading branch information
jerelmiller authored Feb 26, 2024
1 parent 66cdf0b commit 8ce6fef
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/sour-colts-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"apollo-client-devtools": minor
---

Changes the tab injection mechanism for better compatibility with websites that might have issues with hydration mismatches when using the old injection mechanism.
8 changes: 7 additions & 1 deletion src/extension/chrome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
}
],
"content_scripts": [
{ "matches": ["<all_urls>"], "js": ["tab.js"], "run_at": "document_start" }
{ "matches": ["<all_urls>"], "js": ["tab.js"], "run_at": "document_start" },
{
"matches": ["<all_urls>"],
"js": ["hook.js"],
"run_at": "document_start",
"world": "MAIN"
}
],
"manifest_version": 3
}
58 changes: 38 additions & 20 deletions src/extension/tab/tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,43 @@
import "./tabRelay";
import browser from "webextension-polyfill";

/*
Content scripts are unable to modify the window object directly.
A common workaround for this issue is to inject an inlined function
into the inspected tab.
*/
if (typeof document === "object" && document instanceof HTMLDocument) {
const script = document.createElement("script");
script.setAttribute("type", "module");
script.setAttribute("src", browser.runtime.getURL("hook.js"));
document.addEventListener("DOMContentLoaded", () => {
const importMap = document.querySelector('script[type="importmap"]');
if (importMap != null) {
importMap.parentNode?.insertBefore(script, importMap.nextSibling);
} else {
const head =
document.head ||
document.getElementsByTagName("head")[0] ||
document.documentElement;
head.insertBefore(script, head.lastChild);
declare const __IS_FIREFOX__: boolean;

// We run the hook.js script on the page as a content script in Manifest v3
// extensions (chrome for now). We do this using execution world MAIN.
//
// We need to inject this code in this manner for Firefox because it does not
// support ExecutionWorld.MAIN:
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/ExecutionWorld
//
// In this content script we have access to DOM, but don't have access to the
// webpage's window, so we inject this inline script tag into the webpage
// instead.
//
// https://github.com/facebook/react/blob/18a9dd1c60fdb711982f32ce5d91acfe8f158fe1/packages/react-devtools-extensions/src/contentScripts/prepareInjection.js
// which is released under a MIT license (Copyright (c) Meta Platforms, Inc. and affiliates.) that can be found here:
// https://github.com/facebook/react/blob/18a9dd1c60fdb711982f32ce5d91acfe8f158fe1/LICENSE
if (__IS_FIREFOX__) {
// eslint-disable-next-line no-inner-declarations
function injectScript(src: string) {
let code = "";
const request = new XMLHttpRequest();
request.addEventListener("load", function () {
code = this.responseText;
});
request.open("GET", src, false);
request.send();

const script = document.createElement("script");
script.textContent = code;

// This script is run before the <head> element is created so we add it to
// <html> instead.
if (typeof document === "object" && document instanceof Document) {
document.documentElement.appendChild(script);
script.parentNode?.removeChild(script);
}
});
}

injectScript(browser.runtime.getURL("hook.js"));
}
1 change: 1 addition & 0 deletions webpack.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default (env) => {
}),
new webpack.DefinePlugin({
VERSION: JSON.stringify(packageJson.version),
__IS_FIREFOX__: target === "firefox",
}),
];

Expand Down

0 comments on commit 8ce6fef

Please sign in to comment.