chromium/ash/webui/common/chrome_os_webui_config.h

// 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.

#ifndef ASH_WEBUI_COMMON_CHROME_OS_WEBUI_CONFIG_H_
#define ASH_WEBUI_COMMON_CHROME_OS_WEBUI_CONFIG_H_

#include <memory>
#include <string>
#include <string_view>

#include "base/functional/callback.h"
#include "content/public/browser/webui_config.h"
#include "content/public/common/url_constants.h"
#include "url/gurl.h"

namespace ash {

// Default WebUIConfig for ChromeOS WebUI. It has an implementation of
// `CreateWebUIController()`, which returns a new `T`. Optionally, it can take a
// CreateWebUIControllerFunc that callers can use to inject dependencies into T.
template <typename T>
class ChromeOSWebUIConfig : public content::WebUIConfig {
 public:
  using CreateWebUIControllerFunc = base::RepeatingCallback<std::unique_ptr<
      content::WebUIController>(content::WebUI*, const GURL& url)>;

  static std::unique_ptr<content::WebUIController>
  DefaultCreateWebUIControllerFunc(content::WebUI* web_ui, const GURL& url) {
    // We need to determine the correct WebUIController
    // constructor to use at compile time, depending on whether it
    // requires only WebUI* or both WebUI* and GURL. We currently
    // don't support WebUIControllers that have two constructors
    // where one has a single WebUI* arg and the other has both
    // WebUI* and GURL params.
    static_assert(!(std::is_constructible_v<T, content::WebUI*> &&
                    std::is_constructible_v<T, content::WebUI*, GURL>));
    if constexpr (std::is_constructible_v<T, content::WebUI*, GURL>) {
      return std::make_unique<T>(web_ui, url);
    } else {
      return std::make_unique<T>(web_ui);
    }
  }

  // Constructs a WebUIConfig for a ChromeOS WebUI.
  ChromeOSWebUIConfig(std::string_view scheme, std::string_view host)
      : ChromeOSWebUIConfig(
            scheme,
            host,
            base::BindRepeating(&DefaultCreateWebUIControllerFunc)) {}

  // Same as above, but takes in an extra `create_controller_func` argument that
  // can be used to pass a function to construct T. Used when we need to inject
  // dependencies into T e.g. T needs a delegate that is implemented in
  // //chrome.
  ChromeOSWebUIConfig(std::string_view scheme,
                      std::string_view host,
                      CreateWebUIControllerFunc create_controller_func)
      : WebUIConfig(scheme, host),
        create_controller_func_(create_controller_func) {}

  ~ChromeOSWebUIConfig() override = default;

  std::unique_ptr<content::WebUIController> CreateWebUIController(
      content::WebUI* web_ui,
      const GURL& url) override {
    return create_controller_func_.Run(web_ui, url);
  }

 private:
  CreateWebUIControllerFunc create_controller_func_;
};

}  //  namespace ash

#endif  //  ASH_WEBUI_COMMON_CHROME_OS_WEBUI_CONFIG_H_