blob: b43a610d835871303c0e9a160c74b912e5cd94c1 [file] [log] [blame]
// 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 "chrome/browser/ui/webui/ash/mako/mako_ui.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_switches.h"
#include "ash/lobster/lobster_controller.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "build/branding_buildflags.h"
#include "chrome/browser/ash/input_method/editor_helpers.h"
#include "chrome/browser/ash/input_method/editor_mediator_factory.h"
#include "chrome/browser/ash/lobster/lobster_service.h"
#include "chrome/browser/ash/lobster/lobster_service_provider.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/ash/mako/url_constants.h"
#include "chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.h"
#include "chrome/grit/orca_resources.h"
#include "chrome/grit/orca_resources_map.h"
#include "chromeos/ash/services/orca/public/mojom/orca_service.mojom.h"
#include "chromeos/constants/chromeos_features.h"
#include "content/public/browser/browser_context.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 "ui/webui/webui_util.h"
namespace ash {
namespace {
constexpr int kEnUSResourceIds[] = {
IDR_MAKO_ORCA_HTML, IDR_MAKO_PRIVACY_HTML, IDR_MAKO_LOBSTER_HTML,
IDR_MAKO_ORCA_JS, IDR_MAKO_LOBSTER_JS, IDR_MAKO_ORCA_TRANSLATION_EN_JS};
constexpr int kLobsterResourceIds[] = {
IDR_MAKO_LOBSTER_HTML,
IDR_MAKO_LOBSTER_JS,
};
} // namespace
MakoUntrustedUIConfig::MakoUntrustedUIConfig()
: DefaultTopChromeWebUIConfig(content::kChromeUIUntrustedScheme,
ash::kChromeUIMakoHost) {}
MakoUntrustedUIConfig::~MakoUntrustedUIConfig() = default;
bool MakoUntrustedUIConfig::IsWebUIEnabled(
content::BrowserContext* browser_context) {
return chromeos::features::IsOrcaEnabled() ||
ash::features::IsLobsterEnabled();
}
bool MakoUntrustedUIConfig::ShouldAutoResizeHost() {
// With resizing support enabled, we should let web viewport resize according
// to dimension of web view rather than updating the dimension of web view
// based on inner web content.
return !base::FeatureList::IsEnabled(ash::features::kOrcaResizingSupport);
}
MakoUntrustedUI::MakoUntrustedUI(content::WebUI* web_ui)
: UntrustedTopChromeWebUIController(web_ui) {
CHECK(chromeos::features::IsOrcaEnabled() ||
ash::features::IsLobsterEnabled());
// Setup the data source
content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
web_ui->GetWebContents()->GetBrowserContext(), kChromeUIMakoURL);
base::span<const webui::ResourcePath> orca_resources = kOrcaResources;
LobsterService* lobster_service =
ash::features::IsLobsterEnabled()
? LobsterServiceProvider::GetForProfile(Profile::FromWebUI(web_ui))
: nullptr;
const bool should_use_l10n_strings = input_method::ShouldUseL10nStrings();
auto should_use_resource =
[&](const webui::ResourcePath& resource_path) -> bool {
// when lobster access is not granted, lobster resources are not allowed.
if (lobster_service == nullptr &&
base::Contains(kLobsterResourceIds, resource_path.id)) {
return false;
}
// when l10n is disabled, only EN-US resources are allowed.
if (!should_use_l10n_strings &&
!base::Contains(kEnUSResourceIds, resource_path.id)) {
return false;
}
return true;
};
// TODO: b:333625296 - Add tests for this conditional behavior
{
std::vector<webui::ResourcePath> orca_en_us_resources;
std::ranges::copy_if(orca_resources,
std::back_inserter(orca_en_us_resources),
should_use_resource);
webui::SetupWebUIDataSource(source, orca_en_us_resources,
IDR_MAKO_ORCA_HTML);
}
source->SetDefaultResource(IDR_MAKO_ORCA_HTML);
// Setup additional CSP overrides
// Intentional space at end of the strings - things are appended to this.
source->OverrideContentSecurityPolicy(
network::mojom::CSPDirectiveName::TrustedTypes,
"trusted-types goog#html polymer_resin lit-html "
"polymer-template-event-attribute-policy polymer-html-literal; ");
source->OverrideContentSecurityPolicy(
network::mojom::CSPDirectiveName::StyleSrc,
"style-src 'unsafe-inline' chrome-untrusted://theme; ");
source->OverrideContentSecurityPolicy(
network::mojom::CSPDirectiveName::ImgSrc, "img-src data:; ");
}
MakoUntrustedUI::~MakoUntrustedUI() = default;
void MakoUntrustedUI::BindInterface(
mojo::PendingReceiver<orca::mojom::EditorClient> pending_receiver) {
if (!chromeos::features::IsOrcaEnabled()) {
mojo::ReportBadMessage("Editor is disabled by flags.");
return;
}
// If mako ui is shown to the user, then we know that EditorMediator is
// allowed for the current profile and will return a valid instance.
input_method::EditorMediatorFactory::GetInstance()
->GetForProfile(Profile::FromWebUI(web_ui()))
->BindEditorClient(std::move(pending_receiver));
}
void MakoUntrustedUI::BindInterface(
mojo::PendingReceiver<color_change_listener::mojom::PageHandler> receiver) {
color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>(
web_ui()->GetWebContents(), std::move(receiver));
}
void MakoUntrustedUI::BindInterface(
mojo::PendingReceiver<lobster::mojom::UntrustedLobsterPageHandler>
pending_receiver) {
if (!ash::features::IsLobsterEnabled()) {
mojo::ReportBadMessage("Lobster is disabled by flags.");
return;
}
Profile* profile = Profile::FromWebUI(web_ui());
LobsterService* lobster_service =
LobsterServiceProvider::GetForProfile(profile);
LobsterSession* active_session =
lobster_service == nullptr ? nullptr : lobster_service->active_session();
if (active_session == nullptr) {
mojo::ReportBadMessage("No active session found.");
return;
}
lobster_page_handler_ =
std::make_unique<LobsterPageHandler>(active_session, profile);
lobster_page_handler_->BindInterface(std::move(pending_receiver));
}
WEB_UI_CONTROLLER_TYPE_IMPL(MakoUntrustedUI)
} // namespace ash