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
Refine how to do session teardown/disconnect/closing #35
Comments
https://lists.w3.org/Archives/Public/public-secondscreen/2015Jan/0012.html (End of the mail "semantics of close" |
Copied from #33: Presumably the user agent will provide the ability for the browser with the initiating page to close the presented document (local or remote). However we may want the user agent to close it on the user's behalf when:
Some of these scenarios can be implemented by the app developer; if so the behavior of e.g. window.close() should be defined in the presentation context. |
I'd like to put my two cents before the F2F meeting. Currently This can be solved by introducing additional state |
Thanks, that seems reasonable. Other options that I would put forth for consideration:
|
Some underlying protocols may not support terminating/closing the 2nd screen content. In DIAL, the ability to "stop" an application is optional [1]. Similarly HbbTV (that builds ontop of DIAL) does not mandate this functionality. The behaviour is also not always needed. For example: a user browses a catalogue of video on demand on a mobile device and chooses a show. They "cast" it to the TV to watch it there and will continue to watch it, even if they close the webpage on the mobile device or take some other action within that page that moves them onto looking at other content on the primary screen. I would therefore propose that [1] DIAL 1.7.1 spec section 4 or 6.4 at http://www.dial-multiscreen.org/dial-protocol-specification |
PROPOSED RESOLUTION: for #35, add a "terminated" state to the list of connection state and clarify in the spec what happens on the presenting side when "close" is called (in one-to-one scenario, killing the application) See relevant discussion during first day of Berlin F2F: |
I like the idea of "terminated". Though it doesn't really answer the question of when the page on the TV is closed, does it? I was first thinking that we could make the statechange event when we transition to "terminated" be cancelable, and make the default behavior be to close the page on the TV. I.e. we'd close the page by default, but the page can override by calling .preventDefault(). However that's somewhat awkward for a couple of reasons. First of all it's only when the last PresentationSession object is terminated that we would want to close the page. Second, it's a bit weird to cancel a statechange event since no matter what, the state does change. It's the closing of the page as a result of it that may or may not happen. So maybe we should fire a "lastsessionterminated" (please come up with a better name) event on the navigator.presentation object when the last session is terminated. The default action of this event would be to kill the page. If the event is cancelled the page stays open. Either way, I think the page can at any time call window.close() to close the application on the TV. |
The timing of closing window varies from application to application, e.g. multi-player game might wait for more incoming session and remote video play might want to close the window immediately. The question here would be: should we default close the window or not? If window is not closed by default, adding "terminated" state should be enough because applications can monitor the session state by themselves. If window is closed by default, we'll have to use the preventDefault() technique mentioned by @sicking in comment 3. |
I think closing the presentation page is a good default when the last device-side page calls .close(). Which is why I'm proposing that calling .close() should transition the PresentationSession to a "terminated" state, and that once the last PresentationSession transitions to "terminated" then we'd fire the "lastsessionterminated" and, by default, close the presentation page. @schien, I don't quite understand if you are saying that there are things about that solutions that you don't like? There's also the question of what to do if the user closes the tab with the controlling page, or navigates to a different page. I don't know what a good default behavior is there. |
First, let's assume we adopt the both a
We are overloading the meaning of the state a little bit. It can mean the state of the presentation (terminated or running). It can also mean the state of a single connection between a controlling page and the presentation (closed or not). I don't think these are inconsistent according to the cases above however. |
If the scenarios above make sense, it seems like we don't need an explicit event to tell the presentation that all sessions are disconnected. And the controlling session should only call close() when it wants to terminate the presentation (so we don't need to define the meaning of preventDefault for the state change). |
@sicking , the major concern for me is that we need to overload the meaning of |
I think we need to support this scenario. And I don't think that relying on GC is a good solution for how to support it. Generally speaking, relying on GC to clean up "heavy" resources, like open sockets, is not a good idea since in the world of modern generational GCs it can take a very long time before an object is GCed. This is why we've added .close() on Blob for example. I would also somewhat argue that in the scenario where multiple parties are connected to the same TV, it feels somewhat strange that the "default action" is that when one of those connections are explicitly (rather than accidentally) ended, that the application on the TV is terminated, even though other people are still connected. But I think that I might be biased here because my mental model is that a PresentationSession is more of a "connection" rather than a "session". So this is probably coloring my judgement here. Anyhow, "default" behavior aside, I think there are two ways that we can address the use case of allowing explicitly disconnecting without closing the application running on the TV:
Technically we could even do both solutions above, though that seems somewhat unnecessary. I can live with either (or both) of these solutions since I think they effectively have the same capability-set. However I'm somewhat in favor of the latter. Basically I think the presentation has access to more of the state needed to make a decision about if the presentation should be closed or not. For example it has awareness of other connections, or if the application might be in a state where the user might experience data-loss if the application is closed right now. I.e. it looks nicer to me to let the application on the TV make the ultimate decision about if it should be closed or not when a connection is explicitly terminated. This is why I propose that we add an event like "lastsessionterminated". This event would be fired when all active sessions has transitioned into the "terminated" state. The default action of this event would be to close the application on the TV. This has several nice properties.
But I could also live with any of:
|
I think adding a .disconnect() is the best forward compatible way. WDYT? |
I actually think we can come to a good solution here by adjusting the semantics I proposed earlier, and without any API facing changes. Let's assume we redefine Below "controlling session" means a PresentationSession in the controlling page and "presentation session" means one in the presented page.
To simplify case 5, we can add a boolean Here is a bit of sample code for the presenting page under this proposal:
This proposal does not give a single controlling session the ability to terminate the entire presentation. This may actually be desirable; a single player should not be able to kill the whole game, and as @sicking argues above the presentation may be in a better position to know when to quit. I still prefer using |
I'd think user would prefer being in control - imagine a presentation that
|
Maybe we can add |
I don't think that we should worry about intentionally misbehaving pages. The most common case is likely going to be a website opening itself on the TV. In that scenario neither side is really more "user controlled". I think this also holds true even if website A opens website B on the TV. It's not obvious to me why we should consider website A as more trusted? So I don't think any of the options here give the user more or less control. But I also don't think that's a problem. The TV/dongle will most likely have a remote control which enables turning off whatever application is running on the TV. In theory the browser could also contain some browser-provided UI for turning off the TV application. But I suspect that an ill-willing application running on the TV is a rare enough problem that browser won't want to sacrifice screen realestate to address that? So I think that what we should optimize for here is developer ergonomics and reducing the risk of bugs. I'm fine with @mfoltzgoogle proposal. I.e. to make the default behavior to leave the presentation running and then leave it up to the presentation code to close the application as appropriate. I don't think we'd need a // Assume that the page already is adding the following handler to
// incoming connected sessions.
session.onstatechange = function(e) {
if (e.state == 'closed' || e.state == 'terminated') {
// Show a message that a player/controller left the presentation.
}
if (e.state == 'terminated') {
// opensessions would be a page-maintained Set
opensessions.delete(session);
if (opensessions.size == 0) {
// The last controller disconnected. Close ourselves. We could also
// set a timer to await new connections.
window.close();
}
} It's just two lines of code more, plus keeping a Set of open connections. But that's likely something that you'd want to do anyway in order to do operations on connected controllers. Ultimately I think the main question here is what default behavior we want to have. I really don't think that either @mfoltzgoogle proposal or mine is hard to implement. I don't have strong opinions on having a |
I don't really mind either way but I share Anton's concerns. So, just to be a bit more concrete here. What should happen if Chrome starts Netflix on ChromeCast then the Chrome application on the user's phone gets killed by Android? Should Netflix stops because there are no more clients and continue running? I wonder how we could handle this without |
If I understand correctly, in all of the current proposals, if the Chrome application is killed, the PresentationSession would transition to a Obviously the application could write whatever application logic to handle this, such as immediately pausing any running video, or immediately closing the application. Or doing either of those things after a timeout. I don't see how adding separate |
I guess I should have added more details. I agree with your description of the expected behaviour and that's probably what a user would expect. However, if a user does the exact same thing (starts Netflix on their ChromeCast from thei Chrome Android) and then wants to stop casting Netflix as in it shouldn't be showing on the ChromeCast anymore. If Netflix were to provide a "Close" button that would call |
@avayvod The expectation is that the controlling user agent will provide a way to terminate the presentation (not just a specific connection) without requiring a loaded page to have a connected session. It seems like this is a necessary part of any usable implementation since there's no guarantee that the user will be able to navigate to a page and then get that page to reconnect to the presentation, just to be able to call @sicking Yes that's what I'm proposing here. Another thought is that as long as there is a controlling session connected to the page, the controller can send a command to the presentation asking it to close itself. Adding |
@mounirlamouri if the netflix website calls Either way, the result would be that if the netflix website calls I think @mfoltzgoogle and I are largely in agreement. That we'd have just a The only point of difference in our proposals is whether we have a I can definitely live with or without the But I can really live with either solution. |
I'm relaying some internal discussion for the benefit of the group (paraphrased). The following arguments were put forth in favor of adding an explicit API that would allow any controller to request ending the presentation (versus
Overall I'm fairly persuaded by these arguments. @sicking I'll reply about |
I take it that in point 2 above, you mean I don't really buy arguments 2 and 3. You can accomplish the same thing in application logic by simply doing But I can live with having both a .terminate() and a .close(). At worst it will be some amount of code that doesn't get used a lot. I do think that we should clearly document that .terminate() is not the only way to shut down applications though, and that window.close() works as well. |
@sicking Yes, in point 2, I intended Integrating the above, here is the API I would propose for session lifecycle.
The following diagram summarizes the state transitions for I've retained Finally, the proposal above includes an event, However, there are at least two cases we need to make sure are handled properly to not close the presentation:
If nothing above sounds objectionable, I can author a PR based on this proposal. |
I think we should avoid adding more states and events than we have to. We can always add them later if the developers complain. We discussed the disconnection case before, for example, and always agreed that the UA would try to reconnect and if it fails, there's nothing for the web page to try anymore. So distinguishing between accidental and intended disconnection doesn't seem valuable to me so far. The onsessionsclosed is only useful if we have the default behavior of shutting down the presentation when all the sessions are in terminated state. This might make life easier for the web developers who want this behavior, however I suspect many of them would actually prefer the presentation not to be closed immediately:
I believe both cases above would be more popular than shutting down the presentation if anything goes wrong. That's why the default behavior on the receiving side should be not to shut down the presentation and give it an option of shutting down itself using window.close(). The ability for the user to stop the presentation vs. just detaching the sender from the receiver is important though so a method on PresentationSession is needed to stop the presentation. I still think we should go forward with three states for the PresentationSession: 'connected', 'disconnected' and 'terminated' - and two methods: disconnect() and terminate(). |
@avayvod All good points. I am in favor of landing a smaller change now, and using feedback to add the additional features discussed in this thread. In particular, it seems like the question of the default behavior for the presentation when all sessions are disconnected will be difficult to answer without additional real world experience. I can say that for Google Cast applications, the default behavior is to leave the presentation running; it's suggested that the presentation close itself when the last sender disconnects [1], but many implement some timeout before doing that. Here is a simplified version of the proposal in #35 (comment):
[1] https://developers.google.com/cast/docs/custom_receiver#session-management I plan to prepare a PR to implement this, |
For user agents that implement 2-UA mode will require a signaling protocol to inform remote endpoint about which state (disconnected/terminated) should be entered, if we take the latest proposal. We might need to address it in the spec as well. |
Unless there are further comments, I plan to merge #190 later today. I'll file a separate feature request to consider defining a behavior when all sessions are disconnected from the presentation (paraphrasing the discussion here). |
Regarding @schien's comment #35 (comment) for behavior of If the controlling context calls If the receiving browsing context terminates itself, there may be signaling required to tell the controlling presentation sessions that this was an explicit termination of the presentation (and not, e.g., by a network disconnection or by powering off the display). This is addressed in L771-792 of the PR as an optional (MAY) requirement for the presenting UA. I think the PR should be updated to handle the case where the receiving context calls |
I note some feedback from the TAG on the lifetime of a presentation: [[ |
(Sorry for absence here, got swamped with other things). I'm generally fine with the change here. What surprises me a little is that there now is no ability to detect when a connection is disconnected? It seems useful for for example a game to automatically pause if connection is lost? Was removing this ability intentional? |
@sicking Thanks for getting back to us. @mfoltzgoogle suggested we should gather additional real world experience from implementations before introducing new @mfoltzgoogle I suggest we track the |
(I think we might start to drift offtopic for this issue, let me know if you want me to raise this as a separate issue). If an implementation has the ability to detect that a message failed to be sent correctly, why wouldn't it transition the connection to a disconnected state? |
On failure to send, it will transition the connection to a closed state. The error event could be used to distinguish an application/user request to close, versus an accidental disconnection. I'm not inherently opposed to adding more states, but would like to see a demonstrated developer need that can't be addressed through the existing API. I can file this as a separate issue to clean up the discussion thread. |
Opened #217, let's continue discussion there. |
There are rough edges when it comes to closing the session, resuming it. We need to gain experience from implementations what happens, when the session is disconnected, user-closed, remote-end closed etc.
This section is one aspect of this, but probably the example section needs to shed more light on how expected and unexpected disconnects are handled.
The text was updated successfully, but these errors were encountered: