blob: 593a6f3b8cb9966039444319aa2cbe6b7563e654 [file] [log] [blame]
// Copyright 2021 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/apps/app_service/subscriber_crosapi.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/notreached.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/intent_util.h"
#include "chrome/browser/apps/app_service/launch_utils.h"
#include "chrome/browser/apps/app_service/metrics/app_service_metrics.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/webui/settings/ash/app_management/app_management_uma.h"
#include "components/services/app_service/public/cpp/app_registry_cache.h"
#include "components/services/app_service/public/cpp/app_types.h"
namespace {
bool Accepts(apps::AppType app_type) {
return app_type == apps::AppType::kUnknown ||
app_type == apps::AppType::kArc || app_type == apps::AppType::kWeb ||
app_type == apps::AppType::kSystemWeb ||
app_type == apps::AppType::kStandaloneBrowserChromeApp;
}
} // namespace
namespace apps {
class AppUpdate;
SubscriberCrosapi::SubscriberCrosapi(Profile* profile)
: profile_(profile),
proxy_(apps::AppServiceProxyFactory::GetForProfile(profile)) {}
SubscriberCrosapi::~SubscriberCrosapi() = default;
void SubscriberCrosapi::RegisterAppServiceProxyFromCrosapi(
mojo::PendingReceiver<crosapi::mojom::AppServiceProxy> receiver) {
// At the moment the app service subscriber will only accept one client
// connect to ash chrome. Any extra clients will be ignored.
// TODO(crbug.com/1174246): Support SxS lacros.
if (crosapi_receiver_.is_bound()) {
return;
}
crosapi_receiver_.Bind(std::move(receiver));
crosapi_receiver_.set_disconnect_handler(base::BindOnce(
&SubscriberCrosapi::OnCrosapiDisconnected, base::Unretained(this)));
}
void SubscriberCrosapi::OnApps(const std::vector<AppPtr>& deltas,
AppType app_type,
bool should_notify_initialized) {
if (!subscriber_.is_bound()) {
return;
}
if (!Accepts(app_type)) {
return;
}
std::vector<AppPtr> apps;
for (const auto& delta : deltas) {
if (Accepts(delta->app_type)) {
apps.push_back(delta->Clone());
}
}
subscriber_->OnApps(std::move(apps), app_type, should_notify_initialized);
}
void SubscriberCrosapi::InitializeApps() {
// For each app type that has already been initialized, republish their apps
// to Lacros as initialized. App types that are yet to initialize will
// initialize via OnApps() in the usual way.
// Sort apps by app type.
std::vector<AppPtr> all_apps = proxy_->AppRegistryCache().GetAllApps();
base::flat_map<AppType, std::vector<AppPtr>> app_type_apps;
for (AppPtr& app : all_apps) {
if (Accepts(app->app_type)) {
app_type_apps[app->app_type].push_back(std::move(app));
}
}
for (AppType app_type : proxy_->AppRegistryCache().InitializedAppTypes()) {
if (Accepts(app_type)) {
OnApps(std::move(app_type_apps[app_type]), app_type,
/*should_notify_initialized=*/true);
}
}
}
void SubscriberCrosapi::InitializePreferredApps(PreferredApps preferred_apps) {
if (subscriber_.is_bound()) {
subscriber_->InitializePreferredApps(std::move(preferred_apps));
}
}
void SubscriberCrosapi::OnPreferredAppsChanged(PreferredAppChangesPtr changes) {
if (!subscriber_.is_bound()) {
return;
}
subscriber_->OnPreferredAppsChanged(std::move(changes));
}
void SubscriberCrosapi::OnCrosapiDisconnected() {
crosapi_receiver_.reset();
subscriber_.reset();
}
void SubscriberCrosapi::RegisterAppServiceSubscriber(
mojo::PendingRemote<crosapi::mojom::AppServiceSubscriber> subscriber) {
// At the moment the app service subscriber will only accept one client
// connect to ash chrome. Any extra clients will be ignored.
// TODO(crbug.com/1174246): Support SxS lacros.
if (subscriber_.is_bound()) {
return;
}
subscriber_.Bind(std::move(subscriber));
subscriber_.set_disconnect_handler(base::BindOnce(
&SubscriberCrosapi::OnSubscriberDisconnected, base::Unretained(this)));
proxy_->RegisterCrosApiSubScriber(this);
}
void SubscriberCrosapi::Launch(crosapi::mojom::LaunchParamsPtr launch_params) {
// TODO(crbug.com/1244506): Link up the return callback.
proxy_->LaunchAppWithParams(
ConvertCrosapiToLaunchParams(launch_params, profile_), base::DoNothing());
}
void SubscriberCrosapi::LaunchWithResult(
crosapi::mojom::LaunchParamsPtr launch_params,
LaunchWithResultCallback callback) {
auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_);
proxy->LaunchAppWithParams(
ConvertCrosapiToLaunchParams(launch_params, profile_),
MojomLaunchResultToLaunchResultCallback(std::move(callback)));
}
void SubscriberCrosapi::LoadIcon(const std::string& app_id,
IconKeyPtr icon_key,
IconType icon_type,
int32_t size_hint_in_dip,
apps::LoadIconCallback callback) {
if (!icon_key) {
std::move(callback).Run(std::make_unique<IconValue>());
return;
}
proxy_->LoadIconFromIconKey(proxy_->AppRegistryCache().GetAppType(app_id),
app_id, *icon_key, icon_type, size_hint_in_dip,
/*allow_placeholder_icon=*/false,
std::move(callback));
}
void SubscriberCrosapi::AddPreferredApp(const std::string& app_id,
crosapi::mojom::IntentPtr intent) {
proxy_->AddPreferredApp(
app_id, apps_util::CreateAppServiceIntentFromCrosapi(intent, profile_));
}
void SubscriberCrosapi::ShowAppManagementPage(const std::string& app_id) {
if (!proxy_->AppRegistryCache().ForOneApp(app_id,
[](const apps::AppUpdate&) {})) {
LOG(WARNING) << "Unknown app: " << app_id;
return;
}
chrome::ShowAppManagementPage(
profile_, app_id, ash::settings::AppManagementEntryPoint::kPageInfoView);
}
void SubscriberCrosapi::SetSupportedLinksPreference(const std::string& app_id) {
proxy_->SetSupportedLinksPreference(app_id);
}
void SubscriberCrosapi::UninstallSilently(const std::string& app_id,
UninstallSource uninstall_source) {
proxy_->UninstallSilently(app_id, uninstall_source);
}
void SubscriberCrosapi::OnSubscriberDisconnected() {
subscriber_.reset();
}
} // namespace apps