// Copyright (c) 2011 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/common/service_process_util.h"

#include <windows.h>

#include <algorithm>
#include <memory>

#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/object_watcher.h"
#include "base/win/scoped_handle.h"
#include "base/win/win_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"

namespace {

const char kTerminateEventSuffix[] = "_service_terminate_evt";

base::string16 GetServiceProcessReadyEventName() {
  return base::UTF8ToWide(
      GetServiceProcessScopedVersionedName("_service_ready"));
}

base::string16 GetServiceProcessTerminateEventName() {
  return base::UTF8ToWide(
      GetServiceProcessScopedVersionedName(kTerminateEventSuffix));
}

std::string GetServiceProcessAutoRunKey() {
  return GetServiceProcessScopedName("_service_run");
}

// Returns the name of the autotun reg value that we used to use for older
// versions of Chrome.
std::string GetObsoleteServiceProcessAutoRunKey() {
  base::FilePath user_data_dir;
  base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  std::string scoped_name = base::WideToUTF8(user_data_dir.value());
  std::replace(scoped_name.begin(), scoped_name.end(), '\\', '!');
  std::replace(scoped_name.begin(), scoped_name.end(), '/', '!');
  scoped_name.append("_service_run");
  return scoped_name;
}

class ServiceProcessTerminateMonitor
    : public base::win::ObjectWatcher::Delegate {
 public:
  explicit ServiceProcessTerminateMonitor(const base::Closure& terminate_task)
      : terminate_task_(terminate_task) {
  }
  void Start() {
    base::string16 event_name = GetServiceProcessTerminateEventName();
    DCHECK(event_name.length() <= MAX_PATH);
    terminate_event_.Set(CreateEvent(NULL, TRUE, FALSE, event_name.c_str()));
    watcher_.StartWatchingOnce(terminate_event_.Get(), this);
  }

  // base::ObjectWatcher::Delegate implementation.
  void OnObjectSignaled(HANDLE object) override {
    if (!terminate_task_.is_null()) {
      terminate_task_.Run();
      terminate_task_.Reset();
    }
  }

 private:
  base::win::ScopedHandle terminate_event_;
  base::win::ObjectWatcher watcher_;
  base::Closure terminate_task_;
};

}  // namespace

// Gets the name of the service process IPC channel.
mojo::NamedPlatformChannel::ServerName GetServiceProcessServerName() {
  return mojo::NamedPlatformChannel::ServerNameFromUTF8(
      GetServiceProcessScopedVersionedName("_service_ipc"));
}

bool ForceServiceProcessShutdown(const std::string& version,
                                 base::ProcessId process_id) {
  base::win::ScopedHandle terminate_event;
  std::string versioned_name = version;
  versioned_name.append(kTerminateEventSuffix);
  base::string16 event_name =
      base::UTF8ToWide(GetServiceProcessScopedName(versioned_name));
  terminate_event.Set(OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name.c_str()));
  if (!terminate_event.IsValid())
    return false;
  SetEvent(terminate_event.Get());
  return true;
}

bool CheckServiceProcessReady() {
  base::string16 event_name = GetServiceProcessReadyEventName();
  base::win::ScopedHandle event(
      OpenEvent(SYNCHRONIZE | READ_CONTROL, false, event_name.c_str()));
  if (!event.IsValid())
    return false;
  // Check if the event is signaled.
  return WaitForSingleObject(event.Get(), 0) == WAIT_OBJECT_0;
}

struct ServiceProcessState::StateData {
  // An event that is signaled when a service process is ready.
  base::win::ScopedHandle ready_event;
  std::unique_ptr<ServiceProcessTerminateMonitor> terminate_monitor;
};

void ServiceProcessState::CreateState() {
  DCHECK(!state_);
  state_ = new StateData;
}

bool ServiceProcessState::TakeSingletonLock() {
  DCHECK(state_);
  base::string16 event_name = GetServiceProcessReadyEventName();
  DCHECK(event_name.length() <= MAX_PATH);
  base::win::ScopedHandle service_process_ready_event;
  service_process_ready_event.Set(
      CreateEvent(NULL, TRUE, FALSE, event_name.c_str()));
  DWORD error = GetLastError();
  if ((error == ERROR_ALREADY_EXISTS) || (error == ERROR_ACCESS_DENIED))
    return false;
  DCHECK(service_process_ready_event.IsValid());
  state_->ready_event.Set(service_process_ready_event.Take());
  return true;
}

bool ServiceProcessState::SignalReady(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    const base::Closure& terminate_task) {
  DCHECK(state_);
  DCHECK(state_->ready_event.IsValid());
  if (!SetEvent(state_->ready_event.Get())) {
    return false;
  }
  if (!terminate_task.is_null()) {
    state_->terminate_monitor.reset(
        new ServiceProcessTerminateMonitor(terminate_task));
    state_->terminate_monitor->Start();
  }
  return true;
}

bool ServiceProcessState::AddToAutoRun() {
  DCHECK(autorun_command_line_.get());
  // Remove the old autorun value first because we changed the naming scheme
  // for the autorun value name.
  base::win::RemoveCommandFromAutoRun(
      HKEY_CURRENT_USER,
      base::UTF8ToWide(GetObsoleteServiceProcessAutoRunKey()));
  return base::win::AddCommandToAutoRun(
      HKEY_CURRENT_USER,
      base::UTF8ToWide(GetServiceProcessAutoRunKey()),
      autorun_command_line_->GetCommandLineString());
}

bool ServiceProcessState::RemoveFromAutoRun() {
  // Remove the old autorun value first because we changed the naming scheme
  // for the autorun value name.
  base::win::RemoveCommandFromAutoRun(
      HKEY_CURRENT_USER,
      base::UTF8ToWide(GetObsoleteServiceProcessAutoRunKey()));
  return base::win::RemoveCommandFromAutoRun(
      HKEY_CURRENT_USER, base::UTF8ToWide(GetServiceProcessAutoRunKey()));
}

void ServiceProcessState::TearDownState() {
  delete state_;
  state_ = NULL;
}
