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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/mac/mock_launchd.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CoreFoundation/CoreFoundation.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/un.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/foundation_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_cftyperef.h"
169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/mac/launchd.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/service_process_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sockaddr_un* throwaway_sockaddr_un;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kMaxPipeNameLength =
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(throwaway_sockaddr_un->sun_path);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool MockLaunchd::MakeABundle(const base::FilePath& dst,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& name,
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              base::FilePath* bundle_root,
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              base::FilePath* executable) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *bundle_root = dst.Append(name + std::string(".app"));
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath contents = bundle_root->AppendASCII("Contents");
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath mac_os = contents.AppendASCII("MacOS");
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *executable = mac_os.Append(name);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath info_plist = contents.Append("Info.plist");
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_util::CreateDirectory(mac_os)) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *data = "#! testbundle\n";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = strlen(data);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_util::WriteFile(*executable, data, len) != len) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chmod(executable->value().c_str(), 0555) != 0) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::VersionInfo version_info;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* info_plist_format =
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<plist version=\"1.0\">\n"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<dict>\n"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <key>CFBundleDevelopmentRegion</key>\n"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <string>English</string>\n"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <key>CFBundleExecutable</key>\n"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <string>%s</string>\n"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <key>CFBundleIdentifier</key>\n"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <string>com.test.%s</string>\n"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <key>CFBundleInfoDictionaryVersion</key>\n"
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <string>6.0</string>\n"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <key>CFBundleShortVersionString</key>\n"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <string>%s</string>\n"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <key>CFBundleVersion</key>\n"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  <string>1</string>\n"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "</dict>\n"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "</plist>\n";
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string info_plist_data =
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPrintf(info_plist_format,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         name.c_str(),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         name.c_str(),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         version_info.Version().c_str());
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  len = info_plist_data.length();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_util::WriteFile(info_plist, info_plist_data.c_str(), len) != len) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const UInt8* bundle_root_path =
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const UInt8*>(bundle_root->value().c_str());
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFURLRef> url(
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              bundle_root_path,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              bundle_root->value().length(),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              true));
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFBundleRef> bundle(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFBundleCreate(kCFAllocatorDefault, url));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bundle.get();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)MockLaunchd::MockLaunchd(const base::FilePath& file,
96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                         base::MessageLoop* loop,
97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                         bool create_socket,
98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                         bool as_service)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : file_(file),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_loop_(loop),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      create_socket_(create_socket),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      as_service_(as_service),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restart_called_(false),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remove_called_(false),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checkin_called_(false),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_called_(false),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete_called_(false) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string pipe_suffix("_SOCKET");
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath socket_path = file_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (socket_path.value().length() + pipe_suffix.length() >
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         kMaxPipeNameLength - 2) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_path = socket_path.DirName();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pipe_name_ = socket_path.value() + pipe_suffix;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MockLaunchd::~MockLaunchd() {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFDictionaryRef MockLaunchd::CopyExports() {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!create_socket_) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ADD_FAILURE();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef env_var =
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::mac::NSToCFCast(GetServiceProcessLaunchDSocketEnvVar());
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFStringRef> socket_path(CFStringCreateWithCString(
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kCFAllocatorDefault, pipe_name_.c_str(), kCFStringEncodingUTF8));
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *keys[] = { env_var };
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *values[] = { socket_path };
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(arraysize(keys) == arraysize(values), array_sizes_must_match);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CFDictionaryCreate(kCFAllocatorDefault,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            keys,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            values,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            arraysize(keys),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &kCFTypeDictionaryKeyCallBacks,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &kCFTypeDictionaryValueCallBacks);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFDictionaryRef MockLaunchd::CopyJobDictionary(CFStringRef label) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!as_service_) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<MultiProcessLock> running_lock(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TakeNamedLock(pipe_name_, false));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (running_lock.get())
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef program = CFSTR(LAUNCH_JOBKEY_PROGRAM);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef program_pid = CFSTR(LAUNCH_JOBKEY_PID);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *keys[] = { program, program_pid };
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFStringRef> path(
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SysUTF8ToCFStringRef(file_.value()));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int process_id = base::GetCurrentProcId();
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFNumberRef> pid(
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFNumberCreate(NULL, kCFNumberIntType, &process_id));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *values[] = { path, pid };
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(arraysize(keys) == arraysize(values), array_sizes_must_match);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CFDictionaryCreate(kCFAllocatorDefault,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            keys,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            values,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            arraysize(keys),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &kCFTypeDictionaryKeyCallBacks,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &kCFTypeDictionaryValueCallBacks);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFDictionaryRef MockLaunchd::CopyDictionaryByCheckingIn(CFErrorRef* error) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checkin_called_ = true;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef program = CFSTR(LAUNCH_JOBKEY_PROGRAM);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef program_args = CFSTR(LAUNCH_JOBKEY_PROGRAMARGUMENTS);
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFStringRef> path(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SysUTF8ToCFStringRef(file_.value()));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *array_values[] = { path.get() };
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFArrayRef> args(CFArrayCreate(
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kCFAllocatorDefault, array_values, 1, &kCFTypeArrayCallBacks));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!create_socket_) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void *keys[] = { program, program_args };
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void *values[] = { path, args };
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    COMPILE_ASSERT(arraysize(keys) == arraysize(values),
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   array_sizes_must_match);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CFDictionaryCreate(kCFAllocatorDefault,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              keys,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              values,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              arraysize(keys),
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &kCFTypeDictionaryKeyCallBacks,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &kCFTypeDictionaryValueCallBacks);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef socket_key = CFSTR(LAUNCH_JOBKEY_SOCKETS);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int local_pipe = -1;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(as_service_);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create unix_addr structure.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sockaddr_un unix_addr = {0};
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unix_addr.sun_family = AF_UNIX;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t path_len =
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::strlcpy(unix_addr.sun_path, pipe_name_.c_str(), kMaxPipeNameLength);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(pipe_name_.length(), path_len);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unix_addr.sun_len = SUN_LEN(&unix_addr);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFSocketSignature signature;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature.protocolFamily = PF_UNIX;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature.socketType = SOCK_STREAM;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature.protocol = 0;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t unix_addr_len = offsetof(struct sockaddr_un,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  sun_path) + path_len + 1;
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFDataRef> address(
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFDataCreate(NULL, reinterpret_cast<UInt8*>(&unix_addr), unix_addr_len));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature.address = address;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFSocketRef socket =
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFSocketCreateWithSocketSignature(NULL, &signature, 0, NULL, NULL);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_pipe = CFSocketGetNative(socket);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(-1, local_pipe);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (local_pipe == -1) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             errno, NULL);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFNumberRef> socket_fd(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFNumberCreate(NULL, kCFNumberIntType, &local_pipe));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *socket_array_values[] = { socket_fd };
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFArrayRef> sockets(CFArrayCreate(
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kCFAllocatorDefault, socket_array_values, 1, &kCFTypeArrayCallBacks));
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFStringRef socket_dict_key = CFSTR("ServiceProcessSocket");
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *socket_keys[] = { socket_dict_key };
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *socket_values[] = { sockets };
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(arraysize(socket_keys) == arraysize(socket_values),
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 socket_array_sizes_must_match);
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFDictionaryRef> socket_dict(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFDictionaryCreate(kCFAllocatorDefault,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         socket_keys,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         socket_values,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         arraysize(socket_keys),
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &kCFTypeDictionaryKeyCallBacks,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &kCFTypeDictionaryValueCallBacks));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *keys[] = { program, program_args, socket_key };
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *values[] = { path, args, socket_dict };
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(arraysize(keys) == arraysize(values), array_sizes_must_match);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CFDictionaryCreate(kCFAllocatorDefault,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            keys,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            values,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            arraysize(keys),
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &kCFTypeDictionaryKeyCallBacks,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &kCFTypeDictionaryValueCallBacks);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MockLaunchd::RemoveJob(CFStringRef label, CFErrorRef* error) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remove_called_ = true;
255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  message_loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MockLaunchd::RestartJob(Domain domain,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             Type type,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             CFStringRef name,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             CFStringRef session_type) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  restart_called_ = true;
264a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  message_loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CFMutableDictionaryRef MockLaunchd::CreatePlistFromFile(
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Domain domain,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type type,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CFStringRef name)  {
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ScopedCFTypeRef<CFDictionaryRef> dict(CopyDictionaryByCheckingIn(NULL));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MockLaunchd::WritePlistToFile(Domain domain,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   Type type,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   CFStringRef name,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   CFDictionaryRef dict) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_called_ = true;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MockLaunchd::DeletePlist(Domain domain,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              Type type,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              CFStringRef name) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete_called_ = true;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MockLaunchd::SignalReady() {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(as_service_);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  running_lock_.reset(TakeNamedLock(pipe_name_, true));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295