X Tutup
Skip to content

Commit e1824c0

Browse files
authored
feat: macOS removal fallback when moveItemToTrash fails (electron#19700)
* feat: macOS removal fallback when moveItemToTrash fails * platform_util shouldn't know about mate::Arguments * pull full_path from args as well
1 parent b579832 commit e1824c0

File tree

6 files changed

+43
-13
lines changed

6 files changed

+43
-13
lines changed

docs/api/shell.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ Returns `Promise<void>`
4343

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

46-
### `shell.moveItemToTrash(fullPath)`
46+
### `shell.moveItemToTrash(fullPath[, deleteOnFail])`
4747

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

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

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

shell/common/api/atom_api_shell.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ v8::Local<v8::Promise> OpenExternal(const GURL& url, mate::Arguments* args) {
7171
return handle;
7272
}
7373

74+
bool MoveItemToTrash(mate::Arguments* args) {
75+
base::FilePath full_path;
76+
args->GetNext(&full_path);
77+
78+
bool delete_on_fail = false;
79+
args->GetNext(&delete_on_fail);
80+
81+
return platform_util::MoveItemToTrash(full_path, delete_on_fail);
82+
}
83+
7484
#if defined(OS_WIN)
7585
bool WriteShortcutLink(const base::FilePath& shortcut_path,
7686
mate::Arguments* args) {
@@ -134,7 +144,7 @@ void Initialize(v8::Local<v8::Object> exports,
134144
dict.SetMethod("showItemInFolder", &platform_util::ShowItemInFolder);
135145
dict.SetMethod("openItem", &platform_util::OpenItem);
136146
dict.SetMethod("openExternal", &OpenExternal);
137-
dict.SetMethod("moveItemToTrash", &platform_util::MoveItemToTrash);
147+
dict.SetMethod("moveItemToTrash", &MoveItemToTrash);
138148
dict.SetMethod("beep", &platform_util::Beep);
139149
#if defined(OS_WIN)
140150
dict.SetMethod("writeShortcutLink", &WriteShortcutLink);

shell/common/platform_util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void OpenExternal(const GURL& url,
4141
OpenExternalCallback callback);
4242

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

4646
void Beep();
4747

shell/common/platform_util_linux.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void OpenExternal(const GURL& url,
8282
std::move(callback).Run(XDGOpen(url.spec(), false) ? "" : "Failed to open");
8383
}
8484

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

8888
// find the trash method

shell/common/platform_util_mac.mm

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,16 +115,35 @@ void OpenExternal(const GURL& url,
115115
});
116116
}
117117

118-
bool MoveItemToTrash(const base::FilePath& full_path) {
118+
bool MoveItemToTrash(const base::FilePath& full_path, bool delete_on_fail) {
119119
NSString* path_string = base::SysUTF8ToNSString(full_path.value());
120-
BOOL status = [[NSFileManager defaultManager]
121-
trashItemAtURL:[NSURL fileURLWithPath:path_string]
122-
resultingItemURL:nil
123-
error:nil];
124-
if (!path_string || !status)
120+
if (!path_string) {
121+
LOG(WARNING) << "Invalid file path " << full_path.value();
122+
return false;
123+
}
124+
125+
NSURL* url = [NSURL fileURLWithPath:path_string];
126+
NSError* err = nil;
127+
BOOL did_trash = [[NSFileManager defaultManager] trashItemAtURL:url
128+
resultingItemURL:nil
129+
error:&err];
130+
131+
if (delete_on_fail) {
132+
// Some volumes may not support a Trash folder or it may be disabled
133+
// so these methods will report failure by returning NO or nil and
134+
// an NSError with NSFeatureUnsupportedError.
135+
// Handle this by deleting the item as a fallback.
136+
if (!did_trash && [err code] == NSFeatureUnsupportedError) {
137+
did_trash = [[NSFileManager defaultManager] removeItemAtURL:url
138+
error:nil];
139+
}
140+
}
141+
142+
if (!did_trash)
125143
LOG(WARNING) << "NSWorkspace failed to move file " << full_path.value()
126144
<< " to trash";
127-
return status;
145+
146+
return did_trash;
128147
}
129148

130149
void Beep() {

shell/common/platform_util_win.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ void OpenExternal(const GURL& url,
335335
std::move(callback));
336336
}
337337

338-
bool MoveItemToTrash(const base::FilePath& path) {
338+
bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
339339
base::win::ScopedCOMInitializer com_initializer;
340340
if (!com_initializer.Succeeded())
341341
return false;

0 commit comments

Comments
 (0)
X Tutup