// 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.
#ifndef CHROME_BROWSER_UI_WEBUI_ASH_SETTINGS_SEARCH_HIERARCHY_H_
#define CHROME_BROWSER_UI_WEBUI_ASH_SETTINGS_SEARCH_HIERARCHY_H_
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "ash/webui/settings/public/constants/routes.mojom.h"
#include "ash/webui/settings/public/constants/setting.mojom.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ui/webui/ash/settings/os_settings_identifier.h"
#include "chrome/browser/ui/webui/ash/settings/search/mojom/search.mojom.h"
namespace ash::settings {
class OsSettingsSections;
// Tracks the OS settings page hierarchy. Settings is composed of a group of
// sections containing subpages and/or settings, and this class provides
// metadata for where these subpages/settings reside and what localized strings
// are used to describe them.
//
// A subpage can either be a direct child of a section or can be a nested
// subpage, meaning that its parent is another subpage.
//
// A setting can either be embedded as a direct child of a section or can be
// a child of a subpage. Additionally, some settings appear in multiple places.
// For example, the Wi-Fi on/off toggle appears in both the top-level Network
// section as well as the Wi-Fi subpage. In cases like this, we consider the
// "primary" location as the more-targeted one - in this example, the Wi-Fi
// subpage is the primary location of the toggle since it is more specific to
// Wi-Fi, and the alternate location is the one embedded in the Network section.
class Hierarchy {
public:
explicit Hierarchy(const OsSettingsSections* sections);
Hierarchy(const Hierarchy& other) = delete;
Hierarchy& operator=(const Hierarchy& other) = delete;
virtual ~Hierarchy();
class SectionMetadata {
public:
SectionMetadata(chromeos::settings::mojom::Section section,
const Hierarchy* hierarchy);
~SectionMetadata();
// Generates a search result for this section, using the canonical search
// tag as the search result text. |relevance_score| must be passed by the
// client, since this result is being created manually instead of via query
// matching.
mojom::SearchResultPtr ToSearchResult(double relevance_score) const;
private:
chromeos::settings::mojom::Section section_;
raw_ptr<const Hierarchy> hierarchy_;
};
class SubpageMetadata {
public:
SubpageMetadata(int name_message_id,
chromeos::settings::mojom::Section section,
chromeos::settings::mojom::Subpage subpage,
mojom::SearchResultIcon icon,
mojom::SearchResultDefaultRank default_rank,
const std::string& url_path_with_parameters,
const Hierarchy* hierarchy);
~SubpageMetadata();
// Generates a search result for this subpage, using the canonical search
// tag as the search result text. |relevance_score| must be passed by the
// client, since this result is being created manually instead of via query
// matching.
mojom::SearchResultPtr ToSearchResult(double relevance_score) const;
// The section in which the subpage appears.
chromeos::settings::mojom::Section section;
// The parent subpage, if applicable. Only applies to nested subpages.
std::optional<chromeos::settings::mojom::Subpage> parent_subpage;
private:
chromeos::settings::mojom::Subpage subpage_;
// Message ID corresponding to the localized string used to describe this
// subpage.
int name_message_id_;
// Icon used for this subpage.
mojom::SearchResultIcon icon_;
// Default rank; used to order returned results.
mojom::SearchResultDefaultRank default_rank_;
// Static URL path, which may need to be modified via
// |modify_url_callback_|.
std::string unmodified_url_path_with_parameters_;
raw_ptr<const Hierarchy> hierarchy_;
};
// The location of a setting, which includes its section and, if applicable,
// its subpage. Some settings are embedded directly into the section and have
// no associated subpage.
struct SettingLocation {
SettingLocation(chromeos::settings::mojom::Section section,
std::optional<chromeos::settings::mojom::Subpage> subpage)
: section(section), subpage(subpage) {}
~SettingLocation() = default;
chromeos::settings::mojom::Section section;
std::optional<chromeos::settings::mojom::Subpage> subpage;
};
struct SettingMetadata {
explicit SettingMetadata(
chromeos::settings::mojom::Section primary_section);
~SettingMetadata();
// The primary location, as described above.
SettingLocation primary;
// Alternate locations, as described above. Empty if the setting has no
// alternate location.
std::vector<SettingLocation> alternates;
};
const SectionMetadata& GetSectionMetadata(
chromeos::settings::mojom::Section section) const;
const SubpageMetadata& GetSubpageMetadata(
chromeos::settings::mojom::Subpage subpage) const;
const SettingMetadata& GetSettingMetadata(
chromeos::settings::mojom::Setting setting) const;
// Generates a list of names of the ancestor sections/subpages for |subpage|.
// The list contains the Settings app name, the section name and, if
// applicable, parent subpage names. Names returned in this list are all
// localized string16s which can be displayed in the UI (e.g., as
// breadcrumbs).
//
// Example 1 - Wi-Fi Networks subpage (no parent subpage):
// ["Settings", "Network"]
// Example 2 - External storage (has parent subpage):
// ["Settings", "Device", "Storage management"]
std::vector<std::u16string> GenerateAncestorHierarchyStrings(
chromeos::settings::mojom::Subpage subpage) const;
// Same as above, but for settings.
std::vector<std::u16string> GenerateAncestorHierarchyStrings(
chromeos::settings::mojom::Setting setting) const;
protected:
std::unordered_map<chromeos::settings::mojom::Section, SectionMetadata>
section_map_;
std::unordered_map<chromeos::settings::mojom::Subpage, SubpageMetadata>
subpage_map_;
std::unordered_map<chromeos::settings::mojom::Setting, SettingMetadata>
setting_map_;
private:
class PerSectionHierarchyGenerator;
friend std::ostream& operator<<(std::ostream& os, const Hierarchy& h);
// Generates an array with the Settings app name and |section|'s name.
std::vector<std::u16string> GenerateHierarchyStrings(
chromeos::settings::mojom::Section section) const;
virtual std::string ModifySearchResultUrl(
chromeos::settings::mojom::Section section,
mojom::SearchResultType type,
OsSettingsIdentifier id,
const std::string& url_to_modify) const;
raw_ptr<const OsSettingsSections> sections_; // Owned by |OsSettingsManager|
};
#ifdef DCHECK
// For logging use only. Prints out text representation of the `Hierarchy`.
std::ostream& operator<<(std::ostream& os, const Hierarchy& h);
#endif
} // namespace ash::settings
#endif // CHROME_BROWSER_UI_WEBUI_ASH_SETTINGS_SEARCH_HIERARCHY_H_