| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/user_education/user_education_util.h" |
| |
| #include <map> |
| #include <optional> |
| #include <vector> |
| |
| #include "ash/display/window_tree_host_manager.h" |
| #include "ash/public/cpp/session/session_types.h" |
| #include "ash/public/cpp/session/user_info.h" |
| #include "ash/session/session_controller_impl.h" |
| #include "ash/shell.h" |
| #include "ash/user_education/user_education_types.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/no_destructor.h" |
| #include "base/ranges/algorithm.h" |
| #include "base/unguessable_token.h" |
| #include "components/account_id/account_id.h" |
| #include "components/session_manager/session_manager_types.h" |
| #include "components/user_education/common/events.h" |
| #include "components/user_education/common/help_bubble.h" |
| #include "ui/aura/window.h" |
| #include "ui/gfx/vector_icon_types.h" |
| #include "ui/views/interaction/element_tracker_views.h" |
| #include "ui/views/view.h" |
| |
| namespace ash::user_education_util { |
| namespace { |
| |
| // Keys used in `user_education::HelpBubbleParams::ExtendedProperties`. |
| constexpr char kHelpBubbleBodyIconKey[] = "helpBubbleBodyIcon"; |
| constexpr char kHelpBubbleIdKey[] = "helpBubbleId"; |
| constexpr char kHelpBubbleModalTypeKey[] = "helpBubbleModalType"; |
| constexpr char kHelpBubbleStyleKey[] = "helpBubbleStyle"; |
| |
| // Helpers --------------------------------------------------------------------- |
| |
| AccountId GetActiveAccountId(const SessionControllerImpl* session_controller) { |
| return session_controller ? session_controller->GetActiveAccountId() |
| : AccountId(); |
| } |
| |
| std::map<std::string, raw_ptr<const gfx::VectorIcon>>& |
| GetHelpBubbleBodyIconRegistry() { |
| static base::NoDestructor< |
| std::map<std::string, raw_ptr<const gfx::VectorIcon>>> |
| registry; |
| return *registry; |
| } |
| |
| const AccountId& GetPrimaryAccountId() { |
| const auto* session_controller = Shell::Get()->session_controller(); |
| return session_controller |
| ? GetAccountId(session_controller->GetPrimaryUserSession()) |
| : EmptyAccountId(); |
| } |
| |
| aura::Window* GetRootWindowForDisplayId(int64_t display_id) { |
| auto* window_tree_host_manager = Shell::Get()->window_tree_host_manager(); |
| return window_tree_host_manager |
| ? window_tree_host_manager->GetRootWindowForDisplayId(display_id) |
| : nullptr; |
| } |
| |
| session_manager::SessionState GetSessionState( |
| const SessionControllerImpl* session_controller) { |
| return session_controller ? session_controller->GetSessionState() |
| : session_manager::SessionState::UNKNOWN; |
| } |
| |
| } // namespace |
| |
| // Utilities ------------------------------------------------------------------- |
| |
| user_education::HelpBubbleParams::ExtendedProperties CreateExtendedProperties( |
| const gfx::VectorIcon& body_icon) { |
| auto& registry = GetHelpBubbleBodyIconRegistry(); |
| |
| auto it = base::ranges::find( |
| registry, &body_icon, |
| &std::pair<const std::string, raw_ptr<const gfx::VectorIcon>>::second); |
| |
| if (it == registry.end()) { |
| const auto token = base::UnguessableToken::Create(); |
| it = registry.emplace(token.ToString(), &body_icon).first; |
| } |
| |
| user_education::HelpBubbleParams::ExtendedProperties extended_properties; |
| extended_properties.values().Set(kHelpBubbleBodyIconKey, it->first); |
| return extended_properties; |
| } |
| |
| user_education::HelpBubbleParams::ExtendedProperties CreateExtendedProperties( |
| HelpBubbleId help_bubble_id) { |
| user_education::HelpBubbleParams::ExtendedProperties extended_properties; |
| extended_properties.values().Set(kHelpBubbleIdKey, |
| static_cast<int>(help_bubble_id)); |
| return extended_properties; |
| } |
| |
| user_education::HelpBubbleParams::ExtendedProperties CreateExtendedProperties( |
| HelpBubbleStyle help_bubble_style) { |
| user_education::HelpBubbleParams::ExtendedProperties extended_properties; |
| extended_properties.values().Set(kHelpBubbleStyleKey, |
| static_cast<int>(help_bubble_style)); |
| return extended_properties; |
| } |
| |
| user_education::HelpBubbleParams::ExtendedProperties CreateExtendedProperties( |
| ui::ModalType modal_type) { |
| user_education::HelpBubbleParams::ExtendedProperties extended_properties; |
| extended_properties.values().Set(kHelpBubbleModalTypeKey, |
| static_cast<int>(modal_type)); |
| return extended_properties; |
| } |
| |
| const AccountId& GetAccountId(const UserSession* user_session) { |
| return user_session ? user_session->user_info.account_id : EmptyAccountId(); |
| } |
| |
| std::optional<std::reference_wrapper<const gfx::VectorIcon>> |
| GetHelpBubbleBodyIcon( |
| const user_education::HelpBubbleParams::ExtendedProperties& |
| extended_properties) { |
| if (const std::string* body_icon = |
| extended_properties.values().FindString(kHelpBubbleBodyIconKey)) { |
| auto& registry = GetHelpBubbleBodyIconRegistry(); |
| auto it = registry.find(*body_icon); |
| CHECK(it != registry.end()); |
| return *it->second; |
| } |
| return std::nullopt; |
| } |
| |
| HelpBubbleId GetHelpBubbleId( |
| const user_education::HelpBubbleParams::ExtendedProperties& |
| extended_properties) { |
| return static_cast<HelpBubbleId>( |
| extended_properties.values().FindInt(kHelpBubbleIdKey).value()); |
| } |
| |
| ui::ModalType GetHelpBubbleModalType( |
| const user_education::HelpBubbleParams::ExtendedProperties& |
| extended_properties) { |
| if (const std::optional<int> model_type = |
| extended_properties.values().FindInt(kHelpBubbleModalTypeKey)) { |
| return static_cast<ui::ModalType>(model_type.value()); |
| } |
| return ui::MODAL_TYPE_NONE; |
| } |
| |
| std::optional<HelpBubbleStyle> GetHelpBubbleStyle( |
| const user_education::HelpBubbleParams::ExtendedProperties& |
| extended_properties) { |
| if (std::optional<int> help_bubble_style = |
| extended_properties.values().FindInt(kHelpBubbleStyleKey)) { |
| return static_cast<HelpBubbleStyle>(help_bubble_style.value()); |
| } |
| return std::nullopt; |
| } |
| |
| views::View* GetMatchingViewInRootWindow(int64_t display_id, |
| ui::ElementIdentifier element_id) { |
| aura::Window* root_window = GetRootWindowForDisplayId(display_id); |
| if (!root_window) { |
| return nullptr; |
| } |
| |
| const std::vector<views::View*> matching_views = |
| views::ElementTrackerViews::GetInstance() |
| ->GetAllMatchingViewsInAnyContext(element_id); |
| |
| for (views::View* matching_view : matching_views) { |
| if (root_window->Contains(matching_view->GetWidget()->GetNativeWindow())) { |
| return matching_view; |
| } |
| } |
| |
| return nullptr; |
| } |
| |
| TimeBucket GetTimeBucket(base::TimeDelta delta) { |
| if (delta <= base::Minutes(1)) { |
| return TimeBucket::kOneMinute; |
| } else if (delta <= base::Minutes(10)) { |
| return TimeBucket::kTenMinutes; |
| } else if (delta <= base::Hours(1)) { |
| return TimeBucket::kOneHour; |
| } else if (delta <= base::Days(1)) { |
| return TimeBucket::kOneDay; |
| } else if (delta <= base::Days(7)) { |
| return TimeBucket::kOneWeek; |
| } else if (delta <= base::Days(14)) { |
| return TimeBucket::kTwoWeeks; |
| } |
| return TimeBucket::kOverTwoWeeks; |
| } |
| |
| std::optional<user_manager::UserType> GetUserType(const AccountId& account_id) { |
| if (const auto* ctrlr = Shell::Get()->session_controller()) { |
| if (const auto* session = ctrlr->GetUserSessionByAccountId(account_id)) { |
| return session->user_info.type; |
| } |
| } |
| return std::nullopt; |
| } |
| |
| bool IsPrimaryAccountActive() { |
| const auto* session_controller = Shell::Get()->session_controller(); |
| return IsPrimaryAccountId(GetActiveAccountId(session_controller)) && |
| GetSessionState(session_controller) == |
| session_manager::SessionState::ACTIVE; |
| } |
| |
| bool IsPrimaryAccountId(const AccountId& account_id) { |
| return account_id.is_valid() ? GetPrimaryAccountId() == account_id : false; |
| } |
| |
| std::string ToString(TutorialId tutorial_id) { |
| switch (tutorial_id) { |
| case TutorialId::kTest1: |
| return "AshTest1"; |
| case TutorialId::kTest2: |
| return "AshTest2"; |
| case TutorialId::kWelcomeTour: |
| return "AshWelcomeTour"; |
| } |
| } |
| |
| } // namespace ash::user_education_util |