Add GCMChannelStatusSyncer to schedule requests and enable/disable GCM
[chromium-blink-merge.git] / chrome / browser / printing / cloud_print / test / cloud_print_proxy_process_browsertest.cc
blobe03d85c9f2a59f2aeae554a2b75950bb45458a9d
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.
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.
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"
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
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;
70 namespace {
72 enum MockServiceProcessExitCodes {
73 kMissingSwitch = 1,
74 kInitializationFailure,
75 kExpectationsNotMet,
76 kShutdownNotGood
79 #if defined(OS_MACOSX)
80 const char kTestExecutablePath[] = "test-executable-path";
81 #endif
83 bool g_good_shutdown = false;
85 void ShutdownTask() {
86 g_good_shutdown = true;
87 g_service_process->Shutdown();
90 class TestStartupClientChannelListener : public IPC::Listener {
91 public:
92 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
93 return false;
97 } // namespace
99 class TestServiceProcess : public ServiceProcess {
100 public:
101 TestServiceProcess() { }
102 virtual ~TestServiceProcess() { }
104 bool Initialize(base::MessageLoopForUI* message_loop,
105 ServiceProcessState* state);
107 base::MessageLoopProxy* IOMessageLoopProxy() {
108 return io_thread_->message_loop_proxy().get();
112 bool TestServiceProcess::Initialize(base::MessageLoopForUI* message_loop,
113 ServiceProcessState* state) {
114 main_message_loop_ = message_loop;
116 service_process_state_.reset(state);
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);
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();
129 explicit MockServiceIPCServer(const IPC::ChannelHandle& handle)
130 : ServiceIPCServer(handle),
131 enabled_(true) { }
133 MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message& message));
134 MOCK_METHOD1(OnChannelConnected, void(int32 peer_pid));
135 MOCK_METHOD0(OnChannelError, void());
137 void SetServiceEnabledExpectations();
138 void SetWillBeDisabledExpectations();
140 void CallServiceOnChannelConnected(int32 peer_pid) {
141 ServiceIPCServer::OnChannelConnected(peer_pid);
144 bool SendInfo();
146 private:
147 cloud_print::CloudPrintProxyInfo info_;
148 bool enabled_;
151 // static
152 std::string MockServiceIPCServer::EnabledUserId() {
153 return std::string("kitteh@canhazcheezburger.cat");
156 void MockServiceIPCServer::SetServiceEnabledExpectations() {
157 EXPECT_CALL(*this, OnChannelConnected(_)).Times(1)
158 .WillRepeatedly(
159 Invoke(this, &MockServiceIPCServer::CallServiceOnChannelConnected));
161 EXPECT_CALL(*this, OnChannelError()).Times(0);
162 EXPECT_CALL(*this, OnMessageReceived(_)).Times(0);
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)));
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)));
183 void MockServiceIPCServer::SetWillBeDisabledExpectations() {
184 SetServiceEnabledExpectations();
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)));
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_)));
205 return true;
208 typedef base::Callback<void(MockServiceIPCServer* server)>
209 SetExpectationsCallback;
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();
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
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));
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;
241 TestServiceProcess service_process;
242 EXPECT_EQ(&service_process, g_service_process);
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));
248 MockServiceIPCServer server(state->GetServiceProcessChannel());
250 // Here is where the expectations/mock responses need to be set up.
251 set_expectations.Run(&server);
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
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());
275 main_message_loop.Run();
276 if (!Mock::VerifyAndClearExpectations(&server))
277 return kExpectationsNotMet;
278 if (!g_good_shutdown)
279 return kShutdownNotGood;
280 return 0;
283 void SetServiceEnabledExpectations(MockServiceIPCServer* server) {
284 server->SetServiceEnabledExpectations();
287 MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledWaitForQuit) {
288 return CloudPrintMockService_Main(
289 base::Bind(&SetServiceEnabledExpectations));
292 void SetServiceWillBeDisabledExpectations(MockServiceIPCServer* server) {
293 server->SetWillBeDisabledExpectations();
296 MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledExpectDisabled) {
297 return CloudPrintMockService_Main(
298 base::Bind(&SetServiceWillBeDisabledExpectations));
301 class CloudPrintProxyPolicyStartupTest : public base::MultiProcessTest,
302 public IPC::Listener {
303 public:
304 CloudPrintProxyPolicyStartupTest();
305 virtual ~CloudPrintProxyPolicyStartupTest();
307 virtual void SetUp() OVERRIDE;
308 virtual void TearDown() OVERRIDE;
310 scoped_refptr<base::MessageLoopProxy> IOMessageLoopProxy() {
311 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
313 base::ProcessHandle Launch(const std::string& name);
314 void WaitForConnect();
315 bool Send(IPC::Message* message);
316 void ShutdownAndWaitForExitWithTimeout(base::ProcessHandle handle);
318 // IPC::Listener implementation
319 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
320 return false;
322 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
324 // MultiProcessTest implementation.
325 virtual CommandLine MakeCmdLine(const std::string& procname) OVERRIDE;
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);
335 protected:
336 content::TestBrowserThreadBundle thread_bundle_;
337 base::ScopedTempDir temp_user_data_dir_;
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_;
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
351 private:
352 class WindowedChannelConnectionObserver {
353 public:
354 WindowedChannelConnectionObserver()
355 : seen_(false),
356 running_(false) { }
358 void Wait() {
359 if (seen_)
360 return;
361 running_ = true;
362 content::RunMessageLoop();
365 void Notify() {
366 seen_ = true;
367 if (running_)
368 base::MessageLoopForUI::current()->Quit();
371 private:
372 bool seen_;
373 bool running_;
376 WindowedChannelConnectionObserver observer_;
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();
387 CloudPrintProxyPolicyStartupTest::~CloudPrintProxyPolicyStartupTest() {
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());
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
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() << "\".";
423 user_data_dir = temp_user_data_dir_.path();
424 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
426 ASSERT_TRUE(test_launcher_utils::OverrideUserDataDir(user_data_dir));
429 void CloudPrintProxyPolicyStartupTest::TearDown() {
430 browser_content_client_.reset();
431 content_client_.reset();
432 content::SetContentClient(NULL);
434 TestingBrowserProcess::DeleteInstance();
437 base::ProcessHandle CloudPrintProxyPolicyStartupTest::Launch(
438 const std::string& name) {
439 EXPECT_FALSE(CheckServiceProcessReady());
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());
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;
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()));
476 bool CloudPrintProxyPolicyStartupTest::Send(IPC::Message* message) {
477 return ServiceProcessControl::GetInstance()->Send(message);
480 void CloudPrintProxyPolicyStartupTest::ShutdownAndWaitForExitWithTimeout(
481 base::ProcessHandle handle) {
482 ASSERT_TRUE(Send(new ServiceMsg_Shutdown()));
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);
493 void CloudPrintProxyPolicyStartupTest::OnChannelConnected(int32 peer_pid) {
494 observer_.Notify();
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;
507 TEST_F(CloudPrintProxyPolicyStartupTest, StartAndShutdown) {
508 TestingBrowserProcess* browser_process =
509 TestingBrowserProcess::GetGlobal();
510 TestingProfileManager profile_manager(browser_process);
511 ASSERT_TRUE(profile_manager.SetUp());
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;
518 base::ProcessHandle handle =
519 Launch("CloudPrintMockService_StartEnabledWaitForQuit");
520 WaitForConnect();
521 ShutdownAndWaitForExitWithTimeout(handle);
522 content::RunAllPendingInMessageLoop();
525 KeyedService* CloudPrintProxyServiceFactoryForPolicyTest(
526 content::BrowserContext* profile) {
527 CloudPrintProxyService* service =
528 new CloudPrintProxyService(static_cast<Profile*>(profile));
529 service->Initialize();
530 return service;
533 TEST_F(CloudPrintProxyPolicyStartupTest, StartBrowserWithoutPolicy) {
534 base::ProcessHandle handle =
535 Launch("CloudPrintMockService_StartEnabledWaitForQuit");
537 // Setup the Browser Process with a full IOThread::Globals.
538 TestingBrowserProcess* browser_process =
539 TestingBrowserProcess::GetGlobal();
541 TestingProfileManager profile_manager(browser_process);
542 ASSERT_TRUE(profile_manager.SetUp());
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;
549 TestingProfile* profile =
550 profile_manager.CreateTestingProfile("StartBrowserWithoutPolicy");
551 CloudPrintProxyServiceFactory::GetInstance()->
552 SetTestingFactory(profile, CloudPrintProxyServiceFactoryForPolicyTest);
554 TestingPrefServiceSyncable* prefs = profile->GetTestingPrefService();
555 prefs->SetUserPref(
556 prefs::kCloudPrintEmail,
557 new base::StringValue(MockServiceIPCServer::EnabledUserId()));
559 CommandLine command_line(CommandLine::NO_PROGRAM);
560 command_line.AppendSwitch(switches::kCheckCloudPrintConnectorPolicy);
561 test_launcher_utils::PrepareBrowserCommandLineForTests(&command_line);
563 WaitForConnect();
564 base::RunLoop run_loop;
565 base::MessageLoop::current()->PostDelayedTask(
566 FROM_HERE,
567 run_loop.QuitClosure(),
568 TestTimeouts::action_timeout());
570 bool should_run_loop = LaunchBrowser(command_line, profile);
571 EXPECT_FALSE(should_run_loop);
572 if (should_run_loop)
573 run_loop.Run();
575 EXPECT_EQ(MockServiceIPCServer::EnabledUserId(),
576 prefs->GetString(prefs::kCloudPrintEmail));
578 ShutdownAndWaitForExitWithTimeout(handle);
579 content::RunAllPendingInMessageLoop();
580 profile_manager.DeleteTestingProfile("StartBrowserWithoutPolicy");
583 TEST_F(CloudPrintProxyPolicyStartupTest, StartBrowserWithPolicy) {
584 base::ProcessHandle handle =
585 Launch("CloudPrintMockService_StartEnabledExpectDisabled");
587 TestingBrowserProcess* browser_process =
588 TestingBrowserProcess::GetGlobal();
589 TestingProfileManager profile_manager(browser_process);
590 ASSERT_TRUE(profile_manager.SetUp());
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;
597 TestingProfile* profile =
598 profile_manager.CreateTestingProfile("StartBrowserWithPolicy");
599 CloudPrintProxyServiceFactory::GetInstance()->
600 SetTestingFactory(profile, CloudPrintProxyServiceFactoryForPolicyTest);
602 TestingPrefServiceSyncable* prefs = profile->GetTestingPrefService();
603 prefs->SetUserPref(
604 prefs::kCloudPrintEmail,
605 new base::StringValue(MockServiceIPCServer::EnabledUserId()));
606 prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
607 new base::FundamentalValue(false));
609 CommandLine command_line(CommandLine::NO_PROGRAM);
610 command_line.AppendSwitch(switches::kCheckCloudPrintConnectorPolicy);
611 test_launcher_utils::PrepareBrowserCommandLineForTests(&command_line);
613 WaitForConnect();
614 base::RunLoop run_loop;
615 base::MessageLoop::current()->PostDelayedTask(
616 FROM_HERE,
617 run_loop.QuitClosure(),
618 TestTimeouts::action_timeout());
620 bool should_run_loop = LaunchBrowser(command_line, profile);
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();
627 EXPECT_EQ("", prefs->GetString(prefs::kCloudPrintEmail));
629 ShutdownAndWaitForExitWithTimeout(handle);
630 content::RunAllPendingInMessageLoop();
631 profile_manager.DeleteTestingProfile("StartBrowserWithPolicy");