// 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 "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"

#include <map>
#include <set>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/stl_util.h"
#include "base/sys_info.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_external_loader.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/owner_key_util.h"
#include "chrome/browser/extensions/external_loader.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/cryptohome/async_method_caller.h"
#include "chromeos/settings/cros_settings_names.h"
#include "content/public/browser/browser_thread.h"

namespace chromeos {

namespace {

// Domain that is used for kiosk-app account IDs.
const char kKioskAppAccountDomain[] = "kiosk-apps";

std::string GenerateKioskAppAccountId(const std::string& app_id) {
  return app_id + '@' + kKioskAppAccountDomain;
}

void OnRemoveAppCryptohomeComplete(const std::string& app,
                                   bool success,
                                   cryptohome::MountError return_code) {
  if (!success) {
    LOG(ERROR) << "Remove cryptohome for " << app
        << " failed, return code: " << return_code;
  }
}

// Check for presence of machine owner public key file.
void CheckOwnerFilePresence(bool *present) {
  scoped_refptr<OwnerKeyUtil> util = OwnerKeyUtil::Create();
  *present = util->IsPublicKeyPresent();
}

scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() {
  base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
  CHECK(pool);
  return pool->GetSequencedTaskRunnerWithShutdownBehavior(
      pool->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
}

}  // namespace

// static
const char KioskAppManager::kKioskDictionaryName[] = "kiosk";
const char KioskAppManager::kKeyApps[] = "apps";
const char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state";
const char KioskAppManager::kIconCacheDir[] = "kiosk/icon";
const char KioskAppManager::kCrxCacheDir[] = "kiosk/crx";

// static
static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER;
KioskAppManager* KioskAppManager::Get() {
  return instance.Pointer();
}

// static
void KioskAppManager::Shutdown() {
  if (instance == NULL)
    return;

  instance.Pointer()->CleanUp();
}

// static
void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterDictionaryPref(kKioskDictionaryName);
}

KioskAppManager::App::App(const KioskAppData& data, bool is_extension_pending)
    : app_id(data.app_id()),
      user_id(data.user_id()),
      name(data.name()),
      icon(data.icon()),
      is_loading(data.IsLoading() || is_extension_pending) {
}

KioskAppManager::App::App() : is_loading(false) {}
KioskAppManager::App::~App() {}

std::string KioskAppManager::GetAutoLaunchApp() const {
  return auto_launch_app_id_;
}

void KioskAppManager::SetAutoLaunchApp(const std::string& app_id) {
  SetAutoLoginState(AUTOLOGIN_REQUESTED);
  // Clean first, so the proper change callbacks are triggered even
  // if we are only changing AutoLoginState here.
  if (!auto_launch_app_id_.empty()) {
    CrosSettings::Get()->SetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
                                   std::string());
  }

  CrosSettings::Get()->SetString(
      kAccountsPrefDeviceLocalAccountAutoLoginId,
      app_id.empty() ? std::string() : GenerateKioskAppAccountId(app_id));
  CrosSettings::Get()->SetInteger(
      kAccountsPrefDeviceLocalAccountAutoLoginDelay, 0);
}

void KioskAppManager::EnableConsumerKioskAutoLaunch(
    const KioskAppManager::EnableKioskAutoLaunchCallback& callback) {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  connector->GetInstallAttributes()->LockDevice(
      std::string(),  // user
      policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH,
      std::string(),  // device_id
      base::Bind(
          &KioskAppManager::OnLockDevice, base::Unretained(this), callback));
}

void KioskAppManager::GetConsumerKioskAutoLaunchStatus(
    const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback) {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  connector->GetInstallAttributes()->ReadImmutableAttributes(
      base::Bind(&KioskAppManager::OnReadImmutableAttributes,
                 base::Unretained(this),
                 callback));
}

bool KioskAppManager::IsConsumerKioskDeviceWithAutoLaunch() {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  return connector->GetInstallAttributes() &&
         connector->GetInstallAttributes()
             ->IsConsumerKioskDeviceWithAutoLaunch();
}

void KioskAppManager::OnLockDevice(
    const KioskAppManager::EnableKioskAutoLaunchCallback& callback,
    policy::EnterpriseInstallAttributes::LockResult result) {
  if (callback.is_null())
    return;

  callback.Run(result == policy::EnterpriseInstallAttributes::LOCK_SUCCESS);
}

void KioskAppManager::OnOwnerFileChecked(
    const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback& callback,
    bool* owner_present) {
  ownership_established_ = *owner_present;

  if (callback.is_null())
    return;

  // If we have owner already established on the machine, don't let
  // consumer kiosk to be enabled.
  if (ownership_established_)
    callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED);
  else
    callback.Run(CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE);
}

void KioskAppManager::OnReadImmutableAttributes(
    const KioskAppManager::GetConsumerKioskAutoLaunchStatusCallback&
        callback) {
  if (callback.is_null())
    return;

  ConsumerKioskAutoLaunchStatus status =
      CONSUMER_KIOSK_AUTO_LAUNCH_DISABLED;
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  policy::EnterpriseInstallAttributes* attributes =
      connector->GetInstallAttributes();
  switch (attributes->GetMode()) {
    case policy::DEVICE_MODE_NOT_SET: {
      if (!base::SysInfo::IsRunningOnChromeOS()) {
        status = CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE;
      } else if (!ownership_established_) {
        bool* owner_present = new bool(false);
        content::BrowserThread::PostBlockingPoolTaskAndReply(
            FROM_HERE,
            base::Bind(&CheckOwnerFilePresence,
                       owner_present),
            base::Bind(&KioskAppManager::OnOwnerFileChecked,
                       base::Unretained(this),
                       callback,
                       base::Owned(owner_present)));
        return;
      }
      break;
    }
    case policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
      status = CONSUMER_KIOSK_AUTO_LAUNCH_ENABLED;
      break;
    default:
      break;
  }

  callback.Run(status);
}

void KioskAppManager::SetEnableAutoLaunch(bool value) {
  SetAutoLoginState(value ? AUTOLOGIN_APPROVED : AUTOLOGIN_REJECTED);
}

bool KioskAppManager::IsAutoLaunchRequested() const {
  if (GetAutoLaunchApp().empty())
    return false;

  // Apps that were installed by the policy don't require machine owner
  // consent through UI.
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  if (connector->IsEnterpriseManaged())
    return false;

  return GetAutoLoginState() == AUTOLOGIN_REQUESTED;
}

bool KioskAppManager::IsAutoLaunchEnabled() const {
  if (GetAutoLaunchApp().empty())
    return false;

  // Apps that were installed by the policy don't require machine owner
  // consent through UI.
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  if (connector->IsEnterpriseManaged())
    return true;

  return GetAutoLoginState() == AUTOLOGIN_APPROVED;
}

void KioskAppManager::AddApp(const std::string& app_id) {
  std::vector<policy::DeviceLocalAccount> device_local_accounts =
      policy::GetDeviceLocalAccounts(CrosSettings::Get());

  // Don't insert the app if it's already in the list.
  for (std::vector<policy::DeviceLocalAccount>::const_iterator
           it = device_local_accounts.begin();
       it != device_local_accounts.end(); ++it) {
    if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
        it->kiosk_app_id == app_id) {
      return;
    }
  }

  // Add the new account.
  device_local_accounts.push_back(policy::DeviceLocalAccount(
      policy::DeviceLocalAccount::TYPE_KIOSK_APP,
      GenerateKioskAppAccountId(app_id),
      app_id));

  policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
}

void KioskAppManager::RemoveApp(const std::string& app_id) {
  // Resets auto launch app if it is the removed app.
  if (auto_launch_app_id_ == app_id)
    SetAutoLaunchApp(std::string());

  std::vector<policy::DeviceLocalAccount> device_local_accounts =
      policy::GetDeviceLocalAccounts(CrosSettings::Get());
  if (device_local_accounts.empty())
    return;

  // Remove entries that match |app_id|.
  for (std::vector<policy::DeviceLocalAccount>::iterator
           it = device_local_accounts.begin();
       it != device_local_accounts.end(); ++it) {
    if (it->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP &&
        it->kiosk_app_id == app_id) {
      device_local_accounts.erase(it);
      break;
    }
  }

  policy::SetDeviceLocalAccounts(CrosSettings::Get(), device_local_accounts);
}

void KioskAppManager::GetApps(Apps* apps) const {
  apps->clear();
  apps->reserve(apps_.size());
  for (size_t i = 0; i < apps_.size(); ++i) {
    const KioskAppData& app_data = *apps_[i];
    if (app_data.status() != KioskAppData::STATUS_ERROR)
      apps->push_back(App(
          app_data, external_cache_->IsExtensionPending(app_data.app_id())));
  }
}

bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
  const KioskAppData* data = GetAppData(app_id);
  if (!data)
    return false;

  *app = App(*data, external_cache_->IsExtensionPending(app_id));
  return true;
}

const base::RefCountedString* KioskAppManager::GetAppRawIcon(
    const std::string& app_id) const {
  const KioskAppData* data = GetAppData(app_id);
  if (!data)
    return NULL;

  return data->raw_icon();
}

bool KioskAppManager::GetDisableBailoutShortcut() const {
  bool enable;
  if (CrosSettings::Get()->GetBoolean(
          kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, &enable)) {
    return !enable;
  }

  return false;
}

void KioskAppManager::ClearAppData(const std::string& app_id) {
  KioskAppData* app_data = GetAppDataMutable(app_id);
  if (!app_data)
    return;

  app_data->ClearCache();
}

void KioskAppManager::UpdateAppDataFromProfile(
    const std::string& app_id,
    Profile* profile,
    const extensions::Extension* app) {
  KioskAppData* app_data = GetAppDataMutable(app_id);
  if (!app_data)
    return;

  app_data->LoadFromInstalledApp(profile, app);
}

void KioskAppManager::RetryFailedAppDataFetch() {
  for (size_t i = 0; i < apps_.size(); ++i) {
    if (apps_[i]->status() == KioskAppData::STATUS_ERROR)
      apps_[i]->Load();
  }
}

bool KioskAppManager::HasCachedCrx(const std::string& app_id) const {
  base::FilePath crx_path;
  std::string version;
  return GetCachedCrx(app_id, &crx_path, &version);
}

void KioskAppManager::AddObserver(KioskAppManagerObserver* observer) {
  observers_.AddObserver(observer);
}

void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) {
  observers_.RemoveObserver(observer);
}

extensions::ExternalLoader* KioskAppManager::CreateExternalLoader() {
  if (external_loader_created_) {
    NOTREACHED();
    return NULL;
  }
  external_loader_created_ = true;
  KioskAppExternalLoader* loader = new KioskAppExternalLoader();
  external_loader_ = loader->AsWeakPtr();

  return loader;
}

void KioskAppManager::InstallFromCache(const std::string& id) {
  const base::DictionaryValue* extension = NULL;
  if (external_cache_->cached_extensions()->GetDictionary(id, &extension)) {
    scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
    base::DictionaryValue* extension_copy = extension->DeepCopy();
    prefs->Set(id, extension_copy);
    external_loader_->SetCurrentAppExtensions(prefs.Pass());
  } else {
    LOG(ERROR) << "Can't find app in the cached externsions"
               << " id = " << id;
  }
}

void KioskAppManager::UpdateExternalCache() {
  UpdateAppData();
}

KioskAppManager::KioskAppManager()
    : ownership_established_(false), external_loader_created_(false) {
  base::FilePath cache_dir;
  GetCrxCacheDir(&cache_dir);
  external_cache_.reset(
      new ExternalCache(cache_dir,
                        g_browser_process->system_request_context(),
                        GetBackgroundTaskRunner(),
                        this,
                        true /* always_check_updates */,
                        false /* wait_for_cache_initialization */));
  UpdateAppData();
  local_accounts_subscription_ =
      CrosSettings::Get()->AddSettingsObserver(
          kAccountsPrefDeviceLocalAccounts,
          base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
  local_account_auto_login_id_subscription_ =
      CrosSettings::Get()->AddSettingsObserver(
          kAccountsPrefDeviceLocalAccountAutoLoginId,
          base::Bind(&KioskAppManager::UpdateAppData, base::Unretained(this)));
}

KioskAppManager::~KioskAppManager() {}

void KioskAppManager::CleanUp() {
  local_accounts_subscription_.reset();
  local_account_auto_login_id_subscription_.reset();
  apps_.clear();
  external_cache_.reset();
}

const KioskAppData* KioskAppManager::GetAppData(
    const std::string& app_id) const {
  for (size_t i = 0; i < apps_.size(); ++i) {
    const KioskAppData* data = apps_[i];
    if (data->app_id() == app_id)
      return data;
  }

  return NULL;
}

KioskAppData* KioskAppManager::GetAppDataMutable(const std::string& app_id) {
  return const_cast<KioskAppData*>(GetAppData(app_id));
}

void KioskAppManager::UpdateAppData() {
  // Gets app id to data mapping for existing apps.
  std::map<std::string, KioskAppData*> old_apps;
  for (size_t i = 0; i < apps_.size(); ++i)
    old_apps[apps_[i]->app_id()] = apps_[i];
  apps_.weak_clear();  // |old_apps| takes ownership

  auto_launch_app_id_.clear();
  std::string auto_login_account_id;
  CrosSettings::Get()->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
                                 &auto_login_account_id);

  // Re-populates |apps_| and reuses existing KioskAppData when possible.
  const std::vector<policy::DeviceLocalAccount> device_local_accounts =
      policy::GetDeviceLocalAccounts(CrosSettings::Get());
  for (std::vector<policy::DeviceLocalAccount>::const_iterator
           it = device_local_accounts.begin();
       it != device_local_accounts.end(); ++it) {
    if (it->type != policy::DeviceLocalAccount::TYPE_KIOSK_APP)
      continue;

    if (it->account_id == auto_login_account_id)
      auto_launch_app_id_ = it->kiosk_app_id;

    // TODO(mnissler): Support non-CWS update URLs.

    std::map<std::string, KioskAppData*>::iterator old_it =
        old_apps.find(it->kiosk_app_id);
    if (old_it != old_apps.end()) {
      apps_.push_back(old_it->second);
      old_apps.erase(old_it);
    } else {
      KioskAppData* new_app =
          new KioskAppData(this, it->kiosk_app_id, it->user_id);
      apps_.push_back(new_app);  // Takes ownership of |new_app|.
      new_app->Load();
    }
  }

  // Clears cache and deletes the remaining old data.
  std::vector<std::string> apps_to_remove;
  for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin();
       it != old_apps.end(); ++it) {
    it->second->ClearCache();
    cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
        it->second->user_id(),
        base::Bind(&OnRemoveAppCryptohomeComplete, it->first));
    apps_to_remove.push_back(it->second->app_id());
  }
  STLDeleteValues(&old_apps);
  external_cache_->RemoveExtensions(apps_to_remove);

  // Request external_cache_ to download new apps and update the existing
  // apps.
  scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
  for (size_t i = 0; i < apps_.size(); ++i)
    prefs->Set(apps_[i]->app_id(), new base::DictionaryValue);
  external_cache_->UpdateExtensionsList(prefs.Pass());

  RetryFailedAppDataFetch();

  FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_,
                    OnKioskAppsSettingsChanged());
}

void KioskAppManager::GetKioskAppIconCacheDir(base::FilePath* cache_dir) {
  base::FilePath user_data_dir;
  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
  *cache_dir = user_data_dir.AppendASCII(kIconCacheDir);
}

void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) {
  FOR_EACH_OBSERVER(KioskAppManagerObserver,
                    observers_,
                    OnKioskAppDataChanged(app_id));
}

void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) {
  FOR_EACH_OBSERVER(KioskAppManagerObserver,
                    observers_,
                    OnKioskAppDataLoadFailure(app_id));
}

void KioskAppManager::OnExtensionListsUpdated(
    const base::DictionaryValue* prefs) {
}

void KioskAppManager::OnExtensionLoadedInCache(const std::string& id) {
  KioskAppData* app_data = GetAppDataMutable(id);
  if (!app_data)
    return;
  FOR_EACH_OBSERVER(KioskAppManagerObserver,
                    observers_,
                    OnKioskExtensionLoadedInCache(id));

}

void KioskAppManager::OnExtensionDownloadFailed(
    const std::string& id,
    extensions::ExtensionDownloaderDelegate::Error error) {
  KioskAppData* app_data = GetAppDataMutable(id);
  if (!app_data)
    return;
  FOR_EACH_OBSERVER(KioskAppManagerObserver,
                    observers_,
                    OnKioskExtensionDownloadFailed(id));
}

KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
  PrefService* prefs = g_browser_process->local_state();
  const base::DictionaryValue* dict =
      prefs->GetDictionary(KioskAppManager::kKioskDictionaryName);
  int value;
  if (!dict->GetInteger(kKeyAutoLoginState, &value))
    return AUTOLOGIN_NONE;

  return static_cast<AutoLoginState>(value);
}

void KioskAppManager::SetAutoLoginState(AutoLoginState state) {
  PrefService* prefs = g_browser_process->local_state();
  DictionaryPrefUpdate dict_update(prefs,
                                   KioskAppManager::kKioskDictionaryName);
  dict_update->SetInteger(kKeyAutoLoginState, state);
  prefs->CommitPendingWrite();
}

void KioskAppManager::GetCrxCacheDir(base::FilePath* cache_dir) {
  base::FilePath user_data_dir;
  CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
  *cache_dir = user_data_dir.AppendASCII(kCrxCacheDir);
}

bool KioskAppManager::GetCachedCrx(const std::string& app_id,
                                   base::FilePath* file_path,
                                   std::string* version) const {
  return external_cache_->GetExtension(app_id, file_path, version);
}

}  // namespace chromeos
