cloud_print_proxy_process_browsertest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/keyed_service/core/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 54using ::testing::AnyNumber; 55using ::testing::Assign; 56using ::testing::AtLeast; 57using ::testing::DoAll; 58using ::testing::Invoke; 59using ::testing::Mock; 60using ::testing::Property; 61using ::testing::Return; 62using ::testing::WithoutArgs; 63using ::testing::_; 64using content::BrowserThread; 65 66namespace { 67 68enum MockServiceProcessExitCodes { 69 kMissingSwitch = 1, 70 kInitializationFailure, 71 kExpectationsNotMet, 72 kShutdownNotGood 73}; 74 75#if defined(OS_MACOSX) 76const char kTestExecutablePath[] = "test-executable-path"; 77#endif 78 79bool g_good_shutdown = false; 80 81void ShutdownTask() { 82 g_good_shutdown = true; 83 g_service_process->Shutdown(); 84} 85 86class TestStartupClientChannelListener : public IPC::Listener { 87 public: 88 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 89 return false; 90 } 91}; 92 93} // namespace 94 95class 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 108bool 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. 121class 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 148std::string MockServiceIPCServer::EnabledUserId() { 149 return std::string("kitteh@canhazcheezburger.cat"); 150} 151 152void 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 179void 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 191bool 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 204typedef 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. 210int 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 278void SetServiceEnabledExpectations(MockServiceIPCServer* server) { 279 server->SetServiceEnabledExpectations(); 280} 281 282MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledWaitForQuit) { 283 return CloudPrintMockService_Main( 284 base::Bind(&SetServiceEnabledExpectations)); 285} 286 287void SetServiceWillBeDisabledExpectations(MockServiceIPCServer* server) { 288 server->SetWillBeDisabledExpectations(); 289} 290 291MULTIPROCESS_IPC_TEST_MAIN(CloudPrintMockService_StartEnabledExpectDisabled) { 292 return CloudPrintMockService_Main( 293 base::Bind(&SetServiceWillBeDisabledExpectations)); 294} 295 296class 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) OVERRIDE; 321 322 bool LaunchBrowser(const CommandLine& command_line, Profile* profile) { 323 int return_code = 0; 324 StartupBrowserCreator browser_creator; 325 return StartupBrowserCreator::ProcessCmdLineImpl( 326 command_line, base::FilePath(), false, profile, 327 StartupBrowserCreator::Profiles(), &return_code, &browser_creator); 328 } 329 330 protected: 331 content::TestBrowserThreadBundle thread_bundle_; 332 base::ScopedTempDir temp_user_data_dir_; 333 334 std::string startup_channel_id_; 335 scoped_ptr<IPC::ChannelProxy> startup_channel_; 336 337#if defined(OS_MACOSX) 338 base::ScopedTempDir temp_dir_; 339 base::FilePath executable_path_, bundle_path_; 340 scoped_ptr<MockLaunchd> mock_launchd_; 341 scoped_ptr<Launchd::ScopedInstance> scoped_launchd_instance_; 342#endif 343 344 private: 345 class WindowedChannelConnectionObserver { 346 public: 347 WindowedChannelConnectionObserver() 348 : seen_(false), 349 running_(false) { } 350 351 void Wait() { 352 if (seen_) 353 return; 354 running_ = true; 355 content::RunMessageLoop(); 356 } 357 358 void Notify() { 359 seen_ = true; 360 if (running_) 361 base::MessageLoopForUI::current()->Quit(); 362 } 363 364 private: 365 bool seen_; 366 bool running_; 367 }; 368 369 WindowedChannelConnectionObserver observer_; 370}; 371 372CloudPrintProxyPolicyStartupTest::CloudPrintProxyPolicyStartupTest() 373 : thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) { 374} 375 376CloudPrintProxyPolicyStartupTest::~CloudPrintProxyPolicyStartupTest() { 377} 378 379void CloudPrintProxyPolicyStartupTest::SetUp() { 380 TestingBrowserProcess::CreateInstance(); 381#if defined(OS_MACOSX) 382 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); 383 EXPECT_TRUE(MockLaunchd::MakeABundle(temp_dir_.path(), 384 "CloudPrintProxyTest", 385 &bundle_path_, 386 &executable_path_)); 387 mock_launchd_.reset(new MockLaunchd(executable_path_, 388 base::MessageLoopForUI::current(), 389 true, false)); 390 scoped_launchd_instance_.reset( 391 new Launchd::ScopedInstance(mock_launchd_.get())); 392#endif 393 394 // Ensure test does not use the standard profile directory. This is copied 395 // from InProcessBrowserTest::SetUp(). These tests require a more complex 396 // process startup so they are unable to just inherit from 397 // InProcessBrowserTest. 398 CommandLine* command_line = CommandLine::ForCurrentProcess(); 399 base::FilePath user_data_dir = 400 command_line->GetSwitchValuePath(switches::kUserDataDir); 401 if (user_data_dir.empty()) { 402 ASSERT_TRUE(temp_user_data_dir_.CreateUniqueTempDir() && 403 temp_user_data_dir_.IsValid()) 404 << "Could not create temporary user data directory \"" 405 << temp_user_data_dir_.path().value() << "\"."; 406 407 user_data_dir = temp_user_data_dir_.path(); 408 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir); 409 } 410 ASSERT_TRUE(test_launcher_utils::OverrideUserDataDir(user_data_dir)); 411} 412 413void CloudPrintProxyPolicyStartupTest::TearDown() { 414 TestingBrowserProcess::DeleteInstance(); 415} 416 417base::ProcessHandle CloudPrintProxyPolicyStartupTest::Launch( 418 const std::string& name) { 419 EXPECT_FALSE(CheckServiceProcessReady()); 420 421 startup_channel_id_ = 422 base::StringPrintf("%d.%p.%d", 423 base::GetCurrentProcId(), this, 424 base::RandInt(0, std::numeric_limits<int>::max())); 425 startup_channel_.reset(new IPC::ChannelProxy( 426 startup_channel_id_, IPC::Channel::MODE_SERVER, 427 this, IOMessageLoopProxy())); 428 429#if defined(OS_POSIX) 430 base::FileHandleMappingVector ipc_file_list; 431 ipc_file_list.push_back(std::make_pair( 432 startup_channel_->TakeClientFileDescriptor(), 433 kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor)); 434 base::LaunchOptions options; 435 options.fds_to_remap = &ipc_file_list; 436 base::ProcessHandle handle = SpawnChildWithOptions(name, options); 437#else 438 base::ProcessHandle handle = SpawnChild(name); 439#endif 440 EXPECT_TRUE(handle); 441 return handle; 442} 443 444void CloudPrintProxyPolicyStartupTest::WaitForConnect() { 445 observer_.Wait(); 446 EXPECT_TRUE(CheckServiceProcessReady()); 447 EXPECT_TRUE(base::MessageLoopProxy::current().get()); 448 ServiceProcessControl::GetInstance()->SetChannel( 449 new IPC::ChannelProxy(GetServiceProcessChannel(), 450 IPC::Channel::MODE_NAMED_CLIENT, 451 ServiceProcessControl::GetInstance(), 452 IOMessageLoopProxy())); 453} 454 455bool CloudPrintProxyPolicyStartupTest::Send(IPC::Message* message) { 456 return ServiceProcessControl::GetInstance()->Send(message); 457} 458 459void CloudPrintProxyPolicyStartupTest::ShutdownAndWaitForExitWithTimeout( 460 base::ProcessHandle handle) { 461 ASSERT_TRUE(Send(new ServiceMsg_Shutdown())); 462 463 int exit_code = -100; 464 bool exited = 465 base::WaitForExitCodeWithTimeout(handle, &exit_code, 466 TestTimeouts::action_timeout()); 467 EXPECT_TRUE(exited); 468 EXPECT_EQ(exit_code, 0); 469 base::CloseProcessHandle(handle); 470} 471 472void CloudPrintProxyPolicyStartupTest::OnChannelConnected(int32 peer_pid) { 473 observer_.Notify(); 474} 475 476CommandLine CloudPrintProxyPolicyStartupTest::MakeCmdLine( 477 const std::string& procname) { 478 CommandLine cl = MultiProcessTest::MakeCmdLine(procname); 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 486TEST_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 504KeyedService* CloudPrintProxyServiceFactoryForPolicyTest( 505 content::BrowserContext* profile) { 506 CloudPrintProxyService* service = 507 new CloudPrintProxyService(static_cast<Profile*>(profile)); 508 service->Initialize(); 509 return service; 510} 511 512TEST_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 base::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 562TEST_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 base::Value::CreateStringValue( 584 MockServiceIPCServer::EnabledUserId())); 585 prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, 586 base::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