Bug 1067255 - Disallow cut and copy in password fields. r=ehsan
authorJan Jongboom <janjongboom@gmail.com>
Wed, 08 Oct 2014 16:27:31 -0700
changeset 209497 c1d2dc87407ef0ccd2071f50a433c36ab6376a47
parent 209496 46c1cce018dee925d211ba14aa494d55ecebb497
child 209498 245fec9779cfb8d91a49d86d907f0189c0e04ae1
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersehsan
bugs1067255
milestone35.0a1
Bug 1067255 - Disallow cut and copy in password fields. r=ehsan
browser/base/content/test/general/test_contextmenu.html
dom/browser-element/mochitest/browserElement_CopyPaste.js
editor/libeditor/nsPlaintextEditor.cpp
editor/libeditor/tests/mochitest.ini
editor/libeditor/tests/test_bug1067255.html
--- a/browser/base/content/test/general/test_contextmenu.html
+++ b/browser/base/content/test/general/test_contextmenu.html
@@ -637,20 +637,20 @@ function runTest(testNum) {
         selectInputText(select_inputtext_password); // Select text prior to opening context menu.
         openContextMenuFor(select_inputtext_password); // Invoke context menu for next test.
     },
 
     function () {
         // Context menu for selected text in input[type="password"]
         checkContextMenu(["context-undo",        false,
                           "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
+                          "context-cut",         false,
+                          "context-copy",        false,
                           "context-paste",       null, // ignore clipboard state
-                          "context-delete",      true,
+                          "context-delete",      false,
                           "---",                 null,
                           "context-selectall",   true,
                           "---",                 null,
                           "spell-check-enabled", true,
                           //spell checker is shown on input[type="password"] on this testcase
                           "spell-dictionaries",  true,
                               ["spell-check-dictionary-en-US", true,
                                "---",                          null,
--- a/dom/browser-element/mochitest/browserElement_CopyPaste.js
+++ b/dom/browser-element/mochitest/browserElement_CopyPaste.js
@@ -87,59 +87,49 @@ function dispatchTest(e) {
       pasteData = "from parent ";
       iframe.src = "data:text/html,<html><body>" +
                    "<input type='text' id='text' value='" + defaultData + "'>" +
                    "</body>" +
                    "</html>";
       stateMeaning = " (test: <input type=text>)";
       focusScript = "var elt=content.document.getElementById('text');elt.focus();elt.select();";
       break;
-    case 2: // test for input password
-      defaultData = "Test for selection change event";
-      pasteData = "from parent ";
-      iframe.src = "data:text/html,<html><body>" +
-                   "<input type='password' id='text' value='" + defaultData + "'>" +
-                   "</body>" +
-                   "</html>";
-      stateMeaning = " (test: <input type=password>)";
-      focusScript = "var elt=content.document.getElementById('text');elt.focus();elt.select();";
-      break;
-    case 3: // test for input number
+    case 2: // test for input number
       defaultData = "12345";
       pasteData = "67890";
       iframe.src = "data:text/html,<html><body>" +
                    "<input type='number' id='text' value='" + defaultData + "'>" +
                    "</body>" +
                    "</html>";
       stateMeaning = " (test: <input type=number>)";
       focusScript = "var elt=content.document.getElementById('text');elt.focus();elt.select();";
       break;
-    case 4: // test for div contenteditable
+    case 3: // test for div contenteditable
       defaultData = "Test for selection change event";
       pasteData = "from parent ";
       iframe.src = "data:text/html,<html><body>" +
                    "<div contenteditable='true' id='text'>" + defaultData + "</div>" +
                    "</body>" +
                    "</html>";
       stateMeaning = " (test: content editable div)";
       focusScript = "var elt=content.document.getElementById('text');elt.focus();";
       break;
-    case 5: // test for normal div
+    case 4: // test for normal div
       SimpleTest.finish();
       return;
       defaultData = "Test for selection change event";
       pasteData = "from parent ";
       iframe.src = "data:text/html,<html><body>" +
                    "<div id='text'>" + defaultData + "</div>" +
                    "</body>" +
                    "</html>";
       stateMeaning = " (test: normal div)";
       focusScript = "var elt=content.document.getElementById('text');elt.focus();";
       break;
-    case 6: // test for normal div with designMode:on
+    case 5: // test for normal div with designMode:on
       defaultData = "Test for selection change event";
       pasteData = "from parent ";
       iframe.src = "data:text/html,<html><body id='text'>" +
                    defaultData +
                    "</body>" +
                    "<script>document.designMode='on';</script>" +
                    "</html>";
       stateMeaning = " (test: normal div with designMode:on)";
@@ -187,43 +177,35 @@ function testCopy1(e) {
     nextTest(true);
   }
 
   let fail = function() {
     nextTest(false);
   }
 
   let compareData = defaultData;
-  if (state == 2) {
-    // In password case, we just check length of text at clipboard is equal
-    // to length of defaultData
-    compareData = function(clipboardText) {
-      return clipboardText.length == defaultData.length;
-    };
-  }
-
   SimpleTest.waitForClipboard(compareData, setup, success, fail);
 }
 
 function testPaste1(e) {
   // Next test paste command, first we copy to global clipboard in parent side.
   // Then paste it to child side.
   copyToClipboard(pasteData);
 
   doCommand("paste");
   SimpleTest.executeSoon(function() { testPaste2(e); });
 }
 
 function testPaste2(e) {
   mm.addMessageListener('content-text', function messageforpaste(msg) {
     mm.removeMessageListener('content-text', messageforpaste);
-    if (state == 5) {
+    if (state == 4) {
       // normal div cannot paste, so the content remain unchange
       ok(SpecialPowers.wrap(msg).json === defaultData, "paste command works" + stateMeaning);
-    } else if (state == 4 && browserElementTestHelpers.getOOPByDefaultPref()) {
+    } else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
       // Something weird when we doCommand with content editable element in OOP. Mark this case as todo
       todo(false, "paste command works" + stateMeaning);
     } else {
       ok(SpecialPowers.wrap(msg).json === pasteData, "paste command works" + stateMeaning);
     }
     SimpleTest.executeSoon(function() { testCut1(e); });
   });
 
@@ -234,17 +216,17 @@ function testCut1(e) {
   // Clean clipboard first
   copyToClipboard("");
   let setup = function() {
     doCommand("selectall");
     doCommand("cut");
   };
 
   let nextTest = function(success) {
-    if (state == 4 && browserElementTestHelpers.getOOPByDefaultPref()) {
+    if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
       // Something weird when we doCommand with content editable element in OOP.
       todo(false, "cut function works" + stateMeaning);
     } else {
       ok(success, "cut function works" + stateMeaning);
     }
     SimpleTest.executeSoon(function() { testCut2(e); });
   };
 
@@ -252,38 +234,32 @@ function testCut1(e) {
     nextTest(true);
   }
 
   let fail = function() {
     nextTest(false);
   }
 
   let compareData = pasteData;
-  if (state == 2) {
-    // In password case, we just check length of text at clipboard is equal
-    // to length of pasteData
-    compareData = function(clipboardText) {
-      return clipboardText.length == pasteData.length;
-    };
-  } else if (state == 4 && browserElementTestHelpers.getOOPByDefaultPref()) {
+  if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
     // Something weird when we doCommand with content editable element in OOP.
     // Always true in this case
     compareData = function() { return true; }
   }
 
   SimpleTest.waitForClipboard(compareData, setup, success, fail);
 }
 
 function testCut2(e) {
   mm.addMessageListener('content-text', function messageforcut(msg) {
     mm.removeMessageListener('content-text', messageforcut);
     // normal div cannot cut
-    if (state == 5) {
+    if (state == 4) {
       ok(SpecialPowers.wrap(msg).json !== "", "cut command works" + stateMeaning);
-    } else if (state == 4 && browserElementTestHelpers.getOOPByDefaultPref()) {
+    } else if (state == 3 && browserElementTestHelpers.getOOPByDefaultPref()) {
       // Something weird when we doCommand with content editable element in OOP. Mark this case as todo
       todo(false, "cut command works" + stateMeaning);
     } else {
       ok(SpecialPowers.wrap(msg).json === "", "cut command works" + stateMeaning);
     }
 
     state++;
     dispatchTest(e);
--- a/editor/libeditor/nsPlaintextEditor.cpp
+++ b/editor/libeditor/nsPlaintextEditor.cpp
@@ -1158,16 +1158,19 @@ nsPlaintextEditor::Redo(uint32_t aCount)
 
 bool
 nsPlaintextEditor::CanCutOrCopy()
 {
   nsCOMPtr<nsISelection> selection;
   if (NS_FAILED(GetSelection(getter_AddRefs(selection))))
     return false;
 
+  if (IsPasswordEditor())
+    return false;
+
   return !selection->Collapsed();
 }
 
 bool
 nsPlaintextEditor::FireClipboardEvent(int32_t aType, int32_t aSelectionType)
 {
   if (aType == NS_PASTE)
     ForceCompositionEnd();
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -133,16 +133,17 @@ skip-if = toolkit == 'android' || e10s
 [test_bug832025.html]
 [test_bug857487.html]
 [test_bug966155.html]
 skip-if = os != "win"
 [test_bug966552.html]
 skip-if = os != "win"
 [test_bug998188.html]
 [test_bug1026397.html]
+[test_bug1067255.html]
 skip-if = e10s
 [test_CF_HTML_clipboard.html]
 [test_contenteditable_focus.html]
 [test_dom_input_event_on_htmleditor.html]
 skip-if = toolkit == 'android' # bug 1054087
 [test_dom_input_event_on_texteditor.html]
 [test_keypress_untrusted_event.html]
 [test_root_element_replacement.html]
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug1067255.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1067255
+-->
+
+<head>
+  <title>Test for Bug 1067255</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<body onload="doTest();">
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1067255">Mozilla Bug 1067255</a>
+
+  <pre id="test">
+    <script type="application/javascript">
+      /** Test for Bug 1067255 **/
+      SimpleTest.waitForExplicitFinish();
+
+      function doTest() {
+        var text = $("text-field");
+        var password = $("password-field");
+
+        var editor1 = SpecialPowers.wrap(text).editor;
+        var editor2 = SpecialPowers.wrap(password).editor;
+
+        text.focus();
+        text.select();
+
+        ok(editor1.canCopy(), "can copy, text");
+        ok(editor1.canCut(), "can cut, text");
+
+        password.focus();
+        password.select();
+
+        ok(!editor2.canCopy(), "can copy, password");
+        ok(!editor2.canCut(), "can cut, password");
+
+        SimpleTest.finish();
+      }
+   </script>
+  </pre>
+
+  <input type="text" value="Gonzo says hi" id="text-field" />
+  <input type="password" value="Jan also" id="password-field" />
+</body>
+</html>