1.9.3 • Published 2 years ago

@factoryfour/frame-client v1.9.3

Weekly downloads
86
License
-
Repository
-
Last release
2 years ago

frame-client

Allows a page to communicate over postMessage with multiple iframes.

Example

Check out /example/app and /example/frame for example usage in React.

Backwards Compatibility

This client can be used within frames that use the older FETCH_DATA protocol built into FactoryFour order & task frames:

const client = new FrameClient();
client.on('initial', data => {
    // do something with initial data
});
client.on('update', data => {
    // do something with updated data
});

// this promise won't be resolved, but the parent window will send 'initial' and 'update'
client.connectParentWindow(); 

// works as usual
client.send('REQUEST_TYPE', payload);

Usage

Parent page

const iframe = document.getElementById('my-iframe');
const client = new FrameClient();
const origin = 'http://domain-where-iframe-is-hosted.com';

// Get ready to handle messages from the frame
client.on('ok_here_is_the_sum', data => {
    console.log('The frame computed the sum: ' + data.sum);
});

// Connect to the iframe
client.connectChildIframe(iframe, origin).then(() => {
    // This will be called when the handshake is complete
    client.send('here_is_some_initial_data', {a: 3, b: 5});
});

// Make as many iframes as you want!
const iframe2 = document.getElementById('another-iframe');
const client2 = new FrameClient();
client2.connectChildIframe(iframe2, origin);

Child (inside the frame)

const client = new FrameClient();

client.on('here_is_some_initial_data', data => {
    const { a, b } = data;
    client.send('ok_here_is_the_sum', {sum: a + b});
});

client.connectParentWindow().then(() => {
    // This will also be called when the handshake is complete
    console.log('Ready to start doing some sums!');
})

Handshake Protocol

This all happens under the hood, and hopefully knowledge of this protocol is not required to use this library in an application.

1. Parent Frame

  • Parent Frame creates an iframe, and ends up with a ref to the iframe HTML element
  • Parent Frame picks a unique "channel ID" to use for this particular frame
  • Parent Frame calls the FrameManager singleton's register method
    • This adds the FrameClient to the global list of FrameClients
    • This can happen before or after the frame is loaded
  • Parent Frame sends CHANNEL_ID just in case the frame is already loaded

2. Child Frame

  • The iframe loads. Its contents must be using this same repo! If not, none of this will work
  • The iframe knows its parent window (window.parent) but does not yet know its channel ID
  • The iframe sends a postMessage to window.parent with type=REQUEST_CHANNEL_IDS

3. Parent Frame

  • FrameManager is always listening for REQUEST_CHANNEL_IDS.
  • When it hears this, it sends type=CHANNEL_ID with the particular channel ID for EACH frame to ALL frames
    • We don't know the source of the REQUEST_CHANNEL_IDS message, so other frames will unexpectedly get notified of their CHANNEL_ID even though they didn't ask for it
      • Technically, we could deduce the source of the message by comparing it to all the contentWindow references we have stored. But this is brittle because if any of the iframes happens to reload, its contentWindow reference will become obsolete
      • Instead, when an iframe reloads, it just sends REQUEST_CHANNEL_IDS again and gets back the same channel ID it had before, allowing the "conversation" to continue

4. Child Frame

  • The iframe hears CHANNEL_ID and switches to the channel protocol, sending a SYN with along with the channelId it just received

5. Parent Frame

  • Parent frame hears SYN on a channel and sends ACK on that channel
  • The promise returned by connectChildIframe or connectChildWindow gets resolved

6. Child Frame

  • The iframe hears ACK and then it considers its connection established\
  • The promise returned by connectParentWindow gets resolved
  • At this point the connection is open and any application-layer message protocol can be carried out on this channel
1.9.3

2 years ago

1.9.2

2 years ago

1.9.1

3 years ago

1.9.0

4 years ago

1.8.5

4 years ago

1.8.4

4 years ago

1.8.2

4 years ago

1.8.3

4 years ago

1.8.1

4 years ago

1.7.2

4 years ago

1.8.0

4 years ago

1.7.1

4 years ago

1.7.0

4 years ago

1.6.2

4 years ago

1.5.4

4 years ago

1.6.1

4 years ago

1.6.0

4 years ago

1.5.3

4 years ago

1.5.2

4 years ago

1.5.1

4 years ago

1.5.0

4 years ago

1.4.0

4 years ago

1.3.1

4 years ago

1.3.0

4 years ago

1.2.0

4 years ago

1.1.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.0.1

5 years ago

1.0.0

5 years ago