| // Copyright 2019 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/help_app_ui/help_app_ui.h" | 
 |  | 
 | #include <utility> | 
 |  | 
 | #include "ash/constants/ash_features.h" | 
 | #include "ash/webui/grit/ash_help_app_resources.h" | 
 | #include "ash/webui/help_app_ui/help_app_manager.h" | 
 | #include "ash/webui/help_app_ui/help_app_manager_factory.h" | 
 | #include "ash/webui/help_app_ui/help_app_page_handler.h" | 
 | #include "ash/webui/help_app_ui/help_app_untrusted_ui.h" | 
 | #include "ash/webui/help_app_ui/search/search_handler.h" | 
 | #include "ash/webui/web_applications/webui_test_prod_util.h" | 
 | #include "base/check_deref.h" | 
 | #include "base/strings/strcat.h" | 
 | #include "chromeos/ash/components/local_search_service/public/cpp/local_search_service_proxy.h" | 
 | #include "chromeos/ash/components/local_search_service/public/cpp/local_search_service_proxy_factory.h" | 
 | #include "chromeos/ash/components/local_search_service/public/mojom/types.mojom.h" | 
 | #include "chromeos/constants/url_constants.h" | 
 | #include "chromeos/strings/grit/chromeos_strings.h" | 
 | #include "components/content_settings/core/common/content_settings_types.h" | 
 | #include "content/public/browser/web_contents.h" | 
 | #include "content/public/browser/web_ui.h" | 
 | #include "content/public/browser/web_ui_data_source.h" | 
 | #include "content/public/common/url_constants.h" | 
 | #include "services/network/public/mojom/content_security_policy.mojom.h" | 
 | #include "ui/webui/webui_allowlist.h" | 
 |  | 
 | namespace ash { | 
 |  | 
 | namespace { | 
 | content::WebUIDataSource* CreateAndAddHostDataSource( | 
 |     content::BrowserContext* browser_context) { | 
 |   content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd( | 
 |       browser_context, kChromeUIHelpAppHost); | 
 |  | 
 |   source->SetDefaultResource(IDR_HELP_APP_HOST_INDEX_DARK_LIGHT_HTML); | 
 |   source->AddResourcePath("app_icon_192.png", IDR_HELP_APP_ICON_192); | 
 |   source->AddResourcePath("app_icon_512.png", IDR_HELP_APP_ICON_512); | 
 |   source->AddResourcePath("browser_proxy.js", IDR_HELP_APP_BROWSER_PROXY_JS); | 
 |  | 
 |   source->AddLocalizedString("appTitle", IDS_HELP_APP_EXPLORE); | 
 |   return source; | 
 | } | 
 | }  // namespace | 
 |  | 
 | HelpAppUI::HelpAppUI(content::WebUI* web_ui, | 
 |                      std::unique_ptr<HelpAppUIDelegate> delegate, | 
 |                      PrefService* pref_service) | 
 |     : MojoWebUIController(web_ui), | 
 |       delegate_(std::move(delegate)), | 
 |       pref_service_(CHECK_DEREF(pref_service)) { | 
 |   content::BrowserContext* browser_context = | 
 |       web_ui->GetWebContents()->GetBrowserContext(); | 
 |   content::WebUIDataSource* host_source = | 
 |       CreateAndAddHostDataSource(browser_context); | 
 |   // We need a CSP override to use the chrome-untrusted://, almanac:// and | 
 |   // cros-apps:// schemes in the host. | 
 |   std::string csp = base::StrCat({"frame-src ", kChromeUIHelpAppUntrustedURL, | 
 |                                   " ", chromeos::kAppInstallUriScheme, ":;"}); | 
 |   host_source->OverrideContentSecurityPolicy( | 
 |       network::mojom::CSPDirectiveName::FrameSrc, csp); | 
 |  | 
 |   // Add ability to request chrome-untrusted: URLs. | 
 |   web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme); | 
 |  | 
 |   // Register common permissions for chrome-untrusted:// pages. | 
 |   // TODO(crbug.com/40710326): Remove this after common permissions are | 
 |   // granted by default. | 
 |   auto* permissions_allowlist = WebUIAllowlist::GetOrCreate(browser_context); | 
 |   const url::Origin untrusted_origin = | 
 |       url::Origin::Create(GURL(kChromeUIHelpAppUntrustedURL)); | 
 |   permissions_allowlist->RegisterAutoGrantedPermissions( | 
 |       untrusted_origin, { | 
 |                             ContentSettingsType::COOKIES, | 
 |                             ContentSettingsType::IMAGES, | 
 |                             ContentSettingsType::JAVASCRIPT, | 
 |                             ContentSettingsType::SOUND, | 
 |                         }); | 
 |  | 
 |   if (MaybeConfigureTestableDataSource(host_source)) { | 
 |     host_source->OverrideContentSecurityPolicy( | 
 |         network::mojom::CSPDirectiveName::ScriptSrc, | 
 |         "script-src chrome://resources chrome://webui-test 'self';"); | 
 |     host_source->OverrideContentSecurityPolicy( | 
 |         network::mojom::CSPDirectiveName::TrustedTypes, | 
 |         std::string("trusted-types test-harness;")); | 
 |   } | 
 |  | 
 |   // Register common permissions for chrome-untrusted:// pages. | 
 |   // TODO(crbug.com/40710326): Remove this after common permissions are | 
 |   // granted by default. | 
 |   auto* magazine_permissions_allowlist = | 
 |       WebUIAllowlist::GetOrCreate(browser_context); | 
 |   const url::Origin magazine_untrusted_origin = | 
 |       url::Origin::Create(GURL(kChromeUIHelpAppKidsMagazineUntrustedURL)); | 
 |   magazine_permissions_allowlist->RegisterAutoGrantedPermissions( | 
 |       magazine_untrusted_origin, { | 
 |                                      ContentSettingsType::COOKIES, | 
 |                                      ContentSettingsType::IMAGES, | 
 |                                      ContentSettingsType::JAVASCRIPT, | 
 |                                      ContentSettingsType::SOUND, | 
 |                                  }); | 
 | } | 
 |  | 
 | HelpAppUI::~HelpAppUI() = default; | 
 |  | 
 | void HelpAppUI::BindInterface( | 
 |     mojo::PendingReceiver<help_app::mojom::PageHandlerFactory> receiver) { | 
 |   page_factory_receiver_.reset(); | 
 |   page_factory_receiver_.Bind(std::move(receiver)); | 
 | } | 
 |  | 
 | void HelpAppUI::BindInterface( | 
 |     mojo::PendingReceiver<local_search_service::mojom::Index> index_receiver) { | 
 |   auto* const factory = local_search_service::LocalSearchServiceProxyFactory:: | 
 |       GetForBrowserContext(web_ui()->GetWebContents()->GetBrowserContext()); | 
 |   factory->SetLocalState(delegate_->GetLocalState()); | 
 |   factory->GetIndex(local_search_service::IndexId::kHelpApp, | 
 |                     local_search_service::Backend::kInvertedIndex, | 
 |                     std::move(index_receiver)); | 
 | } | 
 |  | 
 | void HelpAppUI::BindInterface( | 
 |     mojo::PendingReceiver<help_app::mojom::SearchHandler> receiver) { | 
 |   if (base::FeatureList::IsEnabled(features::kHelpAppLauncherSearch)) { | 
 |     help_app::HelpAppManagerFactory::GetForBrowserContext( | 
 |         web_ui()->GetWebContents()->GetBrowserContext()) | 
 |         ->search_handler() | 
 |         ->BindInterface(std::move(receiver)); | 
 |   } | 
 | } | 
 |  | 
 | void HelpAppUI::CreatePageHandler( | 
 |     mojo::PendingReceiver<help_app::mojom::PageHandler> receiver) { | 
 |   page_handler_ = std::make_unique<HelpAppPageHandler>( | 
 |       this, std::move(receiver), pref_service_); | 
 | } | 
 |  | 
 | bool HelpAppUI::IsJavascriptErrorReportingEnabled() { | 
 |   // JavaScript errors are reported via CrashReportPrivate.reportError. Don't | 
 |   // send duplicate reports via WebUI. | 
 |   return false; | 
 | } | 
 |  | 
 | WEB_UI_CONTROLLER_TYPE_IMPL(HelpAppUI) | 
 |  | 
 | }  // namespace ash |