Bug 1556875 [wpt PR 17178] - NativeFileSystemDirectoryHandleImpl::GetChildURL should validate |name|, a=testonly

Automatic update from web-platform-tests
NativeFileSystemDirectoryHandleImpl::GetChildURL should validate |name|

Updates NativeFileSystemDirectoryHandleImpl::GetChildURL() to return a
base::File::Error for invalid |name| input.  |name| must specify a
direct child of the current directory.  Invalid |name| inputs include:

 1. Empty string: ''
 2. Current directory: '.'
 3. Parent directory: '..'
 4. Strings containing path separators like '/'

Updates the callers of GetChildURL() to handle errors by immediately
running callbacks with the base::File::Error returned by GetChildURL().

Extends existing NativeFileSystem API webtests by adding invalid 'name'
input tests for each JavaScript API with a 'name' parameter, including
getFile(), getDirectory(), moveTo(), and copyTo().

Bug: 960411
Change-Id: Ida6ebf1cb2d1017e2cafe386c30d5cb65430055c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1643984
Commit-Queue: Steve Becker <stevebe@microsoft.com>
Auto-Submit: Steve Becker <stevebe@microsoft.com>
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#666118}

--

wp5At-commits: 78171013d97f5416ccc24e91a43d44d98fc30036
wpt-pr: 17178
This commit is contained in:
Steve Becker 2019-06-13 15:32:38 +00:00 коммит произвёл James Graham
Родитель 72eb076d03
Коммит 23b13b7d73
5 изменённых файлов: 251 добавлений и 3 удалений

Просмотреть файл

@ -69,4 +69,64 @@ promise_test(async t => {
assert_array_equals(await getSortedDirectoryEntries(dir), ['old-file', 'target']);
}, 'copyTo() when target file already exists should overwrite target');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir_name = 'subdir-name';
const subdir = await createDirectory(t, subdir_name, /*parent=*/dir);
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/subdir);
// An empty name indicates that the filename should remain unchanged.
await file.copyTo(dir, /*name=*/"");
await dir.getFile(file_name);
}, `copyTo() when target is empty`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir_name = 'subdir-name';
const subdir = await createDirectory(t, subdir_name, /*parent=*/dir);
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/subdir);
await promise_rejects(t, 'SecurityError', file.copyTo(dir, /*name=*/kCurrentDirectory));
}, `copyTo() when target is ${kCurrentDirectory}`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const first_subdir_name = 'first-subdir-name';
const first_subdir = await createDirectory(t, first_subdir_name, /*parent=*/dir);
const second_subdir_name = 'second-subdir-name';
const second_subdir = await createDirectory(t, second_subdir_name, /*parent=*/first_subdir);
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/second_subdir);
await promise_rejects(t, 'SecurityError', file.copyTo(first_subdir, /*name=*/kParentDirectory));
}, `copyTo() when target is ${kParentDirectory}`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/dir);
const first_subdir_name = 'first-subdir-name';
const first_subdir = await createDirectory(t, first_subdir_name, /*parent=*/dir);
const second_subdir_name = 'second-subdir-name';
const second_subdir = await createDirectory(t, second_subdir_name, /*parent=*/first_subdir);
for (let i = 0; i < kPathSeparators.length; ++i) {
const path_with_separator = `${second_subdir_name}${kPathSeparators[i]}${file_name}`;
await promise_rejects(t, 'SecurityError', file.copyTo(first_subdir, path_with_separator),
`copyTo() must reject names containing "${kPathSeparators[i]}"`);
}
}, 'copyTo() when target contains path separator');
// TODO(mek): Tests to copy directories.

Просмотреть файл

@ -43,7 +43,6 @@ promise_test(async t => {
assert_array_equals(await getSortedDirectoryEntries(target_dir), ['old-file']);
}, 'moveTo() to move a file into a sub-directory');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const handle = await createFileWithContents(t, 'old-file', '12345', dir);
@ -69,4 +68,64 @@ promise_test(async t => {
assert_array_equals(await getSortedDirectoryEntries(dir), ['target']);
}, 'moveTo() when target file already exists should overwrite target');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir_name = 'subdir-name';
const subdir = await createDirectory(t, subdir_name, /*parent=*/dir);
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/subdir);
// An empty name indicates that the filename should remain unchanged.
await file.moveTo(dir, /*name=*/"");
await dir.getFile(file_name);
}, `moveTo() when target is empty`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir_name = 'subdir-name';
const subdir = await createDirectory(t, subdir_name, /*parent=*/dir);
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/subdir);
await promise_rejects(t, 'SecurityError', file.moveTo(dir, /*name=*/kCurrentDirectory));
}, `moveTo() when target is ${kCurrentDirectory}`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const first_subdir_name = 'first-subdir-name';
const first_subdir = await createDirectory(t, first_subdir_name, /*parent=*/dir);
const second_subdir_name = 'second-subdir-name';
const second_subdir = await createDirectory(t, second_subdir_name, /*parent=*/first_subdir);
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/second_subdir);
await promise_rejects(t, 'SecurityError', file.moveTo(first_subdir, /*name=*/kParentDirectory));
}, `moveTo() when target is ${kParentDirectory}`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const file_name = 'file-name';
const file = await createEmptyFile(t, file_name, /*parent=*/dir);
const first_subdir_name = 'first-subdir-name';
const first_subdir = await createDirectory(t, first_subdir_name, /*parent=*/dir);
const second_subdir_name = 'second-subdir-name';
const second_subdir = await createDirectory(t, second_subdir_name, /*parent=*/first_subdir);
for (let i = 0; i < kPathSeparators.length; ++i) {
const path_with_separator = `${second_subdir_name}${kPathSeparators[i]}${file_name}`;
await promise_rejects(t, 'SecurityError', file.moveTo(first_subdir, path_with_separator),
`moveTo() must reject names containing "${kPathSeparators[i]}"`);
}
}, 'moveTo() when target contains path separator');
// TODO(mek): Tests to move directories.

Просмотреть файл

@ -55,3 +55,52 @@ promise_test(async t => {
await promise_rejects(t, 'TypeMismatchError', root.getDirectory('file-name', { create: false }));
await promise_rejects(t, 'TypeMismatchError', root.getDirectory('file-name', { create: true }));
}, 'getDirectory() when a file already exists with the same name');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
await promise_rejects(t, 'NotFoundError', dir.getDirectory("", { create: true }));
await promise_rejects(t, 'NotFoundError', dir.getDirectory("", { create: false }));
}, 'getDirectory() with empty name');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
await promise_rejects(t, 'SecurityError', dir.getDirectory(kCurrentDirectory));
await promise_rejects(t, 'SecurityError', dir.getDirectory(kCurrentDirectory, { create: true }));
}, `getDirectory() with "${kCurrentDirectory}" name`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir = await createDirectory(t, 'subdir-name', /*parent=*/dir);
await promise_rejects(t, 'SecurityError', subdir.getDirectory(kParentDirectory));
await promise_rejects(t, 'SecurityError', subdir.getDirectory(kParentDirectory, { create: true }));
}, `getDirectory() with "${kParentDirectory}" name`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const first_subdir_name = 'first-subdir-name';
const first_subdir = await createDirectory(t, first_subdir_name, /*parent=*/dir);
const second_subdir_name = 'second-subdir-name';
const second_subdir = await createDirectory(t, second_subdir_name, /*parent=*/first_subdir);
for (let i = 0; i < kPathSeparators.length; ++i) {
const path_with_separator = `${first_subdir_name}${kPathSeparators[i]}${second_subdir_name}`;
await promise_rejects(t, 'SecurityError', dir.getDirectory(path_with_separator),
`getDirectory() must reject names containing "${kPathSeparators[i]}"`);
}
}, 'getDirectory(create=false) with a path separator when the directory exists');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir_name = 'subdir-name';
const subdir = await createDirectory(t, subdir_name, /*parent=*/dir);
for (let i = 0; i < kPathSeparators.length; ++i) {
const path_with_separator = `${subdir_name}${kPathSeparators[i]}file_name`;
await promise_rejects(t, 'SecurityError', dir.getDirectory(path_with_separator, { create: true }),
`getDirectory(true) must reject names containing "${kPathSeparators[i]}"`);
}
}, 'getDirectory(create=true) with a path separator');

