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 <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 18 matching lines...) Expand all Loading... | |
29 | 29 |
30 #if defined(OS_CHROMEOS) | 30 #if defined(OS_CHROMEOS) |
31 #include "base/path_service.h" | 31 #include "base/path_service.h" |
32 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 32 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
33 #include "chrome/common/chrome_constants.h" | 33 #include "chrome/common/chrome_constants.h" |
34 #include "chrome/common/chrome_paths.h" | 34 #include "chrome/common/chrome_paths.h" |
35 #include "chromeos/chromeos_switches.h" | 35 #include "chromeos/chromeos_switches.h" |
36 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
37 #endif | 37 #endif |
38 | 38 |
39 #if defined(OS_WIN) | |
40 #include <AccCtrl.h> | |
41 #include <Aclapi.h> | |
42 #include "base/callback_forward.h" | |
43 #include "base/files/file_util.h" | |
44 #include "base/path_service.h" | |
45 #include "chrome/common/chrome_paths.h" | |
46 #include "chrome/common/chrome_switches.h" | |
47 #endif | |
Peter Kasting
2016/06/04 01:24:25
Nit: There's a lot of stuff in this block and adde
WC Leung
2016/06/04 04:55:22
SGTM
| |
48 | |
39 namespace { | 49 namespace { |
40 | 50 |
41 const ProfileManager::CreateCallback kOnProfileSwitchDoNothing; | 51 const ProfileManager::CreateCallback kOnProfileSwitchDoNothing; |
42 | 52 |
43 // An observer that returns back to test code after a new profile is | 53 // An observer that returns back to test code after a new profile is |
44 // initialized. | 54 // initialized. |
45 void OnUnblockOnProfileCreation(base::RunLoop* run_loop, | 55 void OnUnblockOnProfileCreation(base::RunLoop* run_loop, |
46 Profile* profile, | 56 Profile* profile, |
47 Profile::CreateStatus status) { | 57 Profile::CreateStatus status) { |
48 if (status == Profile::CREATE_STATUS_INITIALIZED) | 58 if (status == Profile::CREATE_STATUS_INITIALIZED) |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
492 | 502 |
493 EXPECT_FALSE(profile->HasOffTheRecordProfile()); | 503 EXPECT_FALSE(profile->HasOffTheRecordProfile()); |
494 EXPECT_FALSE(profile_manager->IsValidProfile(incognito_profile)); | 504 EXPECT_FALSE(profile_manager->IsValidProfile(incognito_profile)); |
495 EXPECT_EQ(initial_profile_count, profile_manager->GetNumberOfProfiles()); | 505 EXPECT_EQ(initial_profile_count, profile_manager->GetNumberOfProfiles()); |
496 // After destroying the incognito profile incognito preferences should be | 506 // After destroying the incognito profile incognito preferences should be |
497 // cleared so the default save path should be taken from the main profile. | 507 // cleared so the default save path should be taken from the main profile. |
498 EXPECT_FALSE(profile->GetOffTheRecordPrefs() | 508 EXPECT_FALSE(profile->GetOffTheRecordPrefs() |
499 ->GetFilePath(prefs::kSaveFileDefaultDirectory) | 509 ->GetFilePath(prefs::kSaveFileDefaultDirectory) |
500 .empty()); | 510 .empty()); |
501 } | 511 } |
512 | |
513 #if defined(OS_WIN) | |
514 | |
515 bool AddAceToObjectsSecurityDescriptor(LPTSTR filename, LPTSTR trustee, | |
brettw
2016/06/03 21:47:24
I'm OK duplicating this code. It's a bit yucky but
Peter Kasting
2016/06/04 01:24:25
It looks to me as if these two are so close that j
WC Leung
2016/06/04 04:55:22
I see. Then I'll do the deduplication.
| |
516 DWORD access_rights, ACCESS_MODE access_mode, DWORD inheritance) { | |
Peter Kasting
2016/06/04 01:24:25
Nit: All lines of args must be indented the same.
WC Leung
2016/06/04 04:55:21
Acknowledged. Anyway, if that deduplication succee
| |
517 // Get a pointer to the existing DACL. | |
518 ACL* old_dacl = nullptr; | |
519 PSECURITY_DESCRIPTOR security_descriptor = nullptr; | |
520 DWORD result = GetNamedSecurityInfo(filename, SE_FILE_OBJECT, | |
521 DACL_SECURITY_INFORMATION, | |
522 nullptr, nullptr, &old_dacl, nullptr, | |
523 &security_descriptor); | |
524 if (result != ERROR_SUCCESS) { | |
525 LOG(WARNING) << "GetNamedSecurityInfo Error " << result; | |
Peter Kasting
2016/06/04 01:24:25
Are you going to collect and analyze this log data
| |
526 } else { | |
527 // Initialize an EXPLICIT_ACCESS structure for the new ACE. | |
528 EXPLICIT_ACCESS explicit_access; | |
529 ZeroMemory(&explicit_access, sizeof(EXPLICIT_ACCESS)); | |
530 explicit_access.grfAccessPermissions = access_rights; | |
531 explicit_access.grfAccessMode = access_mode; | |
532 explicit_access.grfInheritance = inheritance; | |
533 explicit_access.Trustee.TrusteeForm = TRUSTEE_IS_NAME; | |
534 explicit_access.Trustee.ptstrName = trustee; | |
Peter Kasting
2016/06/04 01:24:25
Nit: Try to use initializer values if possible, e.
| |
535 | |
536 // Create a new ACL that merges the new ACE into the existing DACL. | |
537 ACL* new_dacl = nullptr; | |
538 result = SetEntriesInAcl(1, &explicit_access, old_dacl, &new_dacl); | |
539 if (result != ERROR_SUCCESS) { | |
540 LOG(WARNING) << "SetEntriesInAcl Error " << result; | |
541 } else { | |
542 // Attach the new ACL as the object's DACL. | |
543 result = SetNamedSecurityInfo(filename, SE_FILE_OBJECT, | |
544 DACL_SECURITY_INFORMATION, | |
545 nullptr, nullptr, new_dacl, nullptr); | |
546 if (result != ERROR_SUCCESS) | |
547 LOG(WARNING) << "SetNamedSecurityInfo Error " << result; | |
548 } | |
549 | |
550 if (new_dacl) | |
Peter Kasting
2016/06/04 01:24:25
Don't conditionalize these LocalFree() calls; it s
WC Leung
2016/06/04 04:55:22
Noted and thanks. https://msdn.microsoft.com/en-us
| |
551 LocalFree((HLOCAL)new_dacl); | |
Peter Kasting
2016/06/04 01:24:25
Consider creating a scoping object that frees thes
WC Leung
2016/06/04 04:55:22
Acknowledged.
| |
552 } | |
553 | |
554 if (security_descriptor) | |
555 LocalFree((HLOCAL)security_descriptor); | |
556 | |
557 return result == ERROR_SUCCESS; | |
558 } | |
559 | |
560 bool RemoveCreateDirectoryPermission(const base::FilePath& path) { | |
561 return AddAceToObjectsSecurityDescriptor( | |
562 const_cast<wchar_t*>(path.value().c_str()), L"EVERYONE", | |
563 FILE_ADD_SUBDIRECTORY, DENY_ACCESS, NO_INHERITANCE); | |
564 } | |
565 | |
566 class ProfileManagerWinBrowserTest : public ProfileManagerBrowserTest { | |
567 public: | |
568 // Tests may be reported as PASS even if the test has never been run. To | |
Peter Kasting
2016/06/04 01:24:25
I have no idea what this is talking about :(.
WC Leung
2016/06/04 04:55:22
You've stumpled on a bug in the browser test. :-)
Peter Kasting
2016/06/04 08:01:39
Please understand this bug completely before proce
WC Leung
2016/06/04 15:48:33
Agree that the bug needs more investigation. The p
| |
569 // mitigate the issue, a "red flag" is raised for suspectable tests. These | |
Peter Kasting
2016/06/04 01:24:25
Do you mean "susceptible" or "suspicious"?
WC Leung
2016/06/04 04:55:22
Susceptble. Sorry for wrong spelling.
WC Leung
2016/06/04 17:34:43
Done.
| |
570 // tests need to call DropRedFlag() to pass the test. | |
571 void DropRedFlag() { red_flag_ = false; } | |
572 | |
573 protected: | |
574 void SetUpCommandLine(base::CommandLine* command_line) override { | |
575 command_line->AppendSwitch(switches::kRestoreLastSession); | |
576 } | |
577 | |
578 bool SetUpUserDataDirectory() override { | |
579 std::string testname( | |
580 testing::UnitTest::GetInstance()->current_test_info()->name()); | |
581 if (testname == "LastOpenedProfileMissing") { | |
brettw
2016/06/03 21:47:24
This seems potentially very confusing since people
WC Leung
2016/06/04 04:55:22
We need to do remove a profile directory and set t
| |
582 red_flag_ = true; | |
583 | |
584 base::FilePath user_data_dir; | |
585 if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) | |
586 return false; | |
587 | |
588 base::FilePath dir_to_delete = user_data_dir.AppendASCII("Profile 1"); | |
589 return base::DirectoryExists(dir_to_delete) && | |
590 DeleteFile(dir_to_delete, true) && | |
591 RemoveCreateDirectoryPermission(user_data_dir); | |
592 } | |
593 return true; | |
594 } | |
595 | |
596 void TearDown() override { | |
597 EXPECT_FALSE(red_flag_); | |
598 ProfileManagerBrowserTest::TearDown(); | |
599 } | |
600 | |
601 private: | |
602 bool red_flag_ = false; | |
603 }; | |
Peter Kasting
2016/06/04 01:24:25
Nit: DISALLOW_COPY_AND_ASSIGN
WC Leung
2016/06/04 04:55:22
Acknowledged.
WC Leung
2016/06/04 17:34:43
Unable to do this in test fixtures, because compil
Peter Kasting
2016/06/04 18:12:31
Why?
WC Leung
2016/06/05 03:04:48
Here's the compiler log:
f:\chromium\src\chrome\b
| |
604 | |
605 IN_PROC_BROWSER_TEST_F(ProfileManagerWinBrowserTest, | |
606 PRE_LastOpenedProfileMissing) { | |
Peter Kasting
2016/06/04 01:24:25
I'm not terribly familiar with using PRE_ in tests
WC Leung
2016/06/04 04:55:22
The test (PRE_ and non-PRE_ as a whole) do the fol
Peter Kasting
2016/06/04 08:01:39
That didn't really answer my question. Are you sa
WC Leung
2016/06/04 15:48:33
Oh sorry for my bad explanation. What you're sayin
| |
607 ProfileManager* profile_manager = g_browser_process->profile_manager(); | |
608 ASSERT_TRUE(profile_manager); | |
609 | |
610 std::vector<base::FilePath> profile_paths; | |
611 // Create two additional profile. | |
612 for (int i = 0; i < 2; ++i) { | |
613 base::FilePath path = profile_manager->GenerateNextProfileDirectoryPath(); | |
614 profile_paths.push_back(path); | |
615 | |
616 base::RunLoop run_loop; | |
617 profile_manager->CreateProfileAsync( | |
618 path, base::Bind(&OnUnblockOnProfileCreation, &run_loop), | |
619 base::string16(), std::string(), std::string()); | |
620 | |
621 // Run the message loop to allow profile creation to take place; the loop is | |
622 // terminated by OnUnblockOnProfileCreation when the profile is created. | |
623 run_loop.Run(); | |
624 | |
625 profiles::SwitchToProfile(path, false, kOnProfileSwitchDoNothing, | |
626 ProfileMetrics::SWITCH_PROFILE_ICON); | |
627 } | |
628 | |
629 ASSERT_EQ(base::FilePath(FILE_PATH_LITERAL("Profile 1")), | |
630 profile_paths[0].BaseName()); | |
631 } | |
632 | |
633 IN_PROC_BROWSER_TEST_F(ProfileManagerWinBrowserTest, | |
634 LastOpenedProfileMissing) { | |
635 DropRedFlag(); | |
636 | |
637 ProfileManager* profile_manager = g_browser_process->profile_manager(); | |
Peter Kasting
2016/06/04 01:24:25
Why do you need this variable?
WC Leung
2016/06/04 04:55:21
I don't need it, sorry for that. Forgot to remove
| |
638 ASSERT_TRUE(profile_manager); | |
639 | |
640 BrowserList* browser_list = BrowserList::GetInstance(); | |
641 EXPECT_EQ(2u, browser_list->size()); | |
642 for (const Browser* browser : *browser_list) { | |
643 EXPECT_NE(base::FilePath(FILE_PATH_LITERAL("Profile 1")), | |
644 browser->profile()->GetPath().BaseName()); | |
645 } | |
646 } | |
647 #endif // defined(OS_WIN) | |
Peter Kasting
2016/06/04 01:24:25
Nit: Blank line above this, or no blank below the
WC Leung
2016/06/04 04:55:22
Acknowledged.
| |
OLD | NEW |