Bug 1317367 part 4. Pass an explicit CallerType to HTMLInputElement::GetValueInternal. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 15 Nov 2016 12:46:32 -0500
changeset 439407 948aee86bbf4867d6b67b5c24ce1dcef5437db91
parent 439406 85d87f11fc091c3c5afb762050efd2cabb0a0892
child 439408 683874fa09afc9c61f0e754d9ea36043e38f6441
push id36000
push userbmo:gasolin@mozilla.com
push dateWed, 16 Nov 2016 01:30:27 +0000
reviewerssmaug
bugs1317367
milestone53.0a1
Bug 1317367 part 4. Pass an explicit CallerType to HTMLInputElement::GetValueInternal. r=smaug I'm not 100% sure that I'm being very consistent in my handling of mFocusedValue, but since that's not used for file inputs, I don't think it matters much... A bigger problem is if people start using this caller type for things other than file inputs.
accessible/html/HTMLFormControlAccessible.cpp
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/RadioNodeList.cpp
dom/html/RadioNodeList.h
dom/interfaces/html/nsIDOMHTMLInputElement.idl
dom/webidl/HTMLInputElement.webidl
dom/webidl/RadioNodeList.webidl
embedding/components/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
layout/forms/nsColorControlFrame.cpp
layout/forms/nsGfxButtonControlFrame.cpp
layout/forms/nsNumberControlFrame.cpp
toolkit/components/satchel/nsFormFillController.cpp
--- a/accessible/html/HTMLFormControlAccessible.cpp
+++ b/accessible/html/HTMLFormControlAccessible.cpp
@@ -346,18 +346,21 @@ HTMLTextFieldAccessible::Value(nsString&
 
   nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea(do_QueryInterface(mContent));
   if (textArea) {
     textArea->GetValue(aValue);
     return;
   }
 
   HTMLInputElement* input = HTMLInputElement::FromContent(mContent);
-  if (input)
-    input->GetValue(aValue);
+  if (input) {
+    // Pass NonSystem as the caller type, to be safe.  We don't expect to have a
+    // file input here.
+    input->GetValue(aValue, CallerType::NonSystem);
+  }
 }
 
 void
 HTMLTextFieldAccessible::ApplyARIAState(uint64_t* aState) const
 {
   HyperTextAccessibleWrap::ApplyARIAState(aState);
   aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState);
 
