Skip to content

Commit

Permalink
feat: macOS removal fallback when moveItemToTrash fails (#19700)
Browse files Browse the repository at this point in the history
* feat: macOS removal fallback when moveItemToTrash fails

* platform_util shouldn't know about mate::Arguments

* pull full_path from args as well
  • Loading branch information
codebytere committed Aug 13, 2019
1 parent b579832 commit e1824c0
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 13 deletions.
5 changes: 3 additions & 2 deletions docs/api/shell.md
Expand Up @@ -43,11 +43,12 @@ Returns `Promise<void>`

Open the given external protocol URL in the desktop's default manner. (For example, mailto: URLs in the user's default mail agent).

### `shell.moveItemToTrash(fullPath)`
### `shell.moveItemToTrash(fullPath[, deleteOnFail])`

* `fullPath` String
* `deleteOnFail` Boolean (optional) - Whether or not to unilaterally remove the item if the Trash is disabled or unsupported on the volume. _macOS_

Returns `Boolean` - Whether the item was successfully moved to the trash.
Returns `Boolean` - Whether the item was successfully moved to the trash or otherwise deleted.

Move the given file to trash and returns a boolean status for the operation.

Expand Down
12 changes: 11 additions & 1 deletion shell/common/api/atom_api_shell.cc
Expand Up @@ -71,6 +71,16 @@ v8::Local<v8::Promise> OpenExternal(const GURL& url, mate::Arguments* args) {
return handle;
}

bool MoveItemToTrash(mate::Arguments* args) {
base::FilePath full_path;
args->GetNext(&full_path);

bool delete_on_fail = false;
args->GetNext(&delete_on_fail);

return platform_util::MoveItemToTrash(full_path, delete_on_fail);
}

#if defined(OS_WIN)
bool WriteShortcutLink(const base::FilePath& shortcut_path,
mate::Arguments* args) {
Expand Down Expand Up @@ -134,7 +144,7 @@ void Initialize(v8::Local<v8::Object> exports,
dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder);
dict.SetMethod("openItem", &platform_util::OpenItem);
dict.SetMethod("openExternal", &OpenExternal);
dict.SetMethod("moveItemToTrash", &platform_util::MoveItemToTrash);
dict.SetMethod("moveItemToTrash", &MoveItemToTrash);
dict.SetMethod("beep", &platform_util::Beep);
#if defined(OS_WIN)
dict.SetMethod("writeShortcutLink", &WriteShortcutLink);
Expand Down
2 changes: 1 addition & 1 deletion shell/common/platform_util.h
Expand Up @@ -41,7 +41,7 @@ void OpenExternal(const GURL& url,
OpenExternalCallback callback);

// Move a file to trash.
bool MoveItemToTrash(const base::FilePath& full_path);
bool MoveItemToTrash(const base::FilePath& full_path, bool delete_on_fail);

void Beep();

Expand Down
2 changes: 1 addition & 1 deletion shell/common/platform_util_linux.cc
Expand Up @@ -82,7 +82,7 @@ void OpenExternal(const GURL& url,
std::move(callback).Run(XDGOpen(url.spec(), false) ? "" : "Failed to open");
}

bool MoveItemToTrash(const base::FilePath& full_path) {
bool MoveItemToTrash(const base::FilePath& full_path, bool delete_on_fail) {
std::unique_ptr<base::Environment> env(base::Environment::Create());

// find the trash method
Expand Down
33 changes: 26 additions & 7 deletions shell/common/platform_util_mac.mm
Expand Up @@ -115,16 +115,35 @@ void OpenExternal(const GURL& url,
});
}

bool MoveItemToTrash(const base::FilePath& full_path) {
bool MoveItemToTrash(const base::FilePath& full_path, bool delete_on_fail) {
NSString* path_string = base::SysUTF8ToNSString(full_path.value());
BOOL status = [[NSFileManager defaultManager]
trashItemAtURL:[NSURL fileURLWithPath:path_string]
resultingItemURL:nil
error:nil];
if (!path_string || !status)
if (!path_string) {
LOG(WARNING) << "Invalid file path " << full_path.value();
return false;
}

NSURL* url = [NSURL fileURLWithPath:path_string];
NSError* err = nil;
BOOL did_trash = [[NSFileManager defaultManager] trashItemAtURL:url
resultingItemURL:nil
error:&err];

if (delete_on_fail) {
// Some volumes may not support a Trash folder or it may be disabled
// so these methods will report failure by returning NO or nil and
// an NSError with NSFeatureUnsupportedError.
// Handle this by deleting the item as a fallback.
if (!did_trash && [err code] == NSFeatureUnsupportedError) {
did_trash = [[NSFileManager defaultManager] removeItemAtURL:url
error:nil];
}
}

if (!did_trash)
LOG(WARNING) << "NSWorkspace failed to move file " << full_path.value()
<< " to trash";
return status;

return did_trash;
}

void Beep() {
Expand Down
2 changes: 1 addition & 1 deletion shell/common/platform_util_win.cc
Expand Up @@ -335,7 +335,7 @@ void OpenExternal(const GURL& url,
std::move(callback));
}

bool MoveItemToTrash(const base::FilePath& path) {
bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
base::win::ScopedCOMInitializer com_initializer;
if (!com_initializer.Succeeded())
return false;
Expand Down

0 comments on commit e1824c0

Please sign in to comment.