When will json global variable be back
kykungz opened this issue · 13 comments
The README.md stated that:
Parsed JSON is exported as a global variable, json, so you can inspect it in the consoleDisabled for now, due to difficulties getting it working with Manifest v3 upgrade.
But is there an estimated date that it will be back?
I've found a workaround for now - paste the following into your console:
json = JSON.parse(document.getElementById("jsonFormatterRaw").querySelector("pre").innerText)
Thanks, @ChrisBAshton !
The workaround provided by @ChrisBAshton works very well. I suggest the rep owner add this information on the README.md file as a suggestion while the global variation option is not available again. I'm glad I found this information here! :)
Thanks all, just added that workaround to the readme.
I'm not sure if it's possible to make it work again out of the box. I think the issue is there's now a stricter separation of contexts, so content scripts can't access the same window
object as the page itself, i.e. can't create window.json
. But maybe there's some trick to do it, so I'll leave this open a while in case anyone else wants to have a go at fixing it.
One potential way of doing this would be to add a setInterval
with a debugger;
statement.
That way DevTools switches to the context of the extension the moment it is opened:
setInterval(() => {
debugger;
}, 500);
Downside of this is that the page is no longer interactive. But you could measure how long it takes to 'execute' the debugger statement using perfomance.now()
and stop the interval the moment it takes more than a couple of milliseconds.
That way users only have to resume the debugger only once:
const interval = setInterval(() => {
const then = performance.now()
debugger
if (performance.now() - then > 100) {
clearInterval(interval)
}
}, 500)
Alternatively it seems like chrome.scripting.executeScript()
might make it possible to inject a static script included with the extension. But it requires a background script, so I didn't actually try this. I'm not sure whether injected scripts like these have access to the global scope of the page.
I did try the debugger statement though and that seems to work.
I've found a workaround for now - paste the following into your console:
json = JSON.parse(document.getElementById("jsonFormatterRaw").querySelector("pre").innerText)
Tampermonkey version that will automatically run on any .json
URL:
// ==UserScript==
// @name JSON formatter `json` global
// @namespace https://github.com/lionel-rowe/
// @version 0.1
// @description try to take over the world!
// @author https://github.com/lionel-rowe/
// @match *://*/*.json
// @match *://*/*.json?*
// @icon https://www.google.com/s2/favicons?sz=64&domain=json.org
// @grant none
// ==/UserScript==
const el = document.querySelector('#jsonFormatterRaw pre');
if (el) window.json ??= JSON.parse(el.textContent);
How did tampermonkey manage to work around the manifest changes? Are they still using manifest v2?
How did tampermonkey manage to work around the manifest changes? Are they still using manifest v2?
Given Tampermonkey #644 [Chrome] Manifest V3: examine the effects is still open, I guess so. It looks like Google has delayed the retirement of v2, though it doesn't seem like there's currently a concrete updated timeline.
@kykungz I don't think that would work. After all, if you can inject a button, why not just inject a <script>
tag?
@kykungz I don't think that would work. After all, if you can inject a button, why not just inject a
<script>
tag?
Good point, I've never develop an extension before, so I'm not really sure how it works haha.
For what it's worth,
I tried attaching a click listener to a button, and yes, it does not work (window
variable seems unaffected).
So I tried again by injecting the script right into the HTML attribute like this:
const buttonInject = document.createElement('button')
buttonInject.innerText = 'Inject window.json'
buttonInject.setAttribute('onclick', `window.json = ${JSON.stringify(parsedJsonValue)}`)
optionBar.appendChild(buttonInject)
and it seems to work.
Does this change anything? Or it will only work locally?
Content scripts can be injected in the main world by setting a manifest key.
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_end",
+ "world": "MAIN"
}
],
This hasn't been supported from the beginning, but I haven't found a clear answer to what Chrome version added support for this. Chrome Developers says the ExecutionWorld
object is in Chrome 95+, but MDN says 102+ and 111+ as a manifest key...?
It is possible for webpages to interfere with these scripts, so caution should be taken when running a script in the main world on untrusted websites.
Or, would a button to copy the JSON to the clipboard be a fine replacement? (related: #145)