Просмотреть файл

@ -1,6 +1,6 @@
// META: script=resources/test-helpers.js
promise_test(async t => cleanupSandboxedFileSystem(),
'Cleanup to setup test environment');
'Cleanup to setup test environment');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
@ -59,4 +59,53 @@ promise_test(async t => {
t.add_cleanup(() => dir_handle.removeRecursively());
await promise_rejects(t, 'TypeMismatchError', dir.getFile('dir-name', { create: true }));
}, 'getFile(create=true) when a directory already exists with the same name');
}, 'getFile(create=true) when a directory already exists with the same name');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
await promise_rejects(t, 'NotFoundError', dir.getFile("", { create: true }));
await promise_rejects(t, 'NotFoundError', dir.getFile("", { create: false }));
}, 'getFile() with empty name');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
await promise_rejects(t, 'SecurityError', dir.getFile(kCurrentDirectory));
await promise_rejects(t, 'SecurityError', dir.getFile(kCurrentDirectory, { create: true }));
}, `getFile() with "${kCurrentDirectory}" name`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir = await createDirectory(t, 'subdir-name', /*parent=*/dir);
await promise_rejects(t, 'SecurityError', subdir.getFile(kParentDirectory));
await promise_rejects(t, 'SecurityError', subdir.getFile(kParentDirectory, { create: true }));
}, `getFile() with "${kParentDirectory}" name`);
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir_name = 'subdir-name';
const subdir = await createDirectory(t, subdir_name, /*parent=*/dir);
const file_name = 'file-name';
await createEmptyFile(t, file_name, /*parent=*/subdir);
for (let i = 0; i < kPathSeparators.length; ++i) {
const path_with_separator = `${subdir_name}${kPathSeparators[i]}${file_name}`;
await promise_rejects(t, 'SecurityError', dir.getFile(path_with_separator),
`getFile() must reject names containing "${kPathSeparators[i]}"`);
}
}, 'getFile(create=false) with a path separator when the file exists.');
promise_test(async t => {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const subdir_name = 'subdir-name';
const subdir = await createDirectory(t, subdir_name, /*parent=*/dir);
for (let i = 0; i < kPathSeparators.length; ++i) {
const path_with_separator = `${subdir_name}${kPathSeparators[i]}file_name`;
await promise_rejects(t, 'SecurityError', dir.getFile(path_with_separator, { create: true }),
`getFile(true) must reject names containing "${kPathSeparators[i]}"`);
}
}, 'getFile(create=true) with a path separator');

Просмотреть файл

@ -1,3 +1,18 @@
// A special path component meaning "this directory."
const kCurrentDirectory = ".";
// A special path component meaning "the parent directory."
const kParentDirectory = "..";
// Array of separators used to separate components in hierarchical paths.
let kPathSeparators;
if (navigator.userAgent.includes("Windows NT")) {
// Windows uses both '/' and '\' as path separators.
kPathSeparators = ['/', '\\' ];
} else {
kPathSeparators = [ '/' ];
}
async function cleanupSandboxedFileSystem() {
const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
for await (let entry of dir.getEntries()) {
@ -38,6 +53,22 @@ async function getSortedDirectoryEntries(handle) {
return result;
}
async function createDirectory(test, name, parent) {
const parent_dir_handle = parent ? parent :
await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const new_dir_handle = await parent_dir_handle.getDirectory(name, { create: true });
test.add_cleanup(async () => {
try {
await new_dir_handle.removeRecursively();
} catch (e) {
// Ignore any errors when removing directories, as tests might
// have already removed the directory.
}
});
return new_dir_handle;
}
async function createEmptyFile(test, name, parent) {
const dir = parent ? parent : await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
const handle = await dir.getFile(name, { create: true });