aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmlmediaelement.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-01-14 06:35:45 -0500
committerGitHub <noreply@github.com>2019-01-14 06:35:45 -0500
commit1f9b13479462d453f8e498f1caa192ae09961307 (patch)
tree0bcd0ae6a0f798e99ec08c1cb1f5755f52d82575 /components/script/dom/htmlmediaelement.rs
parent6197f1addad631455cb4dcb215e172896f54a9ab (diff)
parent352fed71d7359e93850a85750a2715dbd5c706b9 (diff)
downloadservo-1f9b13479462d453f8e498f1caa192ae09961307.tar.gz
servo-1f9b13479462d453f8e498f1caa192ae09961307.zip
Auto merge of #22348 - germangb:html_media_ended, r=ferjm
Implement Ended media attribute <!-- Please describe your changes on the following line: --> This PR should implement: * New method `HTMLMediaElement::earliest_possible_position()` for the [earliest possible position](https://html.spec.whatwg.org/multipage/media.html#earliest-possible-position) * `Ended` attribute following https://html.spec.whatwg.org/multipage/media.html#ended-playback * Queue steps for when the playback position reaches the end This PR contains placeholders for the following issues (I can rebase changes after the corresponding PRs get merged) - #22321 (Define the Loop attribute) - #22293 (To identify playback direction. Either forwards or backwards) --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [x] These changes fix #22294. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22348) <!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/htmlmediaelement.rs')
-rw-r--r--components/script/dom/htmlmediaelement.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index 64c36f1d017..dd83c2061de 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -1119,6 +1119,63 @@ impl HTMLMediaElement {
// an unsupported format, or can otherwise not be rendered at all"
if self.ready_state.get() < ReadyState::HaveMetadata {
self.queue_dedicated_media_source_failure_steps();
+ } else {
+ // https://html.spec.whatwg.org/multipage/#reaches-the-end
+ match self.direction_of_playback() {
+ PlaybackDirection::Forwards => {
+ // Step 1.
+ if self.Loop() {
+ self.seek(
+ self.earliest_possible_position(),
+ /* approximate_for_speed*/ false,
+ );
+ } else {
+ // Step 2.
+ // The **ended playback** condition is implemented inside of
+ // the HTMLMediaElementMethods::Ended method
+
+ // Step 3.
+ let window = window_from_node(self);
+ let this = Trusted::new(self);
+
+ let _ = window.task_manager().media_element_task_source().queue(
+ task!(reaches_the_end_steps: move || {
+ let this = this.root();
+ // Step 3.1.
+ this.upcast::<EventTarget>().fire_event(atom!("timeupdate"));
+
+ // Step 3.2.
+ if this.Ended() && !this.Paused() {
+ // Step 3.2.1.
+ this.paused.set(true);
+
+ // Step 3.2.2.
+ this.upcast::<EventTarget>().fire_event(atom!("pause"));
+
+ // Step 3.2.3.
+ this.take_pending_play_promises(Err(Error::Abort));
+ this.fulfill_in_flight_play_promises(|| ());
+ }
+
+ // Step 3.3.
+ this.upcast::<EventTarget>().fire_event(atom!("ended"));
+ }),
+ window.upcast(),
+ );
+ }
+ },
+
+ PlaybackDirection::Backwards => {
+ if self.playback_position.get() <= self.earliest_possible_position() {
+ let window = window_from_node(self);
+
+ window
+ .task_manager()
+ .media_element_task_source()
+ .queue_simple_event(self.upcast(), atom!("ended"), &window);
+ }
+ },
+ }
}
},
PlayerEvent::Error => {
@@ -1261,6 +1318,38 @@ impl HTMLMediaElement {
},
}
}
+
+ // https://html.spec.whatwg.org/multipage/#earliest-possible-position
+ fn earliest_possible_position(&self) -> f64 {
+ self.played
+ .borrow()
+ .start(0)
+ .unwrap_or_else(|_| self.playback_position.get())
+ }
+}
+
+// XXX Placeholder for [https://github.com/servo/servo/issues/22293]
+#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)]
+enum PlaybackDirection {
+ Forwards,
+ #[allow(dead_code)]
+ Backwards,
+}
+
+// XXX Placeholder implementations for:
+//
+// - https://github.com/servo/servo/issues/22293
+// - https://github.com/servo/servo/issues/22321
+impl HTMLMediaElement {
+ // https://github.com/servo/servo/issues/22293
+ fn direction_of_playback(&self) -> PlaybackDirection {
+ PlaybackDirection::Forwards
+ }
+
+ // https://github.com/servo/servo/pull/22321
+ fn Loop(&self) -> bool {
+ false
+ }
}
impl HTMLMediaElementMethods for HTMLMediaElement {
@@ -1514,6 +1603,20 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
self.seeking.get()
}
+ // https://html.spec.whatwg.org/multipage/#ended-playback
+ fn Ended(&self) -> bool {
+ if self.ready_state.get() < ReadyState::HaveMetadata {
+ return false;
+ }
+
+ let playback_pos = self.playback_position.get();
+
+ match self.direction_of_playback() {
+ PlaybackDirection::Forwards => playback_pos >= self.Duration() && !self.Loop(),
+ PlaybackDirection::Backwards => playback_pos <= self.earliest_possible_position(),
+ }
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-media-fastseek
fn FastSeek(&self, time: Finite<f64>) {
self.seek(*time, /* approximate_for_speed */ true);