Though the title is decently explanatory, I'm curious as how netflix detects how a user is afk. I've looked through the code via chrome's inspect element, and found it may be done through javascript/jquery depending on the mouse position. Is there anyway anyone can verify this or if incorrect, discover the method it is determined? I'm looking to make a plugin to prevent it from pausing.
It's hard to know for sure what Netflix exactly uses to determine if a user has left Netflix, as Netflix probably obfuscates their JavaScript code and it's illegal to reverse engineer it. But there a few possibilities:
A timer that constantly calls document.hasFocus() to see if it has changed.
Most web browsers (Firefox v10+, Chrome v13+, Internet Explorer v10+, Opera v12.10+, and Safari v7+) have a built-in event to check if a window/tab is active or not. Mozilla has documentation on using the visibilitychange event, including an example with a video that pauses or plays when the visibility changes.
Whenever the javascript events onmousemove or onkeydown is called and the page is loaded for the first time, a variable is set to the current unix time. A timer checks this variable to see if so much time has elapsed since the event is called to see if the user has left the window. This is highly unlikely as people may watch a 2 hour movie without ever touching their mouse or keyboard.
There's also this previous question on StackOverflow which includes many different answers to the same question you asked.
Related
BEFORE YOU TRY AND MARK THIS AS A REPEATED QUESTION
I know this is possible, and all of the other questions are old. Here's why this question is different:
Netflix has been able to do this. Try streaming Netflix, turn subtitles on, and you can see that if you try and take a screenshot, the subtitle will appear, but the video will not.
Try this again with OBS. When you use a desktop/window capture, you can see the video from Netflix playing in the browser, but at the SAME time, OBS can't pick it up.
This Wordpress plugin (which I haven't tried out personally, so not sure if it works, but the reviews are promising)
So now that I've assured you this isn't a question with the context of 2014, are there any new ways to be able to avoid screen capture on the web? I've assumed that it's impossible for a while, but it looks like there might be an API for it somewhere, and no one hasn't asked this question in years here. It'd be useful for preventing capture in my own JS websites, so I was just wondering how I could implement this myself. Thanks.
Your initial assumption is correct, it's impossible. The Netflix example is different, because it isn't preventing a screenshot of the webpage (which is why the subtitles still get captured) but of the video stream, which is embedded in the webpage, but not actually a part of it. The video isn't captured in your example because it's protected by Encrypted Media Extensions. This also means, though, that the video isn't playable in just any browser, it's only accessible in browsers that support EME.
So, the answer to "how do you prevent screen captures on the web" is "convince every browser manufacturer to include features in their browser that allow you to control screen capturing, and then only make your website available to browsers that support that feature" (which is essentially what Netflix did for video).
You could try playing a transparent DRM-protected video on top of your content (and forward any user event to the element below it). When the user takes a screenshot, the video should produce a solid overlay on top of your actual content.
I'm facing problem with facebook video embedded on my post. My client wanted me to follow this method: https://medium.com/#BenBillups/facebook-video-embeds-that-actually-work-57037f8cdcf3
I've done all of the part except PHP code because that wasn't required by my client. Now what is happening. When page loads a play button appear to start video. On click it work just fine. It plays the video but only on desktops. The click event triggers on mobiles and tablets. But it doesn't start the video.
Please take a look at https://candylish.com/mix-and-match-swirl-cookies/ and also check in mobile. You'll see the difference.
In short, you've to click twice in mobile to start video.
Please help me sort this out.
Thanks :)
I think you are simply dealing with mobile browser's general reluctance to start playing video, when they can't determine it was directly connected to a user interaction (and therefor likely willingly triggered by the user.)
//Autoplay
FB.Event.subscribe('xfbml.ready', function(msg) {
if (msg.type === 'video') {
msg.instance.play();
}
});
This code waits for one of the SDK's events to fire and then tries to call the play method, introducing exactly the kind of asynchronism/detachment that gets this blocked, because techniques like that are often used in a malicious way.
In short, you've to click twice in mobile to start video.
That second click is "a whole different animal" altogether ... it happens on the native play button of the (now) embedded social plugin. The other script is not involved at all any more at this point, and this click is a direct user interaction that triggers the video to play, so it is allowed to work. This isn't nested into anything asynchronous or callbacks, it is straight up click => trigger play.
I don't think you will find any example using this technique where this will work differently.
Mobile browsers are more gracious when it comes to autoplay-on-page-load(!) videos, if those videos do not contain an audio track or are embedded to be muted by default. I don't think Facebook offers the latter as an option for mobile to begin with (the data-autoplay attribute does that for desktop, but is documented to not work on mobile) - so at most you could try with a Facebook video that is silent to begin with; but apart from that I'm not sure this restriction resp. when it actually gets lifted even applies here, it's probably not going to fulfill your client's requirement either.
I started typing this as a comment, but besides that it has gotten a little longer now, in this case I think it can't be done actually simply is the answer, even if it might not be a satisfying one.
I'm looking for a way to check if a device supports either the DeviceOrientationEvent or DeviceMotionEvent. To be more precisely I wan't to know if the device really has an accelerometer.
Unfortunately window.DeviceMotionEvent and window.ondevicemotion respectively window.DeviceOrientationEvent and window.ondeviceorientation exists although the device - MacBook Retina - doesn't have an accelerometer.
It's clear to me, that if the Event is never fired, the callback-function of an eventlistener will also never run. But in my case I, my program need's to know if the device has an accelerometer, because the user should receive a notification if there is no accelerometer.
Answers of this post unfortunately didn't work for my problem.
Detecting support for a given JavaScript event?
Given your program needs to have an accelerometer functionality to function, I'm assuming you're blocking its execution if there is none.
So your program could 'block' by default, and listen for a single deviceMotionEvent which will initialize the whole of your program, which will ultimately bind onto window.ondevicemotion. That way you don't need to block the execution for with a setTimeout; a deviceMotionEvent will likely be fired rather quickly after window load.
Further to this question, I'm getting a curious result when binding a function to the change event of the Storage object in Chrome 8.0.552.224.
The test:
<!DOCTYPE html>
<html>
<head>
<title>Chrome localStorage Test</title>
<script type="text/javascript" >
var handle_storage = function () {
alert('storage event');
};
window.addEventListener("storage", handle_storage, false);
</script>
</head>
<body>
<button id="add" onclick="localStorage.setItem('a','test')">Add</button>
<button id="clear" onclick="localStorage.clear()">Clear</button>
</body>
</html>
Open up the page in two Chrome windows, one window with two tabs,
Click the 'Add' button
When I do this I get an alert box displayed on on the second tab and on the second window but not on the tab that invoked the event (the I clicked on). As I understand it I should see three alert boxes (one for each tab opened).
Is this a bug? Is anyone else getting this behaviour? If not what version are you running? Or have I just got this all completely wrong?
Update and final conlusion
It turns out that the spec actually says that this is the desired behavior, therefore IE9's implementation is broken.
4.2 The sessionStorage attribute
When the setItem(), removeItem(), and clear() methods are called on a Storage object x ... if the methods did something, then in every HTMLDocument ... [that is] associated with the same storage area, other than x, a storage event must be fired....
So as we can see, the spec does do a really bad job at making it clear, that this is the specified behavior. That was the reason why Opera 10's implementation was broken and it's most likely also the reason why IE9's implementation is broken.
What do we learn from that? Always read every, single, word of the specification (especially if you're implementing the stuff...).
Old answer
As you said the basic behavior here is "Invoke on all but the current page".
There's an old Chrome Bug Report from last July.
As one can read there, Firefox has the same "issue". I've tested this with the latest nightly, still behaves the same way like in Chrome.
Another test in Opera 11 shows that this must be some kind spec'ed behavior, since Opera 11 does the exact same thing but Opera 10 did fire events on all windows / tabs. Sadly the official changelogs for Opera 11 do not state any change for this behavior.
Reading through the specification, nothing there states this behavior. The only thing I could find is:
The storage event is fired when a storage area changes, as described in the previous two sections (for session storage, for local storage).
When this happens, the user agent must queue a task to fire an event with the name storage, which does not bubble and is not cancelable, and which uses the StorageEvent interface, at each Window object whose Document object has a Storage object that is affected.
Note: This includes Document objects that are not fully active, but events fired on those are ignored by the event loop until the Document becomes fully active again.
Well, what does the Note mean?
From another specification:
A Document is said to be fully active when it is the active document of its browsing context, and either its browsing context is a top-level browsing context, or the Document through which that browsing context is nested is itself fully active.
Doesn't make sense? Yes. Does it help us in any way? No.
So we (in the JavaScript Chatroom) poked on #whatwg to see what all of this is about, so far there has been no response. I'll update my answer as soon as we get any response.
To conclude for now
Firefox, Chrome, Safari and Opera have the exact same behavior. That is, they do not fire on the tab / window that made the chance to localStorage.
But IE9 Beta behaves like Opera 10, so it fires on all tabs / windows.
Since the author of the localStorage spec works at Google in R&D, I hardly doubt Chrome would get this wrong. And since there are no Bugs on this over at Bugzilla and Opera changed the behavior in 11, it seems that this is the way it should work. Still no answer why it works this way and why IE9 behaves differently, but we're still waiting for a response from #whatwg.
Ivo Wetzel's answer for what is going wrong is correct.
I was having the same problem but managed to work around this limitation in the spec by manually creating and firing a StorageEvent in the tab that initiated the storage change (see StorageEvent#initStorageEvent).
I'm currently working on a jQuery plugin that tracks a visitors mouse behavior. Movements, clicks, scrolling and resizing are all recorded and sent, via Ajax, to a location where this data is parsed and stored.
Originally, the data is sent to a script when the user leaves the page. By 'leaves' I'm referring to refreshing, going back and forth though history, closing the window/tab and going to a different address.
The solution works in all browsers EXCEPT for Opera. I'm using jQuery's 'unload' event which isn't supported by Opera at all. Neither is onbeforeunload or onunload.
The question is, how do I implement this kind of functionality for Opera browsers?
One solution I had was to make special use of a 'polling' feature I created. This feature allows you to specify an interval which pushes the content to the server every 'x' seconds. Setting this to 1 second specifically for Opera browsers would probably solve this issue, but it's an awful amount of overhead and the requests aren't always completed in sequence, etc ...
Any suggestions or am I only stuck with the above option?
Thanks!
I suppose I could just link you guys to the plugin source. http://www.thedrunkenepic.com/junk/jquery.mousalytics.js
Regarding the code linked above, adding:
if(window.opera)
{
options.interval = 1;
}
On line 89 works great. My only concern is overhead, so I'm still looking for a more elegant solution.
According to http://bytes.com/topic/javascript/insights/799229-browser-quirk-onload-onunload-do-not-fire-back-forward-refresh-opera, Opera never really fires onload / onunload events, so functionality like this isn't possible without hacks.
http://dev.opera.com/articles/view/efficient-javascript/?page=4 seems to confirm this, and basically states that opera tries to maintain the state of the page across requests.
On further investgation, http://unitehowto.com/Onunload indicates that it might be possible with opera.io.webserver.addEventListener('_close', onunload, false); (where onunload is a previously defined function), however it also indicates that this functionality is not consistent across all versions of opera, and might not work at all.
I think that your best option is probably to use the polling option for Opera, or possibly use a server-side check for the current page and where it falls in the history queue.
Does adding this line of JavaScript work for you?
history.navigationMode = 'compatible';
Source: http://www.opera.com/support/kb/view/827/
I've had the same problem and this saved my day:
if( typeof(opera) != 'undefined' )
{
opera.setOverrideHistoryNavigationMode( 'compatible' );
history.navigationMode = 'compatible';
}
More info about this problem can be found at: http://www.opera.com/support/kb/view/827/