1// Copyright 2014 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 "base/macros.h"
6#include "base/memory/ref_counted.h"
7#include "base/message_loop/message_loop.h"
8#include "base/prefs/pref_service.h"
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/browser/autofill/personal_data_manager_factory.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/tabs/tab_strip_model.h"
14#include "chrome/test/base/in_process_browser_test.h"
15#include "chrome/test/base/ui_test_utils.h"
16#include "components/autofill/core/browser/autofill_profile.h"
17#include "components/autofill/core/browser/autofill_test_utils.h"
18#include "components/autofill/core/browser/personal_data_manager.h"
19#include "components/autofill/core/browser/personal_data_manager_observer.h"
20#include "components/autofill/core/common/autofill_pref_names.h"
21#include "content/public/test/browser_test_utils.h"
22#include "content/public/test/test_utils.h"
23#include "net/url_request/test_url_fetcher_factory.h"
24#include "testing/gtest/include/gtest/gtest.h"
25
26namespace autofill {
27namespace {
28
29// TODO(isherman): Similar classes are defined in a few other Autofill browser
30// tests. It would be good to factor out the shared code into a helper file.
31class WindowedPersonalDataManagerObserver : public PersonalDataManagerObserver {
32 public:
33  explicit WindowedPersonalDataManagerObserver(Profile* profile)
34      : profile_(profile),
35        message_loop_runner_(new content::MessageLoopRunner){
36    PersonalDataManagerFactory::GetForProfile(profile_)->AddObserver(this);
37  }
38  virtual ~WindowedPersonalDataManagerObserver() {}
39
40  // Waits for the PersonalDataManager's list of profiles to be updated.
41  void Wait() {
42    message_loop_runner_->Run();
43    PersonalDataManagerFactory::GetForProfile(profile_)->RemoveObserver(this);
44  }
45
46  // PersonalDataManagerObserver:
47  virtual void OnPersonalDataChanged() OVERRIDE {
48    message_loop_runner_->Quit();
49  }
50
51 private:
52  Profile* profile_;
53  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
54};
55
56class WindowedNetworkObserver : public net::TestURLFetcher::DelegateForTests {
57 public:
58  explicit WindowedNetworkObserver(const std::string& expected_upload_data)
59      : factory_(new net::TestURLFetcherFactory),
60        expected_upload_data_(expected_upload_data),
61        message_loop_runner_(new content::MessageLoopRunner) {
62    factory_->SetDelegateForTests(this);
63  }
64  ~WindowedNetworkObserver() {}
65
66  // Waits for a network request with the |expected_upload_data_|.
67  void Wait() {
68    message_loop_runner_->Run();
69    factory_.reset();
70  }
71
72  // net::TestURLFetcher::DelegateForTests:
73  virtual void OnRequestStart(int fetcher_id) OVERRIDE {
74    net::TestURLFetcher* fetcher = factory_->GetFetcherByID(fetcher_id);
75    if (fetcher->upload_data() == expected_upload_data_)
76      message_loop_runner_->Quit();
77
78    // Not interested in any further status updates from this fetcher.
79    fetcher->SetDelegateForTests(NULL);
80  }
81  virtual void OnChunkUpload(int fetcher_id) OVERRIDE {}
82  virtual void OnRequestEnd(int fetcher_id) OVERRIDE {}
83
84 private:
85  // Mocks out network requests.
86  scoped_ptr<net::TestURLFetcherFactory> factory_;
87
88  const std::string expected_upload_data_;
89  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
90
91  DISALLOW_COPY_AND_ASSIGN(WindowedNetworkObserver);
92};
93
94}  // namespace
95
96class AutofillServerTest : public InProcessBrowserTest  {
97 public:
98  virtual void SetUpOnMainThread() OVERRIDE {
99    // Disable interactions with the Mac Keychain.
100    PrefService* pref_service = browser()->profile()->GetPrefs();
101    test::DisableSystemServices(pref_service);
102
103    // Enable uploads, and load a new tab to force the AutofillDownloadManager
104    // to update its cached view of the prefs.
105    pref_service->SetDouble(prefs::kAutofillPositiveUploadRate, 1.0);
106    pref_service->SetDouble(prefs::kAutofillNegativeUploadRate, 1.0);
107    AddBlankTabAndShow(browser());
108  }
109};
110
111// Regression test for http://crbug.com/177419
112IN_PROC_BROWSER_TEST_F(AutofillServerTest,
113                       QueryAndUploadBothIncludeFieldsWithAutocompleteOff) {
114  // Seed some test Autofill profile data, as upload requests are only made when
115  // there is local data available to use as a baseline.
116  WindowedPersonalDataManagerObserver personal_data_observer(
117      browser()->profile());
118  PersonalDataManagerFactory::GetForProfile(browser()->profile())
119      ->AddProfile(test::GetFullProfile());
120  personal_data_observer.Wait();
121
122  // Load the test page. Expect a query request upon loading the page.
123  const char kDataURIPrefix[] = "data:text/html;charset=utf-8,";
124  const char kFormHtml[] =
125      "<form id='test_form'>"
126      "  <input id='one'>"
127      "  <input id='two' autocomplete='off'>"
128      "  <input id='three'>"
129      "  <input id='four' autocomplete='off'>"
130      "  <input type='submit'>"
131      "</form>"
132      "<script>"
133      "  document.onclick = function() {"
134      "    document.getElementById('test_form').submit();"
135      "  };"
136      "</script>";
137  const char kQueryRequest[] =
138      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
139      "<autofillquery clientversion=\"6.1.1715.1442/en (GGLL)\">"
140      "<form signature=\"15916856893790176210\">"
141      "<field signature=\"2594484045\"/>"
142      "<field signature=\"2750915947\"/>"
143      "<field signature=\"3494787134\"/>"
144      "<field signature=\"1236501728\"/>"
145      "</form>"
146      "</autofillquery>";
147  WindowedNetworkObserver query_network_observer(kQueryRequest);
148  ui_test_utils::NavigateToURL(
149      browser(), GURL(std::string(kDataURIPrefix) + kFormHtml));
150  query_network_observer.Wait();
151
152  // Submit the form, using a simulated mouse click because form submissions not
153  // triggered by user gestures are ignored. Expect an upload request upon form
154  // submission, with form fields matching those from the query request.
155  const char kUploadRequest[] =
156      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
157      "<autofillupload clientversion=\"6.1.1715.1442/en (GGLL)\""
158      " formsignature=\"15916856893790176210\""
159      " autofillused=\"false\""
160      " datapresent=\"1f7e0003780000080004\">"
161      "<field signature=\"2594484045\" autofilltype=\"2\"/>"
162      "<field signature=\"2750915947\" autofilltype=\"2\"/>"
163      "<field signature=\"3494787134\" autofilltype=\"2\"/>"
164      "<field signature=\"1236501728\" autofilltype=\"2\"/>"
165      "</autofillupload>";
166  WindowedNetworkObserver upload_network_observer(kUploadRequest);
167  content::WebContents* web_contents =
168      browser()->tab_strip_model()->GetActiveWebContents();
169  content::SimulateMouseClick(
170      web_contents, 0, blink::WebMouseEvent::ButtonLeft);
171  upload_network_observer.Wait();
172}
173
174}  // namespace autofill
175