OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/install_static/user_data_dir.h" | |
6 | |
7 #include <windows.h> | |
8 #include <assert.h> | |
9 | |
10 #include "chrome/install_static/install_details.h" | |
11 #include "chrome/install_static/install_util.h" | |
12 #include "chrome/install_static/policy_path_parser.h" | |
13 #include "chrome_elf/nt_registry/nt_registry.h" | |
14 | |
15 namespace install_static { | |
16 | |
17 namespace { | |
18 | |
19 std::wstring g_user_data_dir; | |
grt (UTC plus 2)
2016/11/22 21:06:58
this will introduce a global dtor, which is banned
scottmg
2016/11/22 21:59:57
Done.
[That rule is pretty lax on Windows tbh, th
| |
20 std::wstring g_invalid_user_data_dir; | |
21 | |
22 // Retrieves a registry policy for the user data directory from the registry, if | |
23 // one is set. If there's none set in either HKLM or HKCU, |user_data_dir| will | |
24 // be unmodified. | |
25 void GetUserDataDirFromRegistryPolicyIfSet(const InstallConstants& mode, | |
26 std::wstring* user_data_dir) { | |
27 assert(user_data_dir); | |
28 std::wstring policies_path = L"SOFTWARE\\Policies\\"; | |
29 AppendChromeInstallSubDirectory(mode, false /* !include_suffix */, | |
30 &policies_path); | |
31 | |
32 std::wstring value; | |
33 | |
34 constexpr wchar_t kUserDataDirRegistryKeyName[] = L"UserDataDir"; | |
35 | |
36 // First, try HKLM. | |
37 if (nt::QueryRegValueSZ(nt::HKLM, nt::NONE, policies_path.c_str(), | |
38 kUserDataDirRegistryKeyName, &value)) { | |
39 *user_data_dir = ExpandPathVariables(value); | |
40 return; | |
41 } | |
42 | |
43 // Second, try HKCU. | |
44 if (nt::QueryRegValueSZ(nt::HKCU, nt::NONE, policies_path.c_str(), | |
45 kUserDataDirRegistryKeyName, &value)) { | |
46 *user_data_dir = ExpandPathVariables(value); | |
47 return; | |
48 } | |
49 } | |
50 | |
51 std::wstring MakeAbsoluteFilePath(const std::wstring& input) { | |
52 wchar_t file_path[MAX_PATH]; | |
53 if (!_wfullpath(file_path, input.c_str(), _countof(file_path))) | |
54 return std::wstring(); | |
55 return file_path; | |
56 } | |
57 | |
58 // The same as GetUserDataDirectory(), but directly queries the global command | |
59 // line object for the --user-data-dir flag. This is the more commonly used | |
60 // function, where GetUserDataDirectory() is used primiarily for testing. | |
61 bool GetUserDataDirectoryUsingProcessCommandLine( | |
62 const InstallConstants& mode, | |
63 std::wstring* result, | |
64 std::wstring* invalid_supplied_directory) { | |
65 return GetUserDataDirectoryImpl( | |
66 GetSwitchValueFromCommandLine(::GetCommandLine(), kUserDataDirSwitch), | |
67 mode, result, invalid_supplied_directory); | |
68 } | |
69 | |
70 // Populates |result| with the default User Data directory for the current | |
71 // user. Returns false if all attempts at locating a User Data directory fail. | |
72 // TODO(ananta) | |
73 // http://crbug.com/604923 | |
74 // Unify this with the Browser Distribution code. | |
75 bool GetDefaultUserDataDirectory(const InstallConstants& mode, | |
76 std::wstring* result) { | |
77 // This environment variable should be set on Windows Vista and later | |
78 // (https://msdn.microsoft.com/library/windows/desktop/dd378457.aspx). | |
79 std::wstring user_data_dir = GetEnvironmentString16(L"LOCALAPPDATA"); | |
80 | |
81 if (user_data_dir.empty()) { | |
82 // LOCALAPPDATA was not set; fallback to the temporary files path. | |
83 DWORD size = ::GetTempPath(0, nullptr); | |
84 if (!size) | |
85 return false; | |
86 user_data_dir.resize(size + 1); | |
87 size = ::GetTempPath(size + 1, &user_data_dir[0]); | |
88 if (!size || size >= user_data_dir.size()) | |
89 return false; | |
90 user_data_dir.resize(size); | |
91 } | |
92 | |
93 result->swap(user_data_dir); | |
94 if ((*result)[result->length() - 1] != L'\\') | |
95 result->push_back(L'\\'); | |
96 AppendChromeInstallSubDirectory(mode, true /* include_suffix */, result); | |
97 result->push_back(L'\\'); | |
98 result->append(L"User Data"); | |
99 return true; | |
100 } | |
101 | |
102 } // namespace | |
103 | |
104 bool GetUserDataDirectoryImpl( | |
105 const std::wstring& user_data_dir_from_command_line, | |
106 const InstallConstants& mode, | |
107 std::wstring* result, | |
108 std::wstring* invalid_supplied_directory) { | |
109 std::wstring user_data_dir = user_data_dir_from_command_line; | |
110 | |
111 GetUserDataDirFromRegistryPolicyIfSet(mode, &user_data_dir); | |
112 | |
113 // On Windows, trailing separators leave Chrome in a bad state. See | |
114 // crbug.com/464616. | |
115 while (!user_data_dir.empty() && | |
116 (user_data_dir.back() == '\\' || user_data_dir.back() == '/')) { | |
117 user_data_dir.pop_back(); | |
118 } | |
119 | |
120 bool got_valid_directory = | |
121 !user_data_dir.empty() && RecursiveDirectoryCreate(user_data_dir); | |
122 if (!got_valid_directory) { | |
123 *invalid_supplied_directory = user_data_dir; | |
124 got_valid_directory = GetDefaultUserDataDirectory(mode, &user_data_dir); | |
125 } | |
126 | |
127 // The Chrome implementation CHECKs() here in the browser process. We | |
128 // don't as this function is used to initialize crash reporting, so | |
129 // we would get no report of this failure. | |
130 assert(got_valid_directory); | |
131 if (!got_valid_directory) | |
132 return false; | |
133 | |
134 *result = MakeAbsoluteFilePath(user_data_dir); | |
135 return true; | |
136 } | |
137 | |
138 bool GetUserDataDirectory(std::wstring* user_data_dir, | |
139 std::wstring* invalid_user_data_dir) { | |
140 if (g_user_data_dir.empty()) { | |
141 if (!GetUserDataDirectoryUsingProcessCommandLine( | |
142 *InstallDetails::Get().mode(), &g_user_data_dir, | |
143 &g_invalid_user_data_dir)) { | |
144 return false; | |
145 } | |
146 assert(!g_user_data_dir.empty()); | |
147 } | |
148 *user_data_dir = g_user_data_dir; | |
149 if (invalid_user_data_dir) | |
150 *invalid_user_data_dir = g_invalid_user_data_dir; | |
151 return true; | |
152 } | |
153 | |
154 } // namespace install_static | |
OLD | NEW |