File: autofill_policy_browsertest.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (226 lines) | stat: -rw-r--r-- 9,033 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>
#include <unordered_map>

#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/run_until.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/autofill/autofill_uitest_util.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/policy/policy_test_utils.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/content/browser/test_autofill_client_injector.h"
#include "components/autofill/content/browser/test_autofill_manager_injector.h"
#include "components/autofill/core/browser/data_manager/addresses/address_data_manager.h"
#include "components/autofill/core/browser/data_manager/personal_data_manager.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/foundations/autofill_manager.h"
#include "components/autofill/core/browser/foundations/browser_autofill_manager.h"
#include "components/autofill/core/browser/foundations/test_autofill_manager_waiter.h"
#include "components/autofill/core/browser/suggestions/suggestion.h"
#include "components/autofill/core/browser/test_utils/autofill_test_utils.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "url/gurl.h"

namespace policy {
namespace {

using ::testing::AssertionResult;
using ::testing::Contains;
using ::testing::Field;
using ::testing::IsEmpty;

const char kAutofillTestPageURL[] = "/autofill/autofill_address_enabled.html";

class AutofillPolicyTest : public PolicyTest,
                           public testing::WithParamInterface<bool> {
 public:
  bool disabled_by_policy() const { return !GetParam(); }

  void SetUpOnMainThread() override {
    InProcessBrowserTest::SetUpOnMainThread();
    // Wait for Personal Data Manager to be fully loaded to prevent that
    // spurious notifications deceive the tests.
    autofill::WaitForPersonalDataManagerToBeLoaded(browser()->profile());
    ASSERT_TRUE(ImportAddress());

    PolicyMap policies;
    SetPolicy(&policies, key::kAutofillAddressEnabled, base::Value(GetParam()));
    UpdateProviderPolicy(policies);

    // The base test fixture creates a tab before we set the policy. We create a
    // new tab so a new ChromeAutofillClient is created.
    AddBlankTabAndShow(browser());
    ASSERT_TRUE(embedded_test_server()->Start());
  }

  content::WebContents* GetWebContents() {
    return browser()->tab_strip_model()->GetActiveWebContents();
  }

  autofill::PersonalDataManager* personal_data_manager() {
    return autofill::PersonalDataManagerFactory::GetForBrowserContext(
        browser()->profile());
  }

  [[nodiscard]] testing::AssertionResult ImportAddress() {
    if (personal_data_manager()->address_data_manager().GetProfiles().size() !=
        0u) {
      return testing::AssertionFailure() << "Should be empty profile.";
    }
    autofill::AddTestProfile(browser()->profile(),
                             autofill::test::GetFullProfile());
    expected_suggestions_["name"] = u"John H. Doe";
    expected_suggestions_["street-address"] = u"666 Erebus St., Apt 8";
    expected_suggestions_["postal-code"] = u"91111";
    expected_suggestions_["city"] = u"Elysium";
    expected_suggestions_["phone"] = u"+1 650-211-1111";
    expected_suggestions_["email"] = u"johndoe@hades.com";
    return personal_data_manager()
                       ->address_data_manager()
                       .GetProfiles()
                       .size() == 1u
               ? testing::AssertionSuccess()
               : testing::AssertionFailure() << "Should be one profile.";
  }

  std::unordered_map<std::string, std::u16string> GetExpectedSuggestions() {
    return expected_suggestions_;
  }

  [[nodiscard]] testing::AssertionResult NavigateToTestPage() {
    if (!(ui_test_utils::NavigateToURL(
            browser(), embedded_test_server()->GetURL(kAutofillTestPageURL)))) {
      return testing::AssertionFailure();
    }
    // Wait for the test page to be rendered to receive clicks.
    content::MainThreadFrameObserver frame_observer(
        GetWebContents()->GetRenderWidgetHostView()->GetRenderWidgetHost());
    frame_observer.Wait();
    return testing::AssertionSuccess();
  }

 protected:
  class TestAutofillManager : public autofill::BrowserAutofillManager {
   public:
    explicit TestAutofillManager(autofill::ContentAutofillDriver* driver)
        : autofill::BrowserAutofillManager(driver) {}

    [[nodiscard]] AssertionResult WaitForFormsSeen() {
      return forms_seen_waiter_.Wait();
    }

    // The test can not wait for autofill popup to show, because when
    // autofill gets disabled, the test will hang there. An alternative is to
    // have a timeout, but it could be flaky on bots with different specs.
    // Hence the test checks the OnAskForValues event, if this event got
    // fired, Autofill popup should have appeared, otherwise it is disabled by
    // policy.
    [[nodiscard]] AssertionResult WaitForAskForValuesToFill() {
      return ask_for_value_to_fill_waiter_.Wait();
    }

   private:
    autofill::TestAutofillManagerWaiter forms_seen_waiter_{
        *this,
        {autofill::AutofillManagerEvent::kFormsSeen}};
    autofill::TestAutofillManagerWaiter ask_for_value_to_fill_waiter_{
        *this,
        {autofill::AutofillManagerEvent::kAskForValuesToFill}};
  };

  class TestAutofillClient : public autofill::ChromeAutofillClient {
   public:
    explicit TestAutofillClient(content::WebContents* web_contents)
        : autofill::ChromeAutofillClient(web_contents) {}

    SuggestionUiSessionId ShowAutofillSuggestions(
        const autofill::AutofillClient::PopupOpenArgs& open_args,
        base::WeakPtr<autofill::AutofillSuggestionDelegate> delegate) override {
      suggestions_ = open_args.suggestions;
      return autofill::ChromeAutofillClient::ShowAutofillSuggestions(open_args,
                                                                     delegate);
    }

    const std::vector<autofill::Suggestion>& suggestions() const {
      return suggestions_;
    }

    void ResetSuggestions() { suggestions_ = {}; }

   private:
    std::vector<autofill::Suggestion> suggestions_;
  };

  TestAutofillClient* autofill_client() {
    return autofill_client_injector_[GetWebContents()];
  }

  TestAutofillManager* autofill_manager() {
    return autofill_manager_injector_[GetWebContents()];
  }

 private:
  autofill::TestAutofillClientInjector<TestAutofillClient>
      autofill_client_injector_;

  autofill::TestAutofillManagerInjector<TestAutofillManager>
      autofill_manager_injector_;

  std::unordered_map<std::string, std::u16string> expected_suggestions_;
};

INSTANTIATE_TEST_SUITE_P(, AutofillPolicyTest, testing::Bool());

IN_PROC_BROWSER_TEST_P(AutofillPolicyTest, AutofillDisabledByPolicy) {
  ASSERT_TRUE(NavigateToTestPage());
  EXPECT_TRUE(autofill_manager()->WaitForFormsSeen());
  for (const auto& [element, expectation] : GetExpectedSuggestions()) {
    SCOPED_TRACE(testing::Message() << "element = " << element
                                    << ", expectation = " << expectation);
    content::SimulateMouseClickOrTapElementWithId(GetWebContents(), element);

    // Showing the Autofill Popup is an asynchronous task.
    EXPECT_TRUE(autofill_manager()->WaitForAskForValuesToFill());
    if (disabled_by_policy()) {
      // Autofill currently does not have the event infrastructure for asserting
      // that no popup was shown. RunUntilIdle() is not sufficient, so this test
      // is misleading.
      // TODO: crbug.com/373703937 - Fix this.
      base::RunLoop().RunUntilIdle();
    } else {
      EXPECT_TRUE(base::test::RunUntil([&]() {
        return !autofill_client()->suggestions().empty();
      })) << "Showing the Autofill Popup timed out.";
    }

    EXPECT_EQ(autofill_client()->suggestions().empty(), disabled_by_policy());
    if (!disabled_by_policy()) {
      // There may be more suggestions, but the first one in the vector
      // should be the expected and shown in the popup.
      EXPECT_THAT(autofill_client()->suggestions(),
                  Contains(Field(
                      &autofill::Suggestion::main_text,
                      Field(&autofill::Suggestion::Text::value, expectation))));
    }
    autofill_client()->ResetSuggestions();
  }
}

}  // namespace
}  // namespace policy