Bug 1378754 - Don't clear marked fields in nsFormFillController upon a persisted pagehide. r=smaug draft
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Fri, 21 Jul 2017 13:32:48 -0700
changeset 613425 c73d1c75f83517c23750e5d3e8c7ab54976630f5
parent 613424 f5e953ff49fd1aab54e48186d78bacd2e5c80238
child 613426 1230a3e148c4ee81fddb5564213a369a9e7a1089
child 613653 7233559b7bfb89a64d20e61113df58ddb6eb021b
push id69793
push usermozilla@noorenberghe.ca
push dateFri, 21 Jul 2017 22:32:34 +0000
reviewerssmaug
bugs1378754
milestone56.0a1
Bug 1378754 - Don't clear marked fields in nsFormFillController upon a persisted pagehide. r=smaug While moving to a new window (using SwapDocShells), a pagehide event[1] is dispatched causing nsFormFillController to clean up mPwmgrInputs and mAutofillInputs for the document. This commit changes the pagehide handler to not clear the hash tables or mutation observers with persisted=true (which would also fix the same bug in password manager autocomplete). This approach comes at the cost of increased memory (hash table entries for fields in session history) but would reduce CPU usage compared to the alternative of re-marking password manager and autofill fields upon every pageshow event. This approach also solves the issue of autofill and password manager autocomplete not working after session history navigation. [1] https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Method/SwapDocShells MozReview-Commit-ID: 8DFWuFynDex
toolkit/components/satchel/nsFormFillController.cpp
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -6,16 +6,17 @@
 
 #include "nsFormFillController.h"
 
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
 #include "mozilla/dom/HTMLInputElement.h"
+#include "mozilla/dom/PageTransitionEvent.h"
 #include "mozilla/Logging.h"
 #include "nsIFormAutoComplete.h"
 #include "nsIInputListAutoComplete.h"
 #include "nsIAutoCompleteSimpleResult.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsIServiceManager.h"
 #include "nsIInterfaceRequestor.h"
@@ -976,31 +977,38 @@ nsFormFillController::HandleEvent(nsIDOM
       }
 
       if (mFocusedInput) {
         if (doc == mFocusedInputNode->OwnerDoc()) {
           StopControllingInput();
         }
       }
 
-      RemoveForDocument(doc);
+      // Only remove the observer notifications and marked autofill and password
+      // manager fields if the page isn't going to be persisted (i.e. it's being
+      // unloaded) so that appropriate autocomplete handling works with bfcache.
+      bool persisted = aEvent->InternalDOMEvent()->AsPageTransitionEvent()->Persisted();
+      if (!persisted) {
+        RemoveForDocument(doc);
+      }
     }
     break;
   default:
     // Handling the default case to shut up stupid -Wswitch warnings.
     // One day compilers will be smarter...
     break;
   }
 
   return NS_OK;
 }
 
 void
 nsFormFillController::RemoveForDocument(nsIDocument* aDoc)
 {
+  MOZ_LOG(sLogger, LogLevel::Verbose, ("RemoveForDocument: %p", aDoc));
   for (auto iter = mPwmgrInputs.Iter(); !iter.Done(); iter.Next()) {
     const nsINode* key = iter.Key();
     if (key && (!aDoc || key->OwnerDoc() == aDoc)) {
       // mFocusedInputNode's observer is tracked separately, so don't remove it
       // here.
       if (key != mFocusedInputNode) {
         const_cast<nsINode*>(key)->RemoveMutationObserver(this);
       }