chromium/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.h"

#include "ash/components/arc/arc_prefs.h"
#include "ash/components/arc/arc_util.h"
#include "ash/constants/ash_features.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/ash/child_accounts/on_device_controls/app_controls_service_factory.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_features.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_pref_names.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_util.h"
#include "chrome/browser/ui/webui/ash/settings/pages/apps/android_apps_handler.h"
#include "chrome/browser/ui/webui/ash/settings/pages/apps/plugin_vm_handler.h"
#include "chrome/browser/ui/webui/ash/settings/pages/crostini/guest_os_handler.h"
#include "chrome/browser/ui/webui/ash/settings/pages/system_preferences/startup_section.h"
#include "chrome/browser/ui/webui/ash/settings/search/search_tag_registry.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_features.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/os_settings_resources.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/isolated_web_apps_policy.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/chromeos/devicetype_utils.h"

namespace ash::settings {

namespace mojom {
using ::chromeos::settings::mojom::kAppDetailsSubpagePath;
using ::chromeos::settings::mojom::kAppManagementSubpagePath;
using ::chromeos::settings::mojom::kAppNotificationsManagerSubpagePath;
using ::chromeos::settings::mojom::kAppNotificationsSubpagePath;
using ::chromeos::settings::mojom::kAppParentalControlsSubpagePath;
using ::chromeos::settings::mojom::kAppsSectionPath;
using ::chromeos::settings::mojom::kArcVmUsbPreferencesSubpagePath;
using ::chromeos::settings::mojom::kGooglePlayStoreSubpagePath;
using ::chromeos::settings::mojom::kManageIsolatedWebAppsSubpagePath;
using ::chromeos::settings::mojom::kPluginVmSharedPathsSubpagePath;
using ::chromeos::settings::mojom::kPluginVmUsbPreferencesSubpagePath;
using ::chromeos::settings::mojom::Section;
using ::chromeos::settings::mojom::Setting;
using ::chromeos::settings::mojom::Subpage;
}  // namespace mojom

namespace {

const std::vector<SearchConcept>& GetAppsSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags({
      {IDS_OS_SETTINGS_TAG_APPS,
       mojom::kAppsSectionPath,
       mojom::SearchResultIcon::kAppsGrid,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSection,
       {.section = mojom::Section::kApps}},
      {IDS_OS_SETTINGS_TAG_APPS_MANAGEMENT,
       mojom::kAppManagementSubpagePath,
       mojom::SearchResultIcon::kAppsGrid,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSubpage,
       {.subpage = mojom::Subpage::kAppManagement},
       {IDS_OS_SETTINGS_TAG_APPS_MANAGEMENT_ALT1, SearchConcept::kAltTagEnd}},
  });
  return *tags;
}

const std::vector<SearchConcept>& GetAppNotificationsSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags({
      {IDS_OS_SETTINGS_TAG_APP_NOTIFICATIONS,
       mojom::kAppNotificationsSubpagePath,
       ash::features::IsOsSettingsRevampWayfindingEnabled()
           ? mojom::SearchResultIcon::kNotifications
           : mojom::SearchResultIcon::kAppsGrid,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSubpage,
       {.subpage = mojom::Subpage::kAppNotifications}},
  });
  return *tags;
}

const std::vector<SearchConcept>& GetAppNotificationsManagerSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags({
      {IDS_OS_SETTINGS_TAG_APP_NOTIFICATIONS_MANAGER,
       mojom::kAppNotificationsManagerSubpagePath,
       ash::features::IsOsSettingsRevampWayfindingEnabled()
           ? mojom::SearchResultIcon::kNotifications
           : mojom::SearchResultIcon::kAppsGrid,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSubpage,
       {.subpage = mojom::Subpage::kAppNotificationsManager}},
  });
  return *tags;
}

const std::vector<SearchConcept>& GetAppBadgingSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags(
      {{IDS_OS_SETTINGS_TAG_APP_BADGING,
        mojom::kAppNotificationsSubpagePath,
        ash::features::IsOsSettingsRevampWayfindingEnabled()
            ? mojom::SearchResultIcon::kNotifications
            : mojom::SearchResultIcon::kAppsGrid,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kAppBadgingOnOff}}});
  return *tags;
}

const std::vector<SearchConcept>& GetTurnOffAppNotificationSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags(
      {{IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_OFF,
        mojom::kAppNotificationsSubpagePath,
        ash::features::IsOsSettingsRevampWayfindingEnabled()
            ? mojom::SearchResultIcon::kNotifications
            : mojom::SearchResultIcon::kAppsGrid,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kDoNotDisturbOnOff},
        {IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_OFF_ALT1,
         SearchConcept::kAltTagEnd}}});
  return *tags;
}

const std::vector<SearchConcept>& GetTurnOnAppNotificationSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags(
      {{IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_ON,
        mojom::kAppNotificationsSubpagePath,
        ash::features::IsOsSettingsRevampWayfindingEnabled()
            ? mojom::SearchResultIcon::kNotifications
            : mojom::SearchResultIcon::kAppsGrid,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kDoNotDisturbOnOff},
        {IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_ON_ALT1,
         SearchConcept::kAltTagEnd}}});
  return *tags;
}

const std::vector<SearchConcept>& GetAndroidPlayStoreSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags({
      {IDS_OS_SETTINGS_TAG_PLAY_STORE,
       mojom::kGooglePlayStoreSubpagePath,
       mojom::SearchResultIcon::kGooglePlay,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSubpage,
       {.subpage = mojom::Subpage::kGooglePlayStore}},
      {IDS_OS_SETTINGS_TAG_REMOVE_PLAY_STORE,
       mojom::kGooglePlayStoreSubpagePath,
       mojom::SearchResultIcon::kGooglePlay,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kRemovePlayStore},
       {IDS_OS_SETTINGS_TAG_REMOVE_PLAY_STORE_ALT1, SearchConcept::kAltTagEnd}},
  });
  return *tags;
}

