Bug 1345767 - Part 7: Factor HasBadInput() out of HTMLInputElement. r?smaug
MozReview-Commit-ID: AUdI2dKMh4U
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -7501,106 +7501,20 @@ HTMLInputElement::IsRangeUnderflow() con
}
bool
HTMLInputElement::HasStepMismatch(bool aUseZeroIfValueNaN) const
{
return mInputType->HasStepMismatch(aUseZeroIfValueNaN);
}
-/**
- * Takes aEmail and attempts to convert everything after the first "@"
- * character (if anything) to punycode before returning the complete result via
- * the aEncodedEmail out-param. The aIndexOfAt out-param is set to the index of
- * the "@" character.
- *
- * If no "@" is found in aEmail, aEncodedEmail is simply set to aEmail and
- * the aIndexOfAt out-param is set to kNotFound.
- *
- * Returns true in all cases unless an attempt to punycode encode fails. If
- * false is returned, aEncodedEmail has not been set.
- *
- * This function exists because ConvertUTF8toACE() splits on ".", meaning that
- * for 'user.name@sld.tld' it would treat "name@sld" as a label. We want to
- * encode the domain part only.
- */
-static bool PunycodeEncodeEmailAddress(const nsAString& aEmail,
- nsAutoCString& aEncodedEmail,
- uint32_t* aIndexOfAt)
-{
- nsAutoCString value = NS_ConvertUTF16toUTF8(aEmail);
- *aIndexOfAt = (uint32_t)value.FindChar('@');
-
- if (*aIndexOfAt == (uint32_t)kNotFound ||
- *aIndexOfAt == value.Length() - 1) {
- aEncodedEmail = value;
- return true;
- }
-
- nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
- if (!idnSrv) {
- NS_ERROR("nsIIDNService isn't present!");
- return false;
- }
-
- uint32_t indexOfDomain = *aIndexOfAt + 1;
-
- const nsDependentCSubstring domain = Substring(value, indexOfDomain);
- bool ace;
- if (NS_SUCCEEDED(idnSrv->IsACE(domain, &ace)) && !ace) {
- nsAutoCString domainACE;
- if (NS_FAILED(idnSrv->ConvertUTF8toACE(domain, domainACE))) {
- return false;
- }
- value.Replace(indexOfDomain, domain.Length(), domainACE);
- }
-
- aEncodedEmail = value;
- return true;
-}
-
bool
HTMLInputElement::HasBadInput() const
{
- if (mType == NS_FORM_INPUT_NUMBER) {
- nsAutoString value;
- GetNonFileValueInternal(value);
- if (!value.IsEmpty()) {
- // The input can't be bad, otherwise it would have been sanitized to the
- // empty string.
- NS_ASSERTION(!GetValueAsDecimal().isNaN(), "Should have sanitized");
- return false;
- }
- nsNumberControlFrame* numberControlFrame =
- do_QueryFrame(GetPrimaryFrame());
- if (numberControlFrame &&
- !numberControlFrame->AnonTextControlIsEmpty()) {
- // The input the user entered failed to parse as a number.
- return true;
- }
- return false;
- }
- if (mType == NS_FORM_INPUT_EMAIL) {
- // With regards to suffering from bad input the spec says that only the
- // punycode conversion works, so we don't care whether the email address is
- // valid or not here. (If the email address is invalid then we will be
- // suffering from a type mismatch.)
- nsAutoString value;
- nsAutoCString unused;
- uint32_t unused2;
- GetNonFileValueInternal(value);
- HTMLSplitOnSpacesTokenizer tokenizer(value, ',');
- while (tokenizer.hasMoreTokens()) {
- if (!PunycodeEncodeEmailAddress(tokenizer.nextToken(), unused, &unused2)) {
- return true;
- }
- }
- return false;
- }
- return false;
+ return mInputType->HasBadInput();
}
void
HTMLInputElement::UpdateTooLongValidityState()
{
SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
}
--- a/dom/html/input/InputType.cpp
+++ b/dom/html/input/InputType.cpp
@@ -128,16 +128,22 @@ InputType::SetValueInternal(const nsAStr
}
mozilla::Decimal
InputType::GetStepBase() const
{
return mInputElement->GetStepBase();
}
+nsIFrame*
+InputType::GetPrimaryFrame() const
+{
+ return mInputElement->GetPrimaryFrame();
+}
+
void
InputType::DropReference()
{
// Drop our (non ref-counted) reference.
mInputElement = nullptr;
}
bool
@@ -183,13 +189,19 @@ InputType::IsRangeUnderflow() const
}
bool
InputType::HasStepMismatch(bool aUseZeroIfValueNaN) const
{
return false;
}
+bool
+InputType::HasBadInput() const
+{
+ return false;
+}
+
nsresult
InputType::MinMaxStepAttrChanged()
{
return NS_OK;
}
--- a/dom/html/input/InputType.h
+++ b/dom/html/input/InputType.h
@@ -23,16 +23,17 @@ NS_floorModulo(mozilla::Decimal x, mozil
namespace mozilla {
namespace dom {
class HTMLInputElement;
} // namespace dom
} // namespace mozilla
struct DoNotDelete;
+class nsIFrame;
/**
* A common superclass for different types of a HTMLInputElement.
*/
class InputType
{
public:
static mozilla::UniquePtr<InputType, DoNotDelete>
@@ -52,16 +53,17 @@ public:
virtual bool IsTooLong() const;
virtual bool IsTooShort() const;
virtual bool IsValueMissing() const;
virtual bool HasTypeMismatch() const;
virtual bool HasPatternMismatch() const;
virtual bool IsRangeOverflow() const;
virtual bool IsRangeUnderflow() const;
virtual bool HasStepMismatch(bool aUseZeroIfValueNaN) const;
+ virtual bool HasBadInput() const;
virtual nsresult MinMaxStepAttrChanged();
protected:
explicit InputType(mozilla::dom::HTMLInputElement* aInputElement)
: mInputElement(aInputElement)
{}
@@ -98,16 +100,21 @@ protected:
/**
* Return the base used to compute if a value matches step.
* Basically, it's the min attribute if present and a default value otherwise.
*
* @return The step base.
*/
mozilla::Decimal GetStepBase() const;
+ /**
+ * Get the primary frame for the input element.
+ */
+ nsIFrame* GetPrimaryFrame() const;
+
mozilla::dom::HTMLInputElement* mInputElement;
};
// Custom deleter for UniquePtr<InputType> to avoid freeing memory pre-allocated
// for InputType, but we still need to call the destructor explictly.
struct DoNotDelete { void operator()(::InputType* p) { p->~InputType(); } };
#endif /* InputType_h__ */
--- a/dom/html/input/NumericInputTypes.cpp
+++ b/dom/html/input/NumericInputTypes.cpp
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "NumericInputTypes.h"
#include "mozilla/dom/HTMLInputElement.h"
+#include "nsNumberControlFrame.h"
#include "nsTextEditorState.h"
bool
NumberInputType::IsMutable() const
{
return !mInputElement->IsDisabled() &&
!mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
}
@@ -81,16 +82,38 @@ NumberInputType::IsValueMissing() const
if (!IsMutable()) {
return false;
}
return IsValueEmpty();
}
+bool
+NumberInputType::HasBadInput() const
+{
+ nsAutoString value;
+ GetNonFileValueInternal(value);
+ if (!value.IsEmpty()) {
+ // The input can't be bad, otherwise it would have been sanitized to the
+ // empty string.
+ NS_ASSERTION(!mInputElement->GetValueAsDecimal().isNaN(),
+ "Should have sanitized");
+ return false;
+ }
+ nsNumberControlFrame* numberControlFrame =
+ do_QueryFrame(GetPrimaryFrame());
+ if (numberControlFrame &&
+ !numberControlFrame->AnonTextControlIsEmpty()) {
+ // The input the user entered failed to parse as a number.
+ return true;
+ }
+ return false;
+}
+
/* input type=range */
nsresult
RangeInputType::MinMaxStepAttrChanged()
{
// The value may need to change when @min/max/step changes since the value may
// have been invalid and can now change to a valid value, or vice versa. For
// example, consider: <input type=range value=-1 max=1 step=3>. The valid
// range is 0 to 1 while the nearest valid steps are -1 and 2 (the max value
--- a/dom/html/input/NumericInputTypes.h
+++ b/dom/html/input/NumericInputTypes.h
@@ -30,16 +30,17 @@ class NumberInputType : public NumericIn
public:
static InputType*
Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
{
return new (aMemory) NumberInputType(aInputElement);
}
bool IsValueMissing() const override;
+ bool HasBadInput() const override;
private:
explicit NumberInputType(mozilla::dom::HTMLInputElement* aInputElement)
: NumericInputTypeBase(aInputElement)
{}
bool IsMutable() const override;
};
--- a/dom/html/input/SingleLineTextInputTypes.cpp
+++ b/dom/html/input/SingleLineTextInputTypes.cpp
@@ -131,16 +131,36 @@ EmailInputType::HasTypeMismatch() const
if (value.IsEmpty()) {
return false;
}
return mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
!IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
}
+bool
+EmailInputType::HasBadInput() const
+{
+ // With regards to suffering from bad input the spec says that only the
+ // punycode conversion works, so we don't care whether the email address is
+ // valid or not here. (If the email address is invalid then we will be
+ // suffering from a type mismatch.)
+ nsAutoString value;
+ nsAutoCString unused;
+ uint32_t unused2;
+ GetNonFileValueInternal(value);
+ HTMLSplitOnSpacesTokenizer tokenizer(value, ',');
+ while (tokenizer.hasMoreTokens()) {
+ if (!PunycodeEncodeEmailAddress(tokenizer.nextToken(), unused, &unused2)) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* static */ bool
EmailInputType::IsValidEmailAddressList(const nsAString& aValue)
{
HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
while (tokenizer.hasMoreTokens()) {
if (!IsValidEmailAddress(tokenizer.nextToken())) {
return false;
--- a/dom/html/input/SingleLineTextInputTypes.h
+++ b/dom/html/input/SingleLineTextInputTypes.h
@@ -100,16 +100,17 @@ class EmailInputType : public SingleLine
public:
static InputType*
Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
{
return new (aMemory) EmailInputType(aInputElement);
}
bool HasTypeMismatch() const override;
+ bool HasBadInput() const override;
private:
explicit EmailInputType(mozilla::dom::HTMLInputElement* aInputElement)
: SingleLineTextInputTypeBase(aInputElement)
{}
/**
* This helper method returns true if aValue is a valid email address.
--- a/dom/html/input/moz.build
+++ b/dom/html/input/moz.build
@@ -25,15 +25,16 @@ UNIFIED_SOURCES += [
'SingleLineTextInputTypes.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [
'/dom/base',
'/dom/html',
+ '/layout/forms',
]
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']