Bug 1378754 - Don't clear marked fields in nsFormFillController upon a persisted pagehide. r=smaug
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Fri, 21 Jul 2017 13:32:48 -0700
changeset 419655 b5a0702e2572a8d87541903a11dabd2b238c412e
parent 419654 af4e5e48ca54ae91255fab74c415182268921f31
child 419656 d9fa2317c55a6480e534f6264a92042fea9cc2df
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1378754
milestone56.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 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);
       }