Backed out 6 changesets (bug 1531101) for Mochitest failure in toolkit/content/tests/widgets/test_videocontrols_error.html. CLOSED TREE
authorDorel Luca <dluca@mozilla.com>
Tue, 12 Mar 2019 02:04:54 +0200
changeset 521456 b9b0378c5e0b
parent 521455 02b387ef172e
child 521457 e5e2e0d4eb05
push id10866
push usernerli@mozilla.com
push dateTue, 12 Mar 2019 18:59:09 +0000
treeherdermozilla-beta@445c24a51727 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1531101
milestone67.0a1
backs out10e9bbf2d1df
44d96bcc51f7
4a4b44c3481a
12bcda2d76db
5887b55233c2
13a0c61ed4fc
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 1531101) for Mochitest failure in toolkit/content/tests/widgets/test_videocontrols_error.html. CLOSED TREE Backed out changeset 10e9bbf2d1df (bug 1531101) Backed out changeset 44d96bcc51f7 (bug 1531101) Backed out changeset 4a4b44c3481a (bug 1531101) Backed out changeset 12bcda2d76db (bug 1531101) Backed out changeset 5887b55233c2 (bug 1531101) Backed out changeset 13a0c61ed4fc (bug 1531101)
dom/html/HTMLVideoElement.cpp
dom/html/HTMLVideoElement.h
dom/webidl/HTMLVideoElement.webidl
toolkit/actors/PictureInPictureChild.jsm
toolkit/content/widgets/videocontrols.js
toolkit/locales/en-US/chrome/global/videocontrols.dtd
toolkit/themes/shared/jar.inc.mn
toolkit/themes/shared/media/pictureinpicture.svg
toolkit/themes/shared/media/videocontrols.css
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -476,29 +476,19 @@ void HTMLVideoElement::CloneElementVisua
   if (!aTargetVideo.SetVisualCloneSource(this)) {
     mVisualCloneTarget = nullptr;
     rv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   aTargetVideo.SetMediaInfo(mMediaInfo);
 
-  if (IsInComposedDoc()) {
-    NotifyUAWidgetSetupOrChange();
-  }
-
   MaybeBeginCloningVisually();
 }
 
-void HTMLVideoElement::StopCloningElementVisually() {
-  if (mVisualCloneTarget) {
-    EndCloningVisually();
-  }
-}
-
 void HTMLVideoElement::MaybeBeginCloningVisually() {
   if (!mVisualCloneTarget) {
     return;
   }
 
   if (mDecoder) {
     MediaDecoderStateMachine* mdsm = mDecoder->GetStateMachine();
     VideoFrameContainer* container =
@@ -531,16 +521,12 @@ void HTMLVideoElement::EndCloningVisuall
     if (container && mVisualCloneTarget->mSelectedVideoStreamTrack) {
       mVisualCloneTarget->mSelectedVideoStreamTrack->RemoveVideoOutput(
           container);
     }
   }
 
   Unused << mVisualCloneTarget->SetVisualCloneSource(nullptr);
   Unused << SetVisualCloneTarget(nullptr);
-
-  if (IsInComposedDoc()) {
-    NotifyUAWidgetSetupOrChange();
-  }
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -134,20 +134,16 @@ class HTMLVideoElement final : public HT
   }
 
   bool MozIsOrientationLocked() const { return mIsOrientationLocked; }
 
   void SetMozIsOrientationLocked(bool aLock) { mIsOrientationLocked = aLock; }
 
   void CloneElementVisually(HTMLVideoElement& aTarget, ErrorResult& rv);
 
-  void StopCloningElementVisually();
-
-  bool IsCloningElementVisually() const { return !!mVisualCloneTarget; }
-
  protected:
   virtual ~HTMLVideoElement();
 
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aGivenProto) override;
 
   /**
    * We create video wakelock when the video is playing and release it when
--- a/dom/webidl/HTMLVideoElement.webidl
+++ b/dom/webidl/HTMLVideoElement.webidl
@@ -54,25 +54,15 @@ partial interface HTMLVideoElement {
   [Pref="media.videocontrols.lock-video-orientation", Func="IsChromeOrXBLOrUAWidget"]
     attribute boolean mozIsOrientationLocked;
 
   // Clones the frames playing in this <video> to the target. Cloning
   // when either node is removed from their DOM trees. Throws if one or
   // both <video> elements are not attached to a DOM tree.
   [Throws, Func="IsChromeOrXBLOrUAWidget"]
     void cloneElementVisually(HTMLVideoElement target);
-
-  // Stops a <video> from cloning visually. Does nothing if the <video>
-  // wasn't cloning in the first place.
-  [Func="IsChromeOrXBLOrUAWidget"]
-    void stopCloningElementVisually();
-
-  // Returns true if the <video> is being cloned visually to another
-  // <video> element (see cloneElementVisually).
-  [Func="IsChromeOrXBLOrUAWidget"]
-    readonly attribute boolean isCloningElementVisually;
 };
 
 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#idl-def-HTMLVideoElement
 partial interface HTMLVideoElement {
   [Func="mozilla::dom::MediaSource::Enabled", NewObject]
   VideoPlaybackQuality getVideoPlaybackQuality();
 };
--- a/toolkit/actors/PictureInPictureChild.jsm
+++ b/toolkit/actors/PictureInPictureChild.jsm
@@ -101,16 +101,12 @@ class PictureInPictureChild extends Acto
     originatingVideo.cloneElementVisually(playerVideo);
 
     let originatingWindow = originatingVideo.ownerGlobal;
     originatingWindow.addEventListener("unload", (e) => {
       this.closePictureInPicture(originatingVideo);
     }, { once: true });
 
     this.content.addEventListener("unload", () => {
-      let video = gWeakVideo && gWeakVideo.get();
-      if (video) {
-        video.stopCloningElementVisually();
-      }
       gWeakVideo = null;
     }, { once: true });
   }
 }
--- a/toolkit/content/widgets/videocontrols.js
+++ b/toolkit/content/widgets/videocontrols.js
@@ -33,38 +33,29 @@ this.VideoControlsWidget = class {
    */
   onchange() {
     this.switchImpl();
   }
 
   /*
    * Actually switch the implementation.
    * - With "controls" set, the VideoControlsImplWidget controls should load.
-   * - Without it, on mobile, the NoControlsMobileImplWidget should load, so
+   * - Without it, on mobile, the NoControlsImplWidget should load, so
    *   the user could see the click-to-play button when the video/audio is blocked.
-   * - Without it, on desktop, the NoControlsPictureInPictureImpleWidget should load
-   *   if the video is being viewed in Picture-in-Picture.
    */
   switchImpl() {
     let newImpl;
     if (this.element.controls) {
       newImpl = VideoControlsImplWidget;
     } else if (this.isMobile) {
-      newImpl = NoControlsMobileImplWidget;
-    } else if (VideoControlsWidget.isPictureInPictureVideo(this.element)) {
-      newImpl = NoControlsPictureInPictureImplWidget;
+      newImpl = NoControlsImplWidget;
     }
-
-    // Skip if we are asked to load the same implementation, and
-    // the underlying element state hasn't changed in ways that we
-    // care about. This can happen if the property is set again
-    // without a value change.
-    if (this.impl &&
-        this.impl.constructor == newImpl &&
-        this.impl.elementStateMatches(this.element)) {
+    // Skip if we are asked to load the same implementation.
+    // This can happen if the property is set again w/o value change.
+    if (this.impl && this.impl.constructor == newImpl) {
       return;
     }
     if (this.impl) {
       this.impl.destructor();
       this.shadowRoot.firstChild.remove();
     }
     if (newImpl) {
       this.impl = new newImpl(this.shadowRoot);
@@ -77,20 +68,16 @@ this.VideoControlsWidget = class {
   destructor() {
     if (!this.impl) {
       return;
     }
     this.impl.destructor();
     this.shadowRoot.firstChild.remove();
     delete this.impl;
   }
-
-  static isPictureInPictureVideo(someVideo) {
-    return someVideo.isCloningElementVisually;
-  }
 };
 
 this.VideoControlsImplWidget = class {
   constructor(shadowRoot) {
     this.shadowRoot = shadowRoot;
     this.element = shadowRoot.host;
     this.document = this.element.ownerDocument;
     this.window = this.document.defaultView;
@@ -113,17 +100,16 @@ this.VideoControlsImplWidget = class {
       progressBar: null,
       bufferBar: null,
       statusOverlay: null,
       controlsSpacer: null,
       clickToPlay: null,
       controlsOverlay: null,
       fullscreenButton: null,
       layoutControls: null,
-      isShowingPictureInPictureMessage: false,
 
       textTracksCount: 0,
       videoEvents: ["play", "pause", "ended", "volumechange", "loadeddata",
                     "loadstart", "timeupdate", "progress",
                     "playing", "waiting", "canplay", "canplaythrough",
                     "seeking", "seeked", "emptied", "loadedmetadata",
                     "error", "suspend", "stalled",
                     "mozvideoonlyseekbegin", "mozvideoonlyseekcompleted"],
@@ -256,18 +242,16 @@ this.VideoControlsImplWidget = class {
         }
 
         // Set the current status icon.
         if (this.hasError()) {
           this.startFadeOut(this.clickToPlay, true);
           this.statusIcon.setAttribute("type", "error");
           this.updateErrorText();
           this.setupStatusFader(true);
-        } else if (VideoControlsWidget.isPictureInPictureVideo(this.video)) {
-          this.setShowPictureInPictureMessage(true);
         }
 
         let adjustableControls = [
           ...this.prioritizedControls,
           this.controlBar,
           this.clickToPlay,
         ];
 
@@ -376,18 +360,17 @@ this.VideoControlsImplWidget = class {
         // For videos with |autoplay| set, we'll leave the controls initially hidden,
         // so that they don't get in the way of the playing video. Otherwise we'll
         // go ahead and reveal the controls now, so they're an obvious user cue.
         var shouldShow = !this.dynamicControls ||
                          (this.video.paused &&
                          !this.video.autoplay);
         // Hide the overlay if the video time is non-zero or if an error occurred to workaround bug 718107.
         let shouldClickToPlayShow = shouldShow && !this.isAudioOnly &&
-                                    this.video.currentTime == 0 && !this.hasError() &&
-                                    !this.isShowingPictureInPictureMessage;
+                                    this.video.currentTime == 0 && !this.hasError();
         this.startFade(this.clickToPlay, shouldClickToPlayShow, true);
         this.startFade(this.controlBar, shouldShow, true);
       },
 
       get dynamicControls() {
         // Don't fade controls for <audio> elements.
         var enabled = !this.isAudioOnly;
 
@@ -529,17 +512,17 @@ this.VideoControlsImplWidget = class {
             break;
           case "loadeddata":
             this.firstFrameShown = true;
             this.setupStatusFader();
             break;
           case "loadstart":
             this.maxCurrentTimeSeen = 0;
             this.controlsSpacer.removeAttribute("aria-label");
-            this.statusOverlay.removeAttribute("status");
+            this.statusOverlay.removeAttribute("error");
             this.statusIcon.setAttribute("type", "throbber");
             this.isAudioOnly = this.video.localName == "audio";
             this.setPlayButtonState(true);
             this.setupNewLoadState();
             this.setupStatusFader();
             break;
           case "progress":
             this.statusIcon.removeAttribute("stalled");
@@ -762,26 +745,16 @@ this.VideoControlsImplWidget = class {
         // do this intentionally to work around requires-user-interaction to
         // play restrictions, and we don't want to display a debug message
         // if that's the case.
         return this.video.error != null ||
                (this.video.networkState == this.video.NETWORK_NO_SOURCE &&
                this.hasSources());
       },
 
-      setShowPictureInPictureMessage(showMessage) {
-        if (showMessage) {
-          this.pictureInPictureOverlay.removeAttribute("hidden");
-        } else {
-          this.pictureInPictureOverlay.setAttribute("hidden", true);
-        }
-
-        this.isShowingPictureInPictureMessage = showMessage;
-      },
-
       hasSources() {
         if (this.video.hasAttribute("src") &&
             this.video.getAttribute("src") !== "") {
           return true;
         }
         for (var child = this.video.firstChild;
              child !== null;
              child = child.nextElementSibling) {
@@ -796,42 +769,42 @@ this.VideoControlsImplWidget = class {
         let error;
         let v = this.video;
         // It is possible to have both v.networkState == NETWORK_NO_SOURCE
         // as well as v.error being non-null. In this case, we will show
         // the v.error.code instead of the v.networkState error.
         if (v.error) {
           switch (v.error.code) {
             case v.error.MEDIA_ERR_ABORTED:
-              error = "statusErrorAborted";
+              error = "errorAborted";
               break;
             case v.error.MEDIA_ERR_NETWORK:
-              error = "statusErrorNetwork";
+              error = "errorNetwork";
               break;
             case v.error.MEDIA_ERR_DECODE:
-              error = "statusErrorDecode";
+              error = "errorDecode";
               break;
             case v.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
               error = v.networkState == v.NETWORK_NO_SOURCE ?
-                "statusErrorNoSource" :
-                "statusErrorSrcNotSupported";
+                "errorNoSource" :
+                "errorSrcNotSupported";
               break;
             default:
-              error = "statusErrorGeneric";
+              error = "errorGeneric";
               break;
           }
         } else if (v.networkState == v.NETWORK_NO_SOURCE) {
-          error = "statusErrorNoSource";
+          error = "errorNoSource";
         } else {
           return; // No error found.
         }
 
         let label = this.shadowRoot.getElementById(error);
         this.controlsSpacer.setAttribute("aria-label", label.textContent);
-        this.statusOverlay.setAttribute("status", error);
+        this.statusOverlay.setAttribute("error", error);
       },
 
       formatTime(aTime, showHours = false) {
         // Format the duration as "h:mm:ss" or "m:ss"
         aTime = Math.round(aTime / 1000);
         let hours = Math.floor(aTime / 3600);
         let mins  = Math.floor((aTime % 3600) / 60);
         let secs  = Math.floor(aTime % 60);
@@ -1963,17 +1936,16 @@ this.VideoControlsImplWidget = class {
         this.bufferBar = this.shadowRoot.getElementById("bufferBar");
         this.scrubberStack = this.shadowRoot.getElementById("scrubberStack");
         this.scrubber = this.shadowRoot.getElementById("scrubber");
         this.durationLabel = this.shadowRoot.getElementById("durationLabel");
         this.positionLabel = this.shadowRoot.getElementById("positionLabel");
         this.positionDurationBox = this.shadowRoot.getElementById("positionDurationBox");
         this.statusOverlay = this.shadowRoot.getElementById("statusOverlay");
         this.controlsOverlay = this.shadowRoot.getElementById("controlsOverlay");
-        this.pictureInPictureOverlay = this.shadowRoot.getElementById("pictureInPictureOverlay");
         this.controlsSpacer = this.shadowRoot.getElementById("controlsSpacer");
         this.clickToPlay = this.shadowRoot.getElementById("clickToPlay");
         this.fullscreenButton = this.shadowRoot.getElementById("fullscreenButton");
         this.castingButton = this.shadowRoot.getElementById("castingButton");
         this.closedCaptionButton = this.shadowRoot.getElementById("closedCaptionButton");
         this.textTrackList = this.shadowRoot.getElementById("textTrackList");
 
         if (this.positionDurationBox) {
@@ -2229,27 +2201,22 @@ this.VideoControlsImplWidget = class {
       <!ENTITY % videocontrolsDTD SYSTEM "chrome://global/locale/videocontrols.dtd">
       %videocontrolsDTD;
       ]>
       <div class="videocontrols" xmlns="http://www.w3.org/1999/xhtml" role="none">
         <link rel="stylesheet" type="text/css" href="chrome://global/skin/media/videocontrols.css" />
         <div id="controlsContainer" class="controlsContainer" role="none">
           <div id="statusOverlay" class="statusOverlay stackItem" hidden="true">
             <div id="statusIcon" class="statusIcon"></div>
-            <span class="statusLabel" id="statusErrorAborted">&error.aborted;</span>
-            <span class="statusLabel" id="statusErrorNetwork">&error.network;</span>
-            <span class="statusLabel" id="statusErrorDecode">&error.decode;</span>
-            <span class="statusLabel" id="statusErrorSrcNotSupported">&error.srcNotSupported;</span>
-            <span class="statusLabel" id="statusErrorNoSource">&error.noSource2;</span>
-            <span class="statusLabel" id="statusErrorGeneric">&error.generic;</span>
-          </div>
-
-          <div id="pictureInPictureOverlay" class="pictureInPictureOverlay stackItem" status="pictureInPicture" hidden="true">
-            <div class="statusIcon" type="pictureInPicture"></div>
-            <span class="statusLabel" id="statusPictureInPicture">&status.pictureInPicture;</span>
+            <span class="errorLabel" id="errorAborted">&error.aborted;</span>
+            <span class="errorLabel" id="errorNetwork">&error.network;</span>
+            <span class="errorLabel" id="errorDecode">&error.decode;</span>
+            <span class="errorLabel" id="errorSrcNotSupported">&error.srcNotSupported;</span>
+            <span class="errorLabel" id="errorNoSource">&error.noSource2;</span>
+            <span class="errorLabel" id="errorGeneric">&error.generic;</span>
           </div>
 
           <div id="controlsOverlay" class="controlsOverlay stackItem" role="none">
             <div class="controlsSpacerStack">
               <div id="controlsSpacer" class="controlsSpacer stackItem" role="none"></div>
               <div id="clickToPlay" class="clickToPlay" hidden="true"></div>
             </div>
 
@@ -2293,21 +2260,16 @@ this.VideoControlsImplWidget = class {
             </div>
             <div id="textTrackList" class="textTrackList" hidden="true" offlabel="&closedCaption.off;"></div>
           </div>
         </div>
       </div>`, "application/xml");
     this.shadowRoot.importNodeAndAppendChildAt(this.shadowRoot, parserDoc.documentElement, true);
   }
 
-  elementStateMatches(element) {
-    let elementInPiP = VideoControlsWidget.isPictureInPictureVideo(element);
-    return this.isShowingPictureInPictureMessage == elementInPiP;
-  }
-
   destructor() {
     this.Utils.terminate();
     this.TouchUtils.terminate();
     this.Utils.updateOrientationState(false);
   }
 
   _setupEventListeners() {
     this.shadowRoot.firstChild.addEventListener("mouseover", event => {
@@ -2325,17 +2287,17 @@ this.VideoControlsImplWidget = class {
     this.shadowRoot.firstChild.addEventListener("mousemove", event => {
       if (!this.Utils.isTouchControls) {
         this.Utils.onMouseMove(event);
       }
     });
   }
 };
 
-this.NoControlsMobileImplWidget = class {
+this.NoControlsImplWidget = class {
   constructor(shadowRoot) {
     this.shadowRoot = shadowRoot;
     this.element = shadowRoot.host;
     this.document = this.element.ownerDocument;
     this.window = this.document.defaultView;
   }
 
   onsetup() {
@@ -2430,20 +2392,16 @@ this.NoControlsMobileImplWidget = class 
           });
         }
       },
     };
     this.Utils.init(this.shadowRoot);
     this.Utils.video.dispatchEvent(new this.window.CustomEvent("MozNoControlsVideoBindingAttached"));
   }
 
-  elementStateMatches(element) {
-    return true;
-  }
-
   destructor() {
     this.Utils.terminate();
   }
 
   generateContent() {
     /*
      * Pass the markup through XML parser purely for the reason of loading the localization DTD.
      * Remove it when migrate to Fluent.
@@ -2461,51 +2419,8 @@ this.NoControlsMobileImplWidget = class 
               <div id="clickToPlay" class="clickToPlay"></div>
             </div>
           </div>
         </div>
       </div>`, "application/xml");
     this.shadowRoot.importNodeAndAppendChildAt(this.shadowRoot, parserDoc.documentElement, true);
   }
 };
-
-this.NoControlsPictureInPictureImplWidget = class {
-  constructor(shadowRoot) {
-    this.shadowRoot = shadowRoot;
-    this.element = shadowRoot.host;
-    this.document = this.element.ownerDocument;
-    this.window = this.document.defaultView;
-  }
-
-  onsetup() {
-    this.generateContent();
-  }
-
-  elementStateMatches(element) {
-    return true;
-  }
-
-  destructor() {
-  }
-
-  generateContent() {
-    /*
-     * Pass the markup through XML parser purely for the reason of loading the localization DTD.
-     * Remove it when migrate to Fluent.
-     */
-    const parser = new this.window.DOMParser();
-    let parserDoc = parser.parseFromString(`<!DOCTYPE bindings [
-      <!ENTITY % videocontrolsDTD SYSTEM "chrome://global/locale/videocontrols.dtd">
-      %videocontrolsDTD;
-      ]>
-      <div class="videocontrols" xmlns="http://www.w3.org/1999/xhtml" role="none">
-        <link rel="stylesheet" type="text/css" href="chrome://global/skin/media/videocontrols.css" />
-        <div id="controlsContainer" class="controlsContainer" role="none">
-          <div class="pictureInPictureOverlay stackItem" status="pictureInPicture">
-            <div id="statusIcon" class="statusIcon" type="pictureInPicture"></div>
-            <span class="statusLabel" id="statusPictureInPicture">&status.pictureInPicture;</span>
-          </div>
-          <div class="controlsOverlay stackItem"></div>
-        </div>
-      </div>`, "application/xml");
-    this.shadowRoot.importNodeAndAppendChildAt(this.shadowRoot, parserDoc.documentElement, true);
-  }
-};
--- a/toolkit/locales/en-US/chrome/global/videocontrols.dtd
+++ b/toolkit/locales/en-US/chrome/global/videocontrols.dtd
@@ -29,18 +29,16 @@
 
 <!ENTITY error.aborted "Video loading stopped.">
 <!ENTITY error.network "Video playback aborted due to a network error.">
 <!ENTITY error.decode "Video can’t be played because the file is corrupt.">
 <!ENTITY error.srcNotSupported "Video format or MIME type is not supported.">
 <!ENTITY error.noSource2 "No video with supported format and MIME type found.">
 <!ENTITY error.generic "Video playback aborted due to an unknown error.">
 
-<!ENTITY status.pictureInPicture "This video is playing in Picture-in-Picture mode.">
-
 <!-- LOCALIZATION NOTE (scrubberScale.nameFormat): the #1 string is the current
 media position, and the #2 string is the total duration. For example, when at
 the 5 minute mark in a 6 hour long video, #1 would be "5:00" and #2 would be
 "6:00:00", result string would be "5:00 of 6:00:00 elapsed".
 -->
 <!ENTITY scrubberScale.nameFormat "#1 of #2 elapsed">
 
 <!-- LOCALIZATION NOTE (positionAndDuration.nameFormat): the #1 string is the current
--- a/toolkit/themes/shared/jar.inc.mn
+++ b/toolkit/themes/shared/jar.inc.mn
@@ -102,11 +102,10 @@ toolkit.jar:
   skin/classic/global/plugins/plugin-blocked.svg            (../../shared/plugins/plugin-blocked.svg)
   skin/classic/global/plugins/pluginGeneric.svg             (../../shared/extensions/category-plugins.svg)
   skin/classic/global/plugins/pluginProblem.css             (../../shared/plugins/pluginProblem.css)
   skin/classic/global/plugins/contentPluginBlocked.png      (../../shared/plugins/contentPluginBlocked.png)
   skin/classic/global/plugins/contentPluginCrashed.png      (../../shared/plugins/contentPluginCrashed.png)
   skin/classic/global/plugins/contentPluginStripe.png       (../../shared/plugins/contentPluginStripe.png)
 #ifdef NIGHTLY_BUILD
   skin/classic/global/pictureinpicture/player.css           (../../shared/pictureinpicture/player.css)
-  skin/classic/global/media/pictureinpicture.svg            (../../shared/media/pictureinpicture.svg)
 #endif
 
deleted file mode 100644
--- a/toolkit/themes/shared/media/pictureinpicture.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
-  <g fill="none" fill-rule="evenodd" stroke="none" stroke-width="1">
-    <path stroke="context-stroke" d="M0.5 0.5h13v13h-13z"/>
-    <path fill="context-fill" d="M8 10h8v6h-8z"/>
-    <path stroke="context-stroke" d="M0.5 5.5h7v-5h-5.5a1.5 1.5 0 0 0 -1.5 1.5v3.5z"/>
-  </g>
-</svg>
\ No newline at end of file
--- a/toolkit/themes/shared/media/videocontrols.css
+++ b/toolkit/themes/shared/media/videocontrols.css
@@ -406,36 +406,21 @@
 .controlsContainer:not(.mobile) .statusIcon[type="throbber"] {
   background: url(chrome://global/skin/media/throbber.png) no-repeat center;
 }
 
 .controlsContainer:not(.mobile) .statusIcon[type="throbber"][stalled] {
   background: url(chrome://global/skin/media/stalled.png) no-repeat center;
 }
 
-.statusIcon[type="error"],
-.statusIcon[type="pictureInPicture"] {
-  background-size: contain;
-  background-repeat: no-repeat;
-  background-position: center;
-}
-
 .statusIcon[type="error"] {
   min-width: 70px;
   min-height: 60px;
-  background-image: url(chrome://global/skin/media/error.png);
-}
-
-.statusIcon[type="pictureInPicture"] {
-  min-width: 84px;
-  min-height: 84px;
-  background-image: url(chrome://global/skin/media/pictureinpicture.svg);
-  -moz-context-properties: fill, stroke;
-  fill: #fff;
-  stroke: #fff;
+  background: url(chrome://global/skin/media/error.png) no-repeat center;
+  background-size: contain;
 }
 
 /* Overlay Play button */
 .clickToPlay {
   min-width: var(--clickToPlay-size);
   min-height: var(--clickToPlay-size);
   border-radius: 50%;
   background-image: url(chrome://global/skin/media/playButton.svg);
@@ -463,45 +448,41 @@
   display: none;
 }
 
 .statusOverlay[fadeout],
 .statusOverlay[error] + .controlsOverlay > .controlsSpacerStack {
   opacity: 0;
 }
 
-.pictureInPictureOverlay {
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-  opacity: 1;
-  background-color: rgb(12, 12, 13);
-}
-
-/* Status description formatting */
-.statusLabel {
+/* Error description formatting */
+.errorLabel {
   padding: 0 10px;
   text-align: center;
   font: message-box;
   font-size: 14px;
   color: #ffffff;
 }
 
-.statusLabel {
+.errorLabel {
   display: none;
 }
 
-[status="errorAborted"]         > [id="statusErrorAborted"],
-[status="errorNetwork"]         > [id="statusErrorNetwork"],
-[status="errorDecode"]          > [id="statusErrorDecode"],
-[status="errorSrcNotSupported"] > [id="statusErrorSrcNotSupported"],
-[status="errorNoSource"]        > [id="statusErrorNoSource"],
-[status="errorGeneric"]         > [id="statusErrorGeneric"],
-[status="pictureInPicture"]     > [id="statusPictureInPicture"] {
+[error="errorAborted"]         > [anonid="errorAborted"],
+[error="errorNetwork"]         > [anonid="errorNetwork"],
+[error="errorDecode"]          > [anonid="errorDecode"],
+[error="errorSrcNotSupported"] > [anonid="errorSrcNotSupported"],
+[error="errorNoSource"]        > [anonid="errorNoSource"],
+[error="errorGeneric"]         > [anonid="errorGeneric"],
+[error="errorAborted"]         > [id="errorAborted"],
+[error="errorNetwork"]         > [id="errorNetwork"],
+[error="errorDecode"]          > [id="errorDecode"],
+[error="errorSrcNotSupported"] > [id="errorSrcNotSupported"],
+[error="errorNoSource"]        > [id="errorNoSource"],
+[error="errorGeneric"]         > [id="errorGeneric"] {
   display: inline;
 }
 
 %ifdef XP_WIN
 @media (-moz-windows-default-theme: 0) {
   .controlsSpacer,
   .clickToPlay {
     background-color: transparent;