// Copyright (c) 2012 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 #include "base/file_path.h" #include "base/path_service.h" #include "base/string16.h" #include "base/stringprintf.h" #include "base/utf_string_conversions.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/browser_tabstrip.h" #include "chrome/browser/ui/tab_contents/tab_contents.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.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 content::NotificationObserver { public: MockNotificationObserver() { } virtual ~MockNotificationObserver() { } MOCK_METHOD3(Observe, void(int type, const content::NotificationSource& source, const content::NotificationDetails& details)); void Register(int type, const content::NotificationSource& source) { registrar_.Add(this, type, source); } private: content::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( content::NOTIFICATION_DOM_OPERATION_RESPONSE, content::NotificationService::AllSources()); testing::InSequence expect_in_sequence; EXPECT_CALL(*mock_tab_observer, OnFirstPendingLoad(_)); EXPECT_CALL(*mock_notification_observer, Observe( testing::Eq( static_cast(content::NOTIFICATION_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); content::RenderViewHost* host = chrome::GetActiveWebContents(browser())->GetRenderViewHost(); 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(string16(), ASCIIToUTF16(script)); } } // Returns the |AutomationTabHelper| for the first browser's first tab. AutomationTabHelper* tab_helper() { return chrome::GetTabContentsAt(browser(), 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( content::NOTIFICATION_DOM_OPERATION_RESPONSE, content::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( static_cast(content::NOTIFICATION_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::kChromeUICrashURL)); }