Bug 1173320 - patch 1/8 - Implement Directory object as string and not as BlobImpl, r=smaug
This commit is contained in:
@@ -251,16 +251,63 @@ class HTMLInputElementState final : public nsISupports
|
||||
mValue = aValue;
|
||||
}
|
||||
|
||||
const nsTArray<RefPtr<BlobImpl>>& GetBlobImpls()
|
||||
void
|
||||
GetFilesOrDirectories(nsPIDOMWindowInner* 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 +321,9 @@ class HTMLInputElementState final : public nsISupports
|
||||
~HTMLInputElementState() {}
|
||||
|
||||
nsString mValue;
|
||||
nsTArray<RefPtr<BlobImpl>> mBlobImpls;
|
||||
|
||||
nsTArray<Directory::BlobImplOrDirectoryPath> mBlobImplsOrDirectoryPaths;
|
||||
|
||||
bool mChecked;
|
||||
bool mCheckedSet;
|
||||
};
|
||||
@@ -340,33 +389,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 +464,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 +483,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 +500,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 +529,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 +765,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 +775,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 +789,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 +843,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
|
||||
@@ -935,7 +1022,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
|
||||
@@ -944,7 +1031,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)) {
|
||||
@@ -1003,8 +1090,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:
|
||||
@@ -1442,9 +1529,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();
|
||||
}
|
||||
@@ -1456,10 +1543,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1494,8 +1581,8 @@ HTMLInputElement::IsValueEmpty() const
|
||||
void
|
||||
HTMLInputElement::ClearFiles(bool aSetValueChanged)
|
||||
{
|
||||
nsTArray<RefPtr<File>> files;
|
||||
SetFiles(files, aSetValueChanged);
|
||||
nsTArray<OwningFileOrDirectory> data;
|
||||
SetFilesOrDirectories(data, aSetValueChanged);
|
||||
}
|
||||
|
||||
/* static */ Decimal
|
||||
@@ -2065,9 +2152,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;
|
||||
}
|
||||
@@ -2117,25 +2204,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;
|
||||
|
||||
@@ -2152,21 +2243,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
|
||||
@@ -2379,14 +2477,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);
|
||||
@@ -2396,7 +2494,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,
|
||||
@@ -2407,13 +2505,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
|
||||
@@ -2421,22 +2519,24 @@ 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->SetAsFile() = file;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -2454,11 +2554,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();
|
||||
}
|
||||
@@ -2538,9 +2638,11 @@ 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])) {
|
||||
const nsTArray<OwningFileOrDirectory>& array =
|
||||
GetFilesOrDirectoriesInternal();
|
||||
|
||||
for (uint32_t i = 0; i < array.Length(); ++i) {
|
||||
if (array[i].IsFile() && !mFileList->Append(array[i].GetAsFile())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -3975,7 +4077,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())) {
|
||||
@@ -4526,7 +4628,7 @@ HTMLInputElement::GetValueAsDate(const nsAString& aValue,
|
||||
}
|
||||
|
||||
uint32_t endOfYearOffset = aValue.Length() - 6;
|
||||
|
||||
|
||||
if (aValue[endOfYearOffset] != '-' ||
|
||||
aValue[endOfYearOffset + 3] != '-') {
|
||||
return false;
|
||||
@@ -4894,45 +4996,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5566,13 +5661,18 @@ 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->AddNameBlobOrNullPair(name, files[i]);
|
||||
if (files[i].IsFile()) {
|
||||
hasBlobs = true;
|
||||
aFormSubmission->AddNameBlobOrNullPair(name, files[i].GetAsFile());
|
||||
}
|
||||
}
|
||||
|
||||
if (files.IsEmpty()) {
|
||||
if (!hasBlobs) {
|
||||
aFormSubmission->AddNameBlobOrNullPair(name, nullptr);
|
||||
}
|
||||
|
||||
@@ -5606,9 +5706,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:
|
||||
@@ -5777,7 +5877,7 @@ HTMLInputElement::AddStates(EventStates aStates)
|
||||
}
|
||||
}
|
||||
}
|
||||
nsGenericHTMLFormElementWithState::AddStates(aStates);
|
||||
nsGenericHTMLFormElementWithState::AddStates(aStates);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -5814,20 +5914,13 @@ HTMLInputElement::RestoreState(nsPresState* aState)
|
||||
break;
|
||||
case VALUE_MODE_FILENAME:
|
||||
{
|
||||
const nsTArray<RefPtr<BlobImpl>>& blobImpls = inputState->GetBlobImpls();
|
||||
nsPIDOMWindowInner* 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:
|
||||
@@ -6337,15 +6430,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;
|
||||
|
||||
Reference in New Issue
Block a user