chromium/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_utils.cc

// Copyright 2022 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/ash/system_web_apps/apps/personalization_app/personalization_app_utils.h"

#include <memory>
#include <string_view>

#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/webui/personalization_app/personalization_app_ui.h"
#include "base/base64.h"
#include "base/logging.h"
#include "base/strings/strcat.h"
#include "chrome/browser/ash/login/demo_mode/demo_session.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_ambient_provider_impl.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_keyboard_backlight_provider_impl.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_sea_pen_provider_impl.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_theme_provider_impl.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.h"
#include "chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_wallpaper_provider_impl.h"
#include "chrome/browser/ash/wallpaper_handlers/wallpaper_fetcher_delegate.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/manta/manta_service_factory.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
#include "components/account_id/account_id.h"
#include "components/language/core/common/locale_util.h"
#include "components/manta/manta_service.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_type.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "url/gurl.h"

namespace ash::personalization_app {

namespace {
bool CanAccessMantaFeaturesWithoutMinorRestrictions(Profile* profile) {
  // Only users who can access manta features without minor restrictions will
  // have SeaPen enabled.
  auto* manta_service = manta::MantaServiceFactory::GetForProfile(profile);
  const bool canAccessMantaFeaturesWithoutMinorRestrictions =
      manta_service &&
      manta_service->CanAccessMantaFeaturesWithoutMinorRestrictions() ==
          manta::FeatureSupportStatus::kSupported;
  return canAccessMantaFeaturesWithoutMinorRestrictions;
}
}  // namespace

std::unique_ptr<content::WebUIController> CreatePersonalizationAppUI(
    content::WebUI* web_ui,
    const GURL& url) {
  auto ambient_provider = std::make_unique<
      ash::personalization_app::PersonalizationAppAmbientProviderImpl>(web_ui);
  auto keyboard_backlight_provider =
      std::make_unique<ash::personalization_app::
                           PersonalizationAppKeyboardBacklightProviderImpl>(
          web_ui);
  auto theme_provider = std::make_unique<
      ash::personalization_app::PersonalizationAppThemeProviderImpl>(web_ui);
  auto user_provider = std::make_unique<
      ash::personalization_app::PersonalizationAppUserProviderImpl>(web_ui);
  auto wallpaper_provider = std::make_unique<
      ash::personalization_app::PersonalizationAppWallpaperProviderImpl>(
      web_ui,
      std::make_unique<wallpaper_handlers::WallpaperFetcherDelegateImpl>());
  auto sea_pen_provider = std::make_unique<
      ash::personalization_app::PersonalizationAppSeaPenProviderImpl>(
      web_ui,
      std::make_unique<wallpaper_handlers::WallpaperFetcherDelegateImpl>());
  return std::make_unique<ash::personalization_app::PersonalizationAppUI>(
      web_ui, std::move(ambient_provider),
      std::move(keyboard_backlight_provider), std::move(sea_pen_provider),
      std::move(theme_provider), std::move(user_provider),
      std::move(wallpaper_provider));
}

const user_manager::User* GetUser(const Profile* profile) {
  auto* profile_helper = ProfileHelper::Get();
  DCHECK(profile_helper);
  const user_manager::User* user = profile_helper->GetUserByProfile(profile);
  return user;
}

AccountId GetAccountId(const Profile* profile) {
  const auto* user = GetUser(profile);
  if (!user) {
    return EmptyAccountId();
  }
  return user->GetAccountId();
}

bool CanSeeWallpaperOrPersonalizationApp(const Profile* profile) {
  const auto* user = GetUser(profile);
  if (!user) {
    return false;
  }
  switch (user->GetType()) {
    case user_manager::UserType::kKioskApp:
    case user_manager::UserType::kWebKioskApp:
      return false;
    case user_manager::UserType::kRegular:
    case user_manager::UserType::kChild:
    case user_manager::UserType::kGuest:
    // Public account users must be able to see personalization app since retail
    // demo mode is implemented as a public account.
    case user_manager::UserType::kPublicAccount:
      return true;
  }
}

bool IsManagedUserEligibleForSeaPen(Profile* profile) {
  DCHECK(profile->GetProfilePolicyConnector()->IsManaged());
  if (!features::IsSeaPenEnterpriseEnabled()) {
    // Without the experiment, managed users are not allowed for SeaPen.
    DVLOG(1) << __func__ << " managed profile";
    return false;
  }
  return CanAccessMantaFeaturesWithoutMinorRestrictions(profile);
}

bool IsSystemInEnglishLanguage() {
  return g_browser_process != nullptr &&
         language::ExtractBaseLanguage(
             g_browser_process->GetApplicationLocale()) == "en";
}

bool IsEligibleForSeaPen(Profile* profile) {
  if (!profile) {
    LOG(ERROR) << __func__ << " no profile";
    return false;
  }

  // Show for Googlers.
  if (gaia::IsGoogleInternalAccountEmail(profile->GetProfileUserName())) {
    DVLOG(1) << __func__ << " Google internal account";
    return true;
  }

  if (features::IsSeaPenDemoModeEnabled() &&
      DemoSession::IsDeviceInDemoMode()) {
    DVLOG(1) << __func__ << " demo mode";
    const auto* user = GetUser(profile);
    return DemoSession::Get() && user &&
           user->GetType() == user_manager::UserType::kPublicAccount;
  }

  if (profile->GetProfilePolicyConnector()->IsManaged() &&
      !IsManagedUserEligibleForSeaPen(profile)) {
    return false;
  }

  const auto* user = GetUser(profile);
  if (!user) {
    LOG(ERROR) << __func__ << " no user";
    return false;
  }
  DVLOG(1) << __func__ << " user_type=" << user->GetType();
  switch (user->GetType()) {
    case user_manager::UserType::kKioskApp:
    case user_manager::UserType::kWebKioskApp:
    case user_manager::UserType::kChild:
    // Demo mode retail devices are type kPublicAccount and may have been
    // handled earlier in this function. But not all kPublicAccount users are in
    // demo mode. Public ChromeOS devices at libraries etc often use
    // kPublicAccount type.
    case user_manager::UserType::kPublicAccount:
    case user_manager::UserType::kGuest:
      return false;
    case user_manager::UserType::kRegular:
      return true;
  }
}

bool IsManagedSeaPenSettingsEnabled(const int settings) {
  switch (static_cast<ManagedSeaPenSettings>(settings)) {
    case ManagedSeaPenSettings::kAllowed:
    case ManagedSeaPenSettings::kAllowedWithoutLogging:
      return true;
    case ManagedSeaPenSettings::kDisabled:
    default:
      return false;
  }
}

bool IsManagedSeaPenWallpaperEnabled(Profile* profile) {
  return IsManagedSeaPenSettingsEnabled(
      profile->GetPrefs()->GetInteger(ash::prefs::kGenAIWallpaperSettings));
}

bool IsManagedSeaPenWallpaperFeedbackEnabled(Profile* profile) {
  return profile->GetPrefs()->GetInteger(ash::prefs::kGenAIWallpaperSettings) ==
         static_cast<int>(ManagedSeaPenSettings::kAllowed);
}

bool IsManagedSeaPenVcBackgroundEnabled(Profile* profile) {
  return IsManagedSeaPenSettingsEnabled(
      profile->GetPrefs()->GetInteger(ash::prefs::kGenAIVcBackgroundSettings));
}

bool IsManagedSeaPenVcBackgroundFeedbackEnabled(Profile* profile) {
  return profile->GetPrefs()->GetInteger(
             ash::prefs::kGenAIVcBackgroundSettings) ==
         static_cast<int>(ManagedSeaPenSettings::kAllowed);
}

bool IsEligibleForSeaPenTextInput(Profile* profile) {
  if (!profile) {
    LOG(ERROR) << __func__ << " no profile";
    return false;
  }
  if (!features::IsSeaPenTextInputEnabled()) {
    // Without the experiment, users are not allowed to use SeaPenTextInput.
    DVLOG(1) << __func__ << " SeaPenTextInput disabled";
    return false;
  }
  if (!IsSystemInEnglishLanguage()) {
    // The feature only supports English users.
    DVLOG(1) << __func__ << " system not in English language";
    return false;
  }
  return IsEligibleForSeaPen(profile) &&
         CanAccessMantaFeaturesWithoutMinorRestrictions(profile);
}

GURL GetJpegDataUrl(const std::string_view encoded_jpg_data) {
  return GURL(base::StrCat(
      {"data:image/jpeg;base64,", base::Base64Encode(encoded_jpg_data)}));
}

}  // namespace ash::personalization_app