// 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 #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/string16.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_common_test.h" #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/personal_data_manager.h" #include "chrome/browser/net/predictor_api.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/translate/translate_infobar_delegate.h" #include "chrome/browser/translate/translate_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/render_messages.h" #include "chrome/renderer/translate_helper.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/browser/renderer_host/mock_render_process_host.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/test/test_url_fetcher_factory.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/keycodes/keyboard_codes.h" static const char* kDataURIPrefix = "data:text/html;charset=utf-8,"; static const char* kTestFormString = "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "
"; class AutofillTest : public InProcessBrowserTest { protected: AutofillTest() { set_show_window(true); EnableDOMAutomation(); } void CreateTestProfile() { autofill_test::DisableSystemServices(browser()->profile()); AutofillProfile profile; autofill_test::SetProfileInfo( &profile, "Milton", "C.", "Waddams", "red.swingline@initech.com", "Initech", "4120 Freidrich Lane", "Basement", "Austin", "Texas", "78744", "United States", "5125551234", "5125550000"); PersonalDataManager* personal_data_manager = browser()->profile()->GetPersonalDataManager(); ASSERT_TRUE(personal_data_manager); personal_data_manager->AddProfile(profile); } void ExpectFieldValue(const std::wstring& field_name, const std::string& expected_value) { std::string value; ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( browser()->GetSelectedTabContents()->render_view_host(), L"", L"window.domAutomationController.send(" L"document.getElementById('" + field_name + L"').value);", &value)); EXPECT_EQ(expected_value, value); } RenderViewHost* render_view_host() { return browser()->GetSelectedTabContents()->render_view_host(); } void SimulateURLFetch(bool success) { TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher); net::URLRequestStatus status; status.set_status(success ? net::URLRequestStatus::SUCCESS : net::URLRequestStatus::FAILED); std::string script = " var google = {};" "google.translate = (function() {" " return {" " TranslateService: function() {" " return {" " isAvailable : function() {" " return true;" " }," " restore : function() {" " return;" " }," " getDetectedLanguage : function() {" " return \"ja\";" " }," " translatePage : function(originalLang, targetLang," " onTranslateProgress) {" " document.getElementsByTagName(\"body\")[0].innerHTML = '" + std::string(kTestFormString) + " ';" " onTranslateProgress(100, true, false);" " }" " };" " }" " };" "})();"; fetcher->delegate()->OnURLFetchComplete(fetcher, fetcher->original_url(), status, success ? 200 : 500, net::ResponseCookies(), script); } void FocusFirstNameField() { LOG(WARNING) << "Clicking on the tab."; ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER)); ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER_FOCUS_VIEW)); LOG(WARNING) << "Focusing the first name field."; bool result = false; ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( render_view_host(), L"", L"if (document.readyState === 'complete')" L" document.getElementById('firstname').focus();" L"else" L" domAutomationController.send(false);", &result)); ASSERT_TRUE(result); } void ExpectFilledTestForm() { ExpectFieldValue(L"firstname", "Milton"); ExpectFieldValue(L"lastname", "Waddams"); ExpectFieldValue(L"address1", "4120 Freidrich Lane"); ExpectFieldValue(L"address2", "Basement"); ExpectFieldValue(L"city", "Austin"); ExpectFieldValue(L"state", "TX"); ExpectFieldValue(L"zip", "78744"); ExpectFieldValue(L"country", "US"); ExpectFieldValue(L"phone", "5125551234"); } void TryBasicFormFill() { FocusFirstNameField(); // Start filling the first name field with "M" and wait for the popup to be // shown. LOG(WARNING) << "Typing 'M' to bring up the Autofill popup."; ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_M, false, true, false, false, chrome::NOTIFICATION_AUTOFILL_DID_SHOW_SUGGESTIONS, Source(render_view_host()))); // Press the down arrow to select the suggestion and preview the autofilled // form. LOG(WARNING) << "Simulating down arrow press to initiate Autofill preview."; ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_DOWN, false, false, false, false, chrome::NOTIFICATION_AUTOFILL_DID_FILL_FORM_DATA, Source(render_view_host()))); // The previewed values should not be accessible to JavaScript. ExpectFieldValue(L"firstname", "M"); ExpectFieldValue(L"lastname", ""); ExpectFieldValue(L"address1", ""); ExpectFieldValue(L"address2", ""); ExpectFieldValue(L"city", ""); ExpectFieldValue(L"state", ""); ExpectFieldValue(L"zip", ""); ExpectFieldValue(L"country", ""); ExpectFieldValue(L"phone", ""); // TODO(isherman): It would be nice to test that the previewed values are // displayed: http://crbug.com/57220 // Press Enter to accept the autofill suggestions. LOG(WARNING) << "Simulating Return press to fill the form."; ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_RETURN, false, false, false, false, chrome::NOTIFICATION_AUTOFILL_DID_FILL_FORM_DATA, Source(render_view_host()))); // The form should be filled. ExpectFilledTestForm(); } private: TestURLFetcherFactory url_fetcher_factory_; }; // Test that basic form fill is working. IN_PROC_BROWSER_TEST_F(AutofillTest, BasicFormFill) { CreateTestProfile(); // Load the test page. ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(std::string(kDataURIPrefix) + kTestFormString))); // Invoke Autofill. TryBasicFormFill(); } // Test that form filling can be initiated by pressing the down arrow. IN_PROC_BROWSER_TEST_F(AutofillTest, AutofillViaDownArrow) { CreateTestProfile(); // Load the test page. ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(std::string(kDataURIPrefix) + kTestFormString))); // Focus a fillable field. FocusFirstNameField(); // Press the down arrow to initiate Autofill and wait for the popup to be // shown. ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_DOWN, false, false, false, false, chrome::NOTIFICATION_AUTOFILL_DID_SHOW_SUGGESTIONS, Source(render_view_host()))); // Press the down arrow to select the suggestion and preview the autofilled // form. ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_DOWN, false, false, false, false, chrome::NOTIFICATION_AUTOFILL_DID_FILL_FORM_DATA, Source(render_view_host()))); // Press Enter to accept the autofill suggestions. ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_RETURN, false, false, false, false, chrome::NOTIFICATION_AUTOFILL_DID_FILL_FORM_DATA, Source(render_view_host()))); // The form should be filled. ExpectFilledTestForm(); } // Test that a JavaScript onchange event is fired after auto-filling a form. IN_PROC_BROWSER_TEST_F(AutofillTest, OnChangeAfterAutofill) { CreateTestProfile(); const char* kOnChangeScript = ""; // Load the test page. ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(std::string(kDataURIPrefix) + kTestFormString + kOnChangeScript))); // Invoke Autofill. FocusFirstNameField(); // Start filling the first name field with "M" and wait for the popup to be // shown. ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_M, false, true, false, false, chrome::NOTIFICATION_AUTOFILL_DID_SHOW_SUGGESTIONS, Source(render_view_host()))); // Press the down arrow to select the suggestion and preview the autofilled // form. ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_DOWN, false, false, false, false, chrome::NOTIFICATION_AUTOFILL_DID_FILL_FORM_DATA, Source(render_view_host()))); // Press Enter to accept the autofill suggestions. ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait( browser(), ui::VKEY_RETURN, false, false, false, false, chrome::NOTIFICATION_AUTOFILL_DID_FILL_FORM_DATA, Source(render_view_host()))); // The form should be filled. ExpectFilledTestForm(); // The change event should have already fired for unfocused fields, both of // and of
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" ""))); // Invoke Autofill. TryBasicFormFill(); ExpectFieldValue(L"state_freeform", ""); } // Test that form filling works after reloading the current page. // This test brought to you by http://crbug.com/69204 #if defined(OS_MACOSX) // Sometimes times out on Mac: http://crbug.com/81451 // Currently enabled for logging. #define MAYBE_AutofillAfterReload AutofillAfterReload #else #define MAYBE_AutofillAfterReload AutofillAfterReload #endif IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_AutofillAfterReload) { LOG(WARNING) << "Creating test profile."; CreateTestProfile(); // Load the test page. LOG(WARNING) << "Bringing browser window to front."; ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); LOG(WARNING) << "Navigating to URL."; ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(std::string(kDataURIPrefix) + kTestFormString))); // Reload the page. LOG(WARNING) << "Reloading the page."; TabContents* tab = browser()->GetSelectedTabContentsWrapper()->tab_contents(); tab->controller().Reload(false); ui_test_utils::WaitForLoadStop(tab); // Invoke Autofill. LOG(WARNING) << "Trying to fill the form."; TryBasicFormFill(); } #if defined(OS_MACOSX) || defined(OS_CHROMEOS) // Test that autofill works after page translation. // http://crbug.com/81451 IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_AutofillAfterTranslate) { #else IN_PROC_BROWSER_TEST_F(AutofillTest, AutofillAfterTranslate) { #endif CreateTestProfile(); GURL url(std::string(kDataURIPrefix) + "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "" "
" "
"); ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url)); // Get translation bar. render_view_host()->OnMessageReceived(ViewHostMsg_TranslateLanguageDetermined( 0, "ja", true)); TranslateInfoBarDelegate* infobar = browser()->GetSelectedTabContentsWrapper()-> GetInfoBarDelegateAt(0)->AsTranslateInfoBarDelegate(); ASSERT_TRUE(infobar != NULL); EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type()); // Simulate translation button press. infobar->Translate(); // Simulate the translate script being retrieved. // Pass fake google.translate lib as the translate script. SimulateURLFetch(true); // Simulate translation to kick onTranslateElementLoad. // But right now, the call stucks here. // Once click the text field, it starts again. ASSERT_TRUE(ui_test_utils::ExecuteJavaScript( render_view_host(), L"", L"cr.googleTranslate.onTranslateElementLoad();")); // Simulate the render notifying the translation has been done. ui_test_utils::WaitForNotification(chrome::NOTIFICATION_PAGE_TRANSLATED); TryBasicFormFill(); }