15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 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/browser/process_singleton.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <fcntl.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <signal.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <sys/un.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/wait.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/posix/eintr_wrapper.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/thread_test_helper.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass ProcessSingletonPosixTest : public testing::Test {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A ProcessSingleton exposing some protected methods for testing.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class TestableProcessSingleton : public ProcessSingleton {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    explicit TestableProcessSingleton(const base::FilePath& user_data_dir)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        : ProcessSingleton(
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            user_data_dir,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            base::Bind(&TestableProcessSingleton::NotificationCallback,
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       base::Unretained(this))) {}
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<CommandLine::StringVector> callback_command_lines_;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    using ProcessSingleton::NotifyOtherProcessWithTimeout;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    using ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    using ProcessSingleton::OverrideCurrentPidForTesting;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    using ProcessSingleton::OverrideKillCallbackForTesting;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   private:
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool NotificationCallback(const CommandLine& command_line,
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              const base::FilePath& current_directory) {
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback_command_lines_.push_back(command_line.argv());
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return true;
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ProcessSingletonPosixTest()
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : kill_callbacks_(0),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_thread_(BrowserThread::IO),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wait_event_(true, false),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        signal_event_(true, false),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        process_singleton_on_thread_(NULL) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_thread_.StartIOThread();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    testing::Test::SetUp();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessSingleton::DisablePromptForTesting();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Put the lock in a temporary directory.  Doesn't need to be a
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // full profile to test this code.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Use a long directory name to ensure that the socket isn't opened through
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // the symlink.
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    user_data_path_ = temp_dir_.path().Append(
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        std::string(sizeof(sockaddr_un::sun_path), 'a'));
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ASSERT_TRUE(CreateDirectory(user_data_path_));
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    lock_path_ = user_data_path_.Append(chrome::kSingletonLockFilename);
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    socket_path_ = user_data_path_.Append(chrome::kSingletonSocketFilename);
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    cookie_path_ = user_data_path_.Append(chrome::kSingletonCookieFilename);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::ThreadTestHelper> io_helper(new base::ThreadTestHelper(
947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(io_helper->Run());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Destruct the ProcessSingleton object before the IO thread so that its
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // internals are destructed properly.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (process_singleton_on_thread_) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      worker_thread_->message_loop()->PostTask(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          base::Bind(&ProcessSingletonPosixTest::DestructProcessSingleton,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          worker_thread_->message_loop_proxy().get()));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(helper->Run());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_thread_.Stop();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    testing::Test::TearDown();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateProcessSingletonOnThread() {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(NULL, worker_thread_.get());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    worker_thread_.reset(new base::Thread("BlockingThread"));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    worker_thread_->Start();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    worker_thread_->message_loop()->PostTask(
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       FROM_HERE,
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       base::Bind(&ProcessSingletonPosixTest::
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      CreateProcessSingletonInternal,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::Unretained(this)));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::ThreadTestHelper> helper(
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        new base::ThreadTestHelper(worker_thread_->message_loop_proxy().get()));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(helper->Run());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestableProcessSingleton* CreateProcessSingleton() {
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return new TestableProcessSingleton(user_data_path_);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void VerifyFiles() {
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    struct stat statbuf;
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_EQ(0, lstat(lock_path_.value().c_str(), &statbuf));
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_TRUE(S_ISLNK(statbuf.st_mode));
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    char buf[PATH_MAX];
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ssize_t len = readlink(lock_path_.value().c_str(), buf, PATH_MAX);
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_GT(len, 0);
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_EQ(0, lstat(socket_path_.value().c_str(), &statbuf));
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_TRUE(S_ISLNK(statbuf.st_mode));
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    len = readlink(socket_path_.value().c_str(), buf, PATH_MAX);
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_GT(len, 0);
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::FilePath socket_target_path = base::FilePath(std::string(buf, len));
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_EQ(0, lstat(socket_target_path.value().c_str(), &statbuf));
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_TRUE(S_ISSOCK(statbuf.st_mode));
1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    len = readlink(cookie_path_.value().c_str(), buf, PATH_MAX);
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_GT(len, 0);
1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::string cookie(buf, len);
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::FilePath remote_cookie_path = socket_target_path.DirName().
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        Append(chrome::kSingletonCookieFilename);
1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    len = readlink(remote_cookie_path.value().c_str(), buf, PATH_MAX);
1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ASSERT_GT(len, 0);
1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    EXPECT_EQ(cookie, std::string(buf, len));
1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ProcessSingleton::NotifyResult NotifyOtherProcess(bool override_kill) {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<TestableProcessSingleton> process_singleton(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CreateProcessSingleton());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine command_line(CommandLine::ForCurrentProcess()->GetProgram());
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line.AppendArg("about:blank");
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (override_kill) {
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      process_singleton->OverrideCurrentPidForTesting(
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::GetCurrentProcId() + 1);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      process_singleton->OverrideKillCallbackForTesting(
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          base::Bind(&ProcessSingletonPosixTest::KillCallback,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return process_singleton->NotifyOtherProcessWithTimeout(
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        command_line, kRetryAttempts, timeout(), true);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A helper method to call ProcessSingleton::NotifyOtherProcessOrCreate().
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessSingleton::NotifyResult NotifyOtherProcessOrCreate(
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const std::string& url) {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<TestableProcessSingleton> process_singleton(
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CreateProcessSingleton());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine command_line(CommandLine::ForCurrentProcess()->GetProgram());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line.AppendArg(url);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return process_singleton->NotifyOtherProcessWithTimeoutOrCreate(
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        command_line, kRetryAttempts, timeout());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckNotified() {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(process_singleton_on_thread_ != NULL);
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(1u, process_singleton_on_thread_->callback_command_lines_.size());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found = false;
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (size_t i = 0;
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         i < process_singleton_on_thread_->callback_command_lines_[0].size();
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         ++i) {
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (process_singleton_on_thread_->callback_command_lines_[0][i] ==
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          "about:blank") {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found = true;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(found);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(0, kill_callbacks_);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BlockWorkerThread() {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    worker_thread_->message_loop()->PostTask(
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        base::Bind(&ProcessSingletonPosixTest::BlockThread,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnblockWorkerThread() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_event_.Signal();  // Unblock the worker thread for shutdown.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signal_event_.Wait();  // Ensure thread unblocks before continuing.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BlockThread() {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_event_.Wait();
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signal_event_.Signal();
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::FilePath user_data_path_;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath lock_path_;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath socket_path_;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath cookie_path_;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int kill_callbacks_;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static const int kRetryAttempts = 2;
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::TimeDelta timeout() const {
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return TestTimeouts::tiny_timeout() * kRetryAttempts;
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateProcessSingletonInternal() {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(!process_singleton_on_thread_);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_singleton_on_thread_ = CreateProcessSingleton();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ProcessSingleton::PROCESS_NONE,
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              process_singleton_on_thread_->NotifyOtherProcessOrCreate());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DestructProcessSingleton() {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(process_singleton_on_thread_);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete process_singleton_on_thread_;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void KillCallback(int pid) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kill_callbacks_++;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread io_thread_;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir temp_dir_;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent wait_event_;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent signal_event_;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Thread> worker_thread_;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestableProcessSingleton* process_singleton_on_thread_;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Test if the socket file and symbol link created by ProcessSingletonPosix
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are valid.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If this test flakes, use http://crbug.com/74554.
2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, CheckSocketFile) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  VerifyFiles();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(james.su@gmail.com): port following tests to Windows.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test success case of NotifyOtherProcess().
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, NotifyOtherProcessSuccess) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED, NotifyOtherProcess(true));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckNotified();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test failure case of NotifyOtherProcess().
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, NotifyOtherProcessFailure) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockWorkerThread();
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ProcessSingleton::PROCESS_NONE, NotifyOtherProcess(true));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1, kill_callbacks_);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnblockWorkerThread();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we don't kill ourselves by accident if a lockfile with the same pid
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// happens to exist.
2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, NotifyOtherProcessNoSuicide) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace lockfile with one containing our own pid.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string symlink_content = base::StringPrintf(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "%s%c%u",
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::GetHostName().c_str(),
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '-',
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::GetCurrentProcId());
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, symlink(symlink_content.c_str(), lock_path_.value().c_str()));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove socket so that we will not be able to notify the existing browser.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, unlink(socket_path_.value().c_str()));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ProcessSingleton::PROCESS_NONE, NotifyOtherProcess(false));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we've gotten to this point without killing ourself, the test succeeded.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we can still notify a process on the same host even after the
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hostname changed.
3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, NotifyOtherProcessHostChanged) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED, NotifyOtherProcess(false));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckNotified();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we fail when lock says process is on another host and we can't
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notify it over the socket.
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, NotifyOtherProcessDifferingHost) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockWorkerThread();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE, NotifyOtherProcess(false));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnblockWorkerThread();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we fail when lock says process is on another host and we can't
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notify it over the socket.
3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, NotifyOtherProcessOrCreate_DifferingHost) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockWorkerThread();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url("about:blank");
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE, NotifyOtherProcessOrCreate(url));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnblockWorkerThread();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that Create fails when another browser is using the profile directory.
3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, CreateFailsWithExistingBrowser) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TestableProcessSingleton> process_singleton(
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProcessSingleton());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_singleton->OverrideCurrentPidForTesting(base::GetCurrentProcId() + 1);
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(process_singleton->Create());
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that Create fails when another browser is using the profile directory
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but with the old socket location.
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, CreateChecksCompatibilitySocket) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TestableProcessSingleton> process_singleton(
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateProcessSingleton());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_singleton->OverrideCurrentPidForTesting(base::GetCurrentProcId() + 1);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do some surgery so as to look like the old configuration.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[PATH_MAX];
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t len = readlink(socket_path_.value().c_str(), buf, sizeof(buf));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(len, 0);
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath socket_target_path = base::FilePath(std::string(buf, len));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, unlink(socket_path_.value().c_str()));
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, rename(socket_target_path.value().c_str(),
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      socket_path_.value().c_str()));
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, unlink(cookie_path_.value().c_str()));
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(process_singleton->Create());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we fail when lock says process is on another host and we can't
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notify it over the socket before of a bad cookie.
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, NotifyOtherProcessOrCreate_BadCookie) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateProcessSingletonOnThread();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change the cookie.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, unlink(cookie_path_.value().c_str()));
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, symlink("INCORRECTCOOKIE", cookie_path_.value().c_str()));
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Also change the hostname, so the remote does not retry.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url("about:blank");
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE, NotifyOtherProcessOrCreate(url));
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(OS_MACOSX)
4055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Test that if there is an existing lock file, and we could not flock()
4065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// it, then exit.
4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, CreateRespectsOldMacLock) {
4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<TestableProcessSingleton> process_singleton(
4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateProcessSingleton());
4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::ScopedFD lock_fd(HANDLE_EINTR(
4115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      open(lock_path_.value().c_str(), O_RDWR | O_CREAT | O_EXLOCK, 0644)));
4125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(lock_fd.is_valid());
4135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(process_singleton->Create());
4145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::File::Info info;
4155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(base::GetFileInfo(lock_path_, &info));
4165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(info.is_directory);
4175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(info.is_symbolic_link);
4185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Test that if there is an existing lock file, and it's not locked, we replace
4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// it.
4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(ProcessSingletonPosixTest, CreateReplacesOldMacLock) {
4235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<TestableProcessSingleton> process_singleton(
4245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateProcessSingleton());
4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(0, base::WriteFile(lock_path_, "", 0));
4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(process_singleton->Create());
4275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  VerifyFiles();
4285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif  // defined(OS_MACOSX)
430