OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/process_singleton.h" | 5 #include "chrome/browser/process_singleton.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <limits.h> | 8 #include <limits.h> |
9 #include <signal.h> | 9 #include <signal.h> |
10 #include <stddef.h> | 10 #include <stddef.h> |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 base::WaitableEvent::InitialState::NOT_SIGNALED), | 76 base::WaitableEvent::InitialState::NOT_SIGNALED), |
77 signal_event_(base::WaitableEvent::ResetPolicy::MANUAL, | 77 signal_event_(base::WaitableEvent::ResetPolicy::MANUAL, |
78 base::WaitableEvent::InitialState::NOT_SIGNALED), | 78 base::WaitableEvent::InitialState::NOT_SIGNALED), |
79 process_singleton_on_thread_(NULL) {} | 79 process_singleton_on_thread_(NULL) {} |
80 | 80 |
81 void SetUp() override { | 81 void SetUp() override { |
82 testing::Test::SetUp(); | 82 testing::Test::SetUp(); |
83 | 83 |
84 ProcessSingleton::DisablePromptForTesting(); | 84 ProcessSingleton::DisablePromptForTesting(); |
85 ProcessSingleton::SkipIsChromeProcessCheckForTesting(false); | 85 ProcessSingleton::SkipIsChromeProcessCheckForTesting(false); |
| 86 ProcessSingleton::SetUserOptedUnlockInUseProfileForTesting(false); |
86 // Put the lock in a temporary directory. Doesn't need to be a | 87 // Put the lock in a temporary directory. Doesn't need to be a |
87 // full profile to test this code. | 88 // full profile to test this code. |
88 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 89 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
89 // Use a long directory name to ensure that the socket isn't opened through | 90 // Use a long directory name to ensure that the socket isn't opened through |
90 // the symlink. | 91 // the symlink. |
91 user_data_path_ = temp_dir_.GetPath().Append( | 92 user_data_path_ = temp_dir_.GetPath().Append( |
92 std::string(sizeof(sockaddr_un::sun_path), 'a')); | 93 std::string(sizeof(sockaddr_un::sun_path), 'a')); |
93 ASSERT_TRUE(CreateDirectory(user_data_path_)); | 94 ASSERT_TRUE(CreateDirectory(user_data_path_)); |
94 | 95 |
95 lock_path_ = user_data_path_.Append(chrome::kSingletonLockFilename); | 96 lock_path_ = user_data_path_.Append(chrome::kSingletonLockFilename); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 // hostname changed. | 332 // hostname changed. |
332 TEST_F(ProcessSingletonPosixTest, NotifyOtherProcessHostChanged) { | 333 TEST_F(ProcessSingletonPosixTest, NotifyOtherProcessHostChanged) { |
333 CreateProcessSingletonOnThread(); | 334 CreateProcessSingletonOnThread(); |
334 EXPECT_EQ(0, unlink(lock_path_.value().c_str())); | 335 EXPECT_EQ(0, unlink(lock_path_.value().c_str())); |
335 EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str())); | 336 EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str())); |
336 | 337 |
337 EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED, NotifyOtherProcess(false)); | 338 EXPECT_EQ(ProcessSingleton::PROCESS_NOTIFIED, NotifyOtherProcess(false)); |
338 CheckNotified(); | 339 CheckNotified(); |
339 } | 340 } |
340 | 341 |
341 // Test that we fail when lock says process is on another host and we can't | 342 // Test that we kill hung browser when lock says process is on another host and |
342 // notify it over the socket. | 343 // we can't notify it over the socket. |
343 TEST_F(ProcessSingletonPosixTest, NotifyOtherProcessDifferingHost) { | 344 TEST_F(ProcessSingletonPosixTest, NotifyOtherProcessDifferingHost) { |
| 345 base::HistogramTester histogram_tester; |
344 CreateProcessSingletonOnThread(); | 346 CreateProcessSingletonOnThread(); |
345 | 347 |
346 BlockWorkerThread(); | 348 BlockWorkerThread(); |
347 | 349 |
348 EXPECT_EQ(0, unlink(lock_path_.value().c_str())); | 350 EXPECT_EQ(0, unlink(lock_path_.value().c_str())); |
349 EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str())); | 351 EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str())); |
350 | 352 |
351 EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE, NotifyOtherProcess(false)); | 353 EXPECT_EQ(ProcessSingleton::PROCESS_NONE, NotifyOtherProcess(true)); |
| 354 ASSERT_EQ(1, kill_callbacks_); |
352 | 355 |
353 ASSERT_EQ(0, unlink(lock_path_.value().c_str())); | 356 // lock_path_ should be unlinked in NotifyOtherProcess(). |
| 357 base::FilePath target_path; |
| 358 EXPECT_FALSE(base::ReadSymbolicLink(lock_path_, &target_path)); |
354 | 359 |
355 UnblockWorkerThread(); | 360 UnblockWorkerThread(); |
| 361 |
| 362 histogram_tester.ExpectUniqueSample( |
| 363 "Chrome.ProcessSingleton.RemoteHungProcessTerminateReason", |
| 364 ProcessSingleton::SOCKET_READ_FAILED, 1u); |
356 } | 365 } |
357 | 366 |
358 // Test that we fail when lock says process is on another host and we can't | 367 // Test that we'll start creating ProcessSingleton when we have old lock file |
359 // notify it over the socket. | 368 // that says process is on another host and there is browser with the same pid |
360 TEST_F(ProcessSingletonPosixTest, NotifyOtherProcessOrCreate_DifferingHost) { | 369 // but with another user data dir. Also suppose that user opted to unlock |
| 370 // profile. |
| 371 TEST_F(ProcessSingletonPosixTest, |
| 372 NotifyOtherProcessDifferingHost_UnlockedProfileBeforeKill) { |
| 373 base::HistogramTester histogram_tester; |
361 CreateProcessSingletonOnThread(); | 374 CreateProcessSingletonOnThread(); |
362 | 375 |
363 BlockWorkerThread(); | 376 BlockWorkerThread(); |
| 377 |
| 378 EXPECT_EQ(0, unlink(lock_path_.value().c_str())); |
| 379 EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str())); |
| 380 |
| 381 // Remove socket so that we will not be able to notify the existing browser. |
| 382 EXPECT_EQ(0, unlink(socket_path_.value().c_str())); |
| 383 |
| 384 // Unlock profile that was locked by process on another host. |
| 385 ProcessSingleton::SetUserOptedUnlockInUseProfileForTesting(true); |
| 386 // Treat process with pid 1234 as browser with different user data dir. |
| 387 ProcessSingleton::SkipIsChromeProcessCheckForTesting(true); |
| 388 |
| 389 EXPECT_EQ(ProcessSingleton::PROCESS_NONE, NotifyOtherProcess(false)); |
| 390 |
| 391 // lock_path_ should be unlinked in NotifyOtherProcess(). |
| 392 base::FilePath target_path; |
| 393 EXPECT_FALSE(base::ReadSymbolicLink(lock_path_, &target_path)); |
| 394 |
| 395 UnblockWorkerThread(); |
| 396 |
| 397 histogram_tester.ExpectUniqueSample( |
| 398 "Chrome.ProcessSingleton.RemoteHungProcessTerminateReason", |
| 399 ProcessSingleton::NOTIFY_ATTEMPTS_EXCEEDED, 1u); |
| 400 histogram_tester.ExpectUniqueSample( |
| 401 "Chrome.ProcessSingleton.RemoteProcessInteractionResult", |
| 402 ProcessSingleton::PROFILE_UNLOCKED_BEFORE_KILL, 1u); |
| 403 } |
| 404 |
| 405 // Test that we unlock profile when lock says process is on another host and we |
| 406 // can't notify it over the socket. |
| 407 TEST_F(ProcessSingletonPosixTest, NotifyOtherProcessOrCreate_DifferingHost) { |
| 408 base::HistogramTester histogram_tester; |
| 409 CreateProcessSingletonOnThread(); |
| 410 |
| 411 BlockWorkerThread(); |
364 | 412 |
365 EXPECT_EQ(0, unlink(lock_path_.value().c_str())); | 413 EXPECT_EQ(0, unlink(lock_path_.value().c_str())); |
366 EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str())); | 414 EXPECT_EQ(0, symlink("FAKEFOOHOST-1234", lock_path_.value().c_str())); |
367 | 415 |
| 416 // Remove socket so that we will not be able to notify the existing browser. |
| 417 EXPECT_EQ(0, unlink(socket_path_.value().c_str())); |
| 418 // Unlock profile that was locked by process on another host. |
| 419 ProcessSingleton::SetUserOptedUnlockInUseProfileForTesting(true); |
| 420 |
368 std::string url("about:blank"); | 421 std::string url("about:blank"); |
369 EXPECT_EQ(ProcessSingleton::PROFILE_IN_USE, NotifyOtherProcessOrCreate(url)); | 422 EXPECT_EQ(ProcessSingleton::PROCESS_NONE, NotifyOtherProcessOrCreate(url)); |
370 | 423 |
371 ASSERT_EQ(0, unlink(lock_path_.value().c_str())); | 424 ASSERT_EQ(0, unlink(lock_path_.value().c_str())); |
372 | 425 |
373 UnblockWorkerThread(); | 426 UnblockWorkerThread(); |
| 427 |
| 428 histogram_tester.ExpectUniqueSample( |
| 429 "Chrome.ProcessSingleton.RemoteProcessInteractionResult", |
| 430 ProcessSingleton::PROFILE_UNLOCKED, 1u); |
374 } | 431 } |
375 | 432 |
376 // Test that Create fails when another browser is using the profile directory. | 433 // Test that Create fails when another browser is using the profile directory. |
377 TEST_F(ProcessSingletonPosixTest, CreateFailsWithExistingBrowser) { | 434 TEST_F(ProcessSingletonPosixTest, CreateFailsWithExistingBrowser) { |
378 CreateProcessSingletonOnThread(); | 435 CreateProcessSingletonOnThread(); |
379 | 436 |
380 std::unique_ptr<TestableProcessSingleton> process_singleton( | 437 std::unique_ptr<TestableProcessSingleton> process_singleton( |
381 CreateProcessSingleton()); | 438 CreateProcessSingleton()); |
382 process_singleton->OverrideCurrentPidForTesting(base::GetCurrentProcId() + 1); | 439 process_singleton->OverrideCurrentPidForTesting(base::GetCurrentProcId() + 1); |
383 EXPECT_FALSE(process_singleton->Create()); | 440 EXPECT_FALSE(process_singleton->Create()); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 // Test that if there is an existing lock file, and it's not locked, we replace | 521 // Test that if there is an existing lock file, and it's not locked, we replace |
465 // it. | 522 // it. |
466 TEST_F(ProcessSingletonPosixTest, CreateReplacesOldMacLock) { | 523 TEST_F(ProcessSingletonPosixTest, CreateReplacesOldMacLock) { |
467 std::unique_ptr<TestableProcessSingleton> process_singleton( | 524 std::unique_ptr<TestableProcessSingleton> process_singleton( |
468 CreateProcessSingleton()); | 525 CreateProcessSingleton()); |
469 EXPECT_EQ(0, base::WriteFile(lock_path_, "", 0)); | 526 EXPECT_EQ(0, base::WriteFile(lock_path_, "", 0)); |
470 EXPECT_TRUE(process_singleton->Create()); | 527 EXPECT_TRUE(process_singleton->Create()); |
471 VerifyFiles(); | 528 VerifyFiles(); |
472 } | 529 } |
473 #endif // defined(OS_MACOSX) | 530 #endif // defined(OS_MACOSX) |
OLD | NEW |