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