Convert PassRefPtr return types to RefPtr.
[WebKit-https.git] / Source / WebCore / html / HTMLSummaryElement.cpp
1 /*
2  * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include "HTMLSummaryElement.h"
23
24 #if ENABLE(DETAILS_ELEMENT)
25 #include "DetailsMarkerControl.h"
26 #include "HTMLDetailsElement.h"
27 #include "HTMLFormControlElement.h"
28 #include "InsertionPoint.h"
29 #include "KeyboardEvent.h"
30 #include "MouseEvent.h"
31 #include "NodeRenderingTraversal.h"
32 #include "PlatformMouseEvent.h"
33 #include "RenderBlockFlow.h"
34
35 namespace WebCore {
36
37 using namespace HTMLNames;
38
39 class SummaryContentElement final : public InsertionPoint {
40 public:
41     static RefPtr<SummaryContentElement> create(Document&);
42
43 private:
44     SummaryContentElement(Document& document)
45         : InsertionPoint(webkitShadowContentTag, document)
46     {
47     }
48 };
49
50 RefPtr<SummaryContentElement> SummaryContentElement::create(Document& document)
51 {
52     return adoptRef(new SummaryContentElement(document));
53 }
54
55 RefPtr<HTMLSummaryElement> HTMLSummaryElement::create(const QualifiedName& tagName, Document& document)
56 {
57     RefPtr<HTMLSummaryElement> summary = adoptRef(new HTMLSummaryElement(tagName, document));
58     summary->ensureUserAgentShadowRoot();
59     return summary;
60 }
61
62 HTMLSummaryElement::HTMLSummaryElement(const QualifiedName& tagName, Document& document)
63     : HTMLElement(tagName, document)
64 {
65     ASSERT(hasTagName(summaryTag));
66 }
67
68 RenderPtr<RenderElement> HTMLSummaryElement::createElementRenderer(PassRef<RenderStyle> style)
69 {
70     return createRenderer<RenderBlockFlow>(*this, WTF::move(style));
71 }
72
73 bool HTMLSummaryElement::childShouldCreateRenderer(const Node& child) const
74 {
75     if (child.isPseudoElement())
76         return HTMLElement::childShouldCreateRenderer(child);
77
78     return hasShadowRootOrActiveInsertionPointParent(child) && HTMLElement::childShouldCreateRenderer(child);
79 }
80
81 void HTMLSummaryElement::didAddUserAgentShadowRoot(ShadowRoot* root)
82 {
83     root->appendChild(DetailsMarkerControl::create(document()), ASSERT_NO_EXCEPTION);
84     root->appendChild(SummaryContentElement::create(document()), ASSERT_NO_EXCEPTION);
85 }
86
87 HTMLDetailsElement* HTMLSummaryElement::detailsElement() const
88 {
89     Node* mayDetails = NodeRenderingTraversal::parent(this);
90     if (!mayDetails || !mayDetails->hasTagName(detailsTag))
91         return nullptr;
92     return downcast<HTMLDetailsElement>(mayDetails);
93 }
94
95 bool HTMLSummaryElement::isMainSummary() const
96 {
97     if (HTMLDetailsElement* details = detailsElement())
98         return details->findMainSummary() == this;
99
100     return false;
101 }
102
103 static bool isClickableControl(Node* node)
104 {
105     ASSERT(node);
106     if (!is<Element>(*node))
107         return false;
108     Element& element = downcast<Element>(*node);
109     if (is<HTMLFormControlElement>(element))
110         return true;
111     Element* host = element.shadowHost();
112     return host && is<HTMLFormControlElement>(host);
113 }
114
115 bool HTMLSummaryElement::supportsFocus() const
116 {
117     return isMainSummary();
118 }
119
120 void HTMLSummaryElement::defaultEventHandler(Event* event)
121 {
122     if (isMainSummary() && renderer()) {
123         if (event->type() == eventNames().DOMActivateEvent && !isClickableControl(event->target()->toNode())) {
124             if (HTMLDetailsElement* details = detailsElement())
125                 details->toggleOpen();
126             event->setDefaultHandled();
127             return;
128         }
129
130         if (is<KeyboardEvent>(*event)) {
131             KeyboardEvent& keyboardEvent = downcast<KeyboardEvent>(*event);
132             if (keyboardEvent.type() == eventNames().keydownEvent && keyboardEvent.keyIdentifier() == "U+0020") {
133                 setActive(true, true);
134                 // No setDefaultHandled() - IE dispatches a keypress in this case.
135                 return;
136             }
137             if (keyboardEvent.type() == eventNames().keypressEvent) {
138                 switch (keyboardEvent.charCode()) {
139                 case '\r':
140                     dispatchSimulatedClick(event);
141                     keyboardEvent.setDefaultHandled();
142                     return;
143                 case ' ':
144                     // Prevent scrolling down the page.
145                     keyboardEvent.setDefaultHandled();
146                     return;
147                 }
148             }
149             if (keyboardEvent.type() == eventNames().keyupEvent && keyboardEvent.keyIdentifier() == "U+0020") {
150                 if (active())
151                     dispatchSimulatedClick(event);
152                 keyboardEvent.setDefaultHandled();
153                 return;
154             }
155         }
156     }
157
158     HTMLElement::defaultEventHandler(event);
159 }
160
161 bool HTMLSummaryElement::willRespondToMouseClickEvents()
162 {
163     if (isMainSummary() && renderer())
164         return true;
165
166     return HTMLElement::willRespondToMouseClickEvents();
167 }
168
169 }
170
171 #endif