Bug 1248148 - Disable firing selection events during HTML editor initialization; r=mystor
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 13 Oct 2016 10:18:31 -0400
changeset 424975 67300cfca7338c03a71e713f1b7103367fad4b29
parent 424974 9d674f5dbc8e1c6d160f844701a0771316a8d833
child 424976 46db039dbe102cf4529df8fe237b20455c3f154d
push id32314
push userbmo:hiikezoe@mozilla-japan.org
push dateFri, 14 Oct 2016 00:31:54 +0000
reviewersmystor
bugs1248148
milestone52.0a1
Bug 1248148 - Disable firing selection events during HTML editor initialization; r=mystor This is similar to what we do for the plaintext editor initialization.
dom/tests/mochitest/general/frameSelectEvents.html
editor/composer/nsEditingSession.cpp
--- a/dom/tests/mochitest/general/frameSelectEvents.html
+++ b/dom/tests/mochitest/general/frameSelectEvents.html
@@ -6,17 +6,17 @@
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   </head>
 
   <body>
     <div id="normal">
       <span id="inner">A bunch of text in a span inside of a div which should be selected</span>
     </div>
 
-    <div id="ce" contenteditable>
+    <div id="ce">
       This is a random block of text
     </div>
 
     <input type="text" id="input" value="XXXXXXXXXXXXXXXXXXX" width="200"> <br>
 
     <textarea id="textarea" width="200">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</textarea>
 
     <script>
@@ -122,24 +122,52 @@
              "SelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
           is(inputSelectionchange, aISelChng || 0,
              "ISelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
           is(textareaSelectionchange, aTSelChng || 0,
              "TSelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
           reset();
         }
 
+        function* contentEditableAction(aElement, aContentEditable,
+                                        aSelStart, aSelChng,
+                                        aISelChng, aTSelChng)
+        {
+          aElement.setAttribute("contenteditable",
+                                aContentEditable ? "true" : "false");
+          yield spin();
+
+          is(selectstart, aSelStart,
+             "SelStart ContentEditable Action");
+          is(selectionchange, aSelChng,
+             "SelStart ContentEditable Action");
+          is(inputSelectionchange, aISelChng || 0,
+             "SelStart ContentEditable Action");
+          is(textareaSelectionchange, aTSelChng || 0,
+             "SelStart ContentEditable Action");
+          reset();
+        }
+
         var selection = document.getSelection();
         function isCollapsed() {
           is(selection.isCollapsed, true, "Selection is collapsed");
         }
         function isNotCollapsed() {
           is(selection.isCollapsed, false, "Selection is not collapsed");
         }
 
+        // Make sure setting the element to contentEditable doesn't cause any selectionchange events
+        yield* contentEditableAction(elt("ce"), true, 0, 0, 0, 0);
+
+        // Make sure setting the element to not be contentEditable doesn't cause any selectionchange events
+        yield* contentEditableAction(elt("ce"), false, 0, 0, 0, 0);
+
+        // Now make the div contentEditable and proceed with the test
+        yield* contentEditableAction(elt("ce"), true, 0, 0, 0, 0);
+
         // Focus the contenteditable text
         yield* mouseAction(elt("ce"), 100, "click", 0, 1);
         isCollapsed();
 
         // Move the selection to the right, this should only fire selectstart once
         selectstartTarget = elt("ce").firstChild;
         yield* keyAction("VK_RIGHT", true, false, 1, 1);
         isNotCollapsed();
--- a/editor/composer/nsEditingSession.cpp
+++ b/editor/composer/nsEditingSession.cpp
@@ -43,16 +43,18 @@
 #include "nsIWebNavigation.h"           // for nsIWebNavigation
 #include "nsIWebProgress.h"             // for nsIWebProgress, etc
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nsPICommandUpdater.h"         // for nsPICommandUpdater
 #include "nsPIDOMWindow.h"              // for nsPIDOMWindow
 #include "nsPresContext.h"              // for nsPresContext
 #include "nsReadableUtils.h"            // for AppendUTF16toUTF8
 #include "nsStringFwd.h"                // for nsAFlatString
+#include "mozilla/dom/Selection.h"      // for AutoHideSelectionChanges
+#include "nsFrameSelection.h"           // for nsFrameSelection
 
 class nsISupports;
 class nsIURI;
 
 /*---------------------------------------------------------------------------
 
   nsEditingSession
 
@@ -400,28 +402,34 @@ nsEditingSession::SetupEditorOnWindow(mo
     mStateMaintainer->NotifyDocumentCreated();
     return NS_ERROR_FAILURE;
   }
 
   // Create editor and do other things
   //  only if we haven't found some error above,
   nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
+  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
+  NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
   if (!mInteractive) {
     // Disable animation of images in this document:
-    nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
-    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
     nsPresContext* presContext = presShell->GetPresContext();
     NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
 
     mImageAnimationMode = presContext->ImageAnimationMode();
     presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
   }
 
+  // Hide selection changes during initialization, in order to hide this
+  // from web pages.
+  RefPtr<nsFrameSelection> fs = presShell->FrameSelection();
+  NS_ENSURE_TRUE(fs, NS_ERROR_FAILURE);
+  mozilla::dom::AutoHideSelectionChanges hideSelectionChanges(fs);
+
   // create and set editor
   // Try to reuse an existing editor
   nsCOMPtr<nsIEditor> editor = do_QueryReferent(mExistingEditor);
   if (editor) {
     editor->PreDestroy(false);
   } else {
     editor = do_CreateInstance(classString, &rv);
     NS_ENSURE_SUCCESS(rv, rv);