// Copyright 2012 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/toolbar/app_menu_model.h"

#include <algorithm>
#include <cmath>
#include <memory>
#include <optional>

#include "base/command_line.h"
#include "base/debug/debugging_buildflags.h"
#include "base/debug/profiler.h"
#include "base/functional/bind.h"
#include "base/i18n/number_formatting.h"
#include "base/i18n/rtl.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/enterprise/isolated_mode/isolated_mode_settings_service_factory.h"
#include "chrome/browser/enterprise/util/managed_browser_utils.h"
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/feedback/report_unsafe_site_dialog.h"
#include "chrome/browser/feedback/show_feedback_page.h"
#include "chrome/browser/glic/browser_ui/glic_vector_icon_manager.h"
#include "chrome/browser/glic/public/glic_enabling.h"
#include "chrome/browser/glic/resources/grit/glic_browser_resources.h"
#include "chrome/browser/media/router/media_router_feature.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_window.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/search/background/ntp_custom_background_service_factory.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h"
#include "chrome/browser/sharing_hub/sharing_hub_features.h"
#include "chrome/browser/signin/account_preview_data_service_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/signin_ui_util.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/global_error/global_error.h"
#include "chrome/browser/ui/global_error/global_error_service.h"
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h"
#include "chrome/browser/ui/immersive/immersive_mode_controller.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/lens/lens_overlay_controller.h"
#include "chrome/browser/ui/lens/lens_overlay_entry_point_controller.h"
#include "chrome/browser/ui/lens/lens_string_utils.h"
#include "chrome/browser/ui/managed_ui.h"
#include "chrome/browser/ui/profiles/profile_colors_util.h"
#include "chrome/browser/ui/profiles/profile_view_utils.h"
#include "chrome/browser/ui/safety_hub/menu_notification_service_factory.h"
#include "chrome/browser/ui/safety_hub/safety_hub_constants.h"
#include "chrome/browser/ui/safety_hub/safety_hub_hats_service.h"
#include "chrome/browser/ui/safety_hub/safety_hub_hats_service_factory.h"
#include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_context_menu_delegate.h"
#include "chrome/browser/ui/side_panel/side_panel_action_callback.h"
#include "chrome/browser/ui/side_panel/side_panel_enums.h"
#include "chrome/browser/ui/startup/default_browser_prompt/default_browser_prompt_manager.h"
#include "chrome/browser/ui/tabs/features.h"
#include "chrome/browser/ui/tabs/recent_tabs_sub_menu_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/vertical_tab_strip_metrics.h"
#include "chrome/browser/ui/tabs/vertical_tab_strip_state_controller.h"
#include "chrome/browser/ui/toolbar/app_menu_icon_controller.h"
#include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h"
#include "chrome/browser/ui/toolbar/chrome_labs/chrome_labs_prefs.h"
#include "chrome/browser/ui/toolbar/chrome_labs/chrome_labs_utils.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/user_education/browser_user_education_interface.h"
#include "chrome/browser/ui/web_applications/web_app_dialog_utils.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
#include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h"
#include "chrome/browser/ui/webui/signin/signin_utils_desktop.h"
#include "chrome/browser/ui/webui/whats_new/whats_new_util.h"
#include "chrome/browser/upgrade_detector/upgrade_detector.h"
#include "chrome/browser/user_education/tutorial_identifiers.h"
#include "chrome/browser/user_education/user_education_service.h"
#include "chrome/browser/user_education/user_education_service_factory.h"
#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
#include "chrome/browser/web_applications/proto/web_app_install_state.pb.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_tab_helper.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/branded_strings.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/theme_resources.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/bookmarks/common/bookmark_bar_visibility_state.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/dom_distiller/content/browser/distillable_page_utils.h"
#include "components/dom_distiller/content/browser/uma_helper.h"
#include "components/dom_distiller/core/dom_distiller_features.h"
#include "components/dom_distiller/core/url_utils.h"
#include "components/feature_engagement/public/event_constants.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/lens/lens_features.h"
#include "components/omnibox/browser/vector_icons.h"
#include "components/password_manager/content/common/web_ui_constants.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_member.h"
#include "components/prefs/pref_service.h"
#include "components/profile_metrics/browser_profile_type.h"
#include "components/saved_tab_groups/public/features.h"
#include "components/send_tab_to_self/features.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/base/signin_switches.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/base/features.h"
#include "components/sync/service/sync_service.h"
#include "components/user_education/common/feature_promo/feature_promo_controller.h"
#include "components/vector_icons/vector_icons.h"
#include "components/webapps/browser/banners/app_banner_manager.h"
#include "components/webapps/browser/banners/install_banner_config.h"
#include "components/webapps/browser/banners/installable_web_app_check_result.h"
#include "components/webapps/browser/banners/web_app_banner_data.h"
#include "components/webapps/common/web_app_id.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/profiling.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/extension_features.h"
#include "media/base/media_switches.h"
#include "ui/base/accelerators/menu_label_accelerator_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/button_menu_item_model.h"
#include "ui/base/models/image_model.h"
#include "ui/base/models/menu_separator_types.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_features.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/text_elider.h"
#include "ui/menus/simple_menu_model.h"

#if BUILDFLAG(GOOGLE_CHROME_BRANDING) || BUILDFLAG(IS_CHROMEOS)
#include "base/feature_list.h"
#endif

#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/policy/system_features_disable_list_policy_handler.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "ui/display/screen.h"
#else
#include "chrome/browser/ui/webui/signin/signin_ui_error.h"
#include "chrome/browser/ui/webui/signin/signin_utils_desktop.h"
#endif

#if BUILDFLAG(IS_WIN)
#include "base/time/time.h"
#include "base/win/shortcut.h"
#include "base/win/windows_version.h"
#include "content/public/browser/gpu_data_manager.h"
#endif

using base::UserMetricsAction;
using content::WebContents;

DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kProfileMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kProfileOpenGuestItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kBookmarksMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kTabGroupsMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kDownloadsMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kHistoryMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kExtensionsMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kClearBrowsingDataMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kMoreToolsMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kIncognitoMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel,
                                      kPasswordAndAutofillMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kPasswordManagerMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kContactInfoMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kIdentityDocsMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kTravelMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kShowLensOverlay);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kSaveAndShareMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kCastTitleItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kInstallAppItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kCreateShortcutItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel,
                                      kSetBrowserAsDefaultMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(AppMenuModel, kHelpMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(ToolsMenuModel, kPerformanceMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(ToolsMenuModel, kChromeLabsMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(ToolsMenuModel, kReadingModeMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(ExtensionsMenuModel,
                                      kManageExtensionsMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(ExtensionsMenuModel,
                                      kVisitChromeWebStoreMenuItem);
DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(HelpMenuModel, kReportUnsafeSiteMenuItem);

namespace {

////////////////////////////////////////////////////////////////////////////////
// AddItemWithStringIdAndVectorIcon
void AddItemWithStringIdAndVectorIcon(ui::SimpleMenuModel* model,
                                      int command_id,
                                      int string_id,
                                      const gfx::VectorIcon& vector_icon) {
  return model->AddItemWithStringIdAndIcon(
      command_id, string_id,
      ui::ImageModel::FromVectorIcon(vector_icon, ui::kColorMenuIcon,
                                     ui::SimpleMenuModel::kDefaultIconSize));
}

////////////////////////////////////////////////////////////////////////////////
// AddSubMenuWithStringIdAndVectorIcon
void AddSubMenuWithStringIdAndVectorIcon(ui::SimpleMenuModel* model,
                                         int command_id,
                                         int string_id,
                                         ui::MenuModel* sub_menu,
                                         const gfx::VectorIcon& vector_icon) {
  return model->AddSubMenuWithStringIdAndIcon(
      command_id, string_id, sub_menu,
      ui::ImageModel::FromVectorIcon(vector_icon, ui::kColorMenuIcon,
                                     ui::SimpleMenuModel::kDefaultIconSize));
}

const gfx::VectorIcon& GetSendTabToSelfIcon() {
  return features::IsRoundedIconsEnabled() ? kDevicesIcon
                                           : kDevicesChromeRefreshOldIcon;
}

// Conditionally return the update app menu item title based on upgrade detector
// state.
std::u16string GetUpgradeDialogTitleText() {
  if (UpgradeDetector::GetInstance()->is_outdated_install() ||
      UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
    return l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_MENU_ITEM);
  }
#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && \
    (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX))
  return l10n_util::GetStringUTF16(IDS_RELAUNCH_TO_UPDATE_ALT);
#else
  return l10n_util::GetStringUTF16(IDS_RELAUNCH_TO_UPDATE);
#endif
}

// Returns the appropriate menu label for the IDC_INSTALL_PWA command if
// available.
std::u16string GetInstallPWALabel(BrowserWindowInterface* browser) {
  // There may be no active web contents in tests.
  auto* const web_contents = browser->tab_strip_model()->GetActiveWebContents();
  if (!web_contents) {
    return std::u16string();
  }
  if (!web_app::CanCreateWebApp(browser)) {
    return std::u16string();
  }
  // Don't allow apps created from chrome-extension urls.
  if (web_contents->GetLastCommittedURL().SchemeIs("chrome-extension")) {
    return std::u16string();
  }

  // TODO(b/328077967): Support async nature of AppBannerManager pipeline runs
  // with the menu model instead of needing this workaround to verify if an
  // non-installable site is installed.
  const webapps::AppId* app_id =
      web_app::WebAppTabHelper::GetAppId(web_contents);
  web_app::WebAppProvider* const provider =
      web_app::WebAppProvider::GetForLocalAppsUnchecked(browser->GetProfile());
  if (app_id &&
      provider->registrar_unsafe().GetInstallState(*app_id) ==
          web_app::proto::INSTALLED_WITH_OS_INTEGRATION &&
      provider->registrar_unsafe().GetAppUserDisplayMode(*app_id) !=
          web_app::mojom::UserDisplayMode::kBrowser) {
    return std::u16string();
  }

  std::u16string install_page_as_app_label =
      l10n_util::GetStringUTF16(IDS_INSTALL_DIY_TO_OS_LAUNCH_SURFACE);
  webapps::AppBannerManager* banner =
      webapps::AppBannerManager::FromWebContents(web_contents);
  if (!banner) {
    // Showing `Install Page as App` allows the user to refetch the manifest and
    // go through the install flow without relying on the AppBannerManager to
    // finish working.
    return install_page_as_app_label;
  }

  std::optional<webapps::InstallBannerConfig> install_config =
      banner->GetCurrentBannerConfig();
  if (!install_config) {
    // In some edge cases where the `AppBannerManager` pipeline hasn't run yet,
    // the information populated to be used for determining installability and
    // other parameters is not available. In this case, allow users to try
    // installability by refetching the manifest.
    return install_page_as_app_label;
  }
  CHECK_EQ(install_config->mode, webapps::AppBannerMode::kWebApp);
  webapps::InstallableWebAppCheckResult installable =
      banner->GetInstallableWebAppCheckResult();

  switch (installable) {
    case webapps::InstallableWebAppCheckResult::kUnknown:
      // Loading of the menu model is synchronous, so there could be a condition
      // where the `AppBannerManager` has not yet finished the pipeline while
      // the menu item has been triggered. In such a case,
      // `banner->GetInstallableWebAppCheckResult()` returns the default value
      // of `kUnknown`.
      // Show `Install Page as App` for that use-case, since that allows the
      // user to trigger the install flow to verify all the data required for
      // installability. The correct dialog will be shown to the user depending
      // on whether the app turns out to be installable or not.
      return install_page_as_app_label;
    case webapps::InstallableWebAppCheckResult::kNo_AlreadyInstalled:
      // Returning an empty string here allows the `launch page as app` field to
      // get populated in place of the `install` strings.
      return std::u16string();
    case webapps::InstallableWebAppCheckResult::kNo:
      return install_page_as_app_label;
    case webapps::InstallableWebAppCheckResult::kYes_ByUserRequest:
    case webapps::InstallableWebAppCheckResult::kYes_Promotable:
      std::u16string app_name = install_config->GetWebOrNativeAppName();
      if (app_name.empty()) {
        // Prefer showing `Install Page as App` here, as users can set the name
        // of the installed app on the DIY app dialog anyway.
        return install_page_as_app_label;
      }
      return l10n_util::GetStringFUTF16(
          IDS_INSTALL_TO_OS_LAUNCH_SURFACE,
          ui::EscapeMenuLabelAmpersands(app_name));
  }
}

// TODO(b/328077967): Implement async updates of menu for app icon.
ui::ImageModel GetInstallPWAIcon(BrowserWindowInterface* browser) {
  ui::ImageModel app_icon_to_use = ui::ImageModel::FromVectorIcon(
      features::IsRoundedIconsEnabled() ? vector_icons::kInstallDesktopIcon
                                        : kInstallDesktopChromeRefreshOldIcon,
      ui::kColorMenuIcon, ui::SimpleMenuModel::kDefaultIconSize);

  content::WebContents* const web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  if (!web_contents) {
    return app_icon_to_use;
  }

  webapps::AppBannerManager* const banner =
      webapps::AppBannerManager::FromWebContents(web_contents);
  if (!banner) {
    return app_icon_to_use;
  }

  // For sites that are not installable (DIY apps), do not return any icons,
  // instead use the default chrome refresh icon for installing.
  auto installable_check_result = banner->GetInstallableWebAppCheckResult();
  if (installable_check_result == webapps::InstallableWebAppCheckResult::kNo ||
      installable_check_result ==
          webapps::InstallableWebAppCheckResult::kUnknown) {
    return app_icon_to_use;
  }

  std::optional<webapps::WebAppBannerData> install_config =
      banner->GetCurrentWebAppBannerData();

  // If no data or no icons have been obtained by the AppBannerManager, return
  // the default icon.
  if (!install_config || install_config->primary_icon.empty()) {
    return app_icon_to_use;
  }

  gfx::ImageSkia primary_icon =
      gfx::ImageSkia::CreateFrom1xBitmap(install_config->primary_icon);
  gfx::ImageSkia resized_app_icon =
      gfx::ImageSkiaOperations::CreateResizedImage(
          primary_icon, skia::ImageOperations::RESIZE_BEST,
          gfx::Size(ui::SimpleMenuModel::kDefaultIconSize,
                    ui::SimpleMenuModel::kDefaultIconSize));
  app_icon_to_use = ui::ImageModel::FromImageSkia(resized_app_icon);
  return app_icon_to_use;
}

// Returns the appropriate menu label for the IDC_OPEN_IN_PWA_WINDOW command if
// available.
std::u16string GetOpenPWALabel(BrowserWindowInterface* browser) {
  std::optional<webapps::AppId> app_id =
      web_app::GetWebAppForActiveTab(browser);
  if (!app_id.has_value()) {
    return std::u16string();
  }

  // Only show this menu item for apps that open in an app window.
  const auto* const provider =
      web_app::WebAppProvider::GetForLocalAppsUnchecked(browser->GetProfile());
  if (provider->registrar_unsafe().GetAppUserDisplayMode(*app_id) ==
      web_app::mojom::UserDisplayMode::kBrowser) {
    return std::u16string();
  }

  const std::u16string short_name =
      base::UTF8ToUTF16(provider->registrar_unsafe().GetAppShortName(*app_id));
  return l10n_util::GetStringFUTF16(
      IDS_OPEN_IN_APP_WINDOW,
      ui::EscapeMenuLabelAmpersands(gfx::TruncateString(
          short_name,
          GetLayoutConstant(LayoutConstant::kAppMenuMaximumCharacterLength),
          gfx::CHARACTER_BREAK)));
}

#if !BUILDFLAG(IS_CHROMEOS)
std::u16string GetSyncSectionTitle(Profile* profile,
                                   signin::IdentityManager* identity_manager) {
  const AccountInfo account = GetAccountInfoFromProfile(profile);

  if (IsSyncPaused(profile) || account.IsEmpty()) {
    return l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE);
  }

  if (signin_util::IsSigninPending(identity_manager)) {
    return base::UTF8ToUTF16(account.GetEmail());
  }

  return l10n_util::GetStringFUTF16(
      IDS_PROFILE_ROW_SIGNED_IN_MESSAGE_WITH_EMAIL,
      {base::UTF8ToUTF16(account.GetEmail())});
}

class ProfileSubMenuModel : public ui::SimpleMenuModel,
                            public ui::SimpleMenuModel::Delegate {
 public:
  ProfileSubMenuModel(ui::SimpleMenuModel::Delegate* delegate,
                      Profile* profile,
                      const ui::ColorProvider* color_provider);
  ProfileSubMenuModel(const ProfileSubMenuModel&) = delete;
  ProfileSubMenuModel& operator=(const ProfileSubMenuModel&) = delete;
  ~ProfileSubMenuModel() override = default;

  const ui::ImageModel& avatar_image_model() const {
    return avatar_image_model_;
  }

  const std::u16string& profile_name() const { return profile_name_; }
  const std::u16string& accessible_name() const { return accessible_name_; }

  // Returns |next_menu_id_| and increments it by n. This allows for 'sharing'
  // command ids with the other variable sized menu, which also uses every other
  // int as an id.
  int GetAndIncrementNextMenuID();

  // Overridden from ui::SimpleMenuModel::Delegate:
  bool IsCommandIdChecked(int command_id) const override;
  bool IsCommandIdEnabled(int command_id) const override;
  bool GetAcceleratorForCommandId(int command_id,
                                  ui::Accelerator* accelerator) const override;
  void ExecuteCommand(int command_id, int event_flags) override;

 private:
  bool BuildSyncSection();

  void BuildGuestProfileRow(Profile* profile);
  void BuildCustomizeProfileRow(Profile* profile);
  void BuildCloseProfileRow(Profile* profile);
  void BuildManageGoogleAccountRow(Profile* profile);

  ui::ImageModel avatar_image_model_;
  std::u16string profile_name_;
  std::u16string accessible_name_;
  raw_ptr<Profile> profile_;
  raw_ptr<ui::SimpleMenuModel::Delegate> app_menu_model_delegate_;
  // ID of the next menu item.
  int next_other_profile_menu_id_;
  base::flat_map<int, base::FilePath> other_profiles_;
};

ProfileSubMenuModel::ProfileSubMenuModel(
    ui::SimpleMenuModel::Delegate* delegate,
    Profile* profile,
    const ui::ColorProvider* color_provider)
    : SimpleMenuModel(this),
      profile_(profile),
      app_menu_model_delegate_(delegate),
      next_other_profile_menu_id_(AppMenuModel::kMinOtherProfileCommandId) {
  const int avatar_icon_size =
      GetLayoutConstant(LayoutConstant::kAppMenuProfileRowAvatarIconSize);
  avatar_image_model_ = ui::ImageModel::FromVectorIcon(
      features::IsRoundedIconsEnabled() ? kAccountCircleIcon
                                        : kAccountCircleChromeRefreshOldIcon,
      ui::kColorMenuIcon, avatar_icon_size);
  // TODO(b/540249284): Temporarily Isolated mode is treated as Incognito. This
  // should be revisited when deciding on the final integration of Isolated
  // mode.
  if (profile->IsIncognitoProfile() ||
      profile->IsEnterpriseIsolatedModeProfile()) {
    avatar_image_model_ = ui::ImageModel::FromVectorIcon(
        features::IsRoundedIconsEnabled() ? kIncognitoCircleFilledIcon
                                          : kIncognitoOldIcon,
        ui::kColorAvatarIconIncognito, avatar_icon_size);
    profile_name_ = l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_TITLE);
  } else if (profile->IsGuestSession()) {
    profile_name_ = l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME);
  } else {
    if (BuildSyncSection()) {
      AddSeparator(ui::NORMAL_SEPARATOR);
    }

    ProfileAttributesEntry* profile_attributes =
        GetProfileAttributesFromProfile(profile);
    // If the profile is being deleted, profile_attributes may be null.
    if (profile_attributes) {
      profile_name_ = GetProfileMenuDisplayName(profile_attributes);
      accessible_name_ = profile_name_;

      AccountInfo account_info = GetAccountInfoFromProfile(profile);
      auto [avatar_image, icon_type] =
          account_info.IsEmpty()
              ? profile_attributes->GetAvatarIconWithType(
                    avatar_icon_size, /*use_high_res_file=*/true,
                    GetPlaceholderAvatarIconParamsDependingOnTheme(
                        ThemeServiceFactory::GetForProfile(profile),
                        /*background_color_id=*/ui::kColorMenuBackground,
                        *color_provider))
              : std::make_pair(
                    account_info.GetAvatarImage().value_or(gfx::Image()),
                    AvatarIconType::kNonPlaceholder);
      // The avatar image can be empty if the account image hasn't been
      // fetched yet, if there is no image, or in tests.
      // Keep the default vector icon for placeholder avatars so that
      // MenuItemView can re-color it on hover in forced-colors mode.
      if (!avatar_image.IsEmpty() &&
          icon_type != AvatarIconType::kPlaceholder) {
        ui::ImageModel avatar_model =
            ui::ImageModel::FromImage(profiles::GetSizedAvatarIcon(
                avatar_image, avatar_icon_size, avatar_icon_size,
                profiles::SHAPE_CIRCLE));
        // TODO(crbug.com/530147081): Clarify if the ring may show up for users
        // with a placeholder icon. Signed in users should have always an
        // account_info and thus they will never have a placeholder icon.
        if (ShouldShowAvatarGradientRing(profile)) {
          avatar_image_model_ =
              ui::ImageModel::FromImageSkia(AddLinearGradientRingToAvatar(
                  avatar_model, *color_provider, avatar_icon_size));
          if (!profile_name_.empty()) {
            accessible_name_ = l10n_util::GetStringFUTF16(
                IDS_PROFILE_AVATAR_NAME_WITH_AI_MEMBERSHIP, profile_name_);
          }
        } else {
          avatar_image_model_ = avatar_model;
        }
      }
    }
  }

  BuildManageGoogleAccountRow(profile);
  BuildCustomizeProfileRow(profile);
  BuildCloseProfileRow(profile);

  bool needs_separator = false;
  const bool is_guest_mode_enabled = profiles::IsGuestModeEnabled(*profile);
  // TODO(b/540249284): Temporarily Isolated mode is treated as Incognito. This
  // should be revisited when deciding on the final integration of Isolated
  // mode.
  if (!profile->IsIncognitoProfile() && !profile->IsGuestSession() &&
      !profile->IsEnterpriseIsolatedModeProfile()) {
    AddSeparator(ui::NORMAL_SEPARATOR);
    AddTitle(l10n_util::GetStringUTF16(IDS_OTHER_CHROME_PROFILES_TITLE));
    auto profile_entries = GetAllOtherProfileEntriesForProfileSubMenu(profile);
    needs_separator = !profile_entries.empty();
    profiles::PlaceholderAvatarIconParams icon_params =
        GetPlaceholderAvatarIconParamsVisibleAgainstColor(
            color_provider->GetColor(ui::kColorMenuBackground));
    for (ProfileAttributesEntry* profile_entry : profile_entries) {
      std::u16string display_name = GetProfileMenuDisplayName(profile_entry);
      int menu_id = GetAndIncrementNextMenuID();

      ui::ImageModel avatar_model =
          ui::ImageModel::FromImage(profiles::GetSizedAvatarIcon(
              profile_entry->GetAvatarIcon(
                  avatar_icon_size, /*use_high_res_file=*/true, icon_params),
              avatar_icon_size, avatar_icon_size, profiles::SHAPE_CIRCLE));

      bool has_ai_ring = false;
      if (base::FeatureList::IsEnabled(
              switches::kEnableAiSubscriptionAvatarRing) &&
          profile_entry->GetAiSubscriptionTier() > 0) {
        has_ai_ring = true;
        avatar_model =
            ui::ImageModel::FromImageSkia(AddLinearGradientRingToAvatar(
                avatar_model, *color_provider, avatar_icon_size));
      }

      AddItemWithIcon(
          menu_id,
          ui::EscapeMenuLabelAmpersands(gfx::TruncateString(
              display_name,
              GetLayoutConstant(LayoutConstant::kAppMenuMaximumCharacterLength),
              gfx::CHARACTER_BREAK)),
          avatar_model);
      if (has_ai_ring && !display_name.empty()) {
        std::optional<size_t> index = GetIndexOfCommandId(menu_id);
        CHECK(index.has_value());
        SetAccessibleNameAt(
            index.value(),
            l10n_util::GetStringFUTF16(
                IDS_PROFILE_AVATAR_NAME_WITH_AI_MEMBERSHIP, display_name));
      }
      other_profiles_.insert({menu_id, profile_entry->GetPath()});
    }

    if (needs_separator) {
      AddSeparator(ui::NORMAL_SEPARATOR);
    }

    if (profiles::IsProfileCreationAllowed()) {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_ADD_NEW_PROFILE, IDS_ADD_NEW_PROFILE,
          features::IsRoundedIconsEnabled() ? kPersonAddIcon
                                            : kAccountAddChromeRefreshOldIcon);
    }
    if (is_guest_mode_enabled) {
      BuildGuestProfileRow(profile);
    }

    AddItemWithStringIdAndVectorIcon(
        this, IDC_MANAGE_CHROME_PROFILES, IDS_MANAGE_CHROME_PROFILES,
        features::IsRoundedIconsEnabled() ? kManageAccountsIcon
                                          : kAccountManageChromeRefreshOldIcon);
  }
}

bool ProfileSubMenuModel::IsCommandIdChecked(int command_id) const {
  return false;
}

bool ProfileSubMenuModel::IsCommandIdEnabled(int command_id) const {
  if (command_id >= AppMenuModel::kMinOtherProfileCommandId) {
    return true;
  }
  return app_menu_model_delegate_ &&
         app_menu_model_delegate_->IsCommandIdEnabled(command_id);
}

bool ProfileSubMenuModel::GetAcceleratorForCommandId(
    int command_id,
    ui::Accelerator* accelerator) const {
  return app_menu_model_delegate_ &&
         app_menu_model_delegate_->GetAcceleratorForCommandId(command_id,
                                                              accelerator);
}

void ProfileSubMenuModel::ExecuteCommand(int command_id, int event_flags) {
  if (other_profiles_.find(command_id) != other_profiles_.end()) {
    return profiles::SwitchToProfile(other_profiles_[command_id],
                                     /*always_create=*/false);
  }
  if (app_menu_model_delegate_) {
    app_menu_model_delegate_->ExecuteCommand(command_id, event_flags);
  }
  return;
}

int ProfileSubMenuModel::GetAndIncrementNextMenuID() {
  const int current_id = next_other_profile_menu_id_;
  next_other_profile_menu_id_ += AppMenuModel::kNumUnboundedMenuTypes;
  return current_id;
}

bool ProfileSubMenuModel::BuildSyncSection() {
#if !BUILDFLAG(IS_CHROMEOS)
  // TODO(crbug.com/440342282): Support personalized signin button.
  if (!CanOfferSignin(profile_, GaiaId(), /*email=*/std::string(),
                      /*allow_account_from_other_profile=*/true)
           .IsOk()) {
    return false;
  }
#endif  // BUILDFLAG(IS_CHROMEOS)

  if (!SyncServiceFactory::IsSyncAllowed(profile_)) {
    return false;
  }

  signin::IdentityManager* identity_manager =
      IdentityManagerFactory::GetForProfile(profile_);
  AddTitle(GetSyncSectionTitle(profile_, identity_manager));

  // First, check for sync errors. They may exist even if sync-the-feature is
  // disabled and only sync-the-transport is running.
  syncer::SyncService* service = SyncServiceFactory::GetForProfile(profile_);
  if (service) {
    const syncer::SyncService::UserActionableError error =
        service->GetUserActionableError();
    if (error != syncer::SyncService::UserActionableError::kNone) {
      int command_id = 0;
      const gfx::VectorIcon* icon = nullptr;
      int button_string_id =
          GetSyncErrorButtonStringId(error, /*support_title_case=*/true);
      switch (error) {
        case syncer::SyncService::UserActionableError::kNone:
          NOTREACHED();
        case syncer::SyncService::UserActionableError::kSignInNeedsUpdate:
          command_id = IDC_SHOW_SIGNIN_WHEN_PAUSED;
          if (identity_manager->HasPrimaryAccount(
                  signin::ConsentLevel::kSync)) {
            button_string_id = IDS_SYNC_RELOGIN_BUTTON_MAYBE_TITLE_CASE;
            icon = &(features::IsRoundedIconsEnabled()
                         ? vector_icons::kSyncDisabledIcon
                         : vector_icons::kSyncOffChromeRefreshOldIcon);
          } else {
            // Merge this case with the others below once ConsentLevel::kSync is
            // gone.
            icon = &(features::IsRoundedIconsEnabled()
                         ? vector_icons::kAccountCircleOffIcon
                         : vector_icons::kAccountCircleOffChromeRefreshOldIcon);
          }
          break;
        case syncer::SyncService::UserActionableError::
            kNeedsTrustedVaultKeyForPasswords:
        case syncer::SyncService::UserActionableError::
            kTrustedVaultRecoverabilityDegradedForPasswords:
        case syncer::SyncService::UserActionableError::
            kTrustedVaultRecoverabilityDegradedForEverything:
        case syncer::SyncService::UserActionableError::
            kNeedsTrustedVaultKeyForEverything:
          command_id = IDC_SHOW_SIGNIN_WHEN_PAUSED;
          icon = &(features::IsRoundedIconsEnabled()
                       ? vector_icons::kAccountCircleOffIcon
                       : vector_icons::kAccountCircleOffChromeRefreshOldIcon);
          break;
        case syncer::SyncService::UserActionableError::kNeedsClientUpgrade:
          command_id = IDC_UPGRADE_DIALOG;
          icon = &(features::IsRoundedIconsEnabled()
                       ? vector_icons::kErrorIcon
                       : vector_icons::kErrorOutlineOldIcon);
          break;
        case syncer::SyncService::UserActionableError::kNeedsPassphrase:
          command_id = IDC_SHOW_SYNC_PASSPHRASE_DIALOG;
          icon = &(features::IsRoundedIconsEnabled()
                       ? vector_icons::kErrorIcon
                       : vector_icons::kErrorOutlineOldIcon);
          break;
        case syncer::SyncService::UserActionableError::
            kNeedsSettingsConfirmation:
        case syncer::SyncService::UserActionableError::kUnrecoverableError:
          // Only shown for "Sync-the-feature".
          command_id = IDC_SHOW_SYNC_SETTINGS;
          icon = &(features::IsRoundedIconsEnabled()
                       ? vector_icons::kErrorIcon
                       : vector_icons::kErrorOutlineOldIcon);
          break;
        case syncer::SyncService::UserActionableError::kBookmarksLimitExceeded:
          // For this specific error (as opposed to all others), there is no
          // error UI in the menu.
          return true;
      }
      CHECK_NE(command_id, 0);
      AddItemWithStringIdAndVectorIcon(this, command_id, button_string_id,
                                       *icon);
      return true;
    }
  }

  if (identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_SHOW_SYNC_SETTINGS, IDS_PROFILE_ROW_SYNC_IS_ON,
        features::IsRoundedIconsEnabled()
            ? vector_icons::kSyncIcon
            : vector_icons::kSyncChromeRefreshOldIcon);
  } else {
    if (syncer::IsReplaceSyncPromosWithSignInPromosEnabled()) {
      if (!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
        AddItemWithStringIdAndVectorIcon(
            this, IDC_SHOW_SIGNIN, IDS_PROFILE_MENU_SIGNIN_PROMO_BUTTON,
            features::IsRoundedIconsEnabled()
                ? kAccountCircleFilledIcon
                : vector_icons::kAccountCircleOldIcon);
        signin_metrics::LogSignInOffered(
            signin_metrics::AccessPoint::kMenu,
            signin_ui_util::GetSingleAccountForPromos(
                identity_manager,
                AccountPreviewDataServiceFactory::GetForProfile(profile_))
                    .IsEmpty()
                ? signin_metrics::PromoAction::
                      PROMO_ACTION_NEW_ACCOUNT_NO_EXISTING_ACCOUNT
                : signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT);
      }
    } else {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_TURN_ON_SYNC, IDS_PROFILE_ROW_TURN_ON_SYNC,
          features::IsRoundedIconsEnabled()
              ? vector_icons::kSyncDisabledIcon
              : vector_icons::kSyncOffChromeRefreshOldIcon);
    }
  }
  return true;
}

void ProfileSubMenuModel::BuildGuestProfileRow(Profile* profile) {
  AddItemWithStringIdAndVectorIcon(
      this, IDC_OPEN_GUEST_PROFILE, IDS_OPEN_GUEST_PROFILE,
      features::IsRoundedIconsEnabled() ? kAccountBoxIcon : kAccountBoxOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_OPEN_GUEST_PROFILE).value(),
                         AppMenuModel::kProfileOpenGuestItem);
}
// TODO(b/540249284): Temporarily Isolated mode is treated as Incognito. This
// should be revisited when deciding on the final integration of Isolated
// mode.
void ProfileSubMenuModel::BuildCustomizeProfileRow(Profile* profile) {
  if (!profile->IsIncognitoProfile() && !profile->IsGuestSession() &&
      !profile->IsEnterpriseIsolatedModeProfile()) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_CUSTOMIZE_CHROME, IDS_CUSTOMIZE_CHROME,
        features::IsRoundedIconsEnabled()
            ? kEditIcon
            : vector_icons::kEditChromeRefreshOldIcon);
  }
}

void ProfileSubMenuModel::BuildCloseProfileRow(Profile* profile) {
  AddItemWithIcon(IDC_CLOSE_PROFILE,
                  l10n_util::GetPluralStringFUTF16(IDS_CLOSE_PROFILE,
                                                   CountBrowsersFor(profile)),
                  ui::ImageModel::FromVectorIcon(
                      features::IsRoundedIconsEnabled()
                          ? vector_icons::kCloseIcon
                          : vector_icons::kCloseChromeRefreshOldIcon,
                      ui::kColorMenuIcon, kDefaultIconSize));
}

void ProfileSubMenuModel::BuildManageGoogleAccountRow(Profile* profile) {
  if (HasUnconstentedProfile(profile) && !IsSyncPaused(profile) &&
      !profile->IsIncognitoProfile() &&
      !profile->IsEnterpriseIsolatedModeProfile()) {
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
    const gfx::VectorIcon& manage_account_icon =
        vector_icons::kGoogleGLogoMonochromeIcon;
#else
    const gfx::VectorIcon& manage_account_icon =
        features::IsRoundedIconsEnabled() ? kManageAccountsIcon
                                          : kAccountManageChromeRefreshOldIcon;
#endif
    AddItemWithStringIdAndVectorIcon(this, IDC_MANAGE_GOOGLE_ACCOUNT,
                                     IDS_MANAGE_GOOGLE_ACCOUNT,
                                     manage_account_icon);
  }
}
#endif  // !BUILDFLAG(IS_CHROMEOS)

class PasswordsAndAutofillSubMenuModel : public ui::SimpleMenuModel {
 public:
  explicit PasswordsAndAutofillSubMenuModel(
      ui::SimpleMenuModel::Delegate* delegate);
  PasswordsAndAutofillSubMenuModel(const PasswordsAndAutofillSubMenuModel&) =
      delete;
  PasswordsAndAutofillSubMenuModel& operator=(
      const PasswordsAndAutofillSubMenuModel&) = delete;
  ~PasswordsAndAutofillSubMenuModel() override = default;
};

PasswordsAndAutofillSubMenuModel::PasswordsAndAutofillSubMenuModel(
    ui::SimpleMenuModel::Delegate* delegate)
    : SimpleMenuModel(delegate) {
  AddItemWithStringIdAndVectorIcon(this, IDC_SHOW_PASSWORD_MANAGER,
                                   IDS_VIEW_PASSWORDS,
                                   features::IsRoundedIconsEnabled()
                                       ? vector_icons::kPasswordManagerIcon
                                       : vector_icons::kPasswordManagerOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_SHOW_PASSWORD_MANAGER).value(),
                         AppMenuModel::kPasswordManagerMenuItem);

  AddItemWithStringIdAndVectorIcon(this, IDC_SHOW_PAYMENT_METHODS,
                                   IDS_YOUR_SAVED_INFO_PAYMENTS_SUBMENU_OPTION,
                                   features::IsRoundedIconsEnabled()
                                       ? kCreditCardIcon
                                       : kCreditCardChromeRefreshOldIcon);

  AddItemWithStringIdAndVectorIcon(
      this, IDC_SHOW_CONTACT_INFO,
      IDS_YOUR_SAVED_INFO_CONTACT_INFO_SUBMENU_OPTION,
      features::IsRoundedIconsEnabled()
          ? vector_icons::kLocationOnIcon
          : vector_icons::kLocationOnChromeRefreshOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_SHOW_CONTACT_INFO).value(),
                         AppMenuModel::kContactInfoMenuItem);
  AddItemWithStringIdAndVectorIcon(
      this, IDC_SHOW_IDENTITY_DOCS, IDS_IDENTITY_DOCS_SUBMENU_OPTION,
      features::IsRoundedIconsEnabled() ? vector_icons::kIdCardIcon
                                        : vector_icons::kIdCardOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_SHOW_IDENTITY_DOCS).value(),
                         AppMenuModel::kIdentityDocsMenuItem);
  AddItemWithStringIdAndVectorIcon(
      this, IDC_SHOW_TRAVEL, IDS_TRAVEL_SUBMENU_OPTION,
      features::IsRoundedIconsEnabled() ? vector_icons::kTripIcon
                                        : vector_icons::kTripOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_SHOW_TRAVEL).value(),
                         AppMenuModel::kTravelMenuItem);
}

class FindAndEditSubMenuModel : public ui::SimpleMenuModel {
 public:
  explicit FindAndEditSubMenuModel(ui::SimpleMenuModel::Delegate* delegate);
  FindAndEditSubMenuModel(const FindAndEditSubMenuModel&) = delete;
  FindAndEditSubMenuModel& operator=(const FindAndEditSubMenuModel&) = delete;
  ~FindAndEditSubMenuModel() override = default;
};

FindAndEditSubMenuModel::FindAndEditSubMenuModel(
    ui::SimpleMenuModel::Delegate* delegate)
    : SimpleMenuModel(delegate) {
  AddItemWithStringIdAndVectorIcon(
      this, IDC_FIND, IDS_FIND,
      features::IsRoundedIconsEnabled() ? kFindInPageIcon : kSearchMenuOldIcon);
  AddSeparator(ui::NORMAL_SEPARATOR);
  AddItemWithStringIdAndVectorIcon(
      this, IDC_CUT, IDS_CUT,
      features::IsRoundedIconsEnabled() ? kContentCutIcon : kCutMenuOldIcon);
  AddItemWithStringIdAndVectorIcon(this, IDC_COPY, IDS_COPY,
                                   features::IsRoundedIconsEnabled()
                                       ? vector_icons::kContentCopyIcon
                                       : kCopyMenuOldIcon);
  AddItemWithStringIdAndVectorIcon(this, IDC_PASTE, IDS_PASTE,
                                   features::IsRoundedIconsEnabled()
                                       ? kContentPasteIcon
                                       : kPasteMenuOldIcon);
}

class SaveAndShareSubMenuModel : public ui::SimpleMenuModel {
 public:
  SaveAndShareSubMenuModel(ui::SimpleMenuModel::Delegate* delegate,
                           BrowserWindowInterface* browser);
  SaveAndShareSubMenuModel(const SaveAndShareSubMenuModel&) = delete;
  SaveAndShareSubMenuModel& operator=(const SaveAndShareSubMenuModel&) = delete;
  ~SaveAndShareSubMenuModel() override = default;

 private:
  // Builds Send Tab to Self target device submenu when enhanced desktop UI is
  // enabled.
  void BuildSendTabToSelfSubmenu(BrowserWindowInterface* browser,
                                 content::WebContents* web_contents);

  // Fallback helper to add simple Send Tab to Self menu item.
  void BuildSendTabToSelfSimpleItem();

  std::unique_ptr<send_tab_to_self::SendTabToSelfContextMenuDelegate>
      send_tab_to_self_submenu_delegate_;
  std::unique_ptr<ui::SimpleMenuModel> send_tab_to_self_submenu_;
};

void SaveAndShareSubMenuModel::BuildSendTabToSelfSubmenu(
    BrowserWindowInterface* browser,
    content::WebContents* web_contents) {
  CHECK(web_contents);

  send_tab_to_self_submenu_delegate_ =
      std::make_unique<send_tab_to_self::SendTabToSelfContextMenuDelegate>(
          web_contents, send_tab_to_self::ShareEntryPoint::kShareMenu);
  send_tab_to_self_submenu_ = std::make_unique<ui::SimpleMenuModel>(
      send_tab_to_self_submenu_delegate_.get());
  send_tab_to_self_submenu_delegate_->PopulateSubmenu(
      send_tab_to_self_submenu_.get());

  AddSubMenuWithStringIdAndIcon(
      IDC_SEND_TAB_TO_SELF, IDS_MENU_SEND_TAB_TO_SELF,
      send_tab_to_self_submenu_.get(),
      ui::ImageModel::FromVectorIcon(GetSendTabToSelfIcon()));

  SetIsNewFeatureAt(GetItemCount() - 1,
                    UserEducationService::MaybeShowNewBadge(
                        browser->GetProfile(),
                        send_tab_to_self::kSendTabToSelfEnhancedDesktopUIv2));
}

void SaveAndShareSubMenuModel::BuildSendTabToSelfSimpleItem() {
  AddItemWithStringIdAndVectorIcon(this, IDC_SEND_TAB_TO_SELF,
                                   IDS_MENU_SEND_TAB_TO_SELF,
                                   GetSendTabToSelfIcon());
}

SaveAndShareSubMenuModel::SaveAndShareSubMenuModel(
    ui::SimpleMenuModel::Delegate* delegate,
    BrowserWindowInterface* browser)
    : SimpleMenuModel(delegate) {
  if (media_router::MediaRouterEnabled(browser->GetProfile())) {
    AddTitle(l10n_util::GetStringUTF16(IDS_SAVE_AND_SHARE_MENU_CAST));
    SetElementIdentifierAt(GetItemCount() - 1, AppMenuModel::kCastTitleItem);
    AddItemWithStringIdAndVectorIcon(
        this, IDC_ROUTE_MEDIA, IDS_MEDIA_ROUTER_MENU_ITEM_TITLE,
        features::IsRoundedIconsEnabled() ? kCastIcon
                                          : kCastChromeRefreshOldIcon);
    AddSeparator(ui::NORMAL_SEPARATOR);
  }
  AddTitle(l10n_util::GetStringUTF16(IDS_SAVE_AND_SHARE_MENU_SAVE));
  AddItemWithStringIdAndVectorIcon(this, IDC_SAVE_PAGE, IDS_SAVE_PAGE,
                                   features::IsRoundedIconsEnabled()
                                       ? kFileSaveIcon
                                       : kFileSaveChromeRefreshOldIcon);
  AddSeparator(ui::NORMAL_SEPARATOR);
  if (std::u16string install_item = GetInstallPWALabel(browser);
      !install_item.empty()) {
    AddItemWithIcon(IDC_INSTALL_PWA, install_item, GetInstallPWAIcon(browser));
    SetElementIdentifierAt(GetItemCount() - 1, AppMenuModel::kInstallAppItem);
  } else if (std::u16string open_item = GetOpenPWALabel(browser);
             !open_item.empty()) {
    AddItemWithIcon(IDC_OPEN_IN_PWA_WINDOW, open_item,
                    ui::ImageModel::FromVectorIcon(
                        features::IsRoundedIconsEnabled()
                            ? kDesktopWindowsIcon
                            : kDesktopWindowsChromeRefreshOldIcon,
                        ui::kColorMenuIcon, kDefaultIconSize));
  }
  AddItemWithStringIdAndVectorIcon(
      this, IDC_CREATE_SHORTCUT, IDS_ADD_TO_OS_LAUNCH_SURFACE,
      features::IsRoundedIconsEnabled() ? kDriveShortcutIcon
                                        : kDriveShortcutChromeRefreshOldIcon);
  SetElementIdentifierAt(GetItemCount() - 1, AppMenuModel::kCreateShortcutItem);
  if (!sharing_hub::SharingIsDisabledByPolicy(browser->GetProfile()) ||
      sharing_hub::DesktopScreenshotsFeatureEnabled(browser->GetProfile())) {
    AddSeparator(ui::NORMAL_SEPARATOR);
    AddTitle(l10n_util::GetStringUTF16(IDS_SAVE_AND_SHARE_MENU_SHARE));
    if (!sharing_hub::SharingIsDisabledByPolicy(browser->GetProfile())) {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_COPY_URL, IDS_APP_MENU_COPY_LINK,
          features::IsRoundedIconsEnabled() ? vector_icons::kLinkIcon
                                            : kLinkChromeRefreshOldIcon);

      // WebContents is required to query target devices and display state for
      // Send Tab to Self.
      content::WebContents* web_contents =
          browser->tab_strip_model()->GetActiveWebContents();
      std::optional<send_tab_to_self::EntryPointDisplayReason> reason =
          web_contents
              ? send_tab_to_self::GetEntryPointDisplayReason(web_contents)
              : std::nullopt;

      // When enhanced desktop UI v2 feature flag is enabled and feature is
      // offered, build submenu with available devices. Otherwise, build simple
      // command item.
      if (web_contents &&
          base::FeatureList::IsEnabled(
              send_tab_to_self::kSendTabToSelfEnhancedDesktopUIv2) &&
          reason == send_tab_to_self::EntryPointDisplayReason::kOfferFeature) {
        BuildSendTabToSelfSubmenu(browser, web_contents);
      } else {
        BuildSendTabToSelfSimpleItem();
      }

      AddItemWithStringIdAndVectorIcon(
          this, IDC_QRCODE_GENERATOR, IDS_APP_MENU_CREATE_QR_CODE,
          features::IsRoundedIconsEnabled() ? kQrCodeIcon
                                            : kQrCodeChromeRefreshOldIcon);
    }
    if (sharing_hub::DesktopScreenshotsFeatureEnabled(browser->GetProfile())) {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_SHARING_HUB_SCREENSHOT, IDS_SHARING_HUB_SCREENSHOT_LABEL,
          features::IsRoundedIconsEnabled() ? kScreenshotRegionIcon
                                            : kSharingHubScreenshotOldIcon);
    }
  }
}

bool ArePromotionsEnabled() {
  PrefService* local_state = g_browser_process->local_state();
  return local_state && local_state->GetBoolean(prefs::kPromotionsEnabled);
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// SetCommandIcon
void SetCommandIcon(ui::SimpleMenuModel* model,
                    int command_id,
                    const gfx::VectorIcon& vector_icon) {
  auto index = model->GetIndexOfCommandId(command_id);
  if (index) {
    model->SetIcon(index.value(), ui::ImageModel::FromVectorIcon(
                                      vector_icon, ui::kColorMenuIcon,
                                      ui::SimpleMenuModel::kDefaultIconSize));
  }
}

////////////////////////////////////////////////////////////////////////////////
// LogWrenchMenuAction
void LogWrenchMenuAction(AppMenuAction action_id) {
  base::UmaHistogramEnumeration("WrenchMenu.MenuAction", action_id,
                                LIMIT_MENU_ACTION);
}

////////////////////////////////////////////////////////////////////////////////
// HelpMenuModel
// Only used in branded builds.

HelpMenuModel::HelpMenuModel(ui::SimpleMenuModel::Delegate* delegate,
                             BrowserWindowInterface* browser)
    : SimpleMenuModel(delegate) {
  Build(browser);
}

HelpMenuModel::~HelpMenuModel() = default;

void HelpMenuModel::Build(BrowserWindowInterface* browser) {
#if BUILDFLAG(IS_CHROMEOS) && defined(OFFICIAL_BUILD)
  int help_string_id = IDS_GET_HELP;
#else
  int help_string_id = IDS_HELP_PAGE;
#endif
  AddItemWithStringIdAndVectorIcon(this, IDC_ABOUT, IDS_ABOUT,
                                   features::IsRoundedIconsEnabled()
                                       ? vector_icons::kInfoIcon
                                       : vector_icons::kInfoRefreshOldIcon);
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  if (whats_new::IsEnabled()) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_CHROME_WHATS_NEW, IDS_CHROME_WHATS_NEW,
        features::IsRoundedIconsEnabled() ? kReleaseAlertIcon
                                          : kReleaseAlertOldIcon);
  }
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
  AddItemWithStringId(IDC_HELP_PAGE_VIA_MENU, help_string_id);
  if (browser_defaults::kShowHelpMenuItemIcon) {
    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    SetIconForCommandId(
        IDC_HELP_PAGE_VIA_MENU,
        ui::ImageModel::FromImage(rb.GetNativeImageNamed(IDR_HELP_MENU)));
  } else {
    SetCommandIcon(
        this, IDC_HELP_PAGE_VIA_MENU,
        features::IsRoundedIconsEnabled() ? kHelpCustomIcon : kHelpMenuOldIcon);
  }
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  if (chrome::CanShowFeedback(browser->GetProfile())) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_FEEDBACK, IDS_FEEDBACK,
        features::IsRoundedIconsEnabled() ? kFeedbackIcon : kReportOldIcon);

    if (feedback::ReportUnsafeSiteDialog::IsEnabled(*browser->GetProfile())) {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_REPORT_UNSAFE_SITE, IDS_REPORT_UNSAFE_SITE,
          features::IsRoundedIconsEnabled() ? vector_icons::kWarningFilledIcon
                                            : vector_icons::kWarningOldIcon);
      SetElementIdentifierAt(
          GetIndexOfCommandId(IDC_REPORT_UNSAFE_SITE).value(),
          HelpMenuModel::kReportUnsafeSiteMenuItem);
    }
  }
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}

////////////////////////////////////////////////////////////////////////////////
// ToolsMenuModel

ToolsMenuModel::ToolsMenuModel(ui::SimpleMenuModel::Delegate* delegate,
                               BrowserWindowInterface* browser)
    : SimpleMenuModel(delegate) {
  Build(browser);
}

ToolsMenuModel::~ToolsMenuModel() = default;

// More tools submenu is constructed as follows:
// - Page specific actions overflow (save page, adding to desktop).
// - Browser / OS level tools (extensions, task manager).
// - Reading mode.
// - Developer tools.
// - Option to enable profiling.
void ToolsMenuModel::Build(BrowserWindowInterface* browser) {
  // Tablet mode does not have a Tab Search button. We should not show tablet
  // mode users these menu items.
  bool is_tablet_mode = false;
#if BUILDFLAG(IS_CHROMEOS)
  is_tablet_mode = display::Screen::Get()->InTabletMode();
#endif  // BUILDFLAG(IS_CHROMEOS)
  if (!is_tablet_mode) {
    AddItemWithStringIdAndVectorIcon(this, IDC_TAB_SEARCH, IDS_TAB_SEARCH_MENU,
                                     features::IsRoundedIconsEnabled()
                                         ? kManageSearchIcon
                                         : kTabSearchTabStripOldIcon);
  }

  AddItemWithStringIdAndVectorIcon(
      this, IDC_NAME_WINDOW, IDS_NAME_WINDOW,
      features::IsRoundedIconsEnabled() ? kWebAssetIcon : kNameWindowOldIcon);

  if (auto* controller = tabs::VerticalTabStripStateController::From(browser)) {
    if (controller->ShouldDisplayVerticalTabs()) {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_TOGGLE_VERTICAL_TABS, IDS_SWITCH_TO_HORIZONTAL_TAB,
          features::IsRoundedIconsEnabled() ? kToolbarIcon : kToolbarOldIcon);
    } else {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_TOGGLE_VERTICAL_TABS, IDS_SWITCH_TO_VERTICAL_TAB,
          base::i18n::IsRTL() ? features::IsRoundedIconsEnabled()
                                    ? kDockToLeftIcon
                                    : kDockToRightOldIcon
          : features::IsRoundedIconsEnabled() ? kDockToRightIcon
                                              : kDockToLeftOldIcon);
      const user_education::DisplayNewBadge show_badge =
          UserEducationService::MaybeShowNewBadge(browser->GetProfile(),
                                                  tabs::kVerticalTabsNewBadge);
      SetIsNewFeatureAt(GetIndexOfCommandId(IDC_TOGGLE_VERTICAL_TABS).value(),
                        show_badge, ui::NewBadgeType::kNew);
    }
  }

  if (CustomizeChromePageHandler::IsSupported(
          NtpCustomBackgroundServiceFactory::GetForProfile(
              browser->GetProfile()),
          browser->GetProfile())) {
    AddItemWithStringIdAndVectorIcon(this, IDC_SHOW_CUSTOMIZE_CHROME_SIDE_PANEL,
                                     IDS_SHOW_CUSTOMIZE_CHROME_SIDE_PANEL,
                                     features::IsRoundedIconsEnabled()
                                         ? kEditIcon
                                         : kEditChromeRefreshOldIcon);
  }

  AddSeparator(ui::NORMAL_SEPARATOR);

  AddItemWithStringIdAndVectorIcon(
      this, IDC_SHOW_READING_MODE_SIDE_PANEL, IDS_SHOW_READING_MODE_SIDE_PANEL,
      features::IsRoundedIconsEnabled() ? kMenuBookIcon
                                        : kMenuBookChromeRefreshOldIcon);
  SetElementIdentifierAt(
      GetIndexOfCommandId(IDC_SHOW_READING_MODE_SIDE_PANEL).value(),
      kReadingModeMenuItem);

  AddSeparator(ui::NORMAL_SEPARATOR);

  AddItemWithStringIdAndVectorIcon(
      this, IDC_PERFORMANCE, IDS_SHOW_PERFORMANCE,
      features::IsRoundedIconsEnabled() ? kSpeedIcon : kPerformanceOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_PERFORMANCE).value(),
                         kPerformanceMenuItem);

  if (chrome::CanOpenTaskManager()) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_TASK_MANAGER_APP_MENU, IDS_TASK_MANAGER,
        features::IsRoundedIconsEnabled() ? kTableChartIcon
                                          : kTaskManagerOldIcon);
  }
#if BUILDFLAG(IS_CHROMEOS)
  AddItemWithStringId(IDC_TAKE_SCREENSHOT, IDS_TAKE_SCREENSHOT);
#endif
  AddSeparator(ui::NORMAL_SEPARATOR);
  AddItemWithStringIdAndVectorIcon(
      this, IDC_DEV_TOOLS, IDS_DEV_TOOLS,
      features::IsRoundedIconsEnabled() ? kCodeIcon : kDeveloperToolsOldIcon);

  if (base::debug::IsProfilingSupported()) {
    AddSeparator(ui::NORMAL_SEPARATOR);
    AddCheckItemWithStringId(IDC_PROFILING_ENABLED, IDS_PROFILING_ENABLED);
  }
  if (IsChromeLabsEnabled()) {
    auto* profile = browser->GetProfile();
    UpdateChromeLabsNewBadgePrefs(profile);
    if (ShouldShowChromeLabsUI(profile)) {
      BooleanPrefMember show_chrome_labs_item;
      show_chrome_labs_item.Init(
          chrome_labs_prefs::kBrowserLabsEnabledEnterprisePolicy,
          profile->GetPrefs());
      if (show_chrome_labs_item.GetValue()) {
        AddSeparator(ui::NORMAL_SEPARATOR);
        AddItemWithStringIdAndVectorIcon(
            this, IDC_SHOW_CHROME_LABS, IDS_CHROMELABS,
            features::IsRoundedIconsEnabled() ? vector_icons::kScienceIcon
                                              : vector_icons::kScienceOldIcon);
        SetElementIdentifierAt(
            GetIndexOfCommandId(IDC_SHOW_CHROME_LABS).value(),
            kChromeLabsMenuItem);
      }
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
// ExtensionsMenuModel

ExtensionsMenuModel::ExtensionsMenuModel(
    ui::SimpleMenuModel::Delegate* delegate,
    BrowserWindowInterface* browser)
    : SimpleMenuModel(delegate) {
  Build(browser);
}

ExtensionsMenuModel::~ExtensionsMenuModel() = default;

// Extensions (sub)menu is constructed as follows:
// - An overflow with two items:
//   - An item to manage extensions at chrome://extensions
//   - An item to visit the Chrome Web Store
void ExtensionsMenuModel::Build(BrowserWindowInterface* browser) {
  AddItemWithStringIdAndVectorIcon(
      this, IDC_EXTENSIONS_SUBMENU_MANAGE_EXTENSIONS,
      IDS_EXTENSIONS_SUBMENU_MANAGE_EXTENSIONS_ITEM,
      features::IsRoundedIconsEnabled()
          ? vector_icons::kChromeExtensionIcon
          : vector_icons::kExtensionChromeRefreshOldIcon);
  SetElementIdentifierAt(
      GetIndexOfCommandId(IDC_EXTENSIONS_SUBMENU_MANAGE_EXTENSIONS).value(),
      kManageExtensionsMenuItem);
  AddItemWithStringId(IDC_EXTENSIONS_SUBMENU_VISIT_CHROME_WEB_STORE,
                      IDS_EXTENSIONS_SUBMENU_CHROME_WEBSTORE_ITEM);
  SetElementIdentifierAt(
      GetIndexOfCommandId(IDC_EXTENSIONS_SUBMENU_VISIT_CHROME_WEB_STORE)
          .value(),
      kVisitChromeWebStoreMenuItem);
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  SetCommandIcon(this, IDC_EXTENSIONS_SUBMENU_VISIT_CHROME_WEB_STORE,
                 vector_icons::kGoogleChromeWebstoreIcon);
#endif
}

////////////////////////////////////////////////////////////////////////////////
// AppMenuModel

// static
AlertMenuItem AppMenuModel::GetAlertItemForRunningTutorial(
    BrowserWindowInterface* browser) {
  if (!browser || !browser->GetWindow()) {
    return AlertMenuItem::kNone;
  }
  auto* const service =
      UserEducationServiceFactory::GetForBrowserContext(browser->GetProfile());
  return service && service->tutorial_service().IsRunningTutorial(
                        kPasswordManagerTutorialId)
             ? AlertMenuItem::kPasswordManager
             : AlertMenuItem::kNone;
}

AppMenuModel::AppMenuModel(ui::AcceleratorProvider* provider,
                           BrowserWindowInterface* browser,
                           AppMenuIconController* app_menu_icon_controller,
                           AlertMenuItem alert_item)
    : ui::SimpleMenuModel(this),
      uma_action_recorded_(false),
      provider_(provider),
      browser_(browser),
      app_menu_icon_controller_(app_menu_icon_controller),
      alert_item_(alert_item) {
  DCHECK(browser_);
}

AppMenuModel::~AppMenuModel() = default;

void AppMenuModel::Init() {
  Build();

#if BUILDFLAG(IS_CHROMEOS)
  PrefService* const local_state = g_browser_process->local_state();
  if (local_state) {
    local_state_pref_change_registrar_.Init(local_state);
    local_state_pref_change_registrar_.Add(
        policy::policy_prefs::kSystemFeaturesDisableList,
        base::BindRepeating(&AppMenuModel::UpdateSettingsItemState,
                            base::Unretained(this)));
    UpdateSettingsItemState();
  }
#endif  // BUILDFLAG(IS_CHROMEOS)
}

bool AppMenuModel::DoesCommandIdDismissMenu(int command_id) const {
  return command_id != IDC_ZOOM_MINUS && command_id != IDC_ZOOM_PLUS;
}

void AppMenuModel::ExecuteCommand(int command_id, int event_flags) {
  GlobalError* error =
      GlobalErrorServiceFactory::GetForProfile(browser_->GetProfile())
          ->GetGlobalErrorByMenuItemCommandID(command_id);
  if (error) {
    error->ExecuteMenuItem(browser_);
    return;
  }

  if (command_id == IDC_VIEW_PASSWORDS) {
    browser()->GetProfile()->GetPrefs()->SetBoolean(
        password_manager::prefs::kPasswordsPrefWithNewLabelUsed, true);
  }

  LogMenuMetrics(command_id);

  switch (command_id) {
    case IDC_SHOW_BOOKMARK_SIDE_PANEL:
    case IDC_SHOW_HISTORY_CLUSTERS_SIDE_PANEL:
    case IDC_SHOW_READING_MODE_SIDE_PANEL:
    case IDC_READING_LIST_MENU_SHOW_UI:
    case IDC_SHOW_CUSTOMIZE_CHROME_SIDE_PANEL: {
      actions::ActionInvocationContext context =
          actions::ActionInvocationContext::Builder()
              .SetProperty(
                  kSidePanelOpenTriggerKey,
                  static_cast<std::underlying_type_t<SidePanelOpenTrigger>>(
                      SidePanelOpenTrigger::kAppMenu))
              .Build();
      chrome::ExecuteCommandWithContext(browser_, command_id,
                                        std::move(context));
      break;
    }

    default:
      chrome::ExecuteCommand(browser_, command_id);
      break;
  }
}

void AppMenuModel::LogSafetyHubInteractionMetrics(
    safety_hub::SafetyHubModuleType sh_module,
    int event_flags) {
  base::UmaHistogramEnumeration("Settings.SafetyHub.Interaction",
                                safety_hub::SafetyHubSurfaces::kThreeDotMenu);
  base::UmaHistogramEnumeration(
      "Settings.SafetyHub.EntryPointInteraction",
      safety_hub::SafetyHubEntryPoint::kMenuNotifications);
  base::UmaHistogramEnumeration("Settings.SafetyHub.MenuNotificationClicked",
                                sh_module);

  if (SafetyHubHatsService* hats_service =
          SafetyHubHatsServiceFactory::GetForProfile(browser_->GetProfile())) {
    hats_service->SafetyHubNotificationClicked(sh_module);
  }
}

void AppMenuModel::LogMenuMetrics(int command_id) {
  base::TimeDelta delta = timer_.Elapsed();

  switch (command_id) {
    case IDC_UPGRADE_DIALOG:
      LogMenuAction(MENU_ACTION_UPGRADE_DIALOG);
      break;
    case IDC_NEW_TAB:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.NewTab", delta);
      }
      LogMenuAction(MENU_ACTION_NEW_TAB);
      break;
    case IDC_NEW_WINDOW:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.NewWindow",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_NEW_WINDOW);
      break;
    case IDC_NEW_INCOGNITO_WINDOW:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.NewIncognitoWindow", delta);
      }
      LogMenuAction(MENU_ACTION_NEW_INCOGNITO_WINDOW);
      break;
    case IDC_NEW_ISOLATED_WINDOW:
      LogMenuAction(MENU_ACTION_NEW_ISOLATED_WINDOW);
      break;

    // Bookmarks sub menu.
    case IDC_SHOW_BOOKMARK_BAR:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowBookmarkBar",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_BOOKMARK_BAR);
      break;
    case IDC_SHOW_BOOKMARK_SIDE_PANEL:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowBookmarkSidePanel", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_BOOKMARK_SIDE_PANEL);
      // Close IPH for side panel menu, if shown.
      BrowserUserEducationInterface::From(browser())
          ->NotifyFeaturePromoFeatureUsed(
              feature_engagement::kIPHPowerBookmarksSidePanelFeature,
              FeaturePromoFeatureUsedAction::kIgnorePromoIfPresent);
      break;
    case IDC_SHOW_BOOKMARK_MANAGER:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowBookmarkMgr",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_BOOKMARK_MANAGER);
      break;
    case IDC_IMPORT_SETTINGS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ImportSettings",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_IMPORT_SETTINGS);
      break;
    case IDC_BOOKMARK_THIS_TAB:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.BookmarkPage",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_BOOKMARK_THIS_TAB);
      break;
    case IDC_BOOKMARK_ALL_TABS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.BookmarkAllTabs",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_BOOKMARK_ALL_TABS);
      break;
    // Lens overlay.
    case IDC_CONTENT_CONTEXT_LENS_OVERLAY:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowLensOverlay",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_LENS_OVERLAY);
      break;
    // Extensions menu.
    case IDC_EXTENSIONS_SUBMENU_MANAGE_EXTENSIONS:
      // Logging the original histograms for experiment comparison purposes.
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ManageExtensions", delta);
      }
      LogMenuAction(MENU_ACTION_MANAGE_EXTENSIONS);
      break;
    case IDC_EXTENSIONS_SUBMENU_VISIT_CHROME_WEB_STORE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.VisitChromeWebStore", delta);
      }
      LogMenuAction(MENU_ACTION_VISIT_CHROME_WEB_STORE);
      break;
    case IDC_FIND_EXTENSIONS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.FindExtensions",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_FIND_EXTENSIONS);
      break;
    // Recent tabs menu.
    case IDC_RESTORE_TAB:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.RestoreTab",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_RESTORE_TAB);
      break;
    case IDC_OPEN_RECENT_TAB:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.OpenRecentTab",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_RECENT_TAB);
      break;
    case IDC_RECENT_TABS_LOGIN_FOR_DEVICE_TABS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.LoginForDeviceTabs", delta);
      }
      LogMenuAction(MENU_ACTION_RECENT_TABS_LOGIN_FOR_DEVICE_TABS);
      break;
    case IDC_RECENT_TABS_SEE_DEVICE_TABS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.SeeDeviceTabs",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_RECENT_TABS_SEE_DEVICE_TABS);
      break;
    case IDC_FIND:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Find", delta);
      }
      LogMenuAction(MENU_ACTION_FIND);
      break;
    case IDC_PRINT:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Print", delta);
      }
      LogMenuAction(MENU_ACTION_PRINT);
      break;
    case IDC_OPEN_GLIC:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.OpenGlic",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_OPEN_GLIC);
      break;

    case IDC_SHOW_TRANSLATE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowTranslate",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_TRANSLATE);
      break;

    // Edit menu.
    case IDC_CUT:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Cut", delta);
      }
      LogMenuAction(MENU_ACTION_CUT);
      break;
    case IDC_COPY:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Copy", delta);
      }
      LogMenuAction(MENU_ACTION_COPY);
      break;
    case IDC_PASTE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Paste", delta);
      }
      LogMenuAction(MENU_ACTION_PASTE);
      break;

    // Save and share menu.
    case IDC_SAVE_PAGE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.SavePage",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SAVE_PAGE);
      break;
    case IDC_INSTALL_PWA:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.InstallPwa",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_INSTALL_PWA);
      break;
    case IDC_OPEN_IN_PWA_WINDOW:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.OpenInPwaWindow",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_OPEN_IN_PWA_WINDOW);
      break;
    case IDC_CREATE_SHORTCUT:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.CreateHostedApp",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_CREATE_HOSTED_APP);
      break;
    case IDC_COPY_URL:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.CopyUrl", delta);
      }
      LogMenuAction(MENU_ACTION_COPY_URL);
      break;
    case IDC_SEND_TAB_TO_SELF:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.SendToDevices",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SEND_TO_DEVICES);
      break;
    case IDC_QRCODE_GENERATOR:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.CreateQrCode",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_CREATE_QR_CODE);
      break;
    case IDC_ROUTE_MEDIA:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Cast", delta);
      }
      LogMenuAction(MENU_ACTION_CAST);
      break;

    // Tools menu.
    case IDC_MANAGE_EXTENSIONS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ManageExtensions", delta);
      }
      LogMenuAction(MENU_ACTION_MANAGE_EXTENSIONS);
      break;
    case IDC_TASK_MANAGER:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.TaskManager",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_TASK_MANAGER);
      break;
    case IDC_CLEAR_BROWSING_DATA:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ClearBrowsingData", delta);
      }
      LogMenuAction(MENU_ACTION_CLEAR_BROWSING_DATA);
      break;
    case IDC_VIEW_SOURCE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ViewSource",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_VIEW_SOURCE);
      break;
    case IDC_DEV_TOOLS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.DevTools",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_DEV_TOOLS);
      break;
    case IDC_DEV_TOOLS_CONSOLE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.DevToolsConsole",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_DEV_TOOLS_CONSOLE);
      break;
    case IDC_DEV_TOOLS_DEVICES:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.DevToolsDevices",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_DEV_TOOLS_DEVICES);
      break;
    case IDC_PROFILING_ENABLED:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ProfilingEnabled", delta);
      }
      LogMenuAction(MENU_ACTION_PROFILING_ENABLED);
      break;
    case IDC_SHOW_CHROME_LABS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowChromeLabs",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_CHROME_LABS);
      break;
    case IDC_SHOW_HISTORY_CLUSTERS_SIDE_PANEL:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowHistoryClustersSidePanel", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_HISTORY_CLUSTER_SIDE_PANEL);
      break;
    case IDC_SHOW_READING_MODE_SIDE_PANEL:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowReadingModeSidePanel", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_READING_MODE_SIDE_PANEL);
      // Close IPH for side panel menu, if shown.
      BrowserUserEducationInterface::From(browser())
          ->NotifyFeaturePromoFeatureUsed(
              feature_engagement::kIPHReadingModeSidePanelFeature,
              FeaturePromoFeatureUsedAction::kIgnorePromoIfPresent);
      break;
    case IDC_SHOW_CUSTOMIZE_CHROME_SIDE_PANEL:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowCustomizeChromeSidePanel", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_CUSTOMIZE_CHROME_SIDE_PANEL);
      break;
    // Zoom menu
    case IDC_ZOOM_MINUS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ZoomMinus",
                                      delta);
        LogMenuAction(MENU_ACTION_ZOOM_MINUS);
      }
      break;
    case IDC_ZOOM_PLUS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ZoomPlus",
                                      delta);
        LogMenuAction(MENU_ACTION_ZOOM_PLUS);
      }
      break;
    case IDC_FULLSCREEN:
      base::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));

      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.EnterFullScreen",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_FULLSCREEN);
      break;
    case IDC_SHOW_HISTORY:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowHistory",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_HISTORY);
      break;
    case IDC_SHOW_DOWNLOADS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowDownloads",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_DOWNLOADS);
      base::UmaHistogramEnumeration(
          "Download.OpenDownloadsFromMenu.PerProfileType",
          profile_metrics::GetBrowserProfileType(browser_->GetProfile()));
      break;
    case IDC_OPTIONS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Settings",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_OPTIONS);
      base::UmaHistogramEnumeration(
          "Settings.OpenSettingsFromMenu.PerProfileType",
          profile_metrics::GetBrowserProfileType(browser_->GetProfile()));
      break;
    case IDC_ABOUT:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.About", delta);
      }
      LogMenuAction(MENU_ACTION_ABOUT);
      break;
    // Help menu.
    case IDC_HELP_PAGE_VIA_MENU:
      base::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));

      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.HelpPage",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_HELP_PAGE_VIA_MENU);
      break;
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
    case IDC_SHOW_BETA_FORUM:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.BetaForum",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_BETA_FORUM);
      break;
    case IDC_FEEDBACK:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Feedback",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_FEEDBACK);
      break;
    case IDC_CHROME_TIPS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ChromeTips",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_CHROME_TIPS);
      break;
    case IDC_CHROME_WHATS_NEW:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ChromeWhatsNew",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_CHROME_WHATS_NEW);
      break;
#endif

    case IDC_TOGGLE_REQUEST_TABLET_SITE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.RequestTabletSite", delta);
      }
      LogMenuAction(MENU_ACTION_TOGGLE_REQUEST_TABLET_SITE);
      break;
    case IDC_EXIT:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.Exit", delta);
      }
      LogMenuAction(MENU_ACTION_EXIT);
      break;

    // Hosted App menu.
    case IDC_OPEN_IN_CHROME:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.OpenInChrome",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_OPEN_IN_CHROME);
      break;
    case IDC_WEB_APP_MENU_APP_INFO:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.AppInfo", delta);
      }
      LogMenuAction(MENU_ACTION_APP_INFO);
      break;
    case IDC_VIEW_PASSWORDS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.PasswordManager",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_PASSWORD_MANAGER);
      break;

      // Profile submenu.
#if !BUILDFLAG(IS_CHROMEOS)
    case IDC_CUSTOMIZE_CHROME:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.CustomizeChrome",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_CUSTOMIZE_CHROME);
      break;
    case IDC_CLOSE_PROFILE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.CloseProfile",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_CLOSE_PROFILE);
      break;
    case IDC_MANAGE_GOOGLE_ACCOUNT:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ManageGoogleAccount", delta);
      }
      LogMenuAction(MENU_ACTION_MANAGE_GOOGLE_ACCOUNT);
      break;
    case IDC_SHOW_SYNC_SETTINGS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowSyncSettings", delta);
      }
      LogMenuAction(MENU_SHOW_SYNC_SETTINGS);
      break;
    case IDC_SHOW_SIGNIN:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowSignin",
                                      delta);
      }
      LogMenuAction(MENU_SHOW_SIGNIN);
      break;
    case IDC_TURN_ON_SYNC:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowTurnOnSync",
                                      delta);
      }
      LogMenuAction(MENU_TURN_ON_SYNC);
      break;
    case IDC_SHOW_SIGNIN_WHEN_PAUSED:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowSigninWhenPaused", delta);
      }
      LogMenuAction(MENU_SHOW_SIGNIN_WHEN_PAUSED);
      break;
    case IDC_OPEN_GUEST_PROFILE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.OpenGuestProfile", delta);
      }
      LogMenuAction(MENU_ACTION_OPEN_GUEST_PROFILE);
      break;
    case IDC_ADD_NEW_PROFILE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.AddNewProfile",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_ADD_NEW_PROFILE);
      break;
    case IDC_MANAGE_CHROME_PROFILES:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ManageChromeProfiles", delta);
      }
      LogMenuAction(MENU_ACTION_MANAGE_CHROME_PROFILES);
      break;
#endif

    // Reading list submenu.
    case IDC_READING_LIST_MENU_ADD_TAB:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ReadingListAddTab", delta);
      }
      LogMenuAction(MENU_ACTION_READING_LIST_ADD_TAB);
      break;
    case IDC_READING_LIST_MENU_SHOW_UI:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ReadingListShowUi", delta);
      }
      LogMenuAction(MENU_ACTION_READING_LIST_SHOW_UI);
      break;

    // Password autofill submenu.
    case IDC_SHOW_PASSWORD_MANAGER:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowPasswordManager", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_PASSWORD_MANAGER);
      break;
    case IDC_SHOW_PAYMENT_METHODS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowPaymentMethods", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_PAYMENT_METHODS);
      break;
    case IDC_SHOW_ADDRESSES:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowAddresses",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_ADDRESSES);
      break;
    case IDC_SHOW_CONTACT_INFO:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowContactInfo",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_CONTACT_INFO);
      break;
    case IDC_SHOW_IDENTITY_DOCS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowIdentityDocs", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_IDENTITY_DOCS);
      break;
    case IDC_SHOW_TRAVEL:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction.ShowTravel",
                                      delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_TRAVEL);
      break;
    case IDC_PERFORMANCE:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.ShowPerformanceSettings", delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_PERFORMANCE_SETTINGS);
      break;
    case IDC_SET_BROWSER_AS_DEFAULT:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.SetBrowserAsDefault", delta);
      }
      LogMenuAction(MENU_ACTION_SET_BROWSER_AS_DEFAULT);
      break;
    case IDC_SAFETY_HUB_SHOW_PASSWORD_CHECKUP:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.SafetyHubNotificationPasswordCheck",
            delta);
      }
      LogMenuAction(MENU_ACTION_SAFETY_HUB_SHOW_PASSWORD_CHECKUP);
      break;
    case IDC_OPEN_SAFETY_HUB:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.SafetyHubNotificationOpenSafetyHub",
            delta);
      }
      LogMenuAction(MENU_ACTION_SHOW_SAFETY_HUB);
      break;
    case IDC_SAFETY_HUB_MANAGE_EXTENSIONS:
      if (!uma_action_recorded_) {
        base::UmaHistogramMediumTimes(
            "WrenchMenu.TimeToAction.SafetyHubNotificationManageExtensions",
            delta);
      }
      LogMenuAction(MENU_ACTION_SAFETY_HUB_MANAGE_EXTENSIONS);
      break;
    case IDC_TOGGLE_VERTICAL_TABS:
      if (auto* controller =
              tabs::VerticalTabStripStateController::From(browser_)) {
        const bool is_vertical = !controller->ShouldDisplayVerticalTabs();
        tabs::RecordVerticalTabStripModeChanged(
            is_vertical, tabs::VerticalTabStripEntryPoint::kAppMenu);
      }
      break;
    default: {
      if (IsOtherProfileCommand(command_id)) {
        if (!uma_action_recorded_) {
          base::UmaHistogramMediumTimes(
              "WrenchMenu.TimeToAction.SwitchToAnotherProfile", delta);
        }
        LogMenuAction(MENU_ACTION_SWITCH_TO_ANOTHER_PROFILE);
      }
      break;
    }
  }

  if (!uma_action_recorded_) {
    base::UmaHistogramMediumTimes("WrenchMenu.TimeToAction", delta);
    uma_action_recorded_ = true;
  }
}

