// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <string> #include "base/file_path.h" #include "base/path_service.h" #include "base/stringprintf.h" #include "chrome/browser/automation/automation_tab_helper.h" #include "chrome/browser/automation/mock_tab_event_observer.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/url_constants.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/common/notification_details.h" #include "content/common/notification_observer.h" #include "content/common/notification_registrar.h" #include "content/common/notification_service.h" #include "content/common/notification_source.h" #include "content/common/notification_type.h" #include "net/base/net_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using testing::_; class MockNotificationObserver : public NotificationObserver { public: MockNotificationObserver() { } virtual ~MockNotificationObserver() { } MOCK_METHOD3(Observe, void(NotificationType type, const NotificationSource& source, const NotificationDetails& details)); void Register(NotificationType type, const NotificationSource& source) { registrar_.Add(this, type, source); } private: NotificationRegistrar registrar_; DISALLOW_COPY_AND_ASSIGN(MockNotificationObserver); }; class AutomationTabHelperBrowserTest : public InProcessBrowserTest { public: AutomationTabHelperBrowserTest() { EnableDOMAutomation(); } virtual ~AutomationTabHelperBrowserTest() { } void SetUpInProcessBrowserTestFixture() { EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_)); test_data_dir_ = test_data_dir_.AppendASCII("automation"); } // Add default expectations for a client redirection initiated by script, // and quit the message loop when the redirect has completed. This expects // that the tab receives news of the redirect before the script returns. void ExpectClientRedirectAndBreak( MockTabEventObserver* mock_tab_observer, MockNotificationObserver* mock_notification_observer) { mock_notification_observer->Register( NotificationType::DOM_OPERATION_RESPONSE, NotificationService::AllSources()); testing::InSequence expect_in_sequence; EXPECT_CALL(*mock_tab_observer, OnFirstPendingLoad(_)); EXPECT_CALL(*mock_notification_observer, Observe( testing::Eq(NotificationType::DOM_OPERATION_RESPONSE), _, _)); EXPECT_CALL(*mock_tab_observer, OnNoMorePendingLoads(_)) .WillOnce(testing::InvokeWithoutArgs( MessageLoopForUI::current(), &MessageLoop::Quit)); } // Executes javascript to execute a given test case found in the current // page's script. If |wait_for_response| is true, this method will not // return until the javascript has been executed. // Use with [ASSERT|EXPECT]_NO_FATAL_FAILURE. void RunTestCaseInJavaScript(int test_case_number, bool wait_for_response) { std::string script = base::StringPrintf("runTestCase(%d);", test_case_number); RenderViewHost* host = browser()->GetSelectedTabContents()->render_view_host(); if (wait_for_response) { ASSERT_TRUE(ui_test_utils::ExecuteJavaScript( host, L"", ASCIIToWide(script))); } else { script += "window.domAutomationController.setAutomationId(0);" "window.domAutomationController.send(0);"; host->ExecuteJavascriptInWebFrame(ASCIIToUTF16(""), ASCIIToUTF16(script)); } } // Returns the |AutomationTabHelper| for the first browser's first tab. AutomationTabHelper* tab_helper() { return browser()->GetTabContentsWrapperAt(0)->automation_tab_helper(); } protected: FilePath test_data_dir_; }; IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, FormSubmission) { ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( test_data_dir_.AppendASCII("client_redirects.html"))); MockNotificationObserver mock_notification_observer; MockTabEventObserver mock_observer(tab_helper()); ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer); ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(1, false)); ui_test_utils::RunMessageLoop(); } IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, CancelFormSubmission) { ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( test_data_dir_.AppendASCII("client_redirects.html"))); MockNotificationObserver mock_notification_observer; MockTabEventObserver mock_observer(tab_helper()); testing::InSequence expect_in_sequence; EXPECT_CALL(mock_observer, OnFirstPendingLoad(_)).Times(0); ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(2, true)); } IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, JsRedirectToSite) { ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( test_data_dir_.AppendASCII("client_redirects.html"))); MockNotificationObserver mock_notification_observer; MockTabEventObserver mock_observer(tab_helper()); ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer); ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(3, false)); ui_test_utils::RunMessageLoop(); } IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, JsRedirectToUnknownSite) { ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( test_data_dir_.AppendASCII("client_redirects.html"))); MockNotificationObserver mock_notification_observer; MockTabEventObserver mock_observer(tab_helper()); ExpectClientRedirectAndBreak(&mock_observer, &mock_notification_observer); ASSERT_NO_FATAL_FAILURE(RunTestCaseInJavaScript(4, false)); ui_test_utils::RunMessageLoop(); } IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, MetaTagRedirect) { MockTabEventObserver mock_observer(tab_helper()); testing::InSequence expect_in_sequence; EXPECT_CALL(mock_observer, OnFirstPendingLoad(_)); EXPECT_CALL(mock_observer, OnNoMorePendingLoads(_)); ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( browser(), net::FilePathToFileURL(test_data_dir_.AppendASCII("meta_redirect.html")), 2); } // Tests that the load stop event occurs after the window onload handler. IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, LoadStopComesAfterOnLoad) { MockNotificationObserver mock_notification_observer; mock_notification_observer.Register(NotificationType::DOM_OPERATION_RESPONSE, NotificationService::AllSources()); MockTabEventObserver mock_tab_observer(tab_helper()); EXPECT_CALL(mock_tab_observer, OnFirstPendingLoad(_)); { testing::InSequence expect_in_sequence; EXPECT_CALL(mock_notification_observer, Observe( testing::Eq(NotificationType::DOM_OPERATION_RESPONSE), _, _)); EXPECT_CALL(mock_tab_observer, OnNoMorePendingLoads(_)); } ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL( test_data_dir_.AppendASCII("sends_message_on_load.html"))); } // Tests that a crashed tab reports that it has stopped loading. IN_PROC_BROWSER_TEST_F(AutomationTabHelperBrowserTest, CrashedTabStopsLoading) { MockTabEventObserver mock_tab_observer(tab_helper()); testing::InSequence expect_in_sequence; EXPECT_CALL(mock_tab_observer, OnFirstPendingLoad(_)); EXPECT_CALL(mock_tab_observer, OnNoMorePendingLoads(_)); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutCrashURL)); }