Bug 1351072 - [e10s] Clear active document when closing popup of <select>. r=smaug, a=jcristau
authorBen Tian <btian@mozilla.com>
Wed, 14 Jun 2017 13:42:03 +0800
changeset 414038 54fe4bc8e0075af5b11a0091fcb477ac8135cc0d
parent 414037 66c52ae642d227406bd09ce7f6c17c8582fbab48
child 414039 4d75a17437df0928b59e56205ac1a1d3787ee3af
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, jcristau
bugs1351072
milestone55.0
Bug 1351072 - [e10s] Clear active document when closing popup of <select>. r=smaug, a=jcristau MozReview-Commit-ID: IaRG67FwIPL
layout/inspector/inDOMUtils.cpp
layout/inspector/inIDOMUtils.idl
toolkit/modules/SelectContentHelper.jsm
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -1104,25 +1104,35 @@ inDOMUtils::SetContentState(nsIDOMElemen
 
   *aRetVal = esm->SetContentState(content, EventStates(aState));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 inDOMUtils::RemoveContentState(nsIDOMElement* aElement,
                                EventStates::InternalType aState,
+                               bool aClearActiveDocument,
                                bool* aRetVal)
 {
   NS_ENSURE_ARG_POINTER(aElement);
 
   RefPtr<EventStateManager> esm =
     inLayoutUtils::GetEventStateManagerFor(aElement);
   NS_ENSURE_TRUE(esm, NS_ERROR_INVALID_ARG);
 
   *aRetVal = esm->SetContentState(nullptr, EventStates(aState));
+
+  if (aClearActiveDocument && EventStates(aState) == NS_EVENT_STATE_ACTIVE) {
+    EventStateManager* activeESM = static_cast<EventStateManager*>(
+      EventStateManager::GetActiveEventStateManager());
+    if (activeESM == esm) {
+      EventStateManager::ClearGlobalActiveContent(nullptr);
+    }
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 inDOMUtils::GetContentState(nsIDOMElement* aElement,
                             EventStates::InternalType* aState)
 {
   *aState = 0;
--- a/layout/inspector/inIDOMUtils.idl
+++ b/layout/inspector/inIDOMUtils.idl
@@ -147,33 +147,37 @@ interface inIDOMUtils : nsISupports
   boolean isIgnorableWhitespace(in nsIDOMCharacterData aDataNode);
   // Returns the "parent" of a node.  The parent of a document node is the
   // frame/iframe containing that document.  aShowingAnonymousContent says
   // whether we are showing anonymous content.
   nsIDOMNode getParentForNode(in nsIDOMNode aNode,
                               in boolean aShowingAnonymousContent);
   nsIDOMNodeList getChildrenForNode(in nsIDOMNode aNode,
                                     in boolean aShowingAnonymousContent);
-  
+
   // XBL utilities
   nsIArray getBindingURLs(in nsIDOMElement aElement);
 
   // content state utilities
   unsigned long long getContentState(in nsIDOMElement aElement);
   /**
    * Setting and removing content state on an element. Both these functions
    * calling EventStateManager::SetContentState internally, the difference is
    * that for the remove case we simply pass in nullptr for the element.
    * Use them accordingly.
    *
+   * When removing the active state, you may optionally also clear the active
+   * document as well by setting aClearActiveDocument
+   *
    * @return Returns true if the state was set successfully. See more details
    * in EventStateManager.h SetContentState.
    */
   bool setContentState(in nsIDOMElement aElement, in unsigned long long aState);
-  bool removeContentState(in nsIDOMElement aElement, in unsigned long long aState);
+  bool removeContentState(in nsIDOMElement aElement, in unsigned long long aState,
+                          [optional] in bool aClearActiveDocument);
 
   nsIDOMFontFaceList getUsedFontFaces(in nsIDOMRange aRange);
 
   /**
    * Get the names of all the supported pseudo-elements.
    * Pseudo-elements which are only accepted in UA style sheets are
    * not included.
    *
--- a/toolkit/modules/SelectContentHelper.jsm
+++ b/toolkit/modules/SelectContentHelper.jsm
@@ -254,29 +254,38 @@ this.SelectContentHelper.prototype = {
     switch (message.name) {
       case "Forms:SelectDropDownItem":
         this.element.selectedIndex = message.data.value;
         this.closedWithEnter = message.data.closedWithEnter;
         break;
 
       case "Forms:DismissedDropDown":
         let selectedOption = this.element.item(this.element.selectedIndex);
-        if (this.initialSelection != selectedOption) {
+        if (this.initialSelection === selectedOption) {
+          // Clear active document
+          DOMUtils.removeContentState(this.element,
+                                      kStateActive,
+                                      /* aClearActiveDocument */ true);
+        } else {
           let win = this.element.ownerGlobal;
           // For ordering of events, we're using non-e10s as our guide here,
           // since the spec isn't exactly clear. In non-e10s, we fire:
           // mousedown, mouseup, input, change, click if the user clicks
           // on an element in the dropdown. If the user uses the keyboard
           // to select an element in the dropdown, we only fire input and
           // change events.
           if (!this.closedWithEnter) {
             this.dispatchMouseEvent(win, selectedOption, "mousedown");
             this.dispatchMouseEvent(win, selectedOption, "mouseup");
-            DOMUtils.removeContentState(this.element, kStateActive);
           }
+          // Clear active document no matter user selects
+          // via keyboard or mouse
+          DOMUtils.removeContentState(this.element,
+                                      kStateActive,
+                                      /* aClearActiveDocument */ true);
 
           let inputEvent = new win.UIEvent("input", {
             bubbles: true,
           });
           this.element.dispatchEvent(inputEvent);
 
           let changeEvent = new win.Event("change", {
             bubbles: true,