OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/shell_integration_linux.h" | 5 #include "chrome/browser/shell_integration_linux.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 if (ran_ok && exit_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { | 157 if (ran_ok && exit_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { |
158 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { | 158 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { |
159 ran_ok = LaunchXdgUtility(argv, &exit_code); | 159 ran_ok = LaunchXdgUtility(argv, &exit_code); |
160 } | 160 } |
161 } | 161 } |
162 | 162 |
163 return ran_ok && exit_code == EXIT_SUCCESS; | 163 return ran_ok && exit_code == EXIT_SUCCESS; |
164 #endif | 164 #endif |
165 } | 165 } |
166 | 166 |
167 #if !defined(OS_CHROMEOS) | 167 // If |protocol| is empty this function checks if Chrome is the default browser, |
168 // If |check| is true, returns the output of "xdg-settings check {property} | 168 // otherwise it checks if Chrome is the default handler application for |
169 // *.desktop", otherwise returns the output of "xdg-settings get {property}", | 169 // |protocol|. |
170 // where property is "default-web-browser" if |protocol| is empty or | 170 DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) { |
171 // "default-url-scheme-handler |protocol|" otherwise. Returns "" if | 171 #if defined(OS_CHROMEOS) |
172 // xdg-settings fails for any reason. | 172 return UNKNOWN_DEFAULT; |
173 std::string GetXdgSettingsOutput(bool check, | 173 #else |
174 const std::string& protocol, | 174 base::ThreadRestrictions::AssertIOAllowed(); |
175 base::Environment* env) { | 175 |
| 176 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
| 177 |
176 std::vector<std::string> argv; | 178 std::vector<std::string> argv; |
177 argv.push_back(kXdgSettings); | 179 argv.push_back(kXdgSettings); |
178 argv.push_back(check ? "check" : "get"); | 180 argv.push_back("check"); |
179 if (protocol.empty()) { | 181 if (protocol.empty()) { |
180 argv.push_back(kXdgSettingsDefaultBrowser); | 182 argv.push_back(kXdgSettingsDefaultBrowser); |
181 } else { | 183 } else { |
182 argv.push_back(kXdgSettingsDefaultSchemeHandler); | 184 argv.push_back(kXdgSettingsDefaultSchemeHandler); |
183 argv.push_back(protocol); | 185 argv.push_back(protocol); |
184 } | 186 } |
185 if (check) | 187 argv.push_back(shell_integration_linux::GetDesktopName(env.get())); |
186 argv.push_back(shell_integration_linux::GetDesktopName(env)); | |
187 | 188 |
188 std::string reply; | 189 std::string reply; |
189 int success_code; | 190 int success_code; |
190 bool ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, | 191 bool ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, |
191 &success_code); | 192 &success_code); |
192 if (ran_ok && success_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { | 193 if (ran_ok && success_code == EXIT_XDG_SETTINGS_SYNTAX_ERROR) { |
193 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { | 194 if (GetChromeVersionOfScript(kXdgSettings, &argv[0])) { |
194 ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, | 195 ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv), &reply, |
195 &success_code); | 196 &success_code); |
196 } | 197 } |
197 } | 198 } |
198 | 199 |
199 if (!ran_ok || success_code != EXIT_SUCCESS) | 200 if (!ran_ok || success_code != EXIT_SUCCESS) { |
200 return std::string(); | 201 // xdg-settings failed: we can't determine or set the default browser. |
201 | 202 return UNKNOWN_DEFAULT; |
202 return reply; | |
203 } | |
204 #endif | |
205 | |
206 // If |protocol| is empty this function checks if Chrome is the default browser, | |
207 // otherwise it checks if Chrome is the default handler application for | |
208 // |protocol|. | |
209 DefaultWebClientState GetDefaultWebClient(const std::string& protocol) { | |
210 #if defined(OS_CHROMEOS) | |
211 return UNKNOWN_DEFAULT; | |
212 #else | |
213 base::ThreadRestrictions::AssertIOAllowed(); | |
214 | |
215 std::unique_ptr<base::Environment> env(base::Environment::Create()); | |
216 std::string xdg_is_default = GetXdgSettingsOutput(true, protocol, env.get()); | |
217 if (base::StartsWith(xdg_is_default, "yes", base::CompareCase::SENSITIVE)) { | |
218 return IS_DEFAULT; | |
219 } | |
220 if (base::StartsWith(xdg_is_default, "no", base::CompareCase::SENSITIVE)) { | |
221 // An output of "no" does not necessarily mean Chrom[e,ium] is not the | |
222 // default. According to the xdg-settings man page, this can happen when | |
223 // "only some of the underlying settings actually reflect that value". Don't | |
224 // return NOT_DEFAULT unless we're sure, or else an annoying "Chrome is not | |
225 // your default browser" banner will appear on every launch | |
226 // (https://crbug.com/578888). | |
227 if (base::StartsWith(GetXdgSettingsOutput(false, protocol, env.get()), | |
228 shell_integration_linux::GetDesktopName(env.get()), | |
229 base::CompareCase::SENSITIVE)) { | |
230 // This is the odd case where 'xdg-settings check' said that Chrome wasn't | |
231 // the default, but 'xdg-settings get' returned Chrome as the default. | |
232 return UNKNOWN_DEFAULT; | |
233 } | |
234 // xdg-settings says the default is non-Chrome, and is self-consistent. | |
235 return NOT_DEFAULT; | |
236 } | 203 } |
237 | 204 |
238 // xdg-settings failed: we can't determine or set the default browser. | 205 // Allow any reply that starts with "yes". |
239 return UNKNOWN_DEFAULT; | 206 return base::StartsWith(reply, "yes", base::CompareCase::SENSITIVE) |
| 207 ? IS_DEFAULT |
| 208 : NOT_DEFAULT; |
240 #endif | 209 #endif |
241 } | 210 } |
242 | 211 |
243 // https://wiki.gnome.org/Projects/GnomeShell/ApplicationBased | 212 // https://wiki.gnome.org/Projects/GnomeShell/ApplicationBased |
244 // The WM_CLASS property should be set to the same as the *.desktop file without | 213 // The WM_CLASS property should be set to the same as the *.desktop file without |
245 // the .desktop extension. We cannot simply use argv[0] in this case, because | 214 // the .desktop extension. We cannot simply use argv[0] in this case, because |
246 // on the stable channel, the executable name is google-chrome-stable, but the | 215 // on the stable channel, the executable name is google-chrome-stable, but the |
247 // desktop file is google-chrome.desktop. | 216 // desktop file is google-chrome.desktop. |
248 std::string GetDesktopBaseName(const std::string& desktop_file_name) { | 217 std::string GetDesktopBaseName(const std::string& desktop_file_name) { |
249 static const char kDesktopExtension[] = ".desktop"; | 218 static const char kDesktopExtension[] = ".desktop"; |
(...skipping 17 matching lines...) Expand all Loading... |
267 | 236 |
268 DefaultWebClientSetPermission GetDefaultWebClientSetPermission() { | 237 DefaultWebClientSetPermission GetDefaultWebClientSetPermission() { |
269 return SET_DEFAULT_UNATTENDED; | 238 return SET_DEFAULT_UNATTENDED; |
270 } | 239 } |
271 | 240 |
272 base::string16 GetApplicationNameForProtocol(const GURL& url) { | 241 base::string16 GetApplicationNameForProtocol(const GURL& url) { |
273 return base::ASCIIToUTF16("xdg-open"); | 242 return base::ASCIIToUTF16("xdg-open"); |
274 } | 243 } |
275 | 244 |
276 DefaultWebClientState GetDefaultBrowser() { | 245 DefaultWebClientState GetDefaultBrowser() { |
277 return GetDefaultWebClient(std::string()); | 246 return GetIsDefaultWebClient(std::string()); |
278 } | 247 } |
279 | 248 |
280 bool IsFirefoxDefaultBrowser() { | 249 bool IsFirefoxDefaultBrowser() { |
281 std::vector<std::string> argv; | 250 std::vector<std::string> argv; |
282 argv.push_back(kXdgSettings); | 251 argv.push_back(kXdgSettings); |
283 argv.push_back("get"); | 252 argv.push_back("get"); |
284 argv.push_back(kXdgSettingsDefaultBrowser); | 253 argv.push_back(kXdgSettingsDefaultBrowser); |
285 | 254 |
286 std::string browser; | 255 std::string browser; |
287 // We don't care about the return value here. | 256 // We don't care about the return value here. |
288 base::GetAppOutput(base::CommandLine(argv), &browser); | 257 base::GetAppOutput(base::CommandLine(argv), &browser); |
289 return browser.find("irefox") != std::string::npos; | 258 return browser.find("irefox") != std::string::npos; |
290 } | 259 } |
291 | 260 |
292 DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol) { | 261 DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol) { |
293 return GetDefaultWebClient(protocol); | 262 return GetIsDefaultWebClient(protocol); |
294 } | 263 } |
295 | 264 |
296 } // namespace shell_integration | 265 } // namespace shell_integration |
297 | 266 |
298 namespace shell_integration_linux { | 267 namespace shell_integration_linux { |
299 | 268 |
300 namespace { | 269 namespace { |
301 | 270 |
302 #if BUILDFLAG(ENABLE_APP_LIST) | 271 #if BUILDFLAG(ENABLE_APP_LIST) |
303 // The Categories for the App Launcher desktop shortcut. Should be the same as | 272 // The Categories for the App Launcher desktop shortcut. Should be the same as |
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1138 base::FilePath applications_menu = GetDataWriteLocation(env.get()); | 1107 base::FilePath applications_menu = GetDataWriteLocation(env.get()); |
1139 applications_menu = applications_menu.AppendASCII("applications"); | 1108 applications_menu = applications_menu.AppendASCII("applications"); |
1140 std::vector<base::FilePath> shortcut_filenames_app_menu = | 1109 std::vector<base::FilePath> shortcut_filenames_app_menu = |
1141 GetExistingProfileShortcutFilenames(profile_path, applications_menu); | 1110 GetExistingProfileShortcutFilenames(profile_path, applications_menu); |
1142 for (const auto& menu : shortcut_filenames_app_menu) { | 1111 for (const auto& menu : shortcut_filenames_app_menu) { |
1143 DeleteShortcutInApplicationsMenu(menu, base::FilePath(kDirectoryFilename)); | 1112 DeleteShortcutInApplicationsMenu(menu, base::FilePath(kDirectoryFilename)); |
1144 } | 1113 } |
1145 } | 1114 } |
1146 | 1115 |
1147 } // namespace shell_integration_linux | 1116 } // namespace shell_integration_linux |
OLD | NEW |