| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/login/login_utils.h" | 5 #include "chrome/browser/chromeos/login/login_utils.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 12 #include "base/scoped_temp_dir.h" | 12 #include "base/scoped_temp_dir.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "base/synchronization/waitable_event.h" |
| 14 #include "base/threading/sequenced_worker_pool.h" | 15 #include "base/threading/sequenced_worker_pool.h" |
| 16 #include "base/threading/thread.h" |
| 15 #include "chrome/browser/chromeos/cros/cros_library.h" | 17 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 16 #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" | 18 #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" |
| 17 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h" | 19 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h" |
| 18 #include "chrome/browser/chromeos/login/authenticator.h" | 20 #include "chrome/browser/chromeos/login/authenticator.h" |
| 19 #include "chrome/browser/chromeos/login/login_status_consumer.h" | 21 #include "chrome/browser/chromeos/login/login_status_consumer.h" |
| 20 #include "chrome/browser/chromeos/login/user_manager.h" | 22 #include "chrome/browser/chromeos/login/user_manager.h" |
| 21 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" | 23 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" |
| 22 #include "chrome/browser/io_thread.h" | 24 #include "chrome/browser/io_thread.h" |
| 23 #include "chrome/browser/net/predictor.h" | 25 #include "chrome/browser/net/predictor.h" |
| 24 #include "chrome/browser/policy/browser_policy_connector.h" | 26 #include "chrome/browser/policy/browser_policy_connector.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 "http://server/device_management?request=policy"; | 89 "http://server/device_management?request=policy"; |
| 88 | 90 |
| 89 const char kDMToken[] = "1234"; | 91 const char kDMToken[] = "1234"; |
| 90 | 92 |
| 91 // Used to mark |flag|, indicating that RefreshPolicies() has executed its | 93 // Used to mark |flag|, indicating that RefreshPolicies() has executed its |
| 92 // callback. | 94 // callback. |
| 93 void SetFlag(bool* flag) { | 95 void SetFlag(bool* flag) { |
| 94 *flag = true; | 96 *flag = true; |
| 95 } | 97 } |
| 96 | 98 |
| 99 // Single task of the fake IO loop used in the test, that just waits until |
| 100 // it is signaled to quit or perform some work. |
| 101 // |completion| is the event to wait for, and |work| is the task to invoke |
| 102 // when signaled. If the task returns false then this quits the IO loop. |
| 103 void BlockLoop(base::WaitableEvent* completion, base::Callback<bool()> work) { |
| 104 do { |
| 105 completion->Wait(); |
| 106 } while (work.Run()); |
| 107 MessageLoop::current()->QuitNow(); |
| 108 } |
| 109 |
| 97 ACTION_P(MockSessionManagerClientRetrievePolicyCallback, policy) { | 110 ACTION_P(MockSessionManagerClientRetrievePolicyCallback, policy) { |
| 98 arg0.Run(*policy); | 111 arg0.Run(*policy); |
| 99 } | 112 } |
| 100 | 113 |
| 101 ACTION_P(MockSessionManagerClientStorePolicyCallback, success) { | 114 ACTION_P(MockSessionManagerClientStorePolicyCallback, success) { |
| 102 arg1.Run(success); | 115 arg1.Run(success); |
| 103 } | 116 } |
| 104 | 117 |
| 105 class LoginUtilsTest : public testing::Test, | 118 class LoginUtilsTest : public testing::Test, |
| 106 public LoginUtils::Delegate, | 119 public LoginUtils::Delegate, |
| 107 public LoginStatusConsumer { | 120 public LoginStatusConsumer { |
| 108 public: | 121 public: |
| 109 // Initialization here is important. The UI thread gets the test's | 122 // Initialization here is important. The UI thread gets the test's |
| 110 // message loop, as does the file thread (which never actually gets | 123 // message loop, as does the file thread (which never actually gets |
| 111 // started - so this is a way to fake multiple threads on a single | 124 // started - so this is a way to fake multiple threads on a single |
| 112 // test thread). The IO thread does not get the message loop set, | 125 // test thread). The IO thread does not get the message loop set, |
| 113 // and is never started. This is necessary so that we skip various | 126 // and is never started. This is necessary so that we skip various |
| 114 // bits of initialization that get posted to the IO thread. We do | 127 // bits of initialization that get posted to the IO thread. We do |
| 115 // however, at one point in the test, temporarily set the message | 128 // however, at one point in the test, temporarily set the message |
| 116 // loop for the IO thread. | 129 // loop for the IO thread. |
| 117 LoginUtilsTest() | 130 LoginUtilsTest() |
| 118 : loop_(MessageLoop::TYPE_IO), | 131 : fake_io_thread_completion_(false, false), |
| 132 fake_io_thread_("fake_io_thread"), |
| 133 loop_(MessageLoop::TYPE_IO), |
| 119 browser_process_( | 134 browser_process_( |
| 120 static_cast<TestingBrowserProcess*>(g_browser_process)), | 135 static_cast<TestingBrowserProcess*>(g_browser_process)), |
| 121 local_state_(browser_process_), | 136 local_state_(browser_process_), |
| 122 ui_thread_(content::BrowserThread::UI, &loop_), | 137 ui_thread_(BrowserThread::UI, &loop_), |
| 123 db_thread_(content::BrowserThread::DB), | 138 db_thread_(BrowserThread::DB), |
| 124 file_thread_(content::BrowserThread::FILE, &loop_), | 139 file_thread_(BrowserThread::FILE, &loop_), |
| 125 io_thread_(content::BrowserThread::IO), | |
| 126 mock_async_method_caller_(NULL), | 140 mock_async_method_caller_(NULL), |
| 127 connector_(NULL), | 141 connector_(NULL), |
| 128 cryptohome_(NULL), | 142 cryptohome_(NULL), |
| 129 prepared_profile_(NULL) {} | 143 prepared_profile_(NULL) {} |
| 130 | 144 |
| 131 virtual void SetUp() OVERRIDE { | 145 virtual void SetUp() OVERRIDE { |
| 146 // This test is not a full blown InProcessBrowserTest, and doesn't have |
| 147 // all the usual threads running. However a lot of subsystems pulled from |
| 148 // ProfileImpl post to IO (usually from ProfileIOData), and DCHECK that |
| 149 // those tasks were posted. Those tasks in turn depend on a lot of other |
| 150 // components that aren't there during this test, so this kludge is used to |
| 151 // have a running IO loop that doesn't really execute any tasks. |
| 152 // |
| 153 // See InvokeOnIO() below for a way to perform specific tasks on IO, when |
| 154 // that's necessary. |
| 155 |
| 156 // A thread is needed to create a new MessageLoop, since there can be only |
| 157 // one loop per thread. |
| 158 fake_io_thread_.StartWithOptions( |
| 159 base::Thread::Options(MessageLoop::TYPE_IO, 0)); |
| 160 MessageLoop* fake_io_loop = fake_io_thread_.message_loop(); |
| 161 // Make this loop enter the single task, BlockLoop(). Pass in the completion |
| 162 // event and the work callback. |
| 163 fake_io_loop->PostTask( |
| 164 FROM_HERE, |
| 165 base::Bind( |
| 166 BlockLoop, |
| 167 &fake_io_thread_completion_, |
| 168 base::Bind(&LoginUtilsTest::DoIOWork, base::Unretained(this)))); |
| 169 // Map BrowserThread::IO to this loop. This allows posting to IO but nothing |
| 170 // will be executed. |
| 171 io_thread_.reset( |
| 172 new content::TestBrowserThread(BrowserThread::IO, fake_io_loop)); |
| 173 |
| 132 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); | 174 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); |
| 133 | 175 |
| 134 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 176 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 135 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, kDMServer); | 177 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, kDMServer); |
| 136 command_line->AppendSwitchASCII(switches::kLoginProfile, "user"); | 178 command_line->AppendSwitchASCII(switches::kLoginProfile, "user"); |
| 137 | 179 |
| 138 local_state_.Get()->RegisterStringPref(prefs::kApplicationLocale, ""); | 180 local_state_.Get()->RegisterStringPref(prefs::kApplicationLocale, ""); |
| 139 | 181 |
| 140 // DBusThreadManager should be initialized before io_thread_state_, as | 182 // DBusThreadManager should be initialized before io_thread_state_, as |
| 141 // DBusThreadManager is used from chromeos::ProxyConfigServiceImpl, | 183 // DBusThreadManager is used from chromeos::ProxyConfigServiceImpl, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 connector_ = browser_process_->browser_policy_connector(); | 262 connector_ = browser_process_->browser_policy_connector(); |
| 221 connector_->Init(); | 263 connector_->Init(); |
| 222 | 264 |
| 223 RunUntilIdle(); | 265 RunUntilIdle(); |
| 224 } | 266 } |
| 225 | 267 |
| 226 virtual void TearDown() OVERRIDE { | 268 virtual void TearDown() OVERRIDE { |
| 227 cryptohome::AsyncMethodCaller::Shutdown(); | 269 cryptohome::AsyncMethodCaller::Shutdown(); |
| 228 mock_async_method_caller_ = NULL; | 270 mock_async_method_caller_ = NULL; |
| 229 | 271 |
| 230 RunUntilIdle(); | 272 InvokeOnIO( |
| 231 { | 273 base::Bind(&LoginUtilsTest::TearDownOnIO, base::Unretained(this))); |
| 232 // chrome_browser_net::Predictor usually skips its shutdown routines on | |
| 233 // unit_tests, but does the full thing when | |
| 234 // g_browser_process->profile_manager() is valid during initialization. | |
| 235 // Run a task on a temporary BrowserThread::IO that allows skipping | |
| 236 // these routines. | |
| 237 // | |
| 238 // It is important to not have a fake message loop on the IO | |
| 239 // thread for the whole test, see comment on LoginUtilsTest | |
| 240 // constructor for details. | |
| 241 io_thread_.DeprecatedSetMessageLoop(&loop_); | |
| 242 loop_.PostTask(FROM_HERE, | |
| 243 base::Bind(&LoginUtilsTest::TearDownOnIO, | |
| 244 base::Unretained(this))); | |
| 245 RunUntilIdle(); | |
| 246 io_thread_.DeprecatedSetMessageLoop(NULL); | |
| 247 } | |
| 248 | 274 |
| 249 // These trigger some tasks that have to run while BrowserThread::UI | 275 // These trigger some tasks that have to run while BrowserThread::UI |
| 250 // exists. Delete all the profiles before deleting the connector. | 276 // exists. Delete all the profiles before deleting the connector. |
| 251 browser_process_->SetProfileManager(NULL); | 277 browser_process_->SetProfileManager(NULL); |
| 252 connector_ = NULL; | 278 connector_ = NULL; |
| 253 browser_process_->SetBrowserPolicyConnector(NULL); | 279 browser_process_->SetBrowserPolicyConnector(NULL); |
| 280 QuitIOLoop(); |
| 254 RunUntilIdle(); | 281 RunUntilIdle(); |
| 255 } | 282 } |
| 256 | 283 |
| 257 void TearDownOnIO() { | 284 void TearDownOnIO() { |
| 285 // chrome_browser_net::Predictor usually skips its shutdown routines on |
| 286 // unit_tests, but does the full thing when |
| 287 // g_browser_process->profile_manager() is valid during initialization. |
| 288 // That includes a WaitableEvent on UI waiting for a task on IO, so that |
| 289 // task must execute. Do it directly from here now. |
| 258 std::vector<Profile*> profiles = | 290 std::vector<Profile*> profiles = |
| 259 browser_process_->profile_manager()->GetLoadedProfiles(); | 291 browser_process_->profile_manager()->GetLoadedProfiles(); |
| 260 for (size_t i = 0; i < profiles.size(); ++i) { | 292 for (size_t i = 0; i < profiles.size(); ++i) { |
| 261 chrome_browser_net::Predictor* predictor = | 293 chrome_browser_net::Predictor* predictor = |
| 262 profiles[i]->GetNetworkPredictor(); | 294 profiles[i]->GetNetworkPredictor(); |
| 263 if (predictor) { | 295 if (predictor) { |
| 264 predictor->EnablePredictorOnIOThread(false); | 296 predictor->EnablePredictorOnIOThread(false); |
| 265 predictor->Shutdown(); | 297 predictor->Shutdown(); |
| 266 } | 298 } |
| 267 } | 299 } |
| 268 } | 300 } |
| 269 | 301 |
| 270 void RunUntilIdle() { | 302 void RunUntilIdle() { |
| 271 loop_.RunUntilIdle(); | 303 loop_.RunUntilIdle(); |
| 272 BrowserThread::GetBlockingPool()->FlushForTesting(); | 304 BrowserThread::GetBlockingPool()->FlushForTesting(); |
| 273 loop_.RunUntilIdle(); | 305 loop_.RunUntilIdle(); |
| 274 } | 306 } |
| 275 | 307 |
| 308 // Invokes |task| on the IO loop and returns after it has executed. |
| 309 void InvokeOnIO(const base::Closure& task) { |
| 310 fake_io_thread_work_ = task; |
| 311 fake_io_thread_completion_.Signal(); |
| 312 content::RunMessageLoop(); |
| 313 } |
| 314 |
| 315 // Makes the fake IO loop return. |
| 316 void QuitIOLoop() { |
| 317 fake_io_thread_completion_.Signal(); |
| 318 content::RunMessageLoop(); |
| 319 } |
| 320 |
| 321 // Helper for BlockLoop, InvokeOnIO and QuitIOLoop. |
| 322 bool DoIOWork() { |
| 323 bool has_work = !fake_io_thread_work_.is_null(); |
| 324 if (has_work) |
| 325 fake_io_thread_work_.Run(); |
| 326 fake_io_thread_work_.Reset(); |
| 327 BrowserThread::PostTask( |
| 328 BrowserThread::UI, FROM_HERE, |
| 329 MessageLoop::QuitWhenIdleClosure()); |
| 330 // If there was work then keep waiting for more work. |
| 331 // If there was no work then quit the fake IO loop. |
| 332 return has_work; |
| 333 } |
| 334 |
| 276 virtual void OnProfilePrepared(Profile* profile) OVERRIDE { | 335 virtual void OnProfilePrepared(Profile* profile) OVERRIDE { |
| 277 EXPECT_FALSE(prepared_profile_); | 336 EXPECT_FALSE(prepared_profile_); |
| 278 prepared_profile_ = profile; | 337 prepared_profile_ = profile; |
| 279 } | 338 } |
| 280 | 339 |
| 281 virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE { | 340 virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE { |
| 282 FAIL() << "OnLoginFailure not expected"; | 341 FAIL() << "OnLoginFailure not expected"; |
| 283 } | 342 } |
| 284 | 343 |
| 285 virtual void OnLoginSuccess(const std::string& username, | 344 virtual void OnLoginSuccess(const std::string& username, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 | 430 |
| 372 net::TestURLFetcher* PrepareDMPolicyFetcher() { | 431 net::TestURLFetcher* PrepareDMPolicyFetcher() { |
| 373 em::DeviceManagementResponse response; | 432 em::DeviceManagementResponse response; |
| 374 response.mutable_policy_response()->add_response(); | 433 response.mutable_policy_response()->add_response(); |
| 375 return PrepareDMServiceFetcher(kDMPolicyRequest, response); | 434 return PrepareDMServiceFetcher(kDMPolicyRequest, response); |
| 376 } | 435 } |
| 377 | 436 |
| 378 protected: | 437 protected: |
| 379 ScopedStubCrosEnabler stub_cros_enabler_; | 438 ScopedStubCrosEnabler stub_cros_enabler_; |
| 380 | 439 |
| 440 base::Closure fake_io_thread_work_; |
| 441 base::WaitableEvent fake_io_thread_completion_; |
| 442 base::Thread fake_io_thread_; |
| 443 |
| 381 MessageLoop loop_; | 444 MessageLoop loop_; |
| 382 TestingBrowserProcess* browser_process_; | 445 TestingBrowserProcess* browser_process_; |
| 383 ScopedTestingLocalState local_state_; | 446 ScopedTestingLocalState local_state_; |
| 384 | 447 |
| 385 content::TestBrowserThread ui_thread_; | 448 content::TestBrowserThread ui_thread_; |
| 386 content::TestBrowserThread db_thread_; | 449 content::TestBrowserThread db_thread_; |
| 387 content::TestBrowserThread file_thread_; | 450 content::TestBrowserThread file_thread_; |
| 388 content::TestBrowserThread io_thread_; | 451 scoped_ptr<content::TestBrowserThread> io_thread_; |
| 389 scoped_ptr<IOThread> io_thread_state_; | 452 scoped_ptr<IOThread> io_thread_state_; |
| 390 | 453 |
| 391 MockDBusThreadManager mock_dbus_thread_manager_; | 454 MockDBusThreadManager mock_dbus_thread_manager_; |
| 392 input_method::MockInputMethodManager mock_input_method_manager_; | 455 input_method::MockInputMethodManager mock_input_method_manager_; |
| 393 net::TestURLFetcherFactory test_url_fetcher_factory_; | 456 net::TestURLFetcherFactory test_url_fetcher_factory_; |
| 394 | 457 |
| 395 cryptohome::MockAsyncMethodCaller* mock_async_method_caller_; | 458 cryptohome::MockAsyncMethodCaller* mock_async_method_caller_; |
| 396 | 459 |
| 397 policy::BrowserPolicyConnector* connector_; | 460 policy::BrowserPolicyConnector* connector_; |
| 398 MockCryptohomeLibrary* cryptohome_; | 461 MockCryptohomeLibrary* cryptohome_; |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 } | 654 } |
| 592 | 655 |
| 593 INSTANTIATE_TEST_CASE_P( | 656 INSTANTIATE_TEST_CASE_P( |
| 594 LoginUtilsBlockingLoginTestInstance, | 657 LoginUtilsBlockingLoginTestInstance, |
| 595 LoginUtilsBlockingLoginTest, | 658 LoginUtilsBlockingLoginTest, |
| 596 testing::Values(0, 1, 2, 3, 4, 5)); | 659 testing::Values(0, 1, 2, 3, 4, 5)); |
| 597 | 660 |
| 598 } // namespace | 661 } // namespace |
| 599 | 662 |
| 600 } | 663 } |
| OLD | NEW |