• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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 "base/nix/xdg_util.h"
6 
7 #include <string>
8 
9 #include "base/base_paths.h"
10 #include "base/environment.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/logging.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_tokenizer.h"
17 #include "base/strings/string_util.h"
18 #include "base/third_party/xdg_user_dirs/xdg_user_dir_lookup.h"
19 #include "base/threading/scoped_blocking_call.h"
20 
21 namespace {
22 
23 // The KDE session version environment variable introduced in KDE 4.
24 const char kKDESessionEnvVar[] = "KDE_SESSION_VERSION";
25 
26 }  // namespace
27 
28 namespace base {
29 namespace nix {
30 
31 const char kDotConfigDir[] = ".config";
32 const char kXdgConfigHomeEnvVar[] = "XDG_CONFIG_HOME";
33 const char kXdgCurrentDesktopEnvVar[] = "XDG_CURRENT_DESKTOP";
34 const char kXdgSessionTypeEnvVar[] = "XDG_SESSION_TYPE";
35 
GetXDGDirectory(Environment * env,const char * env_name,const char * fallback_dir)36 FilePath GetXDGDirectory(Environment* env, const char* env_name,
37                          const char* fallback_dir) {
38   FilePath path;
39   std::string env_value;
40   if (env->GetVar(env_name, &env_value) && !env_value.empty()) {
41     path = FilePath(env_value);
42   } else {
43     PathService::Get(DIR_HOME, &path);
44     path = path.Append(fallback_dir);
45   }
46   return path.StripTrailingSeparators();
47 }
48 
GetXDGUserDirectory(const char * dir_name,const char * fallback_dir)49 FilePath GetXDGUserDirectory(const char* dir_name, const char* fallback_dir) {
50   FilePath path;
51   char* xdg_dir = xdg_user_dir_lookup(dir_name);
52   if (xdg_dir) {
53     path = FilePath(xdg_dir);
54     free(xdg_dir);
55   } else {
56     PathService::Get(DIR_HOME, &path);
57     path = path.Append(fallback_dir);
58   }
59   return path.StripTrailingSeparators();
60 }
61 
GetXDGDataWriteLocation(Environment * env)62 FilePath GetXDGDataWriteLocation(Environment* env) {
63   return GetXDGDirectory(env, "XDG_DATA_HOME", ".local/share");
64 }
65 
GetXDGDataSearchLocations(Environment * env)66 std::vector<FilePath> GetXDGDataSearchLocations(Environment* env) {
67   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
68 
69   std::vector<FilePath> search_paths;
70   search_paths.push_back(GetXDGDataWriteLocation(env));
71 
72   std::string xdg_data_dirs;
73   if (env->GetVar("XDG_DATA_DIRS", &xdg_data_dirs) && !xdg_data_dirs.empty()) {
74     StringTokenizer tokenizer(xdg_data_dirs, ":");
75     while (tokenizer.GetNext()) {
76       search_paths.emplace_back(tokenizer.token_piece());
77     }
78   } else {
79     search_paths.emplace_back("/usr/local/share");
80     search_paths.emplace_back("/usr/share");
81   }
82 
83   return search_paths;
84 }
85 
GetDesktopEnvironment(Environment * env)86 DesktopEnvironment GetDesktopEnvironment(Environment* env) {
87   // kXdgCurrentDesktopEnvVar is the newest standard circa 2012.
88   std::string xdg_current_desktop;
89   if (env->GetVar(kXdgCurrentDesktopEnvVar, &xdg_current_desktop)) {
90     // It could have multiple values separated by colon in priority order.
91     for (const auto& value : SplitStringPiece(
92              xdg_current_desktop, ":", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY)) {
93       if (value == "Unity") {
94         // gnome-fallback sessions set kXdgCurrentDesktopEnvVar to Unity
95         // DESKTOP_SESSION can be gnome-fallback or gnome-fallback-compiz
96         std::string desktop_session;
97         if (env->GetVar("DESKTOP_SESSION", &desktop_session) &&
98             desktop_session.find("gnome-fallback") != std::string::npos) {
99           return DESKTOP_ENVIRONMENT_GNOME;
100         }
101         return DESKTOP_ENVIRONMENT_UNITY;
102       }
103       if (value == "Deepin")
104         return DESKTOP_ENVIRONMENT_DEEPIN;
105       if (value == "GNOME")
106         return DESKTOP_ENVIRONMENT_GNOME;
107       if (value == "X-Cinnamon")
108         return DESKTOP_ENVIRONMENT_CINNAMON;
109       if (value == "KDE") {
110         std::string kde_session;
111         if (env->GetVar(kKDESessionEnvVar, &kde_session)) {
112           if (kde_session == "5") {
113             return DESKTOP_ENVIRONMENT_KDE5;
114           }
115           if (kde_session == "6") {
116             return DESKTOP_ENVIRONMENT_KDE6;
117           }
118         }
119         return DESKTOP_ENVIRONMENT_KDE4;
120       }
121       if (value == "Pantheon")
122         return DESKTOP_ENVIRONMENT_PANTHEON;
123       if (value == "XFCE")
124         return DESKTOP_ENVIRONMENT_XFCE;
125       if (value == "UKUI")
126         return DESKTOP_ENVIRONMENT_UKUI;
127       if (value == "LXQt")
128         return DESKTOP_ENVIRONMENT_LXQT;
129     }
130   }
131 
132   // DESKTOP_SESSION was what everyone used in 2010.
133   std::string desktop_session;
134   if (env->GetVar("DESKTOP_SESSION", &desktop_session)) {
135     if (desktop_session == "deepin")
136       return DESKTOP_ENVIRONMENT_DEEPIN;
137     if (desktop_session == "gnome" || desktop_session == "mate")
138       return DESKTOP_ENVIRONMENT_GNOME;
139     if (desktop_session == "kde4" || desktop_session == "kde-plasma")
140       return DESKTOP_ENVIRONMENT_KDE4;
141     if (desktop_session == "kde") {
142       // This may mean KDE4 on newer systems, so we have to check.
143       if (env->HasVar(kKDESessionEnvVar))
144         return DESKTOP_ENVIRONMENT_KDE4;
145       return DESKTOP_ENVIRONMENT_KDE3;
146     }
147     if (desktop_session.find("xfce") != std::string::npos ||
148         desktop_session == "xubuntu") {
149       return DESKTOP_ENVIRONMENT_XFCE;
150     }
151     if (desktop_session == "ukui")
152       return DESKTOP_ENVIRONMENT_UKUI;
153   }
154 
155   // Fall back on some older environment variables.
156   // Useful particularly in the DESKTOP_SESSION=default case.
157   if (env->HasVar("GNOME_DESKTOP_SESSION_ID"))
158     return DESKTOP_ENVIRONMENT_GNOME;
159   if (env->HasVar("KDE_FULL_SESSION")) {
160     if (env->HasVar(kKDESessionEnvVar))
161       return DESKTOP_ENVIRONMENT_KDE4;
162     return DESKTOP_ENVIRONMENT_KDE3;
163   }
164 
165   return DESKTOP_ENVIRONMENT_OTHER;
166 }
167 
GetDesktopEnvironmentName(DesktopEnvironment env)168 const char* GetDesktopEnvironmentName(DesktopEnvironment env) {
169   switch (env) {
170     case DESKTOP_ENVIRONMENT_OTHER:
171       return nullptr;
172     case DESKTOP_ENVIRONMENT_CINNAMON:
173       return "CINNAMON";
174     case DESKTOP_ENVIRONMENT_DEEPIN:
175       return "DEEPIN";
176     case DESKTOP_ENVIRONMENT_GNOME:
177       return "GNOME";
178     case DESKTOP_ENVIRONMENT_KDE3:
179       return "KDE3";
180     case DESKTOP_ENVIRONMENT_KDE4:
181       return "KDE4";
182     case DESKTOP_ENVIRONMENT_KDE5:
183       return "KDE5";
184     case DESKTOP_ENVIRONMENT_KDE6:
185       return "KDE6";
186     case DESKTOP_ENVIRONMENT_PANTHEON:
187       return "PANTHEON";
188     case DESKTOP_ENVIRONMENT_UNITY:
189       return "UNITY";
190     case DESKTOP_ENVIRONMENT_XFCE:
191       return "XFCE";
192     case DESKTOP_ENVIRONMENT_UKUI:
193       return "UKUI";
194     case DESKTOP_ENVIRONMENT_LXQT:
195       return "LXQT";
196   }
197   return nullptr;
198 }
199 
GetDesktopEnvironmentName(Environment * env)200 const char* GetDesktopEnvironmentName(Environment* env) {
201   return GetDesktopEnvironmentName(GetDesktopEnvironment(env));
202 }
203 
GetSessionType(Environment & env)204 SessionType GetSessionType(Environment& env) {
205   std::string xdg_session_type;
206   if (!env.GetVar(kXdgSessionTypeEnvVar, &xdg_session_type))
207     return SessionType::kUnset;
208 
209   TrimWhitespaceASCII(ToLowerASCII(xdg_session_type), TrimPositions::TRIM_ALL,
210                       &xdg_session_type);
211 
212   if (xdg_session_type == "wayland")
213     return SessionType::kWayland;
214 
215   if (xdg_session_type == "x11")
216     return SessionType::kX11;
217 
218   if (xdg_session_type == "tty")
219     return SessionType::kTty;
220 
221   if (xdg_session_type == "mir")
222     return SessionType::kMir;
223 
224   if (xdg_session_type == "unspecified")
225     return SessionType::kUnspecified;
226 
227   LOG(ERROR) << "Unknown XDG_SESSION_TYPE: " << xdg_session_type;
228   return SessionType::kOther;
229 }
230 
231 }  // namespace nix
232 }  // namespace base
233