const std::vector<SearchConcept>& GetAndroidSettingsSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags({
      {IDS_OS_SETTINGS_TAG_ANDROID_SETTINGS_WITH_PLAY_STORE,
       mojom::kGooglePlayStoreSubpagePath,
       mojom::SearchResultIcon::kGooglePlay,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kManageAndroidPreferences},
       {IDS_OS_SETTINGS_TAG_ANDROID_SETTINGS_WITH_PLAY_STORE_ALT1,
        SearchConcept::kAltTagEnd}},
  });
  return *tags;
}

const std::vector<SearchConcept>& GetAndroidNoPlayStoreSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags({
      {IDS_OS_SETTINGS_TAG_ANDROID_SETTINGS,
       mojom::kAppsSectionPath,
       mojom::SearchResultIcon::kAndroid,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kManageAndroidPreferences},
       {IDS_OS_SETTINGS_TAG_ANDROID_SETTINGS_ALT1, SearchConcept::kAltTagEnd}},
  });
  return *tags;
}

const std::vector<SearchConcept>& GetAndroidPlayStoreDisabledSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags({
      {IDS_OS_SETTINGS_TAG_ANDROID_TURN_ON_PLAY_STORE,
       mojom::kAppsSectionPath,
       mojom::SearchResultIcon::kAndroid,
       mojom::SearchResultDefaultRank::kMedium,
       mojom::SearchResultType::kSetting,
       {.setting = mojom::Setting::kTurnOnPlayStore},
       {IDS_OS_SETTINGS_TAG_ANDROID_TURN_ON_PLAY_STORE_ALT1,
        SearchConcept::kAltTagEnd}},
  });
  return *tags;
}

const std::vector<SearchConcept>& GetManageIsolatedWebAppsSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags(
      {{IDS_OS_SETTINGS_TAG_MANAGE_ISOLATED_WEB_APPS,
        mojom::kManageIsolatedWebAppsSubpagePath,
        ash::features::IsOsSettingsRevampWayfindingEnabled()
            ? mojom::SearchResultIcon::kNotifications
            : mojom::SearchResultIcon::kAppsGrid,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSubpage,
        {.subpage = mojom::Subpage::kManageIsolatedWebApps}}});
  return *tags;
}

const std::vector<SearchConcept>& GetParentalControlsSearchConcepts() {
  // Redirect search queries to the parental controls row in the Apps section
  // because the app parental controls page should only be accessed after the
  // user has entered their PIN, which is triggered from the settings row.
  static const base::NoDestructor<std::vector<SearchConcept>> tags(
      {{IDS_OS_SETTINGS_TAG_APPS_PARENTAL_CONTROLS,
        mojom::kAppsSectionPath,
        mojom::SearchResultIcon::kAppsParentalControls,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kAppParentalControls},
        {IDS_OS_SETTINGS_TAG_APPS_PARENTAL_CONTROLS_ALT1,
         SearchConcept::kAltTagEnd}}});
  return *tags;
}

const std::vector<SearchConcept>& GetTurnOnIsolatedWebAppsSearchConcepts() {
  static const base::NoDestructor<std::vector<SearchConcept>> tags(
      {{IDS_OS_SETTINGS_TAG_TURN_ON_ISOLATED_WEB_APPS,
        mojom::kManageIsolatedWebAppsSubpagePath,
        ash::features::IsOsSettingsRevampWayfindingEnabled()
            ? mojom::SearchResultIcon::kNotifications
            : mojom::SearchResultIcon::kAppsGrid,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kEnableIsolatedWebAppsOnOff},
        {IDS_OS_SETTINGS_TAG_TURN_ON_ISOLATED_WEB_APPS_ALT1,
         SearchConcept::kAltTagEnd}}});
  return *tags;
}

