// Copyright 2013 The Chromium 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 "chromeos/dbus/fake_session_manager_client.h"

#include <utility>

#include "base/base64.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/location.h"
#include "base/numerics/safe_conversions.h"
#include "base/path_service.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/dbus/constants/dbus_paths.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/login_manager/policy_descriptor.pb.h"
#include "chromeos/dbus/util/account_identifier_operators.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "crypto/sha2.h"

namespace chromeos {

using RetrievePolicyCallback = FakeSessionManagerClient::RetrievePolicyCallback;
using RetrievePolicyResponseType =
    FakeSessionManagerClient::RetrievePolicyResponseType;

namespace {

constexpr char kFakeContainerInstanceId[] = "0123456789ABCDEF";
constexpr char kStubDevicePolicyFileNamePrefix[] = "stub_device_policy";
constexpr char kStubPerAccountPolicyFileNamePrefix[] = "stub_policy";
constexpr char kStubStateKeysFileName[] = "stub_state_keys";
constexpr char kStubExtensionPolicyFileNameFragment[] = "_extension_";
constexpr char kStubSigninExtensionPolicyFileNameFragment[] =
    "_signin_extension_";
constexpr char kStubPerAccountPolicyKeyFileName[] = "policy.pub";
constexpr char kEmptyAccountId[] = "";

// Helper to asynchronously retrieve a file's content.
std::string GetFileContent(const base::FilePath& path) {
  std::string result;
  if (!path.empty())
    base::ReadFileToString(path, &result);
  return result;
}

// Helper to write files in a background thread.
void StoreFiles(std::map<base::FilePath, std::string> paths_and_data) {
  for (const auto& kv : paths_and_data) {
    const base::FilePath& path = kv.first;
    if (path.empty() || !base::CreateDirectory(path.DirName())) {
      LOG(WARNING) << "Failed to write to " << path.value();
      continue;
    }
    const std::string& data = kv.second;
    int result = base::WriteFile(path, data.data(), data.size());
    if (result == -1 || static_cast<size_t>(result) != data.size())
      LOG(WARNING) << "Failed to write to " << path.value();
  }
}

// Creates a PolicyDescriptor object to store/retrieve Chrome policy.
login_manager::PolicyDescriptor MakeChromePolicyDescriptor(
    login_manager::PolicyAccountType account_type,
    const std::string& account_id) {
  login_manager::PolicyDescriptor descriptor;
  descriptor.set_account_type(account_type);
  descriptor.set_account_id(account_id);
  descriptor.set_domain(login_manager::POLICY_DOMAIN_CHROME);
  return descriptor;
}

// Returns true if the policy descriptor points to Chrome device policy.
bool IsChromeDevicePolicy(const login_manager::PolicyDescriptor& descriptor) {
  DCHECK(descriptor.has_account_type());
  DCHECK(descriptor.has_domain());
  return descriptor.account_type() == login_manager::ACCOUNT_TYPE_DEVICE &&
         descriptor.domain() == login_manager::POLICY_DOMAIN_CHROME;
}

// Helper to asynchronously read (or if missing create) state key stubs.
std::vector<std::string> ReadCreateStateKeysStub(const base::FilePath& path) {
  std::string contents;
  if (base::PathExists(path)) {
    contents = GetFileContent(path);
  } else {
    // Create stub state keys on the fly.
    for (int i = 0; i < 5; ++i) {
      contents += crypto::SHA256HashString(
          base::IntToString(i) +
          base::Int64ToString(base::Time::Now().ToJavaTime()));
    }
    StoreFiles({{path, contents}});
  }

  std::vector<std::string> state_keys;
  for (size_t i = 0; i < contents.size() / 32; ++i)
    state_keys.push_back(contents.substr(i * 32, 32));
  return state_keys;
}

// Gets the postfix of the stub policy filename, which is based the
// |descriptor|'s domain and component id. Returns an empty string if the domain
// doesn't use a component id (e.g. normal Chrome user/device policy).
std::string GetStubPolicyFilenamePostfix(
    const login_manager::PolicyDescriptor& descriptor) {
  DCHECK(descriptor.has_domain());
  switch (descriptor.domain()) {
    case login_manager::POLICY_DOMAIN_CHROME:
      return std::string();
    case login_manager::POLICY_DOMAIN_EXTENSIONS:
      DCHECK(descriptor.has_component_id());
      return kStubExtensionPolicyFileNameFragment + descriptor.component_id();
    case login_manager::POLICY_DOMAIN_SIGNIN_EXTENSIONS:
      DCHECK(descriptor.has_component_id());
      return kStubSigninExtensionPolicyFileNameFragment +
             descriptor.component_id();
  }
  NOTREACHED();
  return std::string();
}

// Returns the last part of the stub policy file path consisting of the filename
// for device accounts and <cryptohome_id>/filename for user and device local
// accounts, e.g.
//   "stub_device_policy" for Chrome device policy or
//   "<cryptohome_id>/stub_policy_extension_<id>" for extension policy.
// This path is also used as key in the in-memory policy map |policy_|.
base::FilePath GetStubRelativePolicyPath(
    const login_manager::PolicyDescriptor& descriptor) {
  DCHECK(descriptor.has_account_type());
  std::string postfix = GetStubPolicyFilenamePostfix(descriptor);
  switch (descriptor.account_type()) {
    case login_manager::ACCOUNT_TYPE_DEVICE:
      return base::FilePath(kStubDevicePolicyFileNamePrefix + postfix);

    case login_manager::ACCOUNT_TYPE_USER:
    case login_manager::ACCOUNT_TYPE_SESSIONLESS_USER:
    case login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT: {
      DCHECK(descriptor.has_account_id());
      cryptohome::AccountIdentifier cryptohome_id;
      cryptohome_id.set_account_id(descriptor.account_id());
      const std::string sanitized_id =
          CryptohomeClient::GetStubSanitizedUsername(cryptohome_id);
      return base::FilePath(sanitized_id)
          .AppendASCII(kStubPerAccountPolicyFileNamePrefix + postfix);
    }
  }
  NOTREACHED();
  return base::FilePath();
}

// Gets the stub file paths of the policy blob and optionally the policy key
// (|key_path|) for the given |descriptor|. |key_path| can be nullptr.
base::FilePath GetStubPolicyFilePath(
    const login_manager::PolicyDescriptor& descriptor,
    base::FilePath* key_path) {
  if (key_path)
    key_path->clear();

  base::FilePath relative_policy_path = GetStubRelativePolicyPath(descriptor);
  DCHECK(descriptor.has_account_type());
  switch (descriptor.account_type()) {
    case login_manager::ACCOUNT_TYPE_DEVICE: {
      base::FilePath owner_key_path;
      CHECK(
          base::PathService::Get(dbus_paths::FILE_OWNER_KEY, &owner_key_path));
      if (key_path)
        *key_path = owner_key_path;
      return owner_key_path.DirName().Append(relative_policy_path);
    }

    case login_manager::ACCOUNT_TYPE_USER:
    case login_manager::ACCOUNT_TYPE_SESSIONLESS_USER:
    case login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT: {
      base::FilePath base_path;
      CHECK(
          base::PathService::Get(dbus_paths::DIR_USER_POLICY_KEYS, &base_path));
      if (key_path) {
        *key_path = base_path.Append(relative_policy_path.DirName())
                        .AppendASCII(kStubPerAccountPolicyKeyFileName);
      }
      return base_path.Append(relative_policy_path);
    }
  }
  NOTREACHED();
  return base::FilePath();
}

// Returns a key that's used for storing policy in memory.
std::string GetMemoryStorageKey(
    const login_manager::PolicyDescriptor& descriptor) {
  base::FilePath relative_policy_path = GetStubRelativePolicyPath(descriptor);
  DCHECK(!relative_policy_path.empty());
  return relative_policy_path.value();
}

// Posts a task to call callback(response).
template <typename CallbackType, typename ResponseType>
void PostReply(const base::Location& from_here,
               CallbackType callback,
               ResponseType response) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      from_here, base::BindOnce(std::move(callback), std::move(response)));
}

}  // namespace

FakeSessionManagerClient::FakeSessionManagerClient()
    : FakeSessionManagerClient(PolicyStorageType::kInMemory) {}

FakeSessionManagerClient::FakeSessionManagerClient(
    PolicyStorageType policy_storage)
    : policy_storage_(policy_storage),
      clear_forced_re_enrollment_vpd_call_count_(0),
      start_device_wipe_call_count_(0),
      request_lock_screen_call_count_(0),
      notify_lock_screen_shown_call_count_(0),
      notify_lock_screen_dismissed_call_count_(0),
      screen_is_locked_(false),
      arc_available_(false),
      delegate_(nullptr),
      weak_ptr_factory_(this) {}

FakeSessionManagerClient::~FakeSessionManagerClient() = default;

void FakeSessionManagerClient::Init(dbus::Bus* bus) {}

void FakeSessionManagerClient::SetStubDelegate(StubDelegate* delegate) {
  delegate_ = delegate;
}

void FakeSessionManagerClient::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void FakeSessionManagerClient::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

bool FakeSessionManagerClient::HasObserver(const Observer* observer) const {
  return observers_.HasObserver(observer);
}

void FakeSessionManagerClient::WaitForServiceToBeAvailable(
    WaitForServiceToBeAvailableCallback callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), true));
}

bool FakeSessionManagerClient::IsScreenLocked() const {
  return screen_is_locked_;
}

void FakeSessionManagerClient::EmitLoginPromptVisible() {
  for (auto& observer : observers_)
    observer.EmitLoginPromptVisibleCalled();
}

void FakeSessionManagerClient::EmitAshInitialized() {}

void FakeSessionManagerClient::RestartJob(int socket_fd,
                                          const std::vector<std::string>& argv,
                                          VoidDBusMethodCallback callback) {}

void FakeSessionManagerClient::SaveLoginPassword(const std::string& password) {}

void FakeSessionManagerClient::StartSession(
    const cryptohome::AccountIdentifier& cryptohome_id) {
  DCHECK_EQ(0UL, user_sessions_.count(cryptohome_id.account_id()));
  std::string user_id_hash =
      CryptohomeClient::GetStubSanitizedUsername(cryptohome_id);
  user_sessions_[cryptohome_id.account_id()] = user_id_hash;
}

void FakeSessionManagerClient::StopSession() {}

void FakeSessionManagerClient::NotifySupervisedUserCreationStarted() {}

void FakeSessionManagerClient::NotifySupervisedUserCreationFinished() {}

void FakeSessionManagerClient::StartDeviceWipe() {
  start_device_wipe_call_count_++;
}

void FakeSessionManagerClient::ClearForcedReEnrollmentVpd(
    VoidDBusMethodCallback callback) {
  clear_forced_re_enrollment_vpd_call_count_++;
  PostReply(FROM_HERE, std::move(callback), true);
}

void FakeSessionManagerClient::StartTPMFirmwareUpdate(
    const std::string& update_mode) {}

void FakeSessionManagerClient::RequestLockScreen() {
  request_lock_screen_call_count_++;
  if (delegate_)
    delegate_->LockScreenForStub();
}

void FakeSessionManagerClient::NotifyLockScreenShown() {
  notify_lock_screen_shown_call_count_++;
  screen_is_locked_ = true;
}

void FakeSessionManagerClient::NotifyLockScreenDismissed() {
  notify_lock_screen_dismissed_call_count_++;
  screen_is_locked_ = false;
}

void FakeSessionManagerClient::RetrieveActiveSessions(
    ActiveSessionsCallback callback) {
  PostReply(FROM_HERE, std::move(callback), user_sessions_);
}

void FakeSessionManagerClient::RetrieveDevicePolicy(
    RetrievePolicyCallback callback) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
  RetrievePolicy(descriptor, std::move(callback));
}

RetrievePolicyResponseType
FakeSessionManagerClient::BlockingRetrieveDevicePolicy(
    std::string* policy_out) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
  return BlockingRetrievePolicy(descriptor, policy_out);
}

void FakeSessionManagerClient::RetrievePolicyForUser(
    const cryptohome::AccountIdentifier& cryptohome_id,
    RetrievePolicyCallback callback) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
  RetrievePolicy(descriptor, std::move(callback));
}

RetrievePolicyResponseType
FakeSessionManagerClient::BlockingRetrievePolicyForUser(
    const cryptohome::AccountIdentifier& cryptohome_id,
    std::string* policy_out) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
  return BlockingRetrievePolicy(descriptor, policy_out);
}

void FakeSessionManagerClient::RetrievePolicyForUserWithoutSession(
    const cryptohome::AccountIdentifier& cryptohome_id,
    RetrievePolicyCallback callback) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, cryptohome_id.account_id());
  RetrievePolicy(descriptor, std::move(callback));
}

void FakeSessionManagerClient::RetrieveDeviceLocalAccountPolicy(
    const std::string& account_id,
    RetrievePolicyCallback callback) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_id);
  RetrievePolicy(descriptor, std::move(callback));
}

RetrievePolicyResponseType
FakeSessionManagerClient::BlockingRetrieveDeviceLocalAccountPolicy(
    const std::string& account_id,
    std::string* policy_out) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_id);
  return BlockingRetrievePolicy(descriptor, policy_out);
}

void FakeSessionManagerClient::RetrievePolicy(
    const login_manager::PolicyDescriptor& descriptor,
    RetrievePolicyCallback callback) {
  if (policy_storage_ == PolicyStorageType::kOnDisk) {
    base::FilePath policy_path =
        GetStubPolicyFilePath(descriptor, nullptr /* key_path */);
    DCHECK(!policy_path.empty());

    base::PostTaskWithTraitsAndReplyWithResult(
        FROM_HERE,
        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
        base::BindOnce(&GetFileContent, policy_path),
        base::BindOnce(std::move(callback),
                       RetrievePolicyResponseType::SUCCESS));
  } else {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(callback), RetrievePolicyResponseType::SUCCESS,
                       policy_[GetMemoryStorageKey(descriptor)]));
  }
}

RetrievePolicyResponseType FakeSessionManagerClient::BlockingRetrievePolicy(
    const login_manager::PolicyDescriptor& descriptor,
    std::string* policy_out) {
  if (policy_storage_ == PolicyStorageType::kOnDisk) {
    base::FilePath policy_path =
        GetStubPolicyFilePath(descriptor, nullptr /* key_path */);
    DCHECK(!policy_path.empty());
    *policy_out = GetFileContent(policy_path);
  } else {
    *policy_out = policy_[GetMemoryStorageKey(descriptor)];
  }
  return RetrievePolicyResponseType::SUCCESS;
}

void FakeSessionManagerClient::StoreDevicePolicy(
    const std::string& policy_blob,
    VoidDBusMethodCallback callback) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
  StorePolicy(descriptor, policy_blob, std::move(callback));
}

void FakeSessionManagerClient::StorePolicyForUser(
    const cryptohome::AccountIdentifier& cryptohome_id,
    const std::string& policy_blob,
    VoidDBusMethodCallback callback) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
  StorePolicy(descriptor, policy_blob, std::move(callback));
}

void FakeSessionManagerClient::StoreDeviceLocalAccountPolicy(
    const std::string& account_id,
    const std::string& policy_blob,
    VoidDBusMethodCallback callback) {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_id);
  StorePolicy(descriptor, policy_blob, std::move(callback));
}

void FakeSessionManagerClient::StorePolicy(
    const login_manager::PolicyDescriptor& descriptor,
    const std::string& policy_blob,
    VoidDBusMethodCallback callback) {
  // Decode the blob to get the new key.
  enterprise_management::PolicyFetchResponse response;
  if (!response.ParseFromString(policy_blob)) {
    PostReply(FROM_HERE, std::move(callback), false /* success */);
    return;
  }

  // Simulate failure.
  if (!store_policy_success_) {
    PostReply(FROM_HERE, std::move(callback), false /* success */);
    return;
  }

  if (policy_storage_ == PolicyStorageType::kOnDisk) {
    // Store policy and maybe key in files (background threads) and call
    // callback in main thread.
    base::FilePath key_path;
    base::FilePath policy_path = GetStubPolicyFilePath(descriptor, &key_path);
    DCHECK(!policy_path.empty());
    DCHECK(!key_path.empty());

    std::map<base::FilePath, std::string> files_to_store;
    files_to_store[policy_path] = policy_blob;
    if (response.has_new_public_key())
      files_to_store[key_path] = response.new_public_key();

    base::PostTaskWithTraitsAndReply(
        FROM_HERE,
        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
        base::BindOnce(StoreFiles, std::move(files_to_store)),
        base::BindOnce(std::move(callback), true /* success */));
  } else {
    policy_[GetMemoryStorageKey(descriptor)] = policy_blob;
    PostReply(FROM_HERE, std::move(callback), true /* success */);

    if (IsChromeDevicePolicy(descriptor)) {
      // TODO(ljusten): For historical reasons, this code path only stores keys
      // for device policy. Should this be extended to other policy?
      if (response.has_new_public_key()) {
        base::FilePath key_path;
        GetStubPolicyFilePath(descriptor, &key_path);
        DCHECK(!key_path.empty());

        base::PostTaskWithTraits(
            FROM_HERE,
            {base::MayBlock(),
             base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
            base::BindOnce(StoreFiles,
                           std::map<base::FilePath, std::string>{
                               {key_path, response.new_public_key()}}));
        for (auto& observer : observers_)
          observer.OwnerKeySet(true /* success */);
      }
      for (auto& observer : observers_)
        observer.PropertyChangeComplete(true /* success */);
    }
  }
}

bool FakeSessionManagerClient::SupportsRestartToApplyUserFlags() const {
  return supports_restart_to_apply_user_flags_;
}

void FakeSessionManagerClient::SetFlagsForUser(
    const cryptohome::AccountIdentifier& cryptohome_id,
    const std::vector<std::string>& flags) {
  flags_for_user_[cryptohome_id] = flags;
}

void FakeSessionManagerClient::GetServerBackedStateKeys(
    StateKeysCallback callback) {
  if (policy_storage_ == PolicyStorageType::kOnDisk) {
    base::FilePath owner_key_path;
    CHECK(base::PathService::Get(dbus_paths::FILE_OWNER_KEY, &owner_key_path));
    const base::FilePath state_keys_path =
        owner_key_path.DirName().AppendASCII(kStubStateKeysFileName);
    base::PostTaskWithTraitsAndReplyWithResult(
        FROM_HERE,
        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
        base::BindOnce(&ReadCreateStateKeysStub, state_keys_path),
        std::move(callback));
  } else {
    PostReply(FROM_HERE, std::move(callback), server_backed_state_keys_);
  }
}

void FakeSessionManagerClient::StartArcMiniContainer(
    const login_manager::StartArcMiniContainerRequest& request,
    StartArcMiniContainerCallback callback) {
  last_start_arc_mini_container_request_ = request;

  if (!arc_available_) {
    PostReply(FROM_HERE, std::move(callback), base::nullopt);
    return;
  }
  // This is starting a new container.
  base::Base64Encode(kFakeContainerInstanceId, &container_instance_id_);
  PostReply(FROM_HERE, std::move(callback), container_instance_id_);
}

void FakeSessionManagerClient::UpgradeArcContainer(
    const login_manager::UpgradeArcContainerRequest& request,
    base::OnceClosure success_callback,
    UpgradeErrorCallback error_callback) {
  last_upgrade_arc_request_ = request;

  if (!arc_available_) {
    PostReply(FROM_HERE, std::move(error_callback), false);
    return;
  }
  if (low_disk_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(&FakeSessionManagerClient::NotifyArcInstanceStopped,
                       weak_ptr_factory_.GetWeakPtr(),
                       login_manager::ArcContainerStopReason::LOW_DISK_SPACE,
                       std::move(container_instance_id_)));
    PostReply(FROM_HERE, std::move(error_callback), true);
    return;
  }
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                std::move(success_callback));
}

void FakeSessionManagerClient::StopArcInstance(
    VoidDBusMethodCallback callback) {
  if (!arc_available_ || container_instance_id_.empty()) {
    PostReply(FROM_HERE, std::move(callback), false /* result */);
    return;
  }

  PostReply(FROM_HERE, std::move(callback), true /* result */);
  // Emulate ArcInstanceStopped signal propagation.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&FakeSessionManagerClient::NotifyArcInstanceStopped,
                     weak_ptr_factory_.GetWeakPtr(),
                     login_manager::ArcContainerStopReason::USER_REQUEST,
                     std::move(container_instance_id_)));
  container_instance_id_.clear();
}

