Commit 83ff4432 authored by Nicholas Hollingum's avatar Nicholas Hollingum Committed by Commit Bot

Support GuestOsApps for borealis

This change allows GuestOsApps to be visible in the shelf/launcher, and
associates its windows with those items.

The behaviour is only partially completed, the current items will be
finished in a forthcoming CL:
 - Support launching the apps from the launcher/pinned shelf items
 - Have context-menus for our shelf/launcher items.

Bug: b/162562622
Change-Id: I7456fb8173cf1964663709fc015ba9cc9b79df12
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454952
Commit-Queue: Nic Hollingum <hollingum@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarNancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarDaniel Ng <danielng@google.com>
Reviewed-by: default avatarJoel Hockey <joelhockey@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816059}
parent 01b6d424
......@@ -16,6 +16,7 @@
#include "chrome/browser/apps/app_service/app_icon_source.h"
#include "chrome/browser/apps/app_service/app_service_metrics.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
#include "chrome/common/chrome_features.h"
......@@ -167,6 +168,11 @@ void AppServiceProxy::Initialize() {
built_in_chrome_os_apps_ =
std::make_unique<BuiltInChromeOsApps>(app_service_, profile_);
}
// TODO(b/170591339): Allow borealis to provide apps for the non-primary
// profile.
if (guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile_)) {
borealis_apps_ = std::make_unique<BorealisApps>(app_service_, profile_);
}
crostini_apps_ = std::make_unique<CrostiniApps>(app_service_, profile_);
extension_apps_ = std::make_unique<ExtensionAppsChromeOs>(
app_service_, profile_, apps::mojom::AppType::kExtension,
......@@ -191,7 +197,6 @@ void AppServiceProxy::Initialize() {
app_service_, profile_, apps::mojom::AppType::kWeb,
&instance_registry_);
}
borealis_apps_ = std::make_unique<BorealisApps>(app_service_, profile_);
#else
if (base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions)) {
web_apps_ = std::make_unique<WebApps>(app_service_, profile_);
......@@ -648,6 +653,7 @@ void AppServiceProxy::Shutdown() {
extension_web_apps_->Shutdown();
}
}
borealis_apps_.reset();
#endif
}
......
......@@ -12,10 +12,14 @@
#include "chrome/browser/chromeos/borealis/borealis_features.h"
#include "chrome/browser/chromeos/borealis/borealis_features_factory.h"
#include "chrome/browser/chromeos/borealis/borealis_util.h"
#include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
#include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/app_management/app_management.mojom.h"
#include "chrome/common/chrome_features.h"
#include "chrome/grit/chrome_unscaled_resources.h"
#include "chrome/grit/generated_resources.h"
#include "components/services/app_service/public/cpp/publisher_base.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
......@@ -59,10 +63,67 @@ BorealisApps::BorealisApps(
const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile)
: profile_(profile) {
Registry()->AddObserver(this);
PublisherBase::Initialize(app_service, apps::mojom::AppType::kBorealis);
// TODO(b/170264723): When uninstalling borealis is completed, ensure that we
// remove the apps from the apps service.
}
BorealisApps::~BorealisApps() = default;
BorealisApps::~BorealisApps() {
Registry()->RemoveObserver(this);
}
guest_os::GuestOsRegistryService* BorealisApps::Registry() {
guest_os::GuestOsRegistryService* registry =
guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile_);
// The GuestOsRegistryService is a dependant of the apps service itself, so it
// is not possible for the apps service to be in a valid state while this is
// null.
DCHECK(registry);
return registry;
}
apps::mojom::AppPtr BorealisApps::Convert(
const guest_os::GuestOsRegistryService::Registration& registration,
bool new_icon_key) {
// We must only convert borealis apps.
DCHECK_EQ(registration.VmType(), guest_os::GuestOsRegistryService::VmType::
ApplicationList_VmType_BOREALIS);
// The installer app is not a GuestOs app, it doesnt have a registration and
// it can't be converted.
DCHECK_NE(registration.app_id(), borealis::kBorealisAppId);
apps::mojom::AppPtr app = PublisherBase::MakeApp(
apps::mojom::AppType::kBorealis, registration.app_id(),
apps::mojom::Readiness::kReady, registration.Name(),
apps::mojom::InstallSource::kUser);
const std::string& executable_file_name = registration.ExecutableFileName();
if (!executable_file_name.empty()) {
app->additional_search_terms.push_back(executable_file_name);
}
for (const std::string& keyword : registration.Keywords()) {
app->additional_search_terms.push_back(keyword);
}
if (new_icon_key) {
auto icon_effects =
base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)
? IconEffects::kCrOsStandardIcon
: IconEffects::kNone;
app->icon_key = icon_key_factory_.MakeIconKey(icon_effects);
}
app->last_launch_time = registration.LastLaunchTime();
app->install_time = registration.InstallTime();
SetAppAllowed(app.get(), !registration.NoDisplay());
return app;
}
void BorealisApps::Connect(
mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
......@@ -72,6 +133,14 @@ void BorealisApps::Connect(
profile_,
borealis::BorealisFeaturesFactory::GetForProfile(profile_)->IsAllowed()));
for (const auto& pair :
Registry()->GetRegisteredApps(guest_os::GuestOsRegistryService::VmType::
ApplicationList_VmType_BOREALIS)) {
const guest_os::GuestOsRegistryService::Registration& registration =
pair.second;
apps.push_back(Convert(registration, /*new_icon_key=*/true));
}
mojo::Remote<apps::mojom::Subscriber> subscriber(
std::move(subscriber_remote));
subscriber->OnApps(std::move(apps));
......@@ -84,16 +153,10 @@ void BorealisApps::LoadIcon(const std::string& app_id,
int32_t size_hint_in_dip,
bool allow_placeholder_icon,
LoadIconCallback callback) {
constexpr bool is_placeholder_icon = false;
if (icon_key &&
(icon_key->resource_id != apps::mojom::IconKey::kInvalidResourceId)) {
LoadIconFromResource(
icon_type, size_hint_in_dip, icon_key->resource_id, is_placeholder_icon,
static_cast<IconEffects>(icon_key->icon_effects), std::move(callback));
return;
}
// On failure, we still run the callback, with the zero IconValue.
std::move(callback).Run(apps::mojom::IconValue::New());
Registry()->LoadIcon(app_id, std::move(icon_key), icon_type, size_hint_in_dip,
allow_placeholder_icon,
apps::mojom::IconKey::kInvalidResourceId,
std::move(callback));
}
void BorealisApps::Launch(const std::string& app_id,
......@@ -109,6 +172,9 @@ void BorealisApps::Launch(const std::string& app_id,
return;
}
borealis::ShowBorealisInstallerView(profile_);
// TODO(b/162562622): Fix the launcher so it runs borealis (if its already
// installed) and support launching apps.
}
void BorealisApps::GetMenuModel(const std::string& app_id,
......@@ -121,6 +187,41 @@ void BorealisApps::GetMenuModel(const std::string& app_id,
AddCommandItem(ash::MENU_CLOSE, IDS_SHELF_CONTEXT_MENU_CLOSE, &menu_items);
}
// TODO(b/162562622): Menu models for borealis apps.
std::move(callback).Run(std::move(menu_items));
}
void BorealisApps::OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service,
guest_os::GuestOsRegistryService::VmType vm_type,
const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) {
if (vm_type != guest_os::GuestOsRegistryService::VmType::
ApplicationList_VmType_BOREALIS) {
return;
}
for (const std::string& app_id : updated_apps) {
if (auto registration = registry_service->GetRegistration(app_id)) {
Publish(Convert(*registration, /*new_icon_key=*/false), subscribers_);
}
}
for (const std::string& app_id : removed_apps) {
apps::mojom::AppPtr app = apps::mojom::App::New();
app->app_type = apps::mojom::AppType::kBorealis;
app->app_id = app_id;
app->readiness = apps::mojom::Readiness::kUninstalledByUser;
Publish(std::move(app), subscribers_);
}
for (const std::string& app_id : inserted_apps) {
if (auto registration = registry_service->GetRegistration(app_id)) {
Publish(Convert(*registration, /*new_icon_key=*/true), subscribers_);
}
}
}
} // namespace apps
......@@ -8,6 +8,8 @@
#include <memory>
#include <string>
#include "chrome/browser/apps/app_service/icon_key_util.h"
#include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
#include "components/services/app_service/public/cpp/publisher_base.h"
#include "components/services/app_service/public/mojom/app_service.mojom.h"
#include "components/services/app_service/public/mojom/types.mojom.h"
......@@ -22,7 +24,8 @@ namespace apps {
// An app publisher (in the App Service sense) of Borealis apps.
// See components/services/app_service/README.md.
class BorealisApps : public apps::PublisherBase {
class BorealisApps : public apps::PublisherBase,
public guest_os::GuestOsRegistryService::Observer {
public:
BorealisApps(const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile);
......@@ -33,6 +36,14 @@ class BorealisApps : public apps::PublisherBase {
BorealisApps& operator=(const BorealisApps&) = delete;
private:
// Helper method to get the registry used by this profile
guest_os::GuestOsRegistryService* Registry();
// Turns GuestOsRegistry's "app" into one the AppService can use.
apps::mojom::AppPtr Convert(
const guest_os::GuestOsRegistryService::Registration& registration,
bool new_icon_key);
// apps::PublisherBase overrides.
void Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
apps::mojom::ConnectOptionsPtr opts) override;
......@@ -51,8 +62,18 @@ class BorealisApps : public apps::PublisherBase {
int64_t display_id,
GetMenuModelCallback callback) override;
// GuestOsRegistryService::Observer overrides.
void OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service,
guest_os::GuestOsRegistryService::VmType vm_type,
const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) override;
mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
apps_util::IncrementingIconKeyFactory icon_key_factory_;
Profile* const profile_;
};
......
......@@ -8,6 +8,7 @@
#include <vector>
#include "base/bind.h"
#include "chrome/browser/chromeos/borealis/borealis_features_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_features.h"
#include "chrome/browser/chromeos/crostini/crostini_mime_types_service.h"
#include "chrome/browser/chromeos/crostini/crostini_mime_types_service_factory.h"
......@@ -83,7 +84,8 @@ void VmApplicationsServiceProvider::UpdateApplicationList(
Profile* profile = ProfileManager::GetPrimaryUserProfile();
if (crostini::CrostiniFeatures::Get()->IsEnabled(profile) ||
plugin_vm::PluginVmFeatures::Get()->IsEnabled(profile)) {
plugin_vm::PluginVmFeatures::Get()->IsEnabled(profile) ||
borealis::BorealisFeaturesFactory::GetForProfile(profile)->IsEnabled()) {
auto* registry_service =
guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile);
registry_service->UpdateApplicationList(request);
......
......@@ -19,6 +19,7 @@
#include "base/time/time.h"
#include "chrome/browser/apps/app_service/dip_px_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/borealis/borealis_features_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_features.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h"
......@@ -568,7 +569,9 @@ GuestOsRegistryService::GetEnabledApps() const {
crostini::CrostiniFeatures::Get()->IsEnabled(profile_);
bool plugin_vm_enabled =
plugin_vm::PluginVmFeatures::Get()->IsEnabled(profile_);
if (!crostini_enabled && !plugin_vm_enabled)
bool borealis_enabled =
borealis::BorealisFeaturesFactory::GetForProfile(profile_)->IsEnabled();
if (!crostini_enabled && !plugin_vm_enabled && !borealis_enabled)
return {};
auto apps = GetAllRegisteredApps();
......@@ -581,6 +584,9 @@ GuestOsRegistryService::GetEnabledApps() const {
case VmType::ApplicationList_VmType_PLUGIN_VM:
enabled = plugin_vm_enabled;
break;
case VmType::ApplicationList_VmType_BOREALIS:
enabled = borealis_enabled;
break;
default:
LOG(ERROR) << "Unsupported VmType: "
<< static_cast<int>(it->second.VmType());
......@@ -632,7 +638,9 @@ void GuestOsRegistryService::RecordStartupMetrics() {
crostini::CrostiniFeatures::Get()->IsEnabled(profile_);
bool plugin_vm_enabled =
plugin_vm::PluginVmFeatures::Get()->IsEnabled(profile_);
if (!crostini_enabled && !plugin_vm_enabled)
bool borealis_enabled =
borealis::BorealisFeaturesFactory::GetForProfile(profile_)->IsEnabled();
if (!crostini_enabled && !plugin_vm_enabled && !borealis_enabled)
return;
int num_crostini_apps = 0;
......@@ -667,6 +675,8 @@ void GuestOsRegistryService::RecordStartupMetrics() {
if (plugin_vm_enabled)
UMA_HISTOGRAM_COUNTS_1000(kPluginVmAppsInstalledHistogram,
num_plugin_vm_apps);
// TODO(b/166691285): borealis launch metrics.
}
base::FilePath GuestOsRegistryService::GetAppPath(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment