0

FS: Recursive RemoveEntry for non-existent handle throws NotFoundError.

This change ensures that FileSystemDirectoryHandle.removeEntry throws a
'NotFoundError' DOMException when attempting to remove a non-existent
entry with recursive set to true. Previously, it returned undefined
instead of throwing the expected DOMException.

Bug: 362301049
Change-Id: I17873135fade0f25068fcbca53ed9faf0a363ee3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5990675
Reviewed-by: François Degros <fdegros@chromium.org>
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Commit-Queue: Xiaohan Zhao <xiaohanzhao@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1407002}
This commit is contained in:
Xiaohan Zhao
2025-01-15 15:38:13 -08:00
committed by Chromium LUCI CQ
parent fd423626f2
commit 8ff34ad1a6
3 changed files with 15 additions and 8 deletions
chrome/browser/ash/file_manager
storage/browser/file_system
third_party/blink/web_tests/external/wpt/fs/script-tests

@ -142,16 +142,17 @@ TEST_F(DeleteIOTaskTest, NoSuchFile) {
base::MockRepeatingCallback<void(const ProgressStatus&)> progress_callback;
base::MockOnceCallback<void(ProgressStatus)> complete_callback;
EXPECT_CALL(progress_callback, Run(_)).Times(0);
// Note that deleting a file that does not exist is expected to succeed.
// Whether the file is deleted or never created has the same end result.
// Deleting a file that does not exist is expected to fail with a
// FILE_ERROR_NOT_FOUND.
EXPECT_CALL(
complete_callback,
Run(AllOf(Field(&ProgressStatus::type, OperationType::kDelete),
Field(&ProgressStatus::state, State::kSuccess),
Field(&ProgressStatus::state, State::kError),
Field(&ProgressStatus::bytes_transferred, 1),
Field(&ProgressStatus::sources, EntryStatusUrls(file_urls)),
Field(&ProgressStatus::sources,
EntryStatusErrors(ElementsAre(base::File::FILE_OK))))))
EntryStatusErrors(
ElementsAre(base::File::FILE_ERROR_NOT_FOUND))))))
.WillOnce(RunClosure(run_loop.QuitClosure()));
DeleteIOTask task(file_urls, file_system_context_);

@ -82,10 +82,6 @@ void RemoveOperationDelegate::DidTryRemoveDirectory(
void RemoveOperationDelegate::DidRemoveFile(StatusCallback callback,
base::File::Error error) {
if (error == base::File::FILE_ERROR_NOT_FOUND) {
std::move(callback).Run(base::File::FILE_OK);
return;
}
std::move(callback).Run(error);
}

@ -128,3 +128,13 @@ directory_test(async (t, root) => {
assert_array_equals(await getSortedDirectoryEntries(root), []);
}, 'createWritable after removeEntry succeeds but doesnt recreate the file');
directory_test(async (t, root) => {
// root
// ├──file-to-keep
// ├──dir-to-keep
await createFileWithContents('file-to-keep', 'abc', root);
const dir_to_keep = await root.getDirectoryHandle('dir-to-keep', {create: true});
await promise_rejects_dom(
t, 'NotFoundError', root.removeEntry('dir-to-remove', {recursive: true}));
}, 'removeEntry() on a non-existent directory recursively should throw NotFoundError');