@@ -152,7 +152,20 @@ object FingerprintScriptGenerator {
152152 window.IntersectionObserver.prototype = OrigIO.prototype;
153153 }
154154
155- // 5. Media Session API hooking for notification media player
155+ // 5. Track genuine user interactions so we differentiate user pauses from backgrounding pauses
156+ window.__feather_explicit_pause = false;
157+ let lastUserTouchTime = 0;
158+ const recordUserTouch = function(e) {
159+ if (e && e.isTrusted) {
160+ lastUserTouchTime = Date.now();
161+ }
162+ };
163+ ['pointerdown', 'mousedown', 'touchstart', 'click', 'keydown'].forEach(function(evt) {
164+ window.addEventListener(evt, recordUserTouch, true);
165+ document.addEventListener(evt, recordUserTouch, true);
166+ });
167+
168+ // 6. Media Session API hooking for notification media player
156169 window.__feather_actions = window.__feather_actions || {};
157170
158171 function getMediaThumbnail() {
@@ -246,18 +259,21 @@ object FingerprintScriptGenerator {
246259 }
247260 } catch(e) {}
248261
249- // 6 . Direct media element tracking & action triggers
262+ // 7 . Direct media element tracking & action triggers
250263 window.__feather_media_play = function() {
264+ window.__feather_explicit_pause = false;
251265 try {
252266 if (window.__feather_actions && typeof window.__feather_actions['play'] === 'function') {
253267 window.__feather_actions['play']();
268+ notifyMediaBridge(true);
254269 return;
255270 }
256271 } catch(e) {}
257272 try {
258273 const moviePlayer = document.getElementById('movie_player');
259274 if (moviePlayer && typeof moviePlayer.playVideo === 'function') {
260275 moviePlayer.playVideo();
276+ notifyMediaBridge(true);
261277 return;
262278 }
263279 } catch(e) {}
@@ -267,6 +283,7 @@ object FingerprintScriptGenerator {
267283 mediaEls.forEach(function(m) {
268284 m.play().catch(function() {});
269285 });
286+ notifyMediaBridge(true);
270287 }
271288 } catch(e) {}
272289 try {
@@ -276,16 +293,19 @@ object FingerprintScriptGenerator {
276293 };
277294
278295 window.__feather_media_pause = function() {
296+ window.__feather_explicit_pause = true;
279297 try {
280298 if (window.__feather_actions && typeof window.__feather_actions['pause'] === 'function') {
281299 window.__feather_actions['pause']();
300+ notifyMediaBridge(false);
282301 return;
283302 }
284303 } catch(e) {}
285304 try {
286305 const moviePlayer = document.getElementById('movie_player');
287306 if (moviePlayer && typeof moviePlayer.pauseVideo === 'function') {
288307 moviePlayer.pauseVideo();
308+ notifyMediaBridge(false);
289309 return;
290310 }
291311 } catch(e) {}
@@ -295,6 +315,7 @@ object FingerprintScriptGenerator {
295315 mediaEls.forEach(function(m) {
296316 m.pause();
297317 });
318+ notifyMediaBridge(false);
298319 }
299320 } catch(e) {}
300321 try {
@@ -334,24 +355,33 @@ object FingerprintScriptGenerator {
334355 }
335356 };
336357
337- // Hook HTMLMediaElement prototype play and pause
358+ // 8. Hook HTMLMediaElement prototype play and pause with background auto-pause defense
338359 try {
339360 const origPlay = HTMLMediaElement.prototype.play;
340361 HTMLMediaElement.prototype.play = function() {
362+ window.__feather_explicit_pause = false;
341363 notifyMediaBridge(true);
342364 return origPlay.apply(this, arguments);
343365 };
344366
345367 const origPause = HTMLMediaElement.prototype.pause;
346368 HTMLMediaElement.prototype.pause = function() {
369+ // Check if the pause call was triggered by genuine user action or explicitly by media session bridge
370+ const isExplicitUserPause = window.__feather_explicit_pause || (Date.now() - lastUserTouchTime < 800);
371+ if (!isExplicitUserPause) {
372+ // Suppress unwanted auto-pause triggered by YouTube visibility listeners or background state!
373+ return;
374+ }
347375 notifyMediaBridge(false);
348376 return origPause.apply(this, arguments);
349377 };
350378 } catch(e) {}
351379
352- // Periodic monitor for HTML media elements
380+ // 9. Periodic monitor & watchdog for HTML media elements
353381 let lastReportedState = null;
354382 let lastReportedTitle = '';
383+ let wasActivePlayback = false;
384+
355385 const monitorMedia = function() {
356386 try {
357387 const els = document.querySelectorAll('video, audio');
@@ -364,11 +394,14 @@ object FingerprintScriptGenerator {
364394 el.__feather_monitored = true;
365395
366396 el.addEventListener('play', function() {
397+ window.__feather_explicit_pause = false;
367398 notifyMediaBridge(true);
368399 });
369400
370401 el.addEventListener('pause', function() {
371- notifyMediaBridge(false);
402+ if (window.__feather_explicit_pause || (Date.now() - lastUserTouchTime < 800)) {
403+ notifyMediaBridge(false);
404+ }
372405 });
373406
374407 el.addEventListener('ended', function() {
@@ -378,6 +411,17 @@ object FingerprintScriptGenerator {
378411 });
379412 });
380413
414+ if (anyPlaying) {
415+ wasActivePlayback = true;
416+ } else if (wasActivePlayback && !window.__feather_explicit_pause && (Date.now() - lastUserTouchTime > 1500)) {
417+ // Video unexpectedly paused while in the background without user touch!
418+ // Auto-resume background playback
419+ const video = document.querySelector('video');
420+ if (video && video.paused && !video.ended) {
421+ video.play().catch(function() {});
422+ }
423+ }
424+
381425 const currentTitle = getMediaTitle();
382426 if (anyPlaying !== lastReportedState || (anyPlaying && currentTitle !== lastReportedTitle)) {
383427 lastReportedState = anyPlaying;
@@ -386,7 +430,7 @@ object FingerprintScriptGenerator {
386430 }
387431 } catch(e) {}
388432 };
389- setInterval(monitorMedia, 1500 );
433+ setInterval(monitorMedia, 800 );
390434 monitorMedia();
391435 } catch(e) {}
392436 })();
0 commit comments