New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inject only once with multiple frames #23
Comments
Hi @dariop, Witchcraft injects itself into every frame by design. When registering as an extension, Witchcraft asks Chrome for all-frames access. Here's an excerpt from
That's the only way to support scripts that require frame/iframe injection. The downside is, of course, if you don't want that feature, you'll need to deal with it. Every time I face that same issue, I usually only want to inject Witchcraft into the topmost window. If that's your case, it can easily be accomplished by doing the check below: function isTopmostWindow() {
return window.self === window.top;
} This function will only return Don't worry about the CPU overhead. This check is a really simple operation, just a boolean comparison. Considering the web application loads 23 frames, Witchcraft loading itself into each frame is the least of your concerns 😄. Witchcraft is a lean extension, just check the code. It doesn't depend on any libraries and the code is really tiny, especially the part that is injected into every frame. It is so small that I can even paste the complete code here: /*
This is the part that gets injected in each frame of the page. It signals the Witchcraft background script that a new
frame has been loaded and gets ready (by creating a listener) to receive and load any matching scripts.
*/
chrome.runtime.onMessage.addListener(({scriptType, scriptContents}) => {
if (scriptType === "js") {
Function(scriptContents)();
} else if (scriptType === "css") {
const style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(scriptContents));
style.setAttribute("data-witchcraft", ""); // to make it easy finding the element if we want to
document.head.appendChild(style);
}
});
chrome.runtime.sendMessage(location.hostname); So you shouldn't worry about memory usage either. Well, that's it. I hope my answer made sense to you. Great question, anyway. I will add it to the FAQ. I'm closing this ticket, but feel free to discuss it further if you want and please let me know if you need more help. Thanks! |
Question added to the FAQ. |
Hello @luciopaiva , I was concerned about injection of my code, not yours :) Anyway, for some reasons regarding the web application I want to extend, I can't inject my code in the topmost window, so I solved in another way: I check if we are in the frame I care about, and in this case (and only in this case) I do some stuff. if(window.name==='my_frame'){
$(document).ready(function(){
//load my data once
if(!!!window.top.myData){
$.ajax({
dataType: "json",
url: 'http://127.0.0.1:5743/myData.json',
async: false
})
.done(function(json) {
window.top.myData= json;
})
}
doStuff();
doStuffUsingMyData();
});
} I used $.ajax() instead of // @include myData.js to load my data, in order to avoid an injection of ~1MB (size of my data) for every frame. Thanks again! |
Got it, nice and elegant solution! |
Hi,
I'm trying to enhance an old web application that I use at work.
This website has a lot of nested frames and iframes, some scripts that force reloads, so for every useful injection of JS/CSS, Witchcraft does 23 (!) unuseful injections!
Is there a way to do injection only once per page?
I'm trying to do it detecting in which frame the script is injected, but the overhead (and wasted RAM) is still huge.
Thank you!
Dario
The text was updated successfully, but these errors were encountered: