Home | History | Annotate | Download | only in service
      1 // Copyright (c) 2010 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 "base/process_util.h"
      6 #include "base/test/test_timeouts.h"
      7 #include "chrome/browser/service/service_process_control.h"
      8 #include "chrome/browser/service/service_process_control_manager.h"
      9 #include "chrome/browser/ui/browser.h"
     10 #include "chrome/common/chrome_version_info.h"
     11 #include "chrome/common/service_process_util.h"
     12 #include "chrome/test/in_process_browser_test.h"
     13 #include "chrome/test/ui_test_utils.h"
     14 
     15 class ServiceProcessControlBrowserTest
     16     : public InProcessBrowserTest {
     17  public:
     18   ServiceProcessControlBrowserTest()
     19       : service_process_handle_(base::kNullProcessHandle) {
     20   }
     21   ~ServiceProcessControlBrowserTest() {
     22     base::CloseProcessHandle(service_process_handle_);
     23     service_process_handle_ = base::kNullProcessHandle;
     24     // Delete all instances of ServiceProcessControl.
     25     ServiceProcessControlManager::GetInstance()->Shutdown();
     26   }
     27 
     28 #if defined(OS_MACOSX)
     29   virtual void TearDown() {
     30     // ForceServiceProcessShutdown removes the process from launchd on Mac.
     31     ForceServiceProcessShutdown("", 0);
     32   }
     33 #endif  // OS_MACOSX
     34 
     35  protected:
     36   void LaunchServiceProcessControl() {
     37     ServiceProcessControl* process =
     38         ServiceProcessControlManager::GetInstance()->GetProcessControl(
     39             browser()->profile());
     40     process_ = process;
     41 
     42     // Launch the process asynchronously.
     43     process->Launch(
     44         NewRunnableMethod(
     45             this,
     46             &ServiceProcessControlBrowserTest::ProcessControlLaunched),
     47         NewRunnableMethod(
     48             this,
     49             &ServiceProcessControlBrowserTest::ProcessControlLaunchFailed));
     50 
     51     // Then run the message loop to keep things running.
     52     ui_test_utils::RunMessageLoop();
     53   }
     54 
     55   // Send a remoting host status request and wait reply from the service.
     56   void SendRequestAndWait() {
     57     process()->GetCloudPrintProxyStatus(NewCallback(
     58         this, &ServiceProcessControlBrowserTest::CloudPrintStatusCallback));
     59     ui_test_utils::RunMessageLoop();
     60   }
     61 
     62   void CloudPrintStatusCallback(
     63       bool enabled, std::string email) {
     64     MessageLoop::current()->Quit();
     65   }
     66 
     67   void Disconnect() {
     68     // This will delete all instances of ServiceProcessControl and close the IPC
     69     // connections.
     70     ServiceProcessControlManager::GetInstance()->Shutdown();
     71     process_ = NULL;
     72   }
     73 
     74   void WaitForShutdown() {
     75     EXPECT_TRUE(base::WaitForSingleProcess(
     76         service_process_handle_,
     77         TestTimeouts::wait_for_terminate_timeout_ms()));
     78   }
     79 
     80   void ProcessControlLaunched() {
     81     base::ProcessId service_pid;
     82     EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
     83     EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
     84     EXPECT_TRUE(base::OpenProcessHandleWithAccess(
     85         service_pid,
     86         base::kProcessAccessWaitForTermination,
     87         &service_process_handle_));
     88     // Quit the current message. Post a QuitTask instead of just calling Quit()
     89     // because this can get invoked in the context of a Launch() call and we
     90     // may not be in Run() yet.
     91     MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
     92   }
     93 
     94   void ProcessControlLaunchFailed() {
     95     ADD_FAILURE();
     96     // Quit the current message.
     97     MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
     98   }
     99 
    100   ServiceProcessControl* process() { return process_; }
    101 
    102  private:
    103   ServiceProcessControl* process_;
    104   base::ProcessHandle service_process_handle_;
    105 };
    106 
    107 // They way that the IPC is implemented only works on windows. This has to
    108 // change when we implement a different scheme for IPC.
    109 // Times out flakily, http://crbug.com/70076.
    110 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
    111                        DISABLED_LaunchAndIPC) {
    112   LaunchServiceProcessControl();
    113 
    114   // Make sure we are connected to the service process.
    115   EXPECT_TRUE(process()->is_connected());
    116   SendRequestAndWait();
    117 
    118   // And then shutdown the service process.
    119   EXPECT_TRUE(process()->Shutdown());
    120 }
    121 
    122 // This tests the case when a service process is launched when browser
    123 // starts but we try to launch it again in the remoting setup dialog.
    124 // Crashes on mac. http://crbug.com/75518
    125 #if defined(OS_MACOSX)
    126 #define MAYBE_LaunchTwice DISABLED_LaunchTwice
    127 #else
    128 #define MAYBE_LaunchTwice LaunchTwice
    129 #endif
    130 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_LaunchTwice) {
    131   // Launch the service process the first time.
    132   LaunchServiceProcessControl();
    133 
    134   // Make sure we are connected to the service process.
    135   EXPECT_TRUE(process()->is_connected());
    136   SendRequestAndWait();
    137 
    138   // Launch the service process again.
    139   LaunchServiceProcessControl();
    140   EXPECT_TRUE(process()->is_connected());
    141   SendRequestAndWait();
    142 
    143   // And then shutdown the service process.
    144   EXPECT_TRUE(process()->Shutdown());
    145 }
    146 
    147 static void DecrementUntilZero(int* count) {
    148   (*count)--;
    149   if (!(*count))
    150     MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
    151 }
    152 
    153 // Invoke multiple Launch calls in succession and ensure that all the tasks
    154 // get invoked.
    155 // Crashes on mac. http://crbug.com/75518
    156 #if defined(OS_MACOSX)
    157 #define MAYBE_MultipleLaunchTasks DISABLED_MultipleLaunchTasks
    158 #else
    159 #define MAYBE_MultipleLaunchTasks MultipleLaunchTasks
    160 #endif
    161 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
    162                        MAYBE_MultipleLaunchTasks) {
    163   ServiceProcessControl* process =
    164       ServiceProcessControlManager::GetInstance()->GetProcessControl(
    165           browser()->profile());
    166   int launch_count = 5;
    167   for (int i = 0; i < launch_count; i++) {
    168     // Launch the process asynchronously.
    169     process->Launch(
    170         NewRunnableFunction(&DecrementUntilZero, &launch_count),
    171         new MessageLoop::QuitTask());
    172   }
    173   // Then run the message loop to keep things running.
    174   ui_test_utils::RunMessageLoop();
    175   EXPECT_EQ(0, launch_count);
    176   // And then shutdown the service process.
    177   EXPECT_TRUE(process->Shutdown());
    178 }
    179 
    180 // Make sure using the same task for success and failure tasks works.
    181 // Crashes on mac. http://crbug.com/75518
    182 #if defined(OS_MACOSX)
    183 #define MAYBE_SameLaunchTask DISABLED_SameLaunchTask
    184 #else
    185 #define MAYBE_SameLaunchTask SameLaunchTask
    186 #endif
    187 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_SameLaunchTask) {
    188   ServiceProcessControl* process =
    189       ServiceProcessControlManager::GetInstance()->GetProcessControl(
    190           browser()->profile());
    191   int launch_count = 5;
    192   for (int i = 0; i < launch_count; i++) {
    193     // Launch the process asynchronously.
    194     Task * task = NewRunnableFunction(&DecrementUntilZero, &launch_count);
    195     process->Launch(task, task);
    196   }
    197   // Then run the message loop to keep things running.
    198   ui_test_utils::RunMessageLoop();
    199   EXPECT_EQ(0, launch_count);
    200   // And then shutdown the service process.
    201   EXPECT_TRUE(process->Shutdown());
    202 }
    203 
    204 // Tests whether disconnecting from the service IPC causes the service process
    205 // to die.
    206 // Crashes on mac. http://crbug.com/75518
    207 #if defined(OS_MACOSX)
    208 #define MAYBE_DieOnDisconnect DISABLED_DieOnDisconnect
    209 #else
    210 #define MAYBE_DieOnDisconnect DieOnDisconnect
    211 #endif
    212 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
    213                        MAYBE_DieOnDisconnect) {
    214   // Launch the service process.
    215   LaunchServiceProcessControl();
    216   // Make sure we are connected to the service process.
    217   EXPECT_TRUE(process()->is_connected());
    218   Disconnect();
    219   WaitForShutdown();
    220 }
    221 
    222 //http://code.google.com/p/chromium/issues/detail?id=70793
    223 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
    224                        DISABLED_ForceShutdown) {
    225   // Launch the service process.
    226   LaunchServiceProcessControl();
    227   // Make sure we are connected to the service process.
    228   EXPECT_TRUE(process()->is_connected());
    229   base::ProcessId service_pid;
    230   EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
    231   EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
    232   chrome::VersionInfo version_info;
    233   ForceServiceProcessShutdown(version_info.Version(), service_pid);
    234   WaitForShutdown();
    235 }
    236 
    237 // Crashes on mac. http://crbug.com/75518
    238 #if defined(OS_MACOSX)
    239 #define MAYBE_CheckPid DISABLED_CheckPid
    240 #else
    241 #define MAYBE_CheckPid CheckPid
    242 #endif
    243 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_CheckPid) {
    244   base::ProcessId service_pid;
    245   EXPECT_FALSE(GetServiceProcessData(NULL, &service_pid));
    246   // Launch the service process.
    247   LaunchServiceProcessControl();
    248   EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
    249   EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
    250 }
    251 
    252 DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControlBrowserTest);
    253