autofill_browsertest.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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/utf_string_conversions.h"
8#include "base/basictypes.h"
9#include "base/ref_counted.h"
10#include "base/scoped_ptr.h"
11#include "base/string16.h"
12#include "chrome/browser/autofill/autofill_common_test.h"
13#include "chrome/browser/autofill/autofill_profile.h"
14#include "chrome/browser/autofill/personal_data_manager.h"
15#include "chrome/browser/net/predictor_api.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/browser/renderer_host/mock_render_process_host.h"
18#include "chrome/browser/renderer_host/render_view_host.h"
19#include "chrome/browser/tab_contents/tab_contents.h"
20#include "chrome/browser/translate/translate_infobar_delegate.h"
21#include "chrome/browser/translate/translate_manager.h"
22#include "chrome/browser/ui/browser.h"
23#include "chrome/browser/ui/browser_window.h"
24#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
25#include "chrome/common/net/test_url_fetcher_factory.h"
26#include "chrome/common/render_messages.h"
27#include "chrome/renderer/translate_helper.h"
28#include "chrome/test/in_process_browser_test.h"
29#include "chrome/test/ui_test_utils.h"
30#include "testing/gtest/include/gtest/gtest.h"
31#include "ui/base/keycodes/keyboard_codes.h"
32
33static const char* kDataURIPrefix = "data:text/html;charset=utf-8,";
34static const char* kTestFormString =
35    "<form action=\"http://www.example.com/\" method=\"POST\">"
36    "<label for=\"firstname\">First name:</label>"
37    " <input type=\"text\" id=\"firstname\""
38    "        onFocus=\"domAutomationController.send(true)\""
39    " /><br />"
40    "<label for=\"lastname\">Last name:</label>"
41    " <input type=\"text\" id=\"lastname\" /><br />"
42    "<label for=\"address1\">Address line 1:</label>"
43    " <input type=\"text\" id=\"address1\" /><br />"
44    "<label for=\"address2\">Address line 2:</label>"
45    " <input type=\"text\" id=\"address2\" /><br />"
46    "<label for=\"city\">City:</label>"
47    " <input type=\"text\" id=\"city\" /><br />"
48    "<label for=\"state\">State:</label>"
49    " <select id=\"state\">"
50    " <option value=\"\" selected=\"yes\">--</option>"
51    " <option value=\"CA\">California</option>"
52    " <option value=\"TX\">Texas</option>"
53    " </select><br />"
54    "<label for=\"zip\">ZIP code:</label>"
55    " <input type=\"text\" id=\"zip\" /><br />"
56    "<label for=\"country\">Country:</label>"
57    " <select id=\"country\">"
58    " <option value=\"\" selected=\"yes\">--</option>"
59    " <option value=\"CA\">Canada</option>"
60    " <option value=\"US\">United States</option>"
61    " </select><br />"
62    "<label for=\"phone\">Phone number:</label>"
63    " <input type=\"text\" id=\"phone\" /><br />"
64    "</form>";
65
66class AutoFillTest : public InProcessBrowserTest {
67 protected:
68  AutoFillTest() {
69    set_show_window(true);
70    EnableDOMAutomation();
71  }
72
73  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
74    URLFetcher::set_factory(&url_fetcher_factory_);
75  }
76
77  void CreateTestProfile() {
78    autofill_test::DisableSystemServices(browser()->profile());
79
80    AutoFillProfile profile;
81    autofill_test::SetProfileInfo(
82        &profile, "Office Space", "Milton", "C.", "Waddams",
83        "red.swingline@initech.com", "Initech", "4120 Freidrich Lane",
84        "Basement", "Austin", "Texas", "78744", "United States", "5125551234",
85        "5125550000");
86
87    PersonalDataManager* personal_data_manager =
88        browser()->profile()->GetPersonalDataManager();
89    ASSERT_TRUE(personal_data_manager);
90
91    std::vector<AutoFillProfile> profiles(1, profile);
92    personal_data_manager->SetProfiles(&profiles);
93  }
94
95  void ExpectFieldValue(const std::wstring& field_name,
96                        const std::string& expected_value) {
97    std::string value;
98    ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
99        browser()->GetSelectedTabContents()->render_view_host(), L"",
100        L"window.domAutomationController.send("
101        L"document.getElementById('" + field_name + L"').value);", &value));
102    EXPECT_EQ(expected_value, value);
103  }
104
105  RenderViewHost* render_view_host() {
106    return browser()->GetSelectedTabContents()->render_view_host();
107  }
108
109  void SimulateURLFetch(bool success) {
110    TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
111    ASSERT_TRUE(fetcher);
112    net::URLRequestStatus status;
113    status.set_status(success ? net::URLRequestStatus::SUCCESS :
114                                net::URLRequestStatus::FAILED);
115
116    std::string script = " var google = {};"
117        "google.translate = (function() {"
118        "  return {"
119        "    TranslateService: function() {"
120        "      return {"
121        "        isAvailable : function() {"
122        "          return true;"
123        "        },"
124        "        restore : function() {"
125        "          return;"
126        "        },"
127        "        getDetectedLanguage : function() {"
128        "          return \"ja\";"
129        "        },"
130        "        translatePage : function(originalLang, targetLang,"
131        "                                 onTranslateProgress) {"
132        "          document.getElementsByTagName(\"body\")[0].innerHTML = '" +
133        std::string(kTestFormString) +
134        "              ';"
135        "          onTranslateProgress(100, true, false);"
136        "        }"
137        "      };"
138        "    }"
139        "  };"
140        "})();";
141
142    fetcher->delegate()->OnURLFetchComplete(fetcher, fetcher->original_url(),
143        status, success ? 200 : 500,
144        ResponseCookies(),
145        script);
146  }
147
148  void FocusFirstNameField() {
149    ASSERT_NO_FATAL_FAILURE(ui_test_utils::ClickOnView(browser(),
150                                                       VIEW_ID_TAB_CONTAINER));
151    ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(),
152                                             VIEW_ID_TAB_CONTAINER_FOCUS_VIEW));
153
154    bool result = false;
155    ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
156        render_view_host(), L"",
157        L"document.getElementById('firstname').focus();", &result));
158    ASSERT_TRUE(result);
159  }
160
161  void ExpectFilledTestForm() {
162    ExpectFieldValue(L"firstname", "Milton");
163    ExpectFieldValue(L"lastname", "Waddams");
164    ExpectFieldValue(L"address1", "4120 Freidrich Lane");
165    ExpectFieldValue(L"address2", "Basement");
166    ExpectFieldValue(L"city", "Austin");
167    ExpectFieldValue(L"state", "TX");
168    ExpectFieldValue(L"zip", "78744");
169    ExpectFieldValue(L"country", "US");
170    ExpectFieldValue(L"phone", "5125551234");
171  }
172
173  void TryBasicFormFill() {
174    FocusFirstNameField();
175
176    // Start filling the first name field with "M" and wait for the popup to be
177    // shown.
178    ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
179        browser(), ui::VKEY_M, false, true, false, false,
180        NotificationType::AUTOFILL_DID_SHOW_SUGGESTIONS,
181        Source<RenderViewHost>(render_view_host())));
182
183    // Press the down arrow to select the suggestion and preview the autofilled
184    // form.
185    ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
186        browser(), ui::VKEY_DOWN, false, false, false, false,
187        NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
188        Source<RenderViewHost>(render_view_host())));
189
190    // The previewed values should not be accessible to JavaScript.
191    ExpectFieldValue(L"firstname", "M");
192    ExpectFieldValue(L"lastname", "");
193    ExpectFieldValue(L"address1", "");
194    ExpectFieldValue(L"address2", "");
195    ExpectFieldValue(L"city", "");
196    ExpectFieldValue(L"state", "");
197    ExpectFieldValue(L"zip", "");
198    ExpectFieldValue(L"country", "");
199    ExpectFieldValue(L"phone", "");
200    // TODO(isherman): It would be nice to test that the previewed values are
201    // displayed: http://crbug.com/57220
202
203    // Press Enter to accept the autofill suggestions.
204    ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
205        browser(), ui::VKEY_RETURN, false, false, false, false,
206        NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
207        Source<RenderViewHost>(render_view_host())));
208
209    // The form should be filled.
210    ExpectFilledTestForm();
211  }
212
213 private:
214  TestURLFetcherFactory url_fetcher_factory_;
215};
216
217// Test that basic form fill is working.
218IN_PROC_BROWSER_TEST_F(AutoFillTest, BasicFormFill) {
219  CreateTestProfile();
220
221  // Load the test page.
222  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
223  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
224      GURL(std::string(kDataURIPrefix) + kTestFormString)));
225
226  // Invoke AutoFill.
227  TryBasicFormFill();
228}
229
230// Test that form filling can be initiated by pressing the down arrow.
231IN_PROC_BROWSER_TEST_F(AutoFillTest, AutoFillViaDownArrow) {
232  CreateTestProfile();
233
234  // Load the test page.
235  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
236  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
237      GURL(std::string(kDataURIPrefix) + kTestFormString)));
238
239  // Focus a fillable field.
240  FocusFirstNameField();
241
242  // Press the down arrow to initiate AutoFill and wait for the popup to be
243  // shown.
244  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
245      browser(), ui::VKEY_DOWN, false, false, false, false,
246      NotificationType::AUTOFILL_DID_SHOW_SUGGESTIONS,
247      Source<RenderViewHost>(render_view_host())));
248
249  // Press the down arrow to select the suggestion and preview the autofilled
250  // form.
251  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
252      browser(), ui::VKEY_DOWN, false, false, false, false,
253      NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
254      Source<RenderViewHost>(render_view_host())));
255
256  // Press Enter to accept the autofill suggestions.
257  ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
258      browser(), ui::VKEY_RETURN, false, false, false, false,
259      NotificationType::AUTOFILL_DID_FILL_FORM_DATA,
260      Source<RenderViewHost>(render_view_host())));
261
262  // The form should be filled.
263  ExpectFilledTestForm();
264}
265
266// Test that form filling works after reloading the current page.
267// This test brought to you by http://crbug.com/69204
268IN_PROC_BROWSER_TEST_F(AutoFillTest, AutoFillAfterReload) {
269  CreateTestProfile();
270
271  // Load the test page.
272  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
273  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
274      GURL(std::string(kDataURIPrefix) + kTestFormString)));
275
276  // Reload the page.
277  NavigationController* controller =
278      &browser()->GetSelectedTabContentsWrapper()->tab_contents()->controller();
279  controller->Reload(false);
280  ui_test_utils::WaitForLoadStop(controller);
281
282  // Invoke AutoFill.
283  TryBasicFormFill();
284}
285
286// Test that autofill works after page translation.
287IN_PROC_BROWSER_TEST_F(AutoFillTest, AutoFillAfterTranslate) {
288  CreateTestProfile();
289
290  GURL url(std::string(kDataURIPrefix) +
291               "<form action=\"http://www.example.com/\" method=\"POST\">"
292               "<label for=\"fn\">なまえ</label>"
293               " <input type=\"text\" id=\"fn\""
294               "        onFocus=\"domAutomationController.send(true)\""
295               " /><br />"
296               "<label for=\"ln\">みょうじ</label>"
297               " <input type=\"text\" id=\"ln\" /><br />"
298               "<label for=\"a1\">Address line 1:</label>"
299               " <input type=\"text\" id=\"a1\" /><br />"
300               "<label for=\"a2\">Address line 2:</label>"
301               " <input type=\"text\" id=\"a2\" /><br />"
302               "<label for=\"ci\">City:</label>"
303               " <input type=\"text\" id=\"ci\" /><br />"
304               "<label for=\"st\">State:</label>"
305               " <select id=\"st\">"
306               " <option value=\"\" selected=\"yes\">--</option>"
307               " <option value=\"CA\">California</option>"
308               " <option value=\"TX\">Texas</option>"
309               " </select><br />"
310               "<label for=\"z\">ZIP code:</label>"
311               " <input type=\"text\" id=\"z\" /><br />"
312               "<label for=\"co\">Country:</label>"
313               " <select id=\"co\">"
314               " <option value=\"\" selected=\"yes\">--</option>"
315               " <option value=\"CA\">Canada</option>"
316               " <option value=\"US\">United States</option>"
317               " </select><br />"
318               "<label for=\"ph\">Phone number:</label>"
319               " <input type=\"text\" id=\"ph\" /><br />"
320               "</form>");
321  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
322  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
323
324  // Get translation bar.
325  int page_id = browser()->GetSelectedTabContents()->controller().
326      GetLastCommittedEntry()->page_id();
327  render_view_host()->OnMessageReceived(ViewHostMsg_PageContents(
328      0, url, page_id, ASCIIToUTF16("test"), "ja", true));
329  TranslateInfoBarDelegate* infobar = browser()->GetSelectedTabContents()->
330      GetInfoBarDelegateAt(0)->AsTranslateInfoBarDelegate();
331
332  ASSERT_TRUE(infobar != NULL);
333  EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE, infobar->type());
334
335  // Simulate translation button press.
336  infobar->Translate();
337
338  // Simulate the translate script being retrieved.
339  // Pass fake google.translate lib as the translate script.
340  SimulateURLFetch(true);
341
342  // Simulate translation to kick onTranslateElementLoad.
343  // But right now, the call stucks here.
344  // Once click the text field, it starts again.
345  ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(
346      render_view_host(), L"",
347      L"cr.googleTranslate.onTranslateElementLoad();"));
348
349  // Simulate the render notifying the translation has been done.
350  ui_test_utils::WaitForNotification(NotificationType::PAGE_TRANSLATED);
351
352  TryBasicFormFill();
353}
354