1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chrome_process_singleton.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/compiler_specific.h" 10 #include "base/files/file_path.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace { 15 16 bool ServerCallback(int* callback_count, 17 const CommandLine& command_line, 18 const base::FilePath& current_directory) { 19 ++(*callback_count); 20 return true; 21 } 22 23 bool ClientCallback(const CommandLine& command_line, 24 const base::FilePath& current_directory) { 25 ADD_FAILURE(); 26 return false; 27 } 28 29 } // namespace 30 31 TEST(ChromeProcessSingletonTest, Basic) { 32 base::ScopedTempDir profile_dir; 33 ASSERT_TRUE(profile_dir.CreateUniqueTempDir()); 34 35 int callback_count = 0; 36 37 ChromeProcessSingleton ps1( 38 profile_dir.path(), 39 base::Bind(&ServerCallback, base::Unretained(&callback_count))); 40 ps1.Unlock(); 41 42 ChromeProcessSingleton ps2(profile_dir.path(), base::Bind(&ClientCallback)); 43 ps2.Unlock(); 44 45 ProcessSingleton::NotifyResult result = ps1.NotifyOtherProcessOrCreate(); 46 47 ASSERT_EQ(ProcessSingleton::PROCESS_NONE, result); 48 ASSERT_EQ(0, callback_count); 49 50 result = ps2.NotifyOtherProcessOrCreate(); 51 ASSERT_EQ(ProcessSingleton::PROCESS_NOTIFIED, result); 52 53 ASSERT_EQ(1, callback_count); 54 } 55 56 TEST(ChromeProcessSingletonTest, Lock) { 57 base::ScopedTempDir profile_dir; 58 ASSERT_TRUE(profile_dir.CreateUniqueTempDir()); 59 60 int callback_count = 0; 61 62 ChromeProcessSingleton ps1( 63 profile_dir.path(), 64 base::Bind(&ServerCallback, base::Unretained(&callback_count))); 65 66 ChromeProcessSingleton ps2(profile_dir.path(), base::Bind(&ClientCallback)); 67 ps2.Unlock(); 68 69 ProcessSingleton::NotifyResult result = ps1.NotifyOtherProcessOrCreate(); 70 71 ASSERT_EQ(ProcessSingleton::PROCESS_NONE, result); 72 ASSERT_EQ(0, callback_count); 73 74 result = ps2.NotifyOtherProcessOrCreate(); 75 ASSERT_EQ(ProcessSingleton::PROCESS_NOTIFIED, result); 76 77 ASSERT_EQ(0, callback_count); 78 ps1.Unlock(); 79 ASSERT_EQ(1, callback_count); 80 } 81 82 #if defined(OS_WIN) && !defined(USE_AURA) 83 namespace { 84 85 void SetForegroundWindowHandler(bool* flag, 86 gfx::NativeWindow /* target_window */) { 87 *flag = true; 88 } 89 90 } // namespace 91 92 TEST(ChromeProcessSingletonTest, LockWithModalDialog) { 93 base::ScopedTempDir profile_dir; 94 ASSERT_TRUE(profile_dir.CreateUniqueTempDir()); 95 96 int callback_count = 0; 97 bool called_set_foreground_window = false; 98 99 ChromeProcessSingleton ps1( 100 profile_dir.path(), 101 base::Bind(&ServerCallback, base::Unretained(&callback_count)), 102 base::Bind(&SetForegroundWindowHandler, 103 base::Unretained(&called_set_foreground_window))); 104 ps1.SetActiveModalDialog(::GetShellWindow()); 105 106 ChromeProcessSingleton ps2(profile_dir.path(), base::Bind(&ClientCallback)); 107 ps2.Unlock(); 108 109 ProcessSingleton::NotifyResult result = ps1.NotifyOtherProcessOrCreate(); 110 111 ASSERT_EQ(ProcessSingleton::PROCESS_NONE, result); 112 ASSERT_EQ(0, callback_count); 113 114 ASSERT_FALSE(called_set_foreground_window); 115 result = ps2.NotifyOtherProcessOrCreate(); 116 ASSERT_EQ(ProcessSingleton::PROCESS_NOTIFIED, result); 117 ASSERT_TRUE(called_set_foreground_window); 118 119 ASSERT_EQ(0, callback_count); 120 ps1.SetActiveModalDialog(NULL); 121 ps1.Unlock(); 122 // The notification sent while a modal dialog was present was silently 123 // dropped. 124 ASSERT_EQ(0, callback_count); 125 126 // But now that the active modal dialog is NULL notifications will be handled. 127 result = ps2.NotifyOtherProcessOrCreate(); 128 ASSERT_EQ(ProcessSingleton::PROCESS_NOTIFIED, result); 129 ASSERT_EQ(1, callback_count); 130 } 131 #endif // defined(OS_WIN) && !defined(USE_AURA) 132