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

#include "content/browser/devtools/protocol/background_service_handler.h"

#include "base/metrics/histogram_functions.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/devtools_background_services_context.h"
#include "content/public/browser/render_process_host.h"

namespace content {
namespace protocol {

namespace {

devtools::proto::BackgroundService ServiceNameToEnum(
    const std::string& service_name) {
  if (service_name == BackgroundService::ServiceNameEnum::BackgroundFetch) {
    return devtools::proto::BackgroundService::BACKGROUND_FETCH;
  } else if (service_name ==
             BackgroundService::ServiceNameEnum::BackgroundSync) {
    return devtools::proto::BackgroundService::BACKGROUND_SYNC;
  } else if (service_name ==
             BackgroundService::ServiceNameEnum::PushMessaging) {
    return devtools::proto::BackgroundService::PUSH_MESSAGING;
  } else if (service_name ==
             BackgroundService::ServiceNameEnum::Notifications) {
    return devtools::proto::BackgroundService::NOTIFICATIONS;
  } else if (service_name ==
             BackgroundService::ServiceNameEnum::PaymentHandler) {
    return devtools::proto::BackgroundService::PAYMENT_HANDLER;
  } else if (service_name ==
             BackgroundService::ServiceNameEnum::PeriodicBackgroundSync) {
    return devtools::proto::BackgroundService::PERIODIC_BACKGROUND_SYNC;
  }
  return devtools::proto::BackgroundService::UNKNOWN;
}

std::string ServiceEnumToName(devtools::proto::BackgroundService service_enum) {
  switch (service_enum) {
    case devtools::proto::BackgroundService::BACKGROUND_FETCH:
      return BackgroundService::ServiceNameEnum::BackgroundFetch;
    case devtools::proto::BackgroundService::BACKGROUND_SYNC:
      return BackgroundService::ServiceNameEnum::BackgroundSync;
    case devtools::proto::BackgroundService::PUSH_MESSAGING:
      return BackgroundService::ServiceNameEnum::PushMessaging;
    case devtools::proto::BackgroundService::NOTIFICATIONS:
      return BackgroundService::ServiceNameEnum::Notifications;
    case devtools::proto::BackgroundService::PAYMENT_HANDLER:
      return BackgroundService::ServiceNameEnum::PaymentHandler;
    case devtools::proto::BackgroundService::PERIODIC_BACKGROUND_SYNC:
      return BackgroundService::ServiceNameEnum::PeriodicBackgroundSync;
    default:
      NOTREACHED();
  }
}

std::unique_ptr<protocol::Array<protocol::BackgroundService::EventMetadata>>
ProtoMapToArray(
    const google::protobuf::Map<std::string, std::string>& event_metadata_map) {
  auto metadata_array = std::make_unique<
      protocol::Array<protocol::BackgroundService::EventMetadata>>();

  for (const auto& entry : event_metadata_map) {
    auto event_metadata = protocol::BackgroundService::EventMetadata::Create()
                              .SetKey(entry.first)
                              .SetValue(entry.second)
                              .Build();
    metadata_array->emplace_back(std::move(event_metadata));
  }

  return metadata_array;
}

std::unique_ptr<protocol::BackgroundService::BackgroundServiceEvent>
ToBackgroundServiceEvent(const devtools::proto::BackgroundServiceEvent& event) {
  base::Time timestamp = base::Time::FromDeltaSinceWindowsEpoch(
      base::Microseconds(event.timestamp()));
  return protocol::BackgroundService::BackgroundServiceEvent::Create()
      .SetTimestamp(timestamp.InMillisecondsFSinceUnixEpoch() /
                    1'000)  // milliseconds -> seconds
      .SetOrigin(event.origin())
      .SetServiceWorkerRegistrationId(
          base::NumberToString(event.service_worker_registration_id()))
      .SetService(ServiceEnumToName(event.background_service()))
      .SetEventName(event.event_name())
      .SetInstanceId(event.instance_id())
      .SetEventMetadata(ProtoMapToArray(event.event_metadata()))
      .SetStorageKey(event.storage_key())
      .Build();
}

}  // namespace

BackgroundServiceHandler::BackgroundServiceHandler()
    : DevToolsDomainHandler(BackgroundService::Metainfo::domainName),
      devtools_context_(nullptr) {}

BackgroundServiceHandler::~BackgroundServiceHandler() {
  DCHECK(enabled_services_.empty());
}

void BackgroundServiceHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ =
      std::make_unique<BackgroundService::Frontend>(dispatcher->channel());
  BackgroundService::Dispatcher::wire(dispatcher, this);
}

void BackgroundServiceHandler::SetRenderer(int process_host_id,
                                           RenderFrameHostImpl* frame_host) {
  RenderProcessHost* process_host = RenderProcessHost::FromID(process_host_id);
  if (!process_host) {
    SetDevToolsContext(nullptr);
    enabled_services_.clear();
    return;
  }

  auto* storage_partition =
      static_cast<StoragePartitionImpl*>(process_host->GetStoragePartition());

  SetDevToolsContext(storage_partition->GetDevToolsBackgroundServicesContext());
  DCHECK(devtools_context_);
}

void BackgroundServiceHandler::SetDevToolsContext(
    DevToolsBackgroundServicesContext* devtools_context) {
  if (devtools_context_ == devtools_context) {
    return;
  }

  if (devtools_context_ && !enabled_services_.empty()) {
    devtools_context_->RemoveObserver(this);
  }

  devtools_context_ =
      static_cast<DevToolsBackgroundServicesContextImpl*>(devtools_context);

  if (devtools_context_ && !enabled_services_.empty()) {
    devtools_context_->AddObserver(this);
  }
}

Response BackgroundServiceHandler::Disable() {
  SetDevToolsContext(nullptr);
  enabled_services_.clear();
  return Response::Success();
}

void BackgroundServiceHandler::StartObserving(
    const std::string& service,
    std::unique_ptr<StartObservingCallback> callback) {
  DCHECK(devtools_context_);

  auto service_enum = ServiceNameToEnum(service);
  if (service_enum == devtools::proto::BackgroundService::UNKNOWN) {
    callback->sendFailure(Response::InvalidParams("Invalid service name"));
    return;
  }

  if (enabled_services_.count(service_enum)) {
    callback->sendSuccess();
    return;
  }

  if (enabled_services_.empty())
    devtools_context_->AddObserver(this);
  enabled_services_.insert(service_enum);

  bool is_recording = devtools_context_->IsRecording(service_enum);

  DCHECK(frontend_);
  frontend_->RecordingStateChanged(is_recording, service);

  devtools_context_->GetLoggedBackgroundServiceEvents(
      service_enum,
      base::BindOnce(&BackgroundServiceHandler::DidGetLoggedEvents,
                     weak_ptr_factory_.GetWeakPtr(), service_enum,
                     std::move(callback)));
}

Response BackgroundServiceHandler::StopObserving(const std::string& service) {
  auto service_enum = ServiceNameToEnum(service);
  if (service_enum == devtools::proto::BackgroundService::UNKNOWN)
    return Response::InvalidParams("Invalid service name");

  if (!enabled_services_.count(service_enum))
    return Response::Success();

  enabled_services_.erase(service_enum);
  if (enabled_services_.empty())
    devtools_context_->RemoveObserver(this);

  return Response::Success();
}

void BackgroundServiceHandler::DidGetLoggedEvents(
    devtools::proto::BackgroundService service,
    std::unique_ptr<StartObservingCallback> callback,
    std::vector<devtools::proto::BackgroundServiceEvent> events) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // These events won't be duplicated in `OnEventReceived` since we are using
  // sequenced task runners.
  for (const auto& event : events)
    frontend_->BackgroundServiceEventReceived(ToBackgroundServiceEvent(event));

  return callback->sendSuccess();
}

Response BackgroundServiceHandler::SetRecording(bool should_record,
                                                const std::string& service) {
  DCHECK(devtools_context_);

  auto service_enum = ServiceNameToEnum(service);
  if (service_enum == devtools::proto::BackgroundService::UNKNOWN)
    return Response::InvalidParams("Invalid service name");

  if (should_record) {
    devtools_context_->StartRecording(service_enum);
  } else {
    devtools_context_->StopRecording(service_enum);
  }

  return Response::Success();
}

Response BackgroundServiceHandler::ClearEvents(const std::string& service) {
  DCHECK(devtools_context_);

  auto service_enum = ServiceNameToEnum(service);
  if (service_enum == devtools::proto::BackgroundService::UNKNOWN)
    return Response::InvalidParams("Invalid service name");

  devtools_context_->ClearLoggedBackgroundServiceEvents(service_enum);
  return Response::Success();
}

void BackgroundServiceHandler::OnEventReceived(
    const devtools::proto::BackgroundServiceEvent& event) {
  if (!enabled_services_.count(event.background_service()))
    return;

  frontend_->BackgroundServiceEventReceived(ToBackgroundServiceEvent(event));
}

void BackgroundServiceHandler::OnRecordingStateChanged(
    bool should_record,
    devtools::proto::BackgroundService service) {
  if (!enabled_services_.count(service))
    return;

  frontend_->RecordingStateChanged(should_record, ServiceEnumToName(service));
}

}  // namespace protocol
}  // namespace content
