• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ShutdownTask()85 void ShutdownTask() {
86   g_good_shutdown = true;
87   g_service_process->Shutdown();
88 }
89 
90 class TestStartupClientChannelListener : public IPC::Listener {
91  public:
OnMessageReceived(const IPC::Message & message)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:
TestServiceProcess()101   TestServiceProcess() { }
~TestServiceProcess()102   virtual ~TestServiceProcess() { }
103 
104   bool Initialize(base::MessageLoopForUI* message_loop,
105                   ServiceProcessState* state);
106 
IOMessageLoopProxy()107   base::MessageLoopProxy* IOMessageLoopProxy() {
108     return io_thread_->message_loop_proxy().get();
109   }
110 };
111 
Initialize(base::MessageLoopForUI * message_loop,ServiceProcessState * state)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 
MockServiceIPCServer(const IPC::ChannelHandle & handle)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 
CallServiceOnChannelConnected(int32 peer_pid)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
EnabledUserId()152 std::string MockServiceIPCServer::EnabledUserId() {
153   return std::string("kitteh@canhazcheezburger.cat");
154 }
155 
SetServiceEnabledExpectations()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 
SetWillBeDisabledExpectations()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 
SendInfo()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.
CloudPrintMockService_Main(SetExpectationsCallback set_expectations)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 
SetServiceEnabledExpectations(MockServiceIPCServer * server)283 void SetServiceEnabledExpectations(MockServiceIPCServer* server) {
284   server->SetServiceEnabledExpectations();
285 }
286 
MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledWaitForQuit)287 MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledWaitForQuit) {
288   return CloudPrintMockService_Main(
289       base::Bind(&SetServiceEnabledExpectations));
290 }
291 
SetServiceWillBeDisabledExpectations(MockServiceIPCServer * server)292 void SetServiceWillBeDisabledExpectations(MockServiceIPCServer* server) {
293   server->SetWillBeDisabledExpectations();
294 }
295 
MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledExpectDisabled)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 
IOMessageLoopProxy()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
OnMessageReceived(const IPC::Message & message)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 
LaunchBrowser(const CommandLine & command_line,Profile * profile)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:
WindowedChannelConnectionObserver()354     WindowedChannelConnectionObserver()
355         : seen_(false),
356           running_(false) { }
357 
Wait()358     void Wait() {
359       if (seen_)
360         return;
361       running_ = true;
362       content::RunMessageLoop();
363     }
364 
Notify()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 
CloudPrintProxyPolicyStartupTest()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 
~CloudPrintProxyPolicyStartupTest()387 CloudPrintProxyPolicyStartupTest::~CloudPrintProxyPolicyStartupTest() {
388 }
389 
SetUp()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 
TearDown()429 void CloudPrintProxyPolicyStartupTest::TearDown() {
430   browser_content_client_.reset();
431   content_client_.reset();
432   content::SetContentClient(NULL);
433 
434   TestingBrowserProcess::DeleteInstance();
435 }
436 
Launch(const std::string & name)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 
WaitForConnect()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 
Send(IPC::Message * message)476 bool CloudPrintProxyPolicyStartupTest::Send(IPC::Message* message) {
477   return ServiceProcessControl::GetInstance()->Send(message);
478 }
479 
ShutdownAndWaitForExitWithTimeout(base::ProcessHandle handle)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 
OnChannelConnected(int32 peer_pid)493 void CloudPrintProxyPolicyStartupTest::OnChannelConnected(int32 peer_pid) {
494   observer_.Notify();
495 }
496 
MakeCmdLine(const std::string & procname)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 
TEST_F(CloudPrintProxyPolicyStartupTest,StartAndShutdown)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 
CloudPrintProxyServiceFactoryForPolicyTest(content::BrowserContext * profile)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 
TEST_F(CloudPrintProxyPolicyStartupTest,StartBrowserWithoutPolicy)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 
TEST_F(CloudPrintProxyPolicyStartupTest,StartBrowserWithPolicy)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