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 <string> 6 7 #include "base/file_path.h" 8 #include "base/path_service.h" 9 #include "base/stringprintf.h" 10 #include "chrome/browser/automation/automation_tab_helper.h" 11 #include "chrome/browser/automation/mock_tab_event_observer.h" 12 #include "chrome/browser/ui/browser.h" 13 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 14 #include "chrome/common/chrome_paths.h" 15 #include "chrome/common/url_constants.h" 16 #include "chrome/test/in_process_browser_test.h" 17 #include "chrome/test/ui_test_utils.h" 18 #include "content/browser/renderer_host/render_view_host.h" 19 #include "content/browser/tab_contents/tab_contents.h" 20 #include "content/common/notification_details.h" 21 #include "content/common/notification_observer.h" 22 #include "content/common/notification_registrar.h" 23 #include "content/common/notification_service.h" 24 #include "content/common/notification_source.h" 25 #include "content/common/notification_type.h" 26 #include "net/base/net_util.h" 27 #include "testing/gmock/include/gmock/gmock.h" 28 #include "testing/gtest/include/gtest/gtest.h" 29 30 using testing::_; 31 32 class MockNotificationObserver : public NotificationObserver { 33 public: 34 MockNotificationObserver() { } 35 virtual ~MockNotificationObserver() { } 36 37 MOCK_METHOD3(Observe, void(NotificationType type, 38 const NotificationSource& source, 39 const NotificationDetails& details)); 40 41 void Register(NotificationType type, const NotificationSource& source) { 42 registrar_.Add(this, type, source); 43 } 44 45 private: 46 NotificationRegistrar registrar_; 47 48 DISALLOW_COPY_AND_ASSIGN(MockNotificationObserver); 49 }; 50 51 class AutomationTabHelperBrowserTest : public InProcessBrowserTest { 52 public: 53 AutomationTabHelperBrowserTest() { 54 EnableDOMAutomation(); 55 } 56 virtual ~AutomationTabHelperBrowserTest() { } 57 58 void SetUpInProcessBrowserTestFixture() { 59 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_)); 60 test_data_dir_ = test_data_dir_.AppendASCII("automation"); 61 } 62 63 // Add default expectations for a client redirection initiated by script, 64 // and quit the message loop when the redirect has completed. This expects 65 // that the tab receives news of the redirect before the script returns. 66 void ExpectClientRedirectAndBreak( 67 MockTabEventObserver* mock_tab_observer, 68 MockNotificationObserver* mock_notification_observer) { 69 mock_notification_observer->Register( 70 NotificationType::DOM_OPERATION_RESPONSE, 71 NotificationService::AllSources()); 72 73 testing::InSequence expect_in_sequence; 74 EXPECT_CALL(*mock_tab_observer, OnFirstPendingLoad(_)); 75 EXPECT_CALL(*mock_notification_observer, Observe( 76 testing::Eq(NotificationType::DOM_OPERATION_RESPONSE), _, _)); 77 EXPECT_CALL(*mock_tab_observer, OnNoMorePendingLoads(_)) 78 .WillOnce(testing::InvokeWithoutArgs( 79 MessageLoopForUI::current(), &MessageLoop::Quit)); 80 } 81 82 // Executes javascript to execute a given test case found in the current 83 // page's script. If |wait_for_response| is true, this method will not 84 // return until the javascript has been executed. 85 // Use with [ASSERT|EXPECT]_NO_FATAL_FAILURE. 86 void RunTestCaseInJavaScript(int test_case_number, bool wait_for_response) { 87 std::string script = base::StringPrintf("runTestCase(%d);", 88 test_case_number); 89 RenderViewHost* host = 90 browser()->GetSelectedTabContents()->render_view_host(); 91 if (wait_for_response) { 92 ASSERT_TRUE(ui_test_utils::ExecuteJavaScript( 93 host, L"", ASCIIToWide(script))); 94 } else { 95 script += "window.domAutomationController.setAutomationId(0);" 96 "window.domAutomationController.send(0);"; 97 host->ExecuteJavascriptInWebFrame(ASCIIToUTF16(""), ASCIIToUTF16(script)); 98 } 99 } 100 101 // Returns the |AutomationTabHelper| for the first browser's first tab. 102 AutomationTabHelper* tab_helper() { 103 return browser()->GetTabContentsWrapperAt(0)->automation_tab_helper(); 104 } 105 106 protected: 107 FilePath test_data_dir_; 108 }; 109 110 IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, FormSubmission) { 111 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( 112 test_data_dir_.AppendASCII("client_redirects.html"))); 113 114 MockNotificationObserver mock_notification_observer; 115 MockTabEventObserver mock_observer(tab_helper()); 116 117 ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer); 118 119 ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(1, false)); 120 ui_test_utils::RunMessageLoop(); 121 } 122 123 IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, 124 CancelFormSubmission) { 125 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( 126 test_data_dir_.AppendASCII("client_redirects.html"))); 127 128 MockNotificationObserver mock_notification_observer; 129 MockTabEventObserver mock_observer(tab_helper()); 130 131 testing::InSequence expect_in_sequence; 132 EXPECT_CALL(mock_observer, OnFirstPendingLoad(_)).Times(0); 133 134 ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(2, true)); 135 } 136 137 IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, 138 JsRedirectToSite) { 139 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( 140 test_data_dir_.AppendASCII("client_redirects.html"))); 141 142 MockNotificationObserver mock_notification_observer; 143 MockTabEventObserver mock_observer(tab_helper()); 144 145 ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer); 146 147 ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(3, false)); 148 ui_test_utils::RunMessageLoop(); 149 } 150 151 IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, 152 JsRedirectToUnknownSite) { 153 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( 154 test_data_dir_.AppendASCII("client_redirects.html"))); 155 156 MockNotificationObserver mock_notification_observer; 157 MockTabEventObserver mock_observer(tab_helper()); 158 159 ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer); 160 161 ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(4, false)); 162 ui_test_utils::RunMessageLoop(); 163 } 164 165 IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, 166 MetaTagRedirect) { 167 MockTabEventObserver mock_observer(tab_helper()); 168 169 testing::InSequence expect_in_sequence; 170 EXPECT_CALL(mock_observer, OnFirstPendingLoad(_)); 171 EXPECT_CALL(mock_observer, OnNoMorePendingLoads(_)); 172 173 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( 174 browser(), 175 net::FilePathToFileURL(test_data_dir_.AppendASCII("meta_redirect.html")), 176 2); 177 } 178 179 // Tests that the load stop event occurs after the window onload handler. 180 IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, 181 LoadStopComesAfterOnLoad) { 182 MockNotificationObserver mock_notification_observer; 183 mock_notification_observer.Register(NotificationType::DOM_OPERATION_RESPONSE, 184 NotificationService::AllSources()); 185 MockTabEventObserver mock_tab_observer(tab_helper()); 186 187 EXPECT_CALL(mock_tab_observer, OnFirstPendingLoad(_)); 188 { 189 testing::InSequence expect_in_sequence; 190 EXPECT_CALL(mock_notification_observer, Observe( 191 testing::Eq(NotificationType::DOM_OPERATION_RESPONSE), _, _)); 192 EXPECT_CALL(mock_tab_observer, OnNoMorePendingLoads(_)); 193 } 194 195 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( 196 test_data_dir_.AppendASCII("sends_message_on_load.html"))); 197 } 198 199 // Tests that a crashed tab reports that it has stopped loading. 200 IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, 201 CrashedTabStopsLoading) { 202 MockTabEventObserver mock_tab_observer(tab_helper()); 203 204 testing::InSequence expect_in_sequence; 205 EXPECT_CALL(mock_tab_observer, OnFirstPendingLoad(_)); 206 EXPECT_CALL(mock_tab_observer, OnNoMorePendingLoads(_)); 207 208 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutCrashURL)); 209 } 210