15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/common/service_process_util.h"
66d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/version.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "components/cloud_devices/common/cloud_devices_switches.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_paths.h"
256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "google_apis/gaia/gaia_switches.h"
266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "ui/base/ui_base_switches.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This should be more than enough to hold a version string assuming each part
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the version string is an int64.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kMaxVersionStringLength = 256;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The structure that gets written to shared memory.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ServiceProcessSharedData {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char service_process_version[kMaxVersionStringLength];
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessId service_process_pid;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the name of the shared memory used by the service process to write its
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// version. The name is not versioned.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetServiceProcessSharedMemName() {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetServiceProcessScopedName("_service_shmem");
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ServiceProcessRunningState {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SERVICE_NOT_RUNNING,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SERVICE_OLDER_VERSION_RUNNING,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SERVICE_SAME_VERSION_RUNNING,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SERVICE_NEWER_VERSION_RUNNING,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceProcessRunningState GetServiceProcessRunningState(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* service_version_out, base::ProcessId* pid_out) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string version;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetServiceProcessData(&version, pid_out))
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVICE_NOT_RUNNING;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only need to check for service running on POSIX because Windows cleans
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up shared memory files when an app crashes, so there isn't a chance of
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // us reading bogus data from shared memory for an app that has died.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CheckServiceProcessReady()) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVICE_NOT_RUNNING;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_POSIX)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this time we have a version string. Set the out param if it exists.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_version_out)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *service_version_out = version;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Version service_version(version);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the version string is invalid, treat it like an older version.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service_version.IsValid())
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVICE_OLDER_VERSION_RUNNING;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the version of the currently *running* instance of Chrome.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::VersionInfo version_info;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!version_info.is_valid()) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Failed to get current file version";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Our own version is invalid. This is an error case. Pretend that we
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // are out of date.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVICE_NEWER_VERSION_RUNNING;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Version running_version(version_info.Version());
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!running_version.IsValid()) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Failed to parse version info";
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Our own version is invalid. This is an error case. Pretend that we
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // are out of date.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVICE_NEWER_VERSION_RUNNING;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (running_version.CompareTo(service_version) > 0) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVICE_OLDER_VERSION_RUNNING;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (service_version.CompareTo(running_version) > 0) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SERVICE_NEWER_VERSION_RUNNING;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SERVICE_SAME_VERSION_RUNNING;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return a name that is scoped to this instance of the service process. We
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use the hash of the user-data-dir as a scoping prefix. We can't use
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the user-data-dir itself as we have limits on the size of the lock names.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetServiceProcessScopedName(const std::string& append_str) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath user_data_dir;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string user_data_dir_path = base::WideToUTF8(user_data_dir.value());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string user_data_dir_path = user_data_dir.value();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string hash = base::SHA1HashString(user_data_dir_path);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string hex_hash = base::HexEncode(hash.c_str(), hash.length());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hex_hash + "." + append_str;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return a name that is scoped to this instance of the service process. We
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use the user-data-dir and the version as a scoping prefix.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetServiceProcessScopedVersionedName(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& append_str) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string versioned_str;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::VersionInfo version_info;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(version_info.is_valid());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  versioned_str.append(version_info.Version());
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  versioned_str.append(append_str);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetServiceProcessScopedName(versioned_str);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads the named shared memory to get the shared data. Returns false if no
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// matching shared memory was found.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetServiceProcessData(std::string* version, base::ProcessId* pid) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::SharedMemory> shared_mem_service_data;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shared_mem_service_data.reset(new base::SharedMemory());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServiceProcessSharedData* service_data = NULL;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shared_mem_service_data.get() &&
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shared_mem_service_data->Open(GetServiceProcessSharedMemName(), true) &&
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shared_mem_service_data->Map(sizeof(ServiceProcessSharedData))) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_data = reinterpret_cast<ServiceProcessSharedData*>(
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shared_mem_service_data->memory());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the version in shared memory is null-terminated. If it is not,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // treat it as invalid.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (version && memchr(service_data->service_process_version, '\0',
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          sizeof(service_data->service_process_version)))
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *version = service_data->service_process_version;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pid)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pid = service_data->service_process_pid;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !OS_MACOSX
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)scoped_ptr<base::CommandLine> CreateServiceProcessCommandLine() {
1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  base::FilePath exe_path;
1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  PathService::Get(content::CHILD_PROCESS_EXE, &exe_path);
1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK(!exe_path.empty()) << "Unable to get service process binary name.";
1626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  scoped_ptr<base::CommandLine> command_line(new base::CommandLine(exe_path));
1636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  command_line->AppendSwitchASCII(switches::kProcessType,
1646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  switches::kServiceProcess);
1656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  static const char* const kSwitchesToCopy[] = {
1666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kCloudPrintSetupProxy,
1676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kCloudPrintURL,
1686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kCloudPrintXmppEndpoint,
1696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#if defined(OS_WIN)
1706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kEnableCloudPrintXps,
1716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#endif
1726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kEnableLogging,
1736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kIgnoreUrlFetcherCertRequests,
1746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kLang,
1756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kLoggingLevel,
1766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kLsoUrl,
1776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kNoServiceAutorun,
1786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kUserDataDir,
1796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kV,
1806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kVModule,
1816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    switches::kWaitForDebugger,
1826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  };
1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
1856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                 kSwitchesToCopy,
1866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                 arraysize(kSwitchesToCopy));
1876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return command_line.Pass();
1886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceProcessState::ServiceProcessState() : state_(NULL) {
1916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  autorun_command_line_ = CreateServiceProcessCommandLine();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateState();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceProcessState::~ServiceProcessState() {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shared_mem_service_data_.get()) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shared_mem_service_data_->Delete(GetServiceProcessSharedMemName());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !OS_MACOSX
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TearDownState();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceProcessState::SignalStopped() {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TearDownState();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shared_mem_service_data_.reset();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceProcessState::Initialize() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!TakeSingletonLock()) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now that we have the singleton, take care of killing an older version, if
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it exists.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HandleOtherVersion())
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write the version we are using to shared memory. This can be used by a
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // newer service to signal us to exit.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateSharedData();
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceProcessState::HandleOtherVersion() {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string running_version;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessId process_id = 0;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServiceProcessRunningState state =
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetServiceProcessRunningState(&running_version, &process_id);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SERVICE_SAME_VERSION_RUNNING:
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SERVICE_NEWER_VERSION_RUNNING:
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SERVICE_OLDER_VERSION_RUNNING:
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If an older version is running, kill it.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ForceServiceProcessShutdown(running_version, process_id);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SERVICE_NOT_RUNNING:
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceProcessState::CreateSharedData() {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::VersionInfo version_info;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!version_info.is_valid()) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Failed to get current file version";
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version_info.Version().length() >= kMaxVersionStringLength) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Version string length is << " <<
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        version_info.Version().length() << "which is longer than" <<
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kMaxVersionStringLength;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::SharedMemory> shared_mem_service_data(
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new base::SharedMemory());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!shared_mem_service_data.get())
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 alloc_size = sizeof(ServiceProcessSharedData);
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(viettrungluu): Named shared memory is deprecated (crbug.com/345734).
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!shared_mem_service_data->CreateNamedDeprecated
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          (GetServiceProcessSharedMemName(), true, alloc_size))
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!shared_mem_service_data->Map(alloc_size))
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(shared_mem_service_data->memory(), 0, alloc_size);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServiceProcessSharedData* shared_data =
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<ServiceProcessSharedData*>(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          shared_mem_service_data->memory());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(shared_data->service_process_version, version_info.Version().c_str(),
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         version_info.Version().length());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shared_data->service_process_pid = base::GetCurrentProcId();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shared_mem_service_data_.reset(shared_mem_service_data.release());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPC::ChannelHandle ServiceProcessState::GetServiceProcessChannel() {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ::GetServiceProcessChannel();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !OS_MACOSX
286