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/WebView.h" 14 #include "third_party/WebKit/public/platform/WebSize.h" 15 #include "ui/events/keycodes/keyboard_codes.h" 16 17 namespace autofill { 18 19 class TestPageClickListener : public PageClickListener { 20 public: 21 TestPageClickListener() 22 : input_element_clicked_called_(false), 23 input_element_lost_focus_called_(false), 24 was_focused_(false), 25 is_focused_(false) { 26 } 27 28 virtual void InputElementClicked(const blink::WebInputElement& element, 29 bool was_focused, 30 bool is_focused) OVERRIDE { 31 input_element_clicked_called_ = true; 32 element_clicked_ = element; 33 was_focused_ = was_focused; 34 is_focused_ = is_focused; 35 } 36 37 virtual void InputElementLostFocus() OVERRIDE { 38 input_element_lost_focus_called_ = true; 39 } 40 41 void ClearResults() { 42 input_element_clicked_called_ = false; 43 input_element_lost_focus_called_ = false; 44 element_clicked_.reset(); 45 was_focused_ = false; 46 is_focused_ = false; 47 } 48 49 bool input_element_clicked_called_; 50 bool input_element_lost_focus_called_; 51 blink::WebInputElement element_clicked_; 52 bool was_focused_; 53 bool is_focused_; 54 }; 55 56 class PageClickTrackerTest : public content::RenderViewTest { 57 protected: 58 virtual void SetUp() OVERRIDE { 59 content::RenderViewTest::SetUp(); 60 61 // RenderView creates PageClickTracker but it doesn't keep it around. 62 // Rather than make it do so for the test, we create a new object. 63 page_click_tracker_.reset(new PageClickTracker(view_, &test_listener_)); 64 65 LoadHTML("<form>" 66 " <input type='text' id='text_1'></input><br>" 67 " <input type='text' id='text_2'></input><br>" 68 " <input type='button' id='button'></input><br>" 69 "</form>"); 70 GetWebWidget()->resize(blink::WebSize(500, 500)); 71 GetWebWidget()->setFocus(true); 72 blink::WebDocument document = view_->GetWebView()->mainFrame()->document(); 73 text_ = document.getElementById("text_1"); 74 ASSERT_FALSE(text_.isNull()); 75 } 76 77 virtual void TearDown() OVERRIDE { 78 text_.reset(); 79 test_listener_.ClearResults(); 80 page_click_tracker_.reset(); 81 content::RenderViewTest::TearDown(); 82 } 83 84 // Send all the messages required for a complete key press. 85 void SendKeyPress(int key_code) { 86 blink::WebKeyboardEvent keyboard_event; 87 keyboard_event.windowsKeyCode = key_code; 88 keyboard_event.setKeyIdentifierFromWindowsKeyCode(); 89 90 keyboard_event.type = blink::WebInputEvent::RawKeyDown; 91 SendWebKeyboardEvent(keyboard_event); 92 93 keyboard_event.type = blink::WebInputEvent::Char; 94 SendWebKeyboardEvent(keyboard_event); 95 96 keyboard_event.type = blink::WebInputEvent::KeyUp; 97 SendWebKeyboardEvent(keyboard_event); 98 } 99 100 scoped_ptr<PageClickTracker> page_click_tracker_; 101 TestPageClickListener test_listener_; 102 blink::WebElement text_; 103 }; 104 105 // Tests that PageClickTracker does notify correctly when a node is clicked. 106 TEST_F(PageClickTrackerTest, PageClickTrackerInputClicked) { 107 // Click the text field once. 108 EXPECT_TRUE(SimulateElementClick("text_1")); 109 EXPECT_TRUE(test_listener_.input_element_clicked_called_); 110 EXPECT_FALSE(test_listener_.was_focused_); 111 EXPECT_TRUE(test_listener_.is_focused_); 112 EXPECT_TRUE(text_ == test_listener_.element_clicked_); 113 test_listener_.ClearResults(); 114 115 // Click the text field again to test that was_focused_ is set correctly. 116 EXPECT_TRUE(SimulateElementClick("text_1")); 117 EXPECT_TRUE(test_listener_.input_element_clicked_called_); 118 EXPECT_TRUE(test_listener_.was_focused_); 119 EXPECT_TRUE(test_listener_.is_focused_); 120 EXPECT_TRUE(text_ == test_listener_.element_clicked_); 121 test_listener_.ClearResults(); 122 123 // Click the button, no notification should happen (this is not a text-input). 124 EXPECT_TRUE(SimulateElementClick("button")); 125 EXPECT_FALSE(test_listener_.input_element_clicked_called_); 126 } 127 128 TEST_F(PageClickTrackerTest, PageClickTrackerInputFocusLost) { 129 // Gain focus on the text field by using tab. 130 EXPECT_NE(text_, text_.document().focusedNode()); 131 SendKeyPress(ui::VKEY_TAB); 132 EXPECT_EQ(text_, text_.document().focusedNode()); 133 EXPECT_FALSE(test_listener_.input_element_lost_focus_called_); 134 135 // Click a button and ensure that the lost focus notification was sent, 136 // even though focus was gained without the mouse. 137 EXPECT_TRUE(SimulateElementClick("button")); 138 EXPECT_TRUE(test_listener_.input_element_lost_focus_called_); 139 test_listener_.ClearResults(); 140 141 // Click a text field and test that no lost focus notifications are sent. 142 EXPECT_TRUE(SimulateElementClick("text_1")); 143 EXPECT_FALSE(test_listener_.input_element_lost_focus_called_); 144 test_listener_.ClearResults(); 145 146 // Select another text field to test that the notifcation for the 147 // first text field losing focus is sent. 148 EXPECT_TRUE(SimulateElementClick("text_2")); 149 EXPECT_TRUE(test_listener_.input_element_lost_focus_called_); 150 test_listener_.ClearResults(); 151 152 // Click the button, a notification should happen since a text field has 153 // lost focus. 154 EXPECT_TRUE(SimulateElementClick("button")); 155 EXPECT_TRUE(test_listener_.input_element_lost_focus_called_); 156 test_listener_.ClearResults(); 157 158 // Click on a text field while the button has focus and ensure no lost focus 159 // notification is sent. 160 EXPECT_TRUE(SimulateElementClick("text_1")); 161 EXPECT_FALSE(test_listener_.input_element_lost_focus_called_); 162 } 163 164 } // namespace autofill 165