chromium/ash/webui/shortcut_customization_ui/shortcuts_app_manager.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/shortcut_customization_ui/shortcuts_app_manager.h"

#include <memory>

#include "ash/constants/ash_features.h"
#include "ash/public/mojom/accelerator_info.mojom-forward.h"
#include "ash/public/mojom/accelerator_info.mojom.h"
#include "ash/webui/common/backend/shortcut_input_provider.h"
#include "ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.h"
#include "ash/webui/shortcut_customization_ui/backend/search/search_concept.h"
#include "ash/webui/shortcut_customization_ui/backend/search/search_concept_registry.h"
#include "ash/webui/shortcut_customization_ui/backend/search/search_handler.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "content/public/browser/web_ui_data_source.h"

namespace ash::shortcut_ui {

ShortcutsAppManager::ShortcutsAppManager(
    local_search_service::LocalSearchServiceProxy* local_search_service_proxy,
    PrefService* pref_service) {
  search_concept_registry_ =
      std::make_unique<SearchConceptRegistry>(*local_search_service_proxy);
  // Initialization of the search maps will occur on first call from
  // `OnAcceleratorsUpdated`.
  search_handler_ = std::make_unique<SearchHandler>(
      search_concept_registry_.get(), local_search_service_proxy);
  accelerator_configuration_provider_ =
      std::make_unique<AcceleratorConfigurationProvider>(pref_service);
  shortcut_input_provider_ = std::make_unique<ShortcutInputProvider>();

  accelerator_configuration_provider_->AddObserver(this);
}

ShortcutsAppManager::~ShortcutsAppManager() = default;

// This KeyedService::Shutdown method is part of a two-phase shutdown process.
// In the first phase, this Shutdown method is called, and is where we drop
// references. Once all KeyedServices are finished with the first phase, the
// services are deleted in the second phase.
void ShortcutsAppManager::Shutdown() {
  accelerator_configuration_provider_->RemoveObserver(this);
  // Note: These must be deleted in the opposite order of their creation to
  // prevent against UAF violations.
  accelerator_configuration_provider_.reset();
  search_handler_.reset();
  search_concept_registry_.reset();
}

void ShortcutsAppManager::OnAcceleratorsUpdated(
    shortcut_ui::AcceleratorConfigurationProvider::AcceleratorConfigurationMap
        config) {
  SetSearchConcepts(
      std::move(config),
      accelerator_configuration_provider_->GetAcceleratorLayoutInfos());
}

void ShortcutsAppManager::SetSearchConcepts(
    shortcut_ui::AcceleratorConfigurationProvider::AcceleratorConfigurationMap
        config,
    std::vector<mojom::AcceleratorLayoutInfoPtr> layout_infos) {
  std::vector<SearchConcept> search_concepts;

  for (auto& layout_info : layout_infos) {
    if (const auto& config_iterator = config.find(layout_info->source);
        config_iterator != config.end()) {
      if (const auto& map_iterator =
              config_iterator->second.find(layout_info->action);
          map_iterator != config_iterator->second.end()) {
        search_concepts.emplace_back(std::move(layout_info),
                                     std::move(map_iterator->second));
      }
    }
  }

  search_concept_registry_->SetSearchConcepts(std::move(search_concepts));
}

}  // namespace ash::shortcut_ui