Bug 1508000 - Dispatch UAWidgetUnbindFromTree event before calling nsGenericHTMLElement::UnbindFromTree() r=emilio
authorTimothy Guan-tin Chien <timdream@gmail.com>
Wed, 28 Nov 2018 02:29:38 +0000
changeset 504899 3d6e1fe4c371780a6bfcd9c33adce87dd4f38fc6
parent 504898 94ecc40729d0302ee3953dbab0d280d4a6b174c4
child 504900 d085db32a53d617676be6f855063d1499dbb1d71
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1508000
milestone65.0a1
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
Bug 1508000 - Dispatch UAWidgetUnbindFromTree event before calling nsGenericHTMLElement::UnbindFromTree() r=emilio Differential Revision: https://phabricator.services.mozilla.com/D12205
dom/html/HTMLInputElement.cpp
dom/html/HTMLMediaElement.cpp
toolkit/content/tests/widgets/mochitest.ini
toolkit/content/tests/widgets/test_ua_widget.html
toolkit/content/tests/widgets/test_ua_widget_sandbox.html
toolkit/content/tests/widgets/test_ua_widget_unbind.html
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -4689,41 +4689,40 @@ HTMLInputElement::UnbindFromTree(bool aD
   // nsGenericHTMLFormElementWithState::UnbindFromTree() will unset the form and
   // that takes care of form's WillRemove so we just have to take care
   // of the case where we're removing from the document and we don't
   // have a form
   if (!mForm && mType == NS_FORM_INPUT_RADIO) {
     WillRemoveFromRadioGroup();
   }
 
+  if (GetShadowRoot() && IsInComposedDoc()) {
+    nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
+      "HTMLInputElement::UnbindFromTree::UAWidgetUnbindFromTree",
+      [self = RefPtr<Element>(this)]() {
+        nsContentUtils::DispatchChromeEvent(
+          self->OwnerDoc(), self,
+          NS_LITERAL_STRING("UAWidgetUnbindFromTree"),
+          CanBubble::eYes, Cancelable::eNo);
+        self->UnattachShadow();
+      })
+    );
+  }
+
   nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
   nsGenericHTMLFormElementWithState::UnbindFromTree(aDeep, aNullParent);
 
   // GetCurrentDoc is returning nullptr so we can update the value
   // missing validity state to reflect we are no longer into a doc.
   UpdateValueMissingValidityState();
   // We might be no longer disabled because of parent chain changed.
   UpdateBarredFromConstraintValidation();
 
   // And now make sure our state is up to date
   UpdateState(false);
-
-  if (GetShadowRoot() && IsInComposedDoc()) {
-    RefPtr<Element> self = this;
-    nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
-      "HTMLInputElement::UnbindFromTree::UAWidgetUnbindFromTree",
-      [self]() {
-        nsContentUtils::DispatchChromeEvent(
-          self->OwnerDoc(), self,
-          NS_LITERAL_STRING("UAWidgetUnbindFromTree"),
-          CanBubble::eYes, Cancelable::eNo);
-        self->UnattachShadow();
-      })
-    );
-  }
 }
 
 void
 HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify)
 {
   uint8_t oldType = mType;
   MOZ_ASSERT(oldType != aNewType);
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4688,28 +4688,34 @@ HTMLMediaElement::ReportTelemetry()
 }
 
 void
 HTMLMediaElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   mUnboundFromTree = true;
   mVisibilityState = Visibility::UNTRACKED;
 
+  if (GetShadowRoot() && IsInComposedDoc()) {
+    nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
+      "HTMLMediaElement::UnbindFromTree::UAWidgetUnbindFromTree",
+      [self = RefPtr<Element>(this)]() {
+        nsContentUtils::DispatchChromeEvent(
+          self->OwnerDoc(), self,
+          NS_LITERAL_STRING("UAWidgetUnbindFromTree"),
+          CanBubble::eYes, Cancelable::eNo);
+        self->UnattachShadow();
+      })
+    );
+  }
+
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 
   MOZ_ASSERT(IsHidden());
   NotifyDecoderActivityChanges();
 
-  AsyncEventDispatcher* dispatcher =
-    new AsyncEventDispatcher(this,
-                             NS_LITERAL_STRING("UAWidgetUnbindFromTree"),
-                             CanBubble::eYes,
-                             ChromeOnlyDispatch::eYes);
-  dispatcher->RunDOMEventWhenSafe();
-
   RefPtr<HTMLMediaElement> self(this);
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableFunction("dom::HTMLMediaElement::UnbindFromTree", [self]() {
       if (self->mUnboundFromTree) {
         self->Pause();
       }
     });
   RunInStableState(task);
