blob: 1dc48d9f585bd7d614c5ef4e353da0d8ae44f654 [file] [log] [blame]
// Copyright 2016 The Fuchsia 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 "peridot/bin/basemgr/user_controller_impl.h"
#include <memory>
#include <utility>
#include <lib/fidl/cpp/synchronous_interface_ptr.h>
#include "peridot/lib/common/async_holder.h"
#include "peridot/lib/common/names.h"
#include "peridot/lib/common/teardown.h"
#include "peridot/lib/fidl/array_to_string.h"
namespace modular {
UserControllerImpl::UserControllerImpl(
fuchsia::sys::Launcher* const launcher,
fuchsia::modular::AppConfig sessionmgr,
fuchsia::modular::AppConfig session_shell,
fuchsia::modular::AppConfig story_shell,
fidl::InterfaceHandle<fuchsia::auth::TokenManager> ledger_token_manager,
fidl::InterfaceHandle<fuchsia::auth::TokenManager> agent_token_manager,
fuchsia::modular::auth::AccountPtr account,
fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner>
view_owner_request,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> base_shell_services,
fidl::InterfaceRequest<fuchsia::modular::UserController>
user_controller_request,
DoneCallback done)
: user_context_binding_(this),
user_controller_binding_(this, std::move(user_controller_request)),
base_shell_services_(base_shell_services ? base_shell_services.Bind()
: nullptr),
done_(std::move(done)) {
// 0. Generate the path to map '/data' for the sessionmgr we are starting.
std::string data_origin;
if (!account) {
// Guest user.
// Generate a random number to be used in this case.
uint32_t random_number = 0;
zx_cprng_draw(&random_number, sizeof random_number);
data_origin = std::string("/data/modular/USER_GUEST_") +
std::to_string(random_number);
} else {
// Non-guest user.
data_origin = std::string("/data/modular/USER_") + std::string(account->id);
}
FXL_LOG(INFO) << "SESSIONMGR DATA ORIGIN IS " << data_origin;
// 1. Launch Sessionmgr in the current environment.
sessionmgr_app_ = std::make_unique<AppClient<fuchsia::modular::Lifecycle>>(
launcher, std::move(sessionmgr), data_origin);
// 2. Initialize the Sessionmgr service.
sessionmgr_app_->services().ConnectToService(sessionmgr_.NewRequest());
sessionmgr_->Initialize(
std::move(account), std::move(session_shell), std::move(story_shell),
std::move(ledger_token_manager), std::move(agent_token_manager),
user_context_binding_.NewBinding(), std::move(view_owner_request));
sessionmgr_app_->SetAppErrorHandler([this] {
FXL_LOG(ERROR) << "Sessionmgr seems to have crashed unexpectedly. "
<< "Calling done_().";
// This prevents us from receiving any further requests.
user_controller_binding_.Unbind();
user_context_binding_.Unbind();
// Logout(), which expects a graceful shutdown of sessionmgr, does not
// apply here because sessionmgr crashed. Just run |done_| directly.
done_(this);
});
}
// |fuchsia::modular::UserController|
void UserControllerImpl::Logout(LogoutCallback done) {
FXL_LOG(INFO) << "fuchsia::modular::UserController::Logout()";
logout_response_callbacks_.push_back(done);
if (logout_response_callbacks_.size() > 1) {
return;
}
// This should prevent us from receiving any further requests.
user_controller_binding_.Unbind();
user_context_binding_.Unbind();
sessionmgr_app_->Teardown(kSessionmgrTimeout, [this] {
for (const auto& done : logout_response_callbacks_) {
done();
}
// We announce |OnLogout| only at point just before deleting ourselves,
// so we can avoid any race conditions that may be triggered by |Shutdown|
// (which in-turn will call this |Logout| since we have not completed yet).
for (auto& watcher : user_watchers_.ptrs()) {
(*watcher)->OnLogout();
}
done_(this);
});
}
// |UserContext|
void UserControllerImpl::GetPresentation(
fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> request) {
if (base_shell_services_) {
base_shell_services_->ConnectToService(kPresentationService,
request.TakeChannel());
}
}
FuturePtr<> UserControllerImpl::SwapSessionShell(
fuchsia::modular::AppConfig session_shell_config) {
auto future = Future<>::Create("SwapSessionShell");
SwapSessionShell(std::move(session_shell_config), future->Completer());
return future;
}
// |fuchsia::modular::UserController|
void UserControllerImpl::SwapSessionShell(
fuchsia::modular::AppConfig session_shell_config,
SwapSessionShellCallback callback) {
sessionmgr_->SwapSessionShell(std::move(session_shell_config), callback);
}
// |fuchsia::modular::UserController|
void UserControllerImpl::Watch(
fidl::InterfaceHandle<fuchsia::modular::UserWatcher> watcher) {
user_watchers_.AddInterfacePtr(watcher.Bind());
}
// |UserContext|
// TODO(alhaad): Reconcile UserContext.Logout() and UserControllerImpl.Logout().
void UserControllerImpl::Logout() {
FXL_LOG(INFO) << "UserContext::Logout()";
Logout([] {});
}
} // namespace modular