Chromium Code Reviews| 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 |