chromium/ios/chrome/browser/webui/ui_bundled/chrome_web_ui_ios_controller_factory.mm

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

#import "ios/chrome/browser/webui/ui_bundled/chrome_web_ui_ios_controller_factory.h"

#import <Foundation/Foundation.h>

#import "base/functional/bind.h"
#import "base/location.h"
#import "base/no_destructor.h"
#import "components/commerce/core/commerce_constants.h"
#import "components/commerce/ios/browser/commerce_internals_ui.h"
#import "components/optimization_guide/optimization_guide_buildflags.h"
#import "components/optimization_guide/optimization_guide_internals/webui/url_constants.h"
#import "components/version_info/channel.h"
#import "ios/chrome/browser/commerce/model/shopping_service_factory.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/model/url/chrome_url_constants.h"
#import "ios/chrome/browser/shared/public/features/system_flags.h"
#import "ios/chrome/browser/webui/ui_bundled/about/about_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/autofill_and_password_manager_internals/autofill_internals_ui_ios.h"
#import "ios/chrome/browser/webui/ui_bundled/autofill_and_password_manager_internals/password_manager_internals_ui_ios.h"
#import "ios/chrome/browser/webui/ui_bundled/crashes_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/download_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/flags_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/gcm/gcm_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/inspect/inspect_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/interstitials/interstitial_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/local_state/local_state_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/management/management_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/net_export/net_export_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/ntp_tiles_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/omaha_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/on_device_llm_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/optimization_guide_internals/optimization_guide_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/policy/policy_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/prefs_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/signin_internals_ui_ios.h"
#import "ios/chrome/browser/webui/ui_bundled/terms_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/translate_internals/translate_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/ukm_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/user_actions_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/userdefaults_internals_ui.h"
#import "ios/chrome/browser/webui/ui_bundled/version_ui.h"
#import "ios/chrome/common/channel_info.h"
#import "ios/components/webui/sync_internals/sync_internals_ui.h"
#import "ios/components/webui/web_ui_url_constants.h"
#import "url/gurl.h"

using ::version_info::Channel;
using web::WebUIIOS;
using web::WebUIIOSController;

