Bug 1345767 - Part 1: Create classes for each of the input types. r?smaug draft
authorJessica Jong <jjong@mozilla.com>
Thu, 04 May 2017 11:43:46 +0800
changeset 572487 4249798b4a8ffa744a23baa6eee643bd2313fb28
parent 571618 a748acbebbde373a88868dc02910fb2bc5e6a023
child 572488 9fb270c0527922cdf7319572ddd155094db70bdd
push id57094
push userjjong@mozilla.com
push dateThu, 04 May 2017 07:44:57 +0000
reviewerssmaug
bugs1345767
milestone55.0a1
Bug 1345767 - Part 1: Create classes for each of the input types. r?smaug MozReview-Commit-ID: 4O6YHHGsLBP
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/input/ButtonInputTypes.h
dom/html/input/CheckableInputTypes.h
dom/html/input/ColorInputType.h
dom/html/input/DateTimeInputTypes.h
dom/html/input/FileInputType.h
dom/html/input/HiddenInputType.h
dom/html/input/InputType.cpp
dom/html/input/InputType.h
dom/html/input/NumericInputTypes.h
dom/html/input/SingleLineTextInputTypes.h
dom/html/input/moz.build
dom/html/moz.build
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -17,16 +17,17 @@
 #include "nsAttrValueInlines.h"
 #include "nsCRTGlue.h"
 
 #include "nsIDOMHTMLInputElement.h"
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIPhonetic.h"
+#include "InputType.h"
 
 #include "HTMLFormSubmissionConstants.h"
 #include "mozilla/Telemetry.h"
 #include "nsIControllers.h"
 #include "nsIStringBundle.h"
 #include "nsFocusManager.h"
 #include "nsColorControlFrame.h"
 #include "nsNumberControlFrame.h"
