platform_util_linux.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/common/platform_util.h"
  5. #include <stdio.h>
  6. #include "base/cancelable_callback.h"
  7. #include "base/environment.h"
  8. #include "base/files/file_util.h"
  9. #include "base/nix/xdg_util.h"
  10. #include "base/process/kill.h"
  11. #include "base/process/launch.h"
  12. #include "url/gurl.h"
  13. #define ELECTRON_TRASH "ELECTRON_TRASH"
  14. #define ELECTRON_DEFAULT_TRASH "gvfs-trash"
  15. namespace {
  16. bool XDGUtilV(const std::vector<std::string>& argv, const bool wait_for_exit) {
  17. base::LaunchOptions options;
  18. options.allow_new_privs = true;
  19. // xdg-open can fall back on mailcap which eventually might plumb through
  20. // to a command that needs a terminal. Set the environment variable telling
  21. // it that we definitely don't have a terminal available and that it should
  22. // bring up a new terminal if necessary. See "man mailcap".
  23. options.environ["MM_NOTTTY"] = "1";
  24. base::Process process = base::LaunchProcess(argv, options);
  25. if (!process.IsValid())
  26. return false;
  27. if (!wait_for_exit) {
  28. base::EnsureProcessGetsReaped(process.Pid());
  29. return true;
  30. }
  31. int exit_code = -1;
  32. if (!process.WaitForExit(&exit_code))
  33. return false;
  34. return (exit_code == 0);
  35. }
  36. bool XDGUtil(const std::string& util,
  37. const std::string& arg,
  38. const bool wait_for_exit) {
  39. std::vector<std::string> argv;
  40. argv.push_back(util);
  41. argv.push_back(arg);
  42. return XDGUtilV(argv, wait_for_exit);
  43. }
  44. bool XDGOpen(const std::string& path, const bool wait_for_exit) {
  45. return XDGUtil("xdg-open", path, wait_for_exit);
  46. }
  47. bool XDGEmail(const std::string& email, const bool wait_for_exit) {
  48. return XDGUtil("xdg-email", email, wait_for_exit);
  49. }
  50. } // namespace
  51. namespace platform_util {
  52. // TODO(estade): It would be nice to be able to select the file in the file
  53. // manager, but that probably requires extending xdg-open. For now just
  54. // show the folder.
  55. bool ShowItemInFolder(const base::FilePath& full_path) {
  56. base::FilePath dir = full_path.DirName();
  57. if (!base::DirectoryExists(dir))
  58. return false;
  59. return XDGOpen(dir.value(), false);
  60. }
  61. bool OpenItem(const base::FilePath& full_path) {
  62. return XDGOpen(full_path.value(), false);
  63. }
  64. bool OpenExternal(const GURL& url, bool activate) {
  65. // Don't wait for exit, since we don't want to wait for the browser/email
  66. // client window to close before returning
  67. if (url.SchemeIs("mailto"))
  68. return XDGEmail(url.spec(), false);
  69. else
  70. return XDGOpen(url.spec(), false);
  71. }
  72. void OpenExternal(const GURL& url,
  73. bool activate,
  74. const OpenExternalCallback& callback) {
  75. // TODO(gabriel): Implement async open if callback is specified
  76. callback.Run(OpenExternal(url, activate) ? "" : "Failed to open");
  77. }
  78. bool MoveItemToTrash(const base::FilePath& full_path) {
  79. std::string trash;
  80. if (getenv(ELECTRON_TRASH) != NULL) {
  81. trash = getenv(ELECTRON_TRASH);
  82. } else {
  83. // Determine desktop environment and set accordingly.
  84. std::unique_ptr<base::Environment> env(base::Environment::Create());
  85. base::nix::DesktopEnvironment desktop_env(
  86. base::nix::GetDesktopEnvironment(env.get()));
  87. if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4 ||
  88. desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE5) {
  89. trash = "kioclient5";
  90. } else if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE3) {
  91. trash = "kioclient";
  92. } else {
  93. trash = ELECTRON_DEFAULT_TRASH;
  94. }
  95. }
  96. std::vector<std::string> argv;
  97. if (trash.compare("kioclient5") == 0 || trash.compare("kioclient") == 0) {
  98. argv.push_back(trash);
  99. argv.push_back("move");
  100. argv.push_back(full_path.value());
  101. argv.push_back("trash:/");
  102. } else if (trash.compare("trash-cli") == 0) {
  103. argv.push_back("trash-put");
  104. argv.push_back(full_path.value());
  105. } else if (trash.compare("gio") == 0) {
  106. argv.push_back("gio");
  107. argv.push_back("trash");
  108. argv.push_back(full_path.value());
  109. } else {
  110. argv.push_back(ELECTRON_DEFAULT_TRASH);
  111. argv.push_back(full_path.value());
  112. }
  113. return XDGUtilV(argv, true);
  114. }
  115. void Beep() {
  116. // echo '\a' > /dev/console
  117. FILE* console = fopen("/dev/console", "r");
  118. if (console == NULL)
  119. return;
  120. fprintf(console, "\a");
  121. fclose(console);
  122. }
  123. } // namespace platform_util