Bug 1154183 part.4 Implement nsXBLWindowKeyHandler::GetElementForHandler() r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 18 Mar 2016 11:25:22 +0900
changeset 289954 6c650c359c8e65904805108b1996a56f08c2a372
parent 289953 024017da65648b6393ddf01126139bd7cb1b172d
child 289955 b0733a06e7f14481ced69b8e3690d79ba7a2c88a
push id18337
push usercbook@mozilla.com
push dateWed, 23 Mar 2016 15:30:25 +0000
treeherderfx-team@67ac681f7e53 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1154183
milestone48.0a1
Bug 1154183 part.4 Implement nsXBLWindowKeyHandler::GetElementForHandler() r=smaug MozReview-Commit-ID: 9qsOLU3QCnr
dom/xbl/nsXBLWindowKeyHandler.cpp
dom/xbl/nsXBLWindowKeyHandler.h
--- a/dom/xbl/nsXBLWindowKeyHandler.cpp
+++ b/dom/xbl/nsXBLWindowKeyHandler.cpp
@@ -592,45 +592,19 @@ nsXBLWindowKeyHandler::WalkHandlersAndEx
     if (!EventMatched(handler, aEventType, aKeyEvent,
                       aCharCode, aIgnoreModifierState)) {
       continue;  // try the next one
     }
 
     // Before executing this handler, check that it's not disabled,
     // and that it has something to do (oncommand of the <key> or its
     // <command> is non-empty).
-    nsCOMPtr<nsIContent> keyContent = handler->GetHandlerElement();
     nsCOMPtr<Element> commandElement;
-
-    // See if we're in a XUL doc.
-    nsCOMPtr<Element> chromeHandlerElement = GetElement();
-    if (chromeHandlerElement && keyContent) {
-      // We are.  Obtain our command attribute.
-      nsAutoString command;
-      keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
-      if (!command.IsEmpty()) {
-        // Locate the command element in question.  Note that we
-        // know "keyContent" is in a doc if we're dealing with it here.
-        NS_ASSERTION(keyContent->IsInDoc(),
-                     "the key element must be in document");
-        nsIDocument* doc = keyContent->GetCurrentDoc();
-        if (doc) {
-          commandElement = do_QueryInterface(doc->GetElementById(command));
-        }
-
-        if (!commandElement) {
-          NS_ERROR("A XUL <key> is observing a command that doesn't exist. "
-                   "Unable to execute key binding!");
-          continue;
-        }
-      }
-    }
-
-    if (!commandElement) {
-      commandElement = do_QueryInterface(keyContent);
+    if (!GetElementForHandler(handler, getter_AddRefs(commandElement))) {
+      continue;
     }
 
     if (commandElement) {
       nsAutoString value;
       commandElement->GetAttribute(NS_LITERAL_STRING("disabled"), value);
       if (value.EqualsLiteral("true")) {
         continue;  // this handler is disabled, try the next one
       }
@@ -648,16 +622,17 @@ nsXBLWindowKeyHandler::WalkHandlersAndEx
       }
     }
 
     if (!aExecute) {
       return true;
     }
 
     nsCOMPtr<EventTarget> target;
+    nsCOMPtr<Element> chromeHandlerElement = GetElement();
     if (chromeHandlerElement) {
       target = commandElement;
     } else {
       target = mTarget;
     }
 
     nsresult rv = handler->ExecuteHandler(target, aKeyEvent->AsEvent());
     if (NS_SUCCEEDED(rv)) {
@@ -717,16 +692,59 @@ nsXBLWindowKeyHandler::GetElement(bool* 
   nsCOMPtr<Element> element = do_QueryReferent(mWeakPtrForElement);
   if (element && aIsDisabled) {
     *aIsDisabled = element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
                                         nsGkAtoms::_true, eCaseMatters);
   }
   return element.forget();
 }
 
+bool
+nsXBLWindowKeyHandler::GetElementForHandler(nsXBLPrototypeHandler* aHandler,
+                                            Element** aElementForHandler)
+{
+  MOZ_ASSERT(aElementForHandler);
+  *aElementForHandler = nullptr;
+
+  nsCOMPtr<nsIContent> keyContent = aHandler->GetHandlerElement();
+
+  // See if we're in a XUL doc.
+  nsCOMPtr<Element> chromeHandlerElement = GetElement();
+  if (chromeHandlerElement && keyContent) {
+    // We are.  Obtain our command attribute.
+    nsAutoString command;
+    keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
+    if (!command.IsEmpty()) {
+      // Locate the command element in question.  Note that we
+      // know "keyContent" is in a doc if we're dealing with it here.
+      NS_ASSERTION(keyContent->IsInDoc(),
+                   "the key element must be in document");
+      nsIDocument* doc = keyContent->GetCurrentDoc();
+      if (NS_WARN_IF(!doc)) {
+        return false;
+      }
+      nsCOMPtr<Element> commandElement =
+        do_QueryInterface(doc->GetElementById(command));
+      if (!commandElement) {
+        NS_ERROR("A XUL <key> is observing a command that doesn't exist. "
+                 "Unable to execute key binding!");
+        return false;
+      }
+      commandElement.swap(*aElementForHandler);
+    }
+  }
+
+  if (!*aElementForHandler) {
+    nsCOMPtr<Element> keyElement = do_QueryInterface(keyContent);
+    keyElement.swap(*aElementForHandler);
+  }
+
+  return true;
+}
+
 ///////////////////////////////////////////////////////////////////////////////////
 
 already_AddRefed<nsXBLWindowKeyHandler>
 NS_NewXBLWindowKeyHandler(nsIDOMElement* aElement, EventTarget* aTarget)
 {
   RefPtr<nsXBLWindowKeyHandler> result =
     new nsXBLWindowKeyHandler(aElement, aTarget);
   return result.forget();
--- a/dom/xbl/nsXBLWindowKeyHandler.h
+++ b/dom/xbl/nsXBLWindowKeyHandler.h
@@ -85,16 +85,29 @@ protected:
   // Is an HTML editable element focused
   bool IsHTMLEditableFieldFocused();
 
   // Returns the element which was passed as a parameter to the constructor,
   // unless the element has been removed from the document. Optionally returns
   // whether the disabled attribute is set on the element (assuming the element
   // is non-null).
   already_AddRefed<mozilla::dom::Element> GetElement(bool* aIsDisabled = nullptr);
+
+  /**
+   * GetElementForHandler() retrieves an element for the handler.  The element
+   * may be a command element or a key element.
+   *
+   * @param aHandler           The handler.
+   * @param aElementForHandler Must not be nullptr.  The element is returned to
+   *                           this.
+   * @return                   true if the handler is valid.  Otherwise, false.
+   */
+  bool GetElementForHandler(nsXBLPrototypeHandler* aHandler,
+                            mozilla::dom::Element** aElementForHandler);
+
   // Using weak pointer to the DOM Element.
   nsWeakPtr              mWeakPtrForElement;
   mozilla::dom::EventTarget* mTarget; // weak ref
 
   // these are not owning references; the prototype handlers are owned
   // by the prototype bindings which are owned by the docinfo.
   nsXBLPrototypeHandler* mHandler;     // platform bindings
   nsXBLPrototypeHandler* mUserHandler; // user-specific bindings