// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/browser_sync/sync_internals_message_handler.h"

#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "components/sync/base/command_line_switches.h"
#include "components/sync/base/data_type.h"
#include "components/sync/engine/events/protocol_event.h"
#include "components/sync/invalidations/sync_invalidations_service.h"
#include "components/sync/model/type_entities_count.h"
#include "components/sync/protocol/sync_invalidations_payload.pb.h"
#include "components/sync/protocol/user_event_specifics.pb.h"
#include "components/sync/service/sync_internals_util.h"
#include "components/sync/service/sync_service.h"
#include "components/sync/service/sync_user_settings.h"
#include "components/sync_user_events/user_event_service.h"

namespace browser_sync {

namespace {

// Converts the string at |index| in |list| to an int, defaulting to 0 on error.
int64_t StringAtIndexToInt64(const base::ListValue& list, size_t index) {
  if (list.size() > index && list[index].is_string()) {
    int64_t integer = 0;
    if (base::StringToInt64(list[index].GetString(), &integer)) {
      return integer;
    }
  }
  return 0;
}

// Returns whether the there is any value at the given |index|.
bool HasSomethingAtIndex(const base::ListValue& list, size_t index) {
  if (list.size() > index && list[index].is_string()) {
    return !list[index].GetString().empty();
  }
  return false;
}

// Returns the initial state of the "include specifics" flag, based on whether
// or not the corresponding command-line switch is set.
bool GetIncludeSpecificsInitialState() {
  return base::CommandLine::ForCurrentProcess()->HasSwitch(
      syncer::kSyncIncludeSpecificsInProtocolLog);
}

}  //  namespace

SyncInternalsMessageHandler::SyncInternalsMessageHandler(
    Delegate* delegate,
    signin::IdentityManager* identity_manager,
    syncer::SyncService* sync_service,
    syncer::SyncInvalidationsService* sync_invalidations_service,
    syncer::UserEventService* user_event_service,
    const std::string& channel)
    : SyncInternalsMessageHandler(
          delegate,
          base::BindRepeating(&syncer::sync_ui_util::ConstructAboutInformation,
                              syncer::sync_ui_util::IncludeSensitiveData(true)),
          identity_manager,
          sync_service,
          sync_invalidations_service,
          user_event_service,
          channel) {
  // This class serves to display debug information to the user, so it's fine to
  // include sensitive data in ConstructAboutInformation() above.
}

SyncInternalsMessageHandler::SyncInternalsMessageHandler(
    Delegate* delegate,
    GetAboutSyncDataCb get_about_sync_data_cb,
    signin::IdentityManager* identity_manager,
    syncer::SyncService* sync_service,
    syncer::SyncInvalidationsService* sync_invalidations_service,
    syncer::UserEventService* user_event_service,
    const std::string& channel)
    : include_specifics_(GetIncludeSpecificsInitialState()),
      delegate_(delegate),
      get_about_sync_data_cb_(std::move(get_about_sync_data_cb)),
      identity_manager_(identity_manager),
      sync_service_(sync_service),
      sync_invalidations_service_(sync_invalidations_service),
      user_event_service_(user_event_service),
      channel_(channel) {}

SyncInternalsMessageHandler::~SyncInternalsMessageHandler() = default;

void SyncInternalsMessageHandler::DisableMessagesToPage() {
  // Invaliding weak ptrs works well here because the only weak ptr we vend is
  // to the sync side to give us information that should be used to populate the
  // page side. If messages are disallowed, we don't care about updating
  // the UI with data, so dropping those callbacks is fine.
  weak_ptr_factory_.InvalidateWeakPtrs();
  sync_service_observation_.Reset();
  protocol_event_observation_.Reset();
  invalidations_observation_.Reset();
}

base::flat_map<std::string, SyncInternalsMessageHandler::PageMessageHandler>
SyncInternalsMessageHandler::GetMessageHandlerMap() {
  return {
      {syncer::sync_ui_util::kRequestDataAndRegisterForUpdates,
       base::BindRepeating(
           &SyncInternalsMessageHandler::HandleRequestDataAndRegisterForUpdates,
           base::Unretained(this))},
      {syncer::sync_ui_util::kRequestListOfTypes,
       base::BindRepeating(
           &SyncInternalsMessageHandler::HandleRequestListOfTypes,
           base::Unretained(this))},
      {syncer::sync_ui_util::kRequestIncludeSpecificsInitialState,
       base::BindRepeating(&SyncInternalsMessageHandler::
                               HandleRequestIncludeSpecificsInitialState,
                           base::Unretained(this))},
      {syncer::sync_ui_util::kSetIncludeSpecifics,
       base::BindRepeating(
           &SyncInternalsMessageHandler::HandleSetIncludeSpecifics,
           base::Unretained(this))},
      {syncer::sync_ui_util::kWriteUserEvent,
       base::BindRepeating(&SyncInternalsMessageHandler::HandleWriteUserEvent,
                           base::Unretained(this))},
      {syncer::sync_ui_util::kRequestStart,
       base::BindRepeating(&SyncInternalsMessageHandler::HandleRequestStart,
                           base::Unretained(this))},
      {syncer::sync_ui_util::kTriggerRefresh,
       base::BindRepeating(&SyncInternalsMessageHandler::HandleTriggerRefresh,
                           base::Unretained(this))},
      {syncer::sync_ui_util::kGetAllNodes,
       base::BindRepeating(&SyncInternalsMessageHandler::HandleGetAllNodes,
                           base::Unretained(this))},
  };
}

void SyncInternalsMessageHandler::HandleRequestDataAndRegisterForUpdates(
    const base::ListValue& args) {
  CHECK(args.empty());

  // Checking IsObserving() protects us from double-registering.  This could
  // happen on a page refresh, where the JavaScript gets re-run but the
  // message handler remains unchanged.
  if (sync_service_ && !sync_service_observation_.IsObserving()) {
    sync_service_observation_.Observe(sync_service_);
  }
  if (sync_service_ && !protocol_event_observation_.IsObserving()) {
    protocol_event_observation_.Observe(sync_service_);
  }
  if (sync_invalidations_service_ &&
      !invalidations_observation_.IsObserving()) {
    invalidations_observation_.Observe(sync_invalidations_service_);
  }

  SendAboutInfoAndEntityCounts();
}

void SyncInternalsMessageHandler::HandleRequestListOfTypes(
    const base::ListValue& args) {
  CHECK(args.empty());

  base::DictValue event_details;
  base::ListValue type_list;
  syncer::DataTypeSet protocol_types = syncer::ProtocolTypes();
  for (syncer::DataType type : protocol_types) {
    type_list.Append(DataTypeToDebugString(type));
  }
  event_details.Set(syncer::sync_ui_util::kTypes, std::move(type_list));
  base::ValueView event_args[] = {event_details};
  delegate_->SendEventToPage(syncer::sync_ui_util::kOnReceivedListOfTypes,
                             event_args);
}

void SyncInternalsMessageHandler::HandleRequestIncludeSpecificsInitialState(
    const base::ListValue& args) {
  CHECK(args.empty());

  base::DictValue value;
  value.Set(syncer::sync_ui_util::kIncludeSpecifics,
            GetIncludeSpecificsInitialState());

  base::ValueView event_args[] = {value};
  delegate_->SendEventToPage(
      syncer::sync_ui_util::kOnReceivedIncludeSpecificsInitialState,
      event_args);
}

void SyncInternalsMessageHandler::HandleGetAllNodes(
    const base::ListValue& args) {
  CHECK_EQ(1U, args.size());

  const std::string& callback_id = args[0].GetString();

  if (sync_service_) {
    // This opens up the possibility of non-javascript code calling us
    // asynchronously, and potentially at times we're not allowed to call into
    // the javascript side. We guard against this by invalidating this weak ptr
    // should javascript become disallowed.
    sync_service_->GetAllNodesForDebugging(
        base::BindOnce(&SyncInternalsMessageHandler::OnReceivedAllNodes,
                       weak_ptr_factory_.GetWeakPtr(), callback_id));
  }
}

void SyncInternalsMessageHandler::HandleSetIncludeSpecifics(
    const base::ListValue& args) {
  CHECK_EQ(1U, args.size());
  include_specifics_ = args[0].GetBool();
}

void SyncInternalsMessageHandler::HandleWriteUserEvent(
    const base::ListValue& args) {
  CHECK_EQ(2U, args.size());

  sync_pb::UserEventSpecifics event_specifics;
  // Even though there's nothing to set inside the test event object, it needs
  // to be created so that later logic can discern our event type.
  event_specifics.mutable_test_event();

  // |event_time_usec| is required.
  event_specifics.set_event_time_usec(StringAtIndexToInt64(args, 0u));

  // |navigation_id| is optional, treat empty string and 0 differently.
  if (HasSomethingAtIndex(args, 1)) {
    event_specifics.set_navigation_id(StringAtIndexToInt64(args, 1u));
  }

  user_event_service_->RecordUserEvent(
      std::make_unique<sync_pb::UserEventSpecifics>(event_specifics));
}

void SyncInternalsMessageHandler::HandleRequestStart(
    const base::ListValue& args) {
#if !BUILDFLAG(IS_CHROMEOS)
  CHECK_EQ(0U, args.size());

  if (!identity_manager_ || !sync_service_) {
    return;
  }

  const bool can_use_api =
      identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSignin) &&
      !identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync);
  if (!can_use_api) {
    return;
  }

  identity_manager_->GetPrimaryAccountMutator()->SetPrimaryAccount(
      identity_manager_->GetPrimaryAccountId(signin::ConsentLevel::kSignin),
      signin::ConsentLevel::kSync,
      signin_metrics::AccessPoint::kSetSyncConsentFromSyncInternals);
  sync_service_->GetUserSettings()->SetInitialSyncFeatureSetupComplete();
#endif  // !BUILDFLAG(IS_CHROMEOS)
}

void SyncInternalsMessageHandler::HandleTriggerRefresh(
    const base::ListValue& args) {
  if (!sync_service_) {
    return;
  }

  sync_service_->TriggerRefresh(
      syncer::SyncService::TriggerRefreshSource::kSyncInternals,
      syncer::DataTypeSet::All());
}

void SyncInternalsMessageHandler::OnReceivedAllNodes(
    const std::string& callback_id,
    base::ListValue nodes) {
  delegate_->ResolvePageCallback(callback_id, nodes);
}

void SyncInternalsMessageHandler::OnStateChanged(syncer::SyncService* sync) {
  SendAboutInfoAndEntityCounts();
}

void SyncInternalsMessageHandler::OnSyncShutdown(syncer::SyncService* sync) {
  // Unreachable, since this class is tied to UI which gets destroyed before the
  // Profile and its KeyedServices.
  NOTREACHED();
}

void SyncInternalsMessageHandler::OnProtocolEvent(
    const syncer::ProtocolEvent& event) {
  base::DictValue dict = event.ToValue(include_specifics_);
  base::ValueView event_args[] = {dict};
  delegate_->SendEventToPage(syncer::sync_ui_util::kOnProtocolEvent,
                             event_args);
}

void SyncInternalsMessageHandler::OnInvalidationReceived(
    const std::string& payload) {
  sync_pb::SyncInvalidationsPayload payload_message;
  if (!payload_message.ParseFromString(payload)) {
    return;
  }

  base::ListValue data_types_list;
  for (const auto& data_type_invalidation :
       payload_message.data_type_invalidations()) {
    const int field_number = data_type_invalidation.data_type_id();
    syncer::DataType type =
        syncer::GetDataTypeFromSpecificsFieldNumber(field_number);
    if (IsRealDataType(type)) {
      data_types_list.Append(syncer::DataTypeToDebugString(type));
    }
  }

  base::ValueView event_args[] = {data_types_list};
  delegate_->SendEventToPage(syncer::sync_ui_util::kOnInvalidationReceived,
                             event_args);
}

void SyncInternalsMessageHandler::SendAboutInfoAndEntityCounts() {
  base::DictValue value = get_about_sync_data_cb_.Run(sync_service_, channel_);
  base::ValueView event_args[] = {value};
  delegate_->SendEventToPage(syncer::sync_ui_util::kOnAboutInfoUpdated,
                             event_args);

  if (sync_service_) {
    sync_service_->GetEntityCountsForDebugging(
        BindRepeating(&SyncInternalsMessageHandler::OnGotEntityCounts,
                      weak_ptr_factory_.GetWeakPtr()));
  }
}

void SyncInternalsMessageHandler::OnGotEntityCounts(
    const syncer::TypeEntitiesCount& entity_counts) {
  base::DictValue count_dictionary;
  count_dictionary.Set(syncer::sync_ui_util::kDataType,
                       DataTypeToDebugString(entity_counts.type));
  count_dictionary.Set(syncer::sync_ui_util::kEntities, entity_counts.entities);
  count_dictionary.Set(syncer::sync_ui_util::kNonTombstoneEntities,
                       entity_counts.non_tombstone_entities);

  base::DictValue event_details;
  event_details.Set(syncer::sync_ui_util::kEntityCounts,
                    std::move(count_dictionary));
  base::ValueView event_args[] = {event_details};
  delegate_->SendEventToPage(syncer::sync_ui_util::kOnEntityCountsUpdated,
                             event_args);
}

}  // namespace browser_sync
