// 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/common/service_process_util.h"

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <utility>

#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/path_service.h"
#include "base/sha1.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "components/cloud_devices/common/cloud_devices_switches.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/version_info/version_info.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "google_apis/gaia/gaia_switches.h"
#include "services/network/public/cpp/network_switches.h"
#include "ui/base/ui_base_switches.h"

#if !defined(OS_MACOSX)

namespace {

// This should be more than enough to hold a version string assuming each part
// of the version string is an int64_t.
const uint32_t kMaxVersionStringLength = 256;

// The structure that gets written to shared memory.
struct ServiceProcessSharedData {
  char service_process_version[kMaxVersionStringLength];
  base::ProcessId service_process_pid;
};

// Gets the name of the shared memory used by the service process to write its
// version. The name is not versioned.
std::string GetServiceProcessSharedMemName() {
  return GetServiceProcessScopedName("_service_shmem");
}

enum ServiceProcessRunningState {
  SERVICE_NOT_RUNNING,
  SERVICE_OLDER_VERSION_RUNNING,
  SERVICE_SAME_VERSION_RUNNING,
  SERVICE_NEWER_VERSION_RUNNING,
};

ServiceProcessRunningState GetServiceProcessRunningState(
    std::string* service_version_out, base::ProcessId* pid_out) {
  std::string version;
  if (!GetServiceProcessData(&version, pid_out))
    return SERVICE_NOT_RUNNING;

#if defined(OS_POSIX)
  // We only need to check for service running on POSIX because Windows cleans
  // up shared memory files when an app crashes, so there isn't a chance of
  // us reading bogus data from shared memory for an app that has died.
  if (!CheckServiceProcessReady()) {
    return SERVICE_NOT_RUNNING;
  }
#endif  // defined(OS_POSIX)

  // At this time we have a version string. Set the out param if it exists.
  if (service_version_out)
    *service_version_out = version;

  base::Version service_version(version);
  // If the version string is invalid, treat it like an older version.
  if (!service_version.IsValid())
    return SERVICE_OLDER_VERSION_RUNNING;

  // Get the version of the currently *running* instance of Chrome.
  const base::Version& running_version = version_info::GetVersion();
  if (!running_version.IsValid()) {
    NOTREACHED() << "Failed to parse version info";
    // Our own version is invalid. This is an error case. Pretend that we
    // are out of date.
    return SERVICE_NEWER_VERSION_RUNNING;
  }

  int comp = running_version.CompareTo(service_version);
  if (comp == 0)
    return SERVICE_SAME_VERSION_RUNNING;
  return comp > 0 ? SERVICE_OLDER_VERSION_RUNNING
                  : SERVICE_NEWER_VERSION_RUNNING;
}

}  // namespace


// Return a name that is scoped to this instance of the service process. We
// use the user-data-dir and the version as a scoping prefix.
std::string GetServiceProcessScopedVersionedName(
    const std::string& append_str) {
  std::string versioned_str = version_info::GetVersionNumber();
  versioned_str.append(append_str);
  return GetServiceProcessScopedName(versioned_str);
}

// Reads the named shared memory to get the shared data. Returns false if no
// matching shared memory was found.
bool GetServiceProcessData(std::string* version, base::ProcessId* pid) {
  std::unique_ptr<base::SharedMemory> shared_mem_service_data;
  shared_mem_service_data.reset(new base::SharedMemory());
  ServiceProcessSharedData* service_data = NULL;
  if (shared_mem_service_data.get() &&
      shared_mem_service_data->Open(GetServiceProcessSharedMemName(), true) &&
      shared_mem_service_data->Map(sizeof(ServiceProcessSharedData))) {
    service_data = reinterpret_cast<ServiceProcessSharedData*>(
        shared_mem_service_data->memory());
    // Make sure the version in shared memory is null-terminated. If it is not,
    // treat it as invalid.
    if (version && memchr(service_data->service_process_version, '\0',
                          sizeof(service_data->service_process_version)))
      *version = service_data->service_process_version;
    if (pid)
      *pid = service_data->service_process_pid;
    return true;
  }
  return false;
}

#endif  // !OS_MACOSX

// Return a name that is scoped to this instance of the service process. We
// use the hash of the user-data-dir as a scoping prefix. We can't use
// the user-data-dir itself as we have limits on the size of the lock names.
std::string GetServiceProcessScopedName(const std::string& append_str) {
  base::FilePath user_data_dir;
  base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
#if defined(OS_WIN)
  std::string user_data_dir_path = base::WideToUTF8(user_data_dir.value());
#elif defined(OS_POSIX)
  std::string user_data_dir_path = user_data_dir.value();
#endif  // defined(OS_WIN)
  std::string hash = base::SHA1HashString(user_data_dir_path);
  std::string hex_hash = base::HexEncode(hash.c_str(), hash.length());
  return hex_hash + "." + append_str;
}

std::unique_ptr<base::CommandLine> CreateServiceProcessCommandLine() {
  base::FilePath exe_path;
  base::PathService::Get(content::CHILD_PROCESS_EXE, &exe_path);
  DCHECK(!exe_path.empty()) << "Unable to get service process binary name.";
  std::unique_ptr<base::CommandLine> command_line(
      new base::CommandLine(exe_path));
  command_line->AppendSwitchASCII(switches::kProcessType,
                                  switches::kCloudPrintServiceProcess);

#if defined(OS_WIN)
  command_line->AppendArg(switches::kPrefetchArgumentOther);
#endif  // defined(OS_WIN)

  static const char* const kSwitchesToCopy[] = {
    network::switches::kIgnoreUrlFetcherCertRequests,
    switches::kCloudPrintSetupProxy,
    switches::kCloudPrintURL,
    switches::kCloudPrintXmppEndpoint,
#if defined(OS_WIN)
    switches::kEnableCloudPrintXps,
#endif
    switches::kEnableLogging,
    switches::kLang,
    switches::kLoggingLevel,
    switches::kLsoUrl,
    switches::kNoServiceAutorun,
    switches::kUserDataDir,
    switches::kV,
    switches::kVModule,
    switches::kWaitForDebugger,
  };

  command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
                                 kSwitchesToCopy, base::size(kSwitchesToCopy));
  return command_line;
}

ServiceProcessState::ServiceProcessState() : state_(NULL) {
  autorun_command_line_ = CreateServiceProcessCommandLine();
  CreateState();
}

ServiceProcessState::~ServiceProcessState() {
#if !defined(OS_MACOSX)
  if (shared_mem_service_data_.get()) {
    shared_mem_service_data_->Delete(GetServiceProcessSharedMemName());
  }
#endif  // !OS_MACOSX
  TearDownState();
}

void ServiceProcessState::SignalStopped() {
  TearDownState();
  shared_mem_service_data_.reset();
}

#if !defined(OS_MACOSX)
bool ServiceProcessState::Initialize() {
  if (!TakeSingletonLock()) {
    return false;
  }
  // Now that we have the singleton, take care of killing an older version, if
  // it exists.
  if (!HandleOtherVersion())
    return false;

  // Write the version we are using to shared memory. This can be used by a
  // newer service to signal us to exit.
  return CreateSharedData();
}

bool ServiceProcessState::HandleOtherVersion() {
  std::string running_version;
  base::ProcessId process_id = 0;
  ServiceProcessRunningState state =
      GetServiceProcessRunningState(&running_version, &process_id);
  switch (state) {
    case SERVICE_SAME_VERSION_RUNNING:
    case SERVICE_NEWER_VERSION_RUNNING:
      return false;
    case SERVICE_OLDER_VERSION_RUNNING:
      // If an older version is running, kill it.
      ForceServiceProcessShutdown(running_version, process_id);
      break;
    case SERVICE_NOT_RUNNING:
      break;
  }
  return true;
}

bool ServiceProcessState::CreateSharedData() {
  if (version_info::GetVersionNumber().length() >= kMaxVersionStringLength) {
    NOTREACHED() << "Version string length is << "
                 << version_info::GetVersionNumber().length()
                 << " which is longer than" << kMaxVersionStringLength;
    return false;
  }

  std::unique_ptr<base::SharedMemory> shared_mem_service_data(
      new base::SharedMemory());
  if (!shared_mem_service_data.get())
    return false;

  uint32_t alloc_size = sizeof(ServiceProcessSharedData);
  // TODO(viettrungluu): Named shared memory is deprecated (crbug.com/345734).
  if (!shared_mem_service_data->CreateNamedDeprecated
          (GetServiceProcessSharedMemName(), true, alloc_size))
    return false;

  if (!shared_mem_service_data->Map(alloc_size))
    return false;

  memset(shared_mem_service_data->memory(), 0, alloc_size);
  ServiceProcessSharedData* shared_data =
      reinterpret_cast<ServiceProcessSharedData*>(
          shared_mem_service_data->memory());
  memcpy(shared_data->service_process_version,
         version_info::GetVersionNumber().c_str(),
         version_info::GetVersionNumber().length());
  shared_data->service_process_pid = base::GetCurrentProcId();
  shared_mem_service_data_ = std::move(shared_mem_service_data);
  return true;
}

mojo::NamedPlatformChannel::ServerName
ServiceProcessState::GetServiceProcessServerName() {
  return ::GetServiceProcessServerName();
}

#endif  // !OS_MACOSX