bool AppMenuModel::IsCommandIdChecked(int command_id) const {
  PrefService* prefs = browser_->GetProfile()->GetPrefs();
  if (command_id == IDC_SHOW_BOOKMARK_BAR) {
    return prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar);
  }
  if (command_id == IDC_BOOKMARK_BAR_SUBMENU_ALWAYS_SHOW) {
    return prefs->GetInteger(bookmarks::prefs::kBookmarkBarVisibilityState) ==
           static_cast<int>(bookmarks::BookmarkBarVisibilityState::kAlwaysShow);
  }
  if (command_id == IDC_BOOKMARK_BAR_SUBMENU_ALWAYS_HIDE) {
    return prefs->GetInteger(bookmarks::prefs::kBookmarkBarVisibilityState) ==
           static_cast<int>(bookmarks::BookmarkBarVisibilityState::kAlwaysHide);
  }
  if (command_id == IDC_BOOKMARK_BAR_SUBMENU_ONLY_ON_NTP) {
    return prefs->GetInteger(bookmarks::prefs::kBookmarkBarVisibilityState) ==
           static_cast<int>(
               bookmarks::BookmarkBarVisibilityState::kOnlyShowOnNtp);
  }
  if (command_id == IDC_PROFILING_ENABLED) {
    return content::Profiling::BeingProfiled();
  }
  if (command_id == IDC_TOGGLE_REQUEST_TABLET_SITE) {
    return chrome::IsRequestingTabletSite(browser_);
  }

  return false;
}

bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
  GlobalError* error =
      GlobalErrorServiceFactory::GetForProfile(browser_->GetProfile())
          ->GetGlobalErrorByMenuItemCommandID(command_id);
  if (error) {
    return true;
  }

  switch (command_id) {
    case IDC_NEW_INCOGNITO_WINDOW:
      return IncognitoModePrefs::IsIncognitoAllowed(browser_->GetProfile());
    default:
      return chrome::IsCommandEnabled(browser_, command_id);
  }
}

bool AppMenuModel::IsCommandIdAlerted(int command_id) const {
  if (command_id == IDC_VIEW_PASSWORDS ||
      command_id == IDC_SHOW_PASSWORD_MANAGER) {
    return alert_item_ == AlertMenuItem::kPasswordManager;
  }

  return false;
}

bool AppMenuModel::GetAcceleratorForCommandId(
    int command_id,
    ui::Accelerator* accelerator) const {
  if (command_id == IDC_NEW_ISOLATED_WINDOW) {
    return provider_->GetAcceleratorForCommandId(IDC_NEW_INCOGNITO_WINDOW,
                                                 accelerator);
  }

  // Reading mode uses different command IDs for different ways of opening
  // it, so adjust to use the command ID for the keyboard shortcut to grab
  // the proper accelerator.
  if (command_id == IDC_SHOW_READING_MODE_SIDE_PANEL) {
    return provider_->GetAcceleratorForCommandId(IDC_SHOW_READING_MODE_KEYBOARD,
                                                 accelerator);
  }

  if (command_id == IDC_NEW_INCOGNITO_WINDOW) {
    if (!IncognitoModePrefs::IsIncognitoAllowed(browser_->GetProfile())) {
      return false;
    }
  }

  return provider_->GetAcceleratorForCommandId(command_id, accelerator);
}

void AppMenuModel::LogMenuAction(AppMenuAction action_id) {
  LogWrenchMenuAction(action_id);
}

// Note: When adding new menu items please place under an appropriate section.
// Capitalization Policy (go/chrome-capitalization):
// In-browser 3-dot app menus use sentence case across all platforms, including
// macOS. Native macOS system menus (the main menu bar and right-click context
// menus) use Title Case separately.
// Menu is organised as follows:
// - Extension toolbar overflow.
// - Global browser errors and warnings.
// - Tabs and windows.
// - Places previously been e.g. History, bookmarks, recent tabs.
// - Page actions e.g. zoom, edit, find, print.
// - Learn about the browser and global customisation e.g. settings, help.
// - Browser relaunch, quit.
void AppMenuModel::Build() {
  // Build (and, by extension, Init) should only be called once.
  DCHECK_EQ(0u, GetItemCount());

  if (app_menu_icon_controller_ &&
      app_menu_icon_controller_->GetTypeAndSeverity().type ==
          AppMenuIconController::IconType::kUpgradeNotification) {
    AddSeparator(ui::SPACING_SEPARATOR);
    const auto update_icon = ui::ImageModel::FromVectorIcon(
        features::IsRoundedIconsEnabled()
            ? kRocketLaunchIcon
            : kBrowserToolsUpdateChromeRefreshOldIcon,
        ui::kColorMenuIconOnEmphasizedBackground, kDefaultIconSize);
    if (browser_defaults::kShowUpgradeMenuItem) {
      AddItemWithIcon(IDC_UPGRADE_DIALOG, GetUpgradeDialogTitleText(),
                      update_icon);
      AddSeparator(ui::SPACING_SEPARATOR);
    }
  }

  if (AddSafetyHubMenuItem() || AddGlobalErrorMenuItems() ||
      AddDefaultBrowserMenuItems()) {
    AddSeparator(ui::NORMAL_SEPARATOR);
  }
  // TODO(b/540249284): Temporarily Isolated mode is treated as Incognito. This
  // should be revisited when deciding on the final integration of Isolated
  // mode.
  AddItemWithStringIdAndVectorIcon(
      this, IDC_NEW_TAB,
      (browser_->GetProfile()->IsIncognitoProfile() ||
       browser_->GetProfile()->IsEnterpriseIsolatedModeProfile()) &&
              !browser_->GetProfile()->IsGuestSession()
          ? IDS_NEW_INCOGNITO_TAB
          : IDS_NEW_TAB,
      features::IsRoundedIconsEnabled() ? kTabIcon : kNewTabRefreshOldIcon);

  AddItemWithStringIdAndVectorIcon(
      this, IDC_NEW_WINDOW, IDS_NEW_WINDOW,
      features::IsRoundedIconsEnabled() ? kNewWindowIcon : kNewWindowOldIcon);

  // This menu item is not visible in Guest Mode. If incognito mode is not
  // available, it will be shown in disabled state. (crbug.com/40703208)
  if (!browser_->GetProfile()->IsGuestSession()) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW,
        features::IsRoundedIconsEnabled() ? kIncognitoIcon
                                          : kIncognitoRefreshMenuOldIcon);
    SetElementIdentifierAt(
        GetIndexOfCommandId(IDC_NEW_INCOGNITO_WINDOW).value(),
        kIncognitoMenuItem);

    bool isolated_mode_enabled =
        enterprise_isolated_mode::IsolatedModeReplacesIncognito(
            browser_->GetProfile());

    if (isolated_mode_enabled) {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_NEW_ISOLATED_WINDOW, IDS_NEW_ISOLATED_WINDOW,
          features::IsRoundedIconsEnabled()
              ? vector_icons::kDomainIcon
              : vector_icons::kBusinessChromeRefreshOldIcon);
    }
  }

  AddSeparator(ui::NORMAL_SEPARATOR);

#if !BUILDFLAG(IS_CHROMEOS)
  sub_menus_.push_back(std::make_unique<ProfileSubMenuModel>(
      this, browser()->GetProfile(),
      BrowserWindow::FromBrowser(browser())->GetColorProvider()));
  auto* const profile_submenu_model =
      static_cast<ProfileSubMenuModel*>(sub_menus_.back().get());
  AddSubMenu(kProfileMenuPlaceholder, profile_submenu_model->profile_name(),
             profile_submenu_model);
  SetIconForCommandId(kProfileMenuPlaceholder,
                      profile_submenu_model->avatar_image_model());
  SetElementIdentifierAt(GetIndexOfCommandId(kProfileMenuPlaceholder).value(),
                         kProfileMenuItem);
  SetAccessibleNameAt(GetIndexOfCommandId(kProfileMenuPlaceholder).value(),
                      profile_submenu_model->accessible_name());
  AddSeparator(ui::SPACING_SEPARATOR);
#endif

  if (!browser_->GetProfile()->IsGuestSession()) {
    sub_menus_.push_back(
        std::make_unique<PasswordsAndAutofillSubMenuModel>(this));
    AddSubMenuWithStringIdAndVectorIcon(
        this, kPasswordsAndAutofillMenuPlaceholder,
        IDS_PASSWORDS_AND_AUTOFILL_MENU, sub_menus_.back().get(),
        features::IsRoundedIconsEnabled()
            ? vector_icons::kPasswordManagerIcon
            : vector_icons::kPasswordManagerOldIcon);
    SetElementIdentifierAt(
        GetIndexOfCommandId(kPasswordsAndAutofillMenuPlaceholder).value(),
        kPasswordAndAutofillMenuItem);
  }

  if (!browser_->GetProfile()->IsOffTheRecord()) {
    auto recent_tabs_sub_menu =
        std::make_unique<RecentTabsSubMenuModel>(provider_, browser_);
    recent_tabs_sub_menu->RegisterLogMenuMetricsCallback(base::BindRepeating(
        &AppMenuModel::LogMenuMetrics, base::Unretained(this)));
    sub_menus_.push_back(std::move(recent_tabs_sub_menu));
    AddSubMenuWithStringIdAndVectorIcon(
        this, kRecentTabsMenuPlaceholder, IDS_HISTORY_MENU,
        sub_menus_.back().get(),
        features::IsRoundedIconsEnabled() ? kHistoryIcon : kHistoryOldIcon);
    SetElementIdentifierAt(
        GetIndexOfCommandId(kRecentTabsMenuPlaceholder).value(),
        kHistoryMenuItem);
  }
  AddItemWithStringIdAndVectorIcon(
      this, IDC_SHOW_DOWNLOADS, IDS_SHOW_DOWNLOADS,
      features::IsRoundedIconsEnabled() ? kDownloadIcon : kDownloadMenuOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_SHOW_DOWNLOADS).value(),
                         kDownloadsMenuItem);
  if (!browser_->GetProfile()->IsGuestSession()) {
    bookmark_sub_menu_model_ =
        std::make_unique<BookmarkSubMenuModel>(this, browser_);

    AddSubMenuWithStringIdAndVectorIcon(
        this, kBookmarksMenuPlaceholder, IDS_BOOKMARKS_AND_LISTS_MENU,
        bookmark_sub_menu_model_.get(),
        features::IsRoundedIconsEnabled() ? kStarIcon
                                          : kBookmarksListsMenuOldIcon);
    SetElementIdentifierAt(
        GetIndexOfCommandId(kBookmarksMenuPlaceholder).value(),
        kBookmarksMenuItem);
  }

  if (browser_->GetProfile()->IsRegularProfile()) {
    auto saved_tab_groups_model = std::make_unique<ui::SimpleMenuModel>(this);
    sub_menus_.push_back(std::move(saved_tab_groups_model));
    AddSubMenuWithStringIdAndVectorIcon(
        this, kSavedTabGroupsMenuPlaceholder, IDS_SAVED_TAB_GROUPS_MENU,
        sub_menus_.back().get(),
        features::IsRoundedIconsEnabled() ? kGridViewIcon
                                          : kSavedTabGroupBarEverythingOldIcon);
    SetElementIdentifierAt(
        GetIndexOfCommandId(kSavedTabGroupsMenuPlaceholder).value(),
        kTabGroupsMenuItem);
  }

  // Extensions sub menu.
  if (ArePromotionsEnabled() &&
      base::FeatureList::IsEnabled(features::kExtensionsCollapseMainMenu) &&
      !extensions::ui_util::HasManageableExtensions(browser_->GetProfile())) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_FIND_EXTENSIONS, IDS_FIND_EXTENSIONS,
        features::IsRoundedIconsEnabled()
            ? vector_icons::kChromeExtensionIcon
            : vector_icons::kExtensionChromeRefreshOldIcon);
    SetElementIdentifierAt(GetIndexOfCommandId(IDC_FIND_EXTENSIONS).value(),
                           ExtensionsMenuModel::kVisitChromeWebStoreMenuItem);
  } else {
    sub_menus_.push_back(std::make_unique<ExtensionsMenuModel>(this, browser_));
    AddSubMenuWithStringIdAndVectorIcon(
        this, kExtensionsSubmenuPlaceholder, IDS_EXTENSIONS_SUBMENU,
        sub_menus_.back().get(),
        features::IsRoundedIconsEnabled()
            ? vector_icons::kChromeExtensionIcon
            : vector_icons::kExtensionChromeRefreshOldIcon);
    SetElementIdentifierAt(
        GetIndexOfCommandId(kExtensionsSubmenuPlaceholder).value(),
        kExtensionsMenuItem);
  }

  AddItemWithStringIdAndVectorIcon(
      this, IDC_CLEAR_BROWSING_DATA, IDS_CLEAR_BROWSING_DATA,
      features::IsRoundedIconsEnabled() ? kDeleteIcon
                                        : kTrashCanRefreshOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(IDC_CLEAR_BROWSING_DATA).value(),
                         kClearBrowsingDataMenuItem);

  AddSeparator(ui::NORMAL_SEPARATOR);
  CreateZoomMenu();
  AddSeparator(ui::NORMAL_SEPARATOR);

  AddItemWithStringIdAndVectorIcon(
      this, IDC_PRINT, IDS_PRINT,
      features::IsRoundedIconsEnabled() ? kPrintIcon : kPrintMenuOldIcon);

  if (glic::GlicEnabling::IsEnabledForProfile(browser_->GetProfile())) {
    AddItemWithStringIdAndVectorIcon(this, IDC_OPEN_GLIC,
                                     IDS_GLIC_THREE_DOT_MENU_ITEM,
                                     glic::GlicVectorIconManager::GetVectorIcon(
                                         IDR_GLIC_BUTTON_VECTOR_ICON));
    SetIsNewFeatureAt(
        GetIndexOfCommandId(IDC_OPEN_GLIC).value(),
        BrowserUserEducationInterface::From(browser())->MaybeShowNewBadgeFor(
            features::kGlicAppMenuNewBadge));
  }

  if (auto* controller = lens::LensOverlayEntryPointController::From(browser());
      controller && controller->IsEnabled()) {
    const gfx::VectorIcon& icon =
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
        vector_icons::kGoogleLensMonochromeLogoIcon;
#else
        features::IsRoundedIconsEnabled()
            ? vector_icons::kSearchIcon
            : vector_icons::kSearchChromeRefreshOldIcon;
#endif
    AddItemWithStringIdAndVectorIcon(
        this, IDC_CONTENT_CONTEXT_LENS_OVERLAY,
        lens::GetLensOverlayEntrypointLabelAltIds(), icon);
    const int lens_command_index =
        GetIndexOfCommandId(IDC_CONTENT_CONTEXT_LENS_OVERLAY).value();
    SetElementIdentifierAt(lens_command_index, kShowLensOverlay);
    SetIsNewFeatureAt(
        lens_command_index,
        BrowserUserEducationInterface::From(browser())->MaybeShowNewBadgeFor(
            lens::features::kLensOverlay));
  }

  AddItemWithStringIdAndVectorIcon(this, IDC_SHOW_TRANSLATE, IDS_SHOW_TRANSLATE,
                                   vector_icons::kGTranslateIcon);

  CreateFindAndEditSubMenu();

  sub_menus_.push_back(
      std::make_unique<SaveAndShareSubMenuModel>(this, browser_));
  int string_id = media_router::MediaRouterEnabled(browser()->GetProfile())
                      ? IDS_CAST_SAVE_AND_SHARE_MENU
                      : IDS_SAVE_AND_SHARE_MENU;
  AddSubMenuWithStringIdAndVectorIcon(
      this, kSaveAndShareMenuPlaceholder, string_id, sub_menus_.back().get(),
      features::IsRoundedIconsEnabled() ? kFileSaveIcon
                                        : kFileSaveChromeRefreshOldIcon);
  SetElementIdentifierAt(
      GetIndexOfCommandId(kSaveAndShareMenuPlaceholder).value(),
      kSaveAndShareMenuItem);

#if BUILDFLAG(IS_CHROMEOS)
  // Always show this option if we're in tablet mode on Chrome OS.
  if (display::Screen::Get()->InTabletMode()) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_TOGGLE_REQUEST_TABLET_SITE, IDS_TOGGLE_REQUEST_TABLET_SITE,
        chrome::IsRequestingTabletSite(browser_)
            ? features::IsRoundedIconsEnabled()
                  ? kMobileCheckIcon
                  : kRequestMobileSiteCheckedOldIcon
        : features::IsRoundedIconsEnabled()
            ? kMobileIcon
            : kRequestMobileSiteUncheckedOldIcon);
  }
#endif

  sub_menus_.push_back(std::make_unique<ToolsMenuModel>(this, browser_));
  AddSubMenuWithStringIdAndVectorIcon(
      this, kMoreToolsMenuPlaceholder, IDS_MORE_TOOLS_MENU,
      sub_menus_.back().get(),
      features::IsRoundedIconsEnabled() ? kHomeRepairServiceIcon
                                        : kMoreToolsMenuOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(kMoreToolsMenuPlaceholder).value(),
                         kMoreToolsMenuItem);

  AddSeparator(ui::NORMAL_SEPARATOR);
// The help submenu is only displayed on official Chrome builds. As the
// 'About' item has been moved to this submenu, it's reinstated here for
// Chromium builds.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  sub_menus_.push_back(std::make_unique<HelpMenuModel>(this, browser_));
  AddSubMenuWithStringIdAndVectorIcon(
      this, kHelpMenuPlaceholder, IDS_HELP_MENU, sub_menus_.back().get(),
      features::IsRoundedIconsEnabled() ? kHelpCustomIcon : kHelpMenuOldIcon);
  SetElementIdentifierAt(GetIndexOfCommandId(kHelpMenuPlaceholder).value(),
                         kHelpMenuItem);
#else
#if BUILDFLAG(IS_CHROMEOS)
  AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT));
#else
  AddItemWithStringIdAndVectorIcon(this, IDC_ABOUT, IDS_ABOUT,
                                   features::IsRoundedIconsEnabled()
                                       ? vector_icons::kInfoIcon
                                       : vector_icons::kInfoRefreshOldIcon);
#endif
#endif

  AddItemWithStringIdAndVectorIcon(
      this, IDC_OPTIONS, IDS_SETTINGS,
      features::IsRoundedIconsEnabled() ? kSettingsIcon : kSettingsMenuOldIcon);

  if (browser_defaults::kShowExitMenuItem) {
    AddItemWithStringIdAndVectorIcon(
        this, IDC_EXIT, IDS_EXIT,
        features::IsRoundedIconsEnabled() ? kExitToAppIcon : kExitMenuOldIcon);
  }

  // On Chrome OS, similar UI is displayed in the system tray menu, instead of
  // this menu.
#if !BUILDFLAG(IS_CHROMEOS)
  if (ShouldDisplayManagedUi(browser_->GetProfile())) {
    AddSeparator(ui::NORMAL_SEPARATOR);
    AddItemWithIcon(
        IDC_SHOW_MANAGEMENT_PAGE,
        GetManagedUiMenuItemLabel(browser_->GetProfile()),
        ui::ImageModel::FromVectorIcon(GetManagedUiIcon(browser_->GetProfile()),
                                       ui::kColorMenuIcon, kDefaultIconSize));

    SetAccessibleNameAt(GetIndexOfCommandId(IDC_SHOW_MANAGEMENT_PAGE).value(),
                        GetManagedUiMenuItemTooltip(browser_->GetProfile()));
#if BUILDFLAG(IS_LINUX)
    if (enterprise_util::IsBrowserManaged(browser_->GetProfile()) &&
        base::FeatureList::IsEnabled(features::kEnterpriseReleaseNotes)) {
      AddItemWithStringIdAndVectorIcon(
          this, IDC_CHROME_ENTERPRISE_RELEASE_NOTES,
          IDS_CHROME_ENTERPRISE_RELEASE_NOTES, omnibox::kChromeProductIcon);
    }
#endif  // BUILDFLAG(IS_LINUX)
  }
#endif  // !BUILDFLAG(IS_CHROMEOS)

  uma_action_recorded_ = false;
}

void AppMenuModel::CreateCutCopyPasteMenu() {
  edit_menu_item_model_ =
      std::make_unique<ui::ButtonMenuItemModel>(IDS_EDIT, this);
  edit_menu_item_model_->AddGroupItemWithStringId(IDC_CUT, IDS_CUT);
  edit_menu_item_model_->AddGroupItemWithStringId(IDC_COPY, IDS_COPY);
  edit_menu_item_model_->AddGroupItemWithStringId(IDC_PASTE, IDS_PASTE);
  AddButtonItem(kEditMenuPlaceholder, edit_menu_item_model_.get());
}

void AppMenuModel::CreateFindAndEditSubMenu() {
  sub_menus_.push_back(std::make_unique<FindAndEditSubMenuModel>(this));
  AddSubMenuWithStringIdAndVectorIcon(
      this, kFindAndEditMenuPlaceholder, IDS_FIND_AND_EDIT_MENU,
      sub_menus_.back().get(),
      features::IsRoundedIconsEnabled() ? kFindInPageIcon : kSearchMenuOldIcon);
}

void AppMenuModel::CreateZoomMenu() {
  zoom_menu_item_model_ =
      std::make_unique<ui::ButtonMenuItemModel>(IDS_ZOOM_MENU, this);
  zoom_menu_item_model_->AddGroupItemWithStringId(IDC_ZOOM_MINUS,
                                                  IDS_ZOOM_MINUS2);
  zoom_menu_item_model_->AddGroupItemWithStringId(IDC_ZOOM_PLUS,
                                                  IDS_ZOOM_PLUS2);
  zoom_menu_item_model_->AddImageItem(IDC_FULLSCREEN);
  AddButtonItem(kZoomMenuPlaceholder, zoom_menu_item_model_.get());
  SetCommandIcon(
      this, kZoomMenuPlaceholder,
      features::IsRoundedIconsEnabled() ? kZoomInIcon : kZoomInOldIcon);
}

bool AppMenuModel::AddGlobalErrorMenuItems() {
  // TODO(sail): Currently we only build the app menu once per browser
  // window. This means that if a new error is added after the menu is built
  // it won't show in the existing app menu. To fix this we need to some
  // how update the menu if new errors are added.
  const GlobalErrorService::GlobalErrorList& errors =
      GlobalErrorServiceFactory::GetForProfile(browser_->GetProfile())
          ->errors();
  bool menu_items_added = false;
  for (GlobalError* error : errors) {
    DCHECK(error);
    if (error->HasMenuItem()) {
      AddItem(error->MenuItemCommandID(), error->MenuItemLabel());
      SetIconForCommandId(error->MenuItemCommandID(), error->MenuItemIcon());
      menu_items_added = true;
    }
  }
  return menu_items_added;
}
// TODO(b/540249284): Temporarily Isolated mode is treated as Incognito. This
// should be revisited when deciding on the final integration of Isolated
// mode.
bool AppMenuModel::AddDefaultBrowserMenuItems() {
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
  if (browser_->GetProfile()->IsIncognitoProfile() ||
      browser_->GetProfile()->IsGuestSession() ||
      browser_->GetProfile()->IsEnterpriseIsolatedModeProfile()) {
    return false;
  }

  if (DefaultBrowserPromptManager::GetInstance()->show_app_menu_item()) {
    AddItemWithIcon(
        IDC_SET_BROWSER_AS_DEFAULT,
        l10n_util::GetStringUTF16(IDS_SET_BROWSER_AS_DEFAULT_MENU_ITEM),
        ui::ImageModel::FromVectorIcon(
            features::IsRoundedIconsEnabled()
                ? omnibox::kChromeProductIcon
                : omnibox::kProductChromeRefreshOldIcon,
            ui::kColorMenuIcon, kDefaultIconSize));
    SetElementIdentifierAt(GetItemCount() - 1,
                           AppMenuModel::kSetBrowserAsDefaultMenuItem);
    return true;
  }
#endif
  return false;
}

bool AppMenuModel::AddSafetyHubMenuItem() {
  auto* safety_hub_menu_notification_service =
      SafetyHubMenuNotificationServiceFactory::GetForProfile(
          browser_->GetProfile());
  if (!safety_hub_menu_notification_service) {
    return false;
  }

  std::optional<MenuNotificationEntry> notification =
      safety_hub_menu_notification_service->GetNotificationToShow();
  if (!notification.has_value()) {
    return false;
  }
  base::UmaHistogramEnumeration("Settings.SafetyHub.Impression",
                                safety_hub::SafetyHubSurfaces::kThreeDotMenu);
  base::UmaHistogramEnumeration(
      "Settings.SafetyHub.EntryPointImpression",
      safety_hub::SafetyHubEntryPoint::kMenuNotifications);
  base::UmaHistogramEnumeration("Settings.SafetyHub.MenuNotificationImpression",
                                notification->module);
  const auto safety_hub_icon = ui::ImageModel::FromVectorIcon(
      features::IsRoundedIconsEnabled() ? kSecurityIcon : kSecurityOldIcon,
      ui::kColorMenuIcon, kDefaultIconSize);
  AddItemWithIcon(notification->command, notification->label, safety_hub_icon);
  SetExecuteCallbackAt(
      GetIndexOfCommandId(notification->command).value(),
      base::BindRepeating(&AppMenuModel::LogSafetyHubInteractionMetrics,
                          base::Unretained(this), notification->module));
  return true;
}

#if BUILDFLAG(IS_CHROMEOS)
void AppMenuModel::UpdateSettingsItemState() {
  bool is_disabled =
      policy::SystemFeaturesDisableListPolicyHandler::IsSystemFeatureDisabled(
          policy::SystemFeature::kBrowserSettings,
          g_browser_process->local_state());

  std::optional<size_t> index = GetIndexOfCommandId(IDC_OPTIONS);
  if (index.has_value()) {
    SetEnabledAt(index.value(), !is_disabled);
  }

#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  index = GetIndexOfCommandId(kHelpMenuPlaceholder);
  if (index.has_value()) {
    ui::SimpleMenuModel* help_menu =
        static_cast<ui::SimpleMenuModel*>(GetSubmenuModelAt(index.value()));
    index = help_menu->GetIndexOfCommandId(IDC_ABOUT);
    if (index.has_value()) {
      help_menu->SetEnabledAt(index.value(), !is_disabled);
    }
  }
#else   // BUILDFLAG(GOOGLE_CHROME_BRANDING)
  index = GetIndexOfCommandId(IDC_ABOUT);
  if (index.has_value()) {
    SetEnabledAt(index.value(), !is_disabled);
  }
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}
#endif  // BUILDFLAG(IS_CHROMEOS)
