1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "DetailsFrame.h" 7 8 #include "mozilla/Attributes.h" 9 #include "mozilla/dom/HTMLDetailsElement.h" 10 #include "mozilla/dom/HTMLSummaryElement.h" 11 #include "nsContentUtils.h" 12 #include "nsPlaceholderFrame.h" 13 #include "nsTextNode.h" 14 15 using namespace mozilla; 16 using namespace mozilla::dom; 17 18 NS_IMPL_FRAMEARENA_HELPERS(DetailsFrame) 19 20 NS_QUERYFRAME_HEAD(DetailsFrame) 21 NS_QUERYFRAME_ENTRY(DetailsFrame) 22 NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator) 23 NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame) 24 25 nsBlockFrame* 26 NS_NewDetailsFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) 27 { 28 return new (aPresShell) DetailsFrame(aContext); 29 } 30 31 DetailsFrame::DetailsFrame(nsStyleContext* aContext) 32 : nsBlockFrame(aContext) 33 { 34 } 35 36 DetailsFrame::~DetailsFrame() 37 { 38 } 39 40 nsIAtom* 41 DetailsFrame::GetType() const 42 { 43 return nsGkAtoms::detailsFrame; 44 } 45 46 void 47 DetailsFrame::SetInitialChildList(ChildListID aListID, nsFrameList& aChildList) 48 { 49 #ifdef DEBUG 50 if (aListID == kPrincipalList) { 51 CheckValidMainSummary(aChildList); 52 } 53 #endif 54 dissect_bthci_sco(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)55 nsBlockFrame::SetInitialChildList(aListID, aChildList); 56 } 57 58 #ifdef DEBUG 59 bool 60 DetailsFrame::CheckValidMainSummary(const nsFrameList& aFrameList) const 61 { 62 for (nsIFrame* child : aFrameList) { 63 HTMLSummaryElement* summary = 64 HTMLSummaryElement::FromContent(child->GetContent()); 65 66 if (child == aFrameList.FirstChild()) { 67 if (summary && summary->IsMainSummary()) { 68 return true; 69 } else if (child->GetContent() == GetContent()) { 70 // The child frame's content is the same as our content, which means 71 // it's a kind of wrapper frame. Descend into its child list to find 72 // main summary. 73 if (CheckValidMainSummary(child->PrincipalChildList())) { 74 return true; 75 } 76 } 77 } else { 78 NS_ASSERTION(!summary || !summary->IsMainSummary(), 79 "Rest of the children are either not summary element " 80 "or are not the main summary!"); 81 } 82 } 83 return false; 84 } 85 #endif 86 87 void 88 DetailsFrame::DestroyFrom(nsIFrame* aDestructRoot) 89 { 90 nsContentUtils::DestroyAnonymousContent(&mDefaultSummary); 91 nsBlockFrame::DestroyFrom(aDestructRoot); 92 } 93 94 nsresult 95 DetailsFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements) 96 { 97 auto* details = HTMLDetailsElement::FromContent(GetContent()); 98 if (details->GetFirstSummary()) { 99 return NS_OK; 100 } 101 102 // The <details> element lacks any direct <summary> child. Create a default 103 // <summary> element as an anonymous content. 104 nsNodeInfoManager* nodeInfoManager = 105 GetContent()->NodeInfo()->NodeInfoManager(); 106 107 already_AddRefed<NodeInfo> nodeInfo = 108 nodeInfoManager->GetNodeInfo(nsGkAtoms::summary, nullptr, kNameSpaceID_XHTML, 109 nsIDOMNode::ELEMENT_NODE); 110 mDefaultSummary = new HTMLSummaryElement(nodeInfo); 111 112 nsXPIDLString defaultSummaryText; 113 nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES, 114 "DefaultSummary", defaultSummaryText); 115 RefPtr<nsTextNode> description = new nsTextNode(nodeInfoManager); 116 description->SetText(defaultSummaryText, false); 117 mDefaultSummary->AppendChildTo(description, false); 118 119 aElements.AppendElement(mDefaultSummary); 120 121 return NS_OK; 122 } 123 124 void 125 DetailsFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, 126 uint32_t aFilter) 127 { 128 if (mDefaultSummary) { 129 aElements.AppendElement(mDefaultSummary); 130 } 131 } 132