1

Is there any mechanism that would allow me handle the values on a browser level? What I mean is either:

  • sessionStorage that I can access values in ANY tab in browser (something like server side sessions)

  • localStorage that would be removed on session end (when closing the browser, not tab)

For example, the video starts in player in one tab. Some flag is stored in that kind of storage. When user opens another tab with the same URL, app should read that flag and dissalow playing the video. Of course it should be removed on exit, otherwise flag would dissalow all the future requests in that browser. Any suggestions?

Dalibor
  • 1,430
  • 18
  • 42
  • You can use localstorage to serve your purpose...Just clear localstorage on browser window closed :)The main task here is to detect bowser window close event... – AkshayJ Dec 08 '15 at 10:16
  • How can I establish when the browser window is closed? I use onunload, onbeforeunload... but it triggers every time page is closed, so all the user has to do is browse around in second tab and the flag will be deleted. Is there any other event to use when the browser window is closed? – Dalibor Dec 08 '15 at 10:19
  • You don't have to care about when the entire browser is closed, though, only about when the tab that's playing the video is closed. Use localStorage to store the flag preventing other tabs from playing the video, and add an onunload (or similar) event to the **TAB** playing the video that clears the localStorage flag on closing that tab. – Ieuan Stanley Dec 08 '15 at 10:29
  • @IStanley: onunload event isnt supported cross browser and also it hits when page is refreshed.Besides,being the same URL you cannot get to know when to clear localstorage. – AkshayJ Dec 08 '15 at 10:33
  • Refreshing shouldn't be an issue - you want it to clear the flag on refresh otherwise the refreshed page would be prevented from playing the video as the flag would still be set. Good point on the onunload front, I'll have a look and see what the most supported event is – Ieuan Stanley Dec 08 '15 at 10:36
  • @IStanley:onbeforeunload event can be the solution :) – AkshayJ Dec 08 '15 at 10:39
  • I've had a look, seems both are equally supported these days. I've added details and references to my answer. – Ieuan Stanley Dec 08 '15 at 10:42
  • Thanks both, but unload event is not an option, because: user opens 2nd tab and tries to play video and is denied due to the flag in localStorage. He browses to, say, homepage and flag is cleared (due to the unload event). He comes back to player and plays the video unauthorized. – Dalibor Dec 09 '15 at 09:21

4 Answers4

1

every tab or window data can save/read to local/session storage but it's limited to that domain only.

The question that you asked about video handling over two tabs, it can be pulled of, but that is very tricky to handle, and I would not suggest to go that road! You can periodicaly save timestamps of video to browser storage but it also depends on server that is sending the video to browser, and you could end up not serving the video to the user at all!

For clearing the data when browser window close I think there is no event for that but there is event for window loosing focus so you can use that I guess.

hth,

Kresimir Pendic
  • 3,597
  • 1
  • 21
  • 28
1

If the requirement is to have this last "as long as the browser window is open", you're going to hit repeated issues as browsers don't work on that level any more - there is tab-level and domain-level (persists like cookies). The "Browser Window" is just a collection of tabs, unless you specifically set up your browser in a certain way (to remove cookies and session data on closing and not share data between window instances). This however is browser setup (and isn't even standard across different browsers), and not something you can control client-side.

If you're willing to consider some alternatives that will provide the end result you seem to require, if not in the specific manner you have specified, read on:

To Expand on AkshayJ's original comment, use localStorage as sessionStorage is only ever tab-specific (it can't be shared).

In order to clear the flag, as part of the same functionality that sets the flag, add an onunload event to the tab playing the video that will clear it when the tab is closed or the window location moves away from the video. This will allow greater functionality than you originally requested, because in your original case the user would have to close down the browser entirely before they could play the video again, even if the tab that was playing the video was long gone or had moved on to another page.

UPDATE:

If the security/authorization around this is of paramount importance (rather than just wanting to stop it happening "by accident"), then using localStorage is completely the wrong approach - this data and its existence is ultimately controlled by the user. They can remove it, or set up their browser so that window instances don't share the data, so all they need to do is open a new window to view your video twice at the same time. A determined user would find their way around this in minutes.

If you want to control it absolutely, you have to take this domain side rather than relying on browser storage, and use some other tag like a list of currently-accessing IPs, or some other method of identifying a unique user, to determine whether the video can be played or not. Bear in mind that you would have the same issues as before regarding when to clear the flag whether it's browser side of domain side.

UPDATE:

re: what event to use, it appears that onunload and onbeforeunload are both fully supported across all common browsers (ref: Here and Here). This Answer recommends using both in order to be on the safe side.

UPDATE:

The OP has expressed worry that unload events are unreliable and that the user might remain locked out forever if something goes wrong. Personally I haven't experienced any unreliability here, but if you're worried, then introduce a timeout aspect. Have the tab playing the video update the flag (wherever it is stored) with a timestamp every 30 seconds/1 minute/whatever. Then when a new instance of the page loads, have it check the timestamp. if something has happened to the existing page such that it froze and unload events didn't run, the timestamp will be out of date because it will have also stopped updating, so you just have to check whether the timestamp is out of date as well as checking for presence.

Community
  • 1
  • 1
Ieuan Stanley
  • 1,248
  • 8
  • 20
  • Thanks, but I don't think that would work: user opens 2nd tab and tries to play video and is denied due to the flag in localStorage. He browses to, say, homepage and flag is cleared (due to the unload event). He comes back to player and plays the video unauthorized. Furthermore, I don't want to rely on someting so fragile as unload event; what if flag remains in localStorage accidently, and user can't play video any more next time they visit the site? – Dalibor Dec 09 '15 at 09:23
  • re: your comment, my understanding is that that is required behaviour? I'm now confused as to the circumstances you want to prevent the video from playing. Surely if the user navigates away from the video they are allowed to play it again, otherwise what's the difference between that and just closing and re-opening their browser? Also bear in mind that Browser instances can be set up to not share cookies/localStorage so they could just open a new window and bypass... I'll update my answer on some stuff regarding that. – Ieuan Stanley Dec 09 '15 at 09:36
  • Please read my initial question. localStorage value should be removed on session end (closing the browser), as in server session. LocalStorage value shouldn't be removed on leaving the page. – Dalibor Dec 09 '15 at 09:48
  • I understand that, but there's no "onbrowserclose" event because browsers don't think about their contents like that. There's tabs, and there's domains, which persist to the same extent as cookies. I'm trying to provide you with an alternative based on the details of the requirement. In the case of the video, there's no need to wait for the browser to be closed if all you want to do is prevent the user from playing the video more than once at a time. In fact you could end up denying a user from playing the video even if it isn't open in any existing tab. Is that what you want? – Ieuan Stanley Dec 09 '15 at 10:00
  • Thank you. My worry still remains, when user browse to another page in 2nd tab and comes back to player, he will be able to play it. – Dalibor Dec 09 '15 at 10:26
  • I've updated my answer with a bit more detail. localStorage will do the job if you want to stop it from happening automatically. That is to say, you don't really want it to happen, but if it does it's not the end of the world. If it is of utmost importance that they can't, then localStorage and sessionStorage aren't secure enough, because it is *user* data, not client data. The user can do whatever they like with it and there's nothing you can do about that. If you're worried about someone bypassing that you need to look at other methods I'm afraid! – Ieuan Stanley Dec 09 '15 at 10:29
  • I'm not afraid of bypassing, here's the scenario: There's the flag that activates when video starts. It's stored in localStorage. On the unload event of the player page, the flag is removed. Right? (When does the unload event trigger? When user leaves the page.) User opens new tab and browses to video page. He is blocked due to the flag. He browses away from that page to home in 2nd tab (as he browses away, unload event is triggered and flag is removed.) He comes back to video page (all that in 2nd tab) and he can play the video because there is no flag anymore. – Dalibor Dec 09 '15 at 11:17
  • Gotcha. Shouldn't be too much of an issue - you could only add the unload event when the flag is set (which is the natural approach anyway). That means it wouldn't be present on a tab which stops when it finds the existing flag. You could double up security on that with the timestamp approach as the "playing" tab would automatically refresh the flag after whatever your wait interval is. Make that short enough (a second or so, not particularly time consuming) and the flag will be back by the time the user reloads the page. – Ieuan Stanley Dec 09 '15 at 11:24
  • I got you a point for all the trouble; however I decided to go with server sessions. Even so, the unload event would be listened also on the 2nd tab because the flag is set when user requests there. Thanks anyway. – Dalibor Dec 09 '15 at 13:05
1
$(window).on('beforeunload', function DecideAction() {
   if (('localStorage' in window) && window['localStorage'] !== null) {
      //get value from localstorage using getItem and allow/deny the further access
   }
});
Davide Pastore
  • 8,678
  • 10
  • 39
  • 53
AkshayJ
  • 771
  • 6
  • 15
0

Finally I gave up of the server side sessions because it raised other issues, and solved it with this workflow:

  • After page load, localStorage value is set if it hasn't been before, as well as flag that the player is opened in this tab. If the localStorage is already set, flag is set to false.

  • If flag is set, play video, otherwise prohibit.

  • On page unload, only if the flag is set (that is, if user opened video in this tab), remove localStorage value.

$(function () {
    if (localStorage.playerTabOpened) {
        var dateNow = Date.now();
        var diffSinceLastTabOpened = (dateNow - localStorage.playerTabOpened) / 1000;
        // if playerTabOpened value was stored more than 1 day ago, delete it anyway because it could be left by chance
        if (diffSinceLastTabOpened > 86400) {
            localStorage.removeItem("playerTabOpened");
        };
    }
    if (!localStorage.playerTabOpened) {
        shared.playerTabOpenedHere = true;
        localStorage.setItem("playerTabOpened", Date.now());
    } else {
        shared.playerTabOpenedHere = false;
    }
});

$(window).on("beforeunload", function () {
    if (shared.playerTabOpenedHere) {
        localStorage.removeItem("playerTabOpened");
    }
});

if (shared.playerTabOpenedHere) {
    // play
} else {
    // throw error
}
Dalibor
  • 1,430
  • 18
  • 42