1// Copyright (c) 2011 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 "base/basictypes.h" 6#include "components/autofill/content/renderer/page_click_listener.h" 7#include "components/autofill/content/renderer/page_click_tracker.h" 8#include "content/public/renderer/render_view.h" 9#include "content/public/test/render_view_test.h" 10#include "testing/gtest/include/gtest/gtest.h" 11#include "third_party/WebKit/public/web/WebDocument.h" 12#include "third_party/WebKit/public/web/WebInputElement.h" 13#include "third_party/WebKit/public/web/WebTextAreaElement.h" 14#include "third_party/WebKit/public/web/WebView.h" 15#include "third_party/WebKit/public/platform/WebSize.h" 16#include "ui/events/keycodes/keyboard_codes.h" 17 18namespace autofill { 19 20class TestPageClickListener : public PageClickListener { 21 public: 22 TestPageClickListener() 23 : form_control_element_clicked_called_(false), 24 form_control_element_lost_focus_called_(false), 25 was_focused_(false) { 26 } 27 28 virtual void FormControlElementClicked( 29 const blink::WebFormControlElement& element, 30 bool was_focused) OVERRIDE { 31 form_control_element_clicked_called_ = true; 32 form_control_element_clicked_ = element; 33 was_focused_ = was_focused; 34 } 35 36 virtual void FormControlElementLostFocus() OVERRIDE { 37 form_control_element_lost_focus_called_ = true; 38 } 39 40 void ClearResults() { 41 form_control_element_clicked_called_ = false; 42 form_control_element_lost_focus_called_ = false; 43 form_control_element_clicked_.reset(); 44 was_focused_ = false; 45 } 46 47 bool form_control_element_clicked_called_; 48 bool form_control_element_lost_focus_called_; 49 blink::WebFormControlElement form_control_element_clicked_; 50 bool was_focused_; 51}; 52 53class PageClickTrackerTest : public content::RenderViewTest { 54 protected: 55 virtual void SetUp() OVERRIDE { 56 content::RenderViewTest::SetUp(); 57 58 // RenderView creates PageClickTracker but it doesn't keep it around. 59 // Rather than make it do so for the test, we create a new object. 60 page_click_tracker_.reset(new PageClickTracker(view_, &test_listener_)); 61 62 LoadHTML("<form>" 63 " <input type='text' id='text_1'></input><br>" 64 " <input type='text' id='text_2'></input><br>" 65 " <textarea id='textarea_1'></textarea><br>" 66 " <textarea id='textarea_2'></textarea><br>" 67 " <input type='button' id='button'></input><br>" 68 "</form>"); 69 GetWebWidget()->resize(blink::WebSize(500, 500)); 70 GetWebWidget()->setFocus(true); 71 blink::WebDocument document = view_->GetWebView()->mainFrame()->document(); 72 text_ = document.getElementById("text_1"); 73 textarea_ = document.getElementById("textarea_1"); 74 ASSERT_FALSE(text_.isNull()); 75 ASSERT_FALSE(textarea_.isNull()); 76 } 77 78 virtual void TearDown() OVERRIDE { 79 text_.reset(); 80 textarea_.reset(); 81 test_listener_.ClearResults(); 82 page_click_tracker_.reset(); 83 content::RenderViewTest::TearDown(); 84 } 85 86 // Send all the messages required for a complete key press. 87 void SendKeyPress(int key_code) { 88 blink::WebKeyboardEvent keyboard_event; 89 keyboard_event.windowsKeyCode = key_code; 90 keyboard_event.setKeyIdentifierFromWindowsKeyCode(); 91 92 keyboard_event.type = blink::WebInputEvent::RawKeyDown; 93 SendWebKeyboardEvent(keyboard_event); 94 95 keyboard_event.type = blink::WebInputEvent::Char; 96 SendWebKeyboardEvent(keyboard_event); 97 98 keyboard_event.type = blink::WebInputEvent::KeyUp; 99 SendWebKeyboardEvent(keyboard_event); 100 } 101 102 scoped_ptr<PageClickTracker> page_click_tracker_; 103 TestPageClickListener test_listener_; 104 blink::WebElement text_; 105 blink::WebElement textarea_; 106}; 107 108// Tests that PageClickTracker does notify correctly when an input 109// node is clicked. 110TEST_F(PageClickTrackerTest, PageClickTrackerInputClicked) { 111 // Click the text field once. 112 EXPECT_TRUE(SimulateElementClick("text_1")); 113 EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); 114 EXPECT_FALSE(test_listener_.was_focused_); 115 EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); 116 test_listener_.ClearResults(); 117 118 // Click the text field again to test that was_focused_ is set correctly. 119 EXPECT_TRUE(SimulateElementClick("text_1")); 120 EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); 121 EXPECT_TRUE(test_listener_.was_focused_); 122 EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_); 123 test_listener_.ClearResults(); 124 125 // Click the button, no notification should happen (this is not a text-input). 126 EXPECT_TRUE(SimulateElementClick("button")); 127 EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); 128} 129 130// Tests that PageClickTracker does notify correctly when a textarea 131// node is clicked. 132TEST_F(PageClickTrackerTest, PageClickTrackerTextAreaClicked) { 133 // Click the textarea field once. 134 EXPECT_TRUE(SimulateElementClick("textarea_1")); 135 EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); 136 EXPECT_FALSE(test_listener_.was_focused_); 137 EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_); 138 test_listener_.ClearResults(); 139 140 // Click the textarea field again to test that was_focused_ is set correctly. 141 EXPECT_TRUE(SimulateElementClick("textarea_1")); 142 EXPECT_TRUE(test_listener_.form_control_element_clicked_called_); 143 EXPECT_TRUE(test_listener_.was_focused_); 144 EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_); 145 test_listener_.ClearResults(); 146 147 // Click the button, no notification should happen (this is not a text-input). 148 EXPECT_TRUE(SimulateElementClick("button")); 149 EXPECT_FALSE(test_listener_.form_control_element_clicked_called_); 150} 151 152TEST_F(PageClickTrackerTest, PageClickTrackerInputFocusLost) { 153 // Gain focus on the text field by using tab. 154 EXPECT_NE(text_, text_.document().focusedElement()); 155 SendKeyPress(ui::VKEY_TAB); 156 EXPECT_EQ(text_, text_.document().focusedElement()); 157 EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_); 158 159 // Click a button and ensure that the lost focus notification was sent, 160 // even though focus was gained without the mouse. 161 EXPECT_TRUE(SimulateElementClick("button")); 162 EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_); 163 test_listener_.ClearResults(); 164 165 // Click a text field and test that no lost focus notifications are sent. 166 EXPECT_TRUE(SimulateElementClick("text_1")); 167 EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_); 168 test_listener_.ClearResults(); 169 170 // Select another text field to test that the notification for the 171 // first text field losing focus is sent. 172 EXPECT_TRUE(SimulateElementClick("text_2")); 173 EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_); 174 test_listener_.ClearResults(); 175 176 // Click the button, a notification should happen since a text field has 177 // lost focus. 178 EXPECT_TRUE(SimulateElementClick("button")); 179 EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_); 180 test_listener_.ClearResults(); 181 182 // Click on a text field while the button has focus and ensure no lost focus 183 // notification is sent. 184 EXPECT_TRUE(SimulateElementClick("text_1")); 185 EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_); 186} 187 188TEST_F(PageClickTrackerTest, PageClickTrackerTextAreaFocusLost) { 189 // Gain focus on the textare field by using tab. 190 EXPECT_NE(textarea_, textarea_.document().focusedElement()); 191 SendKeyPress(ui::VKEY_TAB); 192 SendKeyPress(ui::VKEY_TAB); 193 SendKeyPress(ui::VKEY_TAB); 194 EXPECT_EQ(textarea_, textarea_.document().focusedElement()); 195 EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_); 196 197 // Click a button and ensure that the lost focus notification was sent, 198 // even though focus was gained without the mouse. 199 EXPECT_TRUE(SimulateElementClick("button")); 200 EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_); 201 test_listener_.ClearResults(); 202 203 // Click a textarea field and test that no lost focus notifications are sent. 204 EXPECT_TRUE(SimulateElementClick("textarea_1")); 205 EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_); 206 test_listener_.ClearResults(); 207 208 // Select another textarea field to test that the notification for the 209 // first textarea field losing focus is sent. 210 EXPECT_TRUE(SimulateElementClick("textarea_2")); 211 EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_); 212 test_listener_.ClearResults(); 213 214 // Click the button, a notification should happen since a textarea field has 215 // lost focus. 216 EXPECT_TRUE(SimulateElementClick("button")); 217 EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_); 218 test_listener_.ClearResults(); 219 220 // Click on a textarea field while the button has focus and ensure no lost 221 // focus notification is sent. 222 EXPECT_TRUE(SimulateElementClick("textarea_1")); 223 EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_); 224} 225 226} // namespace autofill 227