Commit 4ad97088 authored by Joel Hockey's avatar Joel Hockey Committed by Commit Bot

Register PluginVM apps separate to crostini

Refactor CrostiniApps and GuestOsRegistryService so that PluginVM apps
are registered as type PluginVm by PluginVmApps.

When I recently changed the icon handling, it was a mistake to register
PluginVM apps as crostini.

Bug: b/158617133
Change-Id: I0877e75b9b087c6ece34cbe8642399b5cc2764c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2379407Reviewed-by: default avatarNancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarTimothy Loh <timloh@chromium.org>
Commit-Queue: Joel Hockey <joelhockey@chromium.org>
Cr-Commit-Position: refs/heads/master@{#802940}
parent 68216b08
...@@ -111,15 +111,15 @@ void CrostiniApps::Connect( ...@@ -111,15 +111,15 @@ void CrostiniApps::Connect(
mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote, mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
apps::mojom::ConnectOptionsPtr opts) { apps::mojom::ConnectOptionsPtr opts) {
std::vector<apps::mojom::AppPtr> apps; std::vector<apps::mojom::AppPtr> apps;
// Register all apps with app service. We will only show termina apps in
// launcher, shelf, etc, but app service will manage icons for all apps which for (const auto& pair :
// can appear in FilesApp open-with. registry_->GetRegisteredApps(guest_os::GuestOsRegistryService::VmType::
for (const auto& pair : registry_->GetAllRegisteredApps()) { ApplicationList_VmType_TERMINA)) {
const std::string& app_id = pair.first;
const guest_os::GuestOsRegistryService::Registration& registration = const guest_os::GuestOsRegistryService::Registration& registration =
pair.second; pair.second;
apps.push_back(Convert(app_id, registration, true)); apps.push_back(Convert(registration, /*new_icon_key=*/true));
} }
mojo::Remote<apps::mojom::Subscriber> subscriber( mojo::Remote<apps::mojom::Subscriber> subscriber(
std::move(subscriber_remote)); std::move(subscriber_remote));
subscriber->OnApps(std::move(apps)); subscriber->OnApps(std::move(apps));
...@@ -132,34 +132,9 @@ void CrostiniApps::LoadIcon(const std::string& app_id, ...@@ -132,34 +132,9 @@ void CrostiniApps::LoadIcon(const std::string& app_id,
int32_t size_hint_in_dip, int32_t size_hint_in_dip,
bool allow_placeholder_icon, bool allow_placeholder_icon,
LoadIconCallback callback) { LoadIconCallback callback) {
if (icon_key) { registry_->LoadIcon(app_id, std::move(icon_key), icon_type, size_hint_in_dip,
if (icon_key->resource_id != apps::mojom::IconKey::kInvalidResourceId) { allow_placeholder_icon, IDR_LOGO_CROSTINI_DEFAULT_192,
// The icon is a resource built into the Chrome OS binary.
constexpr bool is_placeholder_icon = false;
LoadIconFromResource(icon_type, size_hint_in_dip, icon_key->resource_id,
is_placeholder_icon,
static_cast<IconEffects>(icon_key->icon_effects),
std::move(callback)); std::move(callback));
return;
} else {
auto scale_factor = apps_util::GetPrimaryDisplayUIScaleFactor();
// Try loading the icon from an on-disk cache. If that fails, fall back
// to LoadIconFromVM.
LoadIconFromFileWithFallback(
icon_type, size_hint_in_dip,
registry_->GetIconPath(app_id, scale_factor),
static_cast<IconEffects>(icon_key->icon_effects), std::move(callback),
base::BindOnce(&CrostiniApps::LoadIconFromVM,
weak_ptr_factory_.GetWeakPtr(), app_id, icon_type,
size_hint_in_dip, scale_factor,
static_cast<IconEffects>(icon_key->icon_effects)));
return;
}
}
// On failure, we still run the callback, with the zero IconValue.
std::move(callback).Run(apps::mojom::IconValue::New());
} }
void CrostiniApps::Launch(const std::string& app_id, void CrostiniApps::Launch(const std::string& app_id,
...@@ -231,17 +206,31 @@ void CrostiniApps::GetMenuModel(const std::string& app_id, ...@@ -231,17 +206,31 @@ void CrostiniApps::GetMenuModel(const std::string& app_id,
void CrostiniApps::OnRegistryUpdated( void CrostiniApps::OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service, guest_os::GuestOsRegistryService* registry_service,
guest_os::GuestOsRegistryService::VmType vm_type,
const std::vector<std::string>& updated_apps, const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps, const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) { const std::vector<std::string>& inserted_apps) {
if (vm_type != guest_os::GuestOsRegistryService::VmType::
ApplicationList_VmType_TERMINA) {
return;
}
for (const std::string& app_id : updated_apps) { for (const std::string& app_id : updated_apps) {
PublishAppID(app_id, PublishAppIDType::kUpdate); if (auto registration = registry_->GetRegistration(app_id)) {
Publish(Convert(*registration, /*new_icon_key=*/false), subscribers_);
}
} }
for (const std::string& app_id : removed_apps) { for (const std::string& app_id : removed_apps) {
PublishAppID(app_id, PublishAppIDType::kUninstall); apps::mojom::AppPtr app = apps::mojom::App::New();
app->app_type = apps::mojom::AppType::kCrostini;
app->app_id = app_id;
app->readiness = apps::mojom::Readiness::kUninstalledByUser;
Publish(std::move(app), subscribers_);
} }
for (const std::string& app_id : inserted_apps) { for (const std::string& app_id : inserted_apps) {
PublishAppID(app_id, PublishAppIDType::kInstall); if (auto registration = registry_->GetRegistration(app_id)) {
Publish(Convert(*registration, /*new_icon_key=*/true), subscribers_);
}
} }
} }
...@@ -262,53 +251,13 @@ void CrostiniApps::OnCrostiniEnabledChanged() { ...@@ -262,53 +251,13 @@ void CrostiniApps::OnCrostiniEnabledChanged() {
Publish(std::move(app), subscribers_); Publish(std::move(app), subscribers_);
} }
void CrostiniApps::LoadIconFromVM(const std::string app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
ui::ScaleFactor scale_factor,
IconEffects icon_effects,
LoadIconCallback callback) {
registry_->RequestIcon(
app_id, scale_factor,
base::BindOnce(&CrostiniApps::OnLoadIconFromVM,
weak_ptr_factory_.GetWeakPtr(), app_id, icon_type,
size_hint_in_dip, icon_effects, std::move(callback)));
}
void CrostiniApps::OnLoadIconFromVM(const std::string app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
IconEffects icon_effects,
LoadIconCallback callback,
std::string compressed_icon_data) {
if (compressed_icon_data.empty()) {
auto registration = registry_->GetRegistration(app_id);
if (crostini::IsUnmatchedCrostiniShelfAppId(app_id) ||
(registration && registration->VmType() ==
guest_os::GuestOsRegistryService::VmType::
ApplicationList_VmType_TERMINA)) {
// Load default penguin for crostini. We must set is_placeholder_icon to
// false to stop endless recursive calls.
LoadIconFromResource(
icon_type, size_hint_in_dip, IDR_LOGO_CROSTINI_DEFAULT_192,
/*is_placeholder_icon=*/false, icon_effects, std::move(callback));
} else {
// Leave it for app service to get a default for Plugin VM.
std::move(callback).Run(apps::mojom::IconValue::New());
}
} else {
LoadIconFromCompressedData(icon_type, size_hint_in_dip, icon_effects,
compressed_icon_data, std::move(callback));
}
}
apps::mojom::AppPtr CrostiniApps::Convert( apps::mojom::AppPtr CrostiniApps::Convert(
const std::string& app_id,
const guest_os::GuestOsRegistryService::Registration& registration, const guest_os::GuestOsRegistryService::Registration& registration,
bool new_icon_key) { bool new_icon_key) {
apps::mojom::AppPtr app = PublisherBase::MakeApp( apps::mojom::AppPtr app = PublisherBase::MakeApp(
apps::mojom::AppType::kCrostini, app_id, apps::mojom::Readiness::kReady, apps::mojom::AppType::kCrostini, registration.app_id(),
registration.Name(), apps::mojom::InstallSource::kUser); apps::mojom::Readiness::kReady, registration.Name(),
apps::mojom::InstallSource::kUser);
const std::string& executable_file_name = registration.ExecutableFileName(); const std::string& executable_file_name = registration.ExecutableFileName();
if (!executable_file_name.empty()) { if (!executable_file_name.empty()) {
...@@ -319,7 +268,7 @@ apps::mojom::AppPtr CrostiniApps::Convert( ...@@ -319,7 +268,7 @@ apps::mojom::AppPtr CrostiniApps::Convert(
} }
if (new_icon_key) { if (new_icon_key) {
app->icon_key = NewIconKey(app_id); app->icon_key = NewIconKey(registration.app_id());
} }
app->last_launch_time = registration.LastLaunchTime(); app->last_launch_time = registration.LastLaunchTime();
...@@ -372,23 +321,4 @@ apps::mojom::IconKeyPtr CrostiniApps::NewIconKey(const std::string& app_id) { ...@@ -372,23 +321,4 @@ apps::mojom::IconKeyPtr CrostiniApps::NewIconKey(const std::string& app_id) {
return icon_key_factory_.MakeIconKey(icon_effects); return icon_key_factory_.MakeIconKey(icon_effects);
} }
void CrostiniApps::PublishAppID(const std::string& app_id,
PublishAppIDType type) {
if (type == PublishAppIDType::kUninstall) {
apps::mojom::AppPtr app = apps::mojom::App::New();
app->app_type = apps::mojom::AppType::kCrostini;
app->app_id = app_id;
app->readiness = apps::mojom::Readiness::kUninstalledByUser;
Publish(std::move(app), subscribers_);
return;
}
base::Optional<guest_os::GuestOsRegistryService::Registration> registration =
registry_->GetRegistration(app_id);
if (registration.has_value()) {
Publish(Convert(app_id, *registration, type == PublishAppIDType::kInstall),
subscribers_);
}
}
} // namespace apps } // namespace apps
...@@ -42,12 +42,6 @@ class CrostiniApps : public KeyedService, ...@@ -42,12 +42,6 @@ class CrostiniApps : public KeyedService,
Profile* profile); Profile* profile);
private: private:
enum class PublishAppIDType {
kInstall,
kUninstall,
kUpdate,
};
void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service); void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service);
// apps::mojom::Publisher overrides. // apps::mojom::Publisher overrides.
...@@ -75,6 +69,7 @@ class CrostiniApps : public KeyedService, ...@@ -75,6 +69,7 @@ class CrostiniApps : public KeyedService,
// GuestOsRegistryService::Observer overrides. // GuestOsRegistryService::Observer overrides.
void OnRegistryUpdated( void OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service, guest_os::GuestOsRegistryService* registry_service,
guest_os::GuestOsRegistryService::VmType vm_type,
const std::vector<std::string>& updated_apps, const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps, const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) override; const std::vector<std::string>& inserted_apps) override;
...@@ -84,26 +79,10 @@ class CrostiniApps : public KeyedService, ...@@ -84,26 +79,10 @@ class CrostiniApps : public KeyedService,
// once it can support hiding apps. // once it can support hiding apps.
void OnCrostiniEnabledChanged(); void OnCrostiniEnabledChanged();
void LoadIconFromVM(const std::string app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
ui::ScaleFactor scale_factor,
IconEffects icon_effects,
LoadIconCallback callback);
void OnLoadIconFromVM(const std::string app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
IconEffects icon_effects,
LoadIconCallback callback,
std::string compressed_icon_data);
apps::mojom::AppPtr Convert( apps::mojom::AppPtr Convert(
const std::string& app_id,
const guest_os::GuestOsRegistryService::Registration& registration, const guest_os::GuestOsRegistryService::Registration& registration,
bool new_icon_key); bool new_icon_key);
apps::mojom::IconKeyPtr NewIconKey(const std::string& app_id); apps::mojom::IconKeyPtr NewIconKey(const std::string& app_id);
void PublishAppID(const std::string& app_id, PublishAppIDType type);
mojo::RemoteSet<apps::mojom::Subscriber> subscribers_; mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/app_management/app_management.mojom.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/chrome_unscaled_resources.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
...@@ -138,7 +139,7 @@ namespace apps { ...@@ -138,7 +139,7 @@ namespace apps {
PluginVmApps::PluginVmApps( PluginVmApps::PluginVmApps(
const mojo::Remote<apps::mojom::AppService>& app_service, const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile) Profile* profile)
: profile_(profile), permissions_observer_(this) { : profile_(profile), registry_(nullptr), permissions_observer_(this) {
// Don't show anything for non-primary profiles. We can't use // Don't show anything for non-primary profiles. We can't use
// `IsPluginVmAllowedForProfile()` here because we still let the user // `IsPluginVmAllowedForProfile()` here because we still let the user
// uninstall Plugin VM when it isn't allowed for some other reasons (e.g. // uninstall Plugin VM when it isn't allowed for some other reasons (e.g.
...@@ -147,6 +148,12 @@ PluginVmApps::PluginVmApps( ...@@ -147,6 +148,12 @@ PluginVmApps::PluginVmApps(
return; return;
} }
registry_ = guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile_);
if (!registry_) {
return;
}
registry_->AddObserver(this);
PublisherBase::Initialize(app_service, apps::mojom::AppType::kPluginVm); PublisherBase::Initialize(app_service, apps::mojom::AppType::kPluginVm);
// Register for Plugin VM changes to policy and installed state, so that we // Register for Plugin VM changes to policy and installed state, so that we
...@@ -169,7 +176,11 @@ PluginVmApps::PluginVmApps( ...@@ -169,7 +176,11 @@ PluginVmApps::PluginVmApps(
} }
} }
PluginVmApps::~PluginVmApps() = default; PluginVmApps::~PluginVmApps() {
if (registry_) {
registry_->RemoveObserver(this);
}
}
void PluginVmApps::Connect( void PluginVmApps::Connect(
mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote, mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote,
...@@ -177,6 +188,14 @@ void PluginVmApps::Connect( ...@@ -177,6 +188,14 @@ void PluginVmApps::Connect(
std::vector<apps::mojom::AppPtr> apps; std::vector<apps::mojom::AppPtr> apps;
apps.push_back(GetPluginVmApp(profile_, is_allowed_)); apps.push_back(GetPluginVmApp(profile_, is_allowed_));
for (const auto& pair :
registry_->GetRegisteredApps(guest_os::GuestOsRegistryService::VmType::
ApplicationList_VmType_PLUGIN_VM)) {
const guest_os::GuestOsRegistryService::Registration& registration =
pair.second;
apps.push_back(Convert(registration, /*new_icon_key=*/true));
}
mojo::Remote<apps::mojom::Subscriber> subscriber( mojo::Remote<apps::mojom::Subscriber> subscriber(
std::move(subscriber_remote)); std::move(subscriber_remote));
subscriber->OnApps(std::move(apps)); subscriber->OnApps(std::move(apps));
...@@ -189,16 +208,10 @@ void PluginVmApps::LoadIcon(const std::string& app_id, ...@@ -189,16 +208,10 @@ void PluginVmApps::LoadIcon(const std::string& app_id,
int32_t size_hint_in_dip, int32_t size_hint_in_dip,
bool allow_placeholder_icon, bool allow_placeholder_icon,
LoadIconCallback callback) { LoadIconCallback callback) {
constexpr bool is_placeholder_icon = false; registry_->LoadIcon(app_id, std::move(icon_key), icon_type, size_hint_in_dip,
if (icon_key && allow_placeholder_icon,
(icon_key->resource_id != apps::mojom::IconKey::kInvalidResourceId)) { apps::mojom::IconKey::kInvalidResourceId,
LoadIconFromResource( std::move(callback));
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());
} }
void PluginVmApps::Launch(const std::string& app_id, void PluginVmApps::Launch(const std::string& app_id,
...@@ -268,6 +281,63 @@ void PluginVmApps::GetMenuModel(const std::string& app_id, ...@@ -268,6 +281,63 @@ void PluginVmApps::GetMenuModel(const std::string& app_id,
std::move(callback).Run(std::move(menu_items)); std::move(callback).Run(std::move(menu_items));
} }
void PluginVmApps::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_PLUGIN_VM) {
return;
}
for (const std::string& app_id : updated_apps) {
if (auto registration = registry_->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::kPluginVm;
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_->GetRegistration(app_id)) {
Publish(Convert(*registration, /*new_icon_key=*/true), subscribers_);
}
}
}
apps::mojom::AppPtr PluginVmApps::Convert(
const guest_os::GuestOsRegistryService::Registration& registration,
bool new_icon_key) {
apps::mojom::AppPtr app = PublisherBase::MakeApp(
apps::mojom::AppType::kPluginVm, registration.app_id(),
apps::mojom::Readiness::kReady, registration.Name(),
apps::mojom::InstallSource::kUser);
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();
app->show_in_launcher = apps::mojom::OptionalBool::kFalse;
app->show_in_search = apps::mojom::OptionalBool::kFalse;
app->show_in_shelf = apps::mojom::OptionalBool::kFalse;
app->show_in_management = apps::mojom::OptionalBool::kFalse;
return app;
}
void PluginVmApps::OnPluginVmAllowedChanged(bool is_allowed) { void PluginVmApps::OnPluginVmAllowedChanged(bool is_allowed) {
// Republish the Plugin VM app when policy changes have changed // Republish the Plugin VM app when policy changes have changed
// its availability. Only changed fields need to be republished. // its availability. Only changed fields need to be republished.
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <string> #include <string>
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "chrome/browser/apps/app_service/icon_key_util.h"
#include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
#include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager.h"
#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
#include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_change_registrar.h"
...@@ -27,7 +29,8 @@ namespace apps { ...@@ -27,7 +29,8 @@ namespace apps {
// //
// See components/services/app_service/README.md. // See components/services/app_service/README.md.
class PluginVmApps : public apps::PublisherBase, class PluginVmApps : public apps::PublisherBase,
public plugin_vm::PluginVmPermissionsObserver { public plugin_vm::PluginVmPermissionsObserver,
public guest_os::GuestOsRegistryService::Observer {
public: public:
PluginVmApps(const mojo::Remote<apps::mojom::AppService>& app_service, PluginVmApps(const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile); Profile* profile);
...@@ -61,6 +64,17 @@ class PluginVmApps : public apps::PublisherBase, ...@@ -61,6 +64,17 @@ class PluginVmApps : public apps::PublisherBase,
int64_t display_id, int64_t display_id,
GetMenuModelCallback callback) override; 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;
apps::mojom::AppPtr Convert(
const guest_os::GuestOsRegistryService::Registration& registration,
bool new_icon_key);
void OnPluginVmAllowedChanged(bool is_allowed); void OnPluginVmAllowedChanged(bool is_allowed);
void OnPluginVmConfiguredChanged(); void OnPluginVmConfiguredChanged();
// plugin_vm::PluginVmPermissionsObserver // plugin_vm::PluginVmPermissionsObserver
...@@ -70,6 +84,9 @@ class PluginVmApps : public apps::PublisherBase, ...@@ -70,6 +84,9 @@ class PluginVmApps : public apps::PublisherBase,
mojo::RemoteSet<apps::mojom::Subscriber> subscribers_; mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
Profile* const profile_; Profile* const profile_;
guest_os::GuestOsRegistryService* registry_;
apps_util::IncrementingIconKeyFactory icon_key_factory_;
// Whether the Plugin VM app is allowed by policy. // Whether the Plugin VM app is allowed by policy.
bool is_allowed_; bool is_allowed_;
......
...@@ -96,9 +96,14 @@ PackageOperationStatus CrostiniPackageNotification::GetOperationStatus() const { ...@@ -96,9 +96,14 @@ PackageOperationStatus CrostiniPackageNotification::GetOperationStatus() const {
void CrostiniPackageNotification::OnRegistryUpdated( void CrostiniPackageNotification::OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service, guest_os::GuestOsRegistryService* registry_service,
guest_os::GuestOsRegistryService::VmType vm_type,
const std::vector<std::string>& updated_apps, const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps, const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) { const std::vector<std::string>& inserted_apps) {
if (vm_type != guest_os::GuestOsRegistryService::VmType::
ApplicationList_VmType_TERMINA) {
return;
}
inserted_apps_.insert(inserted_apps.begin(), inserted_apps.end()); inserted_apps_.insert(inserted_apps.begin(), inserted_apps.end());
} }
......
...@@ -60,6 +60,7 @@ class CrostiniPackageNotification ...@@ -60,6 +60,7 @@ class CrostiniPackageNotification
// GuestOsRegistryService::Observer: // GuestOsRegistryService::Observer:
void OnRegistryUpdated( void OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service, guest_os::GuestOsRegistryService* registry_service,
guest_os::GuestOsRegistryService::VmType vm_type,
const std::vector<std::string>& updated_apps, const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps, const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) override; const std::vector<std::string>& inserted_apps) override;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/time/clock.h" #include "base/time/clock.h"
#include "base/time/default_clock.h" #include "base/time/default_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/apps/app_service/dip_px_util.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/crostini/crostini_features.h" #include "chrome/browser/chromeos/crostini/crostini_features.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h"
...@@ -668,6 +669,86 @@ base::FilePath GuestOsRegistryService::GetIconPath( ...@@ -668,6 +669,86 @@ base::FilePath GuestOsRegistryService::GetIconPath(
} }
} }
void GuestOsRegistryService::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,
int fallback_icon_resource_id,
apps::mojom::Publisher::LoadIconCallback callback) {
if (icon_key) {
if (icon_key->resource_id != apps::mojom::IconKey::kInvalidResourceId) {
// The icon is a resource built into the Chrome OS binary.
constexpr bool is_placeholder_icon = false;
apps::LoadIconFromResource(
icon_type, size_hint_in_dip, icon_key->resource_id,
is_placeholder_icon,
static_cast<apps::IconEffects>(icon_key->icon_effects),
std::move(callback));
return;
} else {
auto scale_factor = apps_util::GetPrimaryDisplayUIScaleFactor();
// Try loading the icon from an on-disk cache. If that fails, fall back
// to LoadIconFromVM.
apps::LoadIconFromFileWithFallback(
icon_type, size_hint_in_dip, GetIconPath(app_id, scale_factor),
static_cast<apps::IconEffects>(icon_key->icon_effects),
std::move(callback),
base::BindOnce(&GuestOsRegistryService::LoadIconFromVM,
weak_ptr_factory_.GetWeakPtr(), app_id, icon_type,
size_hint_in_dip, scale_factor,
static_cast<apps::IconEffects>(icon_key->icon_effects),
fallback_icon_resource_id));
return;
}
}
// On failure, we still run the callback, with the zero IconValue.
std::move(callback).Run(apps::mojom::IconValue::New());
}
void GuestOsRegistryService::LoadIconFromVM(
const std::string& app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
ui::ScaleFactor scale_factor,
apps::IconEffects icon_effects,
int fallback_icon_resource_id,
apps::mojom::Publisher::LoadIconCallback callback) {
RequestIcon(app_id, scale_factor,
base::BindOnce(&GuestOsRegistryService::OnLoadIconFromVM,
weak_ptr_factory_.GetWeakPtr(), app_id, icon_type,
size_hint_in_dip, icon_effects,
fallback_icon_resource_id, std::move(callback)));
}
void GuestOsRegistryService::OnLoadIconFromVM(
const std::string& app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
apps::IconEffects icon_effects,
int fallback_icon_resource_id,
apps::mojom::Publisher::LoadIconCallback callback,
std::string compressed_icon_data) {
if (compressed_icon_data.empty()) {
if (fallback_icon_resource_id != apps::mojom::IconKey::kInvalidResourceId) {
// We load the fallback icon, but we tell AppsService that this is not
// a placeholder to avoid endless repeat calls since we don't expect to
// find a better icon than this any time soon.
apps::LoadIconFromResource(
icon_type, size_hint_in_dip, fallback_icon_resource_id,
/*is_placeholder_icon=*/false, icon_effects, std::move(callback));
} else {
std::move(callback).Run(apps::mojom::IconValue::New());
}
} else {
apps::LoadIconFromCompressedData(icon_type, size_hint_in_dip, icon_effects,
compressed_icon_data, std::move(callback));
}
}
void GuestOsRegistryService::RequestIcon( void GuestOsRegistryService::RequestIcon(
const std::string& app_id, const std::string& app_id,
ui::ScaleFactor scale_factor, ui::ScaleFactor scale_factor,
...@@ -724,8 +805,10 @@ void GuestOsRegistryService::ClearApplicationList( ...@@ -724,8 +805,10 @@ void GuestOsRegistryService::ClearApplicationList(
std::vector<std::string> updated_apps; std::vector<std::string> updated_apps;
std::vector<std::string> inserted_apps; std::vector<std::string> inserted_apps;
for (Observer& obs : observers_) for (Observer& obs : observers_) {
obs.OnRegistryUpdated(this, updated_apps, removed_apps, inserted_apps); obs.OnRegistryUpdated(this, vm_type, updated_apps, removed_apps,
inserted_apps);
}
} }
void GuestOsRegistryService::UpdateApplicationList( void GuestOsRegistryService::UpdateApplicationList(
...@@ -839,8 +922,10 @@ void GuestOsRegistryService::UpdateApplicationList( ...@@ -839,8 +922,10 @@ void GuestOsRegistryService::UpdateApplicationList(
if (updated_apps.empty() && removed_apps.empty() && inserted_apps.empty()) if (updated_apps.empty() && removed_apps.empty() && inserted_apps.empty())
return; return;
for (Observer& obs : observers_) for (Observer& obs : observers_) {
obs.OnRegistryUpdated(this, updated_apps, removed_apps, inserted_apps); obs.OnRegistryUpdated(this, app_list.vm_type(), updated_apps, removed_apps,
inserted_apps);
}
} }
void GuestOsRegistryService::RemoveAppData(const std::string& app_id) { void GuestOsRegistryService::RemoveAppData(const std::string& app_id) {
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/apps/app_service/app_icon_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_simple_types.h" #include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
#include "chromeos/dbus/vm_applications/apps.pb.h" #include "chromeos/dbus/vm_applications/apps.pb.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "components/services/app_service/public/mojom/app_service.mojom.h"
#include "ui/base/resource/scale_factor.h" #include "ui/base/resource/scale_factor.h"
class Profile; class Profile;
...@@ -116,6 +118,7 @@ class GuestOsRegistryService : public KeyedService { ...@@ -116,6 +118,7 @@ class GuestOsRegistryService : public KeyedService {
// last_launch_time field is updated. // last_launch_time field is updated.
virtual void OnRegistryUpdated( virtual void OnRegistryUpdated(
guest_os::GuestOsRegistryService* registry_service, guest_os::GuestOsRegistryService* registry_service,
VmType vm_type,
const std::vector<std::string>& updated_apps, const std::vector<std::string>& updated_apps,
const std::vector<std::string>& removed_apps, const std::vector<std::string>& removed_apps,
const std::vector<std::string>& inserted_apps) {} const std::vector<std::string>& inserted_apps) {}
...@@ -146,6 +149,36 @@ class GuestOsRegistryService : public KeyedService { ...@@ -146,6 +149,36 @@ class GuestOsRegistryService : public KeyedService {
base::FilePath GetIconPath(const std::string& app_id, base::FilePath GetIconPath(const std::string& app_id,
ui::ScaleFactor scale_factor) const; ui::ScaleFactor scale_factor) const;
// Attempts to load icon in the following order:
// 1/ Loads from resource if |icon_key->resource_id| is valid (non-zero).
// 2/ Looks up file cache.
// 3/ Fetches from VM.
// 4/ Uses |fallback_icon_resource_id| if it is valid (non-zero).
// 5/ Returns empty.
void 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,
int fallback_icon_resource_id,
apps::mojom::Publisher::LoadIconCallback callback);
void LoadIconFromVM(const std::string& app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
ui::ScaleFactor scale_factor,
apps::IconEffects icon_effects,
int fallback_icon_resource_id,
apps::mojom::Publisher::LoadIconCallback callback);
void OnLoadIconFromVM(const std::string& app_id,
apps::mojom::IconType icon_type,
int32_t size_hint_in_dip,
apps::IconEffects icon_effects,
int fallback_icon_resource_id,
apps::mojom::Publisher::LoadIconCallback callback,
std::string compressed_icon_data);
// Fetches icons from container. // Fetches icons from container.
void RequestIcon(const std::string& app_id, void RequestIcon(const std::string& app_id,
ui::ScaleFactor scale_factor, ui::ScaleFactor scale_factor,
......
...@@ -50,8 +50,9 @@ class GuestOsRegistryServiceTest : public testing::Test { ...@@ -50,8 +50,9 @@ class GuestOsRegistryServiceTest : public testing::Test {
class Observer : public GuestOsRegistryService::Observer { class Observer : public GuestOsRegistryService::Observer {
public: public:
MOCK_METHOD4(OnRegistryUpdated, MOCK_METHOD5(OnRegistryUpdated,
void(GuestOsRegistryService*, void(GuestOsRegistryService*,
GuestOsRegistryService::VmType,
const std::vector<std::string>&, const std::vector<std::string>&,
const std::vector<std::string>&, const std::vector<std::string>&,
const std::vector<std::string>&)); const std::vector<std::string>&));
...@@ -170,9 +171,12 @@ TEST_F(GuestOsRegistryServiceTest, Observer) { ...@@ -170,9 +171,12 @@ TEST_F(GuestOsRegistryServiceTest, Observer) {
Observer observer; Observer observer;
service()->AddObserver(&observer); service()->AddObserver(&observer);
EXPECT_CALL(observer, EXPECT_CALL(
observer,
OnRegistryUpdated( OnRegistryUpdated(
service(), testing::IsEmpty(), testing::IsEmpty(), service(),
GuestOsRegistryService::VmType::ApplicationList_VmType_TERMINA,
testing::IsEmpty(), testing::IsEmpty(),
testing::UnorderedElementsAre(app_id_1, app_id_2, app_id_3))); testing::UnorderedElementsAre(app_id_1, app_id_2, app_id_3)));
service()->UpdateApplicationList(app_list); service()->UpdateApplicationList(app_list);
...@@ -181,9 +185,12 @@ TEST_F(GuestOsRegistryServiceTest, Observer) { ...@@ -181,9 +185,12 @@ TEST_F(GuestOsRegistryServiceTest, Observer) {
// Rename name for "app 3" to "banana" // Rename name for "app 3" to "banana"
app_list.mutable_apps(2)->mutable_name()->mutable_values(0)->set_value( app_list.mutable_apps(2)->mutable_name()->mutable_values(0)->set_value(
"banana"); "banana");
EXPECT_CALL(observer, EXPECT_CALL(
OnRegistryUpdated(service(), testing::ElementsAre(app_id_3), observer,
testing::ElementsAre(app_id_2), OnRegistryUpdated(
service(),
GuestOsRegistryService::VmType::ApplicationList_VmType_TERMINA,
testing::ElementsAre(app_id_3), testing::ElementsAre(app_id_2),
testing::ElementsAre(app_id_4))); testing::ElementsAre(app_id_4)));
service()->UpdateApplicationList(app_list); service()->UpdateApplicationList(app_list);
} }
...@@ -199,16 +206,23 @@ TEST_F(GuestOsRegistryServiceTest, ObserverForPvmDefault) { ...@@ -199,16 +206,23 @@ TEST_F(GuestOsRegistryServiceTest, ObserverForPvmDefault) {
service()->AddObserver(&observer); service()->AddObserver(&observer);
// Observers should be called when apps are added or updated. // Observers should be called when apps are added or updated.
EXPECT_CALL(observer, OnRegistryUpdated( EXPECT_CALL(
service(), testing::IsEmpty(), testing::IsEmpty(), observer,
OnRegistryUpdated(
service(),
GuestOsRegistryService::VmType::ApplicationList_VmType_PLUGIN_VM,
testing::IsEmpty(), testing::IsEmpty(),
testing::UnorderedElementsAre(app_id_1))) testing::UnorderedElementsAre(app_id_1)))
.Times(1); .Times(1);
service()->UpdateApplicationList(app_list); service()->UpdateApplicationList(app_list);
// Observers should be called when apps are removed. // Observers should be called when apps are removed.
EXPECT_CALL(observer, EXPECT_CALL(
OnRegistryUpdated(service(), testing::IsEmpty(), observer,
testing::UnorderedElementsAre(app_id_1), OnRegistryUpdated(
service(),
GuestOsRegistryService::VmType::ApplicationList_VmType_PLUGIN_VM,
testing::IsEmpty(), testing::UnorderedElementsAre(app_id_1),
testing::IsEmpty())) testing::IsEmpty()))
.Times(1); .Times(1);
service()->ClearApplicationList( service()->ClearApplicationList(
...@@ -287,8 +301,12 @@ TEST_F(GuestOsRegistryServiceTest, InstallAndLaunchTime) { ...@@ -287,8 +301,12 @@ TEST_F(GuestOsRegistryServiceTest, InstallAndLaunchTime) {
Observer observer; Observer observer;
service()->AddObserver(&observer); service()->AddObserver(&observer);
EXPECT_CALL(observer, OnRegistryUpdated(service(), testing::IsEmpty(), EXPECT_CALL(
testing::IsEmpty(), observer,
OnRegistryUpdated(
service(),
GuestOsRegistryService::VmType::ApplicationList_VmType_TERMINA,
testing::IsEmpty(), testing::IsEmpty(),
testing::ElementsAre(app_id))); testing::ElementsAre(app_id)));
service()->UpdateApplicationList(app_list); service()->UpdateApplicationList(app_list);
...@@ -301,7 +319,7 @@ TEST_F(GuestOsRegistryServiceTest, InstallAndLaunchTime) { ...@@ -301,7 +319,7 @@ TEST_F(GuestOsRegistryServiceTest, InstallAndLaunchTime) {
// UpdateApplicationList with nothing changed. Times shouldn't be updated and // UpdateApplicationList with nothing changed. Times shouldn't be updated and
// the observer shouldn't fire. // the observer shouldn't fire.
test_clock_.Advance(base::TimeDelta::FromHours(1)); test_clock_.Advance(base::TimeDelta::FromHours(1));
EXPECT_CALL(observer, OnRegistryUpdated(_, _, _, _)).Times(0); EXPECT_CALL(observer, OnRegistryUpdated(_, _, _, _, _)).Times(0);
service()->UpdateApplicationList(app_list); service()->UpdateApplicationList(app_list);
result = service()->GetRegistration(app_id); result = service()->GetRegistration(app_id);
EXPECT_EQ(result->InstallTime(), install_time); EXPECT_EQ(result->InstallTime(), install_time);
...@@ -318,9 +336,13 @@ TEST_F(GuestOsRegistryServiceTest, InstallAndLaunchTime) { ...@@ -318,9 +336,13 @@ TEST_F(GuestOsRegistryServiceTest, InstallAndLaunchTime) {
// The install time shouldn't change if fields change. // The install time shouldn't change if fields change.
test_clock_.Advance(base::TimeDelta::FromHours(1)); test_clock_.Advance(base::TimeDelta::FromHours(1));
app_list.mutable_apps(0)->set_no_display(true); app_list.mutable_apps(0)->set_no_display(true);
EXPECT_CALL(observer, EXPECT_CALL(
OnRegistryUpdated(service(), testing::ElementsAre(app_id), observer,
testing::IsEmpty(), testing::IsEmpty())); OnRegistryUpdated(
service(),
GuestOsRegistryService::VmType::ApplicationList_VmType_TERMINA,
testing::ElementsAre(app_id), testing::IsEmpty(),
testing::IsEmpty()));
service()->UpdateApplicationList(app_list); service()->UpdateApplicationList(app_list);
result = service()->GetRegistration(app_id); result = service()->GetRegistration(app_id);
EXPECT_EQ(result->InstallTime(), install_time); EXPECT_EQ(result->InstallTime(), install_time);
......
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