// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/components/arc/session/arc_container_client_adapter.h"
#include <string>
#include <utility>
#include "ash/components/arc/session/arc_session.h"
#include "ash/components/arc/session/arc_upgrade_params.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/task/single_thread_task_runner.h"
#include "chromeos/ash/components/cryptohome/cryptohome_parameters.h"
#include "chromeos/ash/components/dbus/arc/arc.pb.h"
#include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
#include "chromeos/dbus/common/dbus_callback.h"
namespace arc {
namespace {
// Converts PackageCacheMode into login_manager's.
UpgradeArcContainerRequest_PackageCacheMode ToLoginManagerPackageCacheMode(
UpgradeParams::PackageCacheMode mode) {
switch (mode) {
case UpgradeParams::PackageCacheMode::DEFAULT:
return UpgradeArcContainerRequest_PackageCacheMode_DEFAULT;
case UpgradeParams::PackageCacheMode::COPY_ON_INIT:
return UpgradeArcContainerRequest_PackageCacheMode_COPY_ON_INIT;
case UpgradeParams::PackageCacheMode::SKIP_SETUP_COPY_ON_INIT:
return UpgradeArcContainerRequest_PackageCacheMode_SKIP_SETUP_COPY_ON_INIT;
}
}
// Converts ArcManagementTransition into login_manager's.
UpgradeArcContainerRequest_ManagementTransition
ToLoginManagerManagementTransition(ArcManagementTransition transition) {
switch (transition) {
case ArcManagementTransition::NO_TRANSITION:
return UpgradeArcContainerRequest_ManagementTransition_NONE;
case ArcManagementTransition::CHILD_TO_REGULAR:
return UpgradeArcContainerRequest_ManagementTransition_CHILD_TO_REGULAR;
case ArcManagementTransition::REGULAR_TO_CHILD:
return UpgradeArcContainerRequest_ManagementTransition_REGULAR_TO_CHILD;
case ArcManagementTransition::UNMANAGED_TO_MANAGED:
return UpgradeArcContainerRequest_ManagementTransition_UNMANAGED_TO_MANAGED;
}
}
} // namespace
class ArcContainerClientAdapter : public ArcClientAdapter,
public ash::SessionManagerClient::Observer {
public:
ArcContainerClientAdapter() {
if (ash::SessionManagerClient::Get())
ash::SessionManagerClient::Get()->AddObserver(this);
}
ArcContainerClientAdapter(const ArcContainerClientAdapter&) = delete;
ArcContainerClientAdapter& operator=(const ArcContainerClientAdapter&) =
delete;
~ArcContainerClientAdapter() override {
if (ash::SessionManagerClient::Get())
ash::SessionManagerClient::Get()->RemoveObserver(this);
}
// ArcClientAdapter overrides:
void StartMiniArc(StartParams params,
chromeos::VoidDBusMethodCallback callback) override {
auto request =
ArcClientAdapter::ConvertStartParamsToStartArcMiniInstanceRequest(
std::move(params));
ash::SessionManagerClient::Get()->StartArcMiniContainer(
request, std::move(callback));
}
UpgradeArcContainerRequest ConvertUpgradeParamsToUpgradeArcContainerRequest(
UpgradeParams params) {
UpgradeArcContainerRequest request;
request.set_account_id(params.account_id);
request.set_is_account_managed(params.is_account_managed);
request.set_is_managed_adb_sideloading_allowed(
params.is_managed_adb_sideloading_allowed);
request.set_skip_boot_completed_broadcast(
params.skip_boot_completed_broadcast);
request.set_packages_cache_mode(
ToLoginManagerPackageCacheMode(params.packages_cache_mode));
request.set_skip_gms_core_cache(params.skip_gms_core_cache);
request.set_skip_tts_cache(params.skip_tts_cache);
request.set_is_demo_session(params.is_demo_session);
request.set_demo_session_apps_path(params.demo_session_apps_path.value());
request.set_locale(params.locale);
request.set_enable_arc_nearby_share(params.enable_arc_nearby_share);
for (const auto& language : params.preferred_languages)
request.add_preferred_languages(language);
request.set_management_transition(
ToLoginManagerManagementTransition(params.management_transition));
return request;
}
void UpgradeArc(UpgradeParams params,
chromeos::VoidDBusMethodCallback callback) override {
auto request = ConvertUpgradeParamsToUpgradeArcContainerRequest(params);
ash::SessionManagerClient::Get()->UpgradeArcContainer(request,
std::move(callback));
}
void StopArcInstance(bool on_shutdown, bool should_backup_log) override {
// Since we have the ArcInstanceStopped() callback, we don't need to do
// anything when StopArcInstance completes.
ash::SessionManagerClient::Get()->StopArcInstance(
cryptohome_id_.id(), should_backup_log, base::DoNothing());
}
void SetUserInfo(const cryptohome::Identification& cryptohome_id,
const std::string& hash,
const std::string& serial_number) override {
DCHECK(cryptohome_id_.id().empty());
if (cryptohome_id.id().empty())
LOG(WARNING) << "cryptohome_id is empty";
cryptohome_id_ = cryptohome_id;
}
// ArcContainerClientAdapter gets the demo session apps path from
// UpgradeParams, so it does not use the DemoModeDelegate.
void SetDemoModeDelegate(DemoModeDelegate* delegate) override {}
// The interface is only for ARCVM.
void TrimVmMemory(TrimVmMemoryCallback callback, int) override {
NOTREACHED();
}
// ash::SessionManagerClient::Observer overrides:
void ArcInstanceStopped(
login_manager::ArcContainerStopReason reason) override {
const bool is_system_shutdown =
reason ==
login_manager::ArcContainerStopReason::SESSION_MANAGER_SHUTDOWN;
for (auto& observer : observer_list_)
observer.ArcInstanceStopped(is_system_shutdown);
}
private:
// A cryptohome ID of the primary profile.
cryptohome::Identification cryptohome_id_;
};
std::unique_ptr<ArcClientAdapter> CreateArcContainerClientAdapter() {
return std::make_unique<ArcContainerClientAdapter>();
}
} // namespace arc