Bug 1497940 - add nsGenericHTMLElement::AttachAndSetUAShadowRoot helper method, r=smaug
authorAlexander Surkov <surkov.alexander@gmail.com>
Fri, 02 Nov 2018 12:18:20 +0800
changeset 444102 17f76aad81aa5027af1c769d647dcc1916403c9e
parent 444101 61f04931011f4fb778b77237e49d2bdd1f2e3aa2
child 444103 2be891b25f69091b7c8dd95c8289b87a930e55e4
push id34982
push useraciure@mozilla.com
push dateFri, 02 Nov 2018 16:45:16 +0000
treeherdermozilla-central@78ac2f95aa4e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1497940
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 1497940 - add nsGenericHTMLElement::AttachAndSetUAShadowRoot helper method, r=smaug
dom/base/Element.cpp
dom/base/Element.h
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1195,36 +1195,25 @@ Element::GetShadowRootByMode() const
   }
 
   /**
    * 3. Return shadow.
    */
   return shadowRoot;
 }
 
-// https://dom.spec.whatwg.org/#dom-element-attachshadow
-already_AddRefed<ShadowRoot>
-Element::AttachShadow(const ShadowRootInit& aInit, ErrorResult& aError)
+bool
+Element::CanAttachShadowDOM() const
 {
   /**
-   * 1. If context object’s namespace is not the HTML namespace,
-   *    then throw a "NotSupportedError" DOMException.
-   */
-  if (!IsHTMLElement() &&
-      !(XRE_IsParentProcess() && IsXULElement() && nsContentUtils::AllowXULXBLForPrincipal(NodePrincipal()))) {
-    aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-    return nullptr;
-  }
-
-  /**
-   * 2. If context object’s local name is not
-   *      a valid custom element name, "article", "aside", "blockquote",
-   *      "body", "div", "footer", "h1", "h2", "h3", "h4", "h5", "h6",
-   *      "header", "main" "nav", "p", "section", or "span",
-   *    then throw a "NotSupportedError" DOMException.
+   * If context object’s local name is not
+   *    a valid custom element name, "article", "aside", "blockquote",
+   *    "body", "div", "footer", "h1", "h2", "h3", "h4", "h5", "h6",
+   *    "header", "main" "nav", "p", "section", or "span",
+   *  return false.
    */
   nsAtom* nameAtom = NodeInfo()->NameAtom();
   if (!(nsContentUtils::IsCustomElementName(nameAtom, NodeInfo()->NamespaceID()) ||
         nameAtom == nsGkAtoms::article ||
         nameAtom == nsGkAtoms::aside ||
         nameAtom == nsGkAtoms::blockquote ||
         nameAtom == nsGkAtoms::body ||
         nameAtom == nsGkAtoms::div ||
@@ -1236,22 +1225,47 @@ Element::AttachShadow(const ShadowRootIn
         nameAtom == nsGkAtoms::h5 ||
         nameAtom == nsGkAtoms::h6 ||
         nameAtom == nsGkAtoms::header ||
         nameAtom == nsGkAtoms::main ||
         nameAtom == nsGkAtoms::nav ||
         nameAtom == nsGkAtoms::p ||
         nameAtom == nsGkAtoms::section ||
         nameAtom == nsGkAtoms::span)) {
+    return false;
+  }
+
+  return true;
+}
+
+// https://dom.spec.whatwg.org/#dom-element-attachshadow
+already_AddRefed<ShadowRoot>
+Element::AttachShadow(const ShadowRootInit& aInit, ErrorResult& aError)
+{
+  /**
+   * 1. If context object’s namespace is not the HTML namespace,
+   *    then throw a "NotSupportedError" DOMException.
+   */
+  if (!IsHTMLElement() &&
+      !(XRE_IsParentProcess() && IsXULElement() && nsContentUtils::AllowXULXBLForPrincipal(NodePrincipal()))) {
     aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return nullptr;
   }
 
   /**
-   * 3. If context object is a shadow host, then throw
+   * 2. If context object’s local name is not valid to attach shadow DOM to,
+   *    then throw a "NotSupportedError" DOMException.
+   */
+  if (!CanAttachShadowDOM()) {
+    aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return nullptr;
+  }
+
+  /**
+   * 2. If context object is a shadow host, then throw
    *    an "InvalidStateError" DOMException.
    */
   if (GetShadowRoot() || GetXBLBinding()) {
     aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
   if (StaticPrefs::dom_webcomponents_shadowdom_report_usage()) {
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1262,16 +1262,17 @@ public:
                                             ErrorResult& aError);
 
   MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRectList> GetClientRects();
   MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRect> GetBoundingClientRect();
 
   // Shadow DOM v1
   already_AddRefed<ShadowRoot> AttachShadow(const ShadowRootInit& aInit,
                                             ErrorResult& aError);
+  bool CanAttachShadowDOM() const;
 
   already_AddRefed<ShadowRoot> AttachShadowWithoutNameChecks(ShadowRootMode aMode);
   void UnattachShadow();
 
   ShadowRoot* GetShadowRootByMode() const;
   void SetSlot(const nsAString& aName, ErrorResult& aError);
   void GetSlot(nsAString& aName);
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4927,30 +4927,16 @@ HTMLMediaElement::AssertReadyStateIsNoth
                    int(mPreloadAction),
                    mSuspendedForPreloadNone,
                    GetError() ? GetError()->Code() : 0);
     MOZ_CRASH_UNSAFE_PRINTF("ReadyState should be HAVE_NOTHING! %s", buf);
   }
 #endif
 }
 
