shell: return status for moveItemToTrash on all platforms
authorRobo <hop2deep@gmail.com>
Fri, 27 Mar 2015 13:01:57 +0000 (18:31 +0530)
committerRobo <hop2deep@gmail.com>
Sat, 28 Mar 2015 19:17:50 +0000 (00:47 +0530)
atom/common/platform_util.h
atom/common/platform_util_linux.cc
atom/common/platform_util_mac.mm
atom/common/platform_util_win.cc
docs/api/shell.md

index 4b03027..7ac150b 100644 (file)
@@ -26,7 +26,7 @@ void OpenItem(const base::FilePath& full_path);
 void OpenExternal(const GURL& url);
 
 // Move a file to trash.
-void MoveItemToTrash(const base::FilePath& full_path);
+bool MoveItemToTrash(const base::FilePath& full_path);
 
 void Beep();
 
index 3c3ae22..d1173c6 100644 (file)
@@ -13,7 +13,7 @@
 
 namespace {
 
-void XDGUtil(const std::string& util, const std::string& arg) {
+bool XDGUtil(const std::string& util, const std::string& arg) {
   std::vector<std::string> argv;
   argv.push_back(util);
   argv.push_back(arg);
@@ -27,8 +27,15 @@ void XDGUtil(const std::string& util, const std::string& arg) {
   options.environ["MM_NOTTTY"] = "1";
 
   base::ProcessHandle handle;
-  if (base::LaunchProcess(argv, options, &handle))
-    base::EnsureProcessGetsReaped(handle);
+  if (base::LaunchProcess(argv, options, &handle)) {
+      int exit_code;
+      base::Process process(handle);
+      base::EnsureProcessGetsReaped(handle);
+      process.WaitForExit(&exit_code);
+      return (exit_code == 0);
+  }
+
+  return false;
 }
 
 void XDGOpen(const std::string& path) {
@@ -65,8 +72,8 @@ void OpenExternal(const GURL& url) {
     XDGOpen(url.spec());
 }
 
-void MoveItemToTrash(const base::FilePath& full_path) {
-  XDGUtil("gvfs-trash", full_path.value());
+bool MoveItemToTrash(const base::FilePath& full_path) {
+  return XDGUtil("gvfs-trash", full_path.value());
 }
 
 void Beep() {
index 769941e..d9fd23c 100644 (file)
@@ -126,19 +126,21 @@ void OpenExternal(const GURL& url) {
     LOG(WARNING) << "NSWorkspace failed to open URL " << url;
 }
 
-void MoveItemToTrash(const base::FilePath& full_path) {
+bool MoveItemToTrash(const base::FilePath& full_path) {
   DCHECK([NSThread isMainThread]);
   NSString* path_string = base::SysUTF8ToNSString(full_path.value());
   NSArray* file_array =
       [NSArray arrayWithObject:[path_string lastPathComponent]];
-  if (!path_string || !file_array || ![[NSWorkspace sharedWorkspace]
-      performFileOperation:NSWorkspaceRecycleOperation
-                    source:[path_string stringByDeletingLastPathComponent]
-               destination:@""
-                     files:file_array
-                       tag:nil])
+  int status = [[NSWorkspace sharedWorkspace]
+                performFileOperation:NSWorkspaceRecycleOperation
+                source:[path_string stringByDeletingLastPathComponent]
+                destination:@""
+                files:file_array
+                tag:nil];
+  if (!path_string || !file_array || !status)
     LOG(WARNING) << "NSWorkspace failed to move file " << full_path.value()
                  << " to trash";
+  return (status == 0);
 }
 
 void Beep() {
index 19ecf45..1abce87 100644 (file)
@@ -164,7 +164,7 @@ void OpenExternal(const GURL& url) {
   }
 }
 
-void MoveItemToTrash(const base::FilePath& path) {
+bool MoveItemToTrash(const base::FilePath& path) {
   // SHFILEOPSTRUCT wants the path to be terminated with two NULLs,
   // so we have to use wcscpy because wcscpy_s writes non-NULLs
   // into the rest of the buffer.
@@ -176,7 +176,20 @@ void MoveItemToTrash(const base::FilePath& path) {
   file_operation.wFunc = FO_DELETE;
   file_operation.pFrom = double_terminated_path;
   file_operation.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION;
-  SHFileOperation(&file_operation);
+  int err = SHFileOperation(&file_operation);
+
+  // Since we're passing flags to the operation telling it to be silent,
+  // it's possible for the operation to be aborted/cancelled without err
+  // being set (although MSDN doesn't give any scenarios for how this can
+  // happen).  See MSDN for SHFileOperation and SHFILEOPTSTRUCT.
+  if (file_operation.fAnyOperationsAborted)
+    return false;
+
+  // Some versions of Windows return ERROR_FILE_NOT_FOUND (0x2) when deleting
+  // an empty directory and some return 0x402 when they should be returning
+  // ERROR_FILE_NOT_FOUND. MSDN says Vista and up won't return 0x402.  Windows 7
+  // can return DE_INVALIDFILES (0x7C) for nonexistent directories.
+  return (err == 0 || err == ERROR_FILE_NOT_FOUND || err == DE_INVALIDFILES);
 }
 
 void Beep() {
index e909ac6..f084887 100644 (file)
@@ -32,7 +32,7 @@ example, mailto: URLs in the default mail user agent.)
 
 * `fullPath` String
 
-Move the given file to trash.
+Move the given file to trash and returns boolean status for the operation.
 
 ## shell.beep()