blob: 384a512119541f9e302c2e9394b567926e74b79a [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/web_applications/app_service/web_apps_base.h"
#include <utility>
#include "base/callback.h"
#include "base/feature_list.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/apps/app_service/intent_util.h"
#include "chrome/browser/apps/app_service/launch_utils.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/web_applications/web_app_dialog_manager.h"
#include "chrome/browser/ui/web_applications/web_app_ui_manager_impl.h"
#include "chrome/browser/web_applications/components/install_finalizer.h"
#include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/components/web_app_utils.h"
#include "chrome/browser/web_applications/system_web_apps/system_web_app_manager.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/common/chrome_features.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_types.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/crosapi/browser_util.h"
#endif
using apps::IconEffects;
namespace web_app {
namespace {
apps::mojom::AppType GetWebAppType() {
// After moving the ordinary Web Apps to Lacros chrome, the remaining web
// apps in ash Chrome will be only System Web Apps. Change the app type
// to kSystemWeb for this case and the kWeb app type will be published from
// the publisher for Lacros web apps.
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (crosapi::browser_util::IsLacrosEnabled() &&
base::FeatureList::IsEnabled(features::kWebAppsCrosapi)) {
return apps::mojom::AppType::kSystemWeb;
}
#endif
return apps::mojom::AppType::kWeb;
}
bool ShouldObserveMediaRequests() {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// The publisher helper owned by WebAppsPublisherHost observes media requests,
// not the publisher helper owned by WebAppsBase.
return false;
#else
return true;
#endif
}
} // namespace
WebAppsBase::WebAppsBase(
const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile)
: profile_(profile),
app_service_(nullptr),
app_type_(GetWebAppType()),
publisher_helper_(profile_,
app_type_,
this,
ShouldObserveMediaRequests()) {
Initialize(app_service);
}
WebAppsBase::~WebAppsBase() = default;
void WebAppsBase::Shutdown() {
if (provider_) {
publisher_helper().Shutdown();
}
}
const WebApp* WebAppsBase::GetWebApp(const AppId& app_id) const {
// GetRegistrar() might return nullptr if the legacy bookmark apps registry is
// enabled. This may happen in migration browser tests.
return GetRegistrar() ? GetRegistrar()->GetAppById(app_id) : nullptr;
}
bool WebAppsBase::Accepts(const std::string& app_id) const {
return WebAppPublisherHelper::Accepts(app_id);
}
void WebAppsBase::Initialize(
const mojo::Remote<apps::mojom::AppService>& app_service) {
DCHECK(profile_);
if (!AreWebAppsEnabled(profile_)) {
return;
}
provider_ = WebAppProvider::Get(profile_);
DCHECK(provider_);
PublisherBase::Initialize(app_service, app_type_);
app_service_ = app_service.get();
}
const WebAppRegistrar* WebAppsBase::GetRegistrar() const {
DCHECK(provider_);
return provider_->registrar().AsWebAppRegistrar();
}
void WebAppsBase::Connect(
mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
apps::mojom::ConnectOptionsPtr opts) {
DCHECK(provider_);
provider_->on_registry_ready().Post(
FROM_HERE, base::BindOnce(&WebAppsBase::StartPublishingWebApps,
AsWeakPtr(), std::move(subscriber_remote)));
}
void WebAppsBase::LoadIcon(const std::string& app_id,
apps::mojom::IconKeyPtr icon_key,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
bool allow_placeholder_icon,
LoadIconCallback callback) {
publisher_helper().LoadIcon(app_id, std::move(icon_key), std::move(icon_type),
size_hint_in_dip, allow_placeholder_icon,
std::move(callback));
}
void WebAppsBase::Launch(const std::string& app_id,
int32_t event_flags,
apps::mojom::LaunchSource launch_source,
apps::mojom::WindowInfoPtr window_info) {
publisher_helper().Launch(app_id, event_flags, launch_source,
std::move(window_info));
}
void WebAppsBase::LaunchAppWithFiles(const std::string& app_id,
apps::mojom::LaunchContainer container,
int32_t event_flags,
apps::mojom::LaunchSource launch_source,
apps::mojom::FilePathsPtr file_paths) {
publisher_helper().LaunchAppWithFiles(app_id, container, event_flags,
launch_source, std::move(file_paths));
}
void WebAppsBase::LaunchAppWithIntent(const std::string& app_id,
int32_t event_flags,
apps::mojom::IntentPtr intent,
apps::mojom::LaunchSource launch_source,
apps::mojom::WindowInfoPtr window_info) {
publisher_helper().LaunchAppWithIntent(app_id, event_flags, std::move(intent),
launch_source, std::move(window_info));
}
void WebAppsBase::SetPermission(const std::string& app_id,
apps::mojom::PermissionPtr permission) {
publisher_helper().SetPermission(app_id, std::move(permission));
}
void WebAppsBase::OpenNativeSettings(const std::string& app_id) {
publisher_helper().OpenNativeSettings(app_id);
}
void WebAppsBase::PublishWebApps(std::vector<apps::mojom::AppPtr> apps) {
const bool should_notify_initialized = false;
if (subscribers_.size() == 1) {
auto& subscriber = *subscribers_.begin();
subscriber->OnApps(std::move(apps), app_type(), should_notify_initialized);
return;
}
for (auto& subscriber : subscribers_) {
std::vector<apps::mojom::AppPtr> cloned_apps;
for (const auto& app : apps)
cloned_apps.push_back(app.Clone());
subscriber->OnApps(std::move(cloned_apps), app_type(),
should_notify_initialized);
}
}
void WebAppsBase::PublishWebApp(apps::mojom::AppPtr app) {
Publish(std::move(app), subscribers_);
}
void WebAppsBase::ModifyWebAppCapabilityAccess(
const std::string& app_id,
absl::optional<bool> accessing_camera,
absl::optional<bool> accessing_microphone) {
ModifyCapabilityAccess(subscribers_, app_id, std::move(accessing_camera),
std::move(accessing_microphone));
}
void WebAppsBase::ConvertWebApps(std::vector<apps::mojom::AppPtr>* apps_out) {
const WebAppRegistrar* registrar = GetRegistrar();
// Can be nullptr in tests.
if (!registrar)
return;
for (const WebApp& web_app : registrar->GetApps()) {
if (Accepts(web_app.app_id())) {
apps_out->push_back(publisher_helper().ConvertWebApp(&web_app));
}
}
}
void WebAppsBase::StartPublishingWebApps(
mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote) {
std::vector<apps::mojom::AppPtr> apps;
ConvertWebApps(&apps);
mojo::Remote<apps::mojom::Subscriber> subscriber(
std::move(subscriber_remote));
subscriber->OnApps(std::move(apps), app_type_,
true /* should_notify_initialized */);
subscribers_.Add(std::move(subscriber));
}
} // namespace web_app