Home | History | Annotate | Download | only in test
      1 // Copyright (c) 2012 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 // Create a service process that uses a Mock to respond to the browser in order
      6 // to test launching the browser using the cloud print policy check command
      7 // line switch.
      8 
      9 #include "base/bind.h"
     10 #include "base/command_line.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/process/kill.h"
     13 #include "base/rand_util.h"
     14 #include "base/synchronization/waitable_event.h"
     15 #include "base/test/multiprocess_test.h"
     16 #include "base/test/test_timeouts.h"
     17 #include "base/time/default_tick_clock.h"
     18 #include "base/time/time.h"
     19 #include "chrome/browser/prefs/browser_prefs.h"
     20 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
     21 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
     22 #include "chrome/browser/service_process/service_process_control.h"
     23 #include "chrome/browser/ui/startup/startup_browser_creator.h"
     24 #include "chrome/common/chrome_switches.h"
     25 #include "chrome/common/pref_names.h"
     26 #include "chrome/common/service_messages.h"
     27 #include "chrome/common/service_process_util.h"
     28 #include "chrome/service/service_ipc_server.h"
     29 #include "chrome/service/service_process.h"
     30 #include "chrome/test/base/test_launcher_utils.h"
     31 #include "chrome/test/base/testing_browser_process.h"
     32 #include "chrome/test/base/testing_io_thread_state.h"
     33 #include "chrome/test/base/testing_pref_service_syncable.h"
     34 #include "chrome/test/base/testing_profile.h"
     35 #include "chrome/test/base/testing_profile_manager.h"
     36 #include "chrome/test/base/ui_test_utils.h"
     37 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
     38 #include "content/public/browser/notification_service.h"
     39 #include "content/public/test/test_browser_thread_bundle.h"
     40 #include "ipc/ipc_descriptors.h"
     41 #include "ipc/ipc_multiprocess_test.h"
     42 #include "ipc/ipc_switches.h"
     43 #include "testing/gmock/include/gmock/gmock.h"
     44 #include "testing/gtest/include/gtest/gtest.h"
     45 #include "testing/multiprocess_func_list.h"
     46 
     47 #if defined(OS_MACOSX)
     48 #include "chrome/common/mac/mock_launchd.h"
     49 #endif
     50 #if defined(OS_POSIX)
     51 #include "base/posix/global_descriptors.h"
     52 #endif
     53 
     54 using ::testing::AnyNumber;
     55 using ::testing::Assign;
     56 using ::testing::AtLeast;
     57 using ::testing::DoAll;
     58 using ::testing::Invoke;
     59 using ::testing::Mock;
     60 using ::testing::Property;
     61 using ::testing::Return;
     62 using ::testing::WithoutArgs;
     63 using ::testing::_;
     64 using content::BrowserThread;
     65 
     66 namespace {
     67 
     68 enum MockServiceProcessExitCodes {
     69   kMissingSwitch = 1,
     70   kInitializationFailure,
     71   kExpectationsNotMet,
     72   kShutdownNotGood
     73 };
     74 
     75 #if defined(OS_MACOSX)
     76 const char kTestExecutablePath[] = "test-executable-path";
     77 #endif
     78 
     79 bool g_good_shutdown = false;
     80 
     81 void ShutdownTask() {
     82   g_good_shutdown = true;
     83   g_service_process->Shutdown();
     84 }
     85 
     86 class TestStartupClientChannelListener : public IPC::Listener {
     87  public:
     88   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
     89     return false;
     90   }
     91 };
     92 
     93 }  // namespace
     94 
     95 class TestServiceProcess : public ServiceProcess {
     96  public:
     97   TestServiceProcess() { }
     98   virtual ~TestServiceProcess() { }
     99 
    100   bool Initialize(base::MessageLoopForUI* message_loop,
    101                   ServiceProcessState* state);
    102 
    103   base::MessageLoopProxy* IOMessageLoopProxy() {
    104     return io_thread_->message_loop_proxy().get();
    105   }
    106 };
    107 
    108 bool TestServiceProcess::Initialize(base::MessageLoopForUI* message_loop,
    109                                     ServiceProcessState* state) {
    110   main_message_loop_ = message_loop;
    111 
    112   service_process_state_.reset(state);
    113 
    114   base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
    115   io_thread_.reset(new base::Thread("TestServiceProcess_IO"));
    116   return io_thread_->StartWithOptions(options);
    117 }
    118 
    119 // This mocks the service side IPC message handler, allowing us to have a
    120 // minimal service process.
    121 class MockServiceIPCServer : public ServiceIPCServer {
    122  public:
    123   static std::string EnabledUserId();
    124 
    125   explicit MockServiceIPCServer(const IPC::ChannelHandle& handle)
    126       : ServiceIPCServer(handle),
    127         enabled_(true) { }
    128 
    129   MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message& message));
    130   MOCK_METHOD1(OnChannelConnected, void(int32 peer_pid));
    131   MOCK_METHOD0(OnChannelError, void());
    132 
    133   void SetServiceEnabledExpectations();
    134   void SetWillBeDisabledExpectations();
    135 
    136   void CallServiceOnChannelConnected(int32 peer_pid) {
    137     ServiceIPCServer::OnChannelConnected(peer_pid);
    138   }
    139 
    140   bool SendInfo();
    141 
    142  private:
    143   cloud_print::CloudPrintProxyInfo info_;
    144   bool enabled_;
    145 };
    146 
    147 // static
    148 std::string MockServiceIPCServer::EnabledUserId() {
    149   return std::string("kitteh (at) canhazcheezburger.cat");
    150 }
    151 
    152 void MockServiceIPCServer::SetServiceEnabledExpectations() {
    153   EXPECT_CALL(*this, OnChannelConnected(_)).Times(1)
    154       .WillRepeatedly(
    155           Invoke(this, &MockServiceIPCServer::CallServiceOnChannelConnected));
    156 
    157   EXPECT_CALL(*this, OnChannelError()).Times(0);
    158   EXPECT_CALL(*this, OnMessageReceived(_)).Times(0);
    159 
    160   EXPECT_CALL(*this,
    161       OnMessageReceived(
    162           Property(&IPC::Message::type,
    163                    static_cast<int32>(ServiceMsg_GetCloudPrintProxyInfo::ID))))
    164       .Times(AnyNumber()).WillRepeatedly(
    165           WithoutArgs(Invoke(this, &MockServiceIPCServer::SendInfo)));
    166 
    167   EXPECT_CALL(*this,
    168               OnMessageReceived(
    169                   Property(&IPC::Message::type,
    170                            static_cast<int32>(ServiceMsg_Shutdown::ID))))
    171       .Times(1)
    172       .WillOnce(
    173           DoAll(Assign(&g_good_shutdown, true),
    174                 WithoutArgs(
    175                     Invoke(g_service_process, &ServiceProcess::Shutdown)),
    176                 Return(true)));
    177 }
    178 
    179 void MockServiceIPCServer::SetWillBeDisabledExpectations() {
    180   SetServiceEnabledExpectations();
    181 
    182   EXPECT_CALL(*this,
    183               OnMessageReceived(
    184                   Property(&IPC::Message::type,
    185                            static_cast<int32>(
    186                                ServiceMsg_DisableCloudPrintProxy::ID))))
    187       .Times(AtLeast(1))
    188       .WillRepeatedly(DoAll(Assign(&enabled_, false), Return(true)));
    189 }
    190 
    191 bool MockServiceIPCServer::SendInfo() {
    192   if (enabled_) {
    193     info_.enabled = true;
    194     info_.email = EnabledUserId();
    195     EXPECT_TRUE(Send(new ServiceHostMsg_CloudPrintProxy_Info(info_)));
    196   } else {
    197     info_.enabled = false;
    198     info_.email = std::string();
    199     EXPECT_TRUE(Send(new ServiceHostMsg_CloudPrintProxy_Info(info_)));
    200   }
    201   return true;
    202 }
    203 
    204 typedef base::Callback<void(MockServiceIPCServer* server)>
    205     SetExpectationsCallback;
    206 
    207 // The return value from this routine is used as the exit code for the mock
    208 // service process. Any non-zero return value will be printed out and can help
    209 // determine the failure.
    210 int CloudPrintMockService_Main(SetExpectationsCallback set_expectations) {
    211   base::MessageLoopForUI main_message_loop;
    212   main_message_loop.set_thread_name("Main Thread");
    213   CommandLine* command_line = CommandLine::ForCurrentProcess();
    214 
    215 #if defined(OS_MACOSX)
    216   if (!command_line->HasSwitch(kTestExecutablePath))
    217     return kMissingSwitch;
    218   base::FilePath executable_path =
    219       command_line->GetSwitchValuePath(kTestExecutablePath);
    220   EXPECT_FALSE(executable_path.empty());
    221   MockLaunchd mock_launchd(executable_path, &main_message_loop, true, true);
    222   Launchd::ScopedInstance use_mock(&mock_launchd);
    223 #endif
    224 
    225   base::FilePath user_data_dir =
    226       command_line->GetSwitchValuePath(switches::kUserDataDir);
    227   CHECK(!user_data_dir.empty());
    228   CHECK(test_launcher_utils::OverrideUserDataDir(user_data_dir));
    229 
    230   ServiceProcessState* state(new ServiceProcessState);
    231   bool service_process_state_initialized = state->Initialize();
    232   EXPECT_TRUE(service_process_state_initialized);
    233   if (!service_process_state_initialized)
    234     return kInitializationFailure;
    235 
    236   TestServiceProcess service_process;
    237   EXPECT_EQ(&service_process, g_service_process);
    238 
    239   // Takes ownership of the pointer, but we can use it since we have the same
    240   // lifetime.
    241   EXPECT_TRUE(service_process.Initialize(&main_message_loop, state));
    242 
    243   MockServiceIPCServer server(state->GetServiceProcessChannel());
    244 
    245   // Here is where the expectations/mock responses need to be set up.
    246   set_expectations.Run(&server);
    247 
    248   EXPECT_TRUE(server.Init());
    249   EXPECT_TRUE(state->SignalReady(service_process.IOMessageLoopProxy(),
    250                                  base::Bind(&ShutdownTask)));
    251 #if defined(OS_MACOSX)
    252   mock_launchd.SignalReady();
    253 #endif
    254 
    255   // Connect up the parent/child IPC channel to signal that the test can
    256   // continue.
    257   TestStartupClientChannelListener listener;
    258   EXPECT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
    259       switches::kProcessChannelID));
    260   std::string startup_channel_name =
    261       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
    262           switches::kProcessChannelID);
    263   scoped_ptr<IPC::ChannelProxy> startup_channel;
    264   startup_channel.reset(
    265       new IPC::ChannelProxy(startup_channel_name,
    266                             IPC::Channel::MODE_CLIENT,
    267                             &listener,
    268                             service_process.IOMessageLoopProxy()));
    269 
    270   main_message_loop.Run();
    271   if (!Mock::VerifyAndClearExpectations(&server))
    272     return kExpectationsNotMet;
    273   if (!g_good_shutdown)
    274     return kShutdownNotGood;
    275   return 0;
    276 }
    277 
    278 void SetServiceEnabledExpectations(MockServiceIPCServer* server) {
    279   server->SetServiceEnabledExpectations();
    280 }
    281 
    282 MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledWaitForQuit) {
    283   return CloudPrintMockService_Main(
    284       base::Bind(&SetServiceEnabledExpectations));
    285 }
    286 
    287 void SetServiceWillBeDisabledExpectations(MockServiceIPCServer* server) {
    288   server->SetWillBeDisabledExpectations();
    289 }
    290 
    291 MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledExpectDisabled) {
    292   return CloudPrintMockService_Main(
    293       base::Bind(&SetServiceWillBeDisabledExpectations));
    294 }
    295 
    296 class CloudPrintProxyPolicyStartupTest : public base::MultiProcessTest,
    297                                          public IPC::Listener {
    298  public:
    299   CloudPrintProxyPolicyStartupTest();
    300   virtual ~CloudPrintProxyPolicyStartupTest();
    301 
    302   virtual void SetUp() OVERRIDE;
    303   virtual void TearDown() OVERRIDE;
    304 
    305   scoped_refptr<base::MessageLoopProxy> IOMessageLoopProxy() {
    306     return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
    307   }
    308   base::ProcessHandle Launch(const std::string& name);
    309   void WaitForConnect();
    310   bool Send(IPC::Message* message);
    311   void ShutdownAndWaitForExitWithTimeout(base::ProcessHandle handle);
    312 
    313   // IPC::Listener implementation
    314   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    315     return false;
    316   }
    317   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
    318 
    319   // MultiProcessTest implementation.
    320   virtual CommandLine MakeCmdLine(const std::string& procname,
    321                                   bool debug_on_start) OVERRIDE;
    322 
    323   bool LaunchBrowser(const CommandLine& command_line, Profile* profile) {
    324     int return_code = 0;
    325     StartupBrowserCreator browser_creator;
    326     return StartupBrowserCreator::ProcessCmdLineImpl(
    327         command_line, base::FilePath(), false, profile,
    328         StartupBrowserCreator::Profiles(), &return_code, &browser_creator);
    329   }
    330 
    331  protected:
    332   content::TestBrowserThreadBundle thread_bundle_;
    333   base::ScopedTempDir temp_user_data_dir_;
    334 
    335   std::string startup_channel_id_;
    336   scoped_ptr<IPC::ChannelProxy> startup_channel_;
    337 
    338 #if defined(OS_MACOSX)
    339   base::ScopedTempDir temp_dir_;
    340   base::FilePath executable_path_, bundle_path_;
    341   scoped_ptr<MockLaunchd> mock_launchd_;
    342   scoped_ptr<Launchd::ScopedInstance> scoped_launchd_instance_;
    343 #endif
    344 
    345  private:
    346   class WindowedChannelConnectionObserver {
    347    public:
    348     WindowedChannelConnectionObserver()
    349         : seen_(false),
    350           running_(false) { }
    351 
    352     void Wait() {
    353       if (seen_)
    354         return;
    355       running_ = true;
    356       content::RunMessageLoop();
    357     }
    358 
    359     void Notify() {
    360       seen_ = true;
    361       if (running_)
    362         base::MessageLoopForUI::current()->Quit();
    363     }
    364 
    365    private:
    366     bool seen_;
    367     bool running_;
    368   };
    369 
    370   WindowedChannelConnectionObserver observer_;
    371 };
    372 
    373 CloudPrintProxyPolicyStartupTest::CloudPrintProxyPolicyStartupTest()
    374     : thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) {
    375 }
    376 
    377 CloudPrintProxyPolicyStartupTest::~CloudPrintProxyPolicyStartupTest() {
    378 }
    379 
    380 void CloudPrintProxyPolicyStartupTest::SetUp() {
    381   TestingBrowserProcess::CreateInstance();
    382 #if defined(OS_MACOSX)
    383   EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
    384   EXPECT_TRUE(MockLaunchd::MakeABundle(temp_dir_.path(),
    385                                        "CloudPrintProxyTest",
    386                                        &bundle_path_,
    387                                        &executable_path_));
    388   mock_launchd_.reset(new MockLaunchd(executable_path_,
    389                                       base::MessageLoopForUI::current(),
    390                                       true, false));
    391   scoped_launchd_instance_.reset(
    392       new Launchd::ScopedInstance(mock_launchd_.get()));
    393 #endif
    394 
    395   // Ensure test does not use the standard profile directory. This is copied
    396   // from InProcessBrowserTest::SetUp(). These tests require a more complex
    397   // process startup so they are unable to just inherit from
    398   // InProcessBrowserTest.
    399   CommandLine* command_line = CommandLine::ForCurrentProcess();
    400   base::FilePath user_data_dir =
    401       command_line->GetSwitchValuePath(switches::kUserDataDir);
    402   if (user_data_dir.empty()) {
    403     ASSERT_TRUE(temp_user_data_dir_.CreateUniqueTempDir() &&
    404                 temp_user_data_dir_.IsValid())
    405         << "Could not create temporary user data directory \""
    406         << temp_user_data_dir_.path().value() << "\".";
    407 
    408     user_data_dir = temp_user_data_dir_.path();
    409     command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
    410   }
    411   ASSERT_TRUE(test_launcher_utils::OverrideUserDataDir(user_data_dir));
    412 }
    413 
    414 void CloudPrintProxyPolicyStartupTest::TearDown() {
    415   TestingBrowserProcess::DeleteInstance();
    416 }
    417 
    418 base::ProcessHandle CloudPrintProxyPolicyStartupTest::Launch(
    419     const std::string& name) {
    420   EXPECT_FALSE(CheckServiceProcessReady());
    421 
    422   startup_channel_id_ =
    423       base::StringPrintf("%d.%p.%d",
    424                          base::GetCurrentProcId(), this,
    425                          base::RandInt(0, std::numeric_limits<int>::max()));
    426   startup_channel_.reset(new IPC::ChannelProxy(
    427       startup_channel_id_, IPC::Channel::MODE_SERVER,
    428       this, IOMessageLoopProxy()));
    429 
    430 #if defined(OS_POSIX)
    431   base::FileHandleMappingVector ipc_file_list;
    432   ipc_file_list.push_back(std::make_pair(
    433       startup_channel_->TakeClientFileDescriptor(),
    434       kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
    435   base::ProcessHandle handle = SpawnChild(name, ipc_file_list, false);
    436 #else
    437   base::ProcessHandle handle = SpawnChild(name, false);
    438 #endif
    439   EXPECT_TRUE(handle);
    440   return handle;
    441 }
    442 
    443 void CloudPrintProxyPolicyStartupTest::WaitForConnect() {
    444   observer_.Wait();
    445   EXPECT_TRUE(CheckServiceProcessReady());
    446   EXPECT_TRUE(base::MessageLoopProxy::current().get());
    447   ServiceProcessControl::GetInstance()->SetChannel(
    448       new IPC::ChannelProxy(GetServiceProcessChannel(),
    449                             IPC::Channel::MODE_NAMED_CLIENT,
    450                             ServiceProcessControl::GetInstance(),
    451                             IOMessageLoopProxy()));
    452 }
    453 
    454 bool CloudPrintProxyPolicyStartupTest::Send(IPC::Message* message) {
    455   return ServiceProcessControl::GetInstance()->Send(message);
    456 }
    457 
    458 void CloudPrintProxyPolicyStartupTest::ShutdownAndWaitForExitWithTimeout(
    459     base::ProcessHandle handle) {
    460   ASSERT_TRUE(Send(new ServiceMsg_Shutdown()));
    461 
    462   int exit_code = -100;
    463   bool exited =
    464       base::WaitForExitCodeWithTimeout(handle, &exit_code,
    465                                        TestTimeouts::action_timeout());
    466   EXPECT_TRUE(exited);
    467   EXPECT_EQ(exit_code, 0);
    468   base::CloseProcessHandle(handle);
    469 }
    470 
    471 void CloudPrintProxyPolicyStartupTest::OnChannelConnected(int32 peer_pid) {
    472   observer_.Notify();
    473 }
    474 
    475 CommandLine CloudPrintProxyPolicyStartupTest::MakeCmdLine(
    476     const std::string& procname,
    477     bool debug_on_start) {
    478   CommandLine cl = MultiProcessTest::MakeCmdLine(procname, debug_on_start);
    479   cl.AppendSwitchASCII(switches::kProcessChannelID, startup_channel_id_);
    480 #if defined(OS_MACOSX)
    481   cl.AppendSwitchASCII(kTestExecutablePath, executable_path_.value());
    482 #endif
    483   return cl;
    484 }
    485 
    486 TEST_F(CloudPrintProxyPolicyStartupTest, StartAndShutdown) {
    487   TestingBrowserProcess* browser_process =
    488       TestingBrowserProcess::GetGlobal();
    489   TestingProfileManager profile_manager(browser_process);
    490   ASSERT_TRUE(profile_manager.SetUp());
    491 
    492   // Must be created after the TestingProfileManager since that creates the
    493   // LocalState for the BrowserProcess.  Must be created before profiles are
    494   // constructed.
    495   chrome::TestingIOThreadState testing_io_thread_state;
    496 
    497   base::ProcessHandle handle =
    498       Launch("CloudPrintMockService_StartEnabledWaitForQuit");
    499   WaitForConnect();
    500   ShutdownAndWaitForExitWithTimeout(handle);
    501   content::RunAllPendingInMessageLoop();
    502 }
    503 
    504 BrowserContextKeyedService* CloudPrintProxyServiceFactoryForPolicyTest(
    505     content::BrowserContext* profile) {
    506   CloudPrintProxyService* service =
    507       new CloudPrintProxyService(static_cast<Profile*>(profile));
    508   service->Initialize();
    509   return service;
    510 }
    511 
    512 TEST_F(CloudPrintProxyPolicyStartupTest, StartBrowserWithoutPolicy) {
    513   base::ProcessHandle handle =
    514       Launch("CloudPrintMockService_StartEnabledWaitForQuit");
    515 
    516   // Setup the Browser Process with a full IOThread::Globals.
    517   TestingBrowserProcess* browser_process =
    518       TestingBrowserProcess::GetGlobal();
    519 
    520   TestingProfileManager profile_manager(browser_process);
    521   ASSERT_TRUE(profile_manager.SetUp());
    522 
    523   // Must be created after the TestingProfileManager since that creates the
    524   // LocalState for the BrowserProcess.  Must be created before profiles are
    525   // constructed.
    526   chrome::TestingIOThreadState testing_io_thread_state;
    527 
    528   TestingProfile* profile =
    529       profile_manager.CreateTestingProfile("StartBrowserWithoutPolicy");
    530   CloudPrintProxyServiceFactory::GetInstance()->
    531       SetTestingFactory(profile, CloudPrintProxyServiceFactoryForPolicyTest);
    532 
    533   TestingPrefServiceSyncable* prefs = profile->GetTestingPrefService();
    534   prefs->SetUserPref(prefs::kCloudPrintEmail,
    535                      Value::CreateStringValue(
    536                          MockServiceIPCServer::EnabledUserId()));
    537 
    538   CommandLine command_line(CommandLine::NO_PROGRAM);
    539   command_line.AppendSwitch(switches::kCheckCloudPrintConnectorPolicy);
    540   test_launcher_utils::PrepareBrowserCommandLineForTests(&command_line);
    541 
    542   WaitForConnect();
    543   base::RunLoop run_loop;
    544   base::MessageLoop::current()->PostDelayedTask(
    545       FROM_HERE,
    546       run_loop.QuitClosure(),
    547       TestTimeouts::action_timeout());
    548 
    549   bool should_run_loop = LaunchBrowser(command_line, profile);
    550   EXPECT_FALSE(should_run_loop);
    551   if (should_run_loop)
    552     run_loop.Run();
    553 
    554   EXPECT_EQ(MockServiceIPCServer::EnabledUserId(),
    555             prefs->GetString(prefs::kCloudPrintEmail));
    556 
    557   ShutdownAndWaitForExitWithTimeout(handle);
    558   content::RunAllPendingInMessageLoop();
    559   profile_manager.DeleteTestingProfile("StartBrowserWithoutPolicy");
    560 }
    561 
    562 TEST_F(CloudPrintProxyPolicyStartupTest, StartBrowserWithPolicy) {
    563   base::ProcessHandle handle =
    564       Launch("CloudPrintMockService_StartEnabledExpectDisabled");
    565 
    566   TestingBrowserProcess* browser_process =
    567       TestingBrowserProcess::GetGlobal();
    568   TestingProfileManager profile_manager(browser_process);
    569   ASSERT_TRUE(profile_manager.SetUp());
    570 
    571   // Must be created after the TestingProfileManager since that creates the
    572   // LocalState for the BrowserProcess.  Must be created before profiles are
    573   // constructed.
    574   chrome::TestingIOThreadState testing_io_thread_state;
    575 
    576   TestingProfile* profile =
    577       profile_manager.CreateTestingProfile("StartBrowserWithPolicy");
    578   CloudPrintProxyServiceFactory::GetInstance()->
    579       SetTestingFactory(profile, CloudPrintProxyServiceFactoryForPolicyTest);
    580 
    581   TestingPrefServiceSyncable* prefs = profile->GetTestingPrefService();
    582   prefs->SetUserPref(prefs::kCloudPrintEmail,
    583                      Value::CreateStringValue(
    584                          MockServiceIPCServer::EnabledUserId()));
    585   prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
    586                         Value::CreateBooleanValue(false));
    587 
    588   CommandLine command_line(CommandLine::NO_PROGRAM);
    589   command_line.AppendSwitch(switches::kCheckCloudPrintConnectorPolicy);
    590   test_launcher_utils::PrepareBrowserCommandLineForTests(&command_line);
    591 
    592   WaitForConnect();
    593   base::RunLoop run_loop;
    594   base::MessageLoop::current()->PostDelayedTask(
    595       FROM_HERE,
    596       run_loop.QuitClosure(),
    597       TestTimeouts::action_timeout());
    598 
    599   bool should_run_loop = LaunchBrowser(command_line, profile);
    600 
    601   // No expectations on run_loop being true here; that would be a race
    602   // condition.
    603   if (should_run_loop)
    604     run_loop.Run();
    605 
    606   EXPECT_EQ("", prefs->GetString(prefs::kCloudPrintEmail));
    607 
    608   ShutdownAndWaitForExitWithTimeout(handle);
    609   content::RunAllPendingInMessageLoop();
    610   profile_manager.DeleteTestingProfile("StartBrowserWithPolicy");
    611 }
    612