// Copyright (c) 2012 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/service/service_ipc_server.h"

#include <algorithm>

#include "base/metrics/histogram_delta_serialization.h"

ServiceIPCServer::ServiceIPCServer(
    Client* client,
    const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
    base::WaitableEvent* shutdown_event)
    : client_(client),
      io_task_runner_(io_task_runner),
      shutdown_event_(shutdown_event),
      binding_(this) {
  DCHECK(client);
  DCHECK(shutdown_event);
  binder_registry_.AddInterface(
      base::Bind(&ServiceIPCServer::HandleServiceProcessConnection,
                 base::Unretained(this)));
}

bool ServiceIPCServer::Init() {
  CreateChannel();
  return true;
}

void ServiceIPCServer::CreateChannel() {
  binding_.Close();

  binding_.Bind(service_manager::mojom::InterfaceProviderRequest(
      client_->CreateChannelMessagePipe()));
  binding_.set_connection_error_handler(
      base::Bind(&ServiceIPCServer::OnChannelError, base::Unretained(this)));
}

ServiceIPCServer::~ServiceIPCServer() = default;

void ServiceIPCServer::OnChannelError() {
  // When an IPC client (typically a browser process) disconnects, the pipe is
  // closed and we get an OnChannelError. If we want to keep servicing requests,
  // we will recreate the channel.
  bool client_was_connected = ipc_client_connected_;
  ipc_client_connected_ = false;
  if (client_was_connected) {
    if (client_->OnIPCClientDisconnect())
      CreateChannel();
  } else if (!ipc_client_connected_) {
    // If the client was never even connected we had an error connecting.
    LOG(ERROR) << "Unable to open service ipc channel";
  }
}

void ServiceIPCServer::Hello(HelloCallback callback) {
  ipc_client_connected_ = true;
  std::move(callback).Run();
}

void ServiceIPCServer::GetHistograms(GetHistogramsCallback callback) {
  if (!histogram_delta_serializer_) {
    histogram_delta_serializer_.reset(
        new base::HistogramDeltaSerialization("ServiceProcess"));
  }
  std::vector<std::string> deltas;
  // "false" to PerpareAndSerializeDeltas() indicates to *not* include
  // histograms held in persistent storage on the assumption that they will be
  // visible to the recipient through other means.
  histogram_delta_serializer_->PrepareAndSerializeDeltas(&deltas, false);
  std::move(callback).Run(deltas);
}

void ServiceIPCServer::ShutDown() {
  client_->OnShutdown();
}

void ServiceIPCServer::UpdateAvailable() {
  client_->OnUpdateAvailable();
}

void ServiceIPCServer::GetInterface(const std::string& interface_name,
                                    mojo::ScopedMessagePipeHandle pipe) {
  binder_registry_.BindInterface(interface_name, std::move(pipe));
}

void ServiceIPCServer::HandleServiceProcessConnection(
    chrome::mojom::ServiceProcessRequest request) {
  service_process_bindings_.AddBinding(this, std::move(request));
}
