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/ui/webui/settings/chromeos/device_section.h"
6 
7 #include "ash/public/ash_interfaces.h"
8 #include "ash/public/cpp/ash_features.h"
9 #include "ash/public/cpp/night_light_controller.h"
10 #include "ash/public/cpp/stylus_utils.h"
11 #include "base/command_line.h"
12 #include "base/feature_list.h"
13 #include "base/metrics/histogram_functions.h"
14 #include "base/no_destructor.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
18 #include "chrome/browser/ui/ui_features.h"
19 #include "chrome/browser/ui/webui/settings/chromeos/device_display_handler.h"
20 #include "chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h"
21 #include "chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h"
22 #include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
23 #include "chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h"
24 #include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h"
25 #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h"
26 #include "chrome/browser/ui/webui/webui_util.h"
27 #include "chrome/common/chrome_features.h"
28 #include "chrome/common/url_constants.h"
29 #include "chrome/common/webui_url_constants.h"
30 #include "chrome/grit/generated_resources.h"
31 #include "chromeos/constants/chromeos_features.h"
32 #include "chromeos/constants/chromeos_switches.h"
33 #include "content/public/browser/web_ui.h"
34 #include "content/public/browser/web_ui_data_source.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/webui/web_ui_util.h"
37 #include "ui/chromeos/events/keyboard_layout_util.h"
38 #include "ui/display/display_features.h"
39 #include "ui/display/display_switches.h"
40 #include "ui/display/manager/touch_device_manager.h"
41 #include "ui/events/devices/device_data_manager.h"
42 
43 namespace chromeos {
44 namespace settings {
45 namespace {
46 
GetDeviceSearchConcepts()47 const std::vector<SearchConcept>& GetDeviceSearchConcepts() {
48   static const base::NoDestructor<std::vector<SearchConcept>> tags({
49       {IDS_OS_SETTINGS_TAG_KEYBOARD,
50        mojom::kKeyboardSubpagePath,
51        mojom::SearchResultIcon::kKeyboard,
52        mojom::SearchResultDefaultRank::kMedium,
53        mojom::SearchResultType::kSubpage,
54        {.subpage = mojom::Subpage::kKeyboard}},
55       {IDS_OS_SETTINGS_TAG_KEYBOARD_AUTO_REPEAT,
56        mojom::kKeyboardSubpagePath,
57        mojom::SearchResultIcon::kKeyboard,
58        mojom::SearchResultDefaultRank::kMedium,
59        mojom::SearchResultType::kSetting,
60        {.setting = mojom::Setting::kKeyboardAutoRepeat},
61        {IDS_OS_SETTINGS_TAG_KEYBOARD_AUTO_REPEAT_ALT1,
62         SearchConcept::kAltTagEnd}},
63       {IDS_OS_SETTINGS_TAG_POWER,
64        mojom::kPowerSubpagePath,
65        mojom::SearchResultIcon::kPower,
66        mojom::SearchResultDefaultRank::kMedium,
67        mojom::SearchResultType::kSubpage,
68        {.subpage = mojom::Subpage::kPower}},
69       {IDS_OS_SETTINGS_TAG_DISPLAY_SIZE,
70        mojom::kDisplaySubpagePath,
71        mojom::SearchResultIcon::kDisplay,
72        mojom::SearchResultDefaultRank::kMedium,
73        mojom::SearchResultType::kSetting,
74        {.setting = mojom::Setting::kDisplaySize},
75        {
76            IDS_OS_SETTINGS_TAG_DISPLAY_SIZE_ALT1,
77            IDS_OS_SETTINGS_TAG_DISPLAY_SIZE_ALT2,
78            IDS_OS_SETTINGS_TAG_DISPLAY_SIZE_ALT3,
79            IDS_OS_SETTINGS_TAG_DISPLAY_SIZE_ALT4,
80            IDS_OS_SETTINGS_TAG_DISPLAY_SIZE_ALT5,
81        }},
82       {IDS_OS_SETTINGS_TAG_STORAGE,
83        mojom::kStorageSubpagePath,
84        mojom::SearchResultIcon::kHardDrive,
85        mojom::SearchResultDefaultRank::kMedium,
86        mojom::SearchResultType::kSubpage,
87        {.subpage = mojom::Subpage::kStorage},
88        {IDS_OS_SETTINGS_TAG_STORAGE_ALT1, IDS_OS_SETTINGS_TAG_STORAGE_ALT2,
89         SearchConcept::kAltTagEnd}},
90       {IDS_OS_SETTINGS_TAG_DISPLAY_NIGHT_LIGHT,
91        mojom::kDisplaySubpagePath,
92        mojom::SearchResultIcon::kDisplay,
93        mojom::SearchResultDefaultRank::kLow,
94        mojom::SearchResultType::kSetting,
95        {.setting = mojom::Setting::kNightLight},
96        {IDS_OS_SETTINGS_TAG_DISPLAY_NIGHT_LIGHT_ALT1,
97         IDS_OS_SETTINGS_TAG_DISPLAY_NIGHT_LIGHT_ALT2,
98         SearchConcept::kAltTagEnd}},
99       {IDS_OS_SETTINGS_TAG_DISPLAY,
100        mojom::kDisplaySubpagePath,
101        mojom::SearchResultIcon::kDisplay,
102        mojom::SearchResultDefaultRank::kMedium,
103        mojom::SearchResultType::kSubpage,
104        {.subpage = mojom::Subpage::kDisplay},
105        {IDS_OS_SETTINGS_TAG_DISPLAY_ALT1, IDS_OS_SETTINGS_TAG_DISPLAY_ALT2,
106         SearchConcept::kAltTagEnd}},
107       {IDS_OS_SETTINGS_TAG_KEYBOARD_SHORTCUTS,
108        mojom::kKeyboardSubpagePath,
109        mojom::SearchResultIcon::kKeyboard,
110        mojom::SearchResultDefaultRank::kMedium,
111        mojom::SearchResultType::kSetting,
112        {.setting = mojom::Setting::kKeyboardShortcuts}},
113       {IDS_OS_SETTINGS_TAG_DEVICE,
114        mojom::kDeviceSectionPath,
115        mojom::SearchResultIcon::kLaptop,
116        mojom::SearchResultDefaultRank::kHigh,
117        mojom::SearchResultType::kSection,
118        {.section = mojom::Section::kDevice}},
119       {IDS_OS_SETTINGS_TAG_KEYBOARD_FUNCTION_KEYS,
120        mojom::kKeyboardSubpagePath,
121        mojom::SearchResultIcon::kKeyboard,
122        mojom::SearchResultDefaultRank::kMedium,
123        mojom::SearchResultType::kSetting,
124        {.setting = mojom::Setting::kKeyboardFunctionKeys}},
125       {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING,
126        mojom::kPowerSubpagePath,
127        mojom::SearchResultIcon::kPower,
128        mojom::SearchResultDefaultRank::kMedium,
129        mojom::SearchResultType::kSetting,
130        {.setting = mojom::Setting::kPowerIdleBehaviorWhileCharging},
131        {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING_ALT1,
132         SearchConcept::kAltTagEnd}},
133       {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY,
134        mojom::kPowerSubpagePath,
135        mojom::SearchResultIcon::kPower,
136        mojom::SearchResultDefaultRank::kMedium,
137        mojom::SearchResultType::kSetting,
138        {.setting = mojom::Setting::kPowerIdleBehaviorWhileOnBattery},
139        {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY_ALT1,
140         SearchConcept::kAltTagEnd}},
141   });
142   return *tags;
143 }
144 
GetTouchpadSearchConcepts()145 const std::vector<SearchConcept>& GetTouchpadSearchConcepts() {
146   static const base::NoDestructor<std::vector<SearchConcept>> tags({
147       {IDS_OS_SETTINGS_TAG_TOUCHPAD_SPEED,
148        mojom::kPointersSubpagePath,
149        mojom::SearchResultIcon::kLaptop,
150        mojom::SearchResultDefaultRank::kMedium,
151        mojom::SearchResultType::kSetting,
152        {.setting = mojom::Setting::kTouchpadSpeed}},
153       {IDS_OS_SETTINGS_TAG_TOUCHPAD_TAP_DRAGGING,
154        mojom::kPointersSubpagePath,
155        mojom::SearchResultIcon::kLaptop,
156        mojom::SearchResultDefaultRank::kMedium,
157        mojom::SearchResultType::kSetting,
158        {.setting = mojom::Setting::kTouchpadTapDragging}},
159       {IDS_OS_SETTINGS_TAG_TOUCHPAD_TAP_TO_CLICK,
160        mojom::kPointersSubpagePath,
161        mojom::SearchResultIcon::kLaptop,
162        mojom::SearchResultDefaultRank::kMedium,
163        mojom::SearchResultType::kSetting,
164        {.setting = mojom::Setting::kTouchpadTapToClick}},
165       {IDS_OS_SETTINGS_TAG_TOUCHPAD,
166        mojom::kPointersSubpagePath,
167        mojom::SearchResultIcon::kLaptop,
168        mojom::SearchResultDefaultRank::kMedium,
169        mojom::SearchResultType::kSubpage,
170        {.subpage = mojom::Subpage::kPointers},
171        {IDS_OS_SETTINGS_TAG_TOUCHPAD_ALT1, SearchConcept::kAltTagEnd}},
172       {IDS_OS_SETTINGS_TAG_TOUCHPAD_REVERSE_SCROLLING,
173        mojom::kPointersSubpagePath,
174        mojom::SearchResultIcon::kLaptop,
175        mojom::SearchResultDefaultRank::kMedium,
176        mojom::SearchResultType::kSetting,
177        {.setting = mojom::Setting::kTouchpadReverseScrolling}},
178       {IDS_OS_SETTINGS_TAG_TOUCHPAD_ACCELERATION,
179        mojom::kPointersSubpagePath,
180        mojom::SearchResultIcon::kLaptop,
181        mojom::SearchResultDefaultRank::kMedium,
182        mojom::SearchResultType::kSetting,
183        {.setting = mojom::Setting::kTouchpadAcceleration}},
184   });
185   return *tags;
186 }
187 
188 const std::vector<SearchConcept>&
GetTouchpadScrollAccelerationSearchConcepts()189 GetTouchpadScrollAccelerationSearchConcepts() {
190   static const base::NoDestructor<std::vector<SearchConcept>> tags({
191       {IDS_OS_SETTINGS_TAG_TOUCHPAD_SCROLL_ACCELERATION,
192        mojom::kPointersSubpagePath,
193        mojom::SearchResultIcon::kLaptop,
194        mojom::SearchResultDefaultRank::kMedium,
195        mojom::SearchResultType::kSetting,
196        {.setting = mojom::Setting::kTouchpadScrollAcceleration}},
197   });
198   return *tags;
199 }
200 
GetMouseSearchConcepts()201 const std::vector<SearchConcept>& GetMouseSearchConcepts() {
202   static const base::NoDestructor<std::vector<SearchConcept>> tags({
203       {IDS_OS_SETTINGS_TAG_MOUSE_ACCELERATION,
204        mojom::kPointersSubpagePath,
205        mojom::SearchResultIcon::kMouse,
206        mojom::SearchResultDefaultRank::kMedium,
207        mojom::SearchResultType::kSetting,
208        {.setting = mojom::Setting::kMouseAcceleration}},
209       {IDS_OS_SETTINGS_TAG_MOUSE_SWAP_BUTTON,
210        mojom::kPointersSubpagePath,
211        mojom::SearchResultIcon::kMouse,
212        mojom::SearchResultDefaultRank::kMedium,
213        mojom::SearchResultType::kSetting,
214        {.setting = mojom::Setting::kMouseSwapPrimaryButtons}},
215       {IDS_OS_SETTINGS_TAG_MOUSE_SPEED,
216        mojom::kPointersSubpagePath,
217        mojom::SearchResultIcon::kMouse,
218        mojom::SearchResultDefaultRank::kMedium,
219        mojom::SearchResultType::kSetting,
220        {.setting = mojom::Setting::kMouseSpeed}},
221       {IDS_OS_SETTINGS_TAG_MOUSE_REVERSE_SCROLLING,
222        mojom::kPointersSubpagePath,
223        mojom::SearchResultIcon::kMouse,
224        mojom::SearchResultDefaultRank::kMedium,
225        mojom::SearchResultType::kSetting,
226        {.setting = mojom::Setting::kMouseReverseScrolling}},
227       {IDS_OS_SETTINGS_TAG_MOUSE,
228        mojom::kPointersSubpagePath,
229        mojom::SearchResultIcon::kMouse,
230        mojom::SearchResultDefaultRank::kMedium,
231        mojom::SearchResultType::kSubpage,
232        {.subpage = mojom::Subpage::kPointers}},
233       {IDS_OS_SETTINGS_TAG_MOUSE_SCROLL_ACCELERATION,
234        mojom::kPointersSubpagePath,
235        mojom::SearchResultIcon::kMouse,
236        mojom::SearchResultDefaultRank::kMedium,
237        mojom::SearchResultType::kSetting,
238        {.setting = mojom::Setting::kMouseScrollAcceleration}},
239   });
240   return *tags;
241 }
242 
GetStylusSearchConcepts()243 const std::vector<SearchConcept>& GetStylusSearchConcepts() {
244   static const base::NoDestructor<std::vector<SearchConcept>> tags({
245       {IDS_OS_SETTINGS_TAG_STYLUS_NOTE_APP,
246        mojom::kStylusSubpagePath,
247        mojom::SearchResultIcon::kStylus,
248        mojom::SearchResultDefaultRank::kMedium,
249        mojom::SearchResultType::kSetting,
250        {.setting = mojom::Setting::kStylusNoteTakingApp},
251        {IDS_OS_SETTINGS_TAG_STYLUS_NOTE_APP_ALT1,
252         IDS_OS_SETTINGS_TAG_STYLUS_NOTE_APP_ALT2, SearchConcept::kAltTagEnd}},
253       {IDS_OS_SETTINGS_TAG_STYLUS_LOCK_SCREEN_LATEST_NOTE,
254        mojom::kStylusSubpagePath,
255        mojom::SearchResultIcon::kStylus,
256        mojom::SearchResultDefaultRank::kMedium,
257        mojom::SearchResultType::kSetting,
258        {.setting = mojom::Setting::kStylusLatestNoteOnLockScreen}},
259       {IDS_OS_SETTINGS_TAG_STYLUS_LOCK_SCREEN_NOTES,
260        mojom::kStylusSubpagePath,
261        mojom::SearchResultIcon::kStylus,
262        mojom::SearchResultDefaultRank::kMedium,
263        mojom::SearchResultType::kSetting,
264        {.setting = mojom::Setting::kStylusNoteTakingFromLockScreen}},
265       {IDS_OS_SETTINGS_TAG_STYLUS_SHELF_TOOLS,
266        mojom::kStylusSubpagePath,
267        mojom::SearchResultIcon::kStylus,
268        mojom::SearchResultDefaultRank::kMedium,
269        mojom::SearchResultType::kSetting,
270        {.setting = mojom::Setting::kStylusToolsInShelf},
271        {IDS_OS_SETTINGS_TAG_STYLUS_SHELF_TOOLS_ALT1,
272         IDS_OS_SETTINGS_TAG_STYLUS_SHELF_TOOLS_ALT2,
273         SearchConcept::kAltTagEnd}},
274       {IDS_OS_SETTINGS_TAG_STYLUS,
275        mojom::kStylusSubpagePath,
276        mojom::SearchResultIcon::kStylus,
277        mojom::SearchResultDefaultRank::kMedium,
278        mojom::SearchResultType::kSubpage,
279        {.subpage = mojom::Subpage::kStylus}},
280   });
281   return *tags;
282 }
283 
GetDisplayArrangementSearchConcepts()284 const std::vector<SearchConcept>& GetDisplayArrangementSearchConcepts() {
285   static const base::NoDestructor<std::vector<SearchConcept>> tags({
286       {IDS_OS_SETTINGS_TAG_DISPLAY_ARRANGEMENT,
287        mojom::kDisplaySubpagePath,
288        mojom::SearchResultIcon::kDisplay,
289        mojom::SearchResultDefaultRank::kMedium,
290        mojom::SearchResultType::kSetting,
291        {.setting = mojom::Setting::kDisplayArrangement},
292        {IDS_OS_SETTINGS_TAG_DISPLAY_ARRANGEMENT_ALT1,
293         IDS_OS_SETTINGS_TAG_DISPLAY_ARRANGEMENT_ALT2,
294         SearchConcept::kAltTagEnd}},
295   });
296   return *tags;
297 }
298 
GetDisplayMirrorSearchConcepts()299 const std::vector<SearchConcept>& GetDisplayMirrorSearchConcepts() {
300   static const base::NoDestructor<std::vector<SearchConcept>> tags({
301       {IDS_OS_SETTINGS_TAG_MIRRORING,
302        mojom::kDisplaySubpagePath,
303        mojom::SearchResultIcon::kDisplay,
304        mojom::SearchResultDefaultRank::kMedium,
305        mojom::SearchResultType::kSetting,
306        {.setting = mojom::Setting::kDisplayMirroring}},
307   });
308   return *tags;
309 }
310 
GetDisplayUnifiedDesktopSearchConcepts()311 const std::vector<SearchConcept>& GetDisplayUnifiedDesktopSearchConcepts() {
312   static const base::NoDestructor<std::vector<SearchConcept>> tags({
313       {IDS_OS_SETTINGS_TAG_UNIFIED_DESKTOP,
314        mojom::kDisplaySubpagePath,
315        mojom::SearchResultIcon::kDisplay,
316        mojom::SearchResultDefaultRank::kMedium,
317        mojom::SearchResultType::kSetting,
318        {.setting = mojom::Setting::kAllowWindowsToSpanDisplays}},
319   });
320   return *tags;
321 }
322 
GetDisplayExternalSearchConcepts()323 const std::vector<SearchConcept>& GetDisplayExternalSearchConcepts() {
324   static const base::NoDestructor<std::vector<SearchConcept>> tags({
325       {IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION,
326        mojom::kDisplaySubpagePath,
327        mojom::SearchResultIcon::kDisplay,
328        mojom::SearchResultDefaultRank::kMedium,
329        mojom::SearchResultType::kSetting,
330        {.setting = mojom::Setting::kDisplayResolution},
331        {IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION_ALT1,
332         IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION_ALT2,
333         SearchConcept::kAltTagEnd}},
334       {IDS_OS_SETTINGS_TAG_DISPLAY_OVERSCAN,
335        mojom::kDisplaySubpagePath,
336        mojom::SearchResultIcon::kDisplay,
337        mojom::SearchResultDefaultRank::kMedium,
338        mojom::SearchResultType::kSetting,
339        {.setting = mojom::Setting::kDisplayOverscan}},
340   });
341   return *tags;
342 }
343 
344 const std::vector<SearchConcept>&
GetDisplayExternalWithRefreshSearchConcepts()345 GetDisplayExternalWithRefreshSearchConcepts() {
346   static const base::NoDestructor<std::vector<SearchConcept>> tags({
347       {IDS_OS_SETTINGS_TAG_DISPLAY_REFRESH_RATE,
348        mojom::kDisplaySubpagePath,
349        mojom::SearchResultIcon::kDisplay,
350        mojom::SearchResultDefaultRank::kMedium,
351        mojom::SearchResultType::kSetting,
352        {.setting = mojom::Setting::kDisplayRefreshRate},
353        {IDS_OS_SETTINGS_TAG_DISPLAY_REFRESH_RATE_ALT1,
354         IDS_OS_SETTINGS_TAG_DISPLAY_REFRESH_RATE_ALT2,
355         SearchConcept::kAltTagEnd}},
356   });
357   return *tags;
358 }
359 
GetDisplayOrientationSearchConcepts()360 const std::vector<SearchConcept>& GetDisplayOrientationSearchConcepts() {
361   static const base::NoDestructor<std::vector<SearchConcept>> tags({
362       {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION,
363        mojom::kDisplaySubpagePath,
364        mojom::SearchResultIcon::kDisplay,
365        mojom::SearchResultDefaultRank::kMedium,
366        mojom::SearchResultType::kSetting,
367        {.setting = mojom::Setting::kDisplayOrientation},
368        {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT1,
369         SearchConcept::kAltTagEnd}},
370   });
371   return *tags;
372 }
373 
GetDisplayAmbientSearchConcepts()374 const std::vector<SearchConcept>& GetDisplayAmbientSearchConcepts() {
375   static const base::NoDestructor<std::vector<SearchConcept>> tags({
376       {IDS_OS_SETTINGS_TAG_DISPLAY_AMBIENT_COLORS,
377        mojom::kDisplaySubpagePath,
378        mojom::SearchResultIcon::kDisplay,
379        mojom::SearchResultDefaultRank::kMedium,
380        mojom::SearchResultType::kSetting,
381        {.setting = mojom::Setting::kAmbientColors}},
382   });
383   return *tags;
384 }
385 
GetDisplayTouchCalibrationSearchConcepts()386 const std::vector<SearchConcept>& GetDisplayTouchCalibrationSearchConcepts() {
387   static const base::NoDestructor<std::vector<SearchConcept>> tags({
388       {IDS_OS_SETTINGS_TAG_DISPLAY_TOUCHSCREEN_CALIBRATION,
389        mojom::kDisplaySubpagePath,
390        mojom::SearchResultIcon::kDisplay,
391        mojom::SearchResultDefaultRank::kMedium,
392        mojom::SearchResultType::kSetting,
393        {.setting = mojom::Setting::kTouchscreenCalibration}},
394   });
395   return *tags;
396 }
397 
GetDisplayNightLightOnSearchConcepts()398 const std::vector<SearchConcept>& GetDisplayNightLightOnSearchConcepts() {
399   static const base::NoDestructor<std::vector<SearchConcept>> tags({
400       {IDS_OS_SETTINGS_TAG_NIGHT_LIGHT_COLOR_TEMPERATURE,
401        mojom::kDisplaySubpagePath,
402        mojom::SearchResultIcon::kDisplay,
403        mojom::SearchResultDefaultRank::kLow,
404        mojom::SearchResultType::kSetting,
405        {.setting = mojom::Setting::kNightLightColorTemperature}},
406   });
407   return *tags;
408 }
409 
GetExternalStorageSearchConcepts()410 const std::vector<SearchConcept>& GetExternalStorageSearchConcepts() {
411   static const base::NoDestructor<std::vector<SearchConcept>> tags({
412       {IDS_OS_SETTINGS_TAG_EXTERNAL_STORAGE,
413        mojom::kExternalStorageSubpagePath,
414        mojom::SearchResultIcon::kHardDrive,
415        mojom::SearchResultDefaultRank::kMedium,
416        mojom::SearchResultType::kSubpage,
417        {.subpage = mojom::Subpage::kExternalStorage}},
418   });
419   return *tags;
420 }
421 
GetPowerWithBatterySearchConcepts()422 const std::vector<SearchConcept>& GetPowerWithBatterySearchConcepts() {
423   static const base::NoDestructor<std::vector<SearchConcept>> tags({
424       {IDS_OS_SETTINGS_TAG_POWER_SOURCE,
425        mojom::kPowerSubpagePath,
426        mojom::SearchResultIcon::kPower,
427        mojom::SearchResultDefaultRank::kMedium,
428        mojom::SearchResultType::kSetting,
429        {.setting = mojom::Setting::kPowerSource},
430        {IDS_OS_SETTINGS_TAG_POWER_SOURCE_ALT1,
431         IDS_OS_SETTINGS_TAG_POWER_SOURCE_ALT2, SearchConcept::kAltTagEnd}},
432   });
433   return *tags;
434 }
435 
GetPowerWithLaptopLidSearchConcepts()436 const std::vector<SearchConcept>& GetPowerWithLaptopLidSearchConcepts() {
437   static const base::NoDestructor<std::vector<SearchConcept>> tags({
438       {IDS_OS_SETTINGS_TAG_POWER_SLEEP_COVER_CLOSED,
439        mojom::kPowerSubpagePath,
440        mojom::SearchResultIcon::kPower,
441        mojom::SearchResultDefaultRank::kMedium,
442        mojom::SearchResultType::kSetting,
443        {.setting = mojom::Setting::kSleepWhenLaptopLidClosed},
444        {IDS_OS_SETTINGS_TAG_POWER_SLEEP_COVER_CLOSED_ALT1,
445         IDS_OS_SETTINGS_TAG_POWER_SLEEP_COVER_CLOSED_ALT2,
446         SearchConcept::kAltTagEnd}},
447   });
448   return *tags;
449 }
450 
IsUnifiedDesktopAvailable()451 bool IsUnifiedDesktopAvailable() {
452   return base::CommandLine::ForCurrentProcess()->HasSwitch(
453       ::switches::kEnableUnifiedDesktop);
454 }
455 
DoesDeviceSupportAmbientColor()456 bool DoesDeviceSupportAmbientColor() {
457   return ash::features::IsAllowAmbientEQEnabled();
458 }
459 
IsTouchCalibrationAvailable()460 bool IsTouchCalibrationAvailable() {
461   return base::CommandLine::ForCurrentProcess()->HasSwitch(
462              switches::kEnableTouchCalibrationSetting) &&
463          display::HasExternalTouchscreenDevice();
464 }
465 
IsListAllDisplayModesEnabled()466 bool IsListAllDisplayModesEnabled() {
467   return display::features::IsListAllDisplayModesEnabled();
468 }
469 
AddDeviceKeyboardStrings(content::WebUIDataSource * html_source)470 void AddDeviceKeyboardStrings(content::WebUIDataSource* html_source) {
471   static constexpr webui::LocalizedString keyboard_strings[] = {
472       {"keyboardTitle", IDS_SETTINGS_KEYBOARD_TITLE},
473       {"keyboardKeyCtrl", IDS_SETTINGS_KEYBOARD_KEY_LEFT_CTRL},
474       {"keyboardKeyAlt", IDS_SETTINGS_KEYBOARD_KEY_LEFT_ALT},
475       {"keyboardKeyCapsLock", IDS_SETTINGS_KEYBOARD_KEY_CAPS_LOCK},
476       {"keyboardKeyCommand", IDS_SETTINGS_KEYBOARD_KEY_COMMAND},
477       {"keyboardKeyDiamond", IDS_SETTINGS_KEYBOARD_KEY_DIAMOND},
478       {"keyboardKeyEscape", IDS_SETTINGS_KEYBOARD_KEY_ESCAPE},
479       {"keyboardKeyBackspace", IDS_SETTINGS_KEYBOARD_KEY_BACKSPACE},
480       {"keyboardKeyAssistant", IDS_SETTINGS_KEYBOARD_KEY_ASSISTANT},
481       {"keyboardKeyDisabled", IDS_SETTINGS_KEYBOARD_KEY_DISABLED},
482       {"keyboardKeyExternalCommand",
483        IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_COMMAND},
484       {"keyboardKeyExternalMeta", IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_META},
485       {"keyboardKeyMeta", IDS_SETTINGS_KEYBOARD_KEY_META},
486       {"keyboardSendFunctionKeys", IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS},
487       {"keyboardEnableAutoRepeat", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_ENABLE},
488       {"keyRepeatDelay", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY},
489       {"keyRepeatDelayLong", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_LONG},
490       {"keyRepeatDelayShort", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_SHORT},
491       {"keyRepeatRate", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE},
492       {"keyRepeatRateSlow", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE_SLOW},
493       {"keyRepeatRateFast", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_FAST},
494       {"showKeyboardShortcutViewer",
495        IDS_SETTINGS_KEYBOARD_SHOW_SHORTCUT_VIEWER},
496       {"keyboardShowLanguageAndInput",
497        IDS_SETTINGS_KEYBOARD_SHOW_LANGUAGE_AND_INPUT},
498       {"keyboardShowInputSettings", IDS_SETTINGS_KEYBOARD_SHOW_INPUT_SETTINGS},
499   };
500   AddLocalizedStringsBulk(html_source, keyboard_strings);
501 
502   html_source->AddLocalizedString("keyboardKeySearch",
503                                   ui::DeviceUsesKeyboardLayout2()
504                                       ? IDS_SETTINGS_KEYBOARD_KEY_LAUNCHER
505                                       : IDS_SETTINGS_KEYBOARD_KEY_SEARCH);
506   html_source->AddLocalizedString(
507       "keyboardSendFunctionKeysDescription",
508       ui::DeviceUsesKeyboardLayout2()
509           ? IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_LAYOUT2_DESCRIPTION
510           : IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_DESCRIPTION);
511 }
512 
AddDeviceStylusStrings(content::WebUIDataSource * html_source)513 void AddDeviceStylusStrings(content::WebUIDataSource* html_source) {
514   static constexpr webui::LocalizedString kStylusStrings[] = {
515       {"stylusTitle", IDS_SETTINGS_STYLUS_TITLE},
516       {"stylusEnableStylusTools", IDS_SETTINGS_STYLUS_ENABLE_STYLUS_TOOLS},
517       {"stylusAutoOpenStylusTools", IDS_SETTINGS_STYLUS_AUTO_OPEN_STYLUS_TOOLS},
518       {"stylusFindMoreAppsPrimary", IDS_SETTINGS_STYLUS_FIND_MORE_APPS_PRIMARY},
519       {"stylusFindMoreAppsSecondary",
520        IDS_SETTINGS_STYLUS_FIND_MORE_APPS_SECONDARY},
521       {"stylusNoteTakingApp", IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LABEL},
522       {"stylusNoteTakingAppEnabledOnLockScreen",
523        IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LOCK_SCREEN_CHECKBOX},
524       {"stylusNoteTakingAppKeepsLastNoteOnLockScreen",
525        IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_KEEP_LATEST_NOTE},
526       {"stylusNoteTakingAppLockScreenSettingsHeader",
527        IDS_SETTINGS_STYLUS_LOCK_SCREEN_NOTES_TITLE},
528       {"stylusNoteTakingAppNoneAvailable",
529        IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_NONE_AVAILABLE},
530       {"stylusNoteTakingAppWaitingForAndroid",
531        IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_WAITING_FOR_ANDROID}};
532   AddLocalizedStringsBulk(html_source, kStylusStrings);
533 
534   html_source->AddBoolean("hasInternalStylus",
535                           ash::stylus_utils::HasInternalStylus());
536 }
537 
AddDeviceDisplayStrings(content::WebUIDataSource * html_source)538 void AddDeviceDisplayStrings(content::WebUIDataSource* html_source) {
539   static constexpr webui::LocalizedString kDisplayStrings[] = {
540       {"displayTitle", IDS_SETTINGS_DISPLAY_TITLE},
541       {"displayArrangementText", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TEXT},
542       {"displayArrangementTitle", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TITLE},
543       {"displayMirror", IDS_SETTINGS_DISPLAY_MIRROR},
544       {"displayMirrorDisplayName", IDS_SETTINGS_DISPLAY_MIRROR_DISPLAY_NAME},
545       {"displayAmbientColorTitle", IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_TITLE},
546       {"displayAmbientColorSubtitle",
547        IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_SUBTITLE},
548       {"displayNightLightLabel", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_LABEL},
549       {"displayNightLightOnAtSunset",
550        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_ON_AT_SUNSET},
551       {"displayNightLightOffAtSunrise",
552        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_OFF_AT_SUNRISE},
553       {"displayNightLightScheduleCustom",
554        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_CUSTOM},
555       {"displayNightLightScheduleLabel",
556        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_LABEL},
557       {"displayNightLightScheduleNever",
558        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_NEVER},
559       {"displayNightLightScheduleSunsetToSunRise",
560        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_SUNSET_TO_SUNRISE},
561       {"displayNightLightStartTime",
562        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_START_TIME},
563       {"displayNightLightStopTime", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_STOP_TIME},
564       {"displayNightLightText", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEXT},
565       {"displayNightLightTemperatureLabel",
566        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMPERATURE_LABEL},
567       {"displayNightLightTempSliderMaxLabel",
568        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MAX_LABEL},
569       {"displayNightLightTempSliderMinLabel",
570        IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MIN_LABEL},
571       {"displayUnifiedDesktop", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP},
572       {"displayUnifiedDesktopOn", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_ON},
573       {"displayUnifiedDesktopOff", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_OFF},
574       {"displayResolutionTitle", IDS_SETTINGS_DISPLAY_RESOLUTION_TITLE},
575       {"displayResolutionText", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT},
576       {"displayResolutionTextBest", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_BEST},
577       {"displayResolutionTextNative",
578        IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_NATIVE},
579       {"displayResolutionSublabel", IDS_SETTINGS_DISPLAY_RESOLUTION_SUBLABEL},
580       {"displayResolutionMenuItem", IDS_SETTINGS_DISPLAY_RESOLUTION_MENU_ITEM},
581       {"displayResolutionOnlyMenuItem",
582        IDS_SETTINGS_DISPLAY_RESOLUTION_ONLY_MENU_ITEM},
583       {"displayResolutionInterlacedMenuItem",
584        IDS_SETTINGS_DISPLAY_RESOLUTION_INTERLACED_MENU_ITEM},
585       {"displayRefreshRateTitle", IDS_SETTINGS_DISPLAY_REFRESH_RATE_TITLE},
586       {"displayRefreshRateSublabel",
587        IDS_SETTINGS_DISPLAY_REFRESH_RATE_SUBLABEL},
588       {"displayRefreshRateMenuItem",
589        IDS_SETTINGS_DISPLAY_REFRESH_RATE_MENU_ITEM},
590       {"displayRefreshRateInterlacedMenuItem",
591        IDS_SETTINGS_DISPLAY_REFRESH_RATE_INTERLACED_MENU_ITEM},
592       {"displayZoomTitle", IDS_SETTINGS_DISPLAY_ZOOM_TITLE},
593       {"displayZoomSublabel", IDS_SETTINGS_DISPLAY_ZOOM_SUBLABEL},
594       {"displayZoomValue", IDS_SETTINGS_DISPLAY_ZOOM_VALUE},
595       {"displayZoomLogicalResolutionText",
596        IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_TEXT},
597       {"displayZoomNativeLogicalResolutionNativeText",
598        IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_NATIVE_TEXT},
599       {"displayZoomLogicalResolutionDefaultText",
600        IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_DEFAULT_TEXT},
601       {"displaySizeSliderMinLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MINIMUM},
602       {"displaySizeSliderMaxLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MAXIMUM},
603       {"displayScreenTitle", IDS_SETTINGS_DISPLAY_SCREEN},
604       {"displayScreenExtended", IDS_SETTINGS_DISPLAY_SCREEN_EXTENDED},
605       {"displayScreenPrimary", IDS_SETTINGS_DISPLAY_SCREEN_PRIMARY},
606       {"displayOrientation", IDS_SETTINGS_DISPLAY_ORIENTATION},
607       {"displayOrientationStandard", IDS_SETTINGS_DISPLAY_ORIENTATION_STANDARD},
608       {"displayOrientationAutoRotate",
609        IDS_SETTINGS_DISPLAY_ORIENTATION_AUTO_ROTATE},
610       {"displayOverscanPageText", IDS_SETTINGS_DISPLAY_OVERSCAN_TEXT},
611       {"displayOverscanPageTitle", IDS_SETTINGS_DISPLAY_OVERSCAN_TITLE},
612       {"displayOverscanSubtitle", IDS_SETTINGS_DISPLAY_OVERSCAN_SUBTITLE},
613       {"displayOverscanInstructions",
614        IDS_SETTINGS_DISPLAY_OVERSCAN_INSTRUCTIONS},
615       {"displayOverscanResize", IDS_SETTINGS_DISPLAY_OVERSCAN_RESIZE},
616       {"displayOverscanPosition", IDS_SETTINGS_DISPLAY_OVERSCAN_POSITION},
617       {"displayOverscanReset", IDS_SETTINGS_DISPLAY_OVERSCAN_RESET},
618       {"displayTouchCalibrationTitle",
619        IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TITLE},
620       {"displayTouchCalibrationText",
621        IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TEXT}};
622   AddLocalizedStringsBulk(html_source, kDisplayStrings);
623 
624   html_source->AddBoolean("unifiedDesktopAvailable",
625                           IsUnifiedDesktopAvailable());
626 
627   html_source->AddBoolean("listAllDisplayModes",
628                           IsListAllDisplayModesEnabled());
629 
630   html_source->AddBoolean("deviceSupportsAmbientColor",
631                           DoesDeviceSupportAmbientColor());
632 
633   html_source->AddBoolean("enableTouchCalibrationSetting",
634                           IsTouchCalibrationAvailable());
635 
636   html_source->AddBoolean(
637       "allowDisplayIdentificationApi",
638       base::FeatureList::IsEnabled(ash::features::kDisplayIdentification));
639 
640   html_source->AddString("invalidDisplayId",
641                          base::NumberToString(display::kInvalidDisplayId));
642 
643   html_source->AddBoolean(
644       "allowDisplayAlignmentApi",
645       base::FeatureList::IsEnabled(ash::features::kDisplayAlignAssist));
646 }
647 
AddDeviceStorageStrings(content::WebUIDataSource * html_source,bool is_external_storage_page_available)648 void AddDeviceStorageStrings(content::WebUIDataSource* html_source,
649                              bool is_external_storage_page_available) {
650   static constexpr webui::LocalizedString kStorageStrings[] = {
651       {"storageTitle", IDS_SETTINGS_STORAGE_TITLE},
652       {"storageItemInUse", IDS_SETTINGS_STORAGE_ITEM_IN_USE},
653       {"storageItemAvailable", IDS_SETTINGS_STORAGE_ITEM_AVAILABLE},
654       {"storageItemSystem", IDS_SETTINGS_STORAGE_ITEM_SYSTEM},
655       {"storageItemMyFiles", IDS_SETTINGS_STORAGE_ITEM_MY_FILES},
656       {"storageItemBrowsingData", IDS_SETTINGS_STORAGE_ITEM_BROWSING_DATA},
657       {"storageItemApps", IDS_SETTINGS_STORAGE_ITEM_APPS},
658       {"storageItemCrostini", IDS_SETTINGS_STORAGE_ITEM_CROSTINI},
659       {"storageItemOtherUsers", IDS_SETTINGS_STORAGE_ITEM_OTHER_USERS},
660       {"storageSizeComputing", IDS_SETTINGS_STORAGE_SIZE_CALCULATING},
661       {"storageSizeUnknown", IDS_SETTINGS_STORAGE_SIZE_UNKNOWN},
662       {"storageSpaceLowMessageTitle",
663        IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_TITLE},
664       {"storageSpaceLowMessageLine1",
665        IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_LINE_1},
666       {"storageSpaceLowMessageLine2",
667        IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_LINE_2},
668       {"storageSpaceCriticallyLowMessageTitle",
669        IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_TITLE},
670       {"storageSpaceCriticallyLowMessageLine1",
671        IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_LINE_1},
672       {"storageSpaceCriticallyLowMessageLine2",
673        IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_LINE_2},
674       {"storageExternal", IDS_SETTINGS_STORAGE_EXTERNAL},
675       {"storageExternalStorageEmptyListHeader",
676        IDS_SETTINGS_STORAGE_EXTERNAL_STORAGE_EMPTY_LIST_HEADER},
677       {"storageExternalStorageListHeader",
678        IDS_SETTINGS_STORAGE_EXTERNAL_STORAGE_LIST_HEADER},
679       {"storageOverviewAriaLabel", IDS_SETTINGS_STORAGE_OVERVIEW_ARIA_LABEL}};
680   AddLocalizedStringsBulk(html_source, kStorageStrings);
681 
682   html_source->AddBoolean("androidEnabled", is_external_storage_page_available);
683 
684   html_source->AddString(
685       "storageAndroidAppsExternalDrivesNote",
686       l10n_util::GetStringFUTF16(
687           IDS_SETTINGS_STORAGE_ANDROID_APPS_ACCESS_EXTERNAL_DRIVES_NOTE,
688           base::ASCIIToUTF16(chrome::kArcExternalStorageLearnMoreURL)));
689 }
690 
AddDevicePowerStrings(content::WebUIDataSource * html_source)691 void AddDevicePowerStrings(content::WebUIDataSource* html_source) {
692   static constexpr webui::LocalizedString kPowerStrings[] = {
693       {"powerTitle", IDS_SETTINGS_POWER_TITLE},
694       {"powerSourceLabel", IDS_SETTINGS_POWER_SOURCE_LABEL},
695       {"powerSourceBattery", IDS_SETTINGS_POWER_SOURCE_BATTERY},
696       {"powerSourceAcAdapter", IDS_SETTINGS_POWER_SOURCE_AC_ADAPTER},
697       {"powerSourceLowPowerCharger",
698        IDS_SETTINGS_POWER_SOURCE_LOW_POWER_CHARGER},
699       {"calculatingPower", IDS_SETTINGS_POWER_SOURCE_CALCULATING},
700       {"powerIdleLabel", IDS_SETTINGS_POWER_IDLE_LABEL},
701       {"powerIdleWhileChargingLabel",
702        IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_LABEL},
703       {"powerIdleWhileChargingAriaLabel",
704        IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_ARIA_LABEL},
705       {"powerIdleWhileOnBatteryLabel",
706        IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_LABEL},
707       {"powerIdleWhileOnBatteryAriaLabel",
708        IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_ARIA_LABEL},
709       {"powerIdleDisplayOffSleep", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_SLEEP},
710       {"powerIdleDisplayOff", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF},
711       {"powerIdleDisplayOn", IDS_SETTINGS_POWER_IDLE_DISPLAY_ON},
712       {"powerIdleDisplayShutDown", IDS_SETTINGS_POWER_IDLE_SHUT_DOWN},
713       {"powerIdleDisplayStopSession", IDS_SETTINGS_POWER_IDLE_STOP_SESSION},
714       {"powerLidSleepLabel", IDS_SETTINGS_POWER_LID_CLOSED_SLEEP_LABEL},
715       {"powerLidSignOutLabel", IDS_SETTINGS_POWER_LID_CLOSED_SIGN_OUT_LABEL},
716       {"powerLidShutDownLabel", IDS_SETTINGS_POWER_LID_CLOSED_SHUT_DOWN_LABEL},
717   };
718   AddLocalizedStringsBulk(html_source, kPowerStrings);
719 }
720 
721 // Mirrors enum of the same name in enums.xml.
722 enum class TouchpadSensitivity {
723   kNONE = 0,
724   kSlowest = 1,
725   kSlow = 2,
726   kMedium = 3,
727   kFast = 4,
728   kFastest = 5,
729   kMaxValue = kFastest,
730 };
731 
732 }  // namespace
733 
DeviceSection(Profile * profile,SearchTagRegistry * search_tag_registry,PrefService * pref_service)734 DeviceSection::DeviceSection(Profile* profile,
735                              SearchTagRegistry* search_tag_registry,
736                              PrefService* pref_service)
737     : OsSettingsSection(profile, search_tag_registry),
738       pref_service_(pref_service) {
739   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
740   updater.AddSearchTags(GetDeviceSearchConcepts());
741 
742   if (features::ShouldShowExternalStorageSettings(profile))
743     updater.AddSearchTags(GetExternalStorageSearchConcepts());
744 
745   PowerManagerClient* power_manager_client = PowerManagerClient::Get();
746   if (power_manager_client) {
747     power_manager_client->AddObserver(this);
748 
749     const base::Optional<power_manager::PowerSupplyProperties>& last_status =
750         power_manager_client->GetLastStatus();
751     if (last_status)
752       PowerChanged(*last_status);
753 
754     // Determine whether to show laptop lid power settings.
755     power_manager_client->GetSwitchStates(base::BindOnce(
756         &DeviceSection::OnGotSwitchStates, weak_ptr_factory_.GetWeakPtr()));
757   }
758 
759   // Keyboard/mouse search tags are added/removed dynamically.
760   pointer_device_observer_.Init();
761   pointer_device_observer_.AddObserver(this);
762   pointer_device_observer_.CheckDevices();
763 
764   // Stylus search tags are added/removed dynamically.
765   ui::DeviceDataManager::GetInstance()->AddObserver(this);
766   UpdateStylusSearchTags();
767 
768   // Display search tags are added/removed dynamically.
769   ash::BindCrosDisplayConfigController(
770       cros_display_config_.BindNewPipeAndPassReceiver());
771   mojo::PendingAssociatedRemote<ash::mojom::CrosDisplayConfigObserver> observer;
772   cros_display_config_observer_receiver_.Bind(
773       observer.InitWithNewEndpointAndPassReceiver());
774   cros_display_config_->AddObserver(std::move(observer));
775   OnDisplayConfigChanged();
776 
777   // Night Light settings are added/removed dynamically.
778   ash::NightLightController* night_light_controller =
779       ash::NightLightController::GetInstance();
780   if (night_light_controller) {
781     ash::NightLightController::GetInstance()->AddObserver(this);
782     OnNightLightEnabledChanged(
783         ash::NightLightController::GetInstance()->GetEnabled());
784   }
785 }
786 
~DeviceSection()787 DeviceSection::~DeviceSection() {
788   pointer_device_observer_.RemoveObserver(this);
789   ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
790 
791   PowerManagerClient* power_manager_client = PowerManagerClient::Get();
792   if (power_manager_client)
793     power_manager_client->RemoveObserver(this);
794 
795   ash::NightLightController* night_light_controller =
796       ash::NightLightController::GetInstance();
797   if (night_light_controller)
798     night_light_controller->RemoveObserver(this);
799 }
800 
AddLoadTimeData(content::WebUIDataSource * html_source)801 void DeviceSection::AddLoadTimeData(content::WebUIDataSource* html_source) {
802   static constexpr webui::LocalizedString kDeviceStrings[] = {
803       {"devicePageTitle", IDS_SETTINGS_DEVICE_TITLE},
804       {"touchPadScrollLabel", IDS_OS_SETTINGS_TOUCHPAD_REVERSE_SCROLL_LABEL},
805   };
806   AddLocalizedStringsBulk(html_source, kDeviceStrings);
807 
808   html_source->AddBoolean("isDemoSession",
809                           chromeos::DemoSession::IsDeviceInDemoMode());
810   html_source->AddBoolean("enableLanguageSettingsV2",
811                           base::FeatureList::IsEnabled(
812                               ::chromeos::features::kLanguageSettingsUpdate));
813 
814   AddDevicePointersStrings(html_source);
815   AddDeviceKeyboardStrings(html_source);
816   AddDeviceStylusStrings(html_source);
817   AddDeviceDisplayStrings(html_source);
818   AddDeviceStorageStrings(
819       html_source, features::ShouldShowExternalStorageSettings(profile()));
820   AddDevicePowerStrings(html_source);
821 }
822 
AddHandlers(content::WebUI * web_ui)823 void DeviceSection::AddHandlers(content::WebUI* web_ui) {
824   if (ash::features::IsDisplayIdentificationEnabled() ||
825       ash::features::IsDisplayAlignmentAssistanceEnabled()) {
826     web_ui->AddMessageHandler(
827         std::make_unique<chromeos::settings::DisplayHandler>());
828   }
829 
830   web_ui->AddMessageHandler(
831       std::make_unique<chromeos::settings::KeyboardHandler>());
832   web_ui->AddMessageHandler(
833       std::make_unique<chromeos::settings::PointerHandler>());
834   web_ui->AddMessageHandler(
835       std::make_unique<chromeos::settings::PowerHandler>(pref_service_));
836   web_ui->AddMessageHandler(
837       std::make_unique<chromeos::settings::StylusHandler>());
838 }
839 
GetSectionNameMessageId() const840 int DeviceSection::GetSectionNameMessageId() const {
841   return IDS_SETTINGS_DEVICE_TITLE;
842 }
843 
GetSection() const844 mojom::Section DeviceSection::GetSection() const {
845   return mojom::Section::kDevice;
846 }
847 
GetSectionIcon() const848 mojom::SearchResultIcon DeviceSection::GetSectionIcon() const {
849   return mojom::SearchResultIcon::kLaptop;
850 }
851 
GetSectionPath() const852 std::string DeviceSection::GetSectionPath() const {
853   return mojom::kDeviceSectionPath;
854 }
855 
LogMetric(mojom::Setting setting,base::Value & value) const856 bool DeviceSection::LogMetric(mojom::Setting setting,
857                               base::Value& value) const {
858   switch (setting) {
859     case mojom::Setting::kTouchpadSpeed:
860       base::UmaHistogramEnumeration(
861           "ChromeOS.Settings.Device.TouchpadSpeedValue",
862           static_cast<TouchpadSensitivity>(value.GetInt()));
863       return true;
864 
865     case mojom::Setting::kKeyboardFunctionKeys:
866       base::UmaHistogramBoolean("ChromeOS.Settings.Device.KeyboardFunctionKeys",
867                                 value.GetBool());
868       return true;
869 
870     default:
871       return false;
872   }
873 }
874 
RegisterHierarchy(HierarchyGenerator * generator) const875 void DeviceSection::RegisterHierarchy(HierarchyGenerator* generator) const {
876   // Pointers.
877   generator->RegisterTopLevelSubpage(
878       IDS_SETTINGS_MOUSE_AND_TOUCHPAD_TITLE, mojom::Subpage::kPointers,
879       mojom::SearchResultIcon::kMouse, mojom::SearchResultDefaultRank::kMedium,
880       mojom::kPointersSubpagePath);
881   static constexpr mojom::Setting kPointersSettings[] = {
882       mojom::Setting::kTouchpadTapToClick,
883       mojom::Setting::kTouchpadTapDragging,
884       mojom::Setting::kTouchpadReverseScrolling,
885       mojom::Setting::kTouchpadAcceleration,
886       mojom::Setting::kTouchpadScrollAcceleration,
887       mojom::Setting::kTouchpadSpeed,
888       mojom::Setting::kMouseSwapPrimaryButtons,
889       mojom::Setting::kMouseReverseScrolling,
890       mojom::Setting::kMouseAcceleration,
891       mojom::Setting::kMouseScrollAcceleration,
892       mojom::Setting::kMouseSpeed,
893   };
894   RegisterNestedSettingBulk(mojom::Subpage::kPointers, kPointersSettings,
895                             generator);
896 
897   // Keyboard.
898   generator->RegisterTopLevelSubpage(
899       IDS_SETTINGS_KEYBOARD_TITLE, mojom::Subpage::kKeyboard,
900       mojom::SearchResultIcon::kKeyboard,
901       mojom::SearchResultDefaultRank::kMedium, mojom::kKeyboardSubpagePath);
902   static constexpr mojom::Setting kKeyboardSettings[] = {
903       mojom::Setting::kKeyboardFunctionKeys,
904       mojom::Setting::kKeyboardAutoRepeat,
905       mojom::Setting::kKeyboardShortcuts,
906   };
907   RegisterNestedSettingBulk(mojom::Subpage::kKeyboard, kKeyboardSettings,
908                             generator);
909 
910   // Stylus.
911   generator->RegisterTopLevelSubpage(
912       IDS_SETTINGS_STYLUS_TITLE, mojom::Subpage::kStylus,
913       mojom::SearchResultIcon::kStylus, mojom::SearchResultDefaultRank::kMedium,
914       mojom::kStylusSubpagePath);
915   static constexpr mojom::Setting kStylusSettings[] = {
916       mojom::Setting::kStylusToolsInShelf,
917       mojom::Setting::kStylusNoteTakingApp,
918       mojom::Setting::kStylusNoteTakingFromLockScreen,
919       mojom::Setting::kStylusLatestNoteOnLockScreen,
920   };
921   RegisterNestedSettingBulk(mojom::Subpage::kStylus, kStylusSettings,
922                             generator);
923 
924   // Display.
925   generator->RegisterTopLevelSubpage(
926       IDS_SETTINGS_DISPLAY_TITLE, mojom::Subpage::kDisplay,
927       mojom::SearchResultIcon::kDisplay,
928       mojom::SearchResultDefaultRank::kMedium, mojom::kDisplaySubpagePath);
929   static constexpr mojom::Setting kDisplaySettings[] = {
930       mojom::Setting::kDisplaySize,
931       mojom::Setting::kNightLight,
932       mojom::Setting::kDisplayOrientation,
933       mojom::Setting::kDisplayArrangement,
934       mojom::Setting::kDisplayResolution,
935       mojom::Setting::kDisplayRefreshRate,
936       mojom::Setting::kDisplayMirroring,
937       mojom::Setting::kAllowWindowsToSpanDisplays,
938       mojom::Setting::kAmbientColors,
939       mojom::Setting::kTouchscreenCalibration,
940       mojom::Setting::kNightLightColorTemperature,
941       mojom::Setting::kDisplayOverscan,
942   };
943   RegisterNestedSettingBulk(mojom::Subpage::kDisplay, kDisplaySettings,
944                             generator);
945 
946   // Storage.
947   generator->RegisterTopLevelSubpage(
948       IDS_SETTINGS_STORAGE_TITLE, mojom::Subpage::kStorage,
949       mojom::SearchResultIcon::kHardDrive,
950       mojom::SearchResultDefaultRank::kMedium, mojom::kStorageSubpagePath);
951   generator->RegisterNestedSubpage(
952       IDS_SETTINGS_STORAGE_EXTERNAL, mojom::Subpage::kExternalStorage,
953       mojom::Subpage::kStorage, mojom::SearchResultIcon::kHardDrive,
954       mojom::SearchResultDefaultRank::kMedium,
955       mojom::kExternalStorageSubpagePath);
956 
957   // Power.
958   generator->RegisterTopLevelSubpage(
959       IDS_SETTINGS_POWER_TITLE, mojom::Subpage::kPower,
960       mojom::SearchResultIcon::kPower, mojom::SearchResultDefaultRank::kMedium,
961       mojom::kPowerSubpagePath);
962   static constexpr mojom::Setting kPowerSettings[] = {
963       mojom::Setting::kPowerIdleBehaviorWhileCharging,
964       mojom::Setting::kPowerIdleBehaviorWhileOnBattery,
965       mojom::Setting::kPowerSource,
966       mojom::Setting::kSleepWhenLaptopLidClosed,
967   };
968   RegisterNestedSettingBulk(mojom::Subpage::kPower, kPowerSettings, generator);
969 }
970 
TouchpadExists(bool exists)971 void DeviceSection::TouchpadExists(bool exists) {
972   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
973   updater.RemoveSearchTags(GetTouchpadSearchConcepts());
974   updater.RemoveSearchTags(GetTouchpadScrollAccelerationSearchConcepts());
975 
976   if (exists) {
977     updater.AddSearchTags(GetTouchpadSearchConcepts());
978     if (base::FeatureList::IsEnabled(chromeos::features::kAllowScrollSettings))
979       updater.AddSearchTags(GetTouchpadScrollAccelerationSearchConcepts());
980   }
981 }
982 
MouseExists(bool exists)983 void DeviceSection::MouseExists(bool exists) {
984   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
985 
986   if (exists)
987     updater.AddSearchTags(GetMouseSearchConcepts());
988   else
989     updater.RemoveSearchTags(GetMouseSearchConcepts());
990 }
991 
PointingStickExists(bool exists)992 void DeviceSection::PointingStickExists(bool exists) {
993   // TODO(crbug.com/1114828): manage search tags when the UI is implemented.
994 }
995 
OnDeviceListsComplete()996 void DeviceSection::OnDeviceListsComplete() {
997   UpdateStylusSearchTags();
998 }
999 
OnNightLightEnabledChanged(bool enabled)1000 void DeviceSection::OnNightLightEnabledChanged(bool enabled) {
1001   OnDisplayConfigChanged();
1002 }
1003 
OnDisplayConfigChanged()1004 void DeviceSection::OnDisplayConfigChanged() {
1005   cros_display_config_->GetDisplayUnitInfoList(
1006       /*single_unified=*/true,
1007       base::BindOnce(&DeviceSection::OnGetDisplayUnitInfoList,
1008                      base::Unretained(this)));
1009 }
1010 
PowerChanged(const power_manager::PowerSupplyProperties & properties)1011 void DeviceSection::PowerChanged(
1012     const power_manager::PowerSupplyProperties& properties) {
1013   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
1014 
1015   if (properties.battery_state() !=
1016       power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT) {
1017     updater.AddSearchTags(GetPowerWithBatterySearchConcepts());
1018   }
1019 }
1020 
OnGetDisplayUnitInfoList(std::vector<ash::mojom::DisplayUnitInfoPtr> display_unit_info_list)1021 void DeviceSection::OnGetDisplayUnitInfoList(
1022     std::vector<ash::mojom::DisplayUnitInfoPtr> display_unit_info_list) {
1023   cros_display_config_->GetDisplayLayoutInfo(base::BindOnce(
1024       &DeviceSection::OnGetDisplayLayoutInfo, base::Unretained(this),
1025       std::move(display_unit_info_list)));
1026 }
1027 
OnGetDisplayLayoutInfo(std::vector<ash::mojom::DisplayUnitInfoPtr> display_unit_info_list,ash::mojom::DisplayLayoutInfoPtr display_layout_info)1028 void DeviceSection::OnGetDisplayLayoutInfo(
1029     std::vector<ash::mojom::DisplayUnitInfoPtr> display_unit_info_list,
1030     ash::mojom::DisplayLayoutInfoPtr display_layout_info) {
1031   bool has_multiple_displays = display_unit_info_list.size() > 1u;
1032 
1033   // Mirroring mode is active if there's at least one display and if there's a
1034   // mirror source ID.
1035   bool is_mirrored = !display_unit_info_list.empty() &&
1036                      display_layout_info->mirror_source_id.has_value();
1037 
1038   bool has_internal_display = false;
1039   bool has_external_display = false;
1040   bool unified_desktop_mode = false;
1041   for (const auto& display_unit_info : display_unit_info_list) {
1042     has_internal_display |= display_unit_info->is_internal;
1043     has_external_display |= !display_unit_info->is_internal;
1044 
1045     unified_desktop_mode |= display_unit_info->is_primary &&
1046                             display_layout_info->layout_mode ==
1047                                 ash::mojom::DisplayLayoutMode::kUnified;
1048   }
1049 
1050   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
1051 
1052   // Arrangement UI.
1053   if (has_multiple_displays || is_mirrored)
1054     updater.AddSearchTags(GetDisplayArrangementSearchConcepts());
1055   else
1056     updater.RemoveSearchTags(GetDisplayArrangementSearchConcepts());
1057 
1058   // Mirror toggle.
1059   if (is_mirrored || (!unified_desktop_mode && has_multiple_displays))
1060     updater.AddSearchTags(GetDisplayMirrorSearchConcepts());
1061   else
1062     updater.RemoveSearchTags(GetDisplayMirrorSearchConcepts());
1063 
1064   // Unified Desktop toggle.
1065   if (unified_desktop_mode ||
1066       (IsUnifiedDesktopAvailable() && has_multiple_displays && !is_mirrored)) {
1067     updater.AddSearchTags(GetDisplayUnifiedDesktopSearchConcepts());
1068   } else {
1069     updater.RemoveSearchTags(GetDisplayUnifiedDesktopSearchConcepts());
1070   }
1071 
1072   // External display settings.
1073   if (has_external_display)
1074     updater.AddSearchTags(GetDisplayExternalSearchConcepts());
1075   else
1076     updater.RemoveSearchTags(GetDisplayExternalSearchConcepts());
1077 
1078   // Refresh Rate dropdown.
1079   if (has_external_display && IsListAllDisplayModesEnabled())
1080     updater.AddSearchTags(GetDisplayExternalWithRefreshSearchConcepts());
1081   else
1082     updater.RemoveSearchTags(GetDisplayExternalWithRefreshSearchConcepts());
1083 
1084   // Orientation settings.
1085   if (!unified_desktop_mode)
1086     updater.AddSearchTags(GetDisplayOrientationSearchConcepts());
1087   else
1088     updater.RemoveSearchTags(GetDisplayOrientationSearchConcepts());
1089 
1090   // Ambient color settings.
1091   if (DoesDeviceSupportAmbientColor() && has_internal_display)
1092     updater.AddSearchTags(GetDisplayAmbientSearchConcepts());
1093   else
1094     updater.RemoveSearchTags(GetDisplayAmbientSearchConcepts());
1095 
1096   // Touch calibration settings.
1097   if (IsTouchCalibrationAvailable())
1098     updater.AddSearchTags(GetDisplayTouchCalibrationSearchConcepts());
1099   else
1100     updater.RemoveSearchTags(GetDisplayTouchCalibrationSearchConcepts());
1101 
1102   // Night Light on settings.
1103   if (ash::NightLightController::GetInstance()->GetEnabled())
1104     updater.AddSearchTags(GetDisplayNightLightOnSearchConcepts());
1105   else
1106     updater.RemoveSearchTags(GetDisplayNightLightOnSearchConcepts());
1107 }
1108 
OnGotSwitchStates(base::Optional<PowerManagerClient::SwitchStates> result)1109 void DeviceSection::OnGotSwitchStates(
1110     base::Optional<PowerManagerClient::SwitchStates> result) {
1111   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
1112 
1113   if (result && result->lid_state != PowerManagerClient::LidState::NOT_PRESENT)
1114     updater.AddSearchTags(GetPowerWithLaptopLidSearchConcepts());
1115 }
1116 
UpdateStylusSearchTags()1117 void DeviceSection::UpdateStylusSearchTags() {
1118   // If not yet complete, wait for OnDeviceListsComplete() callback.
1119   if (!ui::DeviceDataManager::GetInstance()->AreDeviceListsComplete())
1120     return;
1121 
1122   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
1123 
1124   // TODO(https://crbug.com/1071905): Only show stylus settings if a stylus has
1125   // been set up. HasStylusInput() will return true for any stylus-compatible
1126   // device, even if it doesn't have a stylus.
1127   if (ash::stylus_utils::HasStylusInput())
1128     updater.AddSearchTags(GetStylusSearchConcepts());
1129   else
1130     updater.RemoveSearchTags(GetStylusSearchConcepts());
1131 }
1132 
AddDevicePointersStrings(content::WebUIDataSource * html_source)1133 void DeviceSection::AddDevicePointersStrings(
1134     content::WebUIDataSource* html_source) {
1135   static constexpr webui::LocalizedString kPointersStrings[] = {
1136       {"mouseTitle", IDS_SETTINGS_MOUSE_TITLE},
1137       {"pointingStickTitle", IDS_SETTINGS_POINTING_STICK_TITLE},
1138       {"touchpadTitle", IDS_SETTINGS_TOUCHPAD_TITLE},
1139       {"mouseAndTouchpadTitle", IDS_SETTINGS_MOUSE_AND_TOUCHPAD_TITLE},
1140       {"touchpadTapToClickEnabledLabel",
1141        IDS_SETTINGS_TOUCHPAD_TAP_TO_CLICK_ENABLED_LABEL},
1142       {"touchpadSpeed", IDS_SETTINGS_TOUCHPAD_SPEED_LABEL},
1143       {"pointerSlow", IDS_SETTINGS_POINTER_SPEED_SLOW_LABEL},
1144       {"pointerFast", IDS_SETTINGS_POINTER_SPEED_FAST_LABEL},
1145       {"mouseScrollSpeed", IDS_SETTINGS_MOUSE_SCROLL_SPEED_LABEL},
1146       {"mouseSpeed", IDS_SETTINGS_MOUSE_SPEED_LABEL},
1147       {"mouseSwapButtons", IDS_SETTINGS_MOUSE_SWAP_BUTTONS_LABEL},
1148       {"primaryMouseButtonLeft", IDS_SETTINGS_PRIMARY_MOUSE_BUTTON_LEFT_LABEL},
1149       {"primaryMouseButtonRight",
1150        IDS_SETTINGS_PRIMARY_MOUSE_BUTTON_RIGHT_LABEL},
1151       {"mouseReverseScroll", IDS_SETTINGS_MOUSE_REVERSE_SCROLL_LABEL},
1152       {"mouseAccelerationLabel", IDS_SETTINGS_MOUSE_ACCELERATION_LABEL},
1153       {"mouseScrollAccelerationLabel",
1154        IDS_SETTINGS_MOUSE_SCROLL_ACCELERATION_LABEL},
1155       {"touchpadAccelerationLabel", IDS_SETTINGS_TOUCHPAD_ACCELERATION_LABEL},
1156       {"touchpadScrollAccelerationLabel",
1157        IDS_SETTINGS_TOUCHPAD_SCROLL_ACCELERATION_LABEL},
1158       {"touchpadScrollSpeed", IDS_SETTINGS_TOUCHPAD_SCROLL_SPEED_LABEL},
1159   };
1160   AddLocalizedStringsBulk(html_source, kPointersStrings);
1161 
1162   html_source->AddString("naturalScrollLearnMoreLink",
1163                          GetHelpUrlWithBoard(chrome::kNaturalScrollHelpURL));
1164 
1165   html_source->AddBoolean(
1166       "allowDisableMouseAcceleration",
1167       base::FeatureList::IsEnabled(::features::kAllowDisableMouseAcceleration));
1168   html_source->AddBoolean(
1169       "allowScrollSettings",
1170       base::FeatureList::IsEnabled(::chromeos::features::kAllowScrollSettings));
1171   html_source->AddBoolean(
1172       "separatePointingStickSettings",
1173       base::FeatureList::IsEnabled(::features::kSeparatePointingStickSettings));
1174 }
1175 
1176 }  // namespace settings
1177 }  // namespace chromeos
1178