namespace {

// A function for creating a new WebUIIOS.
using WebUIIOSFactoryFunction =
    std::unique_ptr<WebUIIOSController> (*)(WebUIIOS* web_ui, const GURL& url);

// Template for defining WebUIIOSFactoryFunction.
template <class T>
std::unique_ptr<WebUIIOSController> NewWebUIIOS(WebUIIOS* web_ui,
                                                const GURL& url) {
  return std::make_unique<T>(web_ui, url.host());
}

template <>
std::unique_ptr<WebUIIOSController> NewWebUIIOS<commerce::CommerceInternalsUI>(
    WebUIIOS* web_ui,
    const GURL& url) {
  ChromeBrowserState* browser_state = ChromeBrowserState::FromWebUIIOS(web_ui);
  return std::make_unique<commerce::CommerceInternalsUI>(
      web_ui, commerce::kChromeUICommerceInternalsHost,
      commerce::ShoppingServiceFactory::GetForBrowserState(browser_state));
}

// Returns a function that can be used to create the right type of WebUIIOS for
// a tab, based on its URL. Returns NULL if the URL doesn't have WebUIIOS
// associated with it.
WebUIIOSFactoryFunction GetWebUIIOSFactoryFunction(const GURL& url) {
  // This will get called a lot to check all URLs, so do a quick check of other
  // schemes to filter out most URLs.
  if (!url.SchemeIs(kChromeUIScheme))
    return nullptr;

  // Please keep this in alphabetical order. If #ifs or special logic is
  // required, add it below in the appropriate section.
  const std::string url_host = url.host();
  if (url_host == kChromeUIAutofillInternalsHost)
    return &NewWebUIIOS<AutofillInternalsUIIOS>;
  if (url_host == kChromeUIChromeURLsHost ||
      url_host == kChromeUIHistogramHost || url_host == kChromeUICreditsHost)
    return &NewWebUIIOS<AboutUI>;
  if (url_host == commerce::kChromeUICommerceInternalsHost) {
    return &NewWebUIIOS<commerce::CommerceInternalsUI>;
  }
  if (url_host == kChromeUICrashesHost)
    return &NewWebUIIOS<CrashesUI>;
  if (url_host == kChromeUIDownloadInternalsHost)
    return &NewWebUIIOS<DownloadInternalsUI>;
  if (url_host == kChromeUIFlagsHost)
    return &NewWebUIIOS<FlagsUI>;
  if (url_host == kChromeUIGCMInternalsHost)
    return &NewWebUIIOS<GCMInternalsUI>;
  if (url_host == kChromeUIInspectHost)
    return &NewWebUIIOS<InspectUI>;
  if (url_host == kChromeUIIntersitialsHost)
    return &NewWebUIIOS<InterstitialUI>;
  if (url_host == kChromeUILocalStateHost)
    return &NewWebUIIOS<LocalStateUI>;
  if (url_host == kChromeUIManagementHost)
    return &NewWebUIIOS<ManagementUI>;
  if (url_host == kChromeUINetExportHost)
    return &NewWebUIIOS<NetExportUI>;
  if (url_host == kChromeUINTPTilesInternalsHost)
    return &NewWebUIIOS<NTPTilesInternalsUI>;
  if (url_host == kChromeUIOmahaHost)
    return &NewWebUIIOS<OmahaUI>;
  if (url_host ==
      optimization_guide_internals::kChromeUIOptimizationGuideInternalsHost) {
    return &NewWebUIIOS<OptimizationGuideInternalsUI>;
  }
  if (url_host == kChromeUIPasswordManagerInternalsHost)
    return &NewWebUIIOS<PasswordManagerInternalsUIIOS>;
  if (url_host == kChromeUIPrefsInternalsHost)
    return &NewWebUIIOS<PrefsInternalsUI>;
  if (url_host == kChromeUISignInInternalsHost)
    return &NewWebUIIOS<SignInInternalsUIIOS>;
  if (url.host_piece() == kChromeUITranslateInternalsHost)
    return &NewWebUIIOS<TranslateInternalsUI>;
  if (url_host == kChromeUIURLKeyedMetricsHost)
    return &NewWebUIIOS<UkmInternalsUI>;
  if (url_host == kChromeUIUserActionsHost)
    return &NewWebUIIOS<UserActionsUI>;
  if (url_host == kChromeUISyncInternalsHost)
    return &NewWebUIIOS<SyncInternalsUI>;
  if (url_host == kChromeUITermsHost)
    return &NewWebUIIOS<TermsUI>;
  if (url_host == kChromeUIVersionHost)
    return &NewWebUIIOS<VersionUI>;
  if (url_host == kChromeUIPolicyHost)
    return &NewWebUIIOS<PolicyUI>;
  if (url_host == kChromeUIUserDefaultsInternalsHost &&
      GetChannel() != Channel::STABLE) {
    return &NewWebUIIOS<UserDefaultsInternalsUI>;
  }
#if BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE)
  if (url_host == kChromeUIOnDeviceLlmInternalsHost) {
    return &NewWebUIIOS<OnDeviceLlmInternalsUI>;
  }
#endif  // BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE)

  return nullptr;
}

}  // namespace

NSInteger ChromeWebUIIOSControllerFactory::GetErrorCodeForWebUIURL(
    const GURL& url) const {
  if (url.host() == kChromeUIDinoHost) {
    return NSURLErrorNotConnectedToInternet;
  }
  if (GetWebUIIOSFactoryFunction(url))
    return 0;
  return NSURLErrorUnsupportedURL;
}

std::unique_ptr<WebUIIOSController>
ChromeWebUIIOSControllerFactory::CreateWebUIIOSControllerForURL(
    WebUIIOS* web_ui,
    const GURL& url) const {
  WebUIIOSFactoryFunction function = GetWebUIIOSFactoryFunction(url);
  if (!function)
    return nullptr;

  return (*function)(web_ui, url);
}

// static
ChromeWebUIIOSControllerFactory*
ChromeWebUIIOSControllerFactory::GetInstance() {
  static base::NoDestructor<ChromeWebUIIOSControllerFactory> instance;
  return instance.get();
}

ChromeWebUIIOSControllerFactory::ChromeWebUIIOSControllerFactory() {}

ChromeWebUIIOSControllerFactory::~ChromeWebUIIOSControllerFactory() {}