// 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 "src/modular/bin/basemgr/session_context_impl.h"

#include <dirent.h>
#include <fcntl.h>
#include <lib/syslog/cpp/macros.h>

#include <fbl/unique_fd.h>

#include "src/lib/files/directory.h"
#include "src/lib/files/file.h"
#include "src/lib/fsl/io/fd.h"
#include "src/modular/bin/basemgr/cobalt/cobalt.h"
#include "src/modular/lib/common/async_holder.h"
#include "src/modular/lib/common/teardown.h"
#include "src/modular/lib/modular_config/modular_config.h"
#include "src/modular/lib/modular_config/modular_config_constants.h"
#include "src/modular/lib/pseudo_dir/pseudo_dir_utils.h"

namespace modular {

using cobalt_registry::ModularLifetimeEventsMetricDimensionEventType;

namespace {

// The path containing a subdirectory for each session.
constexpr char kSessionDirectoryLocation[] = "/data/modular";

// A standard prefix used on every session directory.
// Note: This is named "USER_" for legacy reasons. SESSION_ may have been more
// appropriate but a change would require a data migration.
constexpr char kSessionDirectoryPrefix[] = "USER_";

// A fixed session ID that is used for new persistent sessions. This is possible
// as basemanager never creates more than a single persistent session per device.
constexpr char kStandardSessionId[] = "0";

// Returns a fully qualified session directory path for |session_id|.
std::string GetSessionDirectory(const std::string& session_id) {
  return std::string(kSessionDirectoryLocation) + "/" + kSessionDirectoryPrefix + session_id;
}

// Returns the session IDs encoded in all existing session directories.
std::vector<std::string> GetExistingSessionIds() {
  std::vector<std::string> dirs;
  if (!files::ReadDirContents(kSessionDirectoryLocation, &dirs)) {
    FX_LOGS(WARNING) << "Could not open session directory location.";
    return std::vector<std::string>();
  }
  std::vector<std::string> output;
  for (const auto& dir : dirs) {
    if (strncmp(dir.c_str(), kSessionDirectoryPrefix, strlen(kSessionDirectoryPrefix)) == 0) {
      auto session_id = dir.substr(strlen(kSessionDirectoryPrefix));
      FX_LOGS(INFO) << "Found existing directory for session " << session_id;
      output.push_back(session_id);
    }
  }
  return output;
}

// Returns a randomly generated session ID and reports the case to cobalt.
std::string GetRandomSessionId() {
  FX_LOGS(INFO) << "Creating session using random ID.";
  ReportEvent(ModularLifetimeEventsMetricDimensionEventType::CreateSessionNewEphemeralAccount);
  uint32_t random_number = 0;
  zx_cprng_draw(&random_number, sizeof random_number);
  return std::to_string(random_number);
}

// Returns a stable session ID, using an ID extracted from the first session
// directory on disk if possible, and a fixed ID if not. The selected case is
// reported to cobalt.
std::string GetStableSessionId() {
  // TODO(fxbug.dev/50300): Once a sufficiently small number of devices are using legacy
  // non-zero session IDs, remove support for sniffing an existing directory and
  // just always use zero.
  auto existing_sessions = GetExistingSessionIds();
  if (existing_sessions.empty()) {
    FX_LOGS(INFO) << "Creating session using new persistent account.";
    ReportEvent(ModularLifetimeEventsMetricDimensionEventType::CreateSessionNewPersistentAccount);
    return kStandardSessionId;
  }

  if (existing_sessions.size() == 1) {
    if (existing_sessions[0] == std::string(kStandardSessionId)) {
      FX_LOGS(INFO) << "Creating session using existing account with fixed ID.";
      ReportEvent(ModularLifetimeEventsMetricDimensionEventType::CreateSessionExistingFixedAccount);
    } else {
      FX_LOGS(INFO) << "Creating session using existing account with legacy non-fixed ID.";
      ReportEvent(
          ModularLifetimeEventsMetricDimensionEventType::CreateSessionExistingPersistentAccount);
    }
    return existing_sessions[0];
  }

  // Walk through all existing sessions looking for the standard session id, which we use if we
  // find it, and the lexicographically minimum session id which we use otherwise.
  std::string lowest_session = existing_sessions[0];
  for (const auto& existing_session : existing_sessions) {
    if (existing_session == std::string(kStandardSessionId)) {
      FX_LOGS(WARNING) << "Creating session using one of multiple existing accounts with fixed ID.";
      ReportEvent(
          ModularLifetimeEventsMetricDimensionEventType::CreateSessionUnverifiableFixedAccount);
      return existing_session;
    }
    if (existing_session < lowest_session) {
      lowest_session = existing_session;
    }
  }
  FX_LOGS(WARNING) << "Creating session by picking the lowest of " << existing_sessions.size()
                   << " existing directories. Fixed ID was not found.";
  ReportEvent(
      ModularLifetimeEventsMetricDimensionEventType::CreateSessionUnverifiablePersistentAccount);
  return lowest_session;
}

}  // namespace

SessionContextImpl::SessionContextImpl(
    fuchsia::sys::Launcher* const launcher,
    fuchsia::modular::session::AppConfig sessionmgr_app_config,
    const modular::ModularConfigAccessor* const config_accessor,
    fuchsia::ui::views::ViewToken view_token,
    fuchsia::sys::ServiceListPtr additional_services_for_sessionmgr,
    fuchsia::sys::ServiceList additional_services_for_agents,
    GetPresentationCallback get_presentation, OnSessionShutdownCallback on_session_shutdown)
    : session_context_binding_(this),
      get_presentation_(std::move(get_presentation)),
      on_session_shutdown_(std::move(on_session_shutdown)),
      weak_factory_(this) {
  FX_CHECK(get_presentation_);
  FX_CHECK(on_session_shutdown_);

  const auto use_random_id = config_accessor->use_random_session_id();

  if (use_random_id) {
    FX_LOGS(INFO) << "Starting session with random session ID.";
  } else {
    FX_LOGS(INFO) << "Starting session with stable session ID.";
  }

  // 0. Generate the path to map '/data' for the sessionmgr we are starting
  std::string session_id = use_random_id ? GetRandomSessionId() : GetStableSessionId();
  auto data_origin = GetSessionDirectory(session_id);

  // 1. Create a PseudoDir containing startup.config. This directory will be injected into
  // sessionmgr's namespace and sessionmgr will read its configurations from there.
  auto config_namespace = CreateAndServeConfigNamespace(config_accessor->GetConfigAsJsonString());

  // 2. Launch Sessionmgr in the current environment.
  sessionmgr_app_ = std::make_unique<AppClient<fuchsia::modular::Lifecycle>>(
      launcher, std::move(sessionmgr_app_config), data_origin,
      std::move(additional_services_for_sessionmgr), std::move(config_namespace));

  // 3. Initialize the Sessionmgr service.

  sessionmgr_app_->services().ConnectToService(sessionmgr_.NewRequest());
  sessionmgr_->Initialize(session_id, session_context_binding_.NewBinding(),
                          std::move(additional_services_for_agents), std::move(view_token));

  sessionmgr_app_->SetAppErrorHandler([weak_this = weak_factory_.GetWeakPtr()] {
    FX_LOGS(ERROR) << "Sessionmgr seems to have crashed unexpectedly. "
                   << "Calling on_session_shutdown_().";
    // This prevents us from receiving any further requests.
    weak_this->session_context_binding_.Unbind();

    // Shutdown(), which expects a graceful shutdown of sessionmgr, does not
    // apply here because sessionmgr crashed. Move |on_session_shutdown_| on to the stack before
    // invoking it, in case the |on_session_shutdown_| deletes |this|.
    auto on_session_shutdown = std::move(weak_this->on_session_shutdown_);
    on_session_shutdown(ShutDownReason::CRITICAL_FAILURE);
    // Don't touch |this|.
  });
}

fuchsia::sys::FlatNamespacePtr SessionContextImpl::CreateAndServeConfigNamespace(
    std::string config_contents) {
  zx::channel config_request_channel;
  zx::channel config_dir_channel;

  FX_CHECK(zx::channel::create(0u, &config_request_channel, &config_dir_channel) == ZX_OK);

  // Host the config file in a PseudoDir
  config_dir_ = modular::MakeFilePathWithContents(modular_config::kStartupConfigFilePath,
                                                  std::move(config_contents));
  config_dir_->Serve(fuchsia::io::OPEN_RIGHT_READABLE, std::move(config_request_channel));

  auto flat_namespace = fuchsia::sys::FlatNamespace::New();
  flat_namespace->paths.push_back(modular_config::kOverriddenConfigDir);
  flat_namespace->directories.push_back(std::move(config_dir_channel));

  return flat_namespace;
}

void SessionContextImpl::Shutdown(ShutDownReason reason, fit::function<void()> callback) {
  shutdown_callbacks_.push_back(std::move(callback));
  if (shutdown_callbacks_.size() > 1) {
    FX_LOGS(INFO) << "fuchsia::modular::internal::SessionContext::Shutdown() "
                     "already called, queuing callback while shutdown is in progress.";
    return;
  }

  // Close the SessionContext channel to ensure no more requests from the
  // channel are processed.
  session_context_binding_.Unbind();

  sessionmgr_app_->Teardown(kSessionmgrTimeout, [weak_this = weak_factory_.GetWeakPtr(), reason] {
    // One of the callbacks might delete |SessionContextImpl|, so always guard against
    // WeakPtr<SessionContextImpl>.
    for (const auto& callback : weak_this->shutdown_callbacks_) {
      callback();
      if (!weak_this) {
        return;
      }
    }
    auto on_session_shutdown = std::move(weak_this->on_session_shutdown_);
    on_session_shutdown(reason);
  });
}

void SessionContextImpl::GetPresentation(
    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> request) {
  get_presentation_(std::move(request));
}

void SessionContextImpl::Restart() {
  Shutdown(ShutDownReason::CLIENT_REQUEST, [] {});
}

void SessionContextImpl::RestartDueToCriticalFailure() {
  Shutdown(ShutDownReason::CRITICAL_FAILURE, [] {});
}

}  // namespace modular
