/src/mozilla-central/gfx/vr/openvr/src/vrpathregistry_public.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //========= Copyright Valve Corporation ============// |
2 | | |
3 | | #include "vrpathregistry_public.h" |
4 | | #include "json/json.h" |
5 | | #include "pathtools_public.h" |
6 | | #include "envvartools_public.h" |
7 | | #include "strtools_public.h" |
8 | | #include "dirtools_public.h" |
9 | | |
10 | | #if defined( WIN32 ) |
11 | | #include <windows.h> |
12 | | #include <shlobj.h> |
13 | | |
14 | | #undef GetEnvironmentVariable |
15 | | #elif defined OSX |
16 | | #include <Foundation/Foundation.h> |
17 | | #include <AppKit/AppKit.h> |
18 | | #elif defined(LINUX) |
19 | | #include <dlfcn.h> |
20 | | #include <stdio.h> |
21 | | #endif |
22 | | |
23 | | #include <algorithm> |
24 | | |
25 | | #ifndef VRLog |
26 | | #if defined( __MINGW32__ ) |
27 | | #define VRLog(args...) fprintf(stderr, args) |
28 | | #elif defined( WIN32 ) |
29 | | #define VRLog(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) |
30 | | #else |
31 | 0 | #define VRLog(args...) fprintf(stderr, args) |
32 | | #endif |
33 | | #endif |
34 | | |
35 | | /** Returns the root of the directory the system wants us to store user config data in */ |
36 | | static std::string GetAppSettingsPath() |
37 | 0 | { |
38 | | #if defined( WIN32 ) |
39 | | WCHAR rwchPath[MAX_PATH]; |
40 | | |
41 | | if( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) ) |
42 | | { |
43 | | return ""; |
44 | | } |
45 | | |
46 | | // Convert the path to UTF-8 and store in the output |
47 | | std::string sUserPath = UTF16to8( rwchPath ); |
48 | | |
49 | | return sUserPath; |
50 | | #elif defined( OSX ) |
51 | | std::string sSettingsDir; |
52 | | @autoreleasepool { |
53 | | // Search for the path |
54 | | NSArray *paths = NSSearchPathForDirectoriesInDomains( NSApplicationSupportDirectory, NSUserDomainMask, YES ); |
55 | | if ( [paths count] == 0 ) |
56 | | { |
57 | | return ""; |
58 | | } |
59 | | |
60 | | NSString *resolvedPath = [paths objectAtIndex:0]; |
61 | | resolvedPath = [resolvedPath stringByAppendingPathComponent: @"OpenVR"]; |
62 | | |
63 | | if ( ![[NSFileManager defaultManager] createDirectoryAtPath: resolvedPath withIntermediateDirectories:YES attributes:nil error:nil] ) |
64 | | { |
65 | | return ""; |
66 | | } |
67 | | |
68 | | sSettingsDir.assign( [resolvedPath UTF8String] ); |
69 | | } |
70 | | return sSettingsDir; |
71 | | #elif defined( LINUX ) |
72 | |
|
73 | 0 | // As defined by XDG Base Directory Specification |
74 | 0 | // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html |
75 | 0 |
|
76 | 0 | const char *pchHome = getenv("XDG_CONFIG_HOME"); |
77 | 0 | if ( ( pchHome != NULL) && ( pchHome[0] != '\0' ) ) |
78 | 0 | { |
79 | 0 | return pchHome; |
80 | 0 | } |
81 | 0 | |
82 | 0 | // |
83 | 0 | // XDG_CONFIG_HOME is not defined, use ~/.config instead |
84 | 0 | // |
85 | 0 | pchHome = getenv( "HOME" ); |
86 | 0 | if ( pchHome == NULL ) |
87 | 0 | { |
88 | 0 | return ""; |
89 | 0 | } |
90 | 0 | |
91 | 0 | std::string sUserPath( pchHome ); |
92 | 0 | sUserPath = Path_Join( sUserPath, ".config" ); |
93 | 0 | return sUserPath; |
94 | | #else |
95 | | #warning "Unsupported platform" |
96 | | #endif |
97 | | } |
98 | | |
99 | | |
100 | | // --------------------------------------------------------------------------- |
101 | | // Purpose: Constructor |
102 | | // --------------------------------------------------------------------------- |
103 | | CVRPathRegistry_Public::CVRPathRegistry_Public() |
104 | 0 | { |
105 | 0 |
|
106 | 0 | } |
107 | | |
108 | | // --------------------------------------------------------------------------- |
109 | | // Purpose: Computes the registry filename |
110 | | // --------------------------------------------------------------------------- |
111 | | std::string CVRPathRegistry_Public::GetOpenVRConfigPath() |
112 | 0 | { |
113 | 0 | std::string sConfigPath = GetAppSettingsPath(); |
114 | 0 | if( sConfigPath.empty() ) |
115 | 0 | return ""; |
116 | 0 | |
117 | 0 | #if defined( _WIN32 ) || defined( LINUX ) |
118 | 0 | sConfigPath = Path_Join( sConfigPath, "openvr" ); |
119 | | #elif defined ( OSX ) |
120 | | sConfigPath = Path_Join( sConfigPath, ".openvr" ); |
121 | | #else |
122 | | #warning "Unsupported platform" |
123 | | #endif |
124 | | sConfigPath = Path_FixSlashes( sConfigPath ); |
125 | 0 | return sConfigPath; |
126 | 0 | } |
127 | | |
128 | | |
129 | | |
130 | | //----------------------------------------------------------------------------- |
131 | | // Purpose: |
132 | | //----------------------------------------------------------------------------- |
133 | | std::string CVRPathRegistry_Public::GetVRPathRegistryFilename() |
134 | 0 | { |
135 | 0 | std::string sPath = GetOpenVRConfigPath(); |
136 | 0 | if ( sPath.empty() ) |
137 | 0 | return ""; |
138 | 0 | |
139 | | #if defined( _WIN32 ) |
140 | | sPath = Path_Join( sPath, "openvrpaths.vrpath" ); |
141 | | #elif defined ( POSIX ) |
142 | 0 | sPath = Path_Join( sPath, "openvrpaths.vrpath" ); |
143 | | #else |
144 | | #error "Unsupported platform" |
145 | | #endif |
146 | | sPath = Path_FixSlashes( sPath ); |
147 | 0 | return sPath; |
148 | 0 | } |
149 | | |
150 | | |
151 | | // --------------------------------------------------------------------------- |
152 | | // Purpose: Converts JSON to a history array |
153 | | // --------------------------------------------------------------------------- |
154 | | static void ParseStringListFromJson( std::vector< std::string > *pvecHistory, const Json::Value & root, const char *pchArrayName ) |
155 | 0 | { |
156 | 0 | if( !root.isMember( pchArrayName ) ) |
157 | 0 | return; |
158 | 0 | |
159 | 0 | const Json::Value & arrayNode = root[ pchArrayName ]; |
160 | 0 | if( !arrayNode ) |
161 | 0 | { |
162 | 0 | VRLog( "VR Path Registry node %s is not an array\n", pchArrayName ); |
163 | 0 | return; |
164 | 0 | } |
165 | 0 |
|
166 | 0 | pvecHistory->clear(); |
167 | 0 | pvecHistory->reserve( arrayNode.size() ); |
168 | 0 | for( uint32_t unIndex = 0; unIndex < arrayNode.size(); unIndex++ ) |
169 | 0 | { |
170 | 0 | std::string sPath( arrayNode[ unIndex ].asString() ); |
171 | 0 | pvecHistory->push_back( sPath ); |
172 | 0 | } |
173 | 0 | } |
174 | | |
175 | | |
176 | | // --------------------------------------------------------------------------- |
177 | | // Purpose: Converts a history array to JSON |
178 | | // --------------------------------------------------------------------------- |
179 | | static void StringListToJson( const std::vector< std::string > & vecHistory, Json::Value & root, const char *pchArrayName ) |
180 | 0 | { |
181 | 0 | Json::Value & arrayNode = root[ pchArrayName ]; |
182 | 0 | for( auto i = vecHistory.begin(); i != vecHistory.end(); i++ ) |
183 | 0 | { |
184 | 0 | arrayNode.append( *i ); |
185 | 0 | } |
186 | 0 | } |
187 | | |
188 | | |
189 | | //----------------------------------------------------------------------------- |
190 | | // Purpose: |
191 | | //----------------------------------------------------------------------------- |
192 | | bool CVRPathRegistry_Public::ToJsonString( std::string &sJsonString ) |
193 | 0 | { |
194 | 0 | std::string sRegPath = GetVRPathRegistryFilename(); |
195 | 0 | if( sRegPath.empty() ) |
196 | 0 | return false; |
197 | 0 | |
198 | 0 | std::string sRegistryContents = Path_ReadTextFile( sRegPath ); |
199 | 0 | if( sRegistryContents.empty() ) |
200 | 0 | return false; |
201 | 0 | |
202 | 0 | sJsonString = sRegistryContents; |
203 | 0 |
|
204 | 0 | return true; |
205 | 0 | } |
206 | | |
207 | | |
208 | | // --------------------------------------------------------------------------- |
209 | | // Purpose: Loads the config file from its well known location |
210 | | // --------------------------------------------------------------------------- |
211 | | bool CVRPathRegistry_Public::BLoadFromFile() |
212 | 0 | { |
213 | 0 | std::string sRegPath = GetVRPathRegistryFilename(); |
214 | 0 | if( sRegPath.empty() ) |
215 | 0 | { |
216 | 0 | VRLog( "Unable to determine VR Path Registry filename\n" ); |
217 | 0 | return false; |
218 | 0 | } |
219 | 0 |
|
220 | 0 | std::string sRegistryContents = Path_ReadTextFile( sRegPath ); |
221 | 0 | if( sRegistryContents.empty() ) |
222 | 0 | { |
223 | 0 | VRLog( "Unable to read VR Path Registry from %s\n", sRegPath.c_str() ); |
224 | 0 | return false; |
225 | 0 | } |
226 | 0 |
|
227 | 0 | Json::Value root; |
228 | 0 | Json::Reader reader; |
229 | 0 |
|
230 | 0 | if( !reader.parse( sRegistryContents, root ) ) |
231 | 0 | { |
232 | 0 | VRLog( "Unable to parse %s: %s\n", sRegPath.c_str(), reader.getFormattedErrorMessages().c_str() ); |
233 | 0 | return false; |
234 | 0 | } |
235 | 0 |
|
236 | 0 | ParseStringListFromJson( &m_vecRuntimePath, root, "runtime" ); |
237 | 0 | ParseStringListFromJson( &m_vecConfigPath, root, "config" ); |
238 | 0 | ParseStringListFromJson( &m_vecLogPath, root, "log" ); |
239 | 0 | if (root.isMember( "external_drivers" ) && root[ "external_drivers" ].isArray() ) |
240 | 0 | { |
241 | 0 | ParseStringListFromJson( &m_vecExternalDrivers, root, "external_drivers" ); |
242 | 0 | } |
243 | 0 |
|
244 | 0 | return true; |
245 | 0 | } |
246 | | |
247 | | |
248 | | // --------------------------------------------------------------------------- |
249 | | // Purpose: Saves the config file to its well known location |
250 | | // --------------------------------------------------------------------------- |
251 | | bool CVRPathRegistry_Public::BSaveToFile() const |
252 | 0 | { |
253 | | #if defined( DASHBOARD_BUILD_MODE ) |
254 | | return false; |
255 | | #else |
256 | | std::string sRegPath = GetVRPathRegistryFilename(); |
257 | 0 | if( sRegPath.empty() ) |
258 | 0 | return false; |
259 | 0 | |
260 | 0 | Json::Value root; |
261 | 0 | |
262 | 0 | root[ "version" ] = 1; |
263 | 0 | root[ "jsonid" ] = "vrpathreg"; |
264 | 0 |
|
265 | 0 | StringListToJson( m_vecRuntimePath, root, "runtime" ); |
266 | 0 | StringListToJson( m_vecConfigPath, root, "config" ); |
267 | 0 | StringListToJson( m_vecLogPath, root, "log" ); |
268 | 0 | StringListToJson( m_vecExternalDrivers, root, "external_drivers" ); |
269 | 0 |
|
270 | 0 | Json::StyledWriter writer; |
271 | 0 | std::string sRegistryContents = writer.write( root ); |
272 | 0 |
|
273 | 0 | // make sure the directory we're writing into actually exists |
274 | 0 | std::string sRegDirectory = Path_StripFilename( sRegPath ); |
275 | 0 | if( !BCreateDirectoryRecursive( sRegDirectory.c_str() ) ) |
276 | 0 | { |
277 | 0 | VRLog( "Unable to create path registry directory %s\n", sRegDirectory.c_str() ); |
278 | 0 | return false; |
279 | 0 | } |
280 | 0 |
|
281 | 0 | if( !Path_WriteStringToTextFile( sRegPath, sRegistryContents.c_str() ) ) |
282 | 0 | { |
283 | 0 | VRLog( "Unable to write VR path registry to %s\n", sRegPath.c_str() ); |
284 | 0 | return false; |
285 | 0 | } |
286 | 0 |
|
287 | 0 | return true; |
288 | 0 | #endif |
289 | 0 | } |
290 | | |
291 | | |
292 | | // --------------------------------------------------------------------------- |
293 | | // Purpose: Returns the current runtime path or NULL if no path is configured. |
294 | | // --------------------------------------------------------------------------- |
295 | | std::string CVRPathRegistry_Public::GetRuntimePath() const |
296 | 0 | { |
297 | 0 | if( m_vecRuntimePath.empty() ) |
298 | 0 | return ""; |
299 | 0 | else |
300 | 0 | return m_vecRuntimePath.front().c_str(); |
301 | 0 | } |
302 | | |
303 | | |
304 | | // --------------------------------------------------------------------------- |
305 | | // Purpose: Returns the current config path or NULL if no path is configured. |
306 | | // --------------------------------------------------------------------------- |
307 | | std::string CVRPathRegistry_Public::GetConfigPath() const |
308 | 0 | { |
309 | 0 | if( m_vecConfigPath.empty() ) |
310 | 0 | return ""; |
311 | 0 | else |
312 | 0 | return m_vecConfigPath.front().c_str(); |
313 | 0 | } |
314 | | |
315 | | |
316 | | // --------------------------------------------------------------------------- |
317 | | // Purpose: Returns the current log path or NULL if no path is configured. |
318 | | // --------------------------------------------------------------------------- |
319 | | std::string CVRPathRegistry_Public::GetLogPath() const |
320 | 0 | { |
321 | 0 | if( m_vecLogPath.empty() ) |
322 | 0 | return ""; |
323 | 0 | else |
324 | 0 | return m_vecLogPath.front().c_str(); |
325 | 0 | } |
326 | | |
327 | | |
328 | | |
329 | | // --------------------------------------------------------------------------- |
330 | | // Purpose: Returns paths using the path registry and the provided override |
331 | | // values. Pass NULL for any paths you don't care about. |
332 | | // --------------------------------------------------------------------------- |
333 | | bool CVRPathRegistry_Public::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers ) |
334 | 0 | { |
335 | 0 | CVRPathRegistry_Public pathReg; |
336 | 0 | bool bLoadedRegistry = pathReg.BLoadFromFile(); |
337 | 0 | int nCountEnvironmentVariables = 0; |
338 | 0 |
|
339 | 0 | if( psRuntimePath ) |
340 | 0 | { |
341 | 0 | if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 ) |
342 | 0 | { |
343 | 0 | *psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar ); |
344 | 0 | nCountEnvironmentVariables++; |
345 | 0 | } |
346 | 0 | else if( !pathReg.GetRuntimePath().empty() ) |
347 | 0 | { |
348 | 0 | *psRuntimePath = pathReg.GetRuntimePath(); |
349 | 0 | } |
350 | 0 | else |
351 | 0 | { |
352 | 0 | *psRuntimePath = ""; |
353 | 0 | } |
354 | 0 | } |
355 | 0 |
|
356 | 0 | if( psConfigPath ) |
357 | 0 | { |
358 | 0 | if ( GetEnvironmentVariable( k_pchConfigOverrideVar ).length() != 0 ) |
359 | 0 | { |
360 | 0 | *psConfigPath = GetEnvironmentVariable( k_pchConfigOverrideVar ); |
361 | 0 | nCountEnvironmentVariables++; |
362 | 0 | } |
363 | 0 | else if( pchConfigPathOverride ) |
364 | 0 | { |
365 | 0 | *psConfigPath = pchConfigPathOverride; |
366 | 0 | } |
367 | 0 | else if( !pathReg.GetConfigPath().empty() ) |
368 | 0 | { |
369 | 0 | *psConfigPath = pathReg.GetConfigPath(); |
370 | 0 | } |
371 | 0 | else |
372 | 0 | { |
373 | 0 | *psConfigPath = ""; |
374 | 0 | } |
375 | 0 | } |
376 | 0 |
|
377 | 0 | if( psLogPath ) |
378 | 0 | { |
379 | 0 | if ( GetEnvironmentVariable( k_pchLogOverrideVar ).length() != 0 ) |
380 | 0 | { |
381 | 0 | *psLogPath = GetEnvironmentVariable( k_pchLogOverrideVar ); |
382 | 0 | nCountEnvironmentVariables++; |
383 | 0 | } |
384 | 0 | else if( pchLogPathOverride ) |
385 | 0 | { |
386 | 0 | *psLogPath = pchLogPathOverride; |
387 | 0 | } |
388 | 0 | else if( !pathReg.GetLogPath().empty() ) |
389 | 0 | { |
390 | 0 | *psLogPath = pathReg.GetLogPath(); |
391 | 0 | } |
392 | 0 | else |
393 | 0 | { |
394 | 0 | *psLogPath = ""; |
395 | 0 | } |
396 | 0 | } |
397 | 0 |
|
398 | 0 | if ( pvecExternalDrivers ) |
399 | 0 | { |
400 | 0 | *pvecExternalDrivers = pathReg.m_vecExternalDrivers; |
401 | 0 | } |
402 | 0 |
|
403 | 0 | if ( nCountEnvironmentVariables == 3 ) |
404 | 0 | { |
405 | 0 | // all three environment variables where set, so we don't need the physical file |
406 | 0 | return true; |
407 | 0 | } |
408 | 0 | |
409 | 0 | return bLoadedRegistry; |
410 | 0 | } |
411 | | |