172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/process_singleton.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <sys/types.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <sys/wait.h>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <signal.h>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <unistd.h>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/eintr_wrapper.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/test/test_timeouts.h"
183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h"
224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/chrome_switches.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/test/chrome_process_util.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/test/ui/ui_test.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ProcessSingletonLinuxTest : public UITest {
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void SetUp() {
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    UITest::SetUp();
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    lock_path_ = user_data_dir().Append(chrome::kSingletonLockFilename);
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    socket_path_ = user_data_dir().Append(chrome::kSingletonSocketFilename);
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    cookie_path_ = user_data_dir().Append(chrome::kSingletonCookieFilename);
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void TearDown() {
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    UITest::TearDown();
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Check that the test cleaned up after itself.
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    struct stat statbuf;
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool lock_exists = lstat(lock_path_.value().c_str(), &statbuf) == 0;
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_FALSE(lock_exists);
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (lock_exists) {
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Unlink to prevent failing future tests if the lock still exists.
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ(unlink(lock_path_.value().c_str()), 0);
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath lock_path_;
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath socket_path_;
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath cookie_path_;
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessSingleton* CreateProcessSingleton() {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath user_data_dir;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new ProcessSingleton(user_data_dir);
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCommandLine CommandLineForUrl(const std::string& url) {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Hack: mutate the current process's command line so we don't show a dialog.
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note that this only works if we have no loose values on the command line,
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // but that's fine for unit tests.  In a UI test we disable error dialogs
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // when spawning Chrome, but this test hits the ProcessSingleton directly.
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CommandLine* cmd_line = CommandLine::ForCurrentProcess();
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!cmd_line->HasSwitch(switches::kNoProcessSingletonDialog))
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cmd_line->AppendSwitch(switches::kNoProcessSingletonDialog);
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CommandLine new_cmd_line(*cmd_line);
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  new_cmd_line.AppendArg(url);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new_cmd_line;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A helper method to call ProcessSingleton::NotifyOtherProcess().
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |url| will be added to CommandLine for current process, so that it can be
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// sent to browser process by ProcessSingleton::NotifyOtherProcess().
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessSingleton::NotifyResult NotifyOtherProcess(const std::string& url,
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  int timeout_ms) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<ProcessSingleton> process_singleton(CreateProcessSingleton());
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return process_singleton->NotifyOtherProcessWithTimeout(
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CommandLineForUrl(url), timeout_ms / 1000, true);
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A helper method to call ProcessSingleton::NotifyOtherProcessOrCreate().
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |url| will be added to CommandLine for current process, so that it can be
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// sent to browser process by ProcessSingleton::NotifyOtherProcessOrCreate().
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessSingleton::NotifyResult NotifyOtherProcessOrCreate(
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& url,
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int timeout_ms) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<ProcessSingleton> process_singleton(CreateProcessSingleton());
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return process_singleton->NotifyOtherProcessWithTimeoutOrCreate(
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CommandLineForUrl(url), timeout_ms / 1000);
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test if the socket file and symbol link created by ProcessSingletonLinux
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// are valid. When running this test, the ProcessSingleton object is already
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// initiated by UITest. So we just test against this existing object.
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// This test is flaky as per http://crbug.com/74554.
106dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ProcessSingletonLinuxTest, FLAKY_CheckSocketFile) {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct stat statbuf;
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, lstat(lock_path_.value().c_str(), &statbuf));
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(S_ISLNK(statbuf.st_mode));
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char buf[PATH_MAX];
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ssize_t len = readlink(lock_path_.value().c_str(), buf, PATH_MAX);
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_GT(len, 0);
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, lstat(socket_path_.value().c_str(), &statbuf));
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(S_ISLNK(statbuf.st_mode));
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  len = readlink(socket_path_.value().c_str(), buf, PATH_MAX);
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_GT(len, 0);
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath socket_target_path = FilePath(std::string(buf, len));
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, lstat(socket_target_path.value().c_str(), &statbuf));
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(S_ISSOCK(statbuf.st_mode));
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  len = readlink(cookie_path_.value().c_str(), buf, PATH_MAX);
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_GT(len, 0);
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string cookie(buf, len);
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath remote_cookie_path = socket_target_path.DirName().
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      Append(chrome::kSingletonCookieFilename);
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  len = readlink(remote_cookie_path.value().c_str(), buf, PATH_MAX);
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_GT(len, 0);
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(cookie, std::string(buf, len));
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The following tests in linux/view does not pass without a window manager,
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// which is true in build/try bots.
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// See http://crbug.com/30953.
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define NotifyOtherProcessSuccess FAILS_NotifyOtherProcessSuccess
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define NotifyOtherProcessHostChanged FAILS_NotifyOtherProcessHostChanged
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(james.su@gmail.com): port following tests to Windows.
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test success case of NotifyOtherProcess().
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessSuccess) {
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url("about:blank");
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int original_tab_count = GetTabCount();
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED,
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(original_tab_count + 1, GetTabCount());
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(url, GetActiveTabURL().spec());
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test failure case of NotifyOtherProcess().
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessFailure) {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::ProcessId pid = browser_process_id();
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_GE(pid, 1);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Block the browser process, then it'll be killed by
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ProcessSingleton::NotifyOtherProcess().
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kill(pid, SIGSTOP);
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Wait to make sure the browser process is actually stopped.
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It's necessary when running with valgrind.
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_GE(HANDLE_EINTR(waitpid(pid, 0, WUNTRACED)), 0);
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url("about:blank");
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ProcessSingleton::PROCESS_NONE,
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Wait for a while to make sure the browser process is actually killed.
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int exit_code = 0;
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(launcher_->WaitForBrowserProcessToQuit(
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                  TestTimeouts::action_max_timeout_ms(), &exit_code));
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(-1, exit_code);  // Expect unclean shutdown.
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that we don't kill ourselves by accident if a lockfile with the same pid
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// happens to exist.
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(mattm): This doesn't really need to be a uitest.  (We don't use the
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// uitest created browser process, but we do use some uitest provided stuff like
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the user_data_dir and the NotifyOtherProcess function in this file, which
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// would have to be duplicated or shared if this test was moved into a
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// unittest.)
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessNoSuicide) {
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Replace lockfile with one containing our own pid.
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string symlink_content = StringPrintf(
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "%s%c%u",
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::GetHostName().c_str(),
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      '-',
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::GetCurrentProcId());
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, symlink(symlink_content.c_str(), lock_path_.value().c_str()));
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Remove socket so that we will not be able to notify the existing browser.
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, unlink(socket_path_.value().c_str()));
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url("about:blank");
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ProcessSingleton::PROCESS_NONE,
20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we've gotten to this point without killing ourself, the test succeeded.
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that we can still notify a process on the same host even after the
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// hostname changed.
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessHostChanged) {
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int original_tab_count = GetTabCount();
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url("about:blank");
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED,
21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(original_tab_count + 1, GetTabCount());
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(url, GetActiveTabURL().spec());
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that we fail when lock says process is on another host and we can't
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// notify it over the socket.
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessDifferingHost) {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::ProcessId pid = browser_process_id();
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_GE(pid, 1);
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Kill the browser process, so that it does not respond on the socket.
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kill(pid, SIGKILL);
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Wait for a while to make sure the browser process is actually killed.
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int exit_code = 0;
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(launcher_->WaitForBrowserProcessToQuit(
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                  TestTimeouts::action_max_timeout_ms(), &exit_code));
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(-1, exit_code);  // Expect unclean shutdown.
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url("about:blank");
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            NotifyOtherProcess(url, TestTimeouts::action_timeout_ms()));
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that we fail when lock says process is on another host and we can't
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// notify it over the socket.
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessOrCreate_DifferingHost) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::ProcessId pid = browser_process_id();
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_GE(pid, 1);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Kill the browser process, so that it does not respond on the socket.
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kill(pid, SIGKILL);
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Wait for a while to make sure the browser process is actually killed.
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int exit_code = 0;
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_TRUE(launcher_->WaitForBrowserProcessToQuit(
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                  TestTimeouts::action_max_timeout_ms(), &exit_code));
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(-1, exit_code);  // Expect unclean shutdown.
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url("about:blank");
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            NotifyOtherProcessOrCreate(url, TestTimeouts::action_timeout_ms()));
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, unlink(lock_path_.value().c_str()));
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that Create fails when another browser is using the profile directory.
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessSingletonLinuxTest, CreateFailsWithExistingBrowser) {
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<ProcessSingleton> process_singleton(CreateProcessSingleton());
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_FALSE(process_singleton->Create());
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that Create fails when another browser is using the profile directory
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// but with the old socket location.
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_F(ProcessSingletonLinuxTest, CreateChecksCompatibilitySocket) {
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<ProcessSingleton> process_singleton(CreateProcessSingleton());
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Do some surgery so as to look like the old configuration.
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char buf[PATH_MAX];
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ssize_t len = readlink(socket_path_.value().c_str(), buf, sizeof(buf));
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_GT(len, 0);
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath socket_target_path = FilePath(std::string(buf, len));
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, unlink(socket_path_.value().c_str()));
2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, rename(socket_target_path.value().c_str(),
2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      socket_path_.value().c_str()));
2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(0, unlink(cookie_path_.value().c_str()));
2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(process_singleton->Create());
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that we fail when lock says process is on another host and we can't
2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// notify it over the socket before of a bad cookie.
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_F(ProcessSingletonLinuxTest, NotifyOtherProcessOrCreate_BadCookie) {
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Change the cookie.
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, unlink(cookie_path_.value().c_str()));
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, symlink("INCORRECTCOOKIE", cookie_path_.value().c_str()));
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Also change the hostname, so the remote does not retry.
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, unlink(lock_path_.value().c_str()));
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str()));
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string url("about:blank");
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE,
30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            NotifyOtherProcessOrCreate(url, TestTimeouts::action_timeout_ms()));
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
310