Bug 1116714 part 2 - Don't create a frame for the custom content container when it has no children. r=roc
☠☠ backed out by 1f32089c6733 ☠ ☠
authorMats Palmgren <mats@mozilla.com>
Tue, 06 Jan 2015 09:27:56 +0000
changeset 222206 5e51dc838a896d4aa649926ae9e763d1a657c169
parent 222205 652bd77f36c180084404def4d0f0748707b2c30e
child 222207 4d2d510fbd623a3799ffc501b8e3561201f8cc36
push id28059
push userryanvm@gmail.com
push dateTue, 06 Jan 2015 15:53:01 +0000
treeherdermozilla-central@4d91c33b351c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1116714
milestone37.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 1116714 part 2 - Don't create a frame for the custom content container when it has no children. r=roc
dom/base/nsDocument.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -5245,16 +5245,17 @@ already_AddRefed<AnonymousContent>
 nsIDocument::InsertAnonymousContent(Element& aElement, ErrorResult& aRv)
 {
   nsIPresShell* shell = GetShell();
   if (!shell || !shell->GetCanvasFrame()) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
+  nsAutoScriptBlocker scriptBlocker;
   nsCOMPtr<Element> container = shell->GetCanvasFrame()
                                      ->GetCustomContentContainer();
   if (!container) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   // Clone the node to avoid returning a direct reference
@@ -5269,29 +5270,32 @@ nsIDocument::InsertAnonymousContent(Elem
   if (NS_FAILED(rv)) {
     return nullptr;
   }
 
   nsRefPtr<AnonymousContent> anonymousContent =
     new AnonymousContent(clonedElement->AsElement());
   mAnonymousContents.AppendElement(anonymousContent);
 
+  shell->GetCanvasFrame()->ShowCustomContentContainer();
+
   return anonymousContent.forget();
 }
 
 void
 nsIDocument::RemoveAnonymousContent(AnonymousContent& aContent,
                                     ErrorResult& aRv)
 {
   nsIPresShell* shell = GetShell();
   if (!shell || !shell->GetCanvasFrame()) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
+  nsAutoScriptBlocker scriptBlocker;
   nsCOMPtr<Element> container = shell->GetCanvasFrame()
                                      ->GetCustomContentContainer();
   if (!container) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
   // Iterate over know customContents to get and remove the right one
@@ -5307,16 +5311,19 @@ nsIDocument::RemoveAnonymousContent(Anon
       container->RemoveChild(*node, aRv);
       if (aRv.Failed()) {
         return;
       }
 
       break;
     }
   }
+  if (mAnonymousContents.IsEmpty()) {
+    shell->GetCanvasFrame()->HideCustomContentContainer();
+  }
 }
 
 //
 // nsIDOMDocument interface
 //
 DocumentType*
 nsIDocument::GetDoctype() const
 {
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -48,16 +48,34 @@ NS_NewCanvasFrame(nsIPresShell* aPresShe
 
 NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame)
 
 NS_QUERYFRAME_HEAD(nsCanvasFrame)
   NS_QUERYFRAME_ENTRY(nsCanvasFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
+void
+nsCanvasFrame::ShowCustomContentContainer()
+{
+  if (mCustomContentContainer) {
+    mCustomContentContainer->UnsetAttr(kNameSpaceID_None, nsGkAtoms::hidden, true);
+  }
+}
+
+void
+nsCanvasFrame::HideCustomContentContainer()
+{
+  if (mCustomContentContainer) {
+    mCustomContentContainer->SetAttr(kNameSpaceID_None, nsGkAtoms::hidden,
+                                     NS_LITERAL_STRING("true"),
+                                     true);
+  }
+}
+
 nsresult
 nsCanvasFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   if (!mContent) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDocument> doc = mContent->OwnerDoc();
@@ -121,16 +139,21 @@ nsCanvasFrame::CreateAnonymousContent(ns
 
   // Append all existing AnonymousContent nodes stored at document level if any.
   int32_t anonymousContentCount = doc->GetAnonymousContents().Length();
   for (int32_t i = 0; i < anonymousContentCount; ++i) {
     nsCOMPtr<Element> node = doc->GetAnonymousContents()[i]->GetContentNode();
     mCustomContentContainer->AppendChildTo(node->AsContent(), true);
   }
 
+  // Only create a frame for mCustomContentContainer if it has some children.
+  if (anonymousContentCount <= 0) {
+    HideCustomContentContainer();
+  }
+
   return NS_OK;
 }
 
 void
 nsCanvasFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, uint32_t aFilter)
 {
   if (mTouchCaretElement) {
     aElements.AppendElement(mTouchCaretElement);
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -99,16 +99,28 @@ public:
     return mSelectionCaretsEndElement;
   }
 
   mozilla::dom::Element* GetCustomContentContainer() const
   {
     return mCustomContentContainer;
   }
 
+  /**
+   * Unhide the CustomContentContainer. This call only has an effect if
+   * mCustomContentContainer is non-null.
+   */
+  void ShowCustomContentContainer();
+
+  /**
+   * Hide the CustomContentContainer. This call only has an effect if
+   * mCustomContentContainer is non-null.
+   */
+  void HideCustomContentContainer();
+
   /** SetHasFocus tells the CanvasFrame to draw with focus ring
    *  @param aHasFocus true to show focus ring, false to hide it
    */
   NS_IMETHOD SetHasFocus(bool aHasFocus);
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE;