// Copyright 2014 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/supervised_user/supervised_user_whitelist_service.h"

#include <stddef.h>

#include <string>
#include <utility>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/strings/string_split.h"
#include "base/values.h"
#include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
#include "chrome/browser/supervised_user/supervised_user_site_list.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_change_processor.h"
#include "components/sync/model/sync_data.h"
#include "components/sync/model/sync_error.h"
#include "components/sync/model/sync_error_factory.h"
#include "components/sync/model/sync_merge_result.h"
#include "components/sync/protocol/sync.pb.h"

const char kName[] = "name";

SupervisedUserWhitelistService::SupervisedUserWhitelistService(
    PrefService* prefs,
    component_updater::SupervisedUserWhitelistInstaller* installer,
    const std::string& client_id)
    : prefs_(prefs),
      installer_(installer),
      client_id_(client_id),
      weak_ptr_factory_(this) {
  DCHECK(prefs);
}

SupervisedUserWhitelistService::~SupervisedUserWhitelistService() {
}

// static
void SupervisedUserWhitelistService::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterDictionaryPref(prefs::kSupervisedUserWhitelists);
}

void SupervisedUserWhitelistService::Init() {
  const base::DictionaryValue* whitelists =
      prefs_->GetDictionary(prefs::kSupervisedUserWhitelists);
  for (base::DictionaryValue::Iterator it(*whitelists); !it.IsAtEnd();
       it.Advance()) {
    registered_whitelists_.insert(it.key());
  }
  UMA_HISTOGRAM_COUNTS_100("ManagedUsers.Whitelist.Count", whitelists->size());

  // The installer can be null in some unit tests.
  if (!installer_)
    return;

  installer_->Subscribe(
      base::Bind(&SupervisedUserWhitelistService::OnWhitelistReady,
                 weak_ptr_factory_.GetWeakPtr()));

  // Register whitelists specified on the command line.
  for (const auto& whitelist : GetWhitelistsFromCommandLine())
    RegisterWhitelist(whitelist.first, whitelist.second, FROM_COMMAND_LINE);
}

void SupervisedUserWhitelistService::AddSiteListsChangedCallback(
    const SiteListsChangedCallback& callback) {
  site_lists_changed_callbacks_.push_back(callback);

  std::vector<scoped_refptr<SupervisedUserSiteList>> whitelists;
  GetLoadedWhitelists(&whitelists);
  callback.Run(whitelists);
}

// static
std::map<std::string, std::string>
SupervisedUserWhitelistService::GetWhitelistsFromCommandLine() {
  std::map<std::string, std::string> whitelists;
  const base::CommandLine* command_line =
      base::CommandLine::ForCurrentProcess();
  std::string command_line_whitelists = command_line->GetSwitchValueASCII(
      switches::kInstallSupervisedUserWhitelists);
  std::vector<base::StringPiece> string_pieces =
      base::SplitStringPiece(command_line_whitelists, ",",
                             base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  for (const base::StringPiece& whitelist : string_pieces) {
    std::string id;
    std::string name;
    size_t separator = whitelist.find(':');
    if (separator != base::StringPiece::npos) {
      whitelist.substr(0, separator).CopyToString(&id);
      whitelist.substr(separator + 1).CopyToString(&name);
    } else {
      whitelist.CopyToString(&id);
    }

    const bool result = whitelists.insert(std::make_pair(id, name)).second;
    DCHECK(result);
  }

  return whitelists;
}

void SupervisedUserWhitelistService::LoadWhitelistForTesting(
    const std::string& id,
    const base::string16& title,
    const base::FilePath& path) {
  bool result = registered_whitelists_.insert(id).second;
  DCHECK(result);
  OnWhitelistReady(id, title, base::FilePath(), path);
}

void SupervisedUserWhitelistService::UnloadWhitelist(const std::string& id) {
  bool result = registered_whitelists_.erase(id) > 0u;
  DCHECK(result);
  loaded_whitelists_.erase(id);
  NotifyWhitelistsChanged();
}

// static
syncer::SyncData SupervisedUserWhitelistService::CreateWhitelistSyncData(
    const std::string& id,
    const std::string& name) {
  sync_pb::EntitySpecifics specifics;
  sync_pb::ManagedUserWhitelistSpecifics* whitelist =
      specifics.mutable_managed_user_whitelist();
  whitelist->set_id(id);
  whitelist->set_name(name);

  return syncer::SyncData::CreateLocalData(id, name, specifics);
}

syncer::SyncMergeResult
SupervisedUserWhitelistService::MergeDataAndStartSyncing(
    syncer::ModelType type,
    const syncer::SyncDataList& initial_sync_data,
    std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
    std::unique_ptr<syncer::SyncErrorFactory> error_handler) {
  DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, type);

  syncer::SyncChangeList change_list;
  syncer::SyncMergeResult result(syncer::SUPERVISED_USER_WHITELISTS);

  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUserWhitelists);
  base::DictionaryValue* pref_dict = update.Get();
  result.set_num_items_before_association(pref_dict->size());
  std::set<std::string> seen_ids;
  int num_items_added = 0;
  int num_items_modified = 0;

  for (const syncer::SyncData& sync_data : initial_sync_data) {
    DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, sync_data.GetDataType());
    const sync_pb::ManagedUserWhitelistSpecifics& whitelist =
        sync_data.GetSpecifics().managed_user_whitelist();
    std::string id = whitelist.id();
    std::string name = whitelist.name();
    seen_ids.insert(id);
    base::DictionaryValue* dict = nullptr;
    if (pref_dict->GetDictionary(id, &dict)) {
      std::string old_name;
      bool result = dict->GetString(kName, &old_name);
      DCHECK(result);
      if (name != old_name) {
        SetWhitelistProperties(dict, whitelist);
        num_items_modified++;
      }
    } else {
      num_items_added++;
      AddNewWhitelist(pref_dict, whitelist);
    }
  }

  std::set<std::string> ids_to_remove;
  for (base::DictionaryValue::Iterator it(*pref_dict); !it.IsAtEnd();
       it.Advance()) {
    if (seen_ids.find(it.key()) == seen_ids.end())
      ids_to_remove.insert(it.key());
  }

  for (const std::string& id : ids_to_remove)
    RemoveWhitelist(pref_dict, id);

  // Notify if whitelists have been uninstalled. We will notify about newly
  // added whitelists later, when they are actually available
  // (in OnWhitelistLoaded).
  if (!ids_to_remove.empty())
    NotifyWhitelistsChanged();

  result.set_num_items_added(num_items_added);
  result.set_num_items_modified(num_items_modified);
  result.set_num_items_deleted(ids_to_remove.size());
  result.set_num_items_after_association(pref_dict->size());
  return result;
}

void SupervisedUserWhitelistService::StopSyncing(syncer::ModelType type) {
  DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, type);
}

syncer::SyncDataList SupervisedUserWhitelistService::GetAllSyncData(
    syncer::ModelType type) const {
  syncer::SyncDataList sync_data;
  const base::DictionaryValue* whitelists =
      prefs_->GetDictionary(prefs::kSupervisedUserWhitelists);
  for (base::DictionaryValue::Iterator it(*whitelists); !it.IsAtEnd();
       it.Advance()) {
    const std::string& id = it.key();
    const base::DictionaryValue* dict = nullptr;
    it.value().GetAsDictionary(&dict);
    std::string name;
    bool result = dict->GetString(kName, &name);
    DCHECK(result);
    sync_pb::EntitySpecifics specifics;
    sync_pb::ManagedUserWhitelistSpecifics* whitelist =
        specifics.mutable_managed_user_whitelist();
    whitelist->set_id(id);
    whitelist->set_name(name);
    sync_data.push_back(syncer::SyncData::CreateLocalData(id, name, specifics));
  }
  return sync_data;
}

syncer::SyncError SupervisedUserWhitelistService::ProcessSyncChanges(
    const base::Location& from_here,
    const syncer::SyncChangeList& change_list) {
  bool whitelists_removed = false;
  syncer::SyncError error;
  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUserWhitelists);
  base::DictionaryValue* pref_dict = update.Get();
  for (const syncer::SyncChange& sync_change : change_list) {
    syncer::SyncData data = sync_change.sync_data();
    DCHECK_EQ(syncer::SUPERVISED_USER_WHITELISTS, data.GetDataType());
    const sync_pb::ManagedUserWhitelistSpecifics& whitelist =
        data.GetSpecifics().managed_user_whitelist();
    std::string id = whitelist.id();
    switch (sync_change.change_type()) {
      case syncer::SyncChange::ACTION_ADD: {
        DCHECK(!pref_dict->HasKey(id)) << id;
        AddNewWhitelist(pref_dict, whitelist);
        break;
      }
      case syncer::SyncChange::ACTION_UPDATE: {
        base::DictionaryValue* dict = nullptr;
        pref_dict->GetDictionaryWithoutPathExpansion(id, &dict);
        SetWhitelistProperties(dict, whitelist);
        break;
      }
      case syncer::SyncChange::ACTION_DELETE: {
        DCHECK(pref_dict->HasKey(id)) << id;
        RemoveWhitelist(pref_dict, id);
        whitelists_removed = true;
        break;
      }
      case syncer::SyncChange::ACTION_INVALID: {
        NOTREACHED();
        break;
      }
    }
  }

  if (whitelists_removed)
    NotifyWhitelistsChanged();

  return error;
}

void SupervisedUserWhitelistService::AddNewWhitelist(
    base::DictionaryValue* pref_dict,
    const sync_pb::ManagedUserWhitelistSpecifics& whitelist) {
  base::RecordAction(base::UserMetricsAction("ManagedUsers_Whitelist_Added"));

  RegisterWhitelist(whitelist.id(), whitelist.name(), FROM_SYNC);
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
  SetWhitelistProperties(dict.get(), whitelist);
  pref_dict->SetWithoutPathExpansion(whitelist.id(), std::move(dict));
}

void SupervisedUserWhitelistService::SetWhitelistProperties(
    base::DictionaryValue* dict,
    const sync_pb::ManagedUserWhitelistSpecifics& whitelist) {
  dict->SetString(kName, whitelist.name());
}

void SupervisedUserWhitelistService::RemoveWhitelist(
    base::DictionaryValue* pref_dict,
    const std::string& id) {
  base::RecordAction(base::UserMetricsAction("ManagedUsers_Whitelist_Removed"));

  pref_dict->RemoveWithoutPathExpansion(id, NULL);
  installer_->UnregisterWhitelist(client_id_, id);
  UnloadWhitelist(id);
}

void SupervisedUserWhitelistService::RegisterWhitelist(const std::string& id,
                                                       const std::string& name,
                                                       WhitelistSource source) {
  bool result = registered_whitelists_.insert(id).second;
  DCHECK(result);

  // Using an empty client ID for whitelists installed from the command line
  // causes the installer to not persist the installation, so the whitelist will
  // be removed the next time the browser is started without the command line
  // flag.
  installer_->RegisterWhitelist(
      source == FROM_COMMAND_LINE ? std::string() : client_id_, id, name);
}

void SupervisedUserWhitelistService::GetLoadedWhitelists(
    std::vector<scoped_refptr<SupervisedUserSiteList>>* whitelists) {
  for (const auto& whitelist : loaded_whitelists_)
    whitelists->push_back(whitelist.second);
}

void SupervisedUserWhitelistService::NotifyWhitelistsChanged() {
  std::vector<scoped_refptr<SupervisedUserSiteList>> whitelists;
  GetLoadedWhitelists(&whitelists);

  for (const auto& callback : site_lists_changed_callbacks_)
    callback.Run(whitelists);
}

void SupervisedUserWhitelistService::OnWhitelistReady(
    const std::string& id,
    const base::string16& title,
    const base::FilePath& large_icon_path,
    const base::FilePath& whitelist_path) {
  // If we did not register the whitelist or it has been unregistered in the
  // mean time, ignore it.
  if (registered_whitelists_.count(id) == 0u)
    return;

  SupervisedUserSiteList::Load(
      id, title, large_icon_path, whitelist_path,
      base::Bind(&SupervisedUserWhitelistService::OnWhitelistLoaded,
                 weak_ptr_factory_.GetWeakPtr(), id, base::TimeTicks::Now()));
}

void SupervisedUserWhitelistService::OnWhitelistLoaded(
    const std::string& id,
    base::TimeTicks start_time,
    const scoped_refptr<SupervisedUserSiteList>& whitelist) {
  if (!whitelist) {
    LOG(WARNING) << "Couldn't load whitelist " << id;
    return;
  }

  UMA_HISTOGRAM_TIMES("ManagedUsers.Whitelist.TotalLoadDuration",
                      base::TimeTicks::Now() - start_time);

  // If the whitelist has been unregistered in the mean time, ignore it.
  if (registered_whitelists_.count(id) == 0u)
    return;

  loaded_whitelists_[id] = whitelist;
  NotifyWhitelistsChanged();
}