--- a/toolkit/content/tests/widgets/mochitest.ini
+++ b/toolkit/content/tests/widgets/mochitest.ini
@@ -20,42 +20,33 @@ support-files =
   videocontrols_direction-2b.html
   videocontrols_direction-2c.html
   videocontrols_direction-2d.html
   videocontrols_direction-2e.html
   videocontrols_direction_test.js
   videomask.css
 
 [test_audiocontrols_dimensions.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_mousecapture_area.html]
-skip-if = (verify && debug) || toolkit == 'android' # Bug 1483656 (android)
-[test_ua_widget.html]
-skip-if = toolkit == 'android' # Bug 1483656
+skip-if = (verify && debug)
+[test_ua_widget_sandbox.html]
+[test_ua_widget_unbind.html]
 [test_videocontrols.html]
 tags = fullscreen
 skip-if = toolkit == 'android' || (verify && debug && (os == 'linux')) #TIMED_OUT
 [test_videocontrols_keyhandler.html]
 skip-if = (toolkit == 'android') || (os == 'linux') #Bug 1366957
 [test_videocontrols_vtt.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_videocontrols_iframe_fullscreen.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_videocontrols_size.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_videocontrols_audio.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_videocontrols_audio_direction.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_videocontrols_jsdisabled.html]
-skip-if = toolkit == 'android' # bug 1272646 & bug 1483656
+skip-if = toolkit == 'android' # bug 1272646
 [test_videocontrols_standalone.html]
-skip-if = toolkit == 'android' # bug 1075573 & bug 1483656
+skip-if = toolkit == 'android' # bug 1075573
 [test_videocontrols_video_direction.html]
-skip-if = os == 'win' || toolkit == 'android' # Bug 1483656 (android)
+skip-if = os == 'win'
 [test_videocontrols_video_noaudio.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_bug898940.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_videocontrols_error.html]
-skip-if = toolkit == 'android' # Bug 1483656
 [test_videocontrols_orientation.html]
 skip-if = true # Bug 1483656
rename from toolkit/content/tests/widgets/test_ua_widget.html
rename to toolkit/content/tests/widgets/test_ua_widget_sandbox.html
--- a/toolkit/content/tests/widgets/test_ua_widget.html
+++ b/toolkit/content/tests/widgets/test_ua_widget_sandbox.html
@@ -1,12 +1,12 @@
 <!DOCTYPE HTML>
 <html>
 <head>
-  <title>UA Widget test</title>
+  <title>UA Widget sandbox test</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
   <script type="text/javascript" src="head.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/widgets/test_ua_widget_unbind.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>UA Widget unbind test</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
+  <script type="text/javascript" src="head.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+
+<div id="content">
+</div>
+
+<pre id="test">
+<script class="testbody">
+
+const content = document.getElementById("content");
+
+add_task(function() {
+  const video = document.createElement("video");
+  video.controls = true;
+  ok(!SpecialPowers.wrap(video).openOrClosedShadowRoot, "UA Widget Shadow Root is not created");
+  content.appendChild(video);
+  ok(!!SpecialPowers.wrap(video).openOrClosedShadowRoot, "UA Widget Shadow Root is created");
+  ok(!!SpecialPowers.wrap(video).openOrClosedShadowRoot.firstChild, "Widget is constructed");
+  content.removeChild(video);
+  ok(!SpecialPowers.wrap(video).openOrClosedShadowRoot, "UA Widget Shadow Root is removed");
+});
+
+add_task(function() {
+  const marquee = document.createElement("marquee");
+  ok(!SpecialPowers.wrap(marquee).openOrClosedShadowRoot, "UA Widget Shadow Root is not created");
+  content.appendChild(marquee);
+  ok(!!SpecialPowers.wrap(marquee).openOrClosedShadowRoot, "UA Widget Shadow Root is created");
+  ok(!!SpecialPowers.wrap(marquee).openOrClosedShadowRoot.firstChild, "Widget is constructed");
+  content.removeChild(marquee);
+  ok(SpecialPowers.wrap(marquee).openOrClosedShadowRoot, "UA Widget Shadow Root is not removed for marquee");
+});
+
+add_task(function() {
+  const input = document.createElement("input");
+  input.type = "date";
+  ok(!SpecialPowers.wrap(input).openOrClosedShadowRoot, "UA Widget Shadow Root is not created");
+  content.appendChild(input);
+  ok(!!SpecialPowers.wrap(input).openOrClosedShadowRoot, "UA Widget Shadow Root is created");
+  ok(!!SpecialPowers.wrap(input).openOrClosedShadowRoot.firstChild, "Widget is constructed");
+  content.removeChild(input);
+  ok(!SpecialPowers.wrap(input).openOrClosedShadowRoot, "UA Widget Shadow Root is removed");
+});
+
+</script>
+</pre>
+</body>
+</html>