void AddAppManagementStrings(content::WebUIDataSource* html_source) {
  const bool kIsRevampEnabled =
      ash::features::IsOsSettingsRevampWayfindingEnabled();

  webui::LocalizedString kLocalizedStrings[] = {
      {"appManagementAppDetailsTitle", IDS_APP_MANAGEMENT_APP_DETAILS_TITLE},
      {"appManagementAppDetailsTooltipWebA11y",
       IDS_APP_MANAGEMENT_APP_DETAILS_TOOLTIP_WEB_A11Y},
      {"appManagementAppDetailsTypeAndroid",
       IDS_APP_MANAGEMENT_APP_DETAILS_TYPE_ANDROID},
      {"appManagementAppDetailsTypeChrome",
       IDS_APP_MANAGEMENT_APP_DETAILS_TYPE_CHROME},
      {"appManagementAppDetailsTypeWeb",
       IDS_APP_MANAGEMENT_APP_DETAILS_TYPE_WEB},
      {"appManagementAppDetailsTypeCrosSystem",
       IDS_APP_MANAGEMENT_APP_DETAILS_TYPE_CROS_SYSTEM},
      {"appManagementAppDetailsInstallSourceWebStore",
       IDS_APP_MANAGEMENT_APP_DETAILS_INSTALL_SOURCE_WEB_STORE},
      {"appManagementAppDetailsInstallSourcePlayStore",
       IDS_APP_MANAGEMENT_APP_DETAILS_INSTALL_SOURCE_PLAY_STORE},
      {"appManagementAppDetailsInstallSourceBrowser",
       IDS_APP_MANAGEMENT_APP_DETAILS_INSTALL_SOURCE_BROWSER},
      {"appManagementAppDetailsTypeAndSourcePreinstalledApp",
       IDS_APP_MANAGEMENT_APP_DETAILS_TYPE_AND_SOURCE_PREINSTALLED_APP},
      {"appManagementAppDetailsTypeAndSourceCombined",
       IDS_APP_MANAGEMENT_APP_DETAILS_TYPE_AND_SOURCE_COMBINED},
      {"appManagementAppDetailsVersion",
       IDS_APP_MANAGEMENT_APP_DETAILS_VERSION},
      {"appManagementAppDetailsStorageTitle",
       IDS_APP_MANAGEMENT_APP_DETAILS_STORAGE_TITLE},
      {"appManagementAppDetailsAppSize",
       IDS_APP_MANAGEMENT_APP_DETAILS_APP_SIZE},
      {"appManagementAppDetailsDataSize",
       IDS_APP_MANAGEMENT_APP_DETAILS_DATA_SIZE},
      {"appManagementAppInstalledByPolicyLabel",
       IDS_APP_MANAGEMENT_POLICY_APP_POLICY_STRING},
      {"appManagementArcManagePermissionsLabel",
       IDS_APP_MANAGEMENT_ARC_MANAGE_PERMISSIONS},
      {"appManagementCameraPermissionLabel", IDS_APP_MANAGEMENT_CAMERA},
      {"appManagementContactsPermissionLabel", IDS_APP_MANAGEMENT_CONTACTS},
      {"appManagementFileHandlingHeader",
       IDS_APP_MANAGEMENT_FILE_HANDLING_HEADER},
      {"appManagementIntentOverlapChangeButton",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_CHANGE_BUTTON},
      {"appManagementIntentOverlapDialogText1App",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_DIALOG_TEXT_1_APP},
      {"appManagementIntentOverlapDialogText2Apps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_DIALOG_TEXT_2_APPS},
      {"appManagementIntentOverlapDialogText3Apps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_DIALOG_TEXT_3_APPS},
      {"appManagementIntentOverlapDialogText4Apps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_DIALOG_TEXT_4_APPS},
      {"appManagementIntentOverlapDialogText5OrMoreApps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_DIALOG_TEXT_5_OR_MORE_APPS},
      {"appManagementIntentOverlapDialogTitle",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_DIALOG_TITLE},
      {"appManagementIntentOverlapWarningText1App",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_WARNING_TEXT_1_APP},
      {"appManagementIntentOverlapWarningText2Apps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_WARNING_TEXT_2_APPS},
      {"appManagementIntentOverlapWarningText3Apps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_WARNING_TEXT_3_APPS},
      {"appManagementIntentOverlapWarningText4Apps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_WARNING_TEXT_4_APPS},
      {"appManagementIntentOverlapWarningText5OrMoreApps",
       IDS_APP_MANAGEMENT_INTENT_OVERLAP_WARNING_TEXT_5_OR_MORE_APPS},
      {"appManagementIntentSettingsDialogTitle",
       IDS_APP_MANAGEMENT_INTENT_SETTINGS_DIALOG_TITLE},
      {"appManagementIntentSettingsTitle",
       IDS_APP_MANAGEMENT_INTENT_SETTINGS_TITLE},
      {"appManagementIntentSharingOpenAppLabel",
       kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_OPEN_IN_APP_TITLE
                        : IDS_APP_MANAGEMENT_INTENT_SHARING_APP_OPEN},
      {"appManagementIntentSharingOpenBrowserLabel",
       IDS_APP_MANAGEMENT_INTENT_SHARING_BROWSER_OPEN},
      {"appManagementIntentSharingTabExplanation",
       IDS_APP_MANAGEMENT_INTENT_SHARING_TAB_EXPLANATION},
      {"appManagementLocationPermissionLabel", IDS_APP_MANAGEMENT_LOCATION},
      {"appManagementMicrophonePermissionLabel", IDS_APP_MANAGEMENT_MICROPHONE},
      {"appManagementMorePermissionsLabel", IDS_APP_MANAGEMENT_MORE_SETTINGS},
      {"appManagementMorePermissionsLabelAndroidApp",
       IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_ANDROID},
      {"appManagementMorePermissionsLabelWebApp",
       IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_WEB_APP},
      {"appManagementMorePermissionsLabelChromeApp",
       IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_CHROME_APP},
      {"appManagementNoAppsFound", IDS_APP_MANAGEMENT_NO_APPS_FOUND},
      {"appManagementNoPermissions",
       IDS_APPLICATION_INFO_APP_NO_PERMISSIONS_TEXT},
      {"appManagementNotificationsLabel",
       kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_TITLE
                        : IDS_APP_MANAGEMENT_NOTIFICATIONS},
      {"appManagementParentAppPermissionExplanation",
       IDS_APP_MANAGEMENT_PARENT_APP_PERMISSION_EXPLANATION},
      {"appManagementPermissionAllowed", IDS_APP_MANAGEMENT_PERMISSION_ALLOWED},
      {"appManagementPermissionAllowedWithDetails",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_WITH_DETAILS},
      {"appManagementPermissionAsk", IDS_APP_MANAGEMENT_PERMISSION_ASK},
      {"appManagementPermissionDenied", IDS_APP_MANAGEMENT_PERMISSION_DENIED},
      {"appManagementPermissionsLabel", IDS_APP_MANAGEMENT_PERMISSIONS},
      {"appManagementPinToShelfLabel", IDS_APP_MANAGEMENT_PIN_TO_SHELF},
      {"appManagementPresetWindowSizesLabel",
       IDS_APP_MANAGEMENT_PRESET_WINDOW_SIZES},
      {"appManagementPresetWindowSizesText",
       IDS_APP_MANAGEMENT_PRESET_WINDOW_SIZES_TEXT},
      {"appManagementPrintingPermissionLabel", IDS_APP_MANAGEMENT_PRINTING},
      {"appManagementSearchPrompt", IDS_APP_MANAGEMENT_SEARCH_PROMPT},
      {"appManagementStoragePermissionLabel", IDS_APP_MANAGEMENT_STORAGE},
      {"appManagementSubAppsListHeading",
       IDS_APP_MANAGEMENT_SUB_APPS_LIST_HEADING},
      {"appManagementSubAppPermissionExplanation",
       IDS_APP_MANAGEMENT_SUB_APP_PERMISSION_EXPLANATION},
      {"appManagementUninstallLabel", IDS_APP_MANAGEMENT_UNINSTALL_APP},
      {"close", IDS_CLOSE},
      {"fileHandlingOverflowDialogTitle",
       IDS_APP_MANAGEMENT_FILE_HANDLING_OVERFLOW_DIALOG_TITLE},
      {"fileHandlingSetDefaults",
       IDS_APP_MANAGEMENT_FILE_HANDLING_SET_DEFAULTS_LINK},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
}

void AddGuestOsStrings(content::WebUIDataSource* html_source) {
  // These strings are used for both Crostini and Plugin VM.
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"guestOsSharedPaths", IDS_SETTINGS_GUEST_OS_SHARED_PATHS},
      {"guestOsSharedPathsListHeading",
       IDS_SETTINGS_GUEST_OS_SHARED_PATHS_LIST_HEADING},
      {"guestOsSharedPathsInstructionsRemove",
       IDS_SETTINGS_GUEST_OS_SHARED_PATHS_INSTRUCTIONS_REMOVE},
      {"guestOsSharedPathsStopSharing",
       IDS_SETTINGS_GUEST_OS_SHARED_PATHS_STOP_SHARING},
      {"guestOsSharedPathsRemoveFailureDialogTitle",
       IDS_SETTINGS_GUEST_OS_SHARED_PATHS_REMOVE_FAILURE_DIALOG_TITLE},
      {"guestOsSharedPathsRemoveFailureTryAgain",
       IDS_SETTINGS_GUEST_OS_SHARED_PATHS_REMOVE_FAILURE_TRY_AGAIN},
      {"guestOsSharedPathsListEmptyMessage",
       IDS_SETTINGS_GUEST_OS_SHARED_PATHS_LIST_EMPTY_MESSAGE},
      {"guestOsSharedUsbDevicesLabel",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_LABEL},
      {"guestOsSharedUsbDevicesDescription",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_DESCRIPTION},
      {"guestOsSharedUsbDevicesExtraDescription",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_EXTRA_DESCRIPTION},
      {"guestOsSharedUsbDevicesListEmptyMessage",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_LIST_EMPTY_MESSAGE},
      {"guestOsSharedUsbDevicesInUse",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_IN_USE},
      {"guestOsSharedUsbDevicesReassign",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_REASSIGN},
      {"guestOsSharedUsbDevicesTableTitle",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_TABLE_TITLE},
      {"guestOsSharedUsbDevicesAddTitle",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_ADD_TITLE},
      {"guestOsSharedUsbDevicesNoneAttached",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_NONE_ATTACHED},
      {"guestOsSharedUsbDevicesNotificationDialogTitleEnable",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_NOTIFICATION_DIALOG_TITLE_ENABLE},
      {"guestOsSharedUsbDevicesNotificationDialogTitleDisable",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_NOTIFICATION_DIALOG_TITLE_DISABLE},
      {"guestOsSharedUsbDevicesNotificationDialogAccept",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_NOTIFICATION_DIALOG_ACCEPT},
      {"guestOsSharedUsbDevicesNotificationsLabel",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_NOTIFICATION_LABEL},
      {"guestOsSharedUsbPersistentPassthroughLabel",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_PERSISTENT_PASSTHROUGH_LABEL},
      {"guestOsSharedUsbPersistentPassthroughDialogTitleEnable",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_PERSISTENT_PASSTHROUGH_DIALOG_TITLE_ENABLE},
      {"guestOsSharedUsbPersistentPassthroughDialogTitleDisable",
       IDS_SETTINGS_GUEST_OS_SHARED_USB_PERSISTENT_PASSTHROUGH_DIALOG_TITLE_DISABLE},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
}

void AddBorealisStrings(content::WebUIDataSource* html_source) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"borealisMainPermissionText",
       IDS_SETTINGS_APPS_BOREALIS_MAIN_PERMISSION_TEXT},
      {"borealisAppPermissionText",
       IDS_SETTINGS_APPS_BOREALIS_APP_PERMISSION_TEXT},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
}

void AddAppParentalControlsStrings(content::WebUIDataSource* html_source) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"appParentalControlsAccessDialogTitle",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_ACCESS_DIALOG_TITLE},
      {"appParentalControlsBlockedAppsCountText",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_BLOCKED_APPS_COUNT_TEXT},
      {"appParentalControlsChoosePinSubtitle",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_CHOOSE_PIN_SUBTITLE},
      {"appParentalControlsChoosePinTitle",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_CHOOSE_PIN_TITLE},
      {"appParentalControlsConfirmPinTitle",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_CONFIRM_PIN_TITLE},
      {"appParentalControlsForgotPinLinkName",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_FORGOT_PIN_LINK_NAME},
      {"appParentalControlsHeaderText",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_APPS_TITLE_TEXT},
      {"appParentalControlsNoAppsText",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_NO_APPS_FOUND_TEXT},
      {"appParentalControlsPinIncorrectErrorText",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_INCORRECT_ERROR_TEXT},
      {"appParentalControlsPinMismatchErrorText",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_MISMATCH_ERROR_TEXT},
      {"appParentalControlsSearchPrompt",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_SEARCH_PROMPT},
      {"appParentalControlsTitle", IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_LABEL},
      {"appParentalControlsPinWrongLengthErrorText",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_WRONG_LENGTH_ERROR_TEXT},
      {"appParentalControlsPinNumericErrorText",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_NUMERIC_ERROR_TEXT},
      {"appParentalControlsTitle", IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_LABEL},
      {"appParentalControlsSetUpButton",
       IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_SET_UP_BUTTON},
      {"appParentalControlsTitle", IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_LABEL},
  };

  html_source->AddLocalizedStrings(kLocalizedStrings);

  html_source->AddString("appParentalControlsLearnMoreUrl",
                         chrome::kAppParentalControlsLearnMoreUrl);

  html_source->AddString(
      "appParentalControlsSubtitle",
      l10n_util::GetStringFUTF16(IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_SUBLABEL,
                                 ui::GetChromeOSDeviceName(),
                                 chrome::kAppParentalControlsLearnMoreUrl));
  html_source->AddString(
      "appParentalControlsSubtitleDescription",
      l10n_util::GetStringFUTF16(
          IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_SUBLABEL_DESCRIPTION,
          ui::GetChromeOSDeviceName()));
}

bool ShowPluginVm(const Profile* profile, const PrefService& pref_service) {
  // Even if not allowed, we still want to show Plugin VM if the VM image is on
  // disk, so that users are still able to delete the image at will.
  return plugin_vm::PluginVmFeatures::Get()->IsAllowed(profile) ||
         pref_service.GetBoolean(plugin_vm::prefs::kPluginVmImageExists);
}

}  // namespace

AppsSection::AppsSection(Profile* profile,
                         SearchTagRegistry* search_tag_registry,
                         PrefService* pref_service,
                         ArcAppListPrefs* arc_app_list_prefs,
                         apps::AppServiceProxy* app_service_proxy)
    : OsSettingsSection(profile, search_tag_registry),
      startup_subsection_(
          !ash::features::IsOsSettingsRevampWayfindingEnabled()
              ? std::make_optional<StartupSection>(profile, search_tag_registry)
              : std::nullopt),
      pref_service_(pref_service),
      arc_app_list_prefs_(arc_app_list_prefs),
      app_service_proxy_(app_service_proxy),
      is_arc_allowed_(arc::IsArcAllowedForProfile(profile)) {
  if (!ash::features::IsOsSettingsRevampWayfindingEnabled()) {
    CHECK(startup_subsection_);
  }

  SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
  updater.AddSearchTags(GetAppsSearchConcepts());

  // Note: The MessageCenterAsh check here is added for unit testing purposes
  // otherwise check statements are not needed in production.
  if (MessageCenterAsh::Get()) {
    MessageCenterAsh::Get()->AddObserver(this);
    OnQuietModeChanged(MessageCenterAsh::Get()->IsQuietMode());
  }

  if (is_arc_allowed_) {
    pref_change_registrar_.Init(pref_service_);
    pref_change_registrar_.Add(
        arc::prefs::kArcEnabled,
        base::BindRepeating(&AppsSection::UpdateAndroidSearchTags,
                            base::Unretained(this)));

    if (arc_app_list_prefs_) {
      arc_app_list_prefs_->AddObserver(this);
    }

    UpdateAndroidSearchTags();
  }

  if (web_app::IsIwaUnmanagedInstallEnabled(profile)) {
    updater.AddSearchTags(GetManageIsolatedWebAppsSearchConcepts());
    updater.AddSearchTags(GetTurnOnIsolatedWebAppsSearchConcepts());
  }

  if (on_device_controls::AppControlsServiceFactory::
          IsOnDeviceAppControlsAvailable(profile)) {
    updater.AddSearchTags(GetParentalControlsSearchConcepts());
  }
}

AppsSection::~AppsSection() {
  // TODO(crbug.com/1237465): observer is never removed because ash::Shell is
  // destroyed first.
  // Note: The MessageCenterAsh check is also added for unit testing purposes.
  if (MessageCenterAsh::Get()) {
    MessageCenterAsh::Get()->RemoveObserver(this);
  }

  if (arc::IsArcAllowedForProfile(profile())) {
    if (arc_app_list_prefs_) {
      arc_app_list_prefs_->RemoveObserver(this);
    }
  }
}

void AppsSection::AddLoadTimeData(content::WebUIDataSource* html_source) {
  const bool kIsRevampEnabled =
      ash::features::IsOsSettingsRevampWayfindingEnabled();

  webui::LocalizedString kLocalizedStrings[] = {
      {"appsPageTitle", IDS_SETTINGS_APPS_TITLE},
      {"appsMenuItemDescription", IDS_OS_SETTINGS_APPS_MENU_ITEM_DESCRIPTION},
      {"appsmenuItemDescriptionArcUnavailable",
       IDS_OS_SETTINGS_APPS_MENU_ITEM_DESCRIPTION_ARC_UNAVAILABLE},
      {"appManagementTitle", IDS_SETTINGS_APPS_LINK_TEXT},
      {"appNotificationsTitle", IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TEXT},
      {"doNotDisturbToggleTitle",
       IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_TITLE},
      {"manageIsolatedWebAppsLinkText",
       IDS_SETTINGS_MANAGE_ISOLATED_WEB_APPS_LINK_TEXT},
      {"manageIsolatedWebAppsTitle",
       IDS_SETTINGS_MANAGE_ISOLATED_WEB_APPS_SUBPAGE_TITLE},

      {"appNotificationsManagerLabel",
       IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LABEL},
      {"appNotificationsManagerSublabel",
       IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION},
      {"doNotDisturbToggleDescription",
       kIsRevampEnabled
           ? IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION
           : IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION},
      {"appNotificationsLinkToBrowserSettingsDescription",
       IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TO_BROWSER_SETTINGS_DESCRIPTION},
      {"appNotificationsRowSublabel",
       IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_LINK_DESCRIPTION},
      {"appNotificationsCountDescription",
       IDS_SETTINGS_APP_NOTIFICATIONS_SUBLABEL_TEXT},
      {"appNotificationsDoNotDisturbEnabledDescription",
       IDS_SETTINGS_APP_NOTIFICATIONS_DND_ENABLED_SUBLABEL_TEXT},
      {"appBadgingToggleLabel", IDS_SETTINGS_APP_BADGING_TOGGLE_LABEL},
      {"appBadgingToggleSublabel", IDS_SETTINGS_APP_BADGING_TOGGLE_SUBLABEL},
      {"enableIsolatedWebAppsToggleLabel",
       IDS_SETTINGS_ENABLE_ISOLATED_WEB_APPS_LABEL},
      {"appManagementAppLanguageLabel", IDS_APP_MANAGEMENT_APP_LANGUAGE_LABEL},
      {"permissionAllowedTextWithTurnOnCameraAccessButton",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_TEXT_WITH_TURN_ON_SYSTEM_CAMERA_ACCESS_BUTTON},
      {"permissionAllowedTextWithTurnOnMicrophoneAccessButton",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_TEXT_WITH_TURN_ON_SYSTEM_MICROPHONE_ACCESS_BUTTON},
      {"permissionAllowedTextWithTurnOnLocationAccessButton",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_TEXT_WITH_TURN_ON_SYSTEM_LOCATION_ACCESS_BUTTON},
      {"permissionAllowedTextWithDetailsAndTurnOnCameraAccessButton",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_TEXT_WITH_DETAILS_AND_TURN_ON_SYSTEM_CAMERA_ACCESS_BUTTON},
      {"permissionAllowedTextWithDetailsAndTurnOnMicrophoneAccessButton",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_TEXT_WITH_DETAILS_AND_TURN_ON_SYSTEM_MICROPHONE_ACCESS_BUTTON},
      {"permissionAllowedTextWithDetailsAndTurnOnLocationAccessButton",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_TEXT_WITH_DETAILS_AND_TURN_ON_SYSTEM_LOCATION_ACCESS_BUTTON},
      {"permissionAllowedButNoCameraConnectedText",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_BUT_NO_CAMERA_CONNECTED_TEXT},
      {"permissionAllowedButNoMicrophoneConnectedText",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_BUT_NO_MICROPHONE_CONNECTED_TEXT},
      {"permissionAllowedButNoCameraConnectedTextWithDetails",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_BUT_NO_CAMERA_CONNECTED_TEXT_WITH_DETAILS},
      {"permissionAllowedButNoMicrophoneConnectedTextWithDetails",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_BUT_NO_MICROPHONE_CONNECTED_TEXT_WITH_DETAILS},
      {"permissionAllowedButMicrophoneHwSwitchActiveText",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_BUT_MICROPHONE_HW_SWITCH_ACTIVE_TEXT},
      {"permissionAllowedButMicrophoneHwSwitchActiveTextWithDetails",
       IDS_APP_MANAGEMENT_PERMISSION_ALLOWED_BUT_MICROPHONE_HW_SWITCH_ACTIVE_TEXT_WITH_DETAILS},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);

  html_source->AddBoolean("appManagementArcReadOnlyPermissions",
                          arc::IsReadOnlyPermissionsEnabled());

  html_source->AddString("appManagementDeviceName",
                         ui::GetChromeOSDeviceName());

  html_source->AddString("appNotificationsBrowserSettingsURL",
                         chrome::kAppNotificationsBrowserSettingsURL);

  // We have 2 variants of Android apps settings. Default case, when the Play
  // Store app exists we show expandable section that allows as to
  // enable/disable the Play Store and link to Android settings which is
  // available once settings app is registered in the system.
  // For AOSP images we don't have the Play Store app. In last case we Android
  // apps settings consists only from root link to Android settings and only
  // visible once settings app is registered.
  html_source->AddBoolean("androidAppsVisible", is_arc_allowed_);
  html_source->AddBoolean("isPlayStoreAvailable", arc::IsPlayStoreAvailable());

  html_source->AddBoolean(
      "showOsSettingsAppNotificationsRow",
      base::FeatureList::IsEnabled(features::kOsSettingsAppNotificationsPage));
  html_source->AddBoolean("isArcVmEnabled", arc::IsArcVmEnabled());

  html_source->AddBoolean("showManageIsolatedWebAppsRow",
                          web_app::IsIwaUnmanagedInstallEnabled(profile()));
  html_source->AddString(
      "isolatedWebAppsDescription",
      l10n_util::GetStringFUTF16(IDS_SETTINGS_ISOLATED_WEB_APPS_DESCRIPTION,
                                 chrome::kIsolatedWebAppsLearnMoreUrl));

  html_source->AddBoolean("privacyHubAppPermissionsV2Enabled",
                          features::IsCrosPrivacyHubAppPermissionsV2Enabled());

  html_source->AddBoolean("privacyHubLocationAccessControlEnabled",
                          ash::features::IsCrosPrivacyHubLocationEnabled());

  html_source->AddBoolean("isAppParentalControlsFeatureAvailable",
                          on_device_controls::AppControlsServiceFactory::
                              IsOnDeviceAppControlsAvailable(profile()));

  AddAppManagementStrings(html_source);
  AddGuestOsStrings(html_source);
  AddAndroidAppStrings(html_source);
  AddPluginVmLoadTimeData(html_source);
  AddBorealisStrings(html_source);
  AddAppParentalControlsStrings(html_source);

  // Startup subsection exists only when OsSettingsRevampWayfinding is disabled.
  if (startup_subsection_) {
    startup_subsection_->AddLoadTimeData(html_source);
  }
}

void AppsSection::AddHandlers(content::WebUI* web_ui) {
  web_ui->AddMessageHandler(
      std::make_unique<AndroidAppsHandler>(profile(), app_service_proxy_));
  if (arc::IsArcVmEnabled()) {
    web_ui->AddMessageHandler(std::make_unique<GuestOsHandler>(profile()));
  }

  if (ShowPluginVm(profile(), *pref_service_)) {
    web_ui->AddMessageHandler(std::make_unique<GuestOsHandler>(profile()));
    web_ui->AddMessageHandler(std::make_unique<PluginVmHandler>(profile()));
  }
}

int AppsSection::GetSectionNameMessageId() const {
  return IDS_SETTINGS_APPS_TITLE;
}

mojom::Section AppsSection::GetSection() const {
  return mojom::Section::kApps;
}

mojom::SearchResultIcon AppsSection::GetSectionIcon() const {
  return mojom::SearchResultIcon::kAppsGrid;
}

const char* AppsSection::GetSectionPath() const {
  return mojom::kAppsSectionPath;
}

bool AppsSection::LogMetric(mojom::Setting setting, base::Value& value) const {
  if (setting == mojom::Setting::kDoNotDisturbOnOff) {
    base::UmaHistogramBoolean("ChromeOS.Settings.Apps.DoNotDisturbOnOff",
                              value.GetBool());
    return true;
  }
  if (setting == mojom::Setting::kAppNotificationOnOff) {
    base::UmaHistogramBoolean(
        "ChromeOS.Settings.NotificationPage.PermissionOnOff", value.GetBool());
    return true;
  }
  return false;
}

void AppsSection::RegisterHierarchy(HierarchyGenerator* generator) const {
  generator->RegisterTopLevelSetting(mojom::Setting::kTurnOnPlayStore);
  generator->RegisterTopLevelSetting(mojom::Setting::kAppParentalControls);

  // Manage apps.
  generator->RegisterTopLevelSubpage(IDS_SETTINGS_APPS_LINK_TEXT,
                                     mojom::Subpage::kAppManagement,
                                     mojom::SearchResultIcon::kAppsGrid,
                                     mojom::SearchResultDefaultRank::kMedium,
                                     mojom::kAppManagementSubpagePath);

  // App Notifications
  generator->RegisterTopLevelSubpage(IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TEXT,
                                     mojom::Subpage::kAppNotifications,
                                     mojom::SearchResultIcon::kAppsGrid,
                                     mojom::SearchResultDefaultRank::kMedium,
                                     mojom::kAppNotificationsSubpagePath);
  generator->RegisterNestedSubpage(
      IDS_OS_SETTINGS_TAG_APP_NOTIFICATIONS_MANAGER,
      mojom::Subpage::kAppNotificationsManager,
      mojom::Subpage::kAppNotifications, mojom::SearchResultIcon::kAppsGrid,
      mojom::SearchResultDefaultRank::kMedium,
      mojom::kAppNotificationsManagerSubpagePath);
  generator->RegisterNestedSetting(mojom::Setting::kDoNotDisturbOnOff,
                                   mojom::Subpage::kAppNotifications);
  generator->RegisterNestedSetting(mojom::Setting::kAppBadgingOnOff,
                                   mojom::Subpage::kAppNotifications);
  generator->RegisterNestedSetting(mojom::Setting::kAppNotificationOnOff,
                                   mojom::Subpage::kAppNotifications);

  // Manage Isolated Web Apps
  generator->RegisterTopLevelSubpage(IDS_SETTINGS_APPS_LINK_TEXT,
                                     mojom::Subpage::kManageIsolatedWebApps,
                                     mojom::SearchResultIcon::kAppsGrid,
                                     mojom::SearchResultDefaultRank::kMedium,
                                     mojom::kManageIsolatedWebAppsSubpagePath);
  generator->RegisterNestedSetting(mojom::Setting::kEnableIsolatedWebAppsOnOff,
                                   mojom::Subpage::kManageIsolatedWebApps);

  // Note: The subpage name in the UI is updated dynamically based on the app
  // being shown, but we use a generic "App details" string here.
  generator->RegisterNestedSubpage(
      IDS_SETTINGS_APP_DETAILS_TITLE, mojom::Subpage::kAppDetails,
      mojom::Subpage::kAppManagement, mojom::SearchResultIcon::kAppsGrid,
      mojom::SearchResultDefaultRank::kMedium, mojom::kAppDetailsSubpagePath);
  generator->RegisterNestedSetting(mojom::Setting::kAppPinToShelfOnOff,
                                   mojom::Subpage::kAppDetails);
  generator->RegisterNestedSetting(mojom::Setting::kAppResizeLockOnOff,
                                   mojom::Subpage::kAppDetails);

  generator->RegisterNestedSubpage(
      IDS_SETTINGS_GUEST_OS_SHARED_PATHS, mojom::Subpage::kPluginVmSharedPaths,
      mojom::Subpage::kAppManagement, mojom::SearchResultIcon::kAppsGrid,
      mojom::SearchResultDefaultRank::kMedium,
      mojom::kPluginVmSharedPathsSubpagePath);
  generator->RegisterNestedSubpage(
      IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_LABEL,
      mojom::Subpage::kPluginVmUsbPreferences, mojom::Subpage::kAppManagement,
      mojom::SearchResultIcon::kAppsGrid,
      mojom::SearchResultDefaultRank::kMedium,
      mojom::kPluginVmUsbPreferencesSubpagePath);

  // Google Play Store.
  generator->RegisterTopLevelSubpage(IDS_SETTINGS_ANDROID_APPS_LABEL,
                                     mojom::Subpage::kGooglePlayStore,
                                     mojom::SearchResultIcon::kGooglePlay,
                                     mojom::SearchResultDefaultRank::kMedium,
                                     mojom::kGooglePlayStoreSubpagePath);
  static constexpr mojom::Setting kGooglePlayStoreSettings[] = {
      mojom::Setting::kManageAndroidPreferences,
      mojom::Setting::kRemovePlayStore,
  };
  RegisterNestedSettingBulk(mojom::Subpage::kGooglePlayStore,
                            kGooglePlayStoreSettings, generator);
  generator->RegisterTopLevelAltSetting(
      mojom::Setting::kManageAndroidPreferences);

  generator->RegisterNestedSubpage(
      IDS_SETTINGS_GUEST_OS_SHARED_USB_DEVICES_LABEL,
      mojom::Subpage::kArcVmUsbPreferences, mojom::Subpage::kGooglePlayStore,
      mojom::SearchResultIcon::kGooglePlay,
      mojom::SearchResultDefaultRank::kMedium,
      mojom::kArcVmUsbPreferencesSubpagePath);

  // On-device parental controls for apps
  generator->RegisterTopLevelSubpage(
      IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_LABEL,
      mojom::Subpage::kAppParentalControls,
      mojom::SearchResultIcon::kAppsParentalControls,
      mojom::SearchResultDefaultRank::kMedium,
      mojom::kAppParentalControlsSubpagePath);

  // Startup subsection exists only when OsSettingsRevampWayfinding is disabled.
  if (startup_subsection_) {
    startup_subsection_->RegisterHierarchy(generator);
  }
}

void AppsSection::OnAppRegistered(const std::string& app_id,
                                  const ArcAppListPrefs::AppInfo& app_info) {
  UpdateAndroidSearchTags();
}

void AppsSection::AddAndroidAppStrings(content::WebUIDataSource* html_source) {
  const bool kIsRevampEnabled =
      ash::features::IsOsSettingsRevampWayfindingEnabled();

  webui::LocalizedString kLocalizedStrings[] = {
      {"androidAppsPageLabel", kIsRevampEnabled
                                   ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_LABEL
                                   : IDS_SETTINGS_ANDROID_APPS_LABEL},
      {"androidAppsEnable", IDS_SETTINGS_TURN_ON},
      {"androidAppsManageApps",
       kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_MANAGE_APPS
                        : IDS_SETTINGS_ANDROID_APPS_MANAGE_APPS},
      {"androidAppsRemove", kIsRevampEnabled
                                ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_REMOVE
                                : IDS_SETTINGS_ANDROID_APPS_REMOVE},
      {"androidAppsRemoveButton", IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON},
      {"androidAppsDisableDialogTitle",
       kIsRevampEnabled
           ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_TITLE
           : IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE},
      {"androidAppsDisableDialogMessage",
       kIsRevampEnabled
           ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_MESSAGE
           : IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE},
      {"androidAppsDisableDialogRemove",
       kIsRevampEnabled ? IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON
                        : IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE},
      {"arcvmSharedUsbDevicesDescription",
       IDS_SETTINGS_APPS_ARC_VM_SHARED_USB_DEVICES_DESCRIPTION},
      {"androidAppsEnableButtonRole",
       IDS_SETTINGS_ANDROID_APPS_ENABLE_BUTTON_ROLE},
      {"androidOpenGooglePlay", IDS_OS_SETTINGS_REVAMP_OPEN_GOOGLE_PLAY},
      {"appLanguageDeviceLanguageLabel",
       IDS_OS_SETTINGS_APP_LANGUAGE_DEVICE_LANGUAGE_LABEL},
      {"appLanguageDialogTitle", IDS_OS_SETTINGS_APP_LANGUAGE_DIALOG_TITLE},
      {"appLanguageDialogSearchPlaceholderText",
       IDS_OS_SETTINGS_APP_LANGUAGE_DIALOG_SEARCH_PLACEHOLDER_TEXT},
      {"appLanguageDialogSuggestedLabel",
       IDS_OS_SETTINGS_APP_LANGUAGE_DIALOG_SUGGESTED_LABEL},
      {"appLanguageDialogAllLanguagesLabel",
       IDS_OS_SETTINGS_APP_LANGUAGE_DIALOG_ALL_LANGUAGES_LABEL},
      {"appLanguageDialogUpdateButtonText",
       IDS_OS_SETTINGS_APP_LANGUAGE_DIALOG_UPDATE_BUTTON_TEXT},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);
  html_source->AddLocalizedString("androidAppsPageTitle",
                                  arc::IsPlayStoreAvailable()
                                      ? IDS_SETTINGS_ANDROID_APPS_TITLE
                                      : IDS_SETTINGS_ANDROID_SETTINGS_TITLE);
  html_source->AddString(
      "androidAppsSubtext",
      kIsRevampEnabled
          ? l10n_util::GetStringFUTF16(
                IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT,
                GetHelpUrlWithBoard(chrome::kAndroidAppsLearnMoreURL))
          : l10n_util::GetStringFUTF16(
                IDS_SETTINGS_ANDROID_APPS_SUBTEXT, ui::GetChromeOSDeviceName(),
                GetHelpUrlWithBoard(chrome::kAndroidAppsLearnMoreURL)));
  if (kIsRevampEnabled) {
    html_source->AddLocalizedString(
        "androidAppsSubtextDescription",
        IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT_DESCRIPTION);
  } else {
    html_source->AddString("androidAppsSubtextDescription",
                           l10n_util::GetStringFUTF16(
                               IDS_SETTINGS_ANDROID_APPS_SUBTEXT_DESCRIPTION,
                               ui::GetChromeOSDeviceName()));
  }
}

void AppsSection::AddPluginVmLoadTimeData(
    content::WebUIDataSource* html_source) {
  static constexpr webui::LocalizedString kLocalizedStrings[] = {
      {"pluginVmSharedPathsInstructionsAdd",
       IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_ADD},
      {"pluginVmSharedPathsRemoveFailureDialogMessage",
       IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_REMOVE_FAILURE_DIALOG_MESSAGE},
      {"pluginVmSharedUsbDevicesDescription",
       IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_USB_DEVICES_DESCRIPTION},
      {"pluginVmPermissionDialogCameraLabel",
       IDS_SETTINGS_APPS_PLUGIN_VM_PERMISSION_DIALOG_CAMERA_LABEL},
      {"pluginVmPermissionDialogMicrophoneLabel",
       IDS_SETTINGS_APPS_PLUGIN_VM_PERMISSION_DIALOG_MICROPHONE_LABEL},
      {"pluginVmPermissionDialogRelaunchButton",
       IDS_SETTINGS_APPS_PLUGIN_VM_PERMISSION_DIALOG_RELAUNCH_BUTTON},
  };
  html_source->AddLocalizedStrings(kLocalizedStrings);

  html_source->AddBoolean("isPluginVmAvailable",
                          ShowPluginVm(profile(), *pref_service_));
  html_source->AddString(
      "pluginVmSharedPathsInstructionsLocate",
      l10n_util::GetStringFUTF16(
          IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_LOCATE,
          base::UTF8ToUTF16(plugin_vm::kChromeOSBaseDirectoryDisplayText)));
}

void AppsSection::UpdateAndroidSearchTags() {
  SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();

  updater.RemoveSearchTags(GetAndroidNoPlayStoreSearchConcepts());
  updater.RemoveSearchTags(GetAndroidPlayStoreDisabledSearchConcepts());
  updater.RemoveSearchTags(GetAndroidPlayStoreSearchConcepts());
  updater.RemoveSearchTags(GetAndroidSettingsSearchConcepts());

  if (!arc::IsPlayStoreAvailable()) {
    updater.AddSearchTags(GetAndroidNoPlayStoreSearchConcepts());
    return;
  }

  if (!arc::IsArcPlayStoreEnabledForProfile(profile())) {
    updater.AddSearchTags(GetAndroidPlayStoreDisabledSearchConcepts());
    return;
  }

  updater.AddSearchTags(GetAndroidPlayStoreSearchConcepts());

  if (arc_app_list_prefs_ &&
      arc_app_list_prefs_->IsRegistered(arc::kSettingsAppId)) {
    updater.AddSearchTags(GetAndroidSettingsSearchConcepts());
  }
}

void AppsSection::OnQuietModeChanged(bool in_quiet_mode) {
  if (!features::IsAppNotificationsPageEnabled()) {
    return;
  }

  const bool kIsRevampEnabled =
      ash::features::IsOsSettingsRevampWayfindingEnabled();
  SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();

  updater.RemoveSearchTags(GetTurnOnAppNotificationSearchConcepts());
  updater.RemoveSearchTags(GetTurnOffAppNotificationSearchConcepts());
  updater.RemoveSearchTags(GetAppNotificationsSearchConcepts());
  if (kIsRevampEnabled) {
    updater.RemoveSearchTags(GetAppNotificationsManagerSearchConcepts());
  }
  updater.RemoveSearchTags(GetAppBadgingSearchConcepts());

  updater.AddSearchTags(GetAppNotificationsSearchConcepts());
  if (kIsRevampEnabled) {
    updater.AddSearchTags(GetAppNotificationsManagerSearchConcepts());
  }
  updater.AddSearchTags(GetAppBadgingSearchConcepts());

  if (!MessageCenterAsh::Get()->IsQuietMode()) {
    updater.AddSearchTags(GetTurnOnAppNotificationSearchConcepts());
    return;
  }

  updater.AddSearchTags(GetTurnOffAppNotificationSearchConcepts());
}

}  // namespace ash::settings