| 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 |