1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/autofill/content/renderer/page_click_tracker.h"
7 #include "base/command_line.h"
8 #include "components/autofill/content/renderer/form_autofill_util.h"
9 #include "components/autofill/content/renderer/page_click_listener.h"
10 #include "components/autofill/core/common/autofill_switches.h"
11 #include "content/public/renderer/render_frame.h"
12 #include "content/public/renderer/render_view.h"
13 #include "third_party/WebKit/public/platform/WebPoint.h"
14 #include "third_party/WebKit/public/platform/WebSize.h"
15 #include "third_party/WebKit/public/web/WebDocument.h"
16 #include "third_party/WebKit/public/web/WebHitTestResult.h"
17 #include "third_party/WebKit/public/web/WebInputElement.h"
18 #include "third_party/WebKit/public/web/WebInputEvent.h"
19 #include "third_party/WebKit/public/web/WebLocalFrame.h"
20 #include "third_party/WebKit/public/web/WebTextAreaElement.h"
21 #include "third_party/WebKit/public/web/WebView.h"
23 using blink::WebElement
;
24 using blink::WebGestureEvent
;
25 using blink::WebInputElement
;
26 using blink::WebInputEvent
;
27 using blink::WebMouseEvent
;
29 using blink::WebPoint
;
31 using blink::WebTextAreaElement
;
35 // Casts |node| to a WebInputElement.
36 // Returns an empty (isNull()) WebInputElement if |node| is not a text field.
37 const WebInputElement
GetTextWebInputElement(const WebNode
& node
) {
38 if (!node
.isElementNode())
39 return WebInputElement();
40 const WebElement element
= node
.toConst
<WebElement
>();
41 if (!element
.hasHTMLTagName("input"))
42 return WebInputElement();
43 const WebInputElement
* input
= blink::toWebInputElement(&element
);
44 if (!autofill::IsTextInput(input
))
45 return WebInputElement();
49 // Casts |node| to a WebTextAreaElement.
50 // Returns an empty (isNull()) WebTextAreaElement if |node| is not a
52 const WebTextAreaElement
GetWebTextAreaElement(const WebNode
& node
) {
53 if (!node
.isElementNode())
54 return WebTextAreaElement();
55 const WebElement element
= node
.toConst
<WebElement
>();
56 if (!element
.hasHTMLTagName("textarea"))
57 return WebTextAreaElement();
58 return element
.toConst
<WebTextAreaElement
>();
65 PageClickTracker::PageClickTracker(content::RenderFrame
* render_frame
,
66 PageClickListener
* listener
)
67 : content::RenderFrameObserver(render_frame
),
68 focused_node_was_last_clicked_(false),
69 was_focused_before_now_(false),
74 PageClickTracker::~PageClickTracker() {
77 void PageClickTracker::OnMouseDown(const WebNode
& mouse_down_node
) {
78 focused_node_was_last_clicked_
= !mouse_down_node
.isNull() &&
79 mouse_down_node
.focused();
82 void PageClickTracker::FocusedNodeChanged(const WebNode
& node
) {
83 was_focused_before_now_
= false;
85 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
86 switches::kEnableAccessorySuggestionView
)) {
87 focused_node_was_last_clicked_
= true;
88 DoFocusChangeComplete();
92 void PageClickTracker::FocusChangeComplete() {
93 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
94 switches::kEnableAccessorySuggestionView
)) {
98 DoFocusChangeComplete();
101 void PageClickTracker::DoFocusChangeComplete() {
102 WebNode focused_node
= render_frame()->GetFocusedElement();
103 if (focused_node_was_last_clicked_
&& !focused_node
.isNull()) {
104 const WebInputElement input_element
= GetTextWebInputElement(focused_node
);
105 if (!input_element
.isNull()) {
106 listener_
->FormControlElementClicked(input_element
,
107 was_focused_before_now_
);
109 const WebTextAreaElement textarea_element
=
110 GetWebTextAreaElement(focused_node
);
111 if (!textarea_element
.isNull()) {
112 listener_
->FormControlElementClicked(textarea_element
,
113 was_focused_before_now_
);
118 was_focused_before_now_
= true;
119 focused_node_was_last_clicked_
= false;
122 // PageClickTracker::Legacy ----------------------------------------------------
124 PageClickTracker::Legacy::Legacy(PageClickTracker
* tracker
)
125 : content::RenderViewObserver(tracker
->render_frame()->GetRenderView()),
129 void PageClickTracker::Legacy::OnDestruct() {
130 // No-op. Don't delete |this|.
133 void PageClickTracker::Legacy::OnMouseDown(const WebNode
& mouse_down_node
) {
134 tracker_
->OnMouseDown(mouse_down_node
);
137 void PageClickTracker::Legacy::FocusChangeComplete() {
138 tracker_
->FocusChangeComplete();
141 } // namespace autofill