import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1212114 - Stop using dom::Promise::MaybeRejectBrokenly() in various FileSystemTaskBase subclasses. r=baku (9f6ea5db27)
- Bug 1253534 - Suspicious code with probably reversed parms in call to IsSingleLineTextControl, r=mounir (1a5ee1fd1e)
- Bug 769117 - Mochitests for youtube flash -> html5 rewriting; r=bz r=hsivonen (6324471dd9)
- Bug 1250148 - FormData should treat empty input type=file as empty string in FormData and as unnamed Blob in HTML submission, r=smaug (7043113247)
- Bug 1173320 - patch 1/8 - Implement Directory object as string and not as BlobImpl, r=smaug (eca4bec6ea)
- Bug 1173320 - patch 2/8 - Proper naming for the FileSystem path serialization, r=smaug (e1604ff2b1)
- Bug 1173320 - patch 3/8 - Improve the Windows path management, r=smaug (f8da8541b5)
- Bug 1252347 - Provide missing implementations of nsIBaseWindow::SetPositionDesktopPix. r=emk (97f9b92465)
- Bug 1235066 - SVG elements should not display title attributes as tooltips. r=enndeakin (a77e809688)
- Bug 1251809 - Add input[type=file] tooltip support for e10s. r=ehsan (9f72cf3cd2)
- Bug 1173320 - patch 4/8 - Directory in FileList, r=smaug (c09d445043)
- Bug 1246244 - Regression test. r=jaws,Margaret (8de084f9db)
- Bug 1224105 - Allow windowless chrome docshells containing content docshells (r=smaug) (3343a2a966)
- Bug 1230267 - Inconsistent display of SVG title as tooltip when multi-process is enabled. r=jst (b3fc298b7f)
- Bug 1173320 - patch 5/8 - Cleanup manual string path management, r=smaug (8f6f0c4e44)
- Bug 1250403 - Part 1. Define ARCH_CPU_ARM64 instead of ARCH_CPU_AARCH64. r=billm (d93a0b54da)
- Bug 1250403 - Part 2. Import crbug #354405 for aarch64. r=billm (9dca949bcc)
- Bug 1246501 - Add ppc specific atomic operations to ipc/chromium. r=Waldo (8054b612be)
- Bug 1257305 - Avoid VS2015 about casting int to void*. r=dvander (6234acf6fc)
- Bug 1207401 - Send B2G sandbox logging to both stderr and logcat. r=kang (ae404aa5ca)
- Bug 1173320 - patch 6/8 - Make FileList clonable to workers if it doesn't contain Directories, r=smaug (ea6ba42f31)
- Bug 1173320 - patch 7/8 - Tests for FileList and Directories, r=smaug (3f11503300)
- Bug 1222522, part 1 - Make most dom/devicestorage/ tests work with e10s. r=dhylands (3cc7e339a5)
- Bug 1173320 - patch 8/8 - Fix e10s tests for DeviceStorage API, r=smaug (949454bae7)
- Bug 1222522, part 2 - Inline devicestorage_cleanup() in dom/devicestorage/ tests. r=dhylands (bcdee11385)
- Bug 1258137 - OSFileSystem should not be kept alive by more than 1 Directory, r=smaug (225775f48d)
- Bug 1255867. Remove some unnecessary AutoJSAPI uses. r=bholley (618cf018e8)
- Bug 1237173 - Part2: Change type of duration to Maybe<StickyTimeDuration>. r=birtles (6b83473e05)
- Bug 1238469 - Part 1: Refactor b2g emulator tests to remove the usage of custom mozharness configs; r=ahal (a128c8a8bb)
- Bug 1238469 - Part 2: Refactor b2g mulet tests to remove the usage of custom mozharness configs; r=ahal (6c7ced3419)
- Bug 1238469 - Part 3: Use b2g_emulator_unittest.py for b2g marionette tests; r=ahal (5fdb88b0e1)
- Bug 1237173 - Part3: Throw TypeError if duration is NaN, negative value or not 'auto' string. r=birtles, r=smaug (d60b0318d2)
- Bug 1136567 - Marionette test for selection carets' positions after changing orientation of device. r=Automatedtester (e7b25b1e4f)
- Bug 1138839 - Part1 - Marionette test for selecting text inside an iframe. r=automatedtester (45db397a94)
- Bug 1138839 - Part2 - Fix naming issue in marionette test for selection carets. r=automatedtester (c54850d9d3)
- Bug 1198542: Update Marionette element IDs to be valid UUID. r=ato This allows WebDriver compatibility to create valid URI. (1b3de245de)
- Bug 1204496: When searching by link text start from the startNode and not the rootNode; r=ato (0dfa3b8830)
- Bug 1157725 - Rewrite test_mouse_action.py to be more robust. r=ato (40273abca2)
- Bug 1141519: added test that puts marionette into a position that can cause hangs when in content scope; r=jgriffin (c99d8cf325)
- Bug 1246407 - Rename parent directories for Marionette client and test harness; r=automatedtester (79d4e521fd)
- Bug 1253989 Part 3 - Use @parameterized to rewrite selection mode tests. r=mtseng (baf189f1d5)
- Bug 1253989 Part 4 - Rename AccessibleCaret test files. r=mtseng (d562edc8f4)
- Bug 1251519 Part 3 - Add regression tests for caret dragging. r=mats (048dd5f103)
- Bug 1253989 Part 5 - Remove touch caret and selection carets naming. r=mtseng (9929425b6d)
- Bug 1253989 Part 6 - Refactor open_test_html(). r=mtseng (25a2424ca1)
- Bug 1251519 Part 4 - Add tests for dragging caret to content boundary. r=mats (489b47269b)
- Bug 1251519 Part 5 - Use union rect of child frames for clamping. r=mats (5520416749)
- Bug 1216924 - Don't align to tiles (either real or virtual) if displayport suppression is enabled. r=BenWa (d470d188e4)
- Bug 1254273 - Align the displayport to a max of 256 pixels even if the layer is larger. r=BenWa (0cf8cc0b6c)
- Bug 1257938 part 3: Remove support for the "layout.css.sticky.enabled" pref (so we'll unconditionally support "position: sticky"). r=corey (fe12efd18f)
- Bug 1257938 part 1: Adjust automated tests to assume position:sticky is unconditionally supported. r=corey (e749ac579e)
- Bug 1257938 part 2: Remove separation between test_position_sticky.html & its helper-file, now that it doesn't need to tweak a pref. r=corey (631edab31a)
- Bug 1257491 - Ensure that if the peek-messages code modifies the displayport, we schedule a repaint. r=BenWa (d6fb6ff96c)
- Bug 1255006 - Ensure the displayport rect takes priority over a suppressed-margins displayport. r=kats (aa6cbc0250)
- Bug 1259235 - Add IsScrollFrameWithSnapping to speed up event regions. r=mstange (2a744c311e)
- Bug 1185140 - [css-grid][flexbox] Make grid/flex item blockification happen before creating table pseudos, per the latest specs. r=dholbert (dddb8b17ef)
- Bug 1224424 - Replace mask-mode:auto keyword by mask-mode:match-source; r=dbaron (5a51b3b301)
- Bug 1252039 - corrected MOZ_ASSERT expression in SeparatorRequiredBetweenTokens. r=dbaron (08790aa514)
- Bug 1243734 - Part 1. Use MOZ_ENABLE_MASK_AS_SHORTHAND to define the type of mask property; r=dbaron (d8cd3a1c4a)
- Bug 1243734 - Part 2. Set up gCSSProperties depends on mask-as-shorth and; r=dbaron (aa6b0259d8)
- Bug 1243734 - Part 3. Set mask-mode reftest as failure before enable mask-as-shorthand; r=dbaron (6a326fbaf2)
- Bug 1243734 - Part 5. Add MOZ_ENABLE_MASK_AS_SHORTHAND compile flag; r=ted r=dbaron (fcc1344ac8)
- Bug 1142531: Check more bits in nsStyleContext::MoveTo assertion. r=heycam (8b62b139df)
- Bug 1258147 - Pierce through display:contents style context ancestors when looking for CB context to compare our writing-mode to. r=jfkthame (956d8c25e5)
- Bug 823483 patch 1 - Check for percentage max-width in addition to percentage width when deciding to ignore intrinsic min-width of replaced elements. r=dholbert (f88cb5f6a8)
- Bug 823483 patch 3 - Limit effect of percentage width and max-width on intrinsic size to elements with replaced element sizing. r=dholbert (2573c3cfff)
- Bug 823483 patch 4 - Make a percentage max-width override a fixed width for replaced element intrinsic size computation. r=dholbert (dda859f06c)
- Bug 823483 patch 5 - Make (again) percentage width on text inputs make intrinsic minimum width be 0. r=dholbert (d46ada73ef)
- Bug 1247929 patch 2 - Hard-code the Web-compatible set of form controls whose intrinsic minimum inline-size shrinks to 0 when inline-size (width) is specified as a percentage. r=dholbert (e4f0c80fcb)
- Bug 1254968 - Add support for running JS builtins' constructors over Xray wrappers without unwrapping the newTarget. r=bholley,f=bz (56213ae395)
- Bug 1249123 - Add telemetry for __defineGetter__/__defineSetter__ |this| values. data-review=bsmedberg r=till (52c5fd3488)
- Bug 1232639 - Implement Object.{values,entries} in C++ to avoid native call overhead in tight loop. r=jorendorff (7262497283)
- Bug 1254966 - Disambiguate JS Telemetry macro names. r=evilpie (781d0916c4)
- Bug 1254384: Use generic shell switch syntax in js/src/jit-test tests. r=nbp (6f5975cc55)
- Bug 1253016 - Remove legacy __defineGetter__/__defineSetter__ this behavior. r=till (cf1b7ad28c)
- Bug 1253016 - Implement and test the new spec for legacy functions. r=till (1ff7762e3e)
This commit is contained in:
2024-02-28 12:10:08 +08:00
parent baacd3ba62
commit cf2d7d1ae9
566 changed files with 7128 additions and 5646 deletions
+250 -135
View File
@@ -11,8 +11,6 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/Date.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/OSFileSystem.h"
#include "nsAttrValueInlines.h"
#include "nsCRTGlue.h"
@@ -251,16 +249,63 @@ class HTMLInputElementState final : public nsISupports
mValue = aValue;
}
const nsTArray<RefPtr<BlobImpl>>& GetBlobImpls()
void
GetFilesOrDirectories(nsPIDOMWindow* aWindow,
nsTArray<OwningFileOrDirectory>& aResult) const
{
return mBlobImpls;
for (uint32_t i = 0; i < mBlobImplsOrDirectoryPaths.Length(); ++i) {
if (mBlobImplsOrDirectoryPaths[i].mType == Directory::BlobImplOrDirectoryPath::eBlobImpl) {
RefPtr<File> file =
File::Create(aWindow,
mBlobImplsOrDirectoryPaths[i].mBlobImpl);
MOZ_ASSERT(file);
OwningFileOrDirectory* element = aResult.AppendElement();
element->SetAsFile() = file;
} else {
MOZ_ASSERT(mBlobImplsOrDirectoryPaths[i].mType == Directory::BlobImplOrDirectoryPath::eDirectoryPath);
nsCOMPtr<nsIFile> file;
NS_ConvertUTF16toUTF8 path(mBlobImplsOrDirectoryPaths[i].mDirectoryPath);
nsresult rv = NS_NewNativeLocalFile(path, true, getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
RefPtr<Directory> directory = Directory::Create(aWindow, file,
Directory::eDOMRootDirectory);
MOZ_ASSERT(directory);
OwningFileOrDirectory* element = aResult.AppendElement();
element->SetAsDirectory() = directory;
}
}
}
void SetBlobImpls(const nsTArray<RefPtr<File>>& aFile)
void SetFilesOrDirectories(const nsTArray<OwningFileOrDirectory>& aArray)
{
mBlobImpls.Clear();
for (uint32_t i = 0, len = aFile.Length(); i < len; ++i) {
mBlobImpls.AppendElement(aFile[i]->Impl());
mBlobImplsOrDirectoryPaths.Clear();
for (uint32_t i = 0; i < aArray.Length(); ++i) {
if (aArray[i].IsFile()) {
Directory::BlobImplOrDirectoryPath* data =
mBlobImplsOrDirectoryPaths.AppendElement();
data->mBlobImpl = aArray[i].GetAsFile()->Impl();
data->mType = Directory::BlobImplOrDirectoryPath::eBlobImpl;
} else {
MOZ_ASSERT(aArray[i].IsDirectory());
nsAutoString fullPath;
nsresult rv = aArray[i].GetAsDirectory()->GetFullRealPath(fullPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
Directory::BlobImplOrDirectoryPath* data =
mBlobImplsOrDirectoryPaths.AppendElement();
data->mDirectoryPath = fullPath;
data->mType = Directory::BlobImplOrDirectoryPath::eDirectoryPath;
}
}
}
@@ -274,7 +319,9 @@ class HTMLInputElementState final : public nsISupports
~HTMLInputElementState() {}
nsString mValue;
nsTArray<RefPtr<BlobImpl>> mBlobImpls;
nsTArray<Directory::BlobImplOrDirectoryPath> mBlobImplsOrDirectoryPaths;
bool mChecked;
bool mCheckedSet;
};
@@ -340,33 +387,65 @@ UploadLastDir::ContentPrefCallback::HandleError(nsresult error)
namespace {
/**
* This may return nullptr if aDomFile's implementation of
* This may return nullptr if the DOM File's implementation of
* File::mozFullPathInternal does not successfully return a non-empty
* string that is a valid path. This can happen on Firefox OS, for example,
* where the file picker can create Blobs.
*/
static already_AddRefed<nsIFile>
DOMFileToLocalFile(File* aDomFile)
DOMFileOrDirectoryToLocalFile(const OwningFileOrDirectory& aData)
{
nsString path;
ErrorResult rv;
aDomFile->GetMozFullPathInternal(path, rv);
if (rv.Failed() || path.IsEmpty()) {
rv.SuppressException();
return nullptr;
if (aData.IsFile()) {
ErrorResult rv;
aData.GetAsFile()->GetMozFullPathInternal(path, rv);
if (rv.Failed() || path.IsEmpty()) {
rv.SuppressException();
return nullptr;
}
} else {
MOZ_ASSERT(aData.IsDirectory());
aData.GetAsDirectory()->GetFullRealPath(path);
}
nsCOMPtr<nsIFile> localFile;
rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
getter_AddRefs(localFile));
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
getter_AddRefs(localFile));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
return localFile.forget();
}
void
GetDOMFileOrDirectoryName(const OwningFileOrDirectory& aData,
nsAString& aName)
{
if (aData.IsFile()) {
aData.GetAsFile()->GetName(aName);
} else {
MOZ_ASSERT(aData.IsDirectory());
ErrorResult rv;
aData.GetAsDirectory()->GetName(aName, rv);
NS_WARN_IF(rv.Failed());
}
}
void
GetDOMFileOrDirectoryPath(const OwningFileOrDirectory& aData,
nsAString& aPath,
ErrorResult& aRv)
{
if (aData.IsFile()) {
aData.GetAsFile()->GetMozFullPathInternal(aPath, aRv);
} else {
MOZ_ASSERT(aData.IsDirectory());
aData.GetAsDirectory()->GetFullRealPath(aPath);
}
}
} // namespace
@@ -383,7 +462,7 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
mFilePicker->GetMode(&mode);
// Collect new selected filenames
nsTArray<RefPtr<File>> newFiles;
nsTArray<OwningFileOrDirectory> newFilesOrDirectories;
if (mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)) {
nsCOMPtr<nsISimpleEnumerator> iter;
nsresult rv =
@@ -402,9 +481,12 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(tmp);
MOZ_ASSERT(domBlob,
"Null file object from FilePicker's file enumerator?");
if (domBlob) {
newFiles.AppendElement(static_cast<File*>(domBlob.get()));
if (!domBlob) {
continue;
}
OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
element->SetAsFile() = static_cast<File*>(domBlob.get());
}
} else {
MOZ_ASSERT(mode == static_cast<int16_t>(nsIFilePicker::modeOpen) ||
@@ -416,16 +498,25 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(tmp);
if (blob) {
RefPtr<File> file = static_cast<Blob*>(blob.get())->ToFile();
newFiles.AppendElement(file);
MOZ_ASSERT(file);
OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
element->SetAsFile() = file;
} else if (tmp) {
RefPtr<Directory> directory = static_cast<Directory*>(tmp.get());
OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
element->SetAsDirectory() = directory;
}
}
if (newFiles.IsEmpty()) {
if (newFilesOrDirectories.IsEmpty()) {
return NS_OK;
}
// Store the last used directory using the content pref service:
nsCOMPtr<nsIFile> file = DOMFileToLocalFile(newFiles[0]);
nsCOMPtr<nsIFile> file =
DOMFileOrDirectoryToLocalFile(newFilesOrDirectories[0]);
if (file) {
nsCOMPtr<nsIFile> lastUsedDir;
file->GetParent(getter_AddRefs(lastUsedDir));
@@ -436,7 +527,7 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
// The text control frame (if there is one) isn't going to send a change
// event because it will think this is done by a script.
// So, we can safely send one by ourself.
mInput->SetFiles(newFiles, true);
mInput->SetFilesOrDirectories(newFilesOrDirectories, true);
return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
NS_LITERAL_STRING("change"), true,
@@ -672,7 +763,8 @@ HTMLInputElement::InitFilePicker(FilePickerType aType)
// Set default directry and filename
nsAutoString defaultName;
const nsTArray<RefPtr<File>>& oldFiles = GetFilesInternal();
const nsTArray<OwningFileOrDirectory>& oldFiles =
GetFilesOrDirectoriesInternal();
nsCOMPtr<nsIFilePickerShownCallback> callback =
new HTMLInputElement::nsFilePickerShownCallback(this, filePicker);
@@ -681,18 +773,10 @@ HTMLInputElement::InitFilePicker(FilePickerType aType)
aType != FILE_PICKER_DIRECTORY) {
nsString path;
ErrorResult error;
oldFiles[0]->GetMozFullPathInternal(path, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
nsCOMPtr<nsIFile> localFile;
rv = NS_NewLocalFile(path, false, getter_AddRefs(localFile));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFile> localFile = DOMFileOrDirectoryToLocalFile(oldFiles[0]);
if (localFile) {
nsCOMPtr<nsIFile> parentFile;
rv = localFile->GetParent(getter_AddRefs(parentFile));
nsresult rv = localFile->GetParent(getter_AddRefs(parentFile));
if (NS_SUCCEEDED(rv)) {
filePicker->SetDisplayDirectory(parentFile);
}
@@ -703,7 +787,8 @@ HTMLInputElement::InitFilePicker(FilePickerType aType)
// one file was selected before.
if (oldFiles.Length() == 1) {
nsAutoString leafName;
oldFiles[0]->GetName(leafName);
GetDOMFileOrDirectoryName(oldFiles[0], leafName);
if (!leafName.IsEmpty()) {
filePicker->SetDefaultString(leafName);
}
@@ -756,7 +841,7 @@ UploadLastDir::FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
NS_PRECONDITION(docURI, "docURI is null");
nsCOMPtr<nsILoadContext> loadContext = aDoc->GetLoadContext();
nsCOMPtr<nsIContentPrefCallback2> prefCallback =
nsCOMPtr<nsIContentPrefCallback2> prefCallback =
new UploadLastDir::ContentPrefCallback(aFilePicker, aFpCallback);
#ifdef MOZ_B2G
@@ -936,7 +1021,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLInputElement,
if (tmp->IsSingleLineTextControl(false)) {
tmp->mInputData.mState->Traverse(cb);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFilesOrDirectories)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFilesAndDirectoriesPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -945,7 +1030,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLInputElement,
nsGenericHTMLFormElementWithState)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilesOrDirectories)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileList)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilesAndDirectoriesPromise)
if (tmp->IsSingleLineTextControl(false)) {
@@ -1004,8 +1089,8 @@ HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) co
// we can just grab the pretty string and use it as wallpaper
GetDisplayFileName(it->mStaticDocFileList);
} else {
it->mFiles.Clear();
it->mFiles.AppendElements(mFiles);
it->mFilesOrDirectories.Clear();
it->mFilesOrDirectories.AppendElements(mFilesOrDirectories);
}
break;
case VALUE_MODE_DEFAULT_ON:
@@ -1454,9 +1539,9 @@ HTMLInputElement::GetValueInternal(nsAString& aValue) const
#else
// XXX We'd love to assert that this can't happen, but some mochitests
// use SpecialPowers to circumvent our more sane security model.
if (!mFiles.IsEmpty()) {
if (!mFilesOrDirectories.IsEmpty()) {
ErrorResult rv;
mFiles[0]->GetMozFullPath(aValue, rv);
GetDOMFileOrDirectoryPath(mFilesOrDirectories[0], aValue, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
@@ -1468,10 +1553,10 @@ HTMLInputElement::GetValueInternal(nsAString& aValue) const
#endif
} else {
// Just return the leaf name
if (mFiles.IsEmpty()) {
if (mFilesOrDirectories.IsEmpty()) {
aValue.Truncate();
} else {
mFiles[0]->GetName(aValue);
GetDOMFileOrDirectoryName(mFilesOrDirectories[0], aValue);
}
}
@@ -1506,8 +1591,8 @@ HTMLInputElement::IsValueEmpty() const
void
HTMLInputElement::ClearFiles(bool aSetValueChanged)
{
nsTArray<RefPtr<File>> files;
SetFiles(files, aSetValueChanged);
nsTArray<OwningFileOrDirectory> data;
SetFilesOrDirectories(data, aSetValueChanged);
}
/* static */ Decimal
@@ -2077,9 +2162,9 @@ void
HTMLInputElement::MozGetFileNameArray(nsTArray<nsString>& aArray,
ErrorResult& aRv)
{
for (uint32_t i = 0; i < mFiles.Length(); i++) {
nsString str;
mFiles[i]->GetMozFullPathInternal(str, aRv);
for (uint32_t i = 0; i < mFilesOrDirectories.Length(); i++) {
nsAutoString str;
GetDOMFileOrDirectoryPath(mFilesOrDirectories[i], str, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -2129,25 +2214,29 @@ HTMLInputElement::MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles)
if (!global) {
return;
}
nsTArray<RefPtr<File>> files;
nsTArray<OwningFileOrDirectory> files;
for (uint32_t i = 0; i < aFiles.Length(); ++i) {
RefPtr<File> file = File::Create(global, aFiles[i].get()->Impl());
MOZ_ASSERT(file);
files.AppendElement(file);
OwningFileOrDirectory* element = files.AppendElement();
element->SetAsFile() = file;
}
SetFiles(files, true);
SetFilesOrDirectories(files, true);
}
void
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv)
HTMLInputElement::MozSetFileNameArray(const Sequence<nsString>& aFileNames,
ErrorResult& aRv)
{
if (XRE_IsContentProcess()) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
nsTArray<RefPtr<File>> files;
nsTArray<OwningFileOrDirectory> files;
for (uint32_t i = 0; i < aFileNames.Length(); ++i) {
nsCOMPtr<nsIFile> file;
@@ -2164,21 +2253,28 @@ HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames, Er
NS_NewLocalFile(aFileNames[i], false, getter_AddRefs(file));
}
if (file) {
nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
RefPtr<File> domFile = File::CreateFromFile(global, file);
files.AppendElement(domFile);
} else {
if (!file) {
continue; // Not much we can do if the file doesn't exist
}
nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
RefPtr<File> domFile = File::CreateFromFile(global, file);
OwningFileOrDirectory* element = files.AppendElement();
element->SetAsFile() = domFile;
}
SetFiles(files, true);
SetFilesOrDirectories(files, true);
}
NS_IMETHODIMP
HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames, uint32_t aLength)
HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames,
uint32_t aLength)
{
if (!nsContentUtils::IsCallerChrome()) {
// setting the value of a "FILE" input widget requires chrome privilege
@@ -2200,6 +2296,34 @@ HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames, uint32_t aLen
return rv.StealNSResult();
}
void
HTMLInputElement::MozSetDirectory(const nsAString& aDirectoryPath,
ErrorResult& aRv)
{
nsCOMPtr<nsIFile> file;
NS_ConvertUTF16toUTF8 path(aDirectoryPath);
aRv = NS_NewNativeLocalFile(path, true, getter_AddRefs(file));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsPIDOMWindow* window = OwnerDoc()->GetInnerWindow();
if (NS_WARN_IF(!window)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
RefPtr<Directory> directory = Directory::Create(window, file,
Directory::eDOMRootDirectory);
MOZ_ASSERT(directory);
nsTArray<OwningFileOrDirectory> array;
OwningFileOrDirectory* element = array.AppendElement();
element->SetAsDirectory() = directory;
SetFilesOrDirectories(array, true);
}
bool
HTMLInputElement::MozIsTextField(bool aExcludePassword)
{
@@ -2391,14 +2515,14 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
return;
}
if (mFiles.Length() == 1) {
mFiles[0]->GetName(aValue);
if (mFilesOrDirectories.Length() == 1) {
GetDOMFileOrDirectoryName(mFilesOrDirectories[0], aValue);
return;
}
nsXPIDLString value;
if (mFiles.IsEmpty()) {
if (mFilesOrDirectories.IsEmpty()) {
if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"NoFilesSelected", value);
@@ -2408,7 +2532,7 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
}
} else {
nsString count;
count.AppendInt(int(mFiles.Length()));
count.AppendInt(int(mFilesOrDirectories.Length()));
const char16_t* params[] = { count.get() };
nsContentUtils::FormatLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
@@ -2419,13 +2543,13 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
}
void
HTMLInputElement::SetFiles(const nsTArray<RefPtr<File>>& aFiles,
bool aSetValueChanged)
HTMLInputElement::SetFilesOrDirectories(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories,
bool aSetValueChanged)
{
mFiles.Clear();
mFiles.AppendElements(aFiles);
mFilesOrDirectories.Clear();
mFilesOrDirectories.AppendElements(aFilesOrDirectories);
AfterSetFiles(aSetValueChanged);
AfterSetFilesOrDirectories(aSetValueChanged);
}
void
@@ -2433,22 +2557,22 @@ HTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
bool aSetValueChanged)
{
RefPtr<FileList> files = static_cast<FileList*>(aFiles);
mFiles.Clear();
mFilesOrDirectories.Clear();
if (aFiles) {
uint32_t listLength;
aFiles->GetLength(&listLength);
for (uint32_t i = 0; i < listLength; i++) {
RefPtr<File> file = files->Item(i);
mFiles.AppendElement(file);
OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
*element = files->UnsafeItem(i);
}
}
AfterSetFiles(aSetValueChanged);
AfterSetFilesOrDirectories(aSetValueChanged);
}
void
HTMLInputElement::AfterSetFiles(bool aSetValueChanged)
HTMLInputElement::AfterSetFilesOrDirectories(bool aSetValueChanged)
{
// No need to flush here, if there's no frame at this point we
// don't need to force creation of one just to tell it about this
@@ -2466,11 +2590,11 @@ HTMLInputElement::AfterSetFiles(bool aSetValueChanged)
// call under GetMozFullPath won't be rejected for not being urgent.
// XXX Protected by the ifndef because the blob code doesn't allow us to send
// this message in b2g.
if (mFiles.IsEmpty()) {
if (mFilesOrDirectories.IsEmpty()) {
mFirstFilePath.Truncate();
} else {
ErrorResult rv;
mFiles[0]->GetMozFullPath(mFirstFilePath, rv);
GetDOMFileOrDirectoryPath(mFilesOrDirectories[0], mFirstFilePath, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
}
@@ -2544,24 +2668,27 @@ HTMLInputElement::HandleNumberControlSpin(void* aData)
}
}
nsresult
void
HTMLInputElement::UpdateFileList()
{
if (mFileList) {
mFileList->Clear();
const nsTArray<RefPtr<File>>& files = GetFilesInternal();
for (uint32_t i = 0; i < files.Length(); ++i) {
if (!mFileList->Append(files[i])) {
return NS_ERROR_FAILURE;
const nsTArray<OwningFileOrDirectory>& array =
GetFilesOrDirectoriesInternal();
for (uint32_t i = 0; i < array.Length(); ++i) {
if (array[i].IsFile()) {
mFileList->Append(array[i].GetAsFile());
} else {
MOZ_ASSERT(array[i].IsDirectory());
mFileList->Append(array[i].GetAsDirectory());
}
}
}
// Make sure we (lazily) create a new Promise for GetFilesAndDirectories:
mFilesAndDirectoriesPromise = nullptr;
return NS_OK;
}
nsresult
@@ -3990,7 +4117,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
nsNumberControlFrame* numberControlFrame =
do_QueryFrame(GetPrimaryFrame());
if (numberControlFrame) {
if (aVisitor.mEvent->mMessage == eMouseDown &&
if (aVisitor.mEvent->mMessage == eMouseDown &&
IsMutable()) {
switch (numberControlFrame->GetSpinButtonForPointerEvent(
aVisitor.mEvent->AsMouseEvent())) {
@@ -4359,8 +4486,8 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType)
// previous type does, we should clear out mFocusedValue.
if (MayFireChangeOnBlur(mType) && !MayFireChangeOnBlur(oldType)) {
GetValue(mFocusedValue);
} else if (!IsSingleLineTextControl(mType, false) &&
IsSingleLineTextControl(oldType, false)) {
} else if (!IsSingleLineTextControl(false, mType) &&
IsSingleLineTextControl(false, oldType)) {
mFocusedValue.Truncate();
}
@@ -4541,7 +4668,7 @@ HTMLInputElement::GetValueAsDate(const nsAString& aValue,
}
uint32_t endOfYearOffset = aValue.Length() - 6;
if (aValue[endOfYearOffset] != '-' ||
aValue[endOfYearOffset + 3] != '-') {
return false;
@@ -4909,45 +5036,38 @@ HTMLInputElement::GetFilesAndDirectories(ErrorResult& aRv)
return nullptr;
}
const nsTArray<RefPtr<File>>& filesAndDirs = GetFilesInternal();
const nsTArray<OwningFileOrDirectory>& filesAndDirs =
GetFilesOrDirectoriesInternal();
Sequence<OwningFileOrDirectory> filesAndDirsSeq;
if (!filesAndDirsSeq.SetLength(filesAndDirs.Length(), mozilla::fallible_t())) {
if (!filesAndDirsSeq.SetLength(filesAndDirs.Length(),
mozilla::fallible_t())) {
p->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
return p.forget();
}
for (uint32_t i = 0; i < filesAndDirs.Length(); ++i) {
if (filesAndDirs[i]->IsDirectory()) {
if (filesAndDirs[i].IsDirectory()) {
#if defined(ANDROID) || defined(MOZ_B2G)
MOZ_ASSERT(false,
"Directory picking should have been redirected to normal "
"file picking for platforms that don't have a directory "
"picker");
#endif
nsAutoString path;
filesAndDirs[i]->GetMozFullPathInternal(path, aRv);
if (aRv.Failed()) {
return nullptr;
}
int32_t leafSeparatorIndex = path.RFind(FILE_PATH_SEPARATOR);
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
RefPtr<OSFileSystem> fs = new OSFileSystem(dirname);
fs->Init(OwnerDoc()->GetInnerWindow());
RefPtr<Directory> directory = filesAndDirs[i].GetAsDirectory();
nsAutoString dompath(NS_LITERAL_STRING(FILESYSTEM_DOM_PATH_SEPARATOR));
dompath.Append(Substring(path, leafSeparatorIndex + 1));
RefPtr<Directory> directory = new Directory(fs, dompath);
// In future we could refactor SetFilePickerFiltersFromAccept to return a
// semicolon separated list of file extensions and include that in the
// filter string passed here.
directory->SetContentFilters(NS_LITERAL_STRING("filter-out-sensitive"));
filesAndDirsSeq[i].SetAsDirectory() = directory;
} else {
MOZ_ASSERT(filesAndDirs[i].IsFile());
// This file was directly selected by the user, so don't filter it.
filesAndDirsSeq[i].SetAsFile() = filesAndDirs[i];
filesAndDirsSeq[i].SetAsFile() = filesAndDirs[i].GetAsFile();
}
}
@@ -5581,17 +5701,19 @@ HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
if (mType == NS_FORM_INPUT_FILE) {
// Submit files
const nsTArray<RefPtr<File>>& files = GetFilesInternal();
const nsTArray<OwningFileOrDirectory>& files =
GetFilesOrDirectoriesInternal();
bool hasBlobs = false;
for (uint32_t i = 0; i < files.Length(); ++i) {
aFormSubmission->AddNameBlobPair(name, files[i]);
if (files[i].IsFile()) {
hasBlobs = true;
aFormSubmission->AddNameBlobOrNullPair(name, files[i].GetAsFile());
}
}
if (files.IsEmpty()) {
RefPtr<BlobImpl> blobImpl =
new EmptyBlobImpl(NS_LITERAL_STRING("application/octet-stream"));
RefPtr<Blob> blob = Blob::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
aFormSubmission->AddNameBlobPair(name, blob);
if (!hasBlobs) {
aFormSubmission->AddNameBlobOrNullPair(name, nullptr);
}
return NS_OK;
@@ -5624,9 +5746,9 @@ HTMLInputElement::SaveState()
}
break;
case VALUE_MODE_FILENAME:
if (!mFiles.IsEmpty()) {
if (!mFilesOrDirectories.IsEmpty()) {
inputState = new HTMLInputElementState();
inputState->SetBlobImpls(mFiles);
inputState->SetFilesOrDirectories(mFilesOrDirectories);
}
break;
case VALUE_MODE_VALUE:
@@ -5795,7 +5917,7 @@ HTMLInputElement::AddStates(EventStates aStates)
}
}
}
nsGenericHTMLFormElementWithState::AddStates(aStates);
nsGenericHTMLFormElementWithState::AddStates(aStates);
}
void
@@ -5832,20 +5954,13 @@ HTMLInputElement::RestoreState(nsPresState* aState)
break;
case VALUE_MODE_FILENAME:
{
const nsTArray<RefPtr<BlobImpl>>& blobImpls = inputState->GetBlobImpls();
nsPIDOMWindow* window = OwnerDoc()->GetInnerWindow();
if (window) {
nsTArray<OwningFileOrDirectory> array;
inputState->GetFilesOrDirectories(window, array);
nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
MOZ_ASSERT(global);
nsTArray<RefPtr<File>> files;
for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
RefPtr<File> file = File::Create(global, blobImpls[i]);
MOZ_ASSERT(file);
files.AppendElement(file);
SetFilesOrDirectories(array, true);
}
SetFiles(files, true);
}
break;
case VALUE_MODE_VALUE:
@@ -6355,15 +6470,15 @@ HTMLInputElement::IsValueMissing() const
switch (GetValueMode()) {
case VALUE_MODE_VALUE:
return IsValueEmpty();
case VALUE_MODE_FILENAME:
{
const nsTArray<RefPtr<File>>& files = GetFilesInternal();
return files.IsEmpty();
}
return GetFilesOrDirectoriesInternal().IsEmpty();
case VALUE_MODE_DEFAULT_ON:
// This should not be used for type radio.
// See the MOZ_ASSERT at the beginning of the method.
return !mChecked;
case VALUE_MODE_DEFAULT:
default:
return false;