@@ -547,17 +550,20 @@ HTMLSpinnerAccessible::NativeRole()
 
 void
 HTMLSpinnerAccessible::Value(nsString& aValue)
 {
   AccessibleWrap::Value(aValue);
   if (!aValue.IsEmpty())
     return;
 
-  HTMLInputElement::FromContent(mContent)->GetValue(aValue);
+  // Pass NonSystem as the caller type, to be safe.  We don't expect to have a
+  // file input here.
+  HTMLInputElement::FromContent(mContent)->GetValue(aValue,
+                                                    CallerType::NonSystem);
 }
 
 double
 HTMLSpinnerAccessible::MaxValue() const
 {
   double value = AccessibleWrap::MaxValue();
   if (!IsNaN(value))
     return value;
@@ -623,17 +629,20 @@ HTMLRangeAccessible::IsWidget() const
 
 void
 HTMLRangeAccessible::Value(nsString& aValue)
 {
   LeafAccessible::Value(aValue);
   if (!aValue.IsEmpty())
     return;
 
-  HTMLInputElement::FromContent(mContent)->GetValue(aValue);
+  // Pass NonSystem as the caller type, to be safe.  We don't expect to have a
+  // file input here.
+  HTMLInputElement::FromContent(mContent)->GetValue(aValue,
+                                                    CallerType::NonSystem);
 }
 
 double
 HTMLRangeAccessible::MaxValue() const
 {
   double value = LeafAccessible::MaxValue();
   if (!IsNaN(value))
     return value;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -686,25 +686,25 @@ nsColorPickerShownCallback::UpdateIntern
                                            bool aTrustedUpdate)
 {
   bool valueChanged = false;
 
   nsAutoString oldValue;
   if (aTrustedUpdate) {
     valueChanged = true;
   } else {
-    mInput->GetValue(oldValue);
+    mInput->GetValue(oldValue, CallerType::System);
   }
 
   IgnoredErrorResult rv;
   mInput->SetValue(aColor, CallerType::System, rv);
 
   if (!aTrustedUpdate) {
     nsAutoString newValue;
-    mInput->GetValue(newValue);
+    mInput->GetValue(newValue, CallerType::System);
     if (!oldValue.Equals(newValue)) {
       valueChanged = true;
     }
   }
 
   if (valueChanged) {
     mValueChanged = true;
     return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
@@ -780,17 +780,17 @@ DatePickerShownCallback::Cancel()
 }
 
 NS_IMETHODIMP
 DatePickerShownCallback::Done(const nsAString& aDate)
 {
   nsAutoString oldValue;
 
   mInput->PickerClosed();
-  mInput->GetValue(oldValue);
+  mInput->GetValue(oldValue, CallerType::System);
 
   if(!oldValue.Equals(aDate)){
     IgnoredErrorResult rv;
     mInput->SetValue(aDate, CallerType::System, rv);
     nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
                             static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
                             NS_LITERAL_STRING("input"), true,
                             false);
@@ -861,17 +861,17 @@ HTMLInputElement::InitDatePicker()
 
   nsresult rv;
   nsCOMPtr<nsIDatePicker> datePicker = do_CreateInstance("@mozilla.org/datepicker;1", &rv);
   if (!datePicker) {
     return rv;
   }
 
   nsAutoString initialValue;
-  GetValueInternal(initialValue);
+  GetNonFileValueInternal(initialValue);
   rv = datePicker->Init(win, title, initialValue);
 
   nsCOMPtr<nsIDatePickerShownCallback> callback =
     new DatePickerShownCallback(this, datePicker);
 
   rv = datePicker->Open(callback);
   if (NS_SUCCEEDED(rv)) {
     mPickerRunning = true;
@@ -906,17 +906,17 @@ HTMLInputElement::InitColorPicker()
                                      "ColorPicker", title);
 
   nsCOMPtr<nsIColorPicker> colorPicker = do_CreateInstance("@mozilla.org/colorpicker;1");
   if (!colorPicker) {
     return NS_ERROR_FAILURE;
   }
 
   nsAutoString initialValue;
-  GetValueInternal(initialValue);
+  GetNonFileValueInternal(initialValue);
   nsresult rv = colorPicker->Init(win, title, initialValue);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIColorPickerShownCallback> callback =
     new nsColorPickerShownCallback(this, colorPicker);
 
   rv = colorPicker->Open(callback);
   if (NS_SUCCEEDED(rv)) {
@@ -1319,17 +1319,17 @@ HTMLInputElement::Clone(mozilla::dom::No
   NS_ENSURE_SUCCESS(rv, rv);
 
   switch (GetValueMode()) {
     case VALUE_MODE_VALUE:
       if (mValueChanged) {
         // We don't have our default value anymore.  Set our value on
         // the clone.
         nsAutoString value;
-        GetValueInternal(value);
+        GetNonFileValueInternal(value);
         // SetValueInternal handles setting the VALUE_CHANGED bit for us
         rv = it->SetValueInternal(value, nsTextEditorState::eSetValue_Notify);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       break;
     case VALUE_MODE_FILENAME:
       if (it->OwnerDoc()->IsStaticDocument()) {
         // We're going to be used in print preview.  Since the doc is static
@@ -1514,17 +1514,17 @@ HTMLInputElement::AfterSetAttr(int32_t a
         // while the nearest valid steps are -1 and 2 (the max value having
         // prevented there being a valid step in range). Changing @max to/from
         // 1 and a number greater than on equal to 3 should change whether we
         // have a step mismatch or not.
         // The value may also need to change between a value that results in
         // a step mismatch and a value that results in overflow. For example,
         // if @max in the example above were to change from 1 to -1.
         nsAutoString value;
-        GetValue(value);
+        GetNonFileValueInternal(value);
         nsresult rv =
           SetValueInternal(value, nsTextEditorState::eSetValue_Internal);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       // Validity state must be updated *after* the SetValueInternal call above
       // or else the following assert will not be valid.
       // We don't assert the state of underflow during creation since
       // DoneCreatingElement sanitizes.
@@ -1533,33 +1533,33 @@ HTMLInputElement::AfterSetAttr(int32_t a
                  mType != NS_FORM_INPUT_RANGE ||
                  !GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
                  "HTML5 spec does not allow underflow for type=range");
     } else if (aName == nsGkAtoms::min) {
       UpdateHasRange();
       if (mType == NS_FORM_INPUT_RANGE) {
         // See @max comment
         nsAutoString value;
-        GetValue(value);
+        GetNonFileValueInternal(value);
         nsresult rv =
           SetValueInternal(value, nsTextEditorState::eSetValue_Internal);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       // See corresponding @max comment
       UpdateRangeUnderflowValidityState();
       UpdateStepMismatchValidityState();
       MOZ_ASSERT(!mDoneCreating ||
                  mType != NS_FORM_INPUT_RANGE ||
                  !GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
                  "HTML5 spec does not allow underflow for type=range");
     } else if (aName == nsGkAtoms::step) {
       if (mType == NS_FORM_INPUT_RANGE) {
         // See @max comment
         nsAutoString value;
-        GetValue(value);
+        GetNonFileValueInternal(value);
         nsresult rv =
           SetValueInternal(value, nsTextEditorState::eSetValue_Internal);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       // See corresponding @max comment
       UpdateStepMismatchValidityState();
       MOZ_ASSERT(!mDoneCreating ||
                  mType != NS_FORM_INPUT_RANGE ||
@@ -1567,17 +1567,17 @@ HTMLInputElement::AfterSetAttr(int32_t a
                  "HTML5 spec does not allow underflow for type=range");
     } else if (aName == nsGkAtoms::dir &&
                aValue && aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
       SetDirectionIfAuto(true, aNotify);
     } else if (aName == nsGkAtoms::lang) {
       if (mType == NS_FORM_INPUT_NUMBER) {
         // Update the value that is displayed to the user to the new locale:
         nsAutoString value;
-        GetValueInternal(value);
+        GetNonFileValueInternal(value);
         nsNumberControlFrame* numberControlFrame =
           do_QueryFrame(GetPrimaryFrame());
         if (numberControlFrame) {
           numberControlFrame->SetValueOfAnonTextControl(value);
         }
       }
     } else if (aName == nsGkAtoms::autocomplete) {
       // Clear the cached @autocomplete attribute state.
@@ -1749,54 +1749,65 @@ HTMLInputElement::GetWidth(uint32_t* aWi
 NS_IMETHODIMP
 HTMLInputElement::SetWidth(uint32_t aWidth)
 {
   ErrorResult rv;
   SetWidth(aWidth, rv);
   return rv.StealNSResult();
 }
 
-NS_IMETHODIMP
-HTMLInputElement::GetValue(nsAString& aValue)
-{
-  GetValueInternal(aValue);
+void
+HTMLInputElement::GetValue(nsAString& aValue, CallerType aCallerType)
+{
+  GetValueInternal(aValue, aCallerType);
 
   // Don't return non-sanitized value for types that are experimental on mobile
   // or datetime types
   if (IsExperimentalMobileType(mType) || IsDateTimeInputType(mType)) {
     SanitizeValue(aValue);
   }
-
-  return NS_OK;
 }
 
 void
-HTMLInputElement::GetValueInternal(nsAString& aValue) const
+HTMLInputElement::GetValueInternal(nsAString& aValue,
+                                   CallerType aCallerType) const
+{
+  if (mType != NS_FORM_INPUT_FILE) {
+    GetNonFileValueInternal(aValue);
+    return;
+  }
+
+  if (aCallerType == CallerType::System) {
+    aValue.Assign(mFirstFilePath);
+  } else {
+    // Just return the leaf name
+    if (mFilesOrDirectories.IsEmpty()) {
+      aValue.Truncate();
+    } else {
+      GetDOMFileOrDirectoryName(mFilesOrDirectories[0], aValue);
+    }
+  }
+}
+
+void
+HTMLInputElement::GetNonFileValueInternal(nsAString& aValue) const
 {
   switch (GetValueMode()) {
     case VALUE_MODE_VALUE:
       if (IsSingleLineTextControl(false)) {
         mInputData.mState->GetValue(aValue, true);
       } else if (!aValue.Assign(mInputData.mValue, fallible)) {
         aValue.Truncate();
       }
       return;
 
     case VALUE_MODE_FILENAME:
-      if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
-        aValue.Assign(mFirstFilePath);
-      } else {
-        // Just return the leaf name
-        if (mFilesOrDirectories.IsEmpty()) {
-          aValue.Truncate();
-        } else {
-          GetDOMFileOrDirectoryName(mFilesOrDirectories[0], aValue);
-        }
-      }
-
+      NS_NOTREACHED("Someone screwed up here");
+      // We'll just return empty string if someone does screw up.
+      aValue.Truncate();
       return;
 
     case VALUE_MODE_DEFAULT:
       // Treat defaultValue as value.
       GetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue);
       return;
 
     case VALUE_MODE_DEFAULT_ON:
@@ -1807,17 +1818,17 @@ HTMLInputElement::GetValueInternal(nsASt
       return;
   }
 }
 
 bool
 HTMLInputElement::IsValueEmpty() const
 {
   nsAutoString value;
-  GetValueInternal(value);
+  GetNonFileValueInternal(value);
 
   return value.IsEmpty();
 }
 
 void
 HTMLInputElement::ClearFiles(bool aSetValueChanged)
 {
   nsTArray<OwningFileOrDirectory> data;
@@ -1928,17 +1939,17 @@ HTMLInputElement::ConvertStringToNumber(
 }
 
 Decimal
 HTMLInputElement::GetValueAsDecimal() const
 {
   Decimal decimalValue;
   nsAutoString stringValue;
 
-  GetValueInternal(stringValue);
+  GetNonFileValueInternal(stringValue);
 
   return !ConvertStringToNumber(stringValue, decimalValue) ? Decimal::nan()
                                                            : decimalValue;
 }
 
 void
 HTMLInputElement::SetValue(const nsAString& aValue, CallerType aCallerType,
                            ErrorResult& aRv)
@@ -1971,48 +1982,41 @@ HTMLInputElement::SetValue(const nsAStri
       // If the value has been set by a script, we basically want to keep the
       // current change event state. If the element is ready to fire a change
       // event, we should keep it that way. Otherwise, we should make sure the
       // element will not fire any event because of the script interaction.
       //
       // NOTE: this is currently quite expensive work (too much string
       // manipulation). We should probably optimize that.
       nsAutoString currentValue;
-      GetValue(currentValue);
+      GetValue(currentValue, aCallerType);
 
       nsresult rv =
         SetValueInternal(aValue, nsTextEditorState::eSetValue_ByContent |
                                  nsTextEditorState::eSetValue_Notify);
       if (NS_FAILED(rv)) {
         aRv.Throw(rv);
         return;
       }
 
       if (mFocusedValue.Equals(currentValue)) {
-        GetValue(mFocusedValue);
+        GetValue(mFocusedValue, aCallerType);
       }
     } else {
       nsresult rv =
         SetValueInternal(aValue, nsTextEditorState::eSetValue_ByContent |
                                  nsTextEditorState::eSetValue_Notify);
       if (NS_FAILED(rv)) {
         aRv.Throw(rv);
         return;
       }
     }
   }
 }
 
-NS_IMETHODIMP
-HTMLInputElement::SetValue(const nsAString& aValue)
-{
-  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()) {
     return nullptr;
   }
@@ -2202,56 +2206,56 @@ HTMLInputElement::GetValueAsDate(ErrorRe
     return Nullable<Date>();
   }
 
   switch (mType) {
     case NS_FORM_INPUT_DATE:
     {
       uint32_t year, month, day;
       nsAutoString value;
-      GetValueInternal(value);
+      GetNonFileValueInternal(value);
       if (!ParseDate(value, &year, &month, &day)) {
         return Nullable<Date>();
       }
 
       JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day));
       return Nullable<Date>(Date(time));
     }
     case NS_FORM_INPUT_TIME:
     {
       uint32_t millisecond;
       nsAutoString value;
-      GetValueInternal(value);
+      GetNonFileValueInternal(value);
       if (!ParseTime(value, &millisecond)) {
         return Nullable<Date>();
       }
 
       JS::ClippedTime time = JS::TimeClip(millisecond);
       MOZ_ASSERT(time.toDouble() == millisecond,
                  "HTML times are restricted to the day after the epoch and "
                  "never clip");
       return Nullable<Date>(Date(time));
     }
     case NS_FORM_INPUT_MONTH:
     {
       uint32_t year, month;
       nsAutoString value;
-      GetValueInternal(value);
+      GetNonFileValueInternal(value);
       if (!ParseMonth(value, &year, &month)) {
         return Nullable<Date>();
       }
 
       JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, 1));
       return Nullable<Date>(Date(time));
     }
     case NS_FORM_INPUT_WEEK:
     {
       uint32_t year, week;
       nsAutoString value;
-      GetValueInternal(value);
+      GetNonFileValueInternal(value);
       if (!ParseWeek(value, &year, &week)) {
         return Nullable<Date>();
       }
 
       double days = DaysSinceEpochFromWeek(year, week);
       JS::ClippedTime time = JS::TimeClip(days * kMsPerDay);
 
       return Nullable<Date>(Date(time));
@@ -3086,18 +3090,20 @@ HTMLInputElement::AfterSetFilesOrDirecto
   }
 
   UpdateAllValidityStates(true);
 }
 
 void
 HTMLInputElement::FireChangeEventIfNeeded()
 {
+  // We're not exposing the GetValue return value anywhere here, so it's safe to
+  // claim to be a system caller.
   nsAutoString value;
-  GetValue(value);
+  GetValue(value, CallerType::System);
 
   if (!MayFireChangeOnBlur() || mFocusedValue.Equals(value)) {
     return;
   }
 
   // Dispatch the change event.
   mFocusedValue = value;
   nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
@@ -3854,27 +3860,27 @@ HTMLInputElement::PreHandleEvent(EventCh
   aVisitor.mItemFlags |= mType;
 
   if (aVisitor.mEvent->mMessage == eFocus &&
       aVisitor.mEvent->IsTrusted() &&
       MayFireChangeOnBlur() &&
       // StartRangeThumbDrag already set mFocusedValue on 'mousedown' before
       // we get the 'focus' event.
       !mIsDraggingRange) {
-    GetValue(mFocusedValue);
+    GetValue(mFocusedValue, CallerType::System);
   }
 
   // Fire onchange (if necessary), before we do the blur, bug 357684.
   if (aVisitor.mEvent->mMessage == eBlur) {
     // Experimental mobile types rely on the system UI to prevent users to not
     // set invalid values but we have to be extra-careful. Especially if the
     // option has been enabled on desktop.
     if (IsExperimentalMobileType(mType)) {
       nsAutoString aValue;
-      GetValueInternal(aValue);
+      GetNonFileValueInternal(aValue);
       nsresult rv =
         SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal);
       NS_ENSURE_SUCCESS(rv, rv);
     }
     FireChangeEventIfNeeded();
   }
 
   if (mType == NS_FORM_INPUT_RANGE &&
@@ -4045,17 +4051,17 @@ HTMLInputElement::StartRangeThumbDrag(Wi
   nsIPresShell::SetCapturingContent(this, CAPTURE_IGNOREALLOWED);
   nsRangeFrame* rangeFrame = do_QueryFrame(GetPrimaryFrame());
 
   // Before we change the value, record the current value so that we'll
   // correctly send a 'change' event if appropriate. We need to do this here
   // because the 'focus' event is handled after the 'mousedown' event that
   // we're being called for (i.e. too late to update mFocusedValue, since we'll
   // have changed it by then).
-  GetValue(mFocusedValue);
+  GetValue(mFocusedValue, CallerType::System);
 
   SetValueOfRangeForUserEvent(rangeFrame->GetValueAtEventPoint(aEvent));
 }
 
 void
 HTMLInputElement::FinishRangeThumbDrag(WidgetGUIEvent* aEvent)
 {
   MOZ_ASSERT(mIsDraggingRange);
@@ -5026,17 +5032,19 @@ HTMLInputElement::HandleTypeChange(uint8
     CancelRangeThumbDrag(false);
   }
 
   ValueModeType aOldValueMode = GetValueMode();
   uint8_t oldType = mType;
   nsAutoString aOldValue;
 
   if (aOldValueMode == VALUE_MODE_VALUE) {
-    GetValue(aOldValue);
+    // Doesn't matter what caller type we pass here, since we know we're not a
+    // file input anyway.
+    GetValue(aOldValue, CallerType::NonSystem);
   }
 
   nsTextEditorState::SelectionProperties sp;
 
   if (GetEditorState()) {
     sp = mInputData.mState->GetSelectionProperties();
   }
 
@@ -5091,17 +5099,17 @@ HTMLInputElement::HandleTypeChange(uint8
   }
 
   // Updating mFocusedValue in consequence:
   // If the new type fires a change event on blur, but the previous type
   // doesn't, we should set mFocusedValue to the current value.
   // Otherwise, if the new type doesn't fire a change event on blur, but the
   // previous type does, we should clear out mFocusedValue.
   if (MayFireChangeOnBlur(mType) && !MayFireChangeOnBlur(oldType)) {
-    GetValue(mFocusedValue);
+    GetValue(mFocusedValue, CallerType::System);
   } else if (!IsSingleLineTextControl(false, mType) &&
              IsSingleLineTextControl(false, oldType)) {
     mFocusedValue.Truncate();
   }
 
   UpdateHasRange();
 
   // Do not notify, it will be done after if needed.
@@ -6005,31 +6013,23 @@ HTMLInputElement::GetControllers(nsICont
 
   ErrorResult rv;
   RefPtr<nsIControllers> controller = GetControllers(rv);
   controller.forget(aResult);
   return rv.StealNSResult();
 }
 
 int32_t
-HTMLInputElement::GetTextLength(ErrorResult& aRv)
+HTMLInputElement::InputTextLength(CallerType aCallerType)
 {
   nsAutoString val;
-  GetValue(val);
+  GetValue(val, aCallerType);
   return val.Length();
 }
 
-NS_IMETHODIMP
-HTMLInputElement::GetTextLength(int32_t* aTextLength)
-{
-  ErrorResult rv;
-  *aTextLength = GetTextLength(rv);
-  return rv.StealNSResult();
-}
-
 void
 HTMLInputElement::SetSelectionRange(int32_t aSelectionStart,
                                     int32_t aSelectionEnd,
                                     const Optional<nsAString>& aDirection,
                                     ErrorResult& aRv)
 {
   if (!SupportsTextSelection()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
@@ -6109,17 +6109,17 @@ HTMLInputElement::SetRangeText(const nsA
   }
 
   if (aStart > aEnd) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   nsAutoString value;
-  GetValueInternal(value);
+  GetNonFileValueInternal(value);
   uint32_t inputValueLength = value.Length();
 
   if (aStart > inputValueLength) {
     aStart = inputValueLength;
   }
 
   if (aEnd > inputValueLength) {
     aEnd = inputValueLength;
@@ -6530,17 +6530,17 @@ HTMLInputElement::SetDefaultValueAsValue
 
 void
 HTMLInputElement::SetDirectionIfAuto(bool aAuto, bool aNotify)
 {
   if (aAuto) {
     SetHasDirAuto();
     if (IsSingleLineTextControl(true)) {
       nsAutoString value;
-      GetValue(value);
+      GetValue(value, CallerType::System);
       SetDirectionalityFromValue(this, value, aNotify);
     }
   } else {
     ClearHasDirAuto();
   }
 }
 
 NS_IMETHODIMP
@@ -6613,41 +6613,21 @@ HTMLInputElement::SubmitNamesValues(HTML
       // to Nav and IE compatibility.
       aFormSubmission->AddNameValuePair(NS_LITERAL_STRING("x"), xVal);
       aFormSubmission->AddNameValuePair(NS_LITERAL_STRING("y"), yVal);
     }
 
     return NS_OK;
   }
 
-  //
-  // Submit name=value
-  //
-
   // If name not there, don't submit
   if (name.IsEmpty()) {
     return NS_OK;
   }
 
-  // Get the value
-  nsAutoString value;
-  nsresult rv = GetValue(value);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  if (mType == NS_FORM_INPUT_SUBMIT && value.IsEmpty() &&
-      !HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
-    // Get our default value, which is the same as our default label
-    nsXPIDLString defaultValue;
-    nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
-                                       "Submit", defaultValue);
-    value = defaultValue;
-  }
-
   //
   // Submit file if its input type=file and this encoding method accepts files
   //
   if (mType == NS_FORM_INPUT_FILE) {
     // Submit files
 
     const nsTArray<OwningFileOrDirectory>& files =
       GetFilesOrDirectoriesInternal();
@@ -6670,16 +6650,34 @@ HTMLInputElement::SubmitNamesValues(HTML
   }
 
   if (mType == NS_FORM_INPUT_HIDDEN && name.EqualsLiteral("_charset_")) {
     nsCString charset;
     aFormSubmission->GetCharset(charset);
     return aFormSubmission->AddNameValuePair(name,
                                              NS_ConvertASCIItoUTF16(charset));
   }
+
+  //
+  // Submit name=value
+  //
+
+  // Get the value
+  nsAutoString value;
+  GetValue(value, CallerType::System);
+
+  if (mType == NS_FORM_INPUT_SUBMIT && value.IsEmpty() &&
+      !HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
+    // Get our default value, which is the same as our default label
+    nsXPIDLString defaultValue;
+    nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
+                                       "Submit", defaultValue);
+    value = defaultValue;
+  }
+
   if (IsSingleLineTextControl(true) &&
       name.EqualsLiteral("isindex") &&
       aFormSubmission->SupportsIsindexSubmission()) {
     return aFormSubmission->AddIsindex(value);
   }
   return aFormSubmission->AddNameValuePair(name, value);
 }
 
@@ -6708,23 +6706,20 @@ HTMLInputElement::SaveState()
       if ((GetValueMode() == VALUE_MODE_DEFAULT &&
            mType != NS_FORM_INPUT_HIDDEN) ||
           mType == NS_FORM_INPUT_PASSWORD || !mValueChanged) {
         break;
       }
 
       inputState = new HTMLInputElementState();
       nsAutoString value;
-      nsresult rv = GetValue(value);
-      if (NS_FAILED(rv)) {
-        return rv;
-      }
+      GetValue(value, CallerType::System);
 
       if (!IsSingleLineTextControl(false)) {
-        rv = nsLinebreakConverter::ConvertStringLineBreaks(
+        nsresult rv = nsLinebreakConverter::ConvertStringLineBreaks(
                value,
                nsLinebreakConverter::eLinebreakPlatform,
                nsLinebreakConverter::eLinebreakContent);
 
         if (NS_FAILED(rv)) {
           NS_ERROR("Converting linebreaks failed!");
           return rv;
         }
@@ -6772,17 +6767,17 @@ HTMLInputElement::DoneCreatingElement()
   if (!restoredCheckedState && mShouldInitChecked) {
     DoSetChecked(DefaultChecked(), false, true);
     DoSetCheckedChanged(false, false);
   }
 
   // Sanitize the value.
   if (GetValueMode() == VALUE_MODE_VALUE) {
     nsAutoString aValue;
-    GetValue(aValue);
+    GetValue(aValue, CallerType::System);
     // TODO: What should we do if SetValueInternal fails?  (The allocation
     // may potentially be big, but most likely we've failed to allocate
     // before the type change.)
     SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal);
   }
 
   mShouldInitChecked = false;
 }
@@ -7450,20 +7445,17 @@ HTMLInputElement::IsTooLong()
 
   int32_t maxLength = MaxLength();
 
   // Maxlength of -1 means parsing error.
   if (maxLength == -1) {
     return false;
   }
 
-  int32_t textLength = -1;
-  GetTextLength(&textLength);
-
-  return textLength > maxLength;
+  return InputTextLength(CallerType::System) > maxLength;
 }
 
 bool
 HTMLInputElement::IsTooShort()
 {
   if (!mValueChanged ||
       !mLastValueChangeWasInteractive ||
       !MinOrMaxLengthApplies() ||
@@ -7473,18 +7465,17 @@ HTMLInputElement::IsTooShort()
 
   int32_t minLength = MinLength();
 
   // Minlength of -1 means parsing error.
   if (minLength == -1) {
     return false;
   }
 
-  int32_t textLength = -1;
-  GetTextLength(&textLength);
+  int32_t textLength = InputTextLength(CallerType::System);
 
   return textLength && textLength < minLength;
 }
 
 bool
 HTMLInputElement::IsValueMissing() const
 {
   // Should use UpdateValueMissingValidityStateForRadio() for type radio.
@@ -7520,17 +7511,17 @@ HTMLInputElement::IsValueMissing() const
 bool
 HTMLInputElement::HasTypeMismatch() const
 {
   if (mType != NS_FORM_INPUT_EMAIL && mType != NS_FORM_INPUT_URL) {
     return false;
   }
 
   nsAutoString value;
-  GetValueInternal(value);
+  GetNonFileValueInternal(value);
 
   if (value.IsEmpty()) {
     return false;
   }
 
   if (mType == NS_FORM_INPUT_EMAIL) {
     return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)
              ? !IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
@@ -7563,17 +7554,17 @@ HTMLInputElement::HasPatternMismatch() c
       !HasAttr(kNameSpaceID_None, nsGkAtoms::pattern)) {
     return false;
   }
 
   nsAutoString pattern;
   GetAttr(kNameSpaceID_None, nsGkAtoms::pattern, pattern);
 
   nsAutoString value;
-  GetValueInternal(value);
+  GetNonFileValueInternal(value);
 
   if (value.IsEmpty()) {
     return false;
   }
 
   nsIDocument* doc = OwnerDoc();
 
   return !nsContentUtils::IsPatternMatching(value, pattern, doc);
@@ -7698,17 +7689,17 @@ static bool PunycodeEncodeEmailAddress(c
   return true;
 }
 
 bool
 HTMLInputElement::HasBadInput() const
 {
   if (mType == NS_FORM_INPUT_NUMBER) {
     nsAutoString value;
-    GetValueInternal(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());
@@ -7722,17 +7713,17 @@ HTMLInputElement::HasBadInput() const
   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;
-    GetValueInternal(value);
+    GetNonFileValueInternal(value);
     HTMLSplitOnSpacesTokenizer tokenizer(value, ',');
     while (tokenizer.hasMoreTokens()) {
       if (!PunycodeEncodeEmailAddress(tokenizer.nextToken(), unused, &unused2)) {
         return true;
       }
     }
     return false;
   }
@@ -7889,42 +7880,38 @@ HTMLInputElement::GetValidationMessage(n
   nsresult rv = NS_OK;
 
   switch (aType)
   {
     case VALIDITY_STATE_TOO_LONG:
     {
       nsXPIDLString message;
       int32_t maxLength = MaxLength();
-      int32_t textLength = -1;
+      int32_t textLength = InputTextLength(CallerType::System);
       nsAutoString strMaxLength;
       nsAutoString strTextLength;
 
-      GetTextLength(&textLength);
-
       strMaxLength.AppendInt(maxLength);
       strTextLength.AppendInt(textLength);
 
       const char16_t* params[] = { strMaxLength.get(), strTextLength.get() };
       rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                                  "FormValidationTextTooLong",
                                                  params, message);
       aValidationMessage = message;
       break;
     }
     case VALIDITY_STATE_TOO_SHORT:
     {
       nsXPIDLString message;
       int32_t minLength = MinLength();
-      int32_t textLength = -1;
+      int32_t textLength = InputTextLength(CallerType::System);
       nsAutoString strMinLength;
       nsAutoString strTextLength;
 
-      GetTextLength(&textLength);
-
       strMinLength.AppendInt(minLength);
       strTextLength.AppendInt(textLength);
 
       const char16_t* params[] = { strMinLength.get(), strTextLength.get() };
       rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                                  "FormValidationTextTooShort",
                                                  params, message);
       aValidationMessage = message;
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -658,21 +658,17 @@ public:
   // XPCOM GetDefaultValue() is OK
   void SetDefaultValue(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::value, aValue, 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);
-  }
+  void GetValue(nsAString& aValue, CallerType aCallerType);
 
   Nullable<Date> GetValueAsDate(ErrorResult& aRv);
 
   void SetValueAsDate(Nullable<Date>, ErrorResult& aRv);
 
   double ValueAsNumber() const
   {
     return DoesValueAsNumberApply() ? GetValueAsDecimal().toDouble()
@@ -771,17 +767,17 @@ public:
   // XPCOM GetUseMap() is OK
   void SetUseMap(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::usemap, aValue, aRv);
   }
 
   nsIControllers* GetControllers(ErrorResult& aRv);
 
-  int32_t GetTextLength(ErrorResult& aRv);
+  int32_t InputTextLength(CallerType aCallerType);
 
   void MozGetFileNameArray(nsTArray<nsString>& aFileNames, ErrorResult& aRv);
 
   void MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv);
   void MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles);
   void MozSetDirectory(const nsAString& aDirectoryPath, ErrorResult& aRv);
 
   /*
@@ -926,20 +922,27 @@ protected:
   /**
    * Setting the value.
    *
    * @param aValue      String to set.
    * @param aFlags      See nsTextEditorState::SetValueFlags.
    */
   nsresult SetValueInternal(const nsAString& aValue, uint32_t aFlags);
 
-  void GetValueInternal(nsAString& aValue) const;
+  // Generic getter for the value that doesn't do experimental control type
+  // sanitization.
+  void GetValueInternal(nsAString& aValue, CallerType aCallerType) const;
+
+  // A getter for callers that know we're not dealing with a file input, so they
+  // don't have to think about the caller type.
+  void GetNonFileValueInternal(nsAString& aValue) const;
 
   /**
-   * Returns whether the current value is the empty string.
+   * Returns whether the current value is the empty string.  This only makes
+   * sense for some input types; does NOT make sense for file inputs.
    *
    * @return whether the current value is the empty string.
    */
   bool IsValueEmpty() const;
 
   void ClearFiles(bool aSetValueChanged);
 
   void SetIndeterminateInternal(bool aValue,
--- a/dom/html/RadioNodeList.cpp
+++ b/dom/html/RadioNodeList.cpp
@@ -27,40 +27,40 @@ GetAsRadio(nsIContent* node)
   HTMLInputElement* el = HTMLInputElement::FromContent(node);
   if (el && el->GetType() == NS_FORM_INPUT_RADIO) {
     return el;
   }
   return nullptr;
 }
 
 void
-RadioNodeList::GetValue(nsString& retval)
+RadioNodeList::GetValue(nsString& retval, CallerType aCallerType)
 {
   for (uint32_t i = 0; i < Length(); i++) {
     HTMLInputElement* maybeRadio = GetAsRadio(Item(i));
     if (maybeRadio && maybeRadio->Checked()) {
-      maybeRadio->GetValue(retval);
+      maybeRadio->GetValue(retval, aCallerType);
       return;
     }
   }
   retval.Truncate();
 }
 
 void
-RadioNodeList::SetValue(const nsAString& value)
+RadioNodeList::SetValue(const nsAString& value, CallerType aCallerType)
 {
   for (uint32_t i = 0; i < Length(); i++) {
 
     HTMLInputElement* maybeRadio = GetAsRadio(Item(i));
     if (!maybeRadio) {
       continue;
     }
 
     nsString curval = nsString();
-    maybeRadio->GetValue(curval);
+    maybeRadio->GetValue(curval, aCallerType);
     if (curval.Equals(value)) {
       maybeRadio->SetChecked(true);
       return;
     }
 
   }
 }
 
--- a/dom/html/RadioNodeList.h
+++ b/dom/html/RadioNodeList.h
@@ -5,32 +5,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_RadioNodeList_h
 #define mozilla_dom_RadioNodeList_h
 
 #include "nsContentList.h"
 #include "nsCOMPtr.h"
 #include "HTMLFormElement.h"
+#include "mozilla/dom/BindingDeclarations.h"
 
 #define MOZILLA_DOM_RADIONODELIST_IMPLEMENTATION_IID \
   { 0xbba7f3e8, 0xf3b5, 0x42e5, \
   { 0x82, 0x08, 0xa6, 0x8b, 0xe0, 0xbc, 0x22, 0x19 } }
 
 namespace mozilla {
 namespace dom {
 
 class RadioNodeList : public nsSimpleContentList
 {
 public:
   explicit RadioNodeList(HTMLFormElement* aForm) : nsSimpleContentList(aForm) { }
 
   virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
-  void GetValue(nsString& retval);
-  void SetValue(const nsAString& value);
+  void GetValue(nsString& retval, CallerType aCallerType);
+  void SetValue(const nsAString& value, CallerType aCallerType);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_RADIONODELIST_IMPLEMENTATION_IID)
 private:
   ~RadioNodeList() { }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(RadioNodeList, MOZILLA_DOM_RADIONODELIST_IMPLEMENTATION_IID)
--- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl
@@ -63,17 +63,16 @@ interface nsIDOMHTMLInputElement : nsISu
            attribute DOMString             align;
 
            attribute unsigned long         size;
            attribute unsigned long width;
            attribute DOMString             src;
 
            attribute DOMString             type;
            attribute DOMString             defaultValue;
-           attribute DOMString             value;
           // 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:
@@ -88,16 +87,15 @@ interface nsIDOMHTMLInputElement : nsISu
            attribute long                  selectionStart;
            attribute long                  selectionEnd;
   void setSelectionRange(in long selectionStart, in long selectionEnd, [optional] in DOMString direction);
            attribute DOMString             selectionDirection;
 
 
            attribute DOMString             useMap;
   readonly attribute nsIControllers        controllers;	
-	readonly attribute long                  textLength;
 
   /**
    * This non-standard method prevents to check types manually to know if the
    * element is a text field.
    */
   boolean mozIsTextField(in boolean aExcludePassword);
 };
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -141,17 +141,18 @@ partial interface HTMLInputElement {
 // Mozilla extensions
 
 partial interface HTMLInputElement {
   [Throws]
   void setSelectionRange(long start, long end, optional DOMString direction);
 
   [GetterThrows, ChromeOnly]
   readonly attribute nsIControllers        controllers;
-  [GetterThrows]
+  // Binaryname because we have a FragmentOrElement function named "TextLength()".
+  [NeedsCallerType, BinaryName="inputTextLength"]
   readonly attribute long                  textLength;
 
   [Throws, ChromeOnly]
   sequence<DOMString> mozGetFileNameArray();
 
   [ChromeOnly, Throws]
   void mozSetFileNameArray(sequence<DOMString> fileNames);
 
--- a/dom/webidl/RadioNodeList.webidl
+++ b/dom/webidl/RadioNodeList.webidl
@@ -7,10 +7,11 @@
  * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlformcontrolscollection-0
  *
  * © Copyright 2004-2014 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 interface RadioNodeList : NodeList {
+  [NeedsCallerType]
   attribute DOMString value;
 };
--- a/embedding/components/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
+++ b/embedding/components/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
@@ -1196,17 +1196,18 @@ PersistNodeFixup::FixupNode(nsIDOMNode *
     if (nodeAsIFrame) {
         rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
-        nsCOMPtr<nsIDOMHTMLInputElement> nodeAsInput = do_QueryInterface(aNodeIn);
+    RefPtr<dom::HTMLInputElement> nodeAsInput =
+        dom::HTMLInputElement::FromContentOrNull(content);
     if (nodeAsInput) {
         rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             // Disable image loads
             nsCOMPtr<nsIImageLoadingContent> imgCon =
                 do_QueryInterface(*aNodeOut);
             if (imgCon) {
                 imgCon->SetLoadingEnabled(false);
@@ -1227,28 +1228,29 @@ PersistNodeFixup::FixupNode(nsIDOMNode *
                 case NS_FORM_INPUT_TEXT:
                 case NS_FORM_INPUT_TEL:
                 case NS_FORM_INPUT_URL:
                 case NS_FORM_INPUT_NUMBER:
                 case NS_FORM_INPUT_RANGE:
                 case NS_FORM_INPUT_DATE:
                 case NS_FORM_INPUT_TIME:
                 case NS_FORM_INPUT_COLOR:
-                    nodeAsInput->GetValue(valueStr);
+                    nodeAsInput->GetValue(valueStr, dom::CallerType::System);
                     // Avoid superfluous value="" serialization
                     if (valueStr.IsEmpty())
                       outElt->RemoveAttribute(valueAttr);
                     else
                       outElt->SetAttribute(valueAttr, valueStr);
                     break;
                 case NS_FORM_INPUT_CHECKBOX:
                 case NS_FORM_INPUT_RADIO:
-                    bool checked;
-                    nodeAsInput->GetChecked(&checked);
-                    outElt->SetDefaultChecked(checked);
+                    {
+                        bool checked = nodeAsInput->Checked();
+                        outElt->SetDefaultChecked(checked);
+                    }
                     break;
                 default:
                     break;
             }
         }
         return rv;
     }
 
--- a/layout/forms/nsColorControlFrame.cpp
+++ b/layout/forms/nsColorControlFrame.cpp
@@ -6,24 +6,26 @@
 #include "nsColorControlFrame.h"
 
 #include "nsContentCreatorFunctions.h"
 #include "nsContentList.h"
 #include "nsContentUtils.h"
 #include "nsCSSPseudoElements.h"
 #include "nsFormControlFrame.h"
 #include "nsGkAtoms.h"
-#include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNode.h"
 #include "nsIFormControl.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
+#include "mozilla/dom/HTMLInputElement.h"
 #include "nsIDocument.h"
 
 using mozilla::dom::Element;
+using mozilla::dom::HTMLInputElement;
+using mozilla::dom::CallerType;
 
 nsColorControlFrame::nsColorControlFrame(nsStyleContext* aContext)
   : nsHTMLButtonControlFrame(aContext)
 {
 }
 
 nsIFrame*
 NS_NewColorControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
@@ -95,18 +97,18 @@ nsColorControlFrame::AppendAnonymousCont
 }
 
 nsresult
 nsColorControlFrame::UpdateColor()
 {
   // Get the color from the "value" property of our content; it will return the
   // default color (through the sanitization algorithm) if there is none.
   nsAutoString color;
-  nsCOMPtr<nsIDOMHTMLInputElement> elt = do_QueryInterface(mContent);
-  elt->GetValue(color);
+  HTMLInputElement* elt = HTMLInputElement::FromContent(mContent);
+  elt->GetValue(color, CallerType::System);
   MOZ_ASSERT(!color.IsEmpty(),
              "Content node's GetValue() should return a valid color string "
              "(the default color, in case no valid color is set)");
 
   // Set the background-color style property of the swatch element to this color
   return mColorContent->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
       NS_LITERAL_STRING("background-color:") + color, true);
 }
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -3,16 +3,17 @@
  * 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 "nsGfxButtonControlFrame.h"
 #include "nsIFormControl.h"
 #include "nsGkAtoms.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
+#include "mozilla/dom/HTMLInputElement.h"
 #include "nsContentUtils.h"
 // MouseEvent suppression in PP
 #include "nsContentList.h"
 
 #include "nsIDOMHTMLInputElement.h"
 #include "nsTextNode.h"
 
 using namespace mozilla;
@@ -134,30 +135,29 @@ nsGfxButtonControlFrame::GetDefaultLabel
                                             prop, aString);
 }
 
 nsresult
 nsGfxButtonControlFrame::GetLabel(nsXPIDLString& aLabel)
 {
   // Get the text from the "value" property on our content if there is
   // one; otherwise set it to a default value (localized).
-  nsresult rv;
-  nsCOMPtr<nsIDOMHTMLInputElement> elt = do_QueryInterface(mContent);
+  dom::HTMLInputElement* elt = dom::HTMLInputElement::FromContent(mContent);
   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value) && elt) {
-    rv = elt->GetValue(aLabel);
+    elt->GetValue(aLabel, dom::CallerType::System);
   } else {
     // Generate localized label.
     // We can't make any assumption as to what the default would be
     // because the value is localized for non-english platforms, thus
     // it might not be the string "Reset", "Submit Query", or "Browse..."
+    nsresult rv;
     rv = GetDefaultLabel(aLabel);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Compress whitespace out of label if needed.
   if (!StyleText()->WhiteSpaceIsSignificant()) {
     aLabel.CompressWhitespace();
   } else if (aLabel.Length() > 2 && aLabel.First() == ' ' &&
              aLabel.CharAt(aLabel.Length() - 1) == ' ') {
     // This is a bit of a hack.  The reason this is here is as follows: we now
     // have default padding on our buttons to make them non-ugly.
     // Unfortunately, IE-windows does not have such padding, so people will
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -399,17 +399,17 @@ nsNumberControlFrame::CreateAnonymousCon
   mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                       NS_LITERAL_STRING("text"), PR_FALSE);
 
   HTMLInputElement* content = HTMLInputElement::FromContent(mContent);
   HTMLInputElement* textField = HTMLInputElement::FromContent(mTextField);
 
   // Initialize the text field value:
   nsAutoString value;
-  content->GetValue(value);
+  content->GetValue(value, CallerType::System);
   SetValueOfAnonTextControl(value);
 
   // If we're readonly, make sure our anonymous text control is too:
   nsAutoString readonly;
   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly)) {
     mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly, false);
   }
 
@@ -704,17 +704,17 @@ nsNumberControlFrame::SetValueOfAnonText
 void
 nsNumberControlFrame::GetValueOfAnonTextControl(nsAString& aValue)
 {
   if (!mTextField) {
     aValue.Truncate();
     return;
   }
 
-  HTMLInputElement::FromContent(mTextField)->GetValue(aValue);
+  HTMLInputElement::FromContent(mTextField)->GetValue(aValue, CallerType::System);
 
 #ifdef ENABLE_INTL_API
   // Here we need to de-localize any number typed in by the user. That is, we
   // need to convert it from the number format of the user's language, region,
   // etc. to the format that the HTML 5 spec defines to be a "valid
   // floating-point number":
   //
   //   http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#floating-point-numbers
@@ -757,17 +757,17 @@ nsNumberControlFrame::GetValueOfAnonText
 
 bool
 nsNumberControlFrame::AnonTextControlIsEmpty()
 {
   if (!mTextField) {
     return true;
   }
   nsAutoString value;
-  HTMLInputElement::FromContent(mTextField)->GetValue(value);
+  HTMLInputElement::FromContent(mTextField)->GetValue(value, CallerType::System);
   return value.IsEmpty();
 }
 
 Element*
 nsNumberControlFrame::GetPseudoElement(CSSPseudoElementType aType)
 {
   if (aType == CSSPseudoElementType::mozNumberWrapper) {
     return mOuterWrapper;
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -3,16 +3,17 @@
 /* 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 "nsFormFillController.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
+#include "mozilla/dom/HTMLInputElement.h"
 #include "nsIFormAutoComplete.h"
 #include "nsIInputListAutoComplete.h"
 #include "nsIAutoCompleteSimpleResult.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsIServiceManager.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
@@ -497,17 +498,19 @@ nsFormFillController::GetSearchAt(uint32
   _retval.AssignLiteral("form-history");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetTextValue(nsAString & aTextValue)
 {
   if (mFocusedInput) {
-    mFocusedInput->GetValue(aTextValue);
+    nsCOMPtr<nsIContent> content = do_QueryInterface(mFocusedInput);
+    HTMLInputElement::FromContent(content)->GetValue(aTextValue,
+                                                     CallerType::System);
   } else {
     aTextValue.Truncate();
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::SetTextValue(const nsAString & aTextValue)