1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reserved.
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 *
24 */
25
26 #include "third_party/blink/renderer/core/html/forms/html_button_element.h"
27
28 #include "third_party/blink/renderer/core/dom/attribute.h"
29 #include "third_party/blink/renderer/core/events/keyboard_event.h"
30 #include "third_party/blink/renderer/core/frame/web_feature.h"
31 #include "third_party/blink/renderer/core/html/forms/form_data.h"
32 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
33 #include "third_party/blink/renderer/core/html_names.h"
34 #include "third_party/blink/renderer/core/layout/layout_object_factory.h"
35 #include "third_party/blink/renderer/core/style/computed_style.h"
36 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
37
38 namespace blink {
39
HTMLButtonElement(Document & document)40 HTMLButtonElement::HTMLButtonElement(Document& document)
41 : HTMLFormControlElement(html_names::kButtonTag, document),
42 type_(SUBMIT),
43 is_activated_submit_(false) {}
44
setType(const AtomicString & type)45 void HTMLButtonElement::setType(const AtomicString& type) {
46 setAttribute(html_names::kTypeAttr, type);
47 }
48
CreateLayoutObject(const ComputedStyle & style,LegacyLayout legacy)49 LayoutObject* HTMLButtonElement::CreateLayoutObject(const ComputedStyle& style,
50 LegacyLayout legacy) {
51 // https://html.spec.whatwg.org/C/#button-layout
52 EDisplay display = style.Display();
53 if (display == EDisplay::kInlineGrid || display == EDisplay::kGrid ||
54 display == EDisplay::kInlineFlex || display == EDisplay::kFlex ||
55 display == EDisplay::kInlineLayoutCustom ||
56 display == EDisplay::kLayoutCustom)
57 return HTMLFormControlElement::CreateLayoutObject(style, legacy);
58 return LayoutObjectFactory::CreateButton(*this, style, legacy);
59 }
60
FormControlType() const61 const AtomicString& HTMLButtonElement::FormControlType() const {
62 switch (type_) {
63 case SUBMIT: {
64 DEFINE_STATIC_LOCAL(const AtomicString, submit, ("submit"));
65 return submit;
66 }
67 case BUTTON: {
68 DEFINE_STATIC_LOCAL(const AtomicString, button, ("button"));
69 return button;
70 }
71 case RESET: {
72 DEFINE_STATIC_LOCAL(const AtomicString, reset, ("reset"));
73 return reset;
74 }
75 }
76
77 NOTREACHED();
78 return g_empty_atom;
79 }
80
IsPresentationAttribute(const QualifiedName & name) const81 bool HTMLButtonElement::IsPresentationAttribute(
82 const QualifiedName& name) const {
83 if (name == html_names::kAlignAttr) {
84 // Don't map 'align' attribute. This matches what Firefox and IE do, but
85 // not Opera. See http://bugs.webkit.org/show_bug.cgi?id=12071
86 return false;
87 }
88
89 return HTMLFormControlElement::IsPresentationAttribute(name);
90 }
91
ParseAttribute(const AttributeModificationParams & params)92 void HTMLButtonElement::ParseAttribute(
93 const AttributeModificationParams& params) {
94 if (params.name == html_names::kTypeAttr) {
95 if (EqualIgnoringASCIICase(params.new_value, "reset"))
96 type_ = RESET;
97 else if (EqualIgnoringASCIICase(params.new_value, "button"))
98 type_ = BUTTON;
99 else
100 type_ = SUBMIT;
101 UpdateWillValidateCache();
102 if (formOwner() && isConnected())
103 formOwner()->InvalidateDefaultButtonStyle();
104 } else {
105 if (params.name == html_names::kFormactionAttr)
106 LogUpdateAttributeIfIsolatedWorldAndInDocument("button", params);
107 HTMLFormControlElement::ParseAttribute(params);
108 }
109 }
110
DefaultEventHandler(Event & event)111 void HTMLButtonElement::DefaultEventHandler(Event& event) {
112 if (event.type() == event_type_names::kDOMActivate &&
113 !IsDisabledFormControl()) {
114 if (Form() && type_ == SUBMIT) {
115 Form()->PrepareForSubmission(&event, this);
116 event.SetDefaultHandled();
117 }
118 if (Form() && type_ == RESET) {
119 Form()->reset();
120 event.SetDefaultHandled();
121 }
122 }
123
124 if (HandleKeyboardActivation(event))
125 return;
126
127 HTMLFormControlElement::DefaultEventHandler(event);
128 }
129
HasActivationBehavior() const130 bool HTMLButtonElement::HasActivationBehavior() const {
131 return true;
132 }
133
WillRespondToMouseClickEvents()134 bool HTMLButtonElement::WillRespondToMouseClickEvents() {
135 if (!IsDisabledFormControl() && Form() && (type_ == SUBMIT || type_ == RESET))
136 return true;
137 return HTMLFormControlElement::WillRespondToMouseClickEvents();
138 }
139
CanBeSuccessfulSubmitButton() const140 bool HTMLButtonElement::CanBeSuccessfulSubmitButton() const {
141 return type_ == SUBMIT;
142 }
143
IsActivatedSubmit() const144 bool HTMLButtonElement::IsActivatedSubmit() const {
145 return is_activated_submit_;
146 }
147
SetActivatedSubmit(bool flag)148 void HTMLButtonElement::SetActivatedSubmit(bool flag) {
149 is_activated_submit_ = flag;
150 }
151
AppendToFormData(FormData & form_data)152 void HTMLButtonElement::AppendToFormData(FormData& form_data) {
153 if (type_ == SUBMIT && !GetName().IsEmpty() && is_activated_submit_)
154 form_data.AppendFromElement(GetName(), Value());
155 }
156
AccessKeyAction(bool send_mouse_events)157 void HTMLButtonElement::AccessKeyAction(bool send_mouse_events) {
158 focus();
159
160 DispatchSimulatedClick(
161 nullptr, send_mouse_events ? kSendMouseUpDownEvents : kSendNoEvents);
162 }
163
IsURLAttribute(const Attribute & attribute) const164 bool HTMLButtonElement::IsURLAttribute(const Attribute& attribute) const {
165 return attribute.GetName() == html_names::kFormactionAttr ||
166 HTMLFormControlElement::IsURLAttribute(attribute);
167 }
168
Value() const169 const AtomicString& HTMLButtonElement::Value() const {
170 return FastGetAttribute(html_names::kValueAttr);
171 }
172
RecalcWillValidate() const173 bool HTMLButtonElement::RecalcWillValidate() const {
174 return type_ == SUBMIT && HTMLFormControlElement::RecalcWillValidate();
175 }
176
DefaultTabIndex() const177 int HTMLButtonElement::DefaultTabIndex() const {
178 return 0;
179 }
180
IsInteractiveContent() const181 bool HTMLButtonElement::IsInteractiveContent() const {
182 return true;
183 }
184
MatchesDefaultPseudoClass() const185 bool HTMLButtonElement::MatchesDefaultPseudoClass() const {
186 // HTMLFormElement::findDefaultButton() traverses the tree. So we check
187 // canBeSuccessfulSubmitButton() first for early return.
188 return CanBeSuccessfulSubmitButton() && Form() &&
189 Form()->FindDefaultButton() == this;
190 }
191
InsertedInto(ContainerNode & insertion_point)192 Node::InsertionNotificationRequest HTMLButtonElement::InsertedInto(
193 ContainerNode& insertion_point) {
194 InsertionNotificationRequest request =
195 HTMLFormControlElement::InsertedInto(insertion_point);
196 LogAddElementIfIsolatedWorldAndInDocument("button", html_names::kTypeAttr,
197 html_names::kFormmethodAttr,
198 html_names::kFormactionAttr);
199 return request;
200 }
201
202 } // namespace blink
203