Browse Source

Added seek and volume support, check origins in postMessage receivers.

pull/195/head
Joachim Bauch 10 years ago
parent
commit
c8ad76005b
  1. 89
      static/js/directives/youtubevideo.js
  2. 82
      static/partials/youtubevideo_sandbox.html

89
static/js/directives/youtubevideo.js

@ -26,9 +26,13 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -26,9 +26,13 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
var YOUTUBE_IFRAME_API_URL = "//www.youtube.com/iframe_api";
var origin = $window.location.protocol + "//" + $window.location.host;
var Sandbox = function(iframe) {
this.iframe = iframe;
this.iframe.src = "data:text/html;charset=utf-8," + encodeURI(sandboxTemplate);
var template = sandboxTemplate;
template = template.replace(/__PARENT__ORIGIN__/g, origin);
this.iframe.src = "data:text/html;charset=utf-8," + encodeURI(template);
this.target = this.iframe.contentWindow;
};
@ -75,21 +79,28 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -75,21 +79,28 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
this.sandbox.postMessage("seekTo", msg);
};
SandboxPlayer.prototype.setVolume = function(volume) {
this.sandbox.postMessage("setVolume", {"volume": volume});
};
SandboxPlayer.prototype.getCurrentTime = function() {
// TODO(fancycode): implement me
return 0;
};
SandboxPlayer.prototype.getPlayerState = function() {
// TODO(fancycode): implement me
return null;
}
var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
var addedIframeScript = false;
var player = null;
var playerReady = null;
var isPaused = null;
var seekDetector = null;
var playReceivedNow = null;
var prevTime = null;
var prevNow = null;
var initialState = null;
var sandbox = new Sandbox($("#youtubeplayer", $element)[0]);
@ -98,6 +109,10 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -98,6 +109,10 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
var isYouTubeIframeAPIReady = isYouTubeIframeAPIReadyDefer.promise;
var onPostMessage = function(event) {
if (event.origin !== "null" || event.source !== sandbox.target) {
// the sandboxed data-url iframe has "null" as origin
return;
}
var msg = event.data;
var data = msg[msg.type] || {};
switch (msg.type) {
@ -119,8 +134,8 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -119,8 +134,8 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
break;
case "youtube.event":
$scope.$apply(function(scope) {
console.log("State change", data.event);
scope.$emit(data.event);
console.log("State change", data);
scope.$emit(data.event, data.position);
});
break;
default:
@ -190,82 +205,34 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -190,82 +205,34 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
return null;
}
var startDetectSeek = function() {
// TODO(fancycode): seek detection should be implemented in the sandbox
/*
var checkSeek = function() {
if (!player) {
return;
}
var now = new Date();
var time = player.getCurrentTime();
if (prevTime === null) {
prevTime = time;
}
if (prevNow === null) {
prevNow = now;
}
var deltaTime = Math.abs(time - prevTime);
var deltaNow = (now - prevNow) * 0.001;
if (deltaTime > deltaNow * 1.1) {
safeApply($scope, function(scope) {
scope.$emit("youtube.seeked", time);
});
}
prevNow = now;
prevTime = time;
};
if (!seekDetector) {
seekDetector = $window.setInterval(function() {
checkSeek();
}, 1000);
}
checkSeek();
*/
};
var stopDetectSeek = function() {
if (seekDetector) {
$window.clearInterval(seekDetector);
seekDetector = null;
}
prevNow = null;
};
$scope.$on("youtube.playing", function() {
$scope.$on("youtube.playing", function(event, position) {
if (initialState === 2) {
initialState = null;
player.pauseVideo();
return;
}
prevTime = null;
startDetectSeek();
if (isPaused) {
isPaused = false;
mediaStream.webrtc.callForEachCall(function(peercall) {
mediaStreamSendYouTubeVideo(peercall, currentToken, {
Type: "Resume",
Resume: {
position: player.getCurrentTime()
position: position
}
});
});
}
});
$scope.$on("youtube.buffering", function() {
$scope.$on("youtube.buffering", function(event, position) {
if (initialState === 2) {
initialState = null;
player.pauseVideo();
}
startDetectSeek();
});
$scope.$on("youtube.paused", function() {
stopDetectSeek();
$scope.$on("youtube.paused", function(event, position) {
if (!$scope.isPublisher || !currentToken) {
return;
}
@ -276,7 +243,7 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -276,7 +243,7 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
mediaStreamSendYouTubeVideo(peercall, currentToken, {
Type: "Pause",
Pause: {
position: player.getCurrentTime()
position: position
}
});
});
@ -284,7 +251,6 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -284,7 +251,6 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
});
$scope.$on("youtube.ended", function() {
stopDetectSeek();
});
$scope.$on("youtube.seeked", function($event, position) {
@ -306,8 +272,6 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -306,8 +272,6 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
playerReady.done(function() {
$("#youtubeplayer").show();
$scope.playbackActive = true;
prevTime = null;
prevNow = null;
isPaused = null;
if (playReceivedNow) {
var delta = ((new Date()) - playReceivedNow) * 0.001;
@ -585,7 +549,6 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial @@ -585,7 +549,6 @@ define(['jquery', 'underscore', 'text!partials/youtubevideo.html', 'text!partial
$scope.currentVideoUrl = null;
$scope.currentVideoId = null;
peers = {};
stopDetectSeek();
playerReady = null;
initialState = null;
mediaStream.webrtc.e.off("statechange", updater);

82
static/partials/youtubevideo_sandbox.html

@ -24,17 +24,22 @@ @@ -24,17 +24,22 @@
<script>
(function () {
var PARENT_ORIGIN = "__PARENT__ORIGIN__"; // will get replaced with real origin
var YouTubeSandbox = function(window) {
this.head = document.getElementsByTagName('head')[0];
this.window = window;
this.addedIframeScript = false;
this.player = null;
this.seekDetector = null;
this.prevTime = null;
this.prevNow = null;
};
YouTubeSandbox.prototype.postMessage = function(type, message) {
var msg = {"type": type};
msg[type] = message;
this.window.parent.postMessage(msg, "*");
this.window.parent.postMessage(msg, PARENT_ORIGIN);
};
YouTubeSandbox.prototype.onYouTubeIframeAPIReady = function() {
@ -87,7 +92,23 @@ @@ -87,7 +92,23 @@
return;
}
that.postMessage("youtube.event", {"event": msg});
switch (msg) {
case "youtube.playing":
that.prevTime = null;
that.startDetectSeek();
break;
case "youtube.buffering":
that.startDetectSeek();
break;
case "youtube.paused":
that.stopDetectSeek();
break;
case "youtube.ended":
that.stopDetectSeek();
break;
}
that.postMessage("youtube.event", {"event": msg, "position": that.player.getCurrentTime()});
}
}
});
@ -95,6 +116,7 @@ @@ -95,6 +116,7 @@
};
YouTubeSandbox.prototype.destroyPlayer = function() {
this.stopDetectSeek();
if (this.player) {
this.player.destroy();
this.player = null;
@ -102,6 +124,8 @@ @@ -102,6 +124,8 @@
};
YouTubeSandbox.prototype.loadVideo = function(id, position) {
this.prevTime = null;
this.prevNow = null;
if (typeof(position) !== "undefined") {
this.player.loadVideoById(id, position);
} else {
@ -125,10 +149,53 @@ @@ -125,10 +149,53 @@
if (typeof(allowSeekAhead) !== "undefined") {
this.player.seekTo(position, allowSeekAhead);
} else {
this.player.seekTo(positio);
this.player.seekTo(position);
}
};
YouTubeSandbox.prototype.setVolume = function(volume) {
this.player.setVolume(volume);
};
YouTubeSandbox.prototype.startDetectSeek = function() {
var that = this;
var checkSeek = function() {
if (!that.player) {
return;
}
var now = new Date();
var time = that.player.getCurrentTime();
if (that.prevTime === null) {
that.prevTime = time;
}
if (that.prevNow === null) {
that.prevNow = now;
}
var deltaTime = Math.abs(time - that.prevTime);
var deltaNow = (now - that.prevNow) * 0.001;
if (deltaTime > deltaNow * 1.1) {
that.postMessage("youtube.event", {"event": "youtube.seeked", "position": time});
}
that.prevNow = now;
that.prevTime = time;
};
if (!this.seekDetector) {
this.seekDetector = this.window.setInterval(function() {
checkSeek();
}, 1000);
}
checkSeek();
};
YouTubeSandbox.prototype.stopDetectSeek = function() {
if (this.seekDetector) {
this.window.clearInterval(this.seekDetector);
this.seekDetector = null;
}
this.prevNow = null;
};
var sandbox = new YouTubeSandbox(window);
window.onYouTubeIframeAPIReady = function() {
@ -136,6 +203,10 @@ @@ -136,6 +203,10 @@
};
window.addEventListener("message", function(event) {
if (event.origin !== PARENT_ORIGIN) {
// only accept messages from spreed-webrtc
return;
}
var msg = event.data;
var data = msg[msg.type] || {};
switch (msg.type) {
@ -163,8 +234,11 @@ @@ -163,8 +234,11 @@
case "seekTo":
sandbox.seekTo(data.position, data.allowSeekAhead);
break;
case "setVolume":
sandbox.setVolume(data.volume);
break;
default:
// ignore unknown messages (e.g. received from YT player)
console.log("Unknown message received", event);
break;
}
}, false);

Loading…
Cancel
Save