Home | History | Annotate | Download | only in browser
      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