- From: Rottsches, Dominik <dominik.rottsches@intel.com>
- Date: Tue, 21 Jan 2014 15:38:28 +0000
- To: "public-webscreens@w3.org" <public-webscreens@w3.org>
Hi, after the previous discussions and Anton's change proposal we have been thinking about how to incorporate this into our spec. Below you find our idea on how to incorporate: - Discovery, including resuming existing sessions, event-based - Handling of multiple displays (representation as a list/sequence) - Moving from WindowProxy to MessagePorts for less tight coupling, relaxing implementation requirements With that in mind, here is a new bit of example code showing how we envision things to work, split into opener context and player side. Your feedback and criticism on this proposal is highly welcome. We put it out here on the list before starting to edit the spec draft. ### On the opener context side: var discovery, playerURL = "http://example.com/player.html"; discovery = navigator.presentation.discoverScreens(playerURL); discovery.addEventListener("discover", discovered); function discovered(e) { // Here we receive at least one or a list of screens // in either "presenting" or "available" state for our playerURL. // - "presenting" here means, that there is an existing // persistent session for playerURL on that screen. // - "available" means that using the connect() method the consumer // of the API can launch the playerURL on this screen. // Discovery is complete, picking the first screen, // we proceed to the next step: resumeOrPresent(e.screens[0]); } This is the basic discovery procedure: We find screens that are suitable or already showing a session for playerURL. After the asynchronous call to discoverScreens() the screensDiscovered event handler is called when there is at least one screen found. Then, in this example, we pick the first screen and move forward to the next step, which would be trying to present our playerURL content on it or resume an existing session: Open issue here: Since there is no good way to choose if there are multiple results in e.screens, alternatively we could have only one object here, selected by the user during the permission request dialog, e.g. e.selectedScreen. function resumeOrPresent(screen) { // Watch for state changes to either "disconnected" or // (see below) "presenting", if we haven't launched a sesion yet. screen.addEventListener("statechange", screenStateChange); if (screen.state == "presenting") { // Screen is already in state "presenting" for our playerURL. // We can resume communication with the session. communicate(screen); } else { // Screen is "available", we can launch our playerURL content on it. screen.present( /* Optionally with options object { "persistent" : true }. */ ); } ) First, we register our event handler for getting notified about any state changes, either to "presenting" or "disconnected. Now two situations can occur: In the case of existing session, the screen is in state "presensting" and we can resume communications with it right away. The other possibility is that the screen is in "available" state, in which case we would like to launch our player content on it. We do that by calling present(). function screenStateChange(e) { if (screen.state == "presenting") communicate(screen); if (screen.state == "disconnected") console.log("Screen disconnected."); } If we previously were in state "available" and had called present(), we now reach state "presenting" and can pick up communications with the screen. In the case of disconnection or an error resulting from calling present() we end up in state "disconnected". So we're no longer presenting on the screen. function communicate(screen) { // Communicates with presentation window. screen.port.postMessage(/*...*/); // Receiving messages. screen.port.onmessage = function(e) { console.log(e.data); }; } The communicate function is just an illustration for web messaging between the opener context and the screen. ### On the presentation window side, e.g. "player.html": var portToOpenerContext; navigator.presentation.addEventListener( "connect", function(e) { portToOpenerContext = e.port; }; portToOpenerContext.onmessage = function(e) { console.log(e.data); } // Receiving messages. portToOpenerContext.postMessage(...); // Sending messages. On the presentation window side, the consumer of the API has to register for the connect Event on the navigator.presentation object to receive the other end of the MessagePort and can then proceed to communicating both ways. An open issue here is: Do we need to notice disconnects in this direction? Should this just be handled through an application defined protocol which acknowledges messages through the MessagePort? Or do we wrap the MessagePort here as well? Or should we have an additional ondisconnect event? Again, we'd be very happy to receive your feedback, criticism or improvement proposals before we start editing the spec. We believe the above code solves the combination of uses cases and improvement requirements, especially the new discovery requirements quite well. Dominik
Received on Tuesday, 21 January 2014 15:38:58 UTC