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