chromium/ash/webui/status_area_internals/status_area_internals_handler.cc

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

#include "ash/webui/status_area_internals/status_area_internals_handler.h"

#include <memory>
#include <utility>

#include "ash/annotator/annotator_controller.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/ime/ime_controller_impl.h"
#include "ash/public/cpp/stylus_utils.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/model/fake_power_status.h"
#include "ash/system/model/fake_system_tray_model.h"
#include "ash/system/model/scoped_fake_power_status.h"
#include "ash/system/model/scoped_fake_system_tray_model.h"
#include "ash/system/palette/palette_tray.h"
#include "ash/system/privacy/privacy_indicators_controller.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/system/video_conference/video_conference_tray_controller.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/components/magic_boost/public/cpp/magic_boost_state.h"
#include "components/prefs/pref_service.h"

namespace ash {

StatusAreaInternalsHandler::StatusAreaInternalsHandler(
    mojo::PendingReceiver<mojom::status_area_internals::PageHandler> receiver)
    : receiver_(this, std::move(receiver)) {
  // When the web UI is in used, we will use a fake system tray model and a fake
  // power status  to mock the data shown in the system tray, then  switch back
  // to use the real model when the web UI is destructed using the scoped
  // setter.
  scoped_fake_model_ = std::make_unique<ScopedFakeSystemTrayModel>();
  scoped_fake_power_status_ = std::make_unique<ScopedFakePowerStatus>();
}

StatusAreaInternalsHandler::~StatusAreaInternalsHandler() = default;

void StatusAreaInternalsHandler::ToggleImeTray(bool visible) {
  Shell::Get()->ime_controller()->ShowImeMenuOnShelf(/*show=*/visible);
}

void StatusAreaInternalsHandler::TogglePaletteTray(bool visible) {
  if (visible) {
    stylus_utils::SetHasStylusInputForTesting();
  } else {
    stylus_utils::SetNoStylusInputForTesting();
  }

  for (auto* root_window_controller :
       Shell::Get()->GetAllRootWindowControllers()) {
    DCHECK(root_window_controller);
    DCHECK(root_window_controller->GetStatusAreaWidget());

    root_window_controller->GetStatusAreaWidget()
        ->palette_tray()
        ->SetDisplayHasStylusForTesting();
  }
}

void StatusAreaInternalsHandler::ToggleLogoutTray(bool visible) {
  Shell::Get()
      ->session_controller()
      ->GetLastActiveUserPrefService()
      ->SetBoolean(prefs::kShowLogoutButtonInTray, visible);
}

void StatusAreaInternalsHandler::ToggleVirtualKeyboardTray(bool visible) {
  Shell::Get()
      ->session_controller()
      ->GetLastActiveUserPrefService()
      ->SetBoolean(prefs::kAccessibilityVirtualKeyboardEnabled, visible);
}

void StatusAreaInternalsHandler::ToggleDictationTray(bool visible) {
  Shell::Get()
      ->session_controller()
      ->GetLastActiveUserPrefService()
      ->SetBoolean(prefs::kAccessibilityDictationEnabled, visible);
}

void StatusAreaInternalsHandler::ToggleVideoConferenceTray(bool visible) {
  VideoConferenceMediaState state;

  if (!visible) {
    VideoConferenceTrayController::Get()->UpdateWithMediaState(state);
    return;
  }

  state.has_media_app = true;
  state.has_camera_permission = true;
  state.has_microphone_permission = true;
  VideoConferenceTrayController::Get()->UpdateWithMediaState(state);
}

void StatusAreaInternalsHandler::ToggleAnnotationTray(bool visible) {
  auto* root_window_controller = Shell::Get()->GetPrimaryRootWindowController();
  DCHECK(root_window_controller);
  DCHECK(root_window_controller->GetStatusAreaWidget());

  auto* annotator_controller = Shell::Get()->annotator_controller();

  if (visible) {
    annotator_controller->RegisterView(
        /*current_root=*/root_window_controller->GetRootWindow());
  } else {
    annotator_controller->DisableAnnotator();
  }
}

void StatusAreaInternalsHandler::TriggerPrivacyIndicators(
    const std::string& app_id,
    const std::string& app_name,
    bool is_camera_used,
    bool is_microphone_used) {
  PrivacyIndicatorsController::Get()->UpdatePrivacyIndicators(
      app_id, base::UTF8ToUTF16(app_name), is_camera_used, is_microphone_used,
      base::MakeRefCounted<PrivacyIndicatorsNotificationDelegate>(),
      PrivacyIndicatorsSource::kApps);
}

void StatusAreaInternalsHandler::SetIsInUserChildSession(
    bool in_child_session) {
  scoped_fake_model_->fake_model()->set_is_in_user_child_session(
      in_child_session);
}

void StatusAreaInternalsHandler::ResetHmrConsentStatus() {
  chromeos::MagicBoostState::Get()->AsyncWriteConsentStatus(
      chromeos::HMRConsentStatus::kUnset);
}

void StatusAreaInternalsHandler::SetBatteryIcon(
    const PageHandler::BatteryIcon icon) {
  FakePowerStatus* fake_power_status =
      scoped_fake_power_status_->fake_power_status();
  fake_power_status->SetDefaultState();
  switch (icon) {
    case PageHandler::BatteryIcon::kXIcon:
      fake_power_status->SetIsBatteryPresent(false);
      break;
    case PageHandler::BatteryIcon::kUnreliableIcon:
      fake_power_status->SetIsUsbChargerConnected(true);
      break;
    case PageHandler::BatteryIcon::kBoltIcon:
      fake_power_status->SetIsLinePowerConnected(true);
      break;
    case PageHandler::BatteryIcon::kBatterySaverPlusIcon:
      fake_power_status->SetIsBatterySaverActive(true);
      break;
    default:
      break;
  }
}

void StatusAreaInternalsHandler::SetBatteryPercent(double percent) {
  scoped_fake_power_status_->fake_power_status()->SetBatteryPercent(percent);
}

}  // namespace ash