Coverage Report

Created: 2018-09-25 14:53

/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