void FakeSessionManagerClient::SetArcCpuRestriction(
    login_manager::ContainerCpuRestrictionState restriction_state,
    VoidDBusMethodCallback callback) {
  PostReply(FROM_HERE, std::move(callback), arc_available_);
}

void FakeSessionManagerClient::EmitArcBooted(
    const cryptohome::AccountIdentifier& cryptohome_id,
    VoidDBusMethodCallback callback) {
  PostReply(FROM_HERE, std::move(callback), arc_available_);
}

void FakeSessionManagerClient::GetArcStartTime(
    DBusMethodCallback<base::TimeTicks> callback) {
  PostReply(
      FROM_HERE, std::move(callback),
      arc_available_ ? base::make_optional(arc_start_time_) : base::nullopt);
}

void FakeSessionManagerClient::NotifyArcInstanceStopped(
    login_manager::ArcContainerStopReason reason,
    const std::string& container_instance_id) {
  for (auto& observer : observers_)
    observer.ArcInstanceStopped(reason, container_instance_id);
}

bool FakeSessionManagerClient::GetFlagsForUser(
    const cryptohome::AccountIdentifier& cryptohome_id,
    std::vector<std::string>* out_flags_for_user) const {
  auto iter = flags_for_user_.find(cryptohome_id);
  if (iter == flags_for_user_.end())
    return false;

  *out_flags_for_user = iter->second;
  return true;
}

const std::string& FakeSessionManagerClient::device_policy() const {
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
  DCHECK(policy_storage_ == PolicyStorageType::kInMemory);
  auto it = policy_.find(GetMemoryStorageKey(descriptor));
  return it != policy_.end() ? it->second : base::EmptyString();
}

void FakeSessionManagerClient::set_device_policy(
    const std::string& policy_blob) {
  DCHECK(policy_storage_ == PolicyStorageType::kInMemory);
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE, kEmptyAccountId);
  policy_[GetMemoryStorageKey(descriptor)] = policy_blob;
}

const std::string& FakeSessionManagerClient::user_policy(
    const cryptohome::AccountIdentifier& cryptohome_id) const {
  DCHECK(policy_storage_ == PolicyStorageType::kInMemory);
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
  auto it = policy_.find(GetMemoryStorageKey(descriptor));
  return it != policy_.end() ? it->second : base::EmptyString();
}

void FakeSessionManagerClient::set_user_policy(
    const cryptohome::AccountIdentifier& cryptohome_id,
    const std::string& policy_blob) {
  DCHECK(policy_storage_ == PolicyStorageType::kInMemory);
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_USER, cryptohome_id.account_id());
  policy_[GetMemoryStorageKey(descriptor)] = policy_blob;
}

void FakeSessionManagerClient::set_user_policy_without_session(
    const cryptohome::AccountIdentifier& cryptohome_id,
    const std::string& policy_blob) {
  DCHECK(policy_storage_ == PolicyStorageType::kInMemory);
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_SESSIONLESS_USER, cryptohome_id.account_id());
  policy_[GetMemoryStorageKey(descriptor)] = policy_blob;
}

const std::string& FakeSessionManagerClient::device_local_account_policy(
    const std::string& account_id) const {
  DCHECK(policy_storage_ == PolicyStorageType::kInMemory);
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_id);
  auto it = policy_.find(GetMemoryStorageKey(descriptor));
  return it != policy_.end() ? it->second : base::EmptyString();
}

void FakeSessionManagerClient::set_device_local_account_policy(
    const std::string& account_id,
    const std::string& policy_blob) {
  DCHECK(policy_storage_ == PolicyStorageType::kInMemory);
  login_manager::PolicyDescriptor descriptor = MakeChromePolicyDescriptor(
      login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT, account_id);
  policy_[GetMemoryStorageKey(descriptor)] = policy_blob;
}

void FakeSessionManagerClient::OnPropertyChangeComplete(bool success) {
  for (auto& observer : observers_)
    observer.PropertyChangeComplete(success);
}

}  // namespace chromeos
