@@ -4739,6 +4739,8 @@ void HTMLMediaElement::Init() {
47394739 mWatchManager .Watch (mTracksCaptured ,
47404740 &HTMLMediaElement::UpdateOutputTrackSources);
47414741 mWatchManager .Watch (mReadyState , &HTMLMediaElement::UpdateOutputTrackSources);
4742+ mWatchManager .Watch (mReadyState ,
4743+ &HTMLMediaElement::UpdatePlaybackPseudoClasses);
47424744
47434745 mWatchManager .Watch (mDownloadSuspendedByCache ,
47444746 &HTMLMediaElement::UpdateReadyStateInternal);
@@ -5112,13 +5114,27 @@ void HTMLMediaElement::UpdateWakeLock() {
51125114
51135115void HTMLMediaElement::UpdatePlaybackPseudoClasses () {
51145116 MOZ_ASSERT (NS_IsMainThread());
5117+ LOG (LogLevel::Debug,
5118+ (" %p UpdatePlaybackPseudoClasses: mPaused=%d, mNetworkState=%d, "
5119+ " mReadyState=%d, mIsCurrentlyStalled=%d" ,
5120+ this , mPaused .Ref (), mNetworkState , mReadyState .Ref (),
5121+ mIsCurrentlyStalled ));
5122+ AutoStateChangeNotifier notifier (*this , /* aNotify=*/ true );
5123+ RemoveStatesSilently (ElementState::PAUSED | ElementState::BUFFERING | ElementState::STALLED);
5124+ // We don’t need to update the playing state because these states are
5125+ // exclusive, and the `:playing` pseudo-class is determined by checking
5126+ // the element's PAUSED state.
51155127 if (mPaused ) {
5116- // We don’t need to update the playing state because these states are
5117- // exclusive, and the `:playing` pseudo-class is determined by checking
5118- // the element's PAUSED state.
5119- AddStates (ElementState::PAUSED);
5120- } else {
5121- RemoveStates (ElementState::PAUSED);
5128+ AddStatesSilently (ElementState::PAUSED);
5129+ return ;
5130+ }
5131+ // https://html.spec.whatwg.org/multipage/semantics-other.html#selector-buffering
5132+ if (mNetworkState == NETWORK_LOADING && mReadyState <= HAVE_CURRENT_DATA) {
5133+ AddStatesSilently (ElementState::BUFFERING);
5134+ // https://html.spec.whatwg.org/multipage/semantics-other.html#selector-stalled
5135+ if (mIsCurrentlyStalled ) {
5136+ AddStatesSilently (ElementState::STALLED);
5137+ }
51225138 }
51235139}
51245140
@@ -6224,6 +6240,8 @@ void HTMLMediaElement::NotifySuspendedByCache(bool aSuspendedByCache) {
62246240
62256241void HTMLMediaElement::DownloadSuspended () {
62266242 if (mNetworkState == NETWORK_LOADING) {
6243+ mIsCurrentlyStalled = false ;
6244+ UpdatePlaybackPseudoClasses ();
62276245 QueueEvent (u" progress" _ns);
62286246 }
62296247 ChangeNetworkState (NETWORK_IDLE);
@@ -6254,6 +6272,8 @@ void HTMLMediaElement::CheckProgress(bool aHaveNewProgress) {
62546272 : (now - mProgressTime >=
62556273 TimeDuration::FromMilliseconds (PROGRESS_MS) &&
62566274 mDataTime > mProgressTime )) {
6275+ mIsCurrentlyStalled = false ;
6276+ UpdatePlaybackPseudoClasses ();
62576277 QueueEvent (u" progress" _ns);
62586278 // Going back 1ms ensures that future data will have now > mProgressTime,
62596279 // and so will trigger another event. mDataTime is not reset because it
@@ -6279,6 +6299,8 @@ void HTMLMediaElement::CheckProgress(bool aHaveNewProgress) {
62796299
62806300 if (now - mDataTime >= TimeDuration::FromMilliseconds (STALL_MS)) {
62816301 if (!mMediaSource ) {
6302+ mIsCurrentlyStalled = true ;
6303+ UpdatePlaybackPseudoClasses ();
62826304 QueueEvent (u" stalled" _ns);
62836305 } else {
62846306 ChangeDelayLoadStatus (false );
@@ -6631,6 +6653,7 @@ void HTMLMediaElement::ChangeNetworkState(nsMediaNetworkState aState) {
66316653
66326654 nsMediaNetworkState oldState = mNetworkState ;
66336655 mNetworkState = aState;
6656+ UpdatePlaybackPseudoClasses ();
66346657 LOG (LogLevel::Debug,
66356658 (" %p Network state changed to %s" , this , gNetworkStateToString [aState]));
66366659 DDLOG (DDLogCategory::Property, " network_state" ,
0 commit comments