OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium OS 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 "login_manager/session_manager_service.h" | 5 #include "login_manager/session_manager_service.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <gtest/gtest.h> | 8 #include <gtest/gtest.h> |
9 #include <signal.h> | 9 #include <signal.h> |
10 #include <unistd.h> | 10 #include <unistd.h> |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
157 } | 157 } |
158 | 158 |
159 void ExpectStartSession(const std::string& email_string, | 159 void ExpectStartSession(const std::string& email_string, |
160 MockChildJob* job, | 160 MockChildJob* job, |
161 MockPrefStore* store) { | 161 MockPrefStore* store) { |
162 EXPECT_CALL(*job, StartSession(email_string)) | 162 EXPECT_CALL(*job, StartSession(email_string)) |
163 .Times(1); | 163 .Times(1); |
164 MockOwnerKey* key = new MockOwnerKey; | 164 MockOwnerKey* key = new MockOwnerKey; |
165 EXPECT_CALL(*key, PopulateFromDiskIfPossible()) | 165 EXPECT_CALL(*key, PopulateFromDiskIfPossible()) |
166 .WillRepeatedly(Return(true)); | 166 .WillRepeatedly(Return(true)); |
167 // First, expect an attempt to set the device owner property, but | 167 // Expect an attempt to check whether this user is the owner; respond |
168 // act like this user isn't the owner. | |
169 EXPECT_CALL(*key, Sign(_, _, _)) | |
170 .WillOnce(Return(false)); | |
171 manager_->test_api().set_ownerkey(key); | |
172 // Now, expect an attempt to check whether this user is the owner; respond | |
173 // as though he is not. | 168 // as though he is not. |
174 std::string other_user("notme"); | 169 std::string other_user("notme"); |
175 EXPECT_CALL(*store, Get(_, _, _)) | 170 EXPECT_CALL(*store, Get(_, _, _)) |
176 .WillOnce(DoAll(SetArgumentPointee<1>(other_user), | 171 .WillOnce(DoAll(SetArgumentPointee<1>(other_user), |
177 Return(true))); | 172 Return(true))); |
178 EXPECT_CALL(*key, Verify(_, _, _, _)) | 173 EXPECT_CALL(*key, Verify(_, _, _, _)) |
179 .WillOnce(Return(true)); | 174 .WillOnce(Return(true)); |
180 // Confirm that the device is owned. | 175 // Confirm that the device is owned. |
181 EXPECT_CALL(*key, HaveCheckedDisk()) | 176 EXPECT_CALL(*key, HaveCheckedDisk()) |
182 .WillOnce(Return(true)); | 177 .WillOnce(Return(true)); |
183 EXPECT_CALL(*key, IsPopulated()) | 178 EXPECT_CALL(*key, IsPopulated()) |
184 .WillOnce(Return(true)) | 179 .WillOnce(Return(true)) |
185 .WillOnce(Return(true)); | 180 .WillOnce(Return(true)); |
181 manager_->test_api().set_ownerkey(key); | |
186 } | 182 } |
187 | 183 |
188 void ExpectStartSessionUnowned(const std::string& email_string, | 184 void ExpectStartSessionUnowned(const std::string& email_string, |
189 MockPrefStore* store) { | 185 MockPrefStore* store) { |
190 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); | 186 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); |
191 EXPECT_CALL(*job, StartSession(email_string)) | 187 EXPECT_CALL(*job, StartSession(email_string)) |
192 .Times(1); | 188 .Times(1); |
193 | 189 |
194 MockChildJob* k_job = new MockChildJob; | 190 MockChildJob* k_job = new MockChildJob; |
195 EXPECT_CALL(*k_job, SetDesiredUid(getuid())) | 191 EXPECT_CALL(*k_job, SetDesiredUid(getuid())) |
196 .Times(1); | 192 .Times(1); |
197 EXPECT_CALL(*k_job, GetDesiredUid()) | 193 EXPECT_CALL(*k_job, GetDesiredUid()) |
198 .Times(1) | 194 .Times(1) |
199 .WillRepeatedly(Return(getuid())); | 195 .WillRepeatedly(Return(getuid())); |
200 EXPECT_CALL(*k_job, IsDesiredUidSet()) | 196 EXPECT_CALL(*k_job, IsDesiredUidSet()) |
201 .WillRepeatedly(Return(true)); | 197 .WillRepeatedly(Return(true)); |
202 ON_CALL(*k_job, Run()) | 198 ON_CALL(*k_job, Run()) |
203 .WillByDefault(Invoke(CleanExit)); | 199 .WillByDefault(Invoke(CleanExit)); |
204 int keygen_pid = kDummyPid + 1; | 200 int keygen_pid = kDummyPid + 1; |
205 | 201 |
206 MockOwnerKey* key = new MockOwnerKey; | 202 MockOwnerKey* key = new MockOwnerKey; |
207 EXPECT_CALL(*key, PopulateFromDiskIfPossible()) | 203 EXPECT_CALL(*key, PopulateFromDiskIfPossible()) |
208 .WillRepeatedly(Return(true)); | 204 .WillRepeatedly(Return(true)); |
209 EXPECT_CALL(*key, StartGeneration(k_job)) | 205 EXPECT_CALL(*key, StartGeneration(k_job)) |
210 .WillOnce(Return(keygen_pid)); | 206 .WillOnce(Return(keygen_pid)); |
211 // act like this user isn't the owner. | |
212 EXPECT_CALL(*key, Sign(_, _, _)) | |
213 .WillOnce(Return(false)); | |
214 | 207 |
215 // Now, expect an attempt to check whether this user is the owner; respond | 208 // Now, expect an attempt to check whether this user is the owner; respond |
216 // as though there isn't one. | 209 // as though there isn't one. |
217 EXPECT_CALL(*store, Get(_, _, _)) | 210 EXPECT_CALL(*store, Get(_, _, _)) |
218 .WillOnce(Return(false)); | 211 .WillOnce(Return(false)); |
219 // Confirm that the device is NOT owned. | 212 // Confirm that the device is NOT owned. |
220 EXPECT_CALL(*key, HaveCheckedDisk()) | 213 EXPECT_CALL(*key, HaveCheckedDisk()) |
221 .WillOnce(Return(true)); | 214 .WillOnce(Return(true)); |
222 EXPECT_CALL(*key, IsPopulated()) | 215 EXPECT_CALL(*key, IsPopulated()) |
223 .WillOnce(Return(false)); | 216 .WillOnce(Return(false)); |
224 | 217 |
225 manager_->test_api().set_keygen_job(k_job); // manager_ takes ownership. | 218 manager_->test_api().set_keygen_job(k_job); // manager_ takes ownership. |
226 manager_->set_uid(getuid()); | 219 manager_->set_uid(getuid()); |
227 manager_->test_api().set_ownerkey(key); | 220 manager_->test_api().set_ownerkey(key); |
228 manager_->test_api().set_prefstore(store); | 221 manager_->test_api().set_prefstore(store); |
229 | 222 |
230 EXPECT_CALL(*(utils_.get()), kill(keygen_pid, getuid(), SIGTERM)) | 223 EXPECT_CALL(*(utils_.get()), kill(keygen_pid, getuid(), SIGTERM)) |
231 .WillOnce(Return(0)); | 224 .WillOnce(Return(0)); |
232 EXPECT_CALL(*(utils_.get()), ChildIsGone(keygen_pid, _)) | 225 EXPECT_CALL(*(utils_.get()), ChildIsGone(keygen_pid, _)) |
233 .WillOnce(Return(true)); | 226 .WillOnce(Return(true)); |
234 MockUtils(); | 227 MockUtils(); |
235 } | 228 } |
236 | 229 |
237 void ExpectStartSessionForOwner(const std::string& email_string, | 230 void ExpectStartSessionForOwner(const std::string& email_string, |
238 MockOwnerKey* key, | 231 MockOwnerKey* key, |
239 MockPrefStore* store) { | 232 MockPrefStore* store, |
233 bool has_key) { | |
240 ON_CALL(*key, PopulateFromDiskIfPossible()) | 234 ON_CALL(*key, PopulateFromDiskIfPossible()) |
241 .WillByDefault(Return(true)); | 235 .WillByDefault(Return(true)); |
242 // First, mimic attempt to whitelist the owner and set a the | 236 int persist_times = 1; |
243 // device owner pref. | 237 if (has_key) { |
244 EXPECT_CALL(*key, Sign(_, _, _)) | 238 // First, mimic attempt to whitelist the owner and set a the |
gauravsh
2011/04/08 04:58:49
nit: s/a the/the/
Chris Masone
2011/04/08 05:57:41
Done.
| |
245 .WillOnce(Return(true)) | 239 // device owner pref. |
246 .RetiresOnSaturation(); | 240 EXPECT_CALL(*key, Sign(_, _, _)) |
247 EXPECT_CALL(*store, Set(_, email_string, _)) | 241 .WillOnce(Return(true)) |
248 .Times(1); | 242 .RetiresOnSaturation(); |
249 EXPECT_CALL(*key, Sign(CastEq(email_string), email_string.length(), _)) | 243 EXPECT_CALL(*store, Set(_, email_string, _)) |
250 .WillOnce(Return(true)) | 244 .Times(1); |
251 .RetiresOnSaturation(); | 245 EXPECT_CALL(*key, Sign(CastEq(email_string), email_string.length(), _)) |
252 EXPECT_CALL(*store, Whitelist(email_string, _)) | 246 .WillOnce(Return(true)) |
253 .Times(1); | 247 .RetiresOnSaturation(); |
248 EXPECT_CALL(*store, Whitelist(email_string, _)) | |
249 .Times(1); | |
250 persist_times = 3; | |
251 } | |
254 EXPECT_CALL(*store, Persist()) | 252 EXPECT_CALL(*store, Persist()) |
255 .WillOnce(Return(true)) | 253 .Times(persist_times) |
256 .WillOnce(Return(true)) | 254 .WillRepeatedly(Return(true)); |
257 .WillOnce(Return(true)); | 255 |
258 // Now, expect an attempt to check whether this user is the owner; | 256 // Now, expect an attempt to check whether this user is the owner; |
259 // respond as though he is. | 257 // respond as though he is. |
260 EXPECT_CALL(*store, Get(_, _, _)) | 258 EXPECT_CALL(*store, Get(_, _, _)) |
261 .WillOnce(DoAll(SetArgumentPointee<1>(email_string), | 259 .WillOnce(DoAll(SetArgumentPointee<1>(email_string), |
262 Return(true))); | 260 Return(true))); |
263 EXPECT_CALL(*key, Verify(_, _, _, _)) | 261 EXPECT_CALL(*key, Verify(_, _, _, _)) |
264 .WillOnce(Return(true)); | 262 .WillOnce(Return(true)); |
265 // Confirm that the device is owned. | 263 // Confirm that the device is owned. |
266 EXPECT_CALL(*key, HaveCheckedDisk()) | 264 EXPECT_CALL(*key, HaveCheckedDisk()) |
267 .Times(AtMost(1)) | 265 .Times(AtMost(1)) |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
499 | 497 |
500 TEST_F(SessionManagerTest, KeygenTest) { | 498 TEST_F(SessionManagerTest, KeygenTest) { |
501 const char key_file_name[] = "foo.pub"; | 499 const char key_file_name[] = "foo.pub"; |
502 ScopedTempDir tmpdir; | 500 ScopedTempDir tmpdir; |
503 ASSERT_TRUE(tmpdir.CreateUniqueTempDir()); | 501 ASSERT_TRUE(tmpdir.CreateUniqueTempDir()); |
504 FilePath key_file_path(tmpdir.path().AppendASCII(key_file_name)); | 502 FilePath key_file_path(tmpdir.path().AppendASCII(key_file_name)); |
505 | 503 |
506 int pid = fork(); | 504 int pid = fork(); |
507 if (pid == 0) { | 505 if (pid == 0) { |
508 execl("./keygen", "./keygen", key_file_path.value().c_str(), NULL); | 506 execl("./keygen", "./keygen", key_file_path.value().c_str(), NULL); |
509 exit(1); | 507 exit(255); |
510 } | 508 } |
511 int status; | 509 int status; |
512 while (waitpid(pid, &status, 0) == -1 && errno == EINTR) | 510 while (waitpid(pid, &status, 0) == -1 && errno == EINTR) |
513 ; | 511 ; |
514 | 512 |
515 LOG(INFO) << "exited waitpid. " << pid << "\n" | 513 LOG(INFO) << "exited waitpid. " << pid << "\n" |
516 << " WIFSIGNALED is " << WIFSIGNALED(status) << "\n" | 514 << " WIFSIGNALED is " << WIFSIGNALED(status) << "\n" |
517 << " WTERMSIG is " << WTERMSIG(status) << "\n" | 515 << " WTERMSIG is " << WTERMSIG(status) << "\n" |
518 << " WIFEXITED is " << WIFEXITED(status) << "\n" | 516 << " WIFEXITED is " << WIFEXITED(status) << "\n" |
519 << " WEXITSTATUS is " << WEXITSTATUS(status); | 517 << " WEXITSTATUS is " << WEXITSTATUS(status); |
520 | 518 |
521 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); | 519 EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); |
522 ASSERT_TRUE(file_util::PathExists(key_file_path)); | 520 EXPECT_TRUE(file_util::PathExists(key_file_path)); |
523 | 521 |
524 SystemUtils utils; | 522 SystemUtils utils; |
525 int32 file_size = 0; | 523 int32 file_size = 0; |
526 ASSERT_TRUE(utils.EnsureAndReturnSafeFileSize(key_file_path, &file_size)); | 524 EXPECT_TRUE(utils.EnsureAndReturnSafeFileSize(key_file_path, &file_size)); |
527 ASSERT_GT(file_size, 0); | 525 EXPECT_GT(file_size, 0); |
528 } | 526 } |
529 | 527 |
530 TEST_F(SessionManagerTest, SessionNotStartedCleanup) { | 528 TEST_F(SessionManagerTest, SessionNotStartedCleanup) { |
531 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); | 529 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); |
532 manager_->test_api().set_child_pid(0, kDummyPid); | 530 manager_->test_api().set_child_pid(0, kDummyPid); |
533 | 531 |
534 int timeout = 3; | 532 int timeout = 3; |
535 EXPECT_CALL(*(utils_.get()), kill(kDummyPid, getuid(), SIGKILL)) | 533 EXPECT_CALL(*(utils_.get()), kill(kDummyPid, getuid(), SIGKILL)) |
536 .WillOnce(Return(0)); | 534 .WillOnce(Return(0)); |
537 EXPECT_CALL(*(utils_.get()), ChildIsGone(kDummyPid, timeout)) | 535 EXPECT_CALL(*(utils_.get()), ChildIsGone(kDummyPid, timeout)) |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 EXPECT_CALL(*(utils_.get()), kill(kShouldNeverKillPid, getuid(), SIGTERM)) | 630 EXPECT_CALL(*(utils_.get()), kill(kShouldNeverKillPid, getuid(), SIGTERM)) |
633 .Times(0); | 631 .Times(0); |
634 EXPECT_CALL(*(utils_.get()), kill(kShouldNeverKillPid, getuid(), SIGABRT)) | 632 EXPECT_CALL(*(utils_.get()), kill(kShouldNeverKillPid, getuid(), SIGABRT)) |
635 .Times(0); | 633 .Times(0); |
636 | 634 |
637 MockUtils(); | 635 MockUtils(); |
638 manager_->test_api().CleanupChildren(kTimeout); | 636 manager_->test_api().CleanupChildren(kTimeout); |
639 } | 637 } |
640 | 638 |
641 TEST_F(SessionManagerTest, StartSession) { | 639 TEST_F(SessionManagerTest, StartSession) { |
640 MockFactory<KeyFailUtil> factory; | |
641 NssUtil::set_factory(&factory); | |
642 | |
642 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); | 643 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); |
643 | 644 |
644 gboolean out; | 645 gboolean out; |
645 gchar email[] = "user@somewhere"; | 646 gchar email[] = "user@somewhere"; |
646 gchar nothing[] = ""; | 647 gchar nothing[] = ""; |
647 MockPrefStore* store = new MockPrefStore; | 648 MockPrefStore* store = new MockPrefStore; |
648 ExpectStartSession(email, job, store); | 649 ExpectStartSession(email, job, store); |
649 manager_->test_api().set_prefstore(store); | 650 manager_->test_api().set_prefstore(store); |
650 manager_->StartSession(email, nothing, &out, NULL); | 651 manager_->StartSession(email, nothing, &out, NULL); |
651 } | 652 } |
652 | 653 |
653 TEST_F(SessionManagerTest, StartSessionNew) { | 654 TEST_F(SessionManagerTest, StartSessionNew) { |
655 MockFactory<KeyFailUtil> factory; | |
656 NssUtil::set_factory(&factory); | |
657 | |
654 gboolean out; | 658 gboolean out; |
655 gchar email[] = "user@somewhere"; | 659 gchar email[] = "user@somewhere"; |
656 gchar nothing[] = ""; | 660 gchar nothing[] = ""; |
657 MockPrefStore* store = new MockPrefStore; | 661 MockPrefStore* store = new MockPrefStore; |
658 ExpectStartSessionUnowned(email, store); | 662 ExpectStartSessionUnowned(email, store); |
659 chromeos::glib::ScopedError error; | 663 chromeos::glib::ScopedError error; |
660 EXPECT_EQ(TRUE, manager_->StartSession(email, | 664 EXPECT_EQ(TRUE, manager_->StartSession(email, |
661 nothing, | 665 nothing, |
662 &out, | 666 &out, |
663 &chromeos::Resetter(&error).lvalue())); | 667 &chromeos::Resetter(&error).lvalue())); |
(...skipping 18 matching lines...) Expand all Loading... | |
682 .Times(1); | 686 .Times(1); |
683 EXPECT_CALL(*(utils_.get()), | 687 EXPECT_CALL(*(utils_.get()), |
684 SendSignalToChromium(chromium::kWhitelistChangeCompleteSignal, | 688 SendSignalToChromium(chromium::kWhitelistChangeCompleteSignal, |
685 StrEq("success"))) | 689 StrEq("success"))) |
686 .Times(1); | 690 .Times(1); |
687 MockUtils(); | 691 MockUtils(); |
688 | 692 |
689 MockOwnerKey* key = new MockOwnerKey; | 693 MockOwnerKey* key = new MockOwnerKey; |
690 MockPrefStore* store = new MockPrefStore; | 694 MockPrefStore* store = new MockPrefStore; |
691 MockDevicePolicy* policy = new MockDevicePolicy; | 695 MockDevicePolicy* policy = new MockDevicePolicy; |
692 ExpectStartSessionForOwner(email, key, store); | 696 ExpectStartSessionForOwner(email, key, store, true); |
693 EXPECT_CALL(*policy, Persist()) | 697 EXPECT_CALL(*policy, Persist()) |
694 .WillOnce(Return(true)); | 698 .WillOnce(Return(true)); |
695 | 699 |
696 manager_->test_api().set_ownerkey(key); | 700 manager_->test_api().set_ownerkey(key); |
697 manager_->test_api().set_prefstore(store); | 701 manager_->test_api().set_prefstore(store); |
698 manager_->test_api().set_policy(policy); | 702 manager_->test_api().set_policy(policy); |
699 | 703 |
700 manager_->StartSession(email, nothing, &out, NULL); | 704 manager_->StartSession(email, nothing, &out, NULL); |
701 EXPECT_CALL(*key, PopulateFromDiskIfPossible()) | 705 EXPECT_CALL(*key, PopulateFromDiskIfPossible()) |
702 .WillOnce(Return(true)); | 706 .WillOnce(Return(true)); |
703 manager_->Run(); | 707 manager_->Run(); |
704 } | 708 } |
705 | 709 |
706 TEST_F(SessionManagerTest, StartOwnerSessionNoKeyNoRecover) { | 710 TEST_F(SessionManagerTest, StartOwnerSessionNoKeyNoRecover) { |
707 MockFactory<KeyFailUtil> factory; | 711 MockFactory<KeyFailUtil> factory; |
708 NssUtil::set_factory(&factory); | 712 NssUtil::set_factory(&factory); |
709 | 713 |
710 gboolean out; | 714 gboolean out; |
711 gchar email[] = "user@somewhere"; | 715 gchar email[] = "user@somewhere"; |
712 gchar nothing[] = ""; | 716 gchar nothing[] = ""; |
713 | 717 |
714 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); | 718 MockChildJob* job = CreateTrivialMockJob(MAYBE_NEVER); |
715 EXPECT_CALL(*(utils_.get()), | |
716 SendSignalToChromium(chromium::kPropertyChangeCompleteSignal, | |
717 StrEq("success"))) | |
718 .Times(1); | |
719 EXPECT_CALL(*(utils_.get()), | |
720 SendSignalToChromium(chromium::kWhitelistChangeCompleteSignal, | |
721 StrEq("success"))) | |
722 .Times(1); | |
723 MockUtils(); | |
724 | |
725 EXPECT_CALL(*mitigator_, Mitigate()) | 719 EXPECT_CALL(*mitigator_, Mitigate()) |
726 .WillOnce(Return(false)); | 720 .WillOnce(Return(false)); |
727 MockOwnerKey* key = new MockOwnerKey; | 721 MockOwnerKey* key = new MockOwnerKey; |
728 MockPrefStore* store = new MockPrefStore; | 722 MockPrefStore* store = new MockPrefStore; |
729 MockDevicePolicy* policy = new MockDevicePolicy; | 723 MockDevicePolicy* policy = new MockDevicePolicy; |
730 ExpectStartSessionForOwner(email, key, store); | 724 ExpectStartSessionForOwner(email, key, store, false); |
731 EXPECT_CALL(*policy, Persist()) | 725 EXPECT_CALL(*policy, Persist()) |
732 .WillOnce(Return(true)); | 726 .WillOnce(Return(true)); |
733 | 727 |
734 manager_->test_api().set_ownerkey(key); | 728 manager_->test_api().set_ownerkey(key); |
735 manager_->test_api().set_prefstore(store); | 729 manager_->test_api().set_prefstore(store); |
736 manager_->test_api().set_policy(policy); | 730 manager_->test_api().set_policy(policy); |
737 | 731 |
738 bool ret_code = manager_->StartSession(email, nothing, &out, NULL); | 732 bool ret_code = manager_->StartSession(email, nothing, &out, NULL); |
739 EXPECT_FALSE(ret_code); | 733 EXPECT_FALSE(ret_code); |
740 EXPECT_EQ(ret_code, out); | 734 EXPECT_EQ(ret_code, out); |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1428 } | 1422 } |
1429 | 1423 |
1430 TEST(SessionManagerTestStatic, GetArgLists3_InitialDashes) { | 1424 TEST(SessionManagerTestStatic, GetArgLists3_InitialDashes) { |
1431 const char* c_args[] = {"--", "a", "b", "c", NULL}; | 1425 const char* c_args[] = {"--", "a", "b", "c", NULL}; |
1432 std::vector<std::vector<std::string> > arg_lists = GetArgs(c_args); | 1426 std::vector<std::vector<std::string> > arg_lists = GetArgs(c_args); |
1433 EXPECT_EQ(1, arg_lists.size()); | 1427 EXPECT_EQ(1, arg_lists.size()); |
1434 EXPECT_EQ(3, arg_lists[0].size()); | 1428 EXPECT_EQ(3, arg_lists[0].size()); |
1435 } | 1429 } |
1436 | 1430 |
1437 } // namespace login_manager | 1431 } // namespace login_manager |
OLD | NEW |