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