| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 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/message_loop.h" | |
| 6 #include "chrome/browser/browser.h" | |
| 7 #include "chrome/browser/find_notification_details.h" | |
| 8 #include "chrome/browser/renderer_host/render_view_host.h" | |
| 9 #include "chrome/browser/tab_contents/tab_contents.h" | |
| 10 #include "chrome/browser/tab_contents/web_contents.h" | |
| 11 #include "chrome/browser/tab_contents/tab_contents_view.h" | |
| 12 #include "chrome/browser/views/find_bar_win.h" | |
| 13 #include "chrome/common/notification_service.h" | |
| 14 #include "chrome/test/in_process_browser_test.h" | |
| 15 #include "chrome/test/ui_test_utils.h" | |
| 16 | |
| 17 const std::wstring kFramePage = L"files/find_in_page/frames.html"; | |
| 18 const std::wstring kFrameData = L"files/find_in_page/framedata_general.html"; | |
| 19 const std::wstring kUserSelectPage = L"files/find_in_page/user-select.html"; | |
| 20 const std::wstring kCrashPage = L"files/find_in_page/crash_1341577.html"; | |
| 21 const std::wstring kTooFewMatchesPage = L"files/find_in_page/bug_1155639.html"; | |
| 22 const std::wstring kEndState = L"files/find_in_page/end_state.html"; | |
| 23 | |
| 24 class FindInPageNotificationObserver : public NotificationObserver { | |
| 25 public: | |
| 26 explicit FindInPageNotificationObserver(TabContents* parent_tab) | |
| 27 : parent_tab_(parent_tab), | |
| 28 active_match_ordinal_(-1), | |
| 29 number_of_matches_(0) { | |
| 30 registrar_.Add(this, NotificationType::FIND_RESULT_AVAILABLE, | |
| 31 Source<TabContents>(parent_tab_)); | |
| 32 ui_test_utils::RunMessageLoop(); | |
| 33 } | |
| 34 | |
| 35 int active_match_ordinal() const { return active_match_ordinal_; } | |
| 36 | |
| 37 int number_of_matches() const { return number_of_matches_; } | |
| 38 | |
| 39 virtual void Observe(NotificationType type, const NotificationSource& source, | |
| 40 const NotificationDetails& details) { | |
| 41 if (type == NotificationType::FIND_RESULT_AVAILABLE) { | |
| 42 Details<FindNotificationDetails> find_details(details); | |
| 43 if (find_details->request_id() == kFindInPageRequestId) { | |
| 44 // We get multiple responses and one of those will contain the ordinal. | |
| 45 // This message comes to us before the final update is sent. | |
| 46 if (find_details->active_match_ordinal() > -1) | |
| 47 active_match_ordinal_ = find_details->active_match_ordinal(); | |
| 48 if (find_details->final_update()) { | |
| 49 number_of_matches_ = find_details->number_of_matches(); | |
| 50 MessageLoopForUI::current()->Quit(); | |
| 51 } else { | |
| 52 DLOG(INFO) << "Ignoring, since we only care about the final message"; | |
| 53 } | |
| 54 } | |
| 55 } else { | |
| 56 NOTREACHED(); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 // The Find mechanism is over asynchronous IPC, so a search is kicked off and | |
| 61 // we wait for notification to find out what the results are. As the user is | |
| 62 // typing, new search requests can be issued and the Request ID helps us make | |
| 63 // sense of whether this is the current request or an old one. The unit tests, | |
| 64 // however, which uses this constant issues only one search at a time, so we | |
| 65 // don't need a rolling id to identify each search. But, we still need to | |
| 66 // specify one, so we just use a fixed one - its value does not matter. | |
| 67 static const int kFindInPageRequestId; | |
| 68 | |
| 69 private: | |
| 70 NotificationRegistrar registrar_; | |
| 71 TabContents* parent_tab_; | |
| 72 // We will at some point (before final update) be notified of the ordinal and | |
| 73 // we need to preserve it so we can send it later. | |
| 74 int active_match_ordinal_; | |
| 75 int number_of_matches_; | |
| 76 }; | |
| 77 | |
| 78 typedef enum FindInPageDirection { BACK = 0, FWD = 1 }; | |
| 79 typedef enum FindInPageCase { IGNORE_CASE = 0, CASE_SENSITIVE = 1 }; | |
| 80 | |
| 81 class FindInPageControllerTest : public InProcessBrowserTest { | |
| 82 public: | |
| 83 FindInPageControllerTest() { | |
| 84 EnableDOMAutomation(); | |
| 85 } | |
| 86 | |
| 87 protected: | |
| 88 int FindInPage(const std::wstring& search_string, | |
| 89 FindInPageDirection forward, | |
| 90 FindInPageCase match_case, | |
| 91 bool find_next) { | |
| 92 WebContents* web_contents = | |
| 93 browser()->GetSelectedTabContents()->AsWebContents(); | |
| 94 if (web_contents) { | |
| 95 web_contents->set_current_find_request_id( | |
| 96 FindInPageNotificationObserver::kFindInPageRequestId); | |
| 97 web_contents->render_view_host()->StartFinding( | |
| 98 FindInPageNotificationObserver::kFindInPageRequestId, | |
| 99 search_string, forward == FWD, match_case == CASE_SENSITIVE, | |
| 100 find_next); | |
| 101 return FindInPageNotificationObserver(web_contents).number_of_matches(); | |
| 102 } | |
| 103 return 0; | |
| 104 } | |
| 105 }; | |
| 106 | |
| 107 // This test loads a page with frames and starts FindInPage requests. | |
| 108 IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindInPageFrames) { | |
| 109 HTTPTestServer* server = StartHTTPServer(); | |
| 110 | |
| 111 // First we navigate to our frames page. | |
| 112 GURL url = server->TestServerPageW(kFramePage); | |
| 113 ui_test_utils::NavigateToURL(browser(), url); | |
| 114 | |
| 115 // Try incremental search (mimicking user typing in). | |
| 116 EXPECT_EQ(18, FindInPage(L"g", FWD, IGNORE_CASE, false)); | |
| 117 EXPECT_EQ(11, FindInPage(L"go", FWD, IGNORE_CASE, false)); | |
| 118 EXPECT_EQ(04, FindInPage(L"goo", FWD, IGNORE_CASE, false)); | |
| 119 EXPECT_EQ(03, FindInPage(L"goog", FWD, IGNORE_CASE, false)); | |
| 120 EXPECT_EQ(02, FindInPage(L"googl", FWD, IGNORE_CASE, false)); | |
| 121 EXPECT_EQ(01, FindInPage(L"google", FWD, IGNORE_CASE, false)); | |
| 122 EXPECT_EQ(00, FindInPage(L"google!", FWD, IGNORE_CASE, false)); | |
| 123 | |
| 124 // Negative test (no matches should be found). | |
| 125 EXPECT_EQ(0, FindInPage(L"Non-existing string", FWD, IGNORE_CASE, false)); | |
| 126 | |
| 127 // 'horse' only exists in the three right frames. | |
| 128 EXPECT_EQ(3, FindInPage(L"horse", FWD, IGNORE_CASE, false)); | |
| 129 | |
| 130 // 'cat' only exists in the first frame. | |
| 131 EXPECT_EQ(1, FindInPage(L"cat", FWD, IGNORE_CASE, false)); | |
| 132 | |
| 133 // Try searching again, should still come up with 1 match. | |
| 134 EXPECT_EQ(1, FindInPage(L"cat", FWD, IGNORE_CASE, false)); | |
| 135 | |
| 136 // Try searching backwards, ignoring case, should still come up with 1 match. | |
| 137 EXPECT_EQ(1, FindInPage(L"CAT", BACK, IGNORE_CASE, false)); | |
| 138 | |
| 139 // Try case sensitive, should NOT find it. | |
| 140 EXPECT_EQ(0, FindInPage(L"CAT", FWD, CASE_SENSITIVE, false)); | |
| 141 | |
| 142 // Try again case sensitive, but this time with right case. | |
| 143 EXPECT_EQ(1, FindInPage(L"dog", FWD, CASE_SENSITIVE, false)); | |
| 144 | |
| 145 // Try non-Latin characters ('Hreggvidur' with 'eth' for 'd' in left frame). | |
| 146 EXPECT_EQ(1, FindInPage(L"Hreggvi\u00F0ur", FWD, IGNORE_CASE, false)); | |
| 147 EXPECT_EQ(1, FindInPage(L"Hreggvi\u00F0ur", FWD, CASE_SENSITIVE, false)); | |
| 148 EXPECT_EQ(0, FindInPage(L"hreggvi\u00F0ur", FWD, CASE_SENSITIVE, false)); | |
| 149 } | |
| 150 | |
| 151 std::string FocusedOnPage(WebContents* web_contents) { | |
| 152 ui_test_utils::JavaScriptRunner js_runner( | |
| 153 web_contents, | |
| 154 L"", | |
| 155 L"window.domAutomationController.send(getFocusedElement());"); | |
| 156 return js_runner.Run(); | |
| 157 } | |
| 158 | |
| 159 // This tests the FindInPage end-state, in other words: what is focused when you | |
| 160 // close the Find box (ie. if you find within a link the link should be | |
| 161 // focused). | |
| 162 // TODO(jcampan): This test needs to be enabled once Jay fixes the issues with | |
| 163 // running two InProc browser tests that both start a web server (crashes). | |
| 164 IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, DISABLED_FindInPageEndState) { | |
| 165 HTTPTestServer* server = StartHTTPServer(); | |
| 166 | |
| 167 // First we navigate to our special focus tracking page. | |
| 168 GURL url = server->TestServerPageW(kEndState); | |
| 169 ui_test_utils::NavigateToURL(browser(), url); | |
| 170 | |
| 171 WebContents* web_contents = | |
| 172 browser()->GetSelectedTabContents()->AsWebContents(); | |
| 173 ASSERT_TRUE(NULL != web_contents); | |
| 174 | |
| 175 // Verify that nothing has focus. | |
| 176 ASSERT_STREQ("{nothing focused}", FocusedOnPage(web_contents).c_str()); | |
| 177 | |
| 178 // Search for a text that exists within a link on the page. | |
| 179 EXPECT_EQ(1, FindInPage(L"nk", FWD, IGNORE_CASE, false)); | |
| 180 | |
| 181 // End the find session, which should set focus to the link. | |
| 182 web_contents->StopFinding(false); | |
| 183 | |
| 184 // Verify that the link is focused. | |
| 185 EXPECT_STREQ("link1", FocusedOnPage(web_contents).c_str()); | |
| 186 | |
| 187 // Search for a text that exists within a link on the page. | |
| 188 EXPECT_EQ(1, FindInPage(L"Google", FWD, IGNORE_CASE, false)); | |
| 189 | |
| 190 // Move the selection to link 1, after searching. | |
| 191 ui_test_utils::JavaScriptRunner js_runner( | |
| 192 web_contents, | |
| 193 L"", | |
| 194 L"window.domAutomationController.send(selectLink1());"); | |
| 195 js_runner.Run(); | |
| 196 | |
| 197 // End the find session. | |
| 198 web_contents->StopFinding(false); | |
| 199 | |
| 200 // Verify that link2 is not focused. | |
| 201 EXPECT_STREQ("", FocusedOnPage(web_contents).c_str()); | |
| 202 } | |
| OLD | NEW |