Bug 1331798 Bookmark panel for new bookmark shouldn't be closed automatically during composition and after text input without keyboard events nor composition events r=jaws
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 19 Jan 2017 15:04:56 +0900
changeset 377304 b69accee20b4a38ba050768729f86f8d21ee0d3f
parent 377303 6587e676b76d68462cacdb567e4c39fff1057194
child 377305 5c43a389e735d16940d2f36b6f167249285c51dc
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1331798
milestone53.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 1331798 Bookmark panel for new bookmark shouldn't be closed automatically during composition and after text input without keyboard events nor composition events r=jaws Bookmark panel for a new bookmark shouldn't be closed automatically during composition even if mouse cursor is moved outside the panel because user may click in IME's UI. Additionally, editor might be modified without keyboard events nor composition events. In such case, the bookmark panel shouldn't be closed automatically too. MozReview-Commit-ID: 1FAUmkXjid
browser/base/content/browser-places.js
browser/base/content/test/general/browser_bookmark_popup.js
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -2,32 +2,36 @@
  * 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/. */
 
 var StarUI = {
   _itemId: -1,
   uri: null,
   _batching: false,
   _isNewBookmark: false,
+  _isComposing: false,
   _autoCloseTimer: 0,
 
   _element(aID) {
     return document.getElementById(aID);
   },
 
   // Edit-bookmark panel
   get panel() {
     delete this.panel;
     var element = this._element("editBookmarkPanel");
     // initially the panel is hidden
     // to avoid impacting startup / new window performance
     element.hidden = false;
     element.addEventListener("keypress", this);
     element.addEventListener("mouseout", this);
     element.addEventListener("mousemove", this);
+    element.addEventListener("compositionstart", this);
+    element.addEventListener("compositionend", this);
+    element.addEventListener("input", this);
     element.addEventListener("popuphidden", this);
     element.addEventListener("popupshown", this);
     return this.panel = element;
   },
 
   // Array of command elements to disable when the panel is opened.
   get _blockedCommands() {
     delete this._blockedCommands;
@@ -130,25 +134,44 @@ var StarUI = {
           case 0:
             let accessKey = document.getElementById("key_close");
             if (eventMatchesKey(aEvent, accessKey)) {
                 this.panel.hidePopup();
             }
             break;
         }
         break;
+      case "compositionstart":
+        if (aEvent.defaultPrevented) {
+          // If the composition was canceled, nothing to do here.
+          break;
+        }
+        // During composition, panel shouldn't be hidden automatically.
+        clearTimeout(this._autoCloseTimer);
+        this._isComposing = true;
+        break;
+      case "compositionend":
+        // After composition is committed, "mouseout" or something can set
+        // auto close timer.
+        this._isComposing = false;
+        break;
+      case "input":
+        // Might be edited some text without keyboard events nor composition
+        // events. Let's cancel auto close in such case.
+        clearTimeout(this._autoCloseTimer);
+        break;
       case "mouseout":
         // Explicit fall-through
       case "popupshown":
         // Don't handle events for descendent elements.
         if (aEvent.target != aEvent.currentTarget) {
           break;
         }
         // auto-close if new and not interacted with
-        if (this._isNewBookmark) {
+        if (this._isNewBookmark && !this._isComposing) {
           // 3500ms matches the timeout that Pocket uses in
           // browser/extensions/pocket/content/panels/js/saved.js
           let delay = 3500;
           if (this._closePanelQuickForTesting) {
             delay /= 10;
           }
           clearTimeout(this._autoCloseTimer);
           this._autoCloseTimer = setTimeout(() => {
--- a/browser/base/content/test/general/browser_bookmark_popup.js
+++ b/browser/base/content/test/general/browser_bookmark_popup.js
@@ -191,16 +191,102 @@ add_task(function* panel_shown_for_new_b
     shouldAutoClose: false,
     popupHideFn() {
       bookmarkPanel.hidePopup();
     },
     isBookmarkRemoved: false,
   });
 });
 
+
+add_task(function* panel_shown_for_new_bookmark_compositionstart_no_autoclose() {
+  yield test_bookmarks_popup({
+    isNewBookmark: true,
+    popupShowFn() {
+      bookmarkStar.click();
+    },
+    *popupEditFn() {
+      let compositionStartPromise = BrowserTestUtils.waitForEvent(bookmarkPanel, "compositionstart");
+      EventUtils.synthesizeComposition({ type: "compositionstart" }, window);
+      info("Waiting for compositionstart event");
+      yield compositionStartPromise;
+      info("Got compositionstart event");
+    },
+    shouldAutoClose: false,
+    popupHideFn() {
+      EventUtils.synthesizeComposition({ type: "compositioncommitasis" });
+      bookmarkPanel.hidePopup();
+    },
+    isBookmarkRemoved: false,
+  });
+});
+
+add_task(function* panel_shown_for_new_bookmark_compositionstart_mouseout_no_autoclose() {
+  yield test_bookmarks_popup({
+    isNewBookmark: true,
+    popupShowFn() {
+      bookmarkStar.click();
+    },
+    *popupEditFn() {
+      let mouseMovePromise = BrowserTestUtils.waitForEvent(bookmarkPanel, "mousemove");
+      EventUtils.synthesizeMouseAtCenter(bookmarkPanel, {type: "mousemove"});
+      info("Waiting for mousemove event");
+      yield mouseMovePromise;
+      info("Got mousemove event");
+
+      let compositionStartPromise = BrowserTestUtils.waitForEvent(bookmarkPanel, "compositionstart");
+      EventUtils.synthesizeComposition({ type: "compositionstart" }, window);
+      info("Waiting for compositionstart event");
+      yield compositionStartPromise;
+      info("Got compositionstart event");
+
+      let mouseOutPromise = BrowserTestUtils.waitForEvent(bookmarkPanel, "mouseout");
+      EventUtils.synthesizeMouse(bookmarkPanel, 0, 0, {type: "mouseout"});
+      EventUtils.synthesizeMouseAtCenter(document.documentElement, {type: "mousemove"});
+      info("Waiting for mouseout event");
+      yield mouseOutPromise;
+      info("Got mouseout event, but shouldn't run autoclose");
+    },
+    shouldAutoClose: false,
+    popupHideFn() {
+      EventUtils.synthesizeComposition({ type: "compositioncommitasis" });
+      bookmarkPanel.hidePopup();
+    },
+    isBookmarkRemoved: false,
+  });
+});
+
+add_task(function* panel_shown_for_new_bookmark_compositionend_mouseout_autoclose() {
+  yield test_bookmarks_popup({
+    isNewBookmark: true,
+    popupShowFn() {
+      bookmarkStar.click();
+    },
+    *popupEditFn() {
+      let mouseMovePromise = BrowserTestUtils.waitForEvent(bookmarkPanel, "mousemove");
+      EventUtils.synthesizeMouseAtCenter(bookmarkPanel, {type: "mousemove"});
+      info("Waiting for mousemove event");
+      yield mouseMovePromise;
+      info("Got mousemove event");
+
+      EventUtils.synthesizeComposition({ type: "compositioncommit", data: "committed text" });
+    },
+    *popupHideFn() {
+      let mouseOutPromise = BrowserTestUtils.waitForEvent(bookmarkPanel, "mouseout");
+      EventUtils.synthesizeMouse(bookmarkPanel, 0, 0, {type: "mouseout"});
+      EventUtils.synthesizeMouseAtCenter(document.documentElement, {type: "mousemove"});
+      info("Waiting for mouseout event");
+      yield mouseOutPromise;
+      info("Got mouseout event, should autoclose now");
+    },
+    shouldAutoClose: false,
+    isBookmarkRemoved: false,
+  });
+});
+
 add_task(function* contextmenu_new_bookmark_keypress_no_autoclose() {
   yield test_bookmarks_popup({
     isNewBookmark: true,
     *popupShowFn(browser) {
       let contextMenu = document.getElementById("contentAreaContextMenu");
       let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu,
                                                           "popupshown");
       let awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu,