Backed out changeset 0eb72829d870 (bug 1813299) for causing failures on test_basic.html. CLOSED TREE

This commit is contained in:
Iulian Moraru 2023-05-31 19:40:46 +03:00
Родитель 448ccac0b9
Коммит ce13e0678e
6 изменённых файлов: 78 добавлений и 156 удалений

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

@ -317,14 +317,8 @@ nsresult GetDirectoryListingTaskParent::IOWork() {
!currFile) {
break;
}
bool isLink, isSpecial, isFile;
if (NS_WARN_IF(NS_FAILED(currFile->IsSymlink(&isLink)) ||
NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
// Although we allow explicit individual selection of symlinks via the
// file picker, we do not process symlinks in directory traversal. Our
// specific policy decision is documented at
// https://bugzilla.mozilla.org/show_bug.cgi?id=1813299#c20
isLink || isSpecial) {
bool isSpecial, isFile;
if (NS_WARN_IF(NS_FAILED(currFile->IsSpecial(&isSpecial))) || isSpecial) {
continue;
}
if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||

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

@ -266,8 +266,13 @@ nsresult GetFilesHelperBase::ExploreDirectory(const nsAString& aDOMPath,
return NS_OK;
}
nsresult rv = AddExploredDirectory(aFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIDirectoryEnumerator> entries;
nsresult rv = aFile->GetDirectoryEntries(getter_AddRefs(entries));
rv = aFile->GetDirectoryEntries(getter_AddRefs(entries));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -281,12 +286,7 @@ nsresult GetFilesHelperBase::ExploreDirectory(const nsAString& aDOMPath,
bool isLink, isSpecial, isFile, isDir;
if (NS_WARN_IF(NS_FAILED(currFile->IsSymlink(&isLink)) ||
NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
isSpecial ||
// Although we allow explicit individual selection of symlinks via the
// file picker, we do not process symlinks in directory traversal. Our
// specific policy decision is documented at
// https://bugzilla.mozilla.org/show_bug.cgi?id=1813299#c20
isLink) {
isSpecial) {
continue;
}
@ -296,6 +296,11 @@ nsresult GetFilesHelperBase::ExploreDirectory(const nsAString& aDOMPath,
continue;
}
// We don't want to explore loops of links.
if (isDir && isLink && !ShouldFollowSymLink(currFile)) {
continue;
}
// The new domPath
nsAutoString domPath;
domPath.Assign(aDOMPath);
@ -335,6 +340,61 @@ nsresult GetFilesHelperBase::ExploreDirectory(const nsAString& aDOMPath,
return NS_OK;
}
nsresult GetFilesHelperBase::AddExploredDirectory(nsIFile* aDir) {
nsresult rv;
#ifdef DEBUG
bool isDir;
rv = aDir->IsDirectory(&isDir);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(isDir, "Why are we here?");
#endif
bool isLink;
rv = aDir->IsSymlink(&isLink);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoString path;
if (!isLink) {
rv = aDir->GetPath(path);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
rv = aDir->GetTarget(path);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
mExploredDirectories.Insert(path);
return NS_OK;
}
bool GetFilesHelperBase::ShouldFollowSymLink(nsIFile* aDir) {
#ifdef DEBUG
bool isLink, isDir;
if (NS_WARN_IF(NS_FAILED(aDir->IsSymlink(&isLink)) ||
NS_FAILED(aDir->IsDirectory(&isDir)))) {
return false;
}
MOZ_ASSERT(isLink && isDir, "Why are we here?");
#endif
nsAutoString targetPath;
if (NS_WARN_IF(NS_FAILED(aDir->GetTarget(targetPath)))) {
return false;
}
return !mExploredDirectories.Contains(targetPath);
}
void GetFilesHelper::ResolveOrRejectPromise(Promise* aPromise) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mListingCompleted);

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

@ -10,7 +10,9 @@
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h"
#include "nsCycleCollectionTraversalCallback.h"
#include "nsHashKeys.h"
#include "nsTArray.h"
#include "nsTHashSet.h"
#include "nsThreadUtils.h"
class nsIGlobalObject;
@ -49,10 +51,15 @@ class GetFilesHelperBase {
nsresult ExploreDirectory(const nsAString& aDOMPath, nsIFile* aFile);
nsresult AddExploredDirectory(nsIFile* aDirectory);
bool ShouldFollowSymLink(nsIFile* aDirectory);
bool mRecursiveFlag;
// We populate this array in the I/O thread with the BlobImpl.
FallibleTArray<RefPtr<BlobImpl>> mTargetBlobImplArray;
nsTHashSet<nsString> mExploredDirectories;
};
// Retrieving the list of files can be very time/IO consuming. We use this

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

@ -67,10 +67,6 @@ function test_getFilesAndDirectories(aDirectory, aRecursive, aNext) {
"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."
);
}
}
});

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

@ -7,10 +7,6 @@ function createProfDFile() {
.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:
@ -38,15 +34,6 @@ function createTreeFile(depth, parent) {
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, 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") {
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);
@ -75,21 +62,6 @@ function createRootFile() {
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)
@ -109,15 +81,6 @@ function createTestFile() {
file2.append("bar.txt");
file2.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
// It's not possible to create symlinks on windows by default, 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") {
var linkFile = dir.clone();
linkFile.append("symlink.txt");
createSymLink(file1.path, linkFile.path);
}
return tmpFile;
}
@ -160,14 +123,3 @@ addMessageListener("file.open", function (e) {
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 });
});
});

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

@ -8,13 +8,12 @@
<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"
const { AppConstants } = SpecialPowers.ChromeUtils.import(
"resource://gre/modules/AppConstants.jsm"
);
let promptHandler;
@ -29,20 +28,6 @@ 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);
@ -85,8 +70,6 @@ function checkFile(file, fileList, dirName) {
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;
@ -105,65 +88,6 @@ function test_fileList(aInputFile, aWhat) {
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");
@ -275,17 +199,6 @@ var tests = [
function() { test_fileList("inputFileWebkitDirectory", testDirData); },
function() {
// Symlinks are not available on Windows and so will not be created.
if (AppConstants.platform === "win") {
info("Skipping individual symlink check on Windows platforms.");
next();
return;
}
test_individualSymlink("inputFileWebkitFile").catch(err => ok(false, `Problem in symlink case: ${err}`));
},
test_webkitdirectory_attribute,
test_changeDataWhileWorking,