mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 565274 - Implement the accept attribute for the form and file upload controls for custom MIME types. r=sicking
This commit is contained in:
parent
b5ff7b1465
commit
6a8c770aec
@ -48,6 +48,7 @@
|
||||
#include "nsIPhonetic.h"
|
||||
|
||||
#include "nsIControllers.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsContentCID.h"
|
||||
@ -106,6 +107,7 @@
|
||||
#include "nsIFilePicker.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIContentPrefService.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPopupWindowManager.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
@ -304,19 +306,7 @@ AsyncClickHandler::Run()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) {
|
||||
PRInt32 filters = mInput->GetFilterFromAccept();
|
||||
|
||||
if (filters) {
|
||||
// We add |filterAll| to be sure the user always has a sane fallback.
|
||||
filePicker->AppendFilters(filters | nsIFilePicker::filterAll);
|
||||
|
||||
// If the accept attribute asked for a filter, we need to make it default.
|
||||
// |filterAll| will always use index=0 so we need to set index=1 as the
|
||||
// current filter.
|
||||
filePicker->SetFilterIndex(1);
|
||||
} else {
|
||||
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
||||
}
|
||||
mInput->SetFilePickerFiltersFromAccept(filePicker);
|
||||
} else {
|
||||
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
||||
}
|
||||
@ -4144,6 +4134,122 @@ nsHTMLInputElement::FieldSetDisabledChanged(bool aNotify)
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLInputElement::SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker)
|
||||
{
|
||||
// We always add |filterAll|
|
||||
filePicker->AppendFilters(nsIFilePicker::filterAll);
|
||||
|
||||
NS_ASSERTION(HasAttr(kNameSpaceID_None, nsGkAtoms::accept),
|
||||
"You should not call SetFilePickerFiltersFromAccept if the"
|
||||
" element has no accept attribute!");
|
||||
nsAutoString accept;
|
||||
nsTArray<nsFilePickerFilter> filters;
|
||||
nsString allExtensionsList;
|
||||
|
||||
// Services to retrieve image/*, audio/*, video/* filters
|
||||
nsCOMPtr<nsIStringBundleService> stringService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (!stringService)
|
||||
return;
|
||||
nsCOMPtr<nsIStringBundle> titleBundle, filterBundle;
|
||||
nsresult rv = stringService->CreateBundle("chrome://global/locale/filepicker.properties",
|
||||
getter_AddRefs(titleBundle));
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
rv = stringService->CreateBundle("chrome://global/content/filepicker.properties",
|
||||
getter_AddRefs(filterBundle));
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
// Service to retrieve mime type information for mime types filters
|
||||
nsCOMPtr<nsIMIMEService> mimeService = do_GetService("@mozilla.org/mime;1");
|
||||
if (!mimeService)
|
||||
return;
|
||||
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::accept, accept);
|
||||
|
||||
HTMLSplitOnSpacesTokenizer tokenizer(accept, ',');
|
||||
|
||||
// Retrieve all filters
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentSubstring& token = tokenizer.nextToken();
|
||||
|
||||
nsString filterName;
|
||||
nsString extensionListStr;
|
||||
bool isTrustedFilter = false;
|
||||
|
||||
// First, check for image/audio/video filters...
|
||||
if (token.EqualsLiteral("image/*")) {
|
||||
titleBundle->GetStringFromName(NS_LITERAL_STRING("imageTitle").get(), getter_Copies(filterName));
|
||||
filterBundle->GetStringFromName(NS_LITERAL_STRING("imageFilter").get(), getter_Copies(extensionListStr));
|
||||
isTrustedFilter = true;
|
||||
} else if (token.EqualsLiteral("audio/*")) {
|
||||
titleBundle->GetStringFromName(NS_LITERAL_STRING("audioTitle").get(), getter_Copies(filterName));
|
||||
filterBundle->GetStringFromName(NS_LITERAL_STRING("audioFilter").get(), getter_Copies(extensionListStr));
|
||||
isTrustedFilter = true;
|
||||
} else if (token.EqualsLiteral("video/*")) {
|
||||
titleBundle->GetStringFromName(NS_LITERAL_STRING("videoTitle").get(), getter_Copies(filterName));
|
||||
filterBundle->GetStringFromName(NS_LITERAL_STRING("videoFilter").get(), getter_Copies(extensionListStr));
|
||||
isTrustedFilter = true;
|
||||
} else {
|
||||
//... if no image/audio/video filter is found, check mime types filters
|
||||
nsCOMPtr<nsIMIMEInfo> mimeInfo;
|
||||
if (!token.IsEmpty() &&
|
||||
NS_SUCCEEDED(mimeService->GetFromTypeAndExtension(NS_ConvertUTF16toUTF8(token),
|
||||
EmptyCString(), // No extension
|
||||
getter_AddRefs(mimeInfo)))) {
|
||||
if (mimeInfo) {
|
||||
// Get mime type name
|
||||
nsCString mimeTypeName;
|
||||
mimeInfo->GetType(mimeTypeName);
|
||||
CopyUTF8toUTF16(mimeTypeName, filterName);
|
||||
// Get extension list
|
||||
nsCOMPtr<nsIUTF8StringEnumerator> extensions;
|
||||
mimeInfo->GetFileExtensions(getter_AddRefs(extensions));
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED(extensions->HasMore(&hasMore)) && hasMore) {
|
||||
nsCString extension;
|
||||
if (NS_FAILED(extensions->GetNext(extension)))
|
||||
continue;
|
||||
if (!extensionListStr.IsEmpty())
|
||||
extensionListStr += NS_ConvertUTF8toUTF16("; ");
|
||||
extensionListStr += NS_ConvertUTF8toUTF16("*.") +
|
||||
NS_ConvertUTF8toUTF16(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsFilePickerFilter filter(filterName, extensionListStr, isTrustedFilter);
|
||||
if (!extensionListStr.IsEmpty() && !filters.Contains(filter)) {
|
||||
if (!allExtensionsList.IsEmpty())
|
||||
allExtensionsList += NS_ConvertUTF8toUTF16("; ");
|
||||
allExtensionsList += extensionListStr;
|
||||
filters.AppendElement(filter);
|
||||
}
|
||||
}
|
||||
|
||||
// Add "All Supported Types" filter
|
||||
if (filters.Length() > 1) {
|
||||
nsXPIDLString title;
|
||||
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
||||
"AllSupportedTypes", title);
|
||||
filePicker->AppendFilter(title, allExtensionsList);
|
||||
}
|
||||
|
||||
// Add each filter
|
||||
for (unsigned int i = 0; i < filters.Length(); ++i) {
|
||||
const nsFilePickerFilter& filter = filters[i];
|
||||
filePicker->AppendFilter(filter.mTitle, filter.mFilter);
|
||||
}
|
||||
|
||||
if (filters.Length() == 1 && filters[0].mIsTrusted) {
|
||||
// |filterAll| will always use index=0 so we need to set index=1 as the
|
||||
// current filter.
|
||||
filePicker->SetFilterIndex(1);
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsHTMLInputElement::GetFilterFromAccept()
|
||||
{
|
||||
|
@ -53,6 +53,8 @@
|
||||
#include "nsIFile.h"
|
||||
|
||||
class nsDOMFileList;
|
||||
class nsIFilePicker;
|
||||
class nsIMIMEInfo;
|
||||
class nsIRadioGroupContainer;
|
||||
class nsIRadioGroupVisitor;
|
||||
class nsIRadioVisitor;
|
||||
@ -273,6 +275,23 @@ public:
|
||||
*/
|
||||
void UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf);
|
||||
|
||||
/**
|
||||
* Set filters to the filePicker according to the accept attribute value.
|
||||
*
|
||||
* See:
|
||||
* http://dev.w3.org/html5/spec/forms.html#attr-input-accept
|
||||
*
|
||||
* @note You should not call this function if the element has no @accept.
|
||||
* @note "All Files" filter is always set, no matter if there is a valid
|
||||
* filter specifed or not.
|
||||
* @note If there is only one valid filter that is audio or video or image,
|
||||
* it will be selected as the default filter. Otherwise "All files" remains
|
||||
* the default filter.
|
||||
* @note If more than one valid filter is found, the "All Supported Types"
|
||||
* filter is added, which is the concatenation of all valid filters.
|
||||
*/
|
||||
void SetFilePickerFiltersFromAccept(nsIFilePicker* filePicker);
|
||||
|
||||
/**
|
||||
* Returns the filter which should be used for the file picker according to
|
||||
* the accept attribute value.
|
||||
@ -604,6 +623,34 @@ protected:
|
||||
bool mInhibitRestoration : 1;
|
||||
bool mCanShowValidUI : 1;
|
||||
bool mCanShowInvalidUI : 1;
|
||||
|
||||
private:
|
||||
struct nsFilePickerFilter {
|
||||
nsFilePickerFilter() {}
|
||||
|
||||
nsFilePickerFilter(const nsString& aTitle,
|
||||
const nsString& aFilter,
|
||||
const bool aIsTrusted)
|
||||
: mTitle(aTitle), mFilter(aFilter), mIsTrusted(aIsTrusted) {}
|
||||
|
||||
nsFilePickerFilter(const nsFilePickerFilter& other) {
|
||||
mTitle = other.mTitle;
|
||||
mFilter = other.mFilter;
|
||||
mIsTrusted = other.mIsTrusted;
|
||||
}
|
||||
|
||||
bool operator== (const nsFilePickerFilter& other) const {
|
||||
return mFilter == other.mFilter;
|
||||
}
|
||||
|
||||
nsString mTitle;
|
||||
nsString mFilter;
|
||||
// mIsTrusted is true if mime type comes from a "trusted" source (e.g. our
|
||||
// hard-coded set).
|
||||
// false means it may come from an "untrusted" source (e.g. OS mime types
|
||||
// mapping, which can be different accross OS, user's personal configuration, ...)
|
||||
bool mIsTrusted;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -49,3 +49,4 @@ ForgotFileEnctypeWarning=Form contains a file input, but is missing method=POST
|
||||
# LOCALIZATION NOTE (DefaultFormSubject): %S will be replaced with brandShortName
|
||||
DefaultFormSubject=Form Post from %S
|
||||
CannotEncodeAllUnicode=A form was submitted in the %S encoding which cannot encode all Unicode characters, so user input may get corrupted. To avoid this problem, the page should be changed so that the form is submitted in the UTF-8 encoding either by changing the encoding of the page itself to UTF-8 or by specifying accept-charset=utf-8 on the form element.
|
||||
AllSupportedTypes=All Supported Types
|
||||
|
Loading…
Reference in New Issue
Block a user