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();
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);
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) {
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() {
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() {
}
}
-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.
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() {
* `fullPath` String
-Move the given file to trash.
+Move the given file to trash and returns boolean status for the operation.
## shell.beep()