Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/generic/DetailsFrame.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "DetailsFrame.h"
8
9
#include "mozilla/Attributes.h"
10
#include "mozilla/dom/HTMLDetailsElement.h"
11
#include "mozilla/dom/HTMLSummaryElement.h"
12
#include "nsContentUtils.h"
13
#include "nsPlaceholderFrame.h"
14
#include "nsTextNode.h"
15
16
using namespace mozilla;
17
using namespace mozilla::dom;
18
19
NS_IMPL_FRAMEARENA_HELPERS(DetailsFrame)
20
21
0
NS_QUERYFRAME_HEAD(DetailsFrame)
22
0
  NS_QUERYFRAME_ENTRY(DetailsFrame)
23
0
  NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
24
0
NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
25
26
nsBlockFrame*
27
NS_NewDetailsFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle)
28
0
{
29
0
  return new (aPresShell) DetailsFrame(aStyle);
30
0
}
31
32
namespace mozilla {
33
34
DetailsFrame::DetailsFrame(ComputedStyle* aStyle)
35
  : nsBlockFrame(aStyle, kClassID)
36
0
{
37
0
}
38
39
DetailsFrame::~DetailsFrame()
40
0
{
41
0
}
42
43
void
44
DetailsFrame::SetInitialChildList(ChildListID aListID, nsFrameList& aChildList)
45
0
{
46
#ifdef DEBUG
47
  if (aListID == kPrincipalList) {
48
    CheckValidMainSummary(aChildList);
49
  }
50
#endif
51
52
0
  nsBlockFrame::SetInitialChildList(aListID, aChildList);
53
0
}
54
55
#ifdef DEBUG
56
bool
57
DetailsFrame::CheckValidMainSummary(const nsFrameList& aFrameList) const
58
{
59
  for (nsIFrame* child : aFrameList) {
60
    HTMLSummaryElement* summary =
61
      HTMLSummaryElement::FromNode(child->GetContent());
62
63
    if (child == aFrameList.FirstChild()) {
64
      if (summary && summary->IsMainSummary()) {
65
        return true;
66
      } else if (child->GetContent() == GetContent()) {
67
        // The child frame's content is the same as our content, which means
68
        // it's a kind of wrapper frame. Descend into its child list to find
69
        // main summary.
70
        if (CheckValidMainSummary(child->PrincipalChildList())) {
71
          return true;
72
        }
73
      }
74
    } else {
75
      NS_ASSERTION(!summary || !summary->IsMainSummary(),
76
                   "Rest of the children are either not summary element "
77
                   "or are not the main summary!");
78
    }
79
  }
80
  return false;
81
}
82
#endif
83
84
void
85
DetailsFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
86
0
{
87
0
  aPostDestroyData.AddAnonymousContent(mDefaultSummary.forget());
88
0
  nsBlockFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
89
0
}
90
91
nsresult
92
DetailsFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
93
0
{
94
0
  auto* details = HTMLDetailsElement::FromNode(GetContent());
95
0
  if (details->GetFirstSummary()) {
96
0
    return NS_OK;
97
0
  }
98
0
99
0
  // The <details> element lacks any direct <summary> child. Create a default
100
0
  // <summary> element as an anonymous content.
101
0
  nsNodeInfoManager* nodeInfoManager =
102
0
    GetContent()->NodeInfo()->NodeInfoManager();
103
0
104
0
  RefPtr<NodeInfo> nodeInfo =
105
0
    nodeInfoManager->GetNodeInfo(nsGkAtoms::summary, nullptr, kNameSpaceID_XHTML,
106
0
                                 nsINode::ELEMENT_NODE);
107
0
  mDefaultSummary = new HTMLSummaryElement(nodeInfo.forget());
108
0
109
0
  nsAutoString defaultSummaryText;
110
0
  nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
111
0
                                     "DefaultSummary", defaultSummaryText);
112
0
  RefPtr<nsTextNode> description = new nsTextNode(nodeInfoManager);
113
0
  description->SetText(defaultSummaryText, false);
114
0
  mDefaultSummary->AppendChildTo(description, false);
115
0
116
0
  aElements.AppendElement(mDefaultSummary);
117
0
118
0
  return NS_OK;
119
0
}
120
121
void
122
DetailsFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
123
                                       uint32_t aFilter)
124
0
{
125
0
  if (mDefaultSummary) {
126
0
    aElements.AppendElement(mDefaultSummary);
127
0
  }
128
0
}
129
130
bool
131
DetailsFrame::HasMainSummaryFrame(nsIFrame* aSummaryFrame)
132
0
{
133
0
  const ChildListIDs flowLists(kPrincipalList | kOverflowList);
134
0
  for (nsIFrame* frag = this; frag; frag = frag->GetNextInFlow()) {
135
0
    for (ChildListIterator lists(frag); !lists.IsDone(); lists.Next()) {
136
0
      if (!flowLists.Contains(lists.CurrentID())) {
137
0
        continue;
138
0
      }
139
0
      for (nsIFrame* child : lists.CurrentList()) {
140
0
        child = nsPlaceholderFrame::GetRealFrameFor(child);
141
0
        // We skip any non-primary frames such as a list-style-position:inside
142
0
        // bullet frame for the <details> itself.
143
0
        if (child->IsPrimaryFrame()) {
144
0
          return aSummaryFrame == child;
145
0
        }
146
0
      }
147
0
    }
148
0
  }
149
0
  return false;
150
0
}
151
152
} // namespace mozilla