Bug 697842 stopPropagation() shouldn't break IME composition r=ehsan
authorMasayuki Nakano <masayuki@d-toybox.com>
Sun, 27 Nov 2011 09:36:36 +0900
changeset 82487 2a28403dee332f15ca2b122260f5378ce4c2edde
parent 82486 300d9c4a3b9af31c471d0a99906781d5836f1e9e
child 82488 8e47f9fbd5f208ec75009f335a2eb32bd4305fd8
push idunknown
push userunknown
push dateunknown
reviewersehsan
bugs697842
milestone11.0a1
Bug 697842 stopPropagation() shouldn't break IME composition r=ehsan
editor/libeditor/base/nsEditorEventListener.cpp
editor/libeditor/html/tests/Makefile.in
editor/libeditor/html/tests/test_bug697842.html
testing/mochitest/tests/SimpleTest/EventUtils.js
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -198,23 +198,26 @@ nsEditorEventListener::InstallToEditor()
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("blur"),
                                NS_EVENT_FLAG_CAPTURE);
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("focus"),
                                NS_EVENT_FLAG_CAPTURE);
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("text"),
-                               NS_EVENT_FLAG_BUBBLE);
+                               NS_EVENT_FLAG_BUBBLE |
+                               NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("compositionstart"),
-                               NS_EVENT_FLAG_BUBBLE);
+                               NS_EVENT_FLAG_BUBBLE |
+                               NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("compositionend"),
-                               NS_EVENT_FLAG_BUBBLE);
+                               NS_EVENT_FLAG_BUBBLE |
+                               NS_EVENT_FLAG_SYSTEM_EVENT);
 
   return NS_OK;
 }
 
 void
 nsEditorEventListener::Disconnect()
 {
   if (!mEditor) {
@@ -284,23 +287,26 @@ nsEditorEventListener::UninstallFromEdit
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("blur"),
                                   NS_EVENT_FLAG_CAPTURE);
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("focus"),
                                   NS_EVENT_FLAG_CAPTURE);
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("text"),
-                                  NS_EVENT_FLAG_BUBBLE);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("compositionstart"),
-                                  NS_EVENT_FLAG_BUBBLE);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("compositionend"),
-                                  NS_EVENT_FLAG_BUBBLE);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT);
 }
 
 already_AddRefed<nsIPresShell>
 nsEditorEventListener::GetPresShell()
 {
   NS_PRECONDITION(mEditor,
     "The caller must check whether this is connected to an editor");
   return mEditor->GetPresShell();
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -85,16 +85,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug629845.html \
 		test_bug640321.html \
 		test_bug668599.html \
 		test_bug674770-1.html \
 		file_bug674770-1.html \
 		test_bug674861.html \
 		test_bug676401.html \
 		test_bug677752.html \
+		test_bug697842.html \
 		test_CF_HTML_clipboard.html \
 		test_contenteditable_focus.html \
 		test_htmleditor_keyevent_handling.html \
 		test_select_all_without_body.html \
 		file_select_all_without_body.html \
 		test_root_element_replacement.html \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug697842.html
@@ -0,0 +1,125 @@
+<!DOCTYPE>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=697842
+-->
+<head>
+  <title>Test for Bug 697842</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css"
+          href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<div id="display">
+  <p id="editor" contenteditable style="min-height: 1.5em;"></p>
+</div>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+</pre>
+
+<script class="testbody" type="application/javascript">
+
+/** Test for Bug 697842 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function runTests()
+{
+  var editor = document.getElementById("editor");
+  editor.focus();
+
+  SimpleTest.executeSoon(function() {
+    var composingString = "";
+
+    function handler(aEvent) {
+      if (aEvent.type != "text") {
+        is(aEvent.data, composingString, "mismatch composition string");
+      }
+      aEvent.stopPropagation();
+      aEvent.preventDefault();
+    }
+
+    editor.addEventListener("compositionstart", handler, true);
+    editor.addEventListener("compositionend", handler, true);
+    editor.addEventListener("compositionupdate", handler, true);
+    editor.addEventListener("text", handler, true);
+
+    // start composition
+    synthesizeComposition({ type: "compositionstart" });
+
+    // input first character
+    composingString = "\u306B";
+    synthesizeComposition({ type: "compositionupdate", data: composingString });
+    synthesizeText(
+      { "composition":
+        { "string": composingString,
+          "clauses":
+          [
+            { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
+          ]
+        },
+        "caret": { "start": 1, "length": 0 }
+      });
+
+    // input second character
+    composingString = "\u306B\u3085";
+    synthesizeComposition({ type: "compositionupdate", data: composingString });
+    synthesizeText(
+      { "composition":
+        { "string": composingString,
+          "clauses":
+          [
+            { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
+          ]
+        },
+        "caret": { "start": 2, "length": 0 }
+      });
+
+    // convert them
+    synthesizeText(
+      { "composition":
+        { "string": composingString,
+          "clauses":
+          [
+            { "length": 2,
+              "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
+          ]
+        },
+        "caret": { "start": 2, "length": 0 }
+      });
+
+    // commit
+    synthesizeText(
+      { "composition":
+        { "string": composingString,
+          "clauses":
+          [
+            { "length": 0, "attr": 0 }
+          ]
+        },
+        "caret": { "start": 2, "length": 0 }
+      });
+
+    synthesizeComposition({ type: "compositionend", data: composingString });
+
+    is(editor.innerHTML, composingString,
+       "editor has unexpected result");
+
+    editor.removeEventListener("compositionstart", handler, true);
+    editor.removeEventListener("compositionend", handler, true);
+    editor.removeEventListener("compositionupdate", handler, true);
+    editor.removeEventListener("text", handler, true);
+
+    SimpleTest.finish();
+  });
+}
+
+
+</script>
+</body>
+
+</html>
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -529,16 +529,22 @@ function _getDOMWindowUtils(aWindow)
     return parent.SpecialPowers.getDOMWindowUtils(aWindow);
   }
 
   //TODO: this is assuming we are in chrome space
   return aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
                                getInterface(Components.interfaces.nsIDOMWindowUtils);
 }
 
+// Must be synchronized with nsIDOMWindowUtils.
+const COMPOSITION_ATTR_RAWINPUT              = 0x02;
+const COMPOSITION_ATTR_SELECTEDRAWTEXT       = 0x03;
+const COMPOSITION_ATTR_CONVERTEDTEXT         = 0x04;
+const COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT = 0x05;
+
 /**
  * Synthesize a composition event.
  *
  * @param aEvent               The composition event information.  This must
  *                             have |type| member.  The value must be
  *                             "compositionstart", "compositionend" or
  *                             "compositionupdate".
  *                             And also this may have |data| and |locale| which