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 317825 67300cfca7338c03a71e713f1b7103367fad4b29
parent 317824 9d674f5dbc8e1c6d160f844701a0771316a8d833
child 317826 46db039dbe102cf4529df8fe237b20455c3f154d
push id82758
push usereakhgari@mozilla.com
push dateThu, 13 Oct 2016 17:46:56 +0000
treeherdermozilla-inbound@67300cfca733 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1248148
milestone52.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 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);