Bug 1340483 - Part 3. Enable preview function only when input is marked as autofill field. r=heycam
authorRay Lin <ralin@mozilla.com>
Wed, 22 Mar 2017 16:55:56 +0800
changeset 353645 02c944a0dca49bc7c85c2d5db4beaba3627d5281
parent 353644 c3dfc1597192b4530bcb362c78e1799bc7c832bf
child 353646 6da00d83aa3c910d0715e36606f354a4cef36ab3
push id31675
push usercbook@mozilla.com
push dateWed, 19 Apr 2017 08:28:05 +0000
treeherdermozilla-central@245811243903 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1340483
milestone55.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 1340483 - Part 3. Enable preview function only when input is marked as autofill field. r=heycam MozReview-Commit-ID: FFqYJ3icRd7
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/HTMLTextAreaElement.cpp
dom/html/HTMLTextAreaElement.h
dom/html/nsITextControlElement.h
layout/forms/nsTextControlFrame.cpp
layout/forms/nsTextControlFrame.h
toolkit/components/satchel/nsFormFillController.cpp
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1094,16 +1094,17 @@ HTMLInputElement::HTMLInputElement(alrea
   , mCanShowValidUI(true)
   , mCanShowInvalidUI(true)
   , mHasRange(false)
   , mIsDraggingRange(false)
   , mNumberControlSpinnerIsSpinning(false)
   , mNumberControlSpinnerSpinsUp(false)
   , mPickerRunning(false)
   , mSelectionCached(true)
+  , mIsPreviewEnabled(false)
 {
   // We are in a type=text so we now we currenty need a nsTextEditorState.
   mInputData.mState =
     nsTextEditorState::Construct(this, &sCachedTextEditorState);
 
   if (!gUploadLastDir)
     HTMLInputElement::InitUploadLastDir();
 
@@ -2925,16 +2926,34 @@ NS_IMETHODIMP_(void)
 HTMLInputElement::GetPreviewValue(nsAString& aValue)
 {
   nsTextEditorState* state = GetEditorState();
   if (state) {
     state->GetPreviewText(aValue);
   }
 }
 
+NS_IMETHODIMP_(void)
+HTMLInputElement::EnablePreview()
+{
+  if (mIsPreviewEnabled) {
+    return;
+  }
+
+  mIsPreviewEnabled = true;
+  // Reconstruct the frame to append an anonymous preview node
+  nsLayoutUtils::PostRestyleEvent(this, nsRestyleHint(0), nsChangeHint_ReconstructFrame);
+}
+
+NS_IMETHODIMP_(bool)
+HTMLInputElement::IsPreviewEnabled()
+{
+  return mIsPreviewEnabled;
+}
+
 void
 HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
 {
   if (OwnerDoc()->IsStaticDocument()) {
     aValue = mStaticDocFileList;
     return;
   }
 
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -234,16 +234,18 @@ public:
   NS_IMETHOD_(Element*) GetRootEditorNode() override;
   NS_IMETHOD_(Element*) CreatePlaceholderNode() override;
   NS_IMETHOD_(Element*) GetPlaceholderNode() override;
   NS_IMETHOD_(Element*) CreatePreviewNode() override;
   NS_IMETHOD_(Element*) GetPreviewNode() override;
   NS_IMETHOD_(void) UpdatePlaceholderVisibility(bool aNotify) override;
   NS_IMETHOD_(void) SetPreviewValue(const nsAString& aValue) override;
   NS_IMETHOD_(void) GetPreviewValue(nsAString& aValue) override;
+  NS_IMETHOD_(void) EnablePreview() override;
+  NS_IMETHOD_(bool) IsPreviewEnabled() override;
   NS_IMETHOD_(bool) GetPlaceholderVisibility() override;
   NS_IMETHOD_(void) InitializeKeyboardEventListeners() override;
   NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override;
   virtual void GetValueFromSetRangeText(nsAString& aValue) override;
   virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override;
   NS_IMETHOD_(bool) HasCachedSelection() override;
 
   // Methods for nsFormFillController so it can do selection operations on input
@@ -1635,16 +1637,17 @@ protected:
   bool                     mCanShowValidUI      : 1;
   bool                     mCanShowInvalidUI    : 1;
   bool                     mHasRange            : 1;
   bool                     mIsDraggingRange     : 1;
   bool                     mNumberControlSpinnerIsSpinning : 1;
   bool                     mNumberControlSpinnerSpinsUp : 1;
   bool                     mPickerRunning : 1;
   bool                     mSelectionCached : 1;
+  bool                     mIsPreviewEnabled : 1;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     GenericSpecifiedValues* aGenericData);
 
   /**
    * Returns true if this input's type will fire a DOM "change" event when it
    * loses focus if its value has changed since it gained focus.
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -57,16 +57,17 @@ HTMLTextAreaElement::HTMLTextAreaElement
     mValueChanged(false),
     mLastValueChangeWasInteractive(false),
     mHandlingSelect(false),
     mDoneAddingChildren(!aFromParser),
     mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
     mDisabledChanged(false),
     mCanShowInvalidUI(true),
     mCanShowValidUI(true),
+    mIsPreviewEnabled(false),
     mState(this)
 {
   AddMutationObserver(this);
 
   // 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
@@ -340,16 +341,34 @@ HTMLTextAreaElement::SetPreviewValue(con
 }
 
 NS_IMETHODIMP_(void)
 HTMLTextAreaElement::GetPreviewValue(nsAString& aValue)
 {
   mState.GetPreviewText(aValue);
 }
 
+NS_IMETHODIMP_(void)
+HTMLTextAreaElement::EnablePreview()
+{
+  if (mIsPreviewEnabled) {
+    return;
+  }
+
+  mIsPreviewEnabled = true;
+  // Reconstruct the frame to append an anonymous preview node
+  nsLayoutUtils::PostRestyleEvent(this, nsRestyleHint(0), nsChangeHint_ReconstructFrame);
+}
+
+NS_IMETHODIMP_(bool)
+HTMLTextAreaElement::IsPreviewEnabled()
+{
+  return mIsPreviewEnabled;
+}
+
 nsresult
 HTMLTextAreaElement::SetValueInternal(const nsAString& aValue,
                                       uint32_t aFlags)
 {
   // Need to set the value changed flag here if our value has in fact changed
   // (i.e. if eSetValue_Notify is in aFlags), so that
   // nsTextControlFrame::UpdateValueDisplay retrieves the correct value if
   // needed.
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -104,16 +104,18 @@ public:
   NS_IMETHOD_(Element*) CreatePlaceholderNode() override;
   NS_IMETHOD_(Element*) GetPlaceholderNode() override;
   NS_IMETHOD_(Element*) CreatePreviewNode() override;
   NS_IMETHOD_(Element*) GetPreviewNode() override;
   NS_IMETHOD_(void) UpdatePlaceholderVisibility(bool aNotify) override;
   NS_IMETHOD_(bool) GetPlaceholderVisibility() override;
   NS_IMETHOD_(void) SetPreviewValue(const nsAString& aValue) override;
   NS_IMETHOD_(void) GetPreviewValue(nsAString& aValue) override;
+  NS_IMETHOD_(void) EnablePreview() override;
+  NS_IMETHOD_(bool) IsPreviewEnabled() override;
   NS_IMETHOD_(void) InitializeKeyboardEventListeners() override;
   NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override;
   virtual void GetValueFromSetRangeText(nsAString& aValue) override;
   virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override;
   NS_IMETHOD_(bool) HasCachedSelection() override;
 
 
   // nsIContent
@@ -321,16 +323,17 @@ protected:
   /** Whether state restoration should be inhibited in DoneAddingChildren. */
   bool                     mInhibitStateRestoration;
   /** Whether our disabled state has changed from the default **/
   bool                     mDisabledChanged;
   /** Whether we should make :-moz-ui-invalid apply on the element. **/
   bool                     mCanShowInvalidUI;
   /** Whether we should make :-moz-ui-valid apply on the element. **/
   bool                     mCanShowValidUI;
+  bool                     mIsPreviewEnabled;
 
   void FireChangeEventIfNeeded();
 
   nsString mFocusedValue;
 
   /** The state of the text editor (selection controller and the editor) **/
   nsTextEditorState mState;
 
--- a/dom/html/nsITextControlElement.h
+++ b/dom/html/nsITextControlElement.h
@@ -170,16 +170,26 @@ public:
   NS_IMETHOD_(void) SetPreviewValue(const nsAString& aValue) = 0;
 
   /**
    * Get the current preview value for text control.
    */
   NS_IMETHOD_(void) GetPreviewValue(nsAString& aValue) = 0;
 
   /**
+   * Enable preview for text control.
+   */
+  NS_IMETHOD_(void) EnablePreview() = 0;
+
+  /**
+   * Find out whether this control enables preview for form autofoll.
+   */
+  NS_IMETHOD_(bool) IsPreviewEnabled() = 0;
+
+  /**
    * Initialize the keyboard event listeners.
    */
   NS_IMETHOD_(void) InitializeKeyboardEventListeners() = 0;
 
   /**
    * Update the placeholder visibility based on the element's state.
    */
   NS_IMETHOD_(void) UpdatePlaceholderVisibility(bool aNotify) = 0;
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -104,16 +104,17 @@ private:
 #endif
 
 nsTextControlFrame::nsTextControlFrame(nsStyleContext* aContext)
   : nsContainerFrame(aContext)
   , mFirstBaseline(NS_INTRINSIC_WIDTH_UNKNOWN)
   , mEditorHasBeenInitialized(false)
   , mIsProcessing(false)
   , mUsePlaceholder(false)
+  , mUsePreview(false)
 #ifdef DEBUG
   , mInEditorInitialization(false)
 #endif
 {
 }
 
 nsTextControlFrame::~nsTextControlFrame()
 {
@@ -362,21 +363,25 @@ nsTextControlFrame::CreateAnonymousConte
     if (!IsSingleLineTextControl()) {
       // For textareas, UpdateValueDisplay doesn't initialize the visibility
       // status of the placeholder because it returns early, so we have to
       // do that manually here.
       txtCtrl->UpdatePlaceholderVisibility(true);
     }
   }
 
-  // Create the preview anonymous content if needed.
-  Element* previewNode = txtCtrl->CreatePreviewNode();
-  NS_ENSURE_TRUE(previewNode, NS_ERROR_OUT_OF_MEMORY);
+  mUsePreview = txtCtrl->IsPreviewEnabled();
 
-  aElements.AppendElement(previewNode);
+  if (mUsePreview) {
+    // Create the preview anonymous content if needed.
+    Element* previewNode = txtCtrl->CreatePreviewNode();
+    NS_ENSURE_TRUE(previewNode, NS_ERROR_OUT_OF_MEMORY);
+
+    aElements.AppendElement(previewNode);
+  }
 
   rv = UpdateValueDisplay(false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // textareas are eagerly initialized
   bool initEagerly = !IsSingleLineTextControl();
   if (!initEagerly) {
     // Also, input elements which have a cached selection should get eager
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -334,16 +334,18 @@ private:
   // Reflow.
   nscoord mFirstBaseline;
 
   // these packed bools could instead use the high order bits on mState, saving 4 bytes 
   bool mEditorHasBeenInitialized;
   bool mIsProcessing;
   // Keep track if we have asked a placeholder node creation.
   bool mUsePlaceholder;
+  // Similarly for preview node creation.
+  bool mUsePreview;
 
 #ifdef DEBUG
   bool mInEditorInitialization;
   friend class EditorInitializerEntryTracker;
 #endif
 
   nsRevocableEventPtr<ScrollOnFocusEvent> mScrollEvent;
 };
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -318,16 +318,19 @@ nsFormFillController::MarkAsAutofillFiel
 
   if (mAutofillInputs.Get(node)) {
     return NS_OK;
   }
 
   mAutofillInputs.Put(node, true);
   node->AddMutationObserverUnlessExists(this);
 
+  nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(aInput);
+  txtCtrl->EnablePreview();
+
   nsFocusManager *fm = nsFocusManager::GetFocusManager();
   if (fm) {
     nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
     if (SameCOMIdentity(focusedContent, node)) {
       nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(node);
       MaybeStartControllingInput(input);
     }
   }