• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "components/autofill/content/renderer/page_click_tracker.h"
6 
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "components/autofill/content/renderer/form_autofill_util.h"
10 #include "components/autofill/content/renderer/page_click_listener.h"
11 #include "content/public/renderer/render_view.h"
12 #include "third_party/WebKit/public/platform/WebString.h"
13 #include "third_party/WebKit/public/web/WebDOMMouseEvent.h"
14 #include "third_party/WebKit/public/web/WebDocument.h"
15 #include "third_party/WebKit/public/web/WebInputElement.h"
16 #include "third_party/WebKit/public/web/WebInputEvent.h"
17 #include "third_party/WebKit/public/web/WebLocalFrame.h"
18 #include "third_party/WebKit/public/web/WebTextAreaElement.h"
19 #include "third_party/WebKit/public/web/WebView.h"
20 
21 using blink::WebDOMEvent;
22 using blink::WebDOMMouseEvent;
23 using blink::WebElement;
24 using blink::WebFormControlElement;
25 using blink::WebFrame;
26 using blink::WebGestureEvent;
27 using blink::WebInputElement;
28 using blink::WebInputEvent;
29 using blink::WebMouseEvent;
30 using blink::WebNode;
31 using blink::WebString;
32 using blink::WebTextAreaElement;
33 using blink::WebView;
34 
35 namespace {
36 
37 // Casts |node| to a WebInputElement.
38 // Returns an empty (isNull()) WebInputElement if |node| is not a text field.
GetTextWebInputElement(const WebNode & node)39 const WebInputElement GetTextWebInputElement(const WebNode& node) {
40   if (!node.isElementNode())
41     return WebInputElement();
42   const WebElement element = node.toConst<WebElement>();
43   if (!element.hasHTMLTagName("input"))
44     return WebInputElement();
45   const WebInputElement* input = blink::toWebInputElement(&element);
46   if (!autofill::IsTextInput(input))
47     return WebInputElement();
48   return *input;
49 }
50 
51 // Casts |node| to a WebTextAreaElement.
52 // Returns an empty (isNull()) WebTextAreaElement if |node| is not a
53 // textarea field.
GetWebTextAreaElement(const WebNode & node)54 const WebTextAreaElement GetWebTextAreaElement(const WebNode& node) {
55   if (!node.isElementNode())
56     return WebTextAreaElement();
57   const WebElement element = node.toConst<WebElement>();
58   if (!element.hasHTMLTagName("textarea"))
59     return WebTextAreaElement();
60   return element.toConst<WebTextAreaElement>();
61 }
62 
63 }  // namespace
64 
65 namespace autofill {
66 
PageClickTracker(content::RenderView * render_view,PageClickListener * listener)67 PageClickTracker::PageClickTracker(content::RenderView* render_view,
68                                    PageClickListener* listener)
69     : content::RenderViewObserver(render_view),
70       was_focused_before_now_(false),
71       listener_(listener),
72       weak_ptr_factory_(this) {
73 }
74 
~PageClickTracker()75 PageClickTracker::~PageClickTracker() {
76 }
77 
DidHandleMouseEvent(const WebMouseEvent & event)78 void PageClickTracker::DidHandleMouseEvent(const WebMouseEvent& event) {
79   if (event.type != WebInputEvent::MouseDown ||
80       event.button != WebMouseEvent::ButtonLeft) {
81     return;
82   }
83 
84   PotentialActivationAt(event.x, event.y);
85 }
86 
DidHandleGestureEvent(const blink::WebGestureEvent & event)87 void PageClickTracker::DidHandleGestureEvent(
88     const blink::WebGestureEvent& event) {
89   if (event.type != blink::WebGestureEvent::GestureTap)
90     return;
91 
92   PotentialActivationAt(event.x, event.y);
93 }
94 
FocusedNodeChanged(const blink::WebNode & node)95 void PageClickTracker::FocusedNodeChanged(const blink::WebNode& node) {
96   was_focused_before_now_ = false;
97   // If the focus change was a result of handling a click or tap, we'll soon get
98   // an associated event. Reset |was_focused_before_now_| to true only after the
99   // message loop unwinds.
100   base::MessageLoop::current()->PostTask(
101       FROM_HERE,
102       base::Bind(&PageClickTracker::SetWasFocused,
103                  weak_ptr_factory_.GetWeakPtr()));
104 }
105 
PotentialActivationAt(int x,int y)106 void PageClickTracker::PotentialActivationAt(int x, int y) {
107   blink::WebNode focused_node = render_view()->GetFocusedElement();
108   if (focused_node.isNull())
109     return;
110 
111   if (!render_view()->NodeContainsPoint(focused_node, gfx::Point(x, y)))
112     return;
113 
114   const WebInputElement input_element = GetTextWebInputElement(focused_node);
115   if (!input_element.isNull()) {
116     listener_->FormControlElementClicked(input_element,
117                                          was_focused_before_now_);
118     return;
119   }
120 
121   const WebTextAreaElement textarea_element =
122       GetWebTextAreaElement(focused_node);
123   if (!textarea_element.isNull()) {
124     listener_->FormControlElementClicked(textarea_element,
125                                          was_focused_before_now_);
126   }
127 }
128 
SetWasFocused()129 void PageClickTracker::SetWasFocused() {
130   was_focused_before_now_ = true;
131 }
132 
133 }  // namespace autofill
134