@@ -1177,16 +1178,19 @@ HTMLInputElement::HTMLInputElement(alrea
   static_assert(sizeof(HTMLInputElement) <= 512,
                 "Keep the size of HTMLInputElement under 512 to avoid "
                 "performance regression!");
 
   // We are in a type=text so we now we currenty need a nsTextEditorState.
   mInputData.mState =
     nsTextEditorState::Construct(this, &sCachedTextEditorState);
 
+  void* memory = mInputTypeMem;
+  mInputType = InputType::Create(this, mType, memory);
+
   if (!gUploadLastDir)
     HTMLInputElement::InitUploadLastDir();
 
   // Set up our default state.  By default we're enabled (since we're
   // a control type that can be disabled but not actually disabled
   // right now), optional, and valid.  We are NOT readwrite by default
   // until someone calls UpdateEditableState on us, apparently!  Also
   // by default we don't have to show validity UI and so forth.
@@ -1211,16 +1215,21 @@ HTMLInputElement::FreeData()
   if (!IsSingleLineTextControl(false)) {
     free(mInputData.mValue);
     mInputData.mValue = nullptr;
   } else {
     UnbindFromFrame(nullptr);
     ReleaseTextEditorState(mInputData.mState);
     mInputData.mState = nullptr;
   }
+
+  if (mInputType) {
+    mInputType->DropReference();
+    mInputType = nullptr;
+  }
 }
 
 nsTextEditorState*
 HTMLInputElement::GetEditorState() const
 {
   if (!IsSingleLineTextControl(false)) {
     return nullptr;
   }
@@ -5216,16 +5225,18 @@ HTMLInputElement::HandleTypeChange(uint8
   if (GetEditorState()) {
     mInputData.mState->SyncUpSelectionPropertiesBeforeDestruction();
     sp = mInputData.mState->GetSelectionProperties();
   }
 
   // We already have a copy of the value, lets free it and changes the type.
   FreeData();
   mType = aNewType;
+  void* memory = mInputTypeMem;
+  mInputType = InputType::Create(this, mType, memory);
 
   if (IsSingleLineTextControl()) {
 
     mInputData.mState =
       nsTextEditorState::Construct(this, &sCachedTextEditorState);
     if (!sp.IsDefault()) {
       mInputData.mState->SetSelectionProperties(sp);
     }
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -12,27 +12,48 @@
 #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/UniquePtr.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"
 #include "nsTextEditorState.h"
+#include "mozilla/Variant.h"
+#include "SingleLineTextInputTypes.h"
+#include "NumericInputTypes.h"
+#include "CheckableInputTypes.h"
+#include "ButtonInputTypes.h"
+#include "DateTimeInputTypes.h"
+#include "ColorInputType.h"
+#include "FileInputType.h"
+#include "HiddenInputType.h"
 
+static constexpr size_t INPUT_TYPE_SIZE = sizeof(
+  mozilla::Variant<TextInputType, SearchInputType, TelInputType, URLInputType,
+                   EmailInputType, PasswordInputType, NumberInputType,
+                   RangeInputType, RadioInputType, CheckboxInputType,
+                   ButtonInputType, ImageInputType, ResetInputType,
+                   SubmitInputType, DateInputType, TimeInputType, WeekInputType,
+                   MonthInputType, DateTimeLocalInputType, FileInputType,
+                   ColorInputType, HiddenInputType> );
+
+class InputType;
+struct DoNotDelete;
 class nsIRadioGroupContainer;
 class nsIRadioVisitor;
 
 namespace mozilla {
 
 class EventChainPostVisitor;
 class EventChainPreVisitor;
 
@@ -1558,16 +1579,24 @@ protected:
 
   /**
    * The selection properties cache for number controls.  This is needed because
    * the number controls don't recycle their text field, so the normal cache in
    * nsTextEditorState cannot do its job.
    */
   nsTextEditorState::SelectionProperties mSelectionProperties;
 
+  /*
+   * InputType object created based on input type.
+   */
+  UniquePtr<InputType, DoNotDelete> mInputType;
+
+  // Memory allocated for mInputType, reused when type changes.
+  char mInputTypeMem[INPUT_TYPE_SIZE];
+
   // Step scale factor values, for input types that have one.
   static const Decimal kStepScaleFactorDate;
   static const Decimal kStepScaleFactorNumberRange;
   static const Decimal kStepScaleFactorTime;
   static const Decimal kStepScaleFactorMonth;
   static const Decimal kStepScaleFactorWeek;
 
   // Default step base value when a type do not have specific one.
new file mode 100644
--- /dev/null
+++ b/dom/html/input/ButtonInputTypes.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef ButtonInputTypes_h__
+#define ButtonInputTypes_h__
+
+#include "InputType.h"
+
+class ButtonInputTypeBase : public ::InputType
+{
+public:
+  ~ButtonInputTypeBase() override {}
+
+protected:
+  explicit ButtonInputTypeBase(mozilla::dom::HTMLInputElement* aInputElement)
+    : InputType(aInputElement)
+  {}
+};
+
+// input type=button
+class ButtonInputType : public ButtonInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) ButtonInputType(aInputElement);
+  }
+
+private:
+  explicit ButtonInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : ButtonInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=image
+class ImageInputType : public ButtonInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) ImageInputType(aInputElement);
+  }
+
+private:
+  explicit ImageInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : ButtonInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=reset
+class ResetInputType : public ButtonInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) ResetInputType(aInputElement);
+  }
+
+private:
+  explicit ResetInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : ButtonInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=submit
+class SubmitInputType : public ButtonInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) SubmitInputType(aInputElement);
+  }
+
+private:
+  explicit SubmitInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : ButtonInputTypeBase(aInputElement)
+  {}
+};
+
+#endif /* ButtonInputTypes_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/CheckableInputTypes.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef CheckableInputTypes_h__
+#define CheckableInputTypes_h__
+
+#include "InputType.h"
+
+class CheckableInputTypeBase : public ::InputType
+{
+public:
+  ~CheckableInputTypeBase() override {}
+
+protected:
+  explicit CheckableInputTypeBase(mozilla::dom::HTMLInputElement* aInputElement)
+    : InputType(aInputElement)
+  {}
+};
+
+// input type=checkbox
+class CheckboxInputType : public CheckableInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) CheckboxInputType(aInputElement);
+  }
+
+private:
+  explicit CheckboxInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : CheckableInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=radio
+class RadioInputType : public CheckableInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) RadioInputType(aInputElement);
+  }
+
+private:
+  explicit RadioInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : CheckableInputTypeBase(aInputElement)
+  {}
+};
+
+#endif /* CheckableInputTypes_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/ColorInputType.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef ColorInputType_h__
+#define ColorInputType_h__
+
+#include "InputType.h"
+
+// input type=color
+class ColorInputType : public ::InputType
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) ColorInputType(aInputElement);
+  }
+
+private:
+  explicit ColorInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : InputType(aInputElement)
+  {}
+};
+
+#endif /* ColorInputType_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/DateTimeInputTypes.h
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef DateTimeInputTypes_h__
+#define DateTimeInputTypes_h__
+
+#include "InputType.h"
+
+class DateTimeInputTypeBase : public ::InputType
+{
+public:
+  ~DateTimeInputTypeBase() override {}
+
+protected:
+  explicit DateTimeInputTypeBase(mozilla::dom::HTMLInputElement* aInputElement)
+    : InputType(aInputElement)
+  {}
+};
+
+// input type=date
+class DateInputType : public DateTimeInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) DateInputType(aInputElement);
+  }
+
+private:
+  explicit DateInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : DateTimeInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=time
+class TimeInputType : public DateTimeInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) TimeInputType(aInputElement);
+  }
+
+private:
+  explicit TimeInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : DateTimeInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=week
+class WeekInputType : public DateTimeInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) WeekInputType(aInputElement);
+  }
+
+private:
+  explicit WeekInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : DateTimeInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=month
+class MonthInputType : public DateTimeInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) MonthInputType(aInputElement);
+  }
+
+private:
+  explicit MonthInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : DateTimeInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=datetime-local
+class DateTimeLocalInputType : public DateTimeInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) DateTimeLocalInputType(aInputElement);
+  }
+
+private:
+  explicit DateTimeLocalInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : DateTimeInputTypeBase(aInputElement)
+  {}
+};
+
+
+#endif /* DateTimeInputTypes_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/FileInputType.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef FileInputType_h__
+#define FileInputType_h__
+
+#include "InputType.h"
+
+// input type=file
+class FileInputType : public ::InputType
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) FileInputType(aInputElement);
+  }
+
+private:
+  explicit FileInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : InputType(aInputElement)
+  {}
+};
+
+#endif /* FileInputType_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/HiddenInputType.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef HiddenInputType_h__
+#define HiddenInputType_h__
+
+#include "InputType.h"
+
+// input type=hidden
+class HiddenInputType : public ::InputType
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) HiddenInputType(aInputElement);
+  }
+
+private:
+  explicit HiddenInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : InputType(aInputElement)
+  {}
+};
+
+#endif /* HiddenInputType_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/InputType.cpp
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "InputType.h"
+
+#include "nsIFormControl.h"
+#include "ButtonInputTypes.h"
+#include "CheckableInputTypes.h"
+#include "ColorInputType.h"
+#include "DateTimeInputTypes.h"
+#include "FileInputType.h"
+#include "HiddenInputType.h"
+#include "NumericInputTypes.h"
+#include "SingleLineTextInputTypes.h"
+
+
+/* static */ mozilla::UniquePtr<InputType, DoNotDelete>
+InputType::Create(mozilla::dom::HTMLInputElement* aInputElement, uint8_t aType,
+                  void* aMemory)
+{
+  mozilla::UniquePtr<InputType, DoNotDelete> inputType;
+  switch(aType) {
+    // Single line text
+    case NS_FORM_INPUT_TEXT:
+      inputType.reset(TextInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_TEL:
+      inputType.reset(TelInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_EMAIL:
+      inputType.reset(EmailInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_SEARCH:
+      inputType.reset(SearchInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_PASSWORD:
+      inputType.reset(PasswordInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_URL:
+      inputType.reset(URLInputType::Create(aInputElement, aMemory));
+      break;
+    // Button
+    case NS_FORM_INPUT_BUTTON:
+      inputType.reset(ButtonInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_SUBMIT:
+      inputType.reset(SubmitInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_IMAGE:
+      inputType.reset(ImageInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_RESET:
+      inputType.reset(ResetInputType::Create(aInputElement, aMemory));
+      break;
+    // Checkable
+    case NS_FORM_INPUT_CHECKBOX:
+      inputType.reset(CheckboxInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_RADIO:
+      inputType.reset(RadioInputType::Create(aInputElement, aMemory));
+      break;
+    // Numeric
+    case NS_FORM_INPUT_NUMBER:
+      inputType.reset(NumberInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_RANGE:
+      inputType.reset(RangeInputType::Create(aInputElement, aMemory));
+      break;
+    // DateTime
+    case NS_FORM_INPUT_DATE:
+      inputType.reset(DateInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_TIME:
+      inputType.reset(TimeInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_MONTH:
+      inputType.reset(MonthInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_WEEK:
+      inputType.reset(WeekInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_DATETIME_LOCAL:
+      inputType.reset(DateTimeLocalInputType::Create(aInputElement, aMemory));
+      break;
+    // Others
+    case NS_FORM_INPUT_COLOR:
+      inputType.reset(ColorInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_FILE:
+      inputType.reset(FileInputType::Create(aInputElement, aMemory));
+      break;
+    case NS_FORM_INPUT_HIDDEN:
+      inputType.reset(HiddenInputType::Create(aInputElement, aMemory));
+      break;
+    default:
+      inputType.reset(TextInputType::Create(aInputElement, aMemory));
+  }
+
+  return inputType;
+}
+
+void
+InputType::DropReference()
+{
+  // Drop our (non ref-counted) reference.
+  mInputElement = nullptr;
+}
new file mode 100644
--- /dev/null
+++ b/dom/html/input/InputType.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef InputType_h__
+#define InputType_h__
+
+#include <stdint.h>
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+namespace dom {
+class HTMLInputElement;
+} // namespace dom
+} // namespace mozilla
+
+struct DoNotDelete;
+
+/**
+ * A common superclass for different types of a HTMLInputElement.
+ */
+class InputType
+{
+public:
+  static mozilla::UniquePtr<InputType, DoNotDelete>
+  Create(mozilla::dom::HTMLInputElement* aInputElement, uint8_t aType,
+         void* aMemory);
+
+  virtual ~InputType() {}
+
+  /**
+   * Drop the reference to the input element.
+   */
+  void DropReference();
+
+protected:
+  explicit InputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : mInputElement(aInputElement)
+  {}
+
+  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__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/NumericInputTypes.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef NumericInputTypes_h__
+#define NumericInputTypes_h__
+
+#include "InputType.h"
+
+class NumericInputTypeBase : public ::InputType
+{
+public:
+  ~NumericInputTypeBase() override {}
+
+protected:
+  explicit NumericInputTypeBase(mozilla::dom::HTMLInputElement* aInputElement)
+    : InputType(aInputElement)
+  {}
+};
+
+// input type=number
+class NumberInputType : public NumericInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) NumberInputType(aInputElement);
+  }
+
+private:
+  explicit NumberInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : NumericInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=range
+class RangeInputType : public NumericInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) RangeInputType(aInputElement);
+  }
+
+private:
+  explicit RangeInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : NumericInputTypeBase(aInputElement)
+  {}
+};
+
+#endif /* NumericInputTypes_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/SingleLineTextInputTypes.h
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef SingleLineTextInputTypes_h__
+#define SingleLineTextInputTypes_h__
+
+#include "InputType.h"
+
+class SingleLineTextInputTypeBase : public ::InputType
+{
+public:
+  ~SingleLineTextInputTypeBase() override {}
+
+protected:
+  explicit SingleLineTextInputTypeBase(
+    mozilla::dom::HTMLInputElement* aInputElement)
+      : InputType(aInputElement)
+  {}
+};
+
+// input type=text
+class TextInputType : public SingleLineTextInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) TextInputType(aInputElement);
+  }
+
+private:
+  explicit TextInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : SingleLineTextInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=search
+class SearchInputType : public SingleLineTextInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) SearchInputType(aInputElement);
+  }
+
+private:
+  explicit SearchInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : SingleLineTextInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=tel
+class TelInputType : public SingleLineTextInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) TelInputType(aInputElement);
+  }
+
+private:
+  explicit TelInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : SingleLineTextInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=url
+class URLInputType : public SingleLineTextInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) URLInputType(aInputElement);
+  }
+
+private:
+  explicit URLInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : SingleLineTextInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=email
+class EmailInputType : public SingleLineTextInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) EmailInputType(aInputElement);
+  }
+
+private:
+  explicit EmailInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : SingleLineTextInputTypeBase(aInputElement)
+  {}
+};
+
+// input type=password
+class PasswordInputType : public SingleLineTextInputTypeBase
+{
+public:
+  static InputType*
+  Create(mozilla::dom::HTMLInputElement* aInputElement, void* aMemory)
+  {
+    return new (aMemory) PasswordInputType(aInputElement);
+  }
+
+private:
+  explicit PasswordInputType(mozilla::dom::HTMLInputElement* aInputElement)
+    : SingleLineTextInputTypeBase(aInputElement)
+  {}
+};
+
+#endif /* SingleLineTextInputTypes_h__ */
new file mode 100644
--- /dev/null
+++ b/dom/html/input/moz.build
@@ -0,0 +1,34 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXPORTS += [
+    'ButtonInputTypes.h',
+    'CheckableInputTypes.h',
+    'ColorInputType.h',
+    'DateTimeInputTypes.h',
+    'FileInputType.h',
+    'HiddenInputType.h',
+    'InputType.h',
+    'NumericInputTypes.h',
+    'SingleLineTextInputTypes.h',
+]
+
+UNIFIED_SOURCES += [
+    'InputType.cpp',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+LOCAL_INCLUDES += [
+    '/dom/base',
+    '/dom/html',
+]
+
+FINAL_LIBRARY = 'xul'
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
+
--- a/dom/html/moz.build
+++ b/dom/html/moz.build
@@ -2,16 +2,18 @@
 # vim: set filetype=python:
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
+DIRS += ['input']
+
 MOCHITEST_MANIFESTS += [
     'test/forms/mochitest.ini',
     'test/imports/mochitest.ini',
     'test/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += [
     'test/chrome.ini',
@@ -227,16 +229,17 @@ EXTRA_COMPONENTS += [
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/caps',
     '/docshell/base',
     '/dom/base',
     '/dom/canvas',
+    '/dom/html/input',
     '/dom/media/',
     '/dom/xbl',
     '/dom/xul',
     '/editor/txmgr',
     '/image',
     '/layout/forms',
     '/layout/generic',
     '/layout/style',