Bug 1340483 - Part 3. Enable preview function only when input is marked as autofill field. r=heycam draft
authorRay Lin <ralin@mozilla.com>
Wed, 22 Mar 2017 16:55:56 +0800
changeset 564426 253f102b30031e2ad86fd2578297ff3ce2b4f5c0
parent 564425 6f0ad39d8e31ac0e680c5d3ee9b2ea705da0e94e
child 564427 75e7f7cbd512dee072b2e7fc6f384e989956e9a3
push id54590
push userbmo:ralin@mozilla.com
push dateTue, 18 Apr 2017 14:37:59 +0000
reviewersheycam
bugs1340483
milestone55.0a1
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);
     }
   }