1 // Copyright 2020 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 "chrome/browser/chromeos/input_method/personal_info_suggester.h"
6
7 #include "ash/public/cpp/ash_pref_names.h"
8 #include "base/guid.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/metrics/histogram_tester.h"
11 #include "base/test/scoped_feature_list.h"
12 #include "chrome/browser/chromeos/input_method/ui/suggestion_details.h"
13 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "chromeos/constants/chromeos_features.h"
16 #include "chromeos/constants/chromeos_pref_names.h"
17 #include "components/autofill/core/browser/autofill_test_utils.h"
18 #include "components/autofill/core/browser/data_model/autofill_profile.h"
19 #include "components/autofill/core/browser/geo/country_names.h"
20 #include "components/autofill/core/browser/test_autofill_client.h"
21 #include "components/autofill/core/browser/test_personal_data_manager.h"
22 #include "components/prefs/scoped_user_pref_update.h"
23 #include "content/public/test/browser_task_environment.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace chromeos {
27 namespace {
28
29 class TestSuggestionHandler : public SuggestionHandlerInterface {
30 public:
DismissSuggestion(int context_id,std::string * error)31 bool DismissSuggestion(int context_id, std::string* error) override {
32 suggestion_text_ = base::EmptyString16();
33 previous_suggestions_.clear();
34 confirmed_length_ = 0;
35 suggestion_accepted_ = false;
36 return true;
37 }
38
SetSuggestion(int context_id,const ui::ime::SuggestionDetails & details,std::string * error)39 bool SetSuggestion(int context_id,
40 const ui::ime::SuggestionDetails& details,
41 std::string* error) override {
42 suggestion_text_ = details.text;
43 confirmed_length_ = details.confirmed_length;
44 show_annotation_ = details.show_annotation;
45 show_setting_link_ = details.show_setting_link;
46 return true;
47 }
48
AcceptSuggestion(int context_id,std::string * error)49 bool AcceptSuggestion(int context_id, std::string* error) override {
50 suggestion_text_ = base::EmptyString16();
51 confirmed_length_ = 0;
52 suggestion_accepted_ = true;
53 return true;
54 }
55
VerifySuggestion(const base::string16 text,const size_t confirmed_length)56 void VerifySuggestion(const base::string16 text,
57 const size_t confirmed_length) {
58 EXPECT_EQ(suggestion_text_, text);
59 EXPECT_EQ(confirmed_length_, confirmed_length);
60 suggestion_text_ = base::EmptyString16();
61 confirmed_length_ = 0;
62 }
63
VerifySuggestionDispatchedToExtension(const std::vector<std::string> & suggestions)64 void VerifySuggestionDispatchedToExtension(
65 const std::vector<std::string>& suggestions) {
66 EXPECT_THAT(previous_suggestions_, testing::ContainerEq(suggestions));
67 }
68
OnSuggestionsChanged(const std::vector<std::string> & suggestions)69 void OnSuggestionsChanged(
70 const std::vector<std::string>& suggestions) override {
71 previous_suggestions_ = suggestions;
72 }
73
ClickButton(const ui::ime::AssistiveWindowButton & button)74 void ClickButton(const ui::ime::AssistiveWindowButton& button) override {
75 button_clicked_ = button.id;
76 }
77
SetButtonHighlighted(int context_id,const ui::ime::AssistiveWindowButton & button,bool highlighted,std::string * error)78 bool SetButtonHighlighted(int context_id,
79 const ui::ime::AssistiveWindowButton& button,
80 bool highlighted,
81 std::string* error) override {
82 return false;
83 }
84
AcceptSuggestionCandidate(int context_id,const base::string16 & candidate,std::string * error)85 bool AcceptSuggestionCandidate(int context_id,
86 const base::string16& candidate,
87 std::string* error) override {
88 return false;
89 }
90
SetAssistiveWindowProperties(int context_id,const AssistiveWindowProperties & assistive_window,std::string * error)91 bool SetAssistiveWindowProperties(
92 int context_id,
93 const AssistiveWindowProperties& assistive_window,
94 std::string* error) override {
95 return false;
96 }
97
VerifyShowAnnotation(const bool show_annotation)98 void VerifyShowAnnotation(const bool show_annotation) {
99 EXPECT_EQ(show_annotation_, show_annotation);
100 }
VerifyShowSettingLink(const bool show_setting_link)101 void VerifyShowSettingLink(const bool show_setting_link) {
102 EXPECT_EQ(show_setting_link_, show_setting_link);
103 }
VerifyButtonClicked(const ui::ime::ButtonId id)104 void VerifyButtonClicked(const ui::ime::ButtonId id) {
105 EXPECT_EQ(button_clicked_, id);
106 }
107
IsSuggestionAccepted()108 bool IsSuggestionAccepted() { return suggestion_accepted_; }
109
110 private:
111 base::string16 suggestion_text_;
112 size_t confirmed_length_ = 0;
113 bool show_annotation_ = false;
114 bool show_setting_link_ = false;
115 bool suggestion_accepted_ = false;
116 ui::ime::ButtonId button_clicked_ = ui::ime::ButtonId::kNone;
117 std::vector<std::string> previous_suggestions_;
118 };
119
120 class TestTtsHandler : public TtsHandler {
121 public:
TestTtsHandler(Profile * profile)122 explicit TestTtsHandler(Profile* profile) : TtsHandler(profile) {}
123
VerifyAnnouncement(const std::string & expected_text)124 void VerifyAnnouncement(const std::string& expected_text) {
125 EXPECT_EQ(text_, expected_text);
126 }
127
128 private:
Speak(const std::string & text)129 void Speak(const std::string& text) override { text_ = text; }
130
131 std::string text_ = "";
132 };
133
134 } // namespace
135
136 class PersonalInfoSuggesterTest : public testing::Test {
137 protected:
PersonalInfoSuggesterTest()138 PersonalInfoSuggesterTest() {
139 autofill_client_.SetPrefs(autofill::test::PrefServiceForTesting());
140 }
141
SetUp()142 void SetUp() override {
143 profile_ = std::make_unique<TestingProfile>();
144 auto tts_handler = std::make_unique<TestTtsHandler>(profile_.get());
145 tts_handler_ = tts_handler.get();
146
147 suggestion_handler_ = std::make_unique<TestSuggestionHandler>();
148
149 personal_data_ = std::make_unique<autofill::TestPersonalDataManager>();
150 personal_data_->SetPrefService(autofill_client_.GetPrefs());
151
152 suggester_ = std::make_unique<PersonalInfoSuggester>(
153 suggestion_handler_.get(), profile_.get(), personal_data_.get(),
154 std::move(tts_handler));
155
156 chrome_keyboard_controller_client_ =
157 ChromeKeyboardControllerClient::CreateForTest();
158 chrome_keyboard_controller_client_->set_keyboard_visible_for_test(false);
159 }
160
SendKeyboardEvent(std::string key)161 void SendKeyboardEvent(std::string key) {
162 InputMethodEngineBase::KeyboardEvent event;
163 event.key = key;
164 suggester_->HandleKeyEvent(event);
165 }
166
167 content::BrowserTaskEnvironment task_environment_{
168 base::test::TaskEnvironment::TimeSource::MOCK_TIME};
169
170 std::unique_ptr<TestingProfile> profile_;
171 TestTtsHandler* tts_handler_;
172 std::unique_ptr<TestSuggestionHandler> suggestion_handler_;
173 std::unique_ptr<PersonalInfoSuggester> suggester_;
174 std::unique_ptr<ChromeKeyboardControllerClient>
175 chrome_keyboard_controller_client_;
176
177 autofill::TestAutofillClient autofill_client_;
178 std::unique_ptr<autofill::TestPersonalDataManager> personal_data_;
179
180 const base::string16 email_ = base::UTF8ToUTF16("johnwayne@me.xyz");
181 const base::string16 first_name_ = base::UTF8ToUTF16("John");
182 const base::string16 last_name_ = base::UTF8ToUTF16("Wayne");
183 const base::string16 full_name_ = base::UTF8ToUTF16("John Wayne");
184 const base::string16 address_ =
185 base::UTF8ToUTF16("1 Dream Road, Hollywood, CA 12345");
186 const base::string16 phone_number_ = base::UTF8ToUTF16("16505678910");
187 };
188
TEST_F(PersonalInfoSuggesterTest,SuggestEmail)189 TEST_F(PersonalInfoSuggesterTest, SuggestEmail) {
190 base::test::ScopedFeatureList feature_list;
191 feature_list.InitWithFeatures(
192 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
193 /*disabled_features=*/{});
194
195 profile_->set_profile_name(base::UTF16ToUTF8(email_));
196
197 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
198 suggestion_handler_->VerifySuggestion(email_, 0);
199 SendKeyboardEvent("Esc");
200
201 suggester_->Suggest(base::UTF8ToUTF16("My email is: "));
202 suggestion_handler_->VerifySuggestion(email_, 0);
203 SendKeyboardEvent("Esc");
204
205 suggester_->Suggest(base::UTF8ToUTF16("hi, my email: "));
206 suggestion_handler_->VerifySuggestion(email_, 0);
207 }
208
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestEmailWhenFlagIsDisabled)209 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestEmailWhenFlagIsDisabled) {
210 base::test::ScopedFeatureList feature_list;
211 feature_list.InitWithFeatures(
212 /*enabled_features=*/{},
213 /*disabled_features=*/{chromeos::features::kAssistPersonalInfoEmail});
214
215 profile_->set_profile_name(base::UTF16ToUTF8(email_));
216
217 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
218 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
219 }
220
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestEmailWhenPrefixDoesNotMatch)221 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestEmailWhenPrefixDoesNotMatch) {
222 base::test::ScopedFeatureList feature_list;
223 feature_list.InitWithFeatures(
224 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
225 /*disabled_features=*/{});
226
227 profile_->set_profile_name(base::UTF16ToUTF8(email_));
228
229 suggester_->Suggest(base::UTF8ToUTF16("my email is John"));
230 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
231
232 suggester_->Suggest(base::UTF8ToUTF16("our email is: "));
233 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
234 }
235
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestWhenVirtualKeyboardEnabled)236 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestWhenVirtualKeyboardEnabled) {
237 base::test::ScopedFeatureList feature_list;
238 feature_list.InitWithFeatures(
239 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
240 /*disabled_features=*/{});
241
242 chrome_keyboard_controller_client_->set_keyboard_visible_for_test(true);
243 profile_->set_profile_name(base::UTF16ToUTF8(email_));
244
245 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
246 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
247 }
248
TEST_F(PersonalInfoSuggesterTest,SendsEmailSuggestionToExtensionWhenVirtualKeyboardEnabled)249 TEST_F(PersonalInfoSuggesterTest,
250 SendsEmailSuggestionToExtensionWhenVirtualKeyboardEnabled) {
251 base::test::ScopedFeatureList feature_list;
252 feature_list.InitWithFeatures(
253 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
254 /*disabled_features=*/{});
255
256 chrome_keyboard_controller_client_->set_keyboard_visible_for_test(true);
257 profile_->set_profile_name(base::UTF16ToUTF8(email_));
258
259 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
260 suggestion_handler_->VerifySuggestionDispatchedToExtension(
261 std::vector<std::string>{base::UTF16ToUTF8(email_)});
262 }
263
TEST_F(PersonalInfoSuggesterTest,SuggestNames)264 TEST_F(PersonalInfoSuggesterTest, SuggestNames) {
265 base::test::ScopedFeatureList feature_list;
266 feature_list.InitWithFeatures(
267 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoName},
268 /*disabled_features=*/{});
269
270 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
271 autofill::test::kEmptyOrigin);
272 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_FIRST,
273 first_name_);
274 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_LAST, last_name_);
275 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL, full_name_);
276 personal_data_->AddProfile(autofill_profile);
277
278 suggester_->Suggest(base::UTF8ToUTF16("my first name is "));
279 suggestion_handler_->VerifySuggestion(first_name_, 0);
280 SendKeyboardEvent("Esc");
281
282 suggester_->Suggest(base::UTF8ToUTF16("my last name is: "));
283 suggestion_handler_->VerifySuggestion(last_name_, 0);
284 SendKeyboardEvent("Esc");
285
286 suggester_->Suggest(base::UTF8ToUTF16("my name is "));
287 suggestion_handler_->VerifySuggestion(full_name_, 0);
288 SendKeyboardEvent("Esc");
289
290 suggester_->Suggest(base::UTF8ToUTF16("Hmm... my FULL name: "));
291 suggestion_handler_->VerifySuggestion(full_name_, 0);
292 }
293
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestNamesWhenFlagIsDisabled)294 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestNamesWhenFlagIsDisabled) {
295 base::test::ScopedFeatureList feature_list;
296 feature_list.InitWithFeatures(
297 /*enabled_features=*/{},
298 /*disabled_features=*/{chromeos::features::kAssistPersonalInfoName});
299
300 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
301 autofill::test::kEmptyOrigin);
302 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_FIRST,
303 first_name_);
304 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_LAST, last_name_);
305 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL, full_name_);
306 personal_data_->AddProfile(autofill_profile);
307
308 suggester_->Suggest(base::UTF8ToUTF16("my first name is "));
309 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
310
311 suggester_->Suggest(base::UTF8ToUTF16("my last name is: "));
312 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
313
314 suggester_->Suggest(base::UTF8ToUTF16("my name is "));
315 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
316 }
317
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestNamesWhenPrefixDoesNotMatch)318 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestNamesWhenPrefixDoesNotMatch) {
319 base::test::ScopedFeatureList feature_list;
320 feature_list.InitWithFeatures(
321 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
322 /*disabled_features=*/{});
323
324 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
325 autofill::test::kEmptyOrigin);
326 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_FIRST,
327 first_name_);
328 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_LAST, last_name_);
329 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL, full_name_);
330 personal_data_->AddProfile(autofill_profile);
331
332 suggester_->Suggest(base::UTF8ToUTF16("our first name is "));
333 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
334
335 suggester_->Suggest(base::UTF8ToUTF16("our last name is: "));
336 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
337
338 suggester_->Suggest(base::UTF8ToUTF16("our name is "));
339 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
340
341 suggester_->Suggest(base::UTF8ToUTF16("our full name: "));
342 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
343 }
344
TEST_F(PersonalInfoSuggesterTest,SuggestAddress)345 TEST_F(PersonalInfoSuggesterTest, SuggestAddress) {
346 base::test::ScopedFeatureList feature_list;
347 feature_list.InitWithFeatures(
348 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoAddress},
349 /*disabled_features=*/{});
350
351 autofill::CountryNames::SetLocaleString("en-US");
352 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
353 autofill::test::kEmptyOrigin);
354 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_LINE1,
355 base::UTF8ToUTF16("1 Dream Road"));
356 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_CITY,
357 base::UTF8ToUTF16("Hollywood"));
358 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_ZIP,
359 base::UTF8ToUTF16("12345"));
360 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_STATE,
361 base::UTF8ToUTF16("CA"));
362 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_COUNTRY,
363 base::UTF8ToUTF16("US"));
364 personal_data_->AddProfile(autofill_profile);
365
366 suggester_->Suggest(base::UTF8ToUTF16("my address is "));
367 suggestion_handler_->VerifySuggestion(address_, 0);
368 SendKeyboardEvent("Esc");
369
370 suggester_->Suggest(base::UTF8ToUTF16("our address is: "));
371 suggestion_handler_->VerifySuggestion(address_, 0);
372 SendKeyboardEvent("Esc");
373
374 suggester_->Suggest(base::UTF8ToUTF16("my shipping address: "));
375 suggestion_handler_->VerifySuggestion(address_, 0);
376 SendKeyboardEvent("Esc");
377
378 suggester_->Suggest(base::UTF8ToUTF16("our billing address is "));
379 suggestion_handler_->VerifySuggestion(address_, 0);
380 SendKeyboardEvent("Esc");
381
382 suggester_->Suggest(base::UTF8ToUTF16("my current address: "));
383 suggestion_handler_->VerifySuggestion(address_, 0);
384 }
385
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestAddressWhenFlagIsDisabled)386 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestAddressWhenFlagIsDisabled) {
387 base::test::ScopedFeatureList feature_list;
388 feature_list.InitWithFeatures(
389 /*enabled_features=*/{},
390 /*disabled_features=*/{chromeos::features::kAssistPersonalInfoAddress});
391
392 autofill::CountryNames::SetLocaleString("en-US");
393 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
394 autofill::test::kEmptyOrigin);
395 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_LINE1,
396 base::UTF8ToUTF16("1 Dream Road"));
397 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_CITY,
398 base::UTF8ToUTF16("Hollywood"));
399 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_ZIP,
400 base::UTF8ToUTF16("12345"));
401 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_STATE,
402 base::UTF8ToUTF16("CA"));
403 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_COUNTRY,
404 base::UTF8ToUTF16("US"));
405 personal_data_->AddProfile(autofill_profile);
406
407 suggester_->Suggest(base::UTF8ToUTF16("my address is "));
408 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
409 }
410
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestAddressWhenPrefixDoesNotMatch)411 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestAddressWhenPrefixDoesNotMatch) {
412 base::test::ScopedFeatureList feature_list;
413 feature_list.InitWithFeatures(
414 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoAddress},
415 /*disabled_features=*/{});
416
417 autofill::CountryNames::SetLocaleString("en-US");
418 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
419 autofill::test::kEmptyOrigin);
420 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_LINE1,
421 base::UTF8ToUTF16("1 Dream Road"));
422 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_CITY,
423 base::UTF8ToUTF16("Hollywood"));
424 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_ZIP,
425 base::UTF8ToUTF16("12345"));
426 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_STATE,
427 base::UTF8ToUTF16("CA"));
428 autofill_profile.SetRawInfo(autofill::ServerFieldType::ADDRESS_HOME_COUNTRY,
429 base::UTF8ToUTF16("US"));
430 personal_data_->AddProfile(autofill_profile);
431
432 suggester_->Suggest(base::UTF8ToUTF16("my address "));
433 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
434
435 suggester_->Suggest(base::UTF8ToUTF16("my last address is: "));
436 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
437
438 suggester_->Suggest(base::UTF8ToUTF16("our address number is "));
439 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
440 }
441
TEST_F(PersonalInfoSuggesterTest,SuggestPhoneNumber)442 TEST_F(PersonalInfoSuggesterTest, SuggestPhoneNumber) {
443 base::test::ScopedFeatureList feature_list;
444 feature_list.InitWithFeatures(
445 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoPhoneNumber},
446 /*disabled_features=*/{});
447
448 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
449 autofill::test::kEmptyOrigin);
450 autofill_profile.SetRawInfo(
451 autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER, phone_number_);
452 personal_data_->AddProfile(autofill_profile);
453
454 suggester_->Suggest(base::UTF8ToUTF16("my phone number is "));
455 suggestion_handler_->VerifySuggestion(phone_number_, 0);
456 SendKeyboardEvent("Esc");
457
458 suggester_->Suggest(base::UTF8ToUTF16("my number is "));
459 suggestion_handler_->VerifySuggestion(phone_number_, 0);
460 SendKeyboardEvent("Esc");
461
462 suggester_->Suggest(base::UTF8ToUTF16("my mobile number is: "));
463 suggestion_handler_->VerifySuggestion(phone_number_, 0);
464 SendKeyboardEvent("Esc");
465
466 suggester_->Suggest(base::UTF8ToUTF16("my number: "));
467 suggestion_handler_->VerifySuggestion(phone_number_, 0);
468 SendKeyboardEvent("Esc");
469
470 suggester_->Suggest(base::UTF8ToUTF16("my telephone number is "));
471 suggestion_handler_->VerifySuggestion(phone_number_, 0);
472 }
473
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestPhoneNumberWhenFlagIsDisabled)474 TEST_F(PersonalInfoSuggesterTest, DoNotSuggestPhoneNumberWhenFlagIsDisabled) {
475 base::test::ScopedFeatureList feature_list;
476 feature_list.InitWithFeatures(
477 /*enabled_features=*/{},
478 /*disabled_features=*/{
479 chromeos::features::kAssistPersonalInfoPhoneNumber});
480
481 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
482 autofill::test::kEmptyOrigin);
483 autofill_profile.SetRawInfo(
484 autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER, phone_number_);
485 personal_data_->AddProfile(autofill_profile);
486
487 suggester_->Suggest(base::UTF8ToUTF16("my phone number is "));
488 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
489 }
490
TEST_F(PersonalInfoSuggesterTest,DoNotSuggestPhoneNumberWhenPrefixDoesNotMatch)491 TEST_F(PersonalInfoSuggesterTest,
492 DoNotSuggestPhoneNumberWhenPrefixDoesNotMatch) {
493 base::test::ScopedFeatureList feature_list;
494 feature_list.InitWithFeatures(
495 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoPhoneNumber},
496 /*disabled_features=*/{});
497
498 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
499 autofill::test::kEmptyOrigin);
500 autofill_profile.SetRawInfo(
501 autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER, phone_number_);
502 personal_data_->AddProfile(autofill_profile);
503
504 suggester_->Suggest(base::UTF8ToUTF16("our phone number is "));
505 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
506
507 suggester_->Suggest(base::UTF8ToUTF16("my number "));
508 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
509
510 suggester_->Suggest(base::UTF8ToUTF16("my number phone is: "));
511 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
512
513 suggester_->Suggest(base::UTF8ToUTF16("my phone phone: "));
514 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
515 }
516
TEST_F(PersonalInfoSuggesterTest,AcceptSuggestionWithDownEnter)517 TEST_F(PersonalInfoSuggesterTest, AcceptSuggestionWithDownEnter) {
518 base::test::ScopedFeatureList feature_list;
519 feature_list.InitWithFeatures(
520 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
521 /*disabled_features=*/{});
522
523 profile_->set_profile_name(base::UTF16ToUTF8(email_));
524
525 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
526 SendKeyboardEvent("Down");
527 SendKeyboardEvent("Enter");
528
529 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
530 EXPECT_TRUE(suggestion_handler_->IsSuggestionAccepted());
531 }
532
TEST_F(PersonalInfoSuggesterTest,AcceptSuggestionWithUpEnter)533 TEST_F(PersonalInfoSuggesterTest, AcceptSuggestionWithUpEnter) {
534 base::test::ScopedFeatureList feature_list;
535 feature_list.InitWithFeatures(
536 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
537 /*disabled_features=*/{});
538
539 DictionaryPrefUpdate update(profile_->GetPrefs(),
540 prefs::kAssistiveInputFeatureSettings);
541 update->SetIntKey(kPersonalInfoSuggesterAcceptanceCount, 1);
542 profile_->set_profile_name(base::UTF16ToUTF8(email_));
543
544 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
545 SendKeyboardEvent("Up");
546 SendKeyboardEvent("Enter");
547
548 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
549 EXPECT_TRUE(suggestion_handler_->IsSuggestionAccepted());
550 }
551
TEST_F(PersonalInfoSuggesterTest,DismissSuggestion)552 TEST_F(PersonalInfoSuggesterTest, DismissSuggestion) {
553 base::test::ScopedFeatureList feature_list;
554 feature_list.InitWithFeatures(
555 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoName},
556 /*disabled_features=*/{});
557
558 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
559 autofill::test::kEmptyOrigin);
560 autofill_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL, full_name_);
561 personal_data_->AddProfile(autofill_profile);
562
563 suggester_->Suggest(base::UTF8ToUTF16("my name is "));
564 SendKeyboardEvent("Esc");
565 suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
566 EXPECT_FALSE(suggestion_handler_->IsSuggestionAccepted());
567 }
568
TEST_F(PersonalInfoSuggesterTest,SuggestWithConfirmedLength)569 TEST_F(PersonalInfoSuggesterTest, SuggestWithConfirmedLength) {
570 base::test::ScopedFeatureList feature_list;
571 feature_list.InitWithFeatures(
572 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoPhoneNumber},
573 /*disabled_features=*/{});
574
575 autofill::AutofillProfile autofill_profile(base::GenerateGUID(),
576 autofill::test::kEmptyOrigin);
577 autofill_profile.SetRawInfo(
578 autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER, phone_number_);
579 personal_data_->AddProfile(autofill_profile);
580
581 suggester_->Suggest(base::UTF8ToUTF16("my phone number is "));
582 suggester_->Suggest(base::UTF8ToUTF16("my phone number is 16"));
583 suggestion_handler_->VerifySuggestion(phone_number_, 2);
584 }
585
TEST_F(PersonalInfoSuggesterTest,DoNotAnnounceSpokenFeedbackWhenChromeVoxIsOff)586 TEST_F(PersonalInfoSuggesterTest,
587 DoNotAnnounceSpokenFeedbackWhenChromeVoxIsOff) {
588 base::test::ScopedFeatureList feature_list;
589 feature_list.InitWithFeatures(
590 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
591 /*disabled_features=*/{});
592
593 profile_->set_profile_name(base::UTF16ToUTF8(email_));
594 profile_->GetPrefs()->SetBoolean(
595 ash::prefs::kAccessibilitySpokenFeedbackEnabled, false);
596
597 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
598 task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5000));
599 tts_handler_->VerifyAnnouncement("");
600
601 SendKeyboardEvent("Down");
602 SendKeyboardEvent("Enter");
603 task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5000));
604 tts_handler_->VerifyAnnouncement("");
605 }
606
TEST_F(PersonalInfoSuggesterTest,AnnounceSpokenFeedbackWhenChromeVoxIsOn)607 TEST_F(PersonalInfoSuggesterTest, AnnounceSpokenFeedbackWhenChromeVoxIsOn) {
608 base::test::ScopedFeatureList feature_list;
609 feature_list.InitWithFeatures(
610 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
611 /*disabled_features=*/{});
612
613 profile_->set_profile_name(base::UTF16ToUTF8(email_));
614 profile_->GetPrefs()->SetBoolean(
615 ash::prefs::kAccessibilitySpokenFeedbackEnabled, true);
616
617 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
618 task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(500));
619 tts_handler_->VerifyAnnouncement("");
620
621 task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1000));
622 tts_handler_->VerifyAnnouncement(
623 "Personal info suggested. Press down arrow to access; escape to ignore.");
624
625 SendKeyboardEvent("Down");
626 SendKeyboardEvent("Enter");
627 task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(200));
628 tts_handler_->VerifyAnnouncement("Suggestion inserted.");
629
630 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
631 task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1500));
632 tts_handler_->VerifyAnnouncement(
633 "Personal info suggested. Press down arrow to access; escape to ignore.");
634 SendKeyboardEvent("Esc");
635 task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(200));
636 tts_handler_->VerifyAnnouncement("Suggestion dismissed.");
637 }
638
TEST_F(PersonalInfoSuggesterTest,DoNotShowAnnotationAfterMaxAcceptanceCount)639 TEST_F(PersonalInfoSuggesterTest, DoNotShowAnnotationAfterMaxAcceptanceCount) {
640 base::test::ScopedFeatureList feature_list;
641 feature_list.InitWithFeatures(
642 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
643 /*disabled_features=*/{});
644
645 for (int i = 0; i < kMaxAcceptanceCount; i++) {
646 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
647 SendKeyboardEvent("Down");
648 SendKeyboardEvent("Enter");
649 suggestion_handler_->VerifyShowAnnotation(true);
650 }
651 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
652 suggestion_handler_->VerifyShowAnnotation(false);
653 }
654
TEST_F(PersonalInfoSuggesterTest,ShowSettingLink)655 TEST_F(PersonalInfoSuggesterTest, ShowSettingLink) {
656 base::test::ScopedFeatureList feature_list;
657 feature_list.InitWithFeatures(
658 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
659 /*disabled_features=*/{});
660
661 DictionaryPrefUpdate update(profile_->GetPrefs(),
662 prefs::kAssistiveInputFeatureSettings);
663 update->RemoveKey(kPersonalInfoSuggesterShowSettingCount);
664 update->RemoveKey(kPersonalInfoSuggesterAcceptanceCount);
665 for (int i = 0; i < kMaxShowSettingCount; i++) {
666 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
667 // Dismiss suggestion.
668 SendKeyboardEvent("Esc");
669 suggestion_handler_->VerifyShowSettingLink(true);
670 }
671 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
672 suggestion_handler_->VerifyShowSettingLink(false);
673 }
674
TEST_F(PersonalInfoSuggesterTest,DoNotShowSettingLinkAfterAcceptance)675 TEST_F(PersonalInfoSuggesterTest, DoNotShowSettingLinkAfterAcceptance) {
676 base::test::ScopedFeatureList feature_list;
677 feature_list.InitWithFeatures(
678 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
679 /*disabled_features=*/{});
680
681 DictionaryPrefUpdate update(profile_->GetPrefs(),
682 prefs::kAssistiveInputFeatureSettings);
683 update->SetIntKey(kPersonalInfoSuggesterShowSettingCount, 0);
684 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
685 suggestion_handler_->VerifyShowSettingLink(true);
686 // Accept suggestion.
687 SendKeyboardEvent("Down");
688 SendKeyboardEvent("Enter");
689 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
690 suggestion_handler_->VerifyShowSettingLink(false);
691 }
692
TEST_F(PersonalInfoSuggesterTest,ClickSettingsWithDownDownEnter)693 TEST_F(PersonalInfoSuggesterTest, ClickSettingsWithDownDownEnter) {
694 base::test::ScopedFeatureList feature_list;
695 feature_list.InitWithFeatures(
696 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
697 /*disabled_features=*/{});
698
699 DictionaryPrefUpdate update(profile_->GetPrefs(),
700 prefs::kAssistiveInputFeatureSettings);
701 update->RemoveKey(kPersonalInfoSuggesterShowSettingCount);
702 update->RemoveKey(kPersonalInfoSuggesterAcceptanceCount);
703 profile_->set_profile_name(base::UTF16ToUTF8(email_));
704
705 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
706 SendKeyboardEvent("Down");
707 SendKeyboardEvent("Down");
708 SendKeyboardEvent("Enter");
709
710 suggestion_handler_->VerifyButtonClicked(
711 ui::ime::ButtonId::kSmartInputsSettingLink);
712 }
713
TEST_F(PersonalInfoSuggesterTest,ClickSettingsWithUpEnter)714 TEST_F(PersonalInfoSuggesterTest, ClickSettingsWithUpEnter) {
715 base::test::ScopedFeatureList feature_list;
716 feature_list.InitWithFeatures(
717 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
718 /*disabled_features=*/{});
719
720 DictionaryPrefUpdate update(profile_->GetPrefs(),
721 prefs::kAssistiveInputFeatureSettings);
722 update->RemoveKey(kPersonalInfoSuggesterShowSettingCount);
723 update->RemoveKey(kPersonalInfoSuggesterAcceptanceCount);
724 profile_->set_profile_name(base::UTF16ToUTF8(email_));
725
726 suggester_->Suggest(base::UTF8ToUTF16("my email is "));
727 SendKeyboardEvent("Up");
728 SendKeyboardEvent("Enter");
729
730 suggestion_handler_->VerifyButtonClicked(
731 ui::ime::ButtonId::kSmartInputsSettingLink);
732 }
733
TEST_F(PersonalInfoSuggesterTest,RecordsTimeToAccept)734 TEST_F(PersonalInfoSuggesterTest, RecordsTimeToAccept) {
735 base::test::ScopedFeatureList feature_list;
736 feature_list.InitWithFeatures(
737 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
738 /*disabled_features=*/{});
739
740 base::HistogramTester histogram_tester;
741 histogram_tester.ExpectTotalCount(
742 "InputMethod.Assistive.TimeToAccept.PersonalInfo", 0);
743
744 profile_->set_profile_name(base::UTF16ToUTF8(email_));
745
746 EXPECT_TRUE(suggester_->Suggest(base::UTF8ToUTF16("my email is ")));
747
748 // Press "Down" to choose and accept the suggestion.
749 SendKeyboardEvent("Down");
750 SendKeyboardEvent("Enter");
751 histogram_tester.ExpectTotalCount(
752 "InputMethod.Assistive.TimeToAccept.PersonalInfo", 1);
753 }
754
TEST_F(PersonalInfoSuggesterTest,RecordsTimeToDismiss)755 TEST_F(PersonalInfoSuggesterTest, RecordsTimeToDismiss) {
756 base::test::ScopedFeatureList feature_list;
757 feature_list.InitWithFeatures(
758 /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
759 /*disabled_features=*/{});
760
761 base::HistogramTester histogram_tester;
762 histogram_tester.ExpectTotalCount(
763 "InputMethod.Assistive.TimeToAccept.PersonalInfo", 0);
764
765 profile_->set_profile_name(base::UTF16ToUTF8(email_));
766
767 EXPECT_TRUE(suggester_->Suggest(base::UTF8ToUTF16("my email is ")));
768 // Press "Esc" to dismiss.
769 SendKeyboardEvent("Esc");
770 histogram_tester.ExpectTotalCount(
771 "InputMethod.Assistive.TimeToDismiss.PersonalInfo", 1);
772 }
773
774 } // namespace chromeos
775