whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.1k stars 2.66k forks source link

Add iframe.readyState and iframe.onreadystatechange #2161

Open andyearnshaw opened 7 years ago

andyearnshaw commented 7 years ago

One of the big challenges I had recently was providing a same-origin iframe with registered custom elements and a jQuery-like API before any scripts run in the iframe document.

Originally, I tried tackling this using a 0ms timer to register the elements and API in the window, but the reason this is so challenging is that there are timing differences related to when the iframe's window and document. For example, when appending an iframe with a src attribute, some browsers will first create a blank document and window and then navigate, creating a new document and new window that replace the previous objects and any modifications you might have made. Cache can also affect the timing.

In the end, I resorted to loading the document via fetch, modifying it to set a base href and replacing the iframe history entry with the location of the document. This was the only way I could guarantee that the behaviour would be the same across browsers. Still, the solution is less than ideal and I feel like it should be much simpler to do this kind of thing. Luckily, for my scenario, the iframe will not contain links and never navigates a second time, but my solution would fall over if I have to support this in the future.

readyState is already provided on a number of interfaces, e.g. Document, HTMLMediaElement, XMLHttpRequest and WebSocket. This property could mirror the state of the iframe document's readyState property, switching to loading and dispatching the readystatechange event once window and document have been created but before any of the document has been parsed. Any initialisation code would then look like this:

var ifr = document.createElement('iframe');
ifr.src = 'widget.html';
ifr.onreadystatechange = () => {
    if (ifr.readyState === 'loading') {
        registerCustomElements(ifr);
        registerAPI(ifr);
    } 
};
targetElement.appendChild(ifr);
domenic commented 7 years ago

Can you explain what the problem is with iframe.contentDocument.onreadystatechange and iframe.contentDocument.readyState?

I don't think we generally want to introduce APIs that only work for same-origin iframes on HTMLIFrameElement.

andyearnshaw commented 7 years ago

Yes, the problem is that you don't know if the document you bind to is going to be replaced with a different one. I'll see if I can get an example together soon.

This wouldn't necessarily only fire for cross-origin iframes, but it wouldn't be as useful in that situation.

On Fri, 9 Dec 2016, 18:15 Domenic Denicola, notifications@github.com wrote:

Can you explain what the problem is with iframe.contentDocument.onreadystatechange and iframe.contentDocument.readyState?

I don't think we generally want to introduce APIs that only work for same-origin iframes on HTMLIFrameElement.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/whatwg/html/issues/2161#issuecomment-266082762, or mute the thread https://github.com/notifications/unsubscribe-auth/ABvdEzuoFHD4MYiZ3BvBcKAUB2n7eHj6ks5rGZq-gaJpZM4LJCQ5 .

domenic commented 7 years ago

No, we can't introduce this for cross-origin iframes, as it leaks information. And so we'd only introduce it for same-origin ones, which would be strange.

It sounds like from your original post there are some cross-browser issues, but we shouldn't be adding new APIs to cover up over those.

andyearnshaw commented 7 years ago

No, we could fix the cross browser issues but it still wouldn't solve the problem of navigation within the iframe. I was hoping we could have a more intuitive way of initializing an iframe with extra features like this.

I'm not sure what extra data it would leak, please explain. We already have an onload event, are we leaking any more than that does? It seems like you can only tell when navigation occurs, but you don't know where to or if it was successful (or if the ready document is an error page).

On Fri, 9 Dec 2016, 19:28 Domenic Denicola, notifications@github.com wrote:

No, we can't introduce this for cross-origin iframes, as it leaks information. And so we'd only introduce it for same-origin ones, which would be strange.

It sounds like from your original post there are some cross-browser issues, but we shouldn't be adding new APIs to cover up over those.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/whatwg/html/issues/2161#issuecomment-266100455, or mute the thread https://github.com/notifications/unsubscribe-auth/ABvdE13mh2TMrPQqzGwuDZZ5im762LhCks5rGavZgaJpZM4LJCQ5 .

duanyao commented 7 years ago

UAs could fire all readystatechange events just before load event on cross-origin iframes, so it leaks no more information than load event.