Bug 1330228 - Use HasBeenTypePassword to skip saving to presentation state. r=baku
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Fri, 21 Dec 2018 16:44:37 +0000
changeset 508846 8420eec6f0cccd845d587b47208498fdaba914dc
parent 508845 df443391eddaf7e16a852ecd71aa8fa361cc3cc4
child 508847 fa89cf35d16f3402c60e204836d533f2e9cb36e1
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1330228
milestone66.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 1330228 - Use HasBeenTypePassword to skip saving to presentation state. r=baku Differential Revision: https://phabricator.services.mozilla.com/D15148
dom/base/test/345339_iframe.html
dom/base/test/test_bug345339.html
dom/html/HTMLInputElement.cpp
dom/html/test/forms/file_login_fields.html
dom/html/test/forms/mochitest.ini
dom/html/test/forms/test_input_hasBeenTypePassword_navigation.html
--- a/dom/base/test/345339_iframe.html
+++ b/dom/base/test/345339_iframe.html
@@ -16,12 +16,14 @@
            checked="checked" />
     <input type="radio" id="radio2" name="answer" value="No" />
   </form>
 
   <input type="password" id="password" />
 
   <input type="hidden" id="hidden" />
 
+  <input id="passwordToggle" />
+
   <input type="file" id="file" />
   </p>
  </body>
 </html>
--- a/dom/base/test/test_bug345339.html
+++ b/dom/base/test/test_bug345339.html
@@ -30,16 +30,22 @@ function afterLoad() {
     var iframeDoc = $("testframe").contentDocument;
 
     /* change all the form controls */
     iframeDoc.getElementById("select").selectedIndex = 1;
     iframeDoc.getElementById("radio2").checked = true;
     iframeDoc.getElementById("password").value = "123456";
     iframeDoc.getElementById("hidden").value = "gecko";
 
+    // Toggle the one field to a password type then text type like password
+    // visibility toggles on the web do.
+    iframeDoc.getElementById("passwordToggle").type = "password";
+    iframeDoc.getElementById("passwordToggle").value = "abcdef";
+    iframeDoc.getElementById("passwordToggle").type = "";
+
     SpecialPowers.wrap(iframeDoc).getElementById("file").mozSetFileArray([file]);
 
     /* Reload the page */
     $("testframe").setAttribute("onload", "afterReload()");
     iframeDoc.location.reload();
 }
 
 addLoadEvent(afterLoad);
@@ -52,16 +58,18 @@ function afterReload() {
     is(iframeDoc.getElementById("radio1").checked, false,
        "radio button #1 value preserved");
     is(iframeDoc.getElementById("radio2").checked, true,
        "radio button #2 value preserved");
     isnot(iframeDoc.getElementById("password").value, "123456",
        "password field value forgotten");
     is(iframeDoc.getElementById("hidden").value, "gecko",
        "hidden field value preserved");
+    is(iframeDoc.getElementById("passwordToggle").value, "",
+       "former password field value not saved");
 
     // The new file object isn't ===, but it's extensionally equal:
     let newFile = iframeDoc.getElementById("file").files[0];
     for (let prop of ["name", "lastModified", "size", "type"]) {
         is(newFile[prop], file[prop],
            "file field " + prop + " property preserved");
     }
     let reader = new FileReader();
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -5819,21 +5819,21 @@ HTMLInputElement::SaveState() {
 
         state->contentData() =
             SaveFileContentData(mFileData->mFilesOrDirectories);
       }
       break;
     case VALUE_MODE_VALUE:
     case VALUE_MODE_DEFAULT:
       // VALUE_MODE_DEFAULT shouldn't have their value saved except 'hidden',
-      // mType shouldn't be NS_FORM_INPUT_PASSWORD and value should have
-      // changed.
+      // mType should have never been NS_FORM_INPUT_PASSWORD and value should
+      // have changed.
       if ((GetValueMode() == VALUE_MODE_DEFAULT &&
            mType != NS_FORM_INPUT_HIDDEN) ||
-          mType == NS_FORM_INPUT_PASSWORD || !mValueChanged) {
+          mHasBeenTypePassword || !mValueChanged) {
         break;
       }
 
       state = GetPrimaryPresState();
       if (!state) {
         return NS_OK;
       }
 
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/file_login_fields.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <script>
+      // Add an unload listener to bypass bfcache.
+      window.addEventListner("unload", _ => _);
+    </script>
+  </head>
+  <body>
+    <input id="un" />
+    <input id="pw1" type="password" />
+    <input id="pw2" />
+    <a id="navigate" href="?navigated">Navigate</a>
+    <a id="back" href="javascript:history.back()">Back</a>
+  </body>
+</html>
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -40,16 +40,18 @@ skip-if = android_version == '18' # Andr
 [test_input_datetime_focus_state.html]
 [test_input_datetime_tabindex.html]
 [test_input_defaultValue.html]
 [test_input_email.html]
 [test_input_event.html]
 skip-if = android_version == '18' # bug 1147974
 [test_input_file_picker.html]
 [test_input_hasBeenTypePassword.html]
+[test_input_hasBeenTypePassword_navigation.html]
+support-files = file_login_fields.html
 [test_input_list_attribute.html]
 [test_input_number_l10n.html]
 # We don't build ICU for Firefox for Android:
 skip-if = os == "android"
 [test_input_number_key_events.html]
 [test_input_number_mouse_events.html]
 # Not run on Firefox for Android where the spin buttons are hidden:
 skip-if = os == "android" || (os == "mac" && debug) # Bug 1484442
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/test_input_hasBeenTypePassword_navigation.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1330228
+-->
+<head>
+  <title>Test hasBeenTypePassword is used with bfcache</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1330228">Mozilla Bug 1330228</a>
+<p id="display">
+  <iframe id="testframe" src="file_login_fields.html"></iframe>
+</p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test hasBeenTypePassword is used with bfcache **/
+SimpleTest.waitForExplicitFinish();
+
+function afterLoad() {
+  var iframeDoc = $("testframe").contentDocument;
+
+  /* change all the form controls */
+  iframeDoc.getElementById("un").value = "username";
+  iframeDoc.getElementById("pw1").value = "password1";
+
+  // Convert pw2 to a password field temporarily to test hasBeenTypePassword.
+  // We don't want the initial or final value to be type=password or we may
+  // not test the right scenario.
+  iframeDoc.getElementById("pw2").type = "password";
+  iframeDoc.getElementById("pw2").value = "password2";
+  iframeDoc.getElementById("pw2").type = "";
+
+  /* navigate the page */
+  $("testframe").setAttribute("onload", "afterNavigation()");
+  // Use a click on an <a> so that the current page is included in session history.
+  iframeDoc.getElementById("navigate").click();
+}
+
+addLoadEvent(afterLoad);
+
+function afterNavigation() {
+  info("Navigated to a new document");
+  var iframeDoc = $("testframe").contentDocument;
+  $("testframe").setAttribute("onload", "afterBack()");
+  // Calling `history.back()` on the contentWindow from here doesn't use bfcache
+  // so call it from within the contentDocument.
+  iframeDoc.getElementById("back").click();
+}
+
+function afterBack() {
+  info("Should be back showing the first document from bfcache");
+  var iframeDoc = $("testframe").contentDocument;
+
+  is(iframeDoc.getElementById("un").value, "username",
+     "username field value remembered");
+  is(iframeDoc.getElementById("pw1").value, "",
+     "type=password field value not remembered");
+  is(iframeDoc.getElementById("pw2").value, "",
+     "former type=password field value not remembered");
+  SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>