chromium/chrome/browser/ash/policy/display/display_settings_handler.cc

// Copyright 2018 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/policy/display/display_settings_handler.h"

#include <utility>

#include "ash/public/ash_interfaces.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"

namespace policy {

DisplaySettingsHandler::DisplaySettingsHandler() {
  ash::BindCrosDisplayConfigController(
      cros_display_config_.BindNewPipeAndPassReceiver());
}

DisplaySettingsHandler::~DisplaySettingsHandler() = default;

void DisplaySettingsHandler::OnDisplayConfigChanged() {
  RequestDisplaysAndApplyChanges();
}

void DisplaySettingsHandler::RegisterHandler(
    std::unique_ptr<DisplaySettingsPolicyHandler> handler) {
  if (!started_)
    handlers_.push_back(std::move(handler));
}

void DisplaySettingsHandler::Start() {
  if (started_)
    return;
  started_ = true;

  // Register observers for all settings
  for (const auto& handler : handlers_) {
    settings_subscriptions_.push_back(
        ash::CrosSettings::Get()->AddSettingsObserver(
            handler->SettingName(),
            base::BindRepeating(&DisplaySettingsHandler::OnSettingUpdate,
                                base::Unretained(this),
                                base::Unretained(handler.get()))));
  }

  // Make the initial display unit info request. This will be queued until the
  // Ash service is ready.
  cros_display_config_->GetDisplayUnitInfoList(
      false /* single_unified */,
      base::BindOnce(&DisplaySettingsHandler::OnGetInitialDisplayInfo,
                     weak_ptr_factory_.GetWeakPtr()));
}

void DisplaySettingsHandler::OnGetInitialDisplayInfo(
    std::vector<crosapi::mojom::DisplayUnitInfoPtr> info_list) {
  // Add this as an observer to the mojo service now that it is ready.
  // (We only care about changes that occur after we apply any changes below).
  mojo::PendingAssociatedRemote<crosapi::mojom::CrosDisplayConfigObserver>
      observer;
  cros_display_config_observer_receiver_.Bind(
      observer.InitWithNewEndpointAndPassReceiver());
  cros_display_config_->AddObserver(std::move(observer));

  ApplyChanges(std::move(info_list));
}

void DisplaySettingsHandler::RequestDisplaysAndApplyChanges() {
  cros_display_config_->GetDisplayUnitInfoList(
      false /* single_unified */,
      base::BindOnce(&DisplaySettingsHandler::ApplyChanges,
                     weak_ptr_factory_.GetWeakPtr()));
}

void DisplaySettingsHandler::ApplyChanges(
    std::vector<crosapi::mojom::DisplayUnitInfoPtr> info_list) {
  for (std::unique_ptr<DisplaySettingsPolicyHandler>& handler : handlers_)
    UpdateSettingAndApplyChanges(handler.get(), info_list);
}

void DisplaySettingsHandler::OnSettingUpdate(
    DisplaySettingsPolicyHandler* handler) {
  cros_display_config_->GetDisplayUnitInfoList(
      false /* single_unified */,
      base::BindOnce(&DisplaySettingsHandler::OnConfigurationChangeForHandler,
                     weak_ptr_factory_.GetWeakPtr(), handler));
}

void DisplaySettingsHandler::UpdateSettingAndApplyChanges(
    DisplaySettingsPolicyHandler* handler,
    const std::vector<crosapi::mojom::DisplayUnitInfoPtr>& info_list) {
  handler->OnSettingUpdate();
  handler->ApplyChanges(cros_display_config_.get(), info_list);
}

void DisplaySettingsHandler::OnConfigurationChangeForHandler(
    DisplaySettingsPolicyHandler* handler,
    std::vector<crosapi::mojom::DisplayUnitInfoPtr> info_list) {
  UpdateSettingAndApplyChanges(handler, info_list);
}

}  // namespace policy