From c7fd535c2f9b8d55af7b536fda4b49671f6e0826 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Tue, 11 May 2021 12:58:52 -0400 Subject: [PATCH] fix: mark age-restricted youtube videos as complete immediately Youtube videos that are age-restricted must be viewed on youtube itself rather than in the embedded player. So we can't notice when the video is watched. Rather than leave it incompletable, just mark the video complete immediately if it's restricted. AA-804 --- .../xmodule/js/spec/video/completion_spec.js | 15 +++++++++++++ .../xmodule/js/src/video/09_completion.js | 22 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/common/lib/xmodule/xmodule/js/spec/video/completion_spec.js b/common/lib/xmodule/xmodule/js/spec/video/completion_spec.js index c4994caae4..94f45eb800 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/completion_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/completion_spec.js @@ -67,5 +67,20 @@ state.el.trigger('ended'); expect(state.completionHandler.markCompletion).toHaveBeenCalled(); }); + + it('calls the completion api if the video is age restricted', function() { + spyOn(state, 'youtubeId').and.returnValue('fakeYouTubeID'); + spyOn(state.completionHandler, 'markCompletion').and.callThrough(); + state.metadata = {fakeYouTubeID: {contentRating: {}}}; + + // Check metadata once with no content rating and it should not be marked complete + state.el.trigger('metadata_received'); + expect(state.completionHandler.markCompletion).not.toHaveBeenCalled(); + + // But with age restricted rating, it will be completed immediately + state.metadata.fakeYouTubeID.contentRating.ytRating = 'ytAgeRestricted'; + state.el.trigger('metadata_received'); + expect(state.completionHandler.markCompletion).toHaveBeenCalled(); + }); }); }).call(this); diff --git a/common/lib/xmodule/xmodule/js/src/video/09_completion.js b/common/lib/xmodule/xmodule/js/src/video/09_completion.js index 97378e92ef..aa53a97b80 100644 --- a/common/lib/xmodule/xmodule/js/src/video/09_completion.js +++ b/common/lib/xmodule/xmodule/js/src/video/09_completion.js @@ -86,6 +86,13 @@ self.handleTimeUpdate(currentTime); }); + /** Event handler to receive youtube metadata (if we even are a youtube link), + * and mark complete, if youtube will insist on hosting the video itself. + */ + this.state.el.on('metadata_received', function() { + self.checkMetadata(); + }); + /** Event handler to clean up resources when the video player * is destroyed. */ @@ -126,6 +133,21 @@ } }, + /** Handler to call when youtube metadata is received */ + checkMetadata: function() { + var metadata = this.state.metadata[this.state.youtubeId()]; + + // https://developers.google.com/youtube/v3/docs/videos#contentDetails.contentRating.ytRating + if (metadata && metadata.contentRating && metadata.contentRating.ytRating === 'ytAgeRestricted') { + // Age-restricted videos won't play in embedded players. Instead, they ask you to watch it on + // youtube itself. Which means we can't notice if they complete it. Rather than leaving an + // incompletable video in the course, let's just mark it complete right now. + if (!this.isComplete) { + this.markCompletion(); + } + } + }, + /** Submit completion to the LMS */ markCompletion: function(currentTime) { var self = this;