1 // Copyright 2018 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/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h"
6
7 #include <utility>
8
9 #include "base/metrics/histogram_macros.h"
10 #include "chrome/browser/consent_auditor/consent_auditor_factory.h"
11 #include "chrome/browser/signin/identity_manager_factory.h"
12 #include "chrome/browser/ui/webui/chromeos/user_image_source.h"
13 #include "chrome/grit/browser_resources.h"
14 #include "chrome/grit/generated_resources.h"
15 #include "chromeos/audio/cras_audio_handler.h"
16 #include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
17 #include "chromeos/services/assistant/public/features.h"
18 #include "components/arc/arc_prefs.h"
19 #include "components/consent_auditor/consent_auditor.h"
20 #include "components/prefs/pref_service.h"
21 #include "components/signin/public/identity_manager/consent_level.h"
22 #include "components/signin/public/identity_manager/identity_manager.h"
23 #include "components/user_manager/user_manager.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/webui/web_ui_util.h"
26
27 namespace {
28
IsPreferenceDefaultEnabled(const PrefService * prefs,const std::string & path)29 bool IsPreferenceDefaultEnabled(const PrefService* prefs,
30 const std::string& path) {
31 const PrefService::Preference* pref = prefs->FindPreference(path);
32
33 if (pref->IsManaged())
34 return pref->GetValue()->GetBool();
35
36 if (pref->GetRecommendedValue())
37 return pref->GetRecommendedValue()->GetBool();
38
39 return true;
40 }
41
IsScreenContextDefaultEnabled(PrefService * prefs)42 bool IsScreenContextDefaultEnabled(PrefService* prefs) {
43 return IsPreferenceDefaultEnabled(
44 prefs, chromeos::assistant::prefs::kAssistantContextEnabled);
45 }
46
IsScreenContextToggleDisabled(PrefService * prefs)47 bool IsScreenContextToggleDisabled(PrefService* prefs) {
48 return prefs->IsManagedPreference(
49 chromeos::assistant::prefs::kAssistantContextEnabled);
50 }
51
52 } // namespace
53
54 namespace chromeos {
55
RecordAssistantOptInStatus(AssistantOptInFlowStatus status)56 void RecordAssistantOptInStatus(AssistantOptInFlowStatus status) {
57 UMA_HISTOGRAM_ENUMERATION("Assistant.OptInFlowStatus", status, kMaxValue + 1);
58 }
59
60 // Construct SettingsUiSelector for the ConsentFlow UI.
GetSettingsUiSelector()61 assistant::SettingsUiSelector GetSettingsUiSelector() {
62 assistant::SettingsUiSelector selector;
63 assistant::ConsentFlowUiSelector* consent_flow_ui =
64 selector.mutable_consent_flow_ui_selector();
65 consent_flow_ui->set_flow_id(assistant::ActivityControlSettingsUiSelector::
66 ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS);
67 selector.set_email_opt_in(true);
68 selector.set_gaia_user_context_ui(true);
69 return selector;
70 }
71
72 // Construct SettingsUiUpdate for user opt-in.
GetSettingsUiUpdate(const std::string & consent_token)73 assistant::SettingsUiUpdate GetSettingsUiUpdate(
74 const std::string& consent_token) {
75 assistant::SettingsUiUpdate update;
76 assistant::ConsentFlowUiUpdate* consent_flow_update =
77 update.mutable_consent_flow_ui_update();
78 consent_flow_update->set_flow_id(
79 assistant::ActivityControlSettingsUiSelector::
80 ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS);
81 consent_flow_update->set_consent_token(consent_token);
82
83 return update;
84 }
85
86 // Construct SettingsUiUpdate for email opt-in.
GetEmailOptInUpdate(bool opted_in)87 assistant::SettingsUiUpdate GetEmailOptInUpdate(bool opted_in) {
88 assistant::SettingsUiUpdate update;
89 assistant::EmailOptInUpdate* email_optin_update =
90 update.mutable_email_opt_in_update();
91 email_optin_update->set_email_opt_in_update_state(
92 opted_in ? assistant::EmailOptInUpdate::OPT_IN
93 : assistant::EmailOptInUpdate::OPT_OUT);
94
95 return update;
96 }
97
98 // Helper method to create zippy data.
CreateZippyData(const SettingZippyList & zippy_list)99 base::Value CreateZippyData(const SettingZippyList& zippy_list) {
100 base::Value zippy_data(base::Value::Type::LIST);
101 for (auto& setting_zippy : zippy_list) {
102 base::Value data(base::Value::Type::DICTIONARY);
103 data.SetKey("title", base::Value(setting_zippy.title()));
104 if (setting_zippy.description_paragraph_size()) {
105 data.SetKey("description",
106 base::Value(setting_zippy.description_paragraph(0)));
107 }
108 if (setting_zippy.additional_info_paragraph_size()) {
109 data.SetKey("additionalInfo",
110 base::Value(setting_zippy.additional_info_paragraph(0)));
111 }
112 data.SetKey("iconUri", base::Value(setting_zippy.icon_uri()));
113 data.SetKey("popupLink", base::Value(l10n_util::GetStringUTF16(
114 IDS_ASSISTANT_ACTIVITY_CONTROL_POPUP_LINK)));
115 zippy_data.Append(std::move(data));
116 }
117 return zippy_data;
118 }
119
120 // Helper method to create disclosure data.
CreateDisclosureData(const SettingZippyList & disclosure_list)121 base::Value CreateDisclosureData(const SettingZippyList& disclosure_list) {
122 base::Value disclosure_data(base::Value::Type::LIST);
123 for (auto& disclosure : disclosure_list) {
124 base::Value data(base::Value::Type::DICTIONARY);
125 data.SetKey("title", base::Value(disclosure.title()));
126 if (disclosure.description_paragraph_size()) {
127 data.SetKey("description",
128 base::Value(disclosure.description_paragraph(0)));
129 }
130 if (disclosure.additional_info_paragraph_size()) {
131 data.SetKey("additionalInfo",
132 base::Value(disclosure.additional_info_paragraph(0)));
133 }
134 data.SetKey("iconUri", base::Value(disclosure.icon_uri()));
135 disclosure_data.Append(std::move(data));
136 }
137 return disclosure_data;
138 }
139
140 // Helper method to create get more screen data.
CreateGetMoreData(bool email_optin_needed,const assistant::EmailOptInUi & email_optin_ui,PrefService * prefs)141 base::Value CreateGetMoreData(bool email_optin_needed,
142 const assistant::EmailOptInUi& email_optin_ui,
143 PrefService* prefs) {
144 base::Value get_more_data(base::Value::Type::LIST);
145
146 // Process screen context data.
147 base::Value context_data(base::Value::Type::DICTIONARY);
148 context_data.SetKey("id", base::Value("context"));
149 context_data.SetKey("title", base::Value(l10n_util::GetStringUTF16(
150 IDS_ASSISTANT_SCREEN_CONTEXT_TITLE)));
151 context_data.SetKey("description", base::Value(l10n_util::GetStringUTF16(
152 IDS_ASSISTANT_SCREEN_CONTEXT_DESC)));
153 context_data.SetKey("defaultEnabled",
154 base::Value(IsScreenContextDefaultEnabled(prefs)));
155 context_data.SetKey("toggleDisabled",
156 base::Value(IsScreenContextToggleDisabled(prefs)));
157 context_data.SetKey(
158 "iconUri",
159 base::Value("https://www.gstatic.com/images/icons/material/system/"
160 "2x/screen_search_desktop_grey600_24dp.png"));
161 get_more_data.Append(std::move(context_data));
162
163 // Process email optin data.
164 if (email_optin_needed) {
165 base::Value data(base::Value::Type::DICTIONARY);
166 data.SetKey("id", base::Value("email"));
167 data.SetKey("title", base::Value(email_optin_ui.title()));
168 data.SetKey("description", base::Value(email_optin_ui.description()));
169 data.SetKey("defaultEnabled",
170 base::Value(email_optin_ui.default_enabled()));
171 data.SetKey("iconUri", base::Value(email_optin_ui.icon_uri()));
172 data.SetKey("legalText", base::Value(email_optin_ui.legal_text()));
173 get_more_data.Append(std::move(data));
174 }
175
176 return get_more_data;
177 }
178
179 // Get string constants for settings ui.
GetSettingsUiStrings(const assistant::SettingsUi & settings_ui,bool activity_control_needed)180 base::Value GetSettingsUiStrings(const assistant::SettingsUi& settings_ui,
181 bool activity_control_needed) {
182 auto consent_ui = settings_ui.consent_flow_ui().consent_ui();
183 auto activity_control_ui = consent_ui.activity_control_ui();
184 auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui();
185 base::Value dictionary(base::Value::Type::DICTIONARY);
186
187 // Add activity control string constants.
188 if (activity_control_needed) {
189 scoped_refptr<base::RefCountedMemory> image =
190 chromeos::UserImageSource::GetUserImage(
191 user_manager::UserManager::Get()->GetActiveUser()->GetAccountId());
192 std::string icon_url = webui::GetPngDataUrl(image->front(), image->size());
193 dictionary.SetKey("valuePropUserImage", base::Value(icon_url));
194
195 dictionary.SetKey("valuePropIdentity",
196 base::Value(activity_control_ui.identity()));
197 dictionary.SetKey("valuePropTitle",
198 base::Value(activity_control_ui.title()));
199 if (activity_control_ui.intro_text_paragraph_size()) {
200 dictionary.SetKey(
201 "valuePropIntro",
202 base::Value(activity_control_ui.intro_text_paragraph(0)));
203 }
204 if (activity_control_ui.footer_paragraph_size()) {
205 dictionary.SetKey("valuePropFooter",
206 base::Value(activity_control_ui.footer_paragraph(0)));
207 }
208 dictionary.SetKey("valuePropNextButton",
209 base::Value(consent_ui.accept_button_text()));
210 dictionary.SetKey("valuePropSkipButton",
211 base::Value(consent_ui.reject_button_text()));
212 }
213
214 // Add third party string constants.
215 dictionary.SetKey("thirdPartyTitle",
216 base::Value(third_party_disclosure_ui.title()));
217 dictionary.SetKey("thirdPartyContinueButton",
218 base::Value(third_party_disclosure_ui.button_continue()));
219 dictionary.SetKey("thirdPartyFooter", base::Value(consent_ui.tos_pp_links()));
220
221 return dictionary;
222 }
223
RecordActivityControlConsent(Profile * profile,std::string ui_audit_key,bool opted_in)224 void RecordActivityControlConsent(Profile* profile,
225 std::string ui_audit_key,
226 bool opted_in) {
227 auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
228 // This function doesn't care about browser sync consent.
229 DCHECK(
230 identity_manager->HasPrimaryAccount(signin::ConsentLevel::kNotRequired));
231 const CoreAccountId account_id =
232 identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kNotRequired);
233
234 using sync_pb::UserConsentTypes;
235 UserConsentTypes::AssistantActivityControlConsent consent;
236 consent.set_ui_audit_key(ui_audit_key);
237 consent.set_status(opted_in ? UserConsentTypes::GIVEN
238 : UserConsentTypes::NOT_GIVEN);
239
240 ConsentAuditorFactory::GetForProfile(profile)
241 ->RecordAssistantActivityControlConsent(account_id, consent);
242 }
243
IsHotwordDspAvailable()244 bool IsHotwordDspAvailable() {
245 return chromeos::CrasAudioHandler::Get()->HasHotwordDevice();
246 }
247
IsVoiceMatchEnforcedOff(const PrefService * prefs)248 bool IsVoiceMatchEnforcedOff(const PrefService* prefs) {
249 // If the hotword preference is managed to always disabled, then we should not
250 // show Voice Match flow.
251 return prefs->IsManagedPreference(
252 assistant::prefs::kAssistantHotwordEnabled) &&
253 !prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled);
254 }
255
256 } // namespace chromeos
257