-void
-HTMLMediaElement::AttachAndSetUAShadowRoot()
-{
-  if (GetShadowRoot()) {
-    MOZ_ASSERT(GetShadowRoot()->IsUAWidget());
-    return;
-  }
-
-  // Add a closed shadow root to host video controls
-  RefPtr<ShadowRoot> shadowRoot =
-    AttachShadowWithoutNameChecks(ShadowRootMode::Closed);
-  shadowRoot->SetIsUAWidget();
-}
-
 nsresult
 HTMLMediaElement::InitializeDecoderAsClone(ChannelMediaDecoder* aOriginal)
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
   NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder");
   AssertReadyStateIsNothing();
 
   MediaDecoderInit decoderInit(this,
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1898,19 +1898,16 @@ private:
   // A pending seek promise which is created at Seek() method call and is
   // resolved/rejected at AsyncResolveSeekDOMPromiseIfExists()/
   // AsyncRejectSeekDOMPromiseIfExists() methods.
   RefPtr<dom::Promise> mSeekDOMPromise;
 
   // For debugging bug 1407148.
   void AssertReadyStateIsNothing();
 
-  // Attach UA Shadow Root if it is not attached.
-  void AttachAndSetUAShadowRoot();
-
   // Contains the unique id of the sink device and the device info.
   // The initial value is ("", nullptr) and the default output device is used.
   // It can contain an invalid id and info if the device has been
   // unplugged. It can be set to ("", nullptr). It follows the spec attribute:
   // https://w3c.github.io/mediacapture-output/#htmlmediaelement-extensions
   // Read/Write from the main thread only.
   Pair<nsString, RefPtr<AudioDeviceInfo>> mSink;
 };
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2887,16 +2887,31 @@ nsGenericHTMLElement::GetWidthHeightForI
 }
 
 bool
 nsGenericHTMLElement::IsEventAttributeNameInternal(nsAtom *aName)
 {
   return nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML);
 }
 
+void
+nsGenericHTMLElement::AttachAndSetUAShadowRoot()
+{
+  MOZ_DIAGNOSTIC_ASSERT(!CanAttachShadowDOM(),
+                        "Cannot be used to attach UI shadow DOM");
+  if (GetShadowRoot()) {
+    MOZ_ASSERT(GetShadowRoot()->IsUAWidget());
+    return;
+  }
+
+  RefPtr<ShadowRoot> shadowRoot =
+    AttachShadowWithoutNameChecks(ShadowRootMode::Closed);
+  shadowRoot->SetIsUAWidget();
+}
+
 /**
  * Construct a URI from a string, as an element.src attribute
  * would be set to. Helper for the media elements.
  */
 nsresult
 nsGenericHTMLElement::NewURIFromString(const nsAString& aURISpec,
                                        nsIURI** aURI)
 {
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -251,16 +251,19 @@ public:
   }
 
   template<typename First, typename... Args>
   inline bool IsAnyOfHTMLElements(First aFirst, Args... aArgs) const
   {
     return IsNodeInternal(aFirst, aArgs...);
   }
 
+  // Attach UA Shadow Root if it is not attached.
+  void AttachAndSetUAShadowRoot();
+
 protected:
   virtual ~nsGenericHTMLElement() {}
 
 public:
   /**
    * Get width and height, using given image request if attributes are unset.
    * Pass a reference to the image request, since the method may change the
    * value and we want to use the updated value.