Bug 1317367 part 3. Pass an explicit CallerType to HTMLInputElement::SetValue at all callsites. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 15 Nov 2016 12:46:31 -0500
changeset 322741 85d87f11fc091c3c5afb762050efd2cabb0a0892
parent 322740 071649612731a4719ccfcdeb935336db61a7079d
child 322742 948aee86bbf4867d6b67b5c24ce1dcef5437db91
push id30961
push userkwierso@gmail.com
push dateThu, 17 Nov 2016 01:08:03 +0000
treeherdermozilla-central@c27117f67fa3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1317367
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1317367 part 3. Pass an explicit CallerType to HTMLInputElement::SetValue at all callsites. r=smaug
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/interfaces/html/nsIDOMHTMLInputElement.idl
dom/webidl/HTMLInputElement.webidl
layout/forms/nsNumberControlFrame.cpp
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -689,17 +689,18 @@ nsColorPickerShownCallback::UpdateIntern
 
   nsAutoString oldValue;
   if (aTrustedUpdate) {
     valueChanged = true;
   } else {
     mInput->GetValue(oldValue);
   }
 
-  mInput->SetValue(aColor);
+  IgnoredErrorResult rv;
+  mInput->SetValue(aColor, CallerType::System, rv);
 
   if (!aTrustedUpdate) {
     nsAutoString newValue;
     mInput->GetValue(newValue);
     if (!oldValue.Equals(newValue)) {
       valueChanged = true;
     }
   }
@@ -782,17 +783,18 @@ NS_IMETHODIMP
 DatePickerShownCallback::Done(const nsAString& aDate)
 {
   nsAutoString oldValue;
 
   mInput->PickerClosed();
   mInput->GetValue(oldValue);
 
   if(!oldValue.Equals(aDate)){
-    mInput->SetValue(aDate);
+    IgnoredErrorResult rv;
+    mInput->SetValue(aDate, CallerType::System, rv);
     nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
                             static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
                             NS_LITERAL_STRING("input"), true,
                             false);
     return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
                             static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
                             NS_LITERAL_STRING("change"), true,
                             false);
@@ -1933,23 +1935,24 @@ HTMLInputElement::GetValueAsDecimal() co
 
   GetValueInternal(stringValue);
 
   return !ConvertStringToNumber(stringValue, decimalValue) ? Decimal::nan()
                                                            : decimalValue;
 }
 
 void
-HTMLInputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
+HTMLInputElement::SetValue(const nsAString& aValue, CallerType aCallerType,
+                           ErrorResult& aRv)
 {
   // check security.  Note that setting the value to the empty string is always
   // OK and gives pages a way to clear a file input if necessary.
   if (mType == NS_FORM_INPUT_FILE) {
     if (!aValue.IsEmpty()) {
-      if (!nsContentUtils::IsCallerChrome()) {
+      if (aCallerType != CallerType::System) {
         // setting the value of a "FILE" input widget requires
         // chrome privilege
         aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
         return;
       }
       Sequence<nsString> list;
       if (!list.AppendElement(aValue, fallible)) {
         aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
@@ -1996,19 +1999,18 @@ HTMLInputElement::SetValue(const nsAStri
       }
     }
   }
 }
 
 NS_IMETHODIMP
 HTMLInputElement::SetValue(const nsAString& aValue)
 {
-  ErrorResult rv;
-  SetValue(aValue, rv);
-  return rv.StealNSResult();
+  NS_NOTREACHED("No one should be calling this method");
+  return NS_ERROR_FAILURE;
 }
 
 nsGenericHTMLElement*
 HTMLInputElement::GetList() const
 {
   nsAutoString dataListId;
   GetAttr(kNameSpaceID_None, nsGkAtoms::list, dataListId);
   if (dataListId.IsEmpty()) {
@@ -2039,28 +2041,30 @@ HTMLInputElement::GetList(nsIDOMHTMLElem
     return NS_OK;
   }
 
   element.forget(aValue);
   return NS_OK;
 }
 
 void
-HTMLInputElement::SetValue(Decimal aValue)
+HTMLInputElement::SetValue(Decimal aValue, CallerType aCallerType)
 {
   MOZ_ASSERT(!aValue.isInfinity(), "aValue must not be Infinity!");
 
   if (aValue.isNaN()) {
-    SetValue(EmptyString());
+    IgnoredErrorResult rv;
+    SetValue(EmptyString(), aCallerType, rv);
     return;
   }
 
   nsAutoString value;
   ConvertNumberToString(aValue, value);
-  SetValue(value);
+  IgnoredErrorResult rv;
+  SetValue(value, aCallerType, rv);
 }
 
 bool
 HTMLInputElement::ConvertNumberToString(Decimal aValue,
                                         nsAString& aResultString) const
 {
   MOZ_ASSERT(DoesValueAsNumberApply(),
              "ConvertNumberToString is only implemented for types implementing .valueAsNumber");
@@ -2263,46 +2267,42 @@ void
 HTMLInputElement::SetValueAsDate(Nullable<Date> aDate, ErrorResult& aRv)
 {
   // TODO: this is temporary until bug 888331 is fixed.
   if (!IsDateTimeInputType(mType) || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
+  // At this point we know we're not a file input, so we can just pass "not
+  // system" as the caller type, since the caller type only matters in the file
+  // input case.
   if (aDate.IsNull() || aDate.Value().IsUndefined()) {
-    aRv = SetValue(EmptyString());
+    SetValue(EmptyString(), CallerType::NonSystem, aRv);
     return;
   }
 
   double milliseconds = aDate.Value().TimeStamp().toDouble();
 
   if (mType != NS_FORM_INPUT_MONTH) {
-    SetValue(Decimal::fromDouble(milliseconds));
+    SetValue(Decimal::fromDouble(milliseconds), CallerType::NonSystem);
     return;
   }
 
   // type=month expects the value to be number of months.
   double year = JS::YearFromTime(milliseconds);
   double month = JS::MonthFromTime(milliseconds);
 
   if (IsNaN(year) || IsNaN(month)) {
-    SetValue(EmptyString());
+    SetValue(EmptyString(), CallerType::NonSystem, aRv);
     return;
   }
 
   int32_t months = MonthsSinceJan1970(year, month + 1);
-  SetValue(Decimal(int32_t(months)));
-}
-
-NS_IMETHODIMP
-HTMLInputElement::GetValueAsNumber(double* aValueAsNumber)
-{
-  *aValueAsNumber = ValueAsNumber();
-  return NS_OK;
+  SetValue(Decimal(int32_t(months)), CallerType::NonSystem);
 }
 
 void
 HTMLInputElement::SetValueAsNumber(double aValueAsNumber, ErrorResult& aRv)
 {
   // TODO: return TypeError when HTMLInputElement is converted to WebIDL, see
   // bug 825197.
   if (IsInfinite(aValueAsNumber)) {
@@ -2310,25 +2310,20 @@ HTMLInputElement::SetValueAsNumber(doubl
     return;
   }
 
   if (!DoesValueAsNumberApply()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  SetValue(Decimal::fromDouble(aValueAsNumber));
-}
-
-NS_IMETHODIMP
-HTMLInputElement::SetValueAsNumber(double aValueAsNumber)
-{
-  ErrorResult rv;
-  SetValueAsNumber(aValueAsNumber, rv);
-  return rv.StealNSResult();
+  // At this point we know we're not a file input, so we can just pass "not
+  // system" as the caller type, since the caller type only matters in the file
+  // input case.
+  SetValue(Decimal::fromDouble(aValueAsNumber), CallerType::NonSystem);
 }
 
 Decimal
 HTMLInputElement::GetMinimum() const
 {
   MOZ_ASSERT(DoesValueAsNumberApply(),
              "GetMinimum() should only be used for types that allow .valueAsNumber");
 
@@ -2491,17 +2486,19 @@ HTMLInputElement::GetValueIfStepped(int3
 nsresult
 HTMLInputElement::ApplyStep(int32_t aStep)
 {
   Decimal nextStep = Decimal::nan(); // unchanged if value will not change
 
   nsresult rv = GetValueIfStepped(aStep, CALLED_FOR_SCRIPT, &nextStep);
 
   if (NS_SUCCEEDED(rv) && nextStep.isFinite()) {
-    SetValue(nextStep);
+    // We know we're not a file input, so the caller type does not matter; just
+    // pass "not system" to be safe.
+    SetValue(nextStep, CallerType::NonSystem);
   }
 
   return rv;
 }
 
 /* static */
 bool
 HTMLInputElement::IsExperimentalMobileType(uint8_t aType)
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -12,16 +12,17 @@
 #include "nsImageLoadingContent.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsITextControlElement.h"
 #include "nsITimer.h"
 #include "nsIPhonetic.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsCOMPtr.h"
 #include "nsIConstraintValidation.h"
+#include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/HTMLFormElement.h" // for HasEverTriedInvalidSubmit()
 #include "mozilla/dom/HTMLInputElementBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "nsIFilePicker.h"
 #include "nsIContentPrefService2.h"
 #include "mozilla/Decimal.h"
 #include "nsContentUtils.h"
@@ -655,17 +656,23 @@ public:
   }
 
   // XPCOM GetDefaultValue() is OK
   void SetDefaultValue(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::value, aValue, aRv);
   }
 
-  void SetValue(const nsAString& aValue, ErrorResult& aRv);
+  void SetValue(const nsAString& aValue, CallerType aCallerType,
+                ErrorResult& aRv);
+  void GetValue(nsAString& aValue, CallerType aCallerType)
+  {
+    // For now just ignore the caller type.
+    GetValue(aValue);
+  }
 
   Nullable<Date> GetValueAsDate(ErrorResult& aRv);
 
   void SetValueAsDate(Nullable<Date>, ErrorResult& aRv);
 
   double ValueAsNumber() const
   {
     return DoesValueAsNumberApply() ? GetValueAsDecimal().toDouble()
@@ -1341,17 +1348,17 @@ protected:
    */
   static bool ParseTime(const nsAString& aValue, uint32_t* aResult);
 
   /**
    * Sets the value of the element to the string representation of the Decimal.
    *
    * @param aValue The Decimal that will be used to set the value.
    */
-  void SetValue(Decimal aValue);
+  void SetValue(Decimal aValue, CallerType aCallerType);
 
   /**
    * Update the HAS_RANGE bit field value.
    */
   void UpdateHasRange();
 
    /**
     * Get the step scale value for the current type.
--- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl
@@ -64,17 +64,16 @@ interface nsIDOMHTMLInputElement : nsISu
 
            attribute unsigned long         size;
            attribute unsigned long width;
            attribute DOMString             src;
 
            attribute DOMString             type;
            attribute DOMString             defaultValue;
            attribute DOMString             value;
-           attribute double                valueAsNumber;
           // valustAsDate is only supported via WebIDL, because it's intimately
           // tied to JS Date objects and xpidl support for that sort of thing is
           // terrible.
 
   [optional_argc] void stepDown([optional] in long n);
   [optional_argc] void stepUp([optional] in long n);
 
   // The following lines are part of the constraint validation API, see:
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -83,17 +83,17 @@ interface HTMLInputElement : HTMLElement
   [Pure, SetterThrows]
            attribute DOMString src;
   [Pure, SetterThrows]
            attribute DOMString step;
   [Pure, SetterThrows]
            attribute DOMString type;
   [Pure, SetterThrows]
            attribute DOMString defaultValue;
-  [Pure, TreatNullAs=EmptyString, SetterThrows]
+  [Pure, TreatNullAs=EmptyString, SetterThrows, NeedsCallerType]
            attribute DOMString value;
   [Throws, Func="HTMLInputElement::ValueAsDateEnabled"]
            attribute Date? valueAsDate;
   [Pure, SetterThrows]
            attribute unrestricted double valueAsNumber;
            attribute unsigned long width;
 
   [Throws]
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -686,17 +686,24 @@ nsNumberControlFrame::SetValueOfAnonText
     ICUUtils::LocalizeNumber(val.toDouble(), langTagIter, localizedValue);
   }
 #endif
 
   // We need to update the value of our anonymous text control here. Note that
   // this must be its value, and not its 'value' attribute (the default value),
   // since the default value is ignored once a user types into the text
   // control.
-  HTMLInputElement::FromContent(mTextField)->SetValue(localizedValue);
+  //
+  // Pass NonSystem as the caller type; this should work fine for actual number
+  // inputs, and be safe in case our input has a type we don't expect for some
+  // reason.
+  IgnoredErrorResult rv;
+  HTMLInputElement::FromContent(mTextField)->SetValue(localizedValue,
+                                                      CallerType::NonSystem,
+                                                      rv);
 }
 
 void
 nsNumberControlFrame::GetValueOfAnonTextControl(nsAString& aValue)
 {
   if (!mTextField) {
     aValue.Truncate();
     return;