-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
cross-origin iframe load events vs window.postMessage #4730
Comments
I haven't had time to look in depth, but I think this is because Chrome posts a task in the sender's renderer process, which then sends the IPC to the browser process to be delivered to the correct renderer process. This was to preserve ordering when a postMessage was sent and then something like focus() was supposed to happen before the message arrived, per this change from alexmos: |
@csreis interesting! That commit definitely talks about this case, but also looks like it changed the behavior described in #3506 (comment) -- now Chrome is claiming Did Chrome also change the behavior of MessageChannel postMessage, or just Window postMessage? See https://bugzilla.mozilla.org/show_bug.cgi?id=1440754#c1 It would be really good to get this actually specced in a sane way instead of UAs coming up with different probably-incompatible workarounds... |
Sorry, I don't know whether that change affected MessageChannel, and alexmos is OOO at the moment. @zetafunction, do you know? I imagine we would want to update MessageChannel if not. I agree that it would be useful to find a consistent way to define how this works. |
FWIW, MessagePort.postMessage and window.postMessage do not use the same task sources, so at least in Gecko they are handled differently. |
@cdumez : what is/was our plan here?? |
Can we do the same thing as I proposed in the other issue? Keep a queue of things that need to go across the boundary. Move them across the boundary end-of-task, and then process the queue on the other side when it arrives? |
You could do that, and that would require "enqueuing" the cross-process operation of firing the load event on the iframe(in the parent) at Step 12 of the-end(of the child), since if you wait until the task that marks the child document as fully loaded, the Reading https://chromium-review.googlesource.com/c/chromium/src/+/1012472/, looks like that problem was solved by having the I think the problem can be described more generally as: you can't fire events in another process "sync" from within a task, you need to enqueue some sort of ipc message(and probably enqueue a task on an event-loop to do the actual DOM manipulation, upon receipt of that ipc-message in some sort of router thread separate from an event-loop) which effectively adds an event-loop tick to the operation, meaning that steps that are now spec-ced as happening "in the same task", end-up gaining a tick due to the ipc(and the task queuing upon receipt in the other process), and loosing their ordering advantage versus operations like Example: Or, marking the document of an iframe as fully loaded should fire the "load" event on the containing iframe element, in the same task that marks the document as fully loaded. If the child document is running in a different process however, you need to communicate with the process of the parent, and effectively queue a task to fire the "load" event on the iframe element. So both operations, in a cross-process scenario, find themselves loosing their ordering advantage versus an operation like And in terms of implementations, I assume that receiving an ipc-message is not done "on the event-loop" directly, rather it happens in a in-process ipc-router thread, which then has to queue a task on an event-loop in response to receiving the ipc-message, since running "on the event-loop" steps on such a router thread would break the processing model of the event-loop, because of the parallel task execution. In other words, ipc-communication I think implies queuing a task on an event-loop in the receiving process(hence the loss of ordering, since an additional task is introduced on the receiving end). I think the problem could perhaps be solved by re-using the parallel-queue concept. Where event-loop A would enqueue-the-following-steps consisting of enqueuing a task on event-loop B, with the task performing the operation that would normally be performed "sync" in a task on event-loop A(but now require a cross-process operation running on event-loop B). (What I like about a parallel queue is that while it could involve crossing process boundaries, it doesn't have to, or it could cross more than one boundary, leaving plenty of flexibility with regards to the level of process isolation to UAs. Also, enqueuing steps doesn't mean they need to be handled immediately, just eventually and in order, leaving plenty of space to UA's to "wait" until layout finishes and what not, which seems to be a consideration discussed in https://chromium-review.googlesource.com/c/chromium/src/+/1012472/) Roughly Something like:
So the idea is that you take certain steps from the currently running algorithm, you stop the currently running task, send an ipc-message containing enough info to continue those steps on a different event-loop, then you receive that ipc-message somewhere either directly in the process where the cross-site window is running(or you might have some central broker re-routing the message), but likely on a different thread, some sort of ipc-router thread, and then from that thread you enqueue a task on the relevant event-loop(which by now is in the same process), and that task consists of running those steps from the original task that you suspended in the other process. So for example in the case of a cross-origin And you'd retain ordering, since the task running the "window-post-message-steps" would itself queue a task for fire the message event, whereas a task running something like the "window focusing steps" would not. And all cross-process operation would incur an additional queued task on the receiving end, consistently. Also, given that the iframe-load-in-progress should be set on the child document when it's marked as fully loaded, and then unset when the load event would have fired, it looks like that part would require sending an ipc-message back to the process of the child in order to unset the flag. |
Consider this testcase:
where the
some-url
file looks like this:What should happen? What I observe in browsers, including Chrome in site-per-process mode with the URLs on different sites, is that "LOADED" is logged before the message event listener fires in the parent document. But per spec, what should happen?
postMessage
, queues a task for the message event.That matches the browser behavior, but step 5 is a process-crossing mess in site-per-process mode, no? In particular, the task from (3) runs in the child's process, but then the load event needs to fire in the parent process. If an async message to do that is sent at that point, it will lose the race to the message event that's already been queued up.
So how does Chrome manage its behavior here in this case? Is it explicitly queueing multiple tasks, on different processes, at https://html.spec.whatwg.org/multipage/parsing.html#the-end step 12 instead of queuing a task in one process that will then send a message to another process?
@annevk @mystor @smaug---- @csreis @Rnia @zetafunction
The text was updated successfully, but these errors were encountered: