diff options
Diffstat (limited to '')
-rw-r--r-- | dom/filesystem/tests/filesystem_commons.js | 180 | ||||
-rw-r--r-- | dom/filesystem/tests/mochitest.ini | 12 | ||||
-rw-r--r-- | dom/filesystem/tests/moz.build | 7 | ||||
-rw-r--r-- | dom/filesystem/tests/script_fileList.js | 176 | ||||
-rw-r--r-- | dom/filesystem/tests/script_promptHandler.js | 18 | ||||
-rw-r--r-- | dom/filesystem/tests/test_basic.html | 118 | ||||
-rw-r--r-- | dom/filesystem/tests/test_bug1319088.html | 65 | ||||
-rw-r--r-- | dom/filesystem/tests/test_webkitdirectory.html | 309 | ||||
-rw-r--r-- | dom/filesystem/tests/test_worker_basic.html | 73 | ||||
-rw-r--r-- | dom/filesystem/tests/worker_basic.js | 50 |
10 files changed, 1008 insertions, 0 deletions
diff --git a/dom/filesystem/tests/filesystem_commons.js b/dom/filesystem/tests/filesystem_commons.js new file mode 100644 index 0000000000..af0ce36339 --- /dev/null +++ b/dom/filesystem/tests/filesystem_commons.js @@ -0,0 +1,180 @@ +function createPath(parentDir, dirOrFile) { + return parentDir.path + (parentDir.path == "/" ? "" : "/") + dirOrFile.name; +} + +function createRelativePath(parentDir, dirOrFile) { + let path = createPath(parentDir, dirOrFile); + is(path[0], "/", "The full path should start with '/'"); + return path.substring(1); +} + +function setup_tests(aNext) { + SimpleTest.requestLongerTimeout(2); + SpecialPowers.pushPrefEnv( + { + set: [ + ["dom.filesystem.pathcheck.disabled", true], + ["dom.webkitBlink.dirPicker.enabled", true], + ], + }, + aNext + ); +} + +function test_basic(aDirectory, aNext) { + ok(aDirectory, "Directory exists."); + ok(aDirectory instanceof Directory, "We have a directory."); + is(aDirectory.path, "/" + aDirectory.name, "directory.path must be '/'+name"); + aNext(); +} + +function test_getFilesAndDirectories(aDirectory, aRecursive, aNext) { + function checkSubDir(dir) { + return dir.getFilesAndDirectories().then(function (data) { + for (var i = 0; i < data.length; ++i) { + ok( + data[i] instanceof File || data[i] instanceof Directory, + "Just Files or Directories" + ); + if (data[i] instanceof Directory) { + isnot( + data[i].name, + "/", + "Subdirectory should be called with the leafname" + ); + isnot( + data[i].path, + "/", + "Subdirectory path should be called with the leafname" + ); + isnot( + data[i].path, + dir.path, + "Subdirectory path should contain the parent path." + ); + is( + data[i].path, + createPath(dir, data[i]), + "Subdirectory path should be called parentdir.path + '/' + leafname: " + + data[i].path + ); + } + + if (data[i] instanceof File) { + is( + data[i].webkitRelativePath, + createRelativePath(dir, data[i]), + "File.webkitRelativePath should be called: parentdir.path + '/' + file.name: " + + data[i].webkitRelativePath + ); + ok( + !data[i].webkitRelativePath.endsWith("symlink.txt"), + "We should never see a path ending with symlink.txt, our symlink sentinel." + ); + } + } + }); + } + + aDirectory + .getFilesAndDirectories() + .then( + function (data) { + ok(data.length, "We should have some data."); + var promises = []; + for (var i = 0; i < data.length; ++i) { + ok( + data[i] instanceof File || data[i] instanceof Directory, + "Just Files or Directories: " + data[i].name + ); + if (data[i] instanceof Directory) { + isnot( + data[i].name, + "/", + "Subdirectory should be called with the leafname" + ); + is( + data[i].path, + createPath(aDirectory, data[i]), + "Subdirectory path should be called parentdir.path + '/' + leafname: " + + data[i].path + ); + if (aRecursive) { + promises.push(checkSubDir(data[i])); + } + } + + if (data[i] instanceof File) { + is( + data[i].webkitRelativePath, + createRelativePath(aDirectory, data[i]), + "File.webkitRelativePath should be called file.name: " + + data[i].webkitRelativePath + ); + } + } + + return Promise.all(promises); + }, + function () { + ok(false, "Something when wrong"); + } + ) + .then(aNext); +} + +function test_getFiles(aDirectory, aRecursive, aNext) { + aDirectory + .getFiles(aRecursive) + .then( + function (data) { + for (var i = 0; i < data.length; ++i) { + ok(data[i] instanceof File, "File: " + data[i].name); + is(aDirectory.path[0], "/", "Directory path must start with '/'"); + ok( + data[i].webkitRelativePath.indexOf(aDirectory.path.substring(1)) == + 0 && + data[i].webkitRelativePath.indexOf("/" + data[i].name) + + ("/" + data[i].name).length == + data[i].webkitRelativePath.length, + "File.webkitRelativePath should be called dir.path + '/' + file.name: " + + data[i].webkitRelativePath + ); + } + }, + function () { + ok(false, "Something when wrong"); + } + ) + .then(aNext); +} + +function test_getFiles_recursiveComparison(aDirectory, aNext) { + aDirectory + .getFiles(true) + .then(function (data) { + is(data.length, 2, "Only 2 files for this test."); + ok( + data[0].name == "foo.txt" || data[0].name == "bar.txt", + "First filename matches" + ); + ok( + data[1].name == "foo.txt" || data[1].name == "bar.txt", + "Second filename matches" + ); + }) + .then(function () { + return aDirectory.getFiles(false); + }) + .then(function (data) { + is(data.length, 1, "Only 1 file for this test."); + ok( + data[0].name == "foo.txt" || data[0].name == "bar.txt", + "First filename matches" + ); + }) + .catch(function () { + ok(false, "Something when wrong"); + }) + .then(aNext); +} diff --git a/dom/filesystem/tests/mochitest.ini b/dom/filesystem/tests/mochitest.ini new file mode 100644 index 0000000000..00326a6e0d --- /dev/null +++ b/dom/filesystem/tests/mochitest.ini @@ -0,0 +1,12 @@ +[DEFAULT] +support-files = + filesystem_commons.js + script_fileList.js + worker_basic.js + +[test_basic.html] +[test_webkitdirectory.html] +skip-if = os == "android" # Bug 1674428 +support-files = script_promptHandler.js +[test_worker_basic.html] +[test_bug1319088.html] diff --git a/dom/filesystem/tests/moz.build b/dom/filesystem/tests/moz.build new file mode 100644 index 0000000000..7c990fbc62 --- /dev/null +++ b/dom/filesystem/tests/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MOCHITEST_MANIFESTS += ["mochitest.ini"] diff --git a/dom/filesystem/tests/script_fileList.js b/dom/filesystem/tests/script_fileList.js new file mode 100644 index 0000000000..47438aa7b3 --- /dev/null +++ b/dom/filesystem/tests/script_fileList.js @@ -0,0 +1,176 @@ +/* eslint-env mozilla/chrome-script */ +// eslint-disable-next-line mozilla/reject-importGlobalProperties +Cu.importGlobalProperties(["File"]); +function createProfDFile() { + return Services.dirsvc + .QueryInterface(Ci.nsIProperties) + .get("ProfD", Ci.nsIFile); +} + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +// Creates a parametric arity directory hierarchy as a function of depth. +// Each directory contains one leaf file, and subdirectories of depth [1, depth). +// e.g. for depth 3: +// +// subdir3 +// - file.txt +// - subdir2 +// - file.txt +// - subdir1 +// - file.txt +// - subdir1 +// - file.txt +// +// Returns the parent directory of the subtree. +function createTreeFile(depth, parent) { + if (!parent) { + parent = Services.dirsvc + .QueryInterface(Ci.nsIProperties) + .get("TmpD", Ci.nsIFile); + parent.append("dir-tree-test"); + parent.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o700); + } + + var nextFile = parent.clone(); + if (depth == 0) { + nextFile.append("file.txt"); + nextFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + + // It's not possible to create symlinks on windows by default or on our + // Android platforms, so we can't create the symlink file there. Our + // callers that care are aware of this and also check AppConstants. + if ( + AppConstants.platform !== "win" && + AppConstants.platform !== "android" + ) { + var linkFile = parent.clone(); + linkFile.append("symlink.txt"); + createSymLink(nextFile.path, linkFile.path); + } + } else { + nextFile.append("subdir" + depth); + nextFile.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o700); + // Decrement the maximal depth by one for each level of nesting. + for (var i = 0; i < depth; i++) { + createTreeFile(i, nextFile); + } + } + + return parent; +} + +function createRootFile() { + var testFile = createProfDFile(); + + // Let's go back to the root of the FileSystem + while (true) { + var parent = testFile.parent; + if (!parent) { + break; + } + + testFile = parent; + } + + return testFile; +} + +var process; +function createSymLink(target, linkName) { + if (!process) { + var ln = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + ln.initWithPath("/bin/ln"); + + process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(ln); + } + + const args = ["-s", target, linkName]; + process.run(true, args, args.length); + Assert.equal(process.exitValue, 0); +} + +function createTestFile() { + var tmpFile = Services.dirsvc + .QueryInterface(Ci.nsIProperties) + .get("TmpD", Ci.nsIFile); + tmpFile.append("dir-test"); + tmpFile.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o700); + + var file1 = tmpFile.clone(); + file1.append("foo.txt"); + file1.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + + var dir = tmpFile.clone(); + dir.append("subdir"); + dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o700); + + var file2 = dir.clone(); + file2.append("bar.txt"); + file2.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + + // It's not possible to create symlinks on windows by default or on our + // Android platforms, so we can't create the symlink file there. Our + // callers that care are aware of this and also check AppConstants. + if (AppConstants.platform !== "win" && AppConstants.platform !== "android") { + var linkFile = dir.clone(); + linkFile.append("symlink.txt"); + createSymLink(file1.path, linkFile.path); + } + + return tmpFile; +} + +addMessageListener("dir.open", function (e) { + var testFile; + + switch (e.path) { + case "ProfD": + // Note that files in the profile directory are not guaranteed to persist- + // see bug 1284742. + testFile = createProfDFile(); + break; + + case "root": + testFile = createRootFile(); + break; + + case "test": + testFile = createTestFile(); + break; + + case "tree": + testFile = createTreeFile(3); + break; + } + + sendAsyncMessage("dir.opened", { + dir: testFile.path, + name: testFile.leafName, + }); +}); + +addMessageListener("file.open", function (e) { + var testFile = Services.dirsvc + .QueryInterface(Ci.nsIProperties) + .get("ProfD", Ci.nsIFile); + testFile.append("prefs.js"); + + File.createFromNsIFile(testFile).then(function (file) { + sendAsyncMessage("file.opened", { file }); + }); +}); + +addMessageListener("symlink.open", function (e) { + let testDir = createTestFile(); + let testFile = testDir.clone(); + testFile.append("subdir"); + testFile.append("symlink.txt"); + + File.createFromNsIFile(testFile).then(function (file) { + sendAsyncMessage("symlink.opened", { dir: testDir.path, file }); + }); +}); diff --git a/dom/filesystem/tests/script_promptHandler.js b/dom/filesystem/tests/script_promptHandler.js new file mode 100644 index 0000000000..ed3bda7404 --- /dev/null +++ b/dom/filesystem/tests/script_promptHandler.js @@ -0,0 +1,18 @@ +/* eslint-env mozilla/chrome-script */ + +let dialogObserverTopic = "common-dialog-loaded"; + +function dialogObserver(subj, topic, data) { + subj.document.querySelector("dialog").acceptDialog(); + sendAsyncMessage("promptAccepted"); +} + +addMessageListener("init", message => { + Services.obs.addObserver(dialogObserver, dialogObserverTopic); + sendAsyncMessage("initDone"); +}); + +addMessageListener("cleanup", message => { + Services.obs.removeObserver(dialogObserver, dialogObserverTopic); + sendAsyncMessage("cleanupDone"); +}); diff --git a/dom/filesystem/tests/test_basic.html b/dom/filesystem/tests/test_basic.html new file mode 100644 index 0000000000..b4daea79c9 --- /dev/null +++ b/dom/filesystem/tests/test_basic.html @@ -0,0 +1,118 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Directory API</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="filesystem_commons.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> + +<body> +<script type="application/javascript"> + +var directory; +var fileList; + +function create_fileList(aPath) { + fileList = document.createElement("input"); + fileList.setAttribute("type", "file"); + document.body.appendChild(fileList); + + var url = SimpleTest.getTestFileURL("script_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + function onOpened(message) { + SpecialPowers.wrap(fileList).mozSetDirectory(message.dir); + fileList.setAttribute("data-name", message.name); + + SpecialPowers.wrap(fileList).getFilesAndDirectories().then(function(array) { + array = SpecialPowers.unwrap(array); + is(array.length, 1, "We want just 1 directory."); + ok(array[0] instanceof Directory, "We want just 1 directory."); + + directory = array[0]; + script.destroy(); + next(); + }); + } + + script.addMessageListener("dir.opened", onOpened); + script.sendAsyncMessage("dir.open", { path: aPath }); +} + +function test_simpleFilePicker(aPath) { + var url = SimpleTest.getTestFileURL("script_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + function onOpened(message) { + SpecialPowers.wrap(fileList).mozSetFileArray([message.file]); + + is(fileList.files.length, 1, "we want 1 element"); + ok(fileList.files[0] instanceof File, "we want 1 file"); + ok("webkitRelativePath" in fileList.files[0], "we have webkitRelativePath attribute"); + is(fileList.files[0].webkitRelativePath, "", "No webkit relative path for normal filePicker"); + + script.destroy(); + next(); + } + + script.addMessageListener("file.opened", onOpened); + script.sendAsyncMessage("file.open"); +} + +function test_duplicateGetFilesAndDirectories() { + var url = SimpleTest.getTestFileURL("script_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + function onOpened(message) { + SpecialPowers.wrap(fileList).mozSetDirectory(message.dir); + + var p1 = SpecialPowers.wrap(fileList).getFilesAndDirectories(); + var p2 = SpecialPowers.wrap(fileList).getFilesAndDirectories(); + + isnot(p1, p2, "We create 2 different promises"); + + script.destroy(); + next(); + } + + script.addMessageListener("dir.opened", onOpened); + script.sendAsyncMessage("dir.open", { path: "test" }); +} + +var tests = [ + function() { setup_tests(next); }, + + function() { create_fileList("tree"); }, + function() { test_basic(directory, next); }, + function() { test_getFilesAndDirectories(directory, true, next); }, + function() { test_getFiles(directory, false, next); }, + function() { test_getFiles(directory, true, next); }, + + function() { create_fileList("test"); }, + function() { test_getFiles_recursiveComparison(directory, next); }, + + function() { create_fileList("root"); }, + function() { test_basic(directory, next); }, + function() { test_getFilesAndDirectories(directory, false, next); }, + function() { test_getFiles(directory, false, next); }, + + test_duplicateGetFilesAndDirectories, + test_simpleFilePicker, +]; + +function next() { + if (!tests.length) { + SimpleTest.finish(); + return; + } + + var test = tests.shift(); + test(); +} + +SimpleTest.waitForExplicitFinish(); +next(); +</script> +</body> +</html> diff --git a/dom/filesystem/tests/test_bug1319088.html b/dom/filesystem/tests/test_bug1319088.html new file mode 100644 index 0000000000..98e0ad46f0 --- /dev/null +++ b/dom/filesystem/tests/test_bug1319088.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for bug 1319088</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> + +<body> +<input id="input" type="file"></input> + +<script type="application/javascript"> + +function testSetup() { + SpecialPowers.pushPrefEnv({"set": [["dom.webkitBlink.dirPicker.enabled", true]]}, next); +} + +function populateInputFile() { + var url = SimpleTest.getTestFileURL("script_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + function onOpened(message) { + var input = document.getElementById("input"); + SpecialPowers.wrap(input).mozSetFileArray([message.file]); + + script.destroy(); + next(); + } + + script.addMessageListener("file.opened", onOpened); + script.sendAsyncMessage("file.open"); +} + +function checkBug() { + var input = document.getElementById("input"); + is(input.files[0].webkitRelativePath, "", "No relative path!"); + + let form = document.createElement("form"); + form.appendChild(input); + + is(input.files[0].webkitRelativePath, "", "No relative path!"); + SimpleTest.finish(); +} + +var tests = [ + testSetup, + populateInputFile, + checkBug, +]; + +function next() { + if (!tests.length) { + SimpleTest.finish(); + return; + } + + var test = tests.shift(); + test(); +} + +SimpleTest.waitForExplicitFinish(); +next(); +</script> +</body> +</html> diff --git a/dom/filesystem/tests/test_webkitdirectory.html b/dom/filesystem/tests/test_webkitdirectory.html new file mode 100644 index 0000000000..50080ad7ba --- /dev/null +++ b/dom/filesystem/tests/test_webkitdirectory.html @@ -0,0 +1,309 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for webkitdirectory and webkitRelativePath</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> + +<body> +<input id="inputFileWebkitDirectory" type="file" webkitdirectory></input> +<input id="inputFileWebkitFile" type="file"></input> +<input id="inputFileDirectoryChange" type="file" webkitdirectory></input> + +<script type="application/javascript"> + +const { AppConstants } = SpecialPowers.ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +let promptHandler; + +function waitForEvent(element, eventName) { + return new Promise(function(resolve) { + element.addEventListener(eventName, e => resolve(e.detail), { once: true }); + }); +} + +function waitForPromptHandled() { + return new Promise(resolve => promptHandler.addMessageListener("promptAccepted", resolve)); +} + +// Populate the given input type=file `aInputFile`'s `files` attribute by: +// - loading `script_fileList.js` in the parent process +// - telling it to generate the "test" template directory pattern which will +// create "foo.txt", "subdir/bar.txt", and if symlinks are available on the +// platform, "symlink.txt" which will be a symlink to "foo.txt". (Note that +// we explicitly expect the symlink to be filtered out if generated, and +// during the enhancement of the test we verified the file was created on +// linux by running the test before fixing the GetFilesHelper logic to filter +// the symlink out and verifying the subsequent `test_fileList` check failed.) +// - Triggering the mock file picker with the base directory of the "test" +// template directory. +// +// It's expected that `test_fileList` will be used after this step completes in +// order to validate the results. +function populateInputFile(aInputFile) { + var url = SimpleTest.getTestFileURL("script_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + var MockFilePicker = SpecialPowers.MockFilePicker; + MockFilePicker.init(window, "A Mock File Picker", SpecialPowers.Ci.nsIFilePicker.modeGetFolder); + + async function onOpened(message) { + MockFilePicker.useDirectory(message.dir); + + let input = document.getElementById(aInputFile); + input.setAttribute("data-name", message.name); + + let promptHandled = waitForPromptHandled(); + let changeEvent = waitForEvent(input, "change"); + + input.click(); + + await promptHandled; + await changeEvent; + + MockFilePicker.cleanup(); + script.destroy(); + next(); + } + + script.addMessageListener("dir.opened", onOpened); + script.sendAsyncMessage("dir.open", { path: "test" }); +} + +function checkFile(file, fileList, dirName) { + for (var i = 0; i < fileList.length; ++i) { + ok(fileList[i] instanceof File, "We want just files."); + if (fileList[i].name == file.name) { + is(fileList[i].webkitRelativePath, dirName + file.path, "Path matches"); + return; + } + } + + ok(false, "File not found."); +} + +// Validate the contents of the given input type=file `aInputFile`'s' `files` +// property against the expected list of files `aWhat`. +function test_fileList(aInputFile, aWhat) { + var input = document.getElementById(aInputFile); + var fileList = input.files; + + if (aWhat == null) { + is(fileList, null, "We want a null fileList for " + aInputFile); + next(); + return; + } + + is(fileList.length, aWhat.length, "We want just " + aWhat.length + " elements for " + aInputFile); + for (var i = 0; i < aWhat.length; ++i) { + checkFile(aWhat[i], fileList, input.dataset.name); + } + + next(); +} + +// Verify that we can explicitly select a symlink and it will not be filtered +// out. This is really a verification that GetFileHelper's file-handling logic +// https://searchfox.org/mozilla-central/rev/065102493dfc49234120c37fc6a334a5b1d86d9e/dom/filesystem/GetFilesHelper.cpp#81-86 +// does not proactively take an action to filter out a selected symlink. +// +// This is a glass box test that is not entirely realistic for our actual system +// file pickers but does reflect what will happen in the drag-and-drop case +// for `HTMLInputElement::MozSetDndFilesAndDirectories` and this helps ensure +// that future implementation changes will behave as expected. Specifically, +// the presence of webkitdirectory will result in the file picker using +// `modeGetFolder` which will only allow selection of a directory and forbid +// file selection. +// +// This test explicitly does not validate HTMLInputElement's non-webkitdirectory +// file selection mechanism because it does not involve GetFileHelper. +async function test_individualSymlink(aInputFile) { + const input = document.getElementById(aInputFile); + + // -- Create the symlink and get a `File` instance pointing at it. + const url = SimpleTest.getTestFileURL("script_fileList.js"); + const script = SpecialPowers.loadChromeScript(url); + + let opened = new Promise(resolve => script.addMessageListener("symlink.opened", resolve)); + script.sendAsyncMessage("symlink.open", {}); + let { dir, file: symlinkFile } = await opened; + info(`symlink.open provided dir: ${dir}`) + + // -- Have the picker pick it + var MockFilePicker = SpecialPowers.MockFilePicker; + MockFilePicker.init(window, "A Mock File Picker", SpecialPowers.Ci.nsIFilePicker.modeOpen); + + MockFilePicker.displayDirectory = dir; + let pickerShown = new Promise(resolve => { + MockFilePicker.showCallback = function() { + // This is where we are diverging from a realistic scenario in order to get + // the expected coverage. + MockFilePicker.setFiles([symlinkFile]); + resolve(); + } + }); + MockFilePicker.returnValue = MockFilePicker.returnOK; + + let changeEvent = waitForEvent(input, "change"); + + input.click(); + + await pickerShown; + await changeEvent; + + MockFilePicker.cleanup(); + script.destroy(); + + // -- Verify that we see the symlink. + let fileList = input.files; + is(fileList.length, 1, "There should be 1 file."); + is(fileList[0].name, "symlink.txt", "The file should be the symlink."); + next(); +} + +function test_webkitdirectory_attribute() { + var a = document.createElement("input"); + a.setAttribute("type", "file"); + + ok("webkitdirectory" in a, "HTMLInputElement.webkitdirectory exists"); + + ok(!a.hasAttribute("webkitdirectory"), "No webkitdirectory DOM attribute by default"); + ok(!a.webkitdirectory, "No webkitdirectory attribute by default"); + + a.webkitdirectory = true; + + ok(a.hasAttribute("webkitdirectory"), "Webkitdirectory DOM attribute is set"); + ok(a.webkitdirectory, "Webkitdirectory attribute is set"); + + next(); +} + +function test_changeDataWhileWorking() { + var url = SimpleTest.getTestFileURL("script_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + var MockFilePicker = SpecialPowers.MockFilePicker; + MockFilePicker.init(window, "A Mock File Picker", SpecialPowers.Ci.nsIFilePicker.modeGetFolder); + let promptHandled; + + // Let's start retrieving the root nsIFile object + new Promise(function(resolve) { + function onOpened(message) { + script.removeMessageListener("dir.opened", onOpened); + resolve(message.dir); + } + + script.addMessageListener("dir.opened", onOpened); + script.sendAsyncMessage("dir.open", { path: "root" }); + }) + + // input.click() pointing to the root dir + .then(async function(aDir) { + MockFilePicker.cleanup(); + MockFilePicker.init(window, "A Mock File Picker", SpecialPowers.Ci.nsIFilePicker.modeGetFolder); + MockFilePicker.useDirectory(aDir); + var input = document.getElementById("inputFileDirectoryChange"); + + promptHandled = waitForPromptHandled(); + input.click(); + }) + + // Before onchange, let's take the 'test' directory + .then(function() { + return new Promise(function(resolve) { + function onOpened(message) { + script.removeMessageListener("dir.opened", onOpened); + script.destroy(); + resolve(message.dir); + } + + script.addMessageListener("dir.opened", onOpened); + script.sendAsyncMessage("dir.open", { path: "test" }); + }); + }) + + // Now let's click again and wait for onchange. + .then(async function(aDir) { + MockFilePicker.cleanup(); + MockFilePicker.init(window, "A Mock File Picker", SpecialPowers.Ci.nsIFilePicker.modeGetFolder); + MockFilePicker.useDirectory(aDir); + + let input = document.getElementById("inputFileDirectoryChange"); + let changeEvent = waitForEvent(input, "change"); + + input.click(); + + await promptHandled; + await changeEvent; + + MockFilePicker.cleanup(); + }) + .then(function() { + test_fileList("inputFileWebkitDirectory", testDirData); + }); +} + +async function test_setup() { + let promptHandlerUrl = SimpleTest.getTestFileURL("script_promptHandler.js") + promptHandler = SpecialPowers.loadChromeScript(promptHandlerUrl); + + let promptHandlerReady = new Promise(resolve => promptHandler.addMessageListener("initDone", resolve)); + promptHandler.sendAsyncMessage("init"); + await promptHandlerReady; + + SpecialPowers.pushPrefEnv({"set": [["dom.filesystem.pathcheck.disabled", true], + ["dom.webkitBlink.dirPicker.enabled", true]]}, next); +} + +async function test_cleanup() { + let promptHandlerDone = new Promise(resolve => promptHandler.addMessageListener("cleanupDone", resolve)); + promptHandler.sendAsyncMessage("cleanup"); + await promptHandlerDone; + promptHandler.destroy(); +} + +var testDirData = [ { name: "foo.txt", path: "/foo.txt" }, + { name: "bar.txt", path: "/subdir/bar.txt" }]; + +var tests = [ + test_setup, + + function() { populateInputFile("inputFileWebkitDirectory"); }, + + function() { test_fileList("inputFileWebkitDirectory", testDirData); }, + + function() { + // Symlinks are not available on Windows and so will not be created. + if (AppConstants.platform === "win" || AppConstants.platform === "android") { + info("Skipping individual symlink check on Windows and Android."); + next(); + return; + } + + test_individualSymlink("inputFileWebkitFile").catch(err => ok(false, `Problem in symlink case: ${err}`)); + }, + + test_webkitdirectory_attribute, + + test_changeDataWhileWorking, +]; + +async function next() { + if (!tests.length) { + await test_cleanup(); + SimpleTest.finish(); + return; + } + + var test = tests.shift(); + await test(); +} + +SimpleTest.waitForExplicitFinish(); +next(); +</script> +</body> +</html> diff --git a/dom/filesystem/tests/test_worker_basic.html b/dom/filesystem/tests/test_worker_basic.html new file mode 100644 index 0000000000..920f32719b --- /dev/null +++ b/dom/filesystem/tests/test_worker_basic.html @@ -0,0 +1,73 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Directory API in workers</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="filesystem_commons.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> + +<body> +<script type="application/javascript"> + +var fileList; + +function create_fileList() { + fileList = document.createElement("input"); + fileList.setAttribute("type", "file"); + document.body.appendChild(fileList); + + var url = SimpleTest.getTestFileURL("script_fileList.js"); + var script = SpecialPowers.loadChromeScript(url); + + function onOpened(message) { + SpecialPowers.wrap(fileList).mozSetDirectory(message.dir); + script.destroy(); + next(); + } + + script.addMessageListener("dir.opened", onOpened); + script.sendAsyncMessage("dir.open", { path: "test" }); +} + +function test_worker() { + SpecialPowers.wrap(fileList).getFilesAndDirectories().then(function(array) { + array = SpecialPowers.unwrap(array); + var worker = new Worker("worker_basic.js"); + worker.onmessage = function(e) { + if (e.data.type == "finish") { + next(); + return; + } + + if (e.data.type == "test") { + ok(e.data.test, e.data.message); + } + }; + + worker.postMessage(array[0]); + }); +} + +var tests = [ + function() { setup_tests(next); }, + + create_fileList, + test_worker, +]; + +function next() { + if (!tests.length) { + SimpleTest.finish(); + return; + } + + var test = tests.shift(); + test(); +} + +SimpleTest.waitForExplicitFinish(); +next(); +</script> +</body> +</html> diff --git a/dom/filesystem/tests/worker_basic.js b/dom/filesystem/tests/worker_basic.js new file mode 100644 index 0000000000..2771c778fd --- /dev/null +++ b/dom/filesystem/tests/worker_basic.js @@ -0,0 +1,50 @@ +/* eslint-env worker */ +importScripts("filesystem_commons.js"); + +function finish() { + postMessage({ type: "finish" }); +} + +function ok(a, msg) { + postMessage({ type: "test", test: !!a, message: msg }); +} + +function is(a, b, msg) { + ok(a === b, msg); +} + +function isnot(a, b, msg) { + ok(a != b, msg); +} + +var tests = [ + function () { + test_basic(directory, next); + }, + function () { + test_getFilesAndDirectories(directory, true, next); + }, + function () { + test_getFiles(directory, false, next); + }, + function () { + test_getFiles(directory, true, next); + }, +]; + +function next() { + if (!tests.length) { + finish(); + return; + } + + var test = tests.shift(); + test(); +} + +var directory; + +onmessage = function (e) { + directory = e.data; + next(); +}; |