I’m creating a Chrome extension, part of its function is to click a link of a website and the site itself will open a new tab, then my extension will print the tab. I’m now facing a problem in detecting the new tab’s completeness.
My original approach is to use chrome.tabs.onUpdated
and by detecting the status change to complete
, the code will continue to run.
async function asyncChkTabLoaded(targetTabID){
return new Promise(resolve => {
chkTabLoaded = function (tabID, tabChanges, tabData) {
if (tabID == targetTabID) {
if ("status" in tabChanges) {
if (tabChanges.status == "complete"){
resolve(tabData);
}
}
}
}
chrome.tabs.onUpdated.addListener(chkTabLoaded);
});
}
await asyncChkTabLoaded(openedTabID);
However, I found that by using this approach, part of the content is not fully loaded, mainly the images. And so the auto-print following will print a website with empty images. complete
is not really meaning complete.
I believe this is due to the weird properties of the tabs.onUpdated
that “The status
property will cycle through "loading"
and "complete"
.” (https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated)
I know that I can detect the loading status of the image by using image.complete
. However, some of the image is a <image> tag wrapping in a <svg>, for example:
<svg id="main-svg" preserveAspectRatio="xMidYMid" viewBox="0 0 486 934">
<image x="0.00" y="0.00" width="486.69" height="632.84" image-rendering="-moz-crisp-edges" preserveAspectRatio="none" xlink:href="data:image/png;base64, iVB0KGgoAA..P2YII="></image>
</svg>
And it seems there’s no complete
attribute for svg element. So using image.complete
may not fully fit my case.
So I think it is the most safetest way to use the load
event of the tab window as a guideline to detect the completeness of the website contents. And here’s how I modify the asyncChkTabLoaded
async function asyncChkTabLoaded(){
return new Promise(resolve => {
console.log("injected onload");
console.log(document.readyState);
sendResolve = function() {
console.log("Window Loaded");
resolve();
}
window.addEventListener("load", sendResolve);
});
}
await chrome.scripting.executeScript({target : {tabId : openedTabID}, func : asyncChkTabLoaded});
However it seems like the load
event will never be fired, and so the promise will never be resolved and await
forever, and my code will never proceed to the next step to print.
The document.readyState
is always loading
. The Window Loaded
can only be printed if I move the resolve()
out of the function sendResolve
.
So my question is how can I detect the tab load
event of the new tab? I prefer to use resolve
in the load
event, and await
the resolve
, instead of putting all the follow codes into the load
eventlistener callback. So my code’s readability is easier and it’s easier to add further code after the await
.
Or how can I detect the last tab status change of tabs.onUpdated
?
Or how can I detect the loading of SVG element? But that will be the least preferable way to solve this problem, as I am not sure what other unpredictable elements are still loading.
Thank you very much for your help 🙂