Index: chrome/browser/profiles/profile_manager_browsertest.cc |
diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc |
index 06f06dc2d8fa4b9e2843c2751ce1d1f706ab6001..d7d160d1b8fff85897353e3f7f62a19cd7e48ede 100644 |
--- a/chrome/browser/profiles/profile_manager_browsertest.cc |
+++ b/chrome/browser/profiles/profile_manager_browsertest.cc |
@@ -36,6 +36,16 @@ |
#include "testing/gtest/include/gtest/gtest.h" |
#endif |
+#if defined(OS_WIN) |
+#include <AccCtrl.h> |
+#include <Aclapi.h> |
+#include "base/callback_forward.h" |
+#include "base/files/file_util.h" |
+#include "base/path_service.h" |
+#include "chrome/common/chrome_paths.h" |
+#include "chrome/common/chrome_switches.h" |
+#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
|
+ |
namespace { |
const ProfileManager::CreateCallback kOnProfileSwitchDoNothing; |
@@ -499,3 +509,139 @@ IN_PROC_BROWSER_TEST_F(ProfileManagerBrowserTest, IncognitoProfile) { |
->GetFilePath(prefs::kSaveFileDefaultDirectory) |
.empty()); |
} |
+ |
+#if defined(OS_WIN) |
+ |
+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.
|
+ 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
|
+ // Get a pointer to the existing DACL. |
+ ACL* old_dacl = nullptr; |
+ PSECURITY_DESCRIPTOR security_descriptor = nullptr; |
+ DWORD result = GetNamedSecurityInfo(filename, SE_FILE_OBJECT, |
+ DACL_SECURITY_INFORMATION, |
+ nullptr, nullptr, &old_dacl, nullptr, |
+ &security_descriptor); |
+ if (result != ERROR_SUCCESS) { |
+ LOG(WARNING) << "GetNamedSecurityInfo Error " << result; |
Peter Kasting
2016/06/04 01:24:25
Are you going to collect and analyze this log data
|
+ } else { |
+ // Initialize an EXPLICIT_ACCESS structure for the new ACE. |
+ EXPLICIT_ACCESS explicit_access; |
+ ZeroMemory(&explicit_access, sizeof(EXPLICIT_ACCESS)); |
+ explicit_access.grfAccessPermissions = access_rights; |
+ explicit_access.grfAccessMode = access_mode; |
+ explicit_access.grfInheritance = inheritance; |
+ explicit_access.Trustee.TrusteeForm = TRUSTEE_IS_NAME; |
+ explicit_access.Trustee.ptstrName = trustee; |
Peter Kasting
2016/06/04 01:24:25
Nit: Try to use initializer values if possible, e.
|
+ |
+ // Create a new ACL that merges the new ACE into the existing DACL. |
+ ACL* new_dacl = nullptr; |
+ result = SetEntriesInAcl(1, &explicit_access, old_dacl, &new_dacl); |
+ if (result != ERROR_SUCCESS) { |
+ LOG(WARNING) << "SetEntriesInAcl Error " << result; |
+ } else { |
+ // Attach the new ACL as the object's DACL. |
+ result = SetNamedSecurityInfo(filename, SE_FILE_OBJECT, |
+ DACL_SECURITY_INFORMATION, |
+ nullptr, nullptr, new_dacl, nullptr); |
+ if (result != ERROR_SUCCESS) |
+ LOG(WARNING) << "SetNamedSecurityInfo Error " << result; |
+ } |
+ |
+ 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
|
+ 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.
|
+ } |
+ |
+ if (security_descriptor) |
+ LocalFree((HLOCAL)security_descriptor); |
+ |
+ return result == ERROR_SUCCESS; |
+} |
+ |
+bool RemoveCreateDirectoryPermission(const base::FilePath& path) { |
+ return AddAceToObjectsSecurityDescriptor( |
+ const_cast<wchar_t*>(path.value().c_str()), L"EVERYONE", |
+ FILE_ADD_SUBDIRECTORY, DENY_ACCESS, NO_INHERITANCE); |
+} |
+ |
+class ProfileManagerWinBrowserTest : public ProfileManagerBrowserTest { |
+ public: |
+ // 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
|
+ // 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.
|
+ // tests need to call DropRedFlag() to pass the test. |
+ void DropRedFlag() { red_flag_ = false; } |
+ |
+ protected: |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ command_line->AppendSwitch(switches::kRestoreLastSession); |
+ } |
+ |
+ bool SetUpUserDataDirectory() override { |
+ std::string testname( |
+ testing::UnitTest::GetInstance()->current_test_info()->name()); |
+ 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
|
+ red_flag_ = true; |
+ |
+ base::FilePath user_data_dir; |
+ if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) |
+ return false; |
+ |
+ base::FilePath dir_to_delete = user_data_dir.AppendASCII("Profile 1"); |
+ return base::DirectoryExists(dir_to_delete) && |
+ DeleteFile(dir_to_delete, true) && |
+ RemoveCreateDirectoryPermission(user_data_dir); |
+ } |
+ return true; |
+ } |
+ |
+ void TearDown() override { |
+ EXPECT_FALSE(red_flag_); |
+ ProfileManagerBrowserTest::TearDown(); |
+ } |
+ |
+ private: |
+ bool red_flag_ = false; |
+}; |
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
|
+ |
+IN_PROC_BROWSER_TEST_F(ProfileManagerWinBrowserTest, |
+ 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
|
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
+ ASSERT_TRUE(profile_manager); |
+ |
+ std::vector<base::FilePath> profile_paths; |
+ // Create two additional profile. |
+ for (int i = 0; i < 2; ++i) { |
+ base::FilePath path = profile_manager->GenerateNextProfileDirectoryPath(); |
+ profile_paths.push_back(path); |
+ |
+ base::RunLoop run_loop; |
+ profile_manager->CreateProfileAsync( |
+ path, base::Bind(&OnUnblockOnProfileCreation, &run_loop), |
+ base::string16(), std::string(), std::string()); |
+ |
+ // Run the message loop to allow profile creation to take place; the loop is |
+ // terminated by OnUnblockOnProfileCreation when the profile is created. |
+ run_loop.Run(); |
+ |
+ profiles::SwitchToProfile(path, false, kOnProfileSwitchDoNothing, |
+ ProfileMetrics::SWITCH_PROFILE_ICON); |
+ } |
+ |
+ ASSERT_EQ(base::FilePath(FILE_PATH_LITERAL("Profile 1")), |
+ profile_paths[0].BaseName()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(ProfileManagerWinBrowserTest, |
+ LastOpenedProfileMissing) { |
+ DropRedFlag(); |
+ |
+ 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
|
+ ASSERT_TRUE(profile_manager); |
+ |
+ BrowserList* browser_list = BrowserList::GetInstance(); |
+ EXPECT_EQ(2u, browser_list->size()); |
+ for (const Browser* browser : *browser_list) { |
+ EXPECT_NE(base::FilePath(FILE_PATH_LITERAL("Profile 1")), |
+ browser->profile()->GetPath().BaseName()); |
+ } |
+} |
+#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.
|