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