Re: connection ceremony for iframe postMessage communications
On Mon, Feb 13, 2012 at 12:57 PM, Ian Hickson wrote: > On Fri, 10 Feb 2012, John J Barton wrote: >> > >> > Why would the connectivity part of this be the hard part? >> >> Because the existing information on cross-domain iframe communications >> is incomplete and written in terms few Web app developers understand, >> the browser implementations are new and the error messages they emit are >> puzzling. Solutions for same-domain cases don't work for cross-domain. >> Async communications is hard to debug. > > I agree with your described problems, but I don't see the link between > them and adding yet more features to the platform. Oh, sorry, I answered the question you asked, rather than the one you wanted to ask ;-) "Why should the connectivity part be part of the platform?" To simplify and thus encourage cross-domain application development as a natural and powerful extension of the Web. Multiple incompatible connection sequences exist and will naturally arise. One may eventually dominate. The process will be long and painful; the advantages of competition seem low. By pursuing a standard connection we accelerate the process. A different push-back would make sense to me: it's not yet time. By having this discussion we put the possibility on the table. Already I've learned how to use the MessageChannel solution and that webintents could be another consumer of this connection layer. Maybe there should be no next steps for now. jjb > > The solution to "existing information on cross-domain iframe > communications is incomplete" is to add more information. The solution to > "existing information on cross-domain iframe communications is written in > terms few Web app developers understand" is to write new information. The > solution to "the browser implementations are new" is to wait. The solution > to "the error messages they emit are puzzling" is to file bugs on the > browsers with suggestions for how to improve them. Etc. > > -- > Ian Hickson U+1047E )\._.,--,'``. fL > http://ln.hixie.ch/ U+263A /, _.. \ _\ ;`._ ,. > Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Fri, 10 Feb 2012, John J Barton wrote: > > > > Why would the connectivity part of this be the hard part? > > Because the existing information on cross-domain iframe communications > is incomplete and written in terms few Web app developers understand, > the browser implementations are new and the error messages they emit are > puzzling. Solutions for same-domain cases don't work for cross-domain. > Async communications is hard to debug. I agree with your described problems, but I don't see the link between them and adding yet more features to the platform. The solution to "existing information on cross-domain iframe communications is incomplete" is to add more information. The solution to "existing information on cross-domain iframe communications is written in terms few Web app developers understand" is to write new information. The solution to "the browser implementations are new" is to wait. The solution to "the error messages they emit are puzzling" is to file bugs on the browsers with suggestions for how to improve them. Etc. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On 2/10/2012 3:44 PM, John J Barton wrote: Thanks. As a hint for the next person, it seems like the asymmetric messages (parent 'ping', iframe 'load') is easier than symmetric ('hello'/'ack') I think there are two more cases. Because the messages are all async, the 'it gets missed case" can be "it gets delayed". That causes additional messages. I've been pursuing something like this for transferring content between frames. That's part of why I was excited to see Web Intents taking off. I also went with a ping mechanism for messaging. I recommend taking this thread over to the Web Intents list and examining it there. I see every reason to want a loose idea of what Web Intents over postMessage would look like. They have a shim mechanism for demo purposes and backwards compatibility, but they don't have the same focus you do (or I do), on iframe postMessage. -Charles
Re: connection ceremony for iframe postMessage communications
On Fri, Feb 10, 2012 at 1:37 PM, Ian Hickson wrote: > On Fri, 10 Feb 2012, John J Barton wrote: >> On Fri, Feb 10, 2012 at 10:58 AM, Ian Hickson wrote: >> > On Fri, 10 Feb 2012, John J Barton wrote: >> >> >> >> Just to clarify, I want to see the layer you just outlined be >> >> standard so we can design iframe components and apps to mix and >> >> match. This can be two simple layers on the current messaging: 1) the >> >> connection ceremony, 2) the key/API format. >> > >> > No reason for it to be standard, just define it as part of the >> > protocol you are implementing over postMessage(). >> >> Ok, so I define it for my app. You write an iframe. You read my >> definition and I can load your iframe. Yay! >> >> Then Boris write an app. He defines it for his app. You change your >> iframe to deal with my app and Boris' app. Ok. >> >> Then Mark Zuckerberg and Larry Page define apps. Soon you are spending >> all of your money hiring devs to deal with connection protocols. >> >> Then maybe you will have a reason for a standard? > > Why would the connectivity part of this be the hard part? Because the existing information on cross-domain iframe communications is incomplete and written in terms few Web app developers understand, the browser implementations are new and the error messages they emit are puzzling. Solutions for same-domain cases don't work for cross-domain. Async communications is hard to debug. > Each of these > apps has an entire protocol you'll have to reimplement if you want to > connect to it! The connectivity part is trivial in comparison. Probably not, at least to start. Most of the early efforts are just things like setting UI sizes or passing config strings. In the long run the essential difference between a JS library widget and an iframe widget will be asynchronous message passing. Libraries, tools, and languages features are gearing up to help. > > I'm all for people standardising their postMessage() protocols, though, > if they want to. Nothing is stopping people from doing so. public-webapps would seem to be an appropriate venue to begin the discussion, esp. since this is where the expertise on web messaging exists. jjb
Re: connection ceremony for iframe postMessage communications
On Fri, 10 Feb 2012, John J Barton wrote: > > I think there are two more cases. Because the messages are all async, > the 'it gets missed case" can be "it gets delayed". That causes > additional messages. > > - parent opens iframe, then sets up communications, iframe is quicker: >- iframe sends 'load' message when ready, but it gets delayed >- parent sends 'ping' message >- parent get first 'load' message, responds with port >- iframe sends 'load' message in response to 'ping' Yeah, after receiving the first 'load', the parent should stop listening for more 'load's. > - parent opens iframe, then sets up communications, parent is quicker: >- parent sends 'ping' message, but it gets delayed >- iframe sends 'load' message when ready >- iframe gets 'ping' message, sends 'load' message in response >- parent gets 'load' message, responds with port That's equivalent to the case of the parent not hooking things up until after the iframe is ready. > This doe not change your conclusion, "the first 'load' message indicates > ready", but I believe it does mean that a third message (sending the > port) is needed. Well, probably far more than three messages -- each time you want to start a conversation you would send a port for that conversation. (By "conversation" I mean an instance of the parent invoking a feature that the iframe provides.) > The 'load' message cannot also send the port. Sure. > > (In practice it's usually much simpler than any of this because the > > parent can guarantee that it sets up its communications first, before > > the iframe is even created, and the child can guarantee that it sets > > up its communications before it finishes loading, so the parent can > > just use the regular 'load' event on the iframe and the child never > > needs to wait at all if it wants to start communicating first.) > > Entangling communications setup with iframe 'load' just makes a > complicated problem harder, not simpler. If we can encapsulate the above > logic in a communications library then we don't have to involve the UI > or impact performance delaying load. Whatever works for you. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Fri, Feb 10, 2012 at 10:58 AM, Ian Hickson wrote: > On Fri, 10 Feb 2012, John J Barton wrote: >> > >> > What I meant was just to do this on the receiving side (inside the >> > iframe), after the onmessage handler has been set up (which we are >> > assuming happens after the 'load' event for some reason): >> > >> > parent.postMessage('load', '*'); >> > >> > That way you don't have to depend on the 'load' event, you can just >> > wait for the message from the inner frame. Then when you get it, you >> > know you can start sending.. >> >> The problem here is that the iframe may issue parent.postMessage('load', >> '*") before the parent onmessage handler has been set up. > > You can always guarantee that you've set up your handler before you create > the iframe. But, suppose that's somehow not possible. Then you just define > "ping" as a message you can send to the inner frame, which the inner frame > then responds to with the aforementioned "load" message. > > So now you have the following situations: > > - parent is set up first, then opens iframe: > - iframe sends 'load' message when ready > > - parent opens iframe, then sets up communications, iframe is quicker: > - iframe sends 'load' message when ready, but it gets missed > - parent sends 'ping' message > - iframe sends 'load' message in response > > - parent opens iframe, then sets up communications, parent is quicker: > - parent sends 'ping' message, but it gets missed > - iframe sends 'load' message when ready > > In all three cases, the first 'load' message that is received indicates > that the communication system is ready. Thanks. As a hint for the next person, it seems like the asymmetric messages (parent 'ping', iframe 'load') is easier than symmetric ('hello'/'ack') I think there are two more cases. Because the messages are all async, the 'it gets missed case" can be "it gets delayed". That causes additional messages. - parent opens iframe, then sets up communications, iframe is quicker: - iframe sends 'load' message when ready, but it gets delayed - parent sends 'ping' message - parent get first 'load' message, responds with port - iframe sends 'load' message in response to 'ping' - parent opens iframe, then sets up communications, parent is quicker: - parent sends 'ping' message, but it gets delayed - iframe sends 'load' message when ready - iframe gets 'ping' message, sends 'load' message in response - parent gets 'load' message, responds with port This doe not change your conclusion, "the first 'load' message indicates ready", but I believe it does mean that a third message (sending the port) is needed. The 'load' message cannot also send the port. It also affects when one removes the listener. > (In practice it's usually much simpler than any of this because the parent > can guarantee that it sets up its communications first, before the iframe > is even created, and the child can guarantee that it sets up its > communications before it finishes loading, so the parent can just use the > regular 'load' event on the iframe and the child never needs to wait at > all if it wants to start communicating first.) Entangling communications setup with iframe 'load' just makes a complicated problem harder, not simpler. If we can encapsulate the above logic in a communications library then we don't have to involve the UI or impact performance delaying load. jjb
Re: connection ceremony for iframe postMessage communications
On Fri, 10 Feb 2012, John J Barton wrote: > On Fri, Feb 10, 2012 at 10:58 AM, Ian Hickson wrote: > > On Fri, 10 Feb 2012, John J Barton wrote: > >> > >> Just to clarify, I want to see the layer you just outlined be > >> standard so we can design iframe components and apps to mix and > >> match. This can be two simple layers on the current messaging: 1) the > >> connection ceremony, 2) the key/API format. > > > > No reason for it to be standard, just define it as part of the > > protocol you are implementing over postMessage(). > > Ok, so I define it for my app. You write an iframe. You read my > definition and I can load your iframe. Yay! > > Then Boris write an app. He defines it for his app. You change your > iframe to deal with my app and Boris' app. Ok. > > Then Mark Zuckerberg and Larry Page define apps. Soon you are spending > all of your money hiring devs to deal with connection protocols. > > Then maybe you will have a reason for a standard? Why would the connectivity part of this be the hard part? Each of these apps has an entire protocol you'll have to reimplement if you want to connect to it! The connectivity part is trivial in comparison. I'm all for people standardising their postMessage() protocols, though, if they want to. Nothing is stopping people from doing so. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Fri, Feb 10, 2012 at 10:58 AM, Ian Hickson wrote: > On Fri, 10 Feb 2012, John J Barton wrote: >> >> Just to clarify, I want to see the layer you just outlined be standard >> so we can design iframe components and apps to mix and match. This can >> be two simple layers on the current messaging: 1) the connection >> ceremony, 2) the key/API format. > > No reason for it to be standard, just define it as part of the protocol > you are implementing over postMessage(). Ok, so I define it for my app. You write an iframe. You read my definition and I can load your iframe. Yay! Then Boris write an app. He defines it for his app. You change your iframe to deal with my app and Boris' app. Ok. Then Mark Zuckerberg and Larry Page define apps. Soon you are spending all of your money hiring devs to deal with connection protocols. Then maybe you will have a reason for a standard? jjb > > -- > Ian Hickson U+1047E )\._.,--,'``. fL > http://ln.hixie.ch/ U+263A /, _.. \ _\ ;`._ ,. > Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Fri, 10 Feb 2012, John J Barton wrote: > > > > What I meant was just to do this on the receiving side (inside the > > iframe), after the onmessage handler has been set up (which we are > > assuming happens after the 'load' event for some reason): > > > > parent.postMessage('load', '*'); > > > > That way you don't have to depend on the 'load' event, you can just > > wait for the message from the inner frame. Then when you get it, you > > know you can start sending.. > > The problem here is that the iframe may issue parent.postMessage('load', > '*") before the parent onmessage handler has been set up. You can always guarantee that you've set up your handler before you create the iframe. But, suppose that's somehow not possible. Then you just define "ping" as a message you can send to the inner frame, which the inner frame then responds to with the aforementioned "load" message. So now you have the following situations: - parent is set up first, then opens iframe: - iframe sends 'load' message when ready - parent opens iframe, then sets up communications, iframe is quicker: - iframe sends 'load' message when ready, but it gets missed - parent sends 'ping' message - iframe sends 'load' message in response - parent opens iframe, then sets up communications, parent is quicker: - parent sends 'ping' message, but it gets missed - iframe sends 'load' message when ready In all three cases, the first 'load' message that is received indicates that the communication system is ready. (In practice it's usually much simpler than any of this because the parent can guarantee that it sets up its communications first, before the iframe is even created, and the child can guarantee that it sets up its communications before it finishes loading, so the parent can just use the regular 'load' event on the iframe and the child never needs to wait at all if it wants to start communicating first.) > > And when you do send, you just send a message whose contents are just > > a single key saying what API endpoint you want, and a port, which you > > then use for all communication for that particular API call. > > Just to clarify, I want to see the layer you just outlined be standard > so we can design iframe components and apps to mix and match. This can > be two simple layers on the current messaging: 1) the connection > ceremony, 2) the key/API format. No reason for it to be standard, just define it as part of the protocol you are implementing over postMessage(). -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Thu, Feb 9, 2012 at 11:53 PM, Ian Hickson wrote: > On Thu, 9 Feb 2012, John J Barton wrote: >> On Thu, Feb 9, 2012 at 4:42 PM, Ian Hickson wrote: >> > On Thu, 9 Feb 2012, John J Barton wrote: >> >> >> >> However the solution has two significant problems: >> >> 1. There is no way to know if portToOtherWindow is connected before >> >> you issue postMessage() >> > >> > Just have the target message you when it's ready. > > What I meant was just to do this on the receiving side (inside the > iframe), after the onmessage handler has been set up (which we are > assuming happens after the 'load' event for some reason): > > parent.postMessage('load', '*'); > > That way you don't have to depend on the 'load' event, you can just wait > for the message from the inner frame. Then when you get it, you know you > can start sending.. The problem here is that the iframe may issue parent.postMessage('load', '*") before the parent onmessage handler has been set up. Modern apps no longer use single-point synchronization. The parent window 'load' event has no time relation to the onmessage handler setup, neither the iframe load event. Instead we have multiple synchronizations based on the dependency relationships. This started with script loading but eventually all content will be loaded this way. In the past I've created synchronization in the parent by making the iframe loading dependent upon the onmessage handler set up. But this complicates and thus constraints the design. A peer-to-peer or symmetric solution would be better. > > And when you do send, you just send a message whose contents are just a > single key saying what API endpoint you want, and a port, which you then > use for all communication for that particular API call. Just to clarify, I want to see the layer you just outlined be standard so we can design iframe components and apps to mix and match. This can be two simple layers on the current messaging: 1) the connection ceremony, 2) the key/API format. > > No races or anything. Unfortunately for devs, the Web app world is becoming asynchronous. jjb > > -- > Ian Hickson U+1047E )\._.,--,'``. fL > http://ln.hixie.ch/ U+263A /, _.. \ _\ ;`._ ,. > Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Thu, 9 Feb 2012, John J Barton wrote: > On Thu, Feb 9, 2012 at 4:42 PM, Ian Hickson wrote: > > On Thu, 9 Feb 2012, John J Barton wrote: > >> > >> However the solution has two significant problems: > >> 1. There is no way to know if portToOtherWindow is connected before > >> you issue postMessage() > > > > Just have the target message you when it's ready. What I meant was just to do this on the receiving side (inside the iframe), after the onmessage handler has been set up (which we are assuming happens after the 'load' event for some reason): parent.postMessage('load', '*'); That way you don't have to depend on the 'load' event, you can just wait for the message from the inner frame. Then when you get it, you know you can start sending.. And when you do send, you just send a message whose contents are just a single key saying what API endpoint you want, and a port, which you then use for all communication for that particular API call. No races or anything. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Thu, Feb 9, 2012 at 4:42 PM, Ian Hickson wrote: > On Thu, 9 Feb 2012, John J Barton wrote: >> >> However the solution has two significant problems: >> 1. There is no way to know if portToOtherWindow is connected before >> you issue postMessage() > > Just have the target message you when it's ready. Ah, ok, just to translate (in case anyone understood what I was talking about before): there already exists an out-of-band introduction system, the global postMessage(), which can be used to set up the in-band channel by sending MessageChannel ports as Transferables. Let me see if I can understand this. Both sides create MessageChannel objects; both sides window.addEventListener('message', handler, false) both sides issue other.postMessage("...", "*", [channel.port2]); The second-place finisher in the race succeeds in posting its port2 to the first-place racer. The first-place racer knows it 'won' because it gets the port. But how does the second-place racer know it should use channel.port1 rather than continue waiting? I guess the first-place racer can send an ACK. If yes, then this ACK message needs to be standard for cross-domain iframes. We also need the containing window's global introduction handler to associate the given port with the correct iframe. The difficulty here is that no property of event.source is available (similar I suppose to iframe.contentWindow having nothing but errors to offer beyond only postMessage). Experimentally event.source === other is true in the handler. Is this given by the standard? > > >> 2. All iframes send messages to the same "handler". > > Pass a MessagePort to the target when you start a new conversation, and > do the rest of the conversation on that. Yes this part is cool. jjb
Re: connection ceremony for iframe postMessage communications
On Thu, 9 Feb 2012, John J Barton wrote: > > However the solution has two significant problems: > 1. There is no way to know if portToOtherWindow is connected before > you issue postMessage() Just have the target message you when it's ready. > 2. All iframes send messages to the same "handler". Pass a MessagePort to the target when you start a new conversation, and do the rest of the conversation on that. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: connection ceremony for iframe postMessage communications
On Thu, Feb 9, 2012 at 11:49 AM, Boris Zbarsky wrote: > That doesn't help with the second problem, of course Ok here are some ideas, riffing off the web messaging doc 1 To iframe element add: readonly attribute MessagePort port; 'message' events from the iframe to the containing window (via window.parent.postMessage) will be delivered to any port listener (as well as the global window handler). This solves the multiplexing part, the container listens to a per-iframe object. 'connect' event would be raised and delivered (synchronously) as soon as the iframe issues window.parent.addEventListener('message'...) and vice versa. This solves the async start up part, each side waits for 'connect' before issuing its first postMessage. The 'connect' for the second-place racer triggers the first real message. Pro: also solves the cross-domain-iframes-don't-really-have-contentWindow problems I discussed before. familiar addEventListener API, reuses MessagePort existing iframe code would just work 2. Have HTMLIFrameElement implement MessagePort. This is similar to #1 but the message port functions are attached to the iframe element directly rather than to its port property. Pro: resembles Worker Con: resembles Worker. 3. To window add: [TreatNonCallableAsNull] attribute Function? onconnect; The function would be called when the iframe issues window.parent.addEventListener('message') The onconnect event delivers a 'port'; the event.target would be the iframe element This solves the multiplexing problem: the container listens to a per-iframe port object. Container can compare the event.target to its iframes to decide which port is associated with which iframe. This solves the async startup by causing the container to act like a server: it must listen for connections early. (Modeled on http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#handler-sharedworkerglobalscope-onconnect, since the parent window is shared by all of its enclosed iframes ) This second one seems like it "solves" the async problem by cheating. Couldn't we just issue addEventListener('message',...) "first" in the parent window? The reason 'connect' is better is that it is out-of-band. If we use 'message' for setting up the connection, then we must hold postMessage traffic until we get the first 'message'. Thus the logic in the message handler must have two paths switching on 'first', exactly the problem we try to avoid. With 'connect', the 'message' handler just focuses on communications, not set up. Pro: A bit more modern, as it follows SharedWorkers Seems like it could be expanded to inter-window communications a la Web Intents Again it seems like the iframe code is all the same. While I have experience with the iframe problems, I don't have experience with the features I've cobble together here. Any feedback? If I had any hints about the issues involved in a real implementation and standard I'd work on simulating this with JS. jjb
Re: connection ceremony for iframe postMessage communications
On Thu, Feb 9, 2012 at 11:49 AM, Boris Zbarsky wrote: > On 2/9/12 1:15 PM, John J Barton wrote: >> >> This leads developers to look for events that will tell them about >> 'load' on iframes, and that leads them to try >> iframe.contentWindow.addEventListener(). It works fine for same-domain >> iframes, but fails for cross-domain. > > > Adding a load listener to the iframe element itself should work for this, > no? I guess you mean: by issuing iframe.addEventListener('load', handler, false); you get notified when the iframe load event has completed (but you don't need to touch the contentWindow property). This will work if the iframe ensures that it completes its connection work before 'load'. This prevents the iframe from using async loading for the scripts that create the connection and for any code that handles messages from the parent. Which, in a typical iframe component, would be all the code, since its main job is to provide for the parent. In addition this solution requires that the above addEventListener be attached after the iframe is inserted (so the iframe exists) but before the parent's 'load' event (which is after the iframe load and thus too late. So I'd say it does not solve the original problem and it's hard to use too. Other than that it's a fine idea ;-). jjb
Re: connection ceremony for iframe postMessage communications
On 2/9/12 1:15 PM, John J Barton wrote: This leads developers to look for events that will tell them about 'load' on iframes, and that leads them to try iframe.contentWindow.addEventListener(). It works fine for same-domain iframes, but fails for cross-domain. Adding a load listener to the iframe element itself should work for this, no? That doesn't help with the second problem, of course -Boris