Bug 733305, add a way to hide XBL, r=bz, a=abillings
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Wed, 10 Oct 2012 22:04:42 +0300
changeset 109910 24783c876df0fc5d2781254a32e7862305996bdd
parent 109909 931a3c5e476d1212a9cf9a58de07e55a8201f087
child 109911 99898ec9976a24f130d3eabf64762797e45f9543
push id16266
push usereakhgari@mozilla.com
push dateThu, 11 Oct 2012 00:21:19 +0000
treeherdermozilla-inbound@21e0f119b3d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, abillings
bugs733305
milestone19.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 733305, add a way to hide XBL, r=bz, a=abillings
content/base/public/nsIContent.h
content/base/public/nsINode.h
content/base/src/FragmentOrElement.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsDOMMutationObserver.cpp
content/base/src/nsDocument.cpp
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsGenericElement.cpp
content/base/src/nsGkAtomList.h
content/events/src/nsDOMMouseEvent.cpp
content/events/src/nsDOMUIEvent.cpp
content/events/src/nsEventDispatcher.cpp
content/events/src/nsEventStateManager.cpp
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLBinding.h
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xbl/src/nsXBLPrototypeBinding.h
content/xbl/src/nsXBLSerialize.h
dom/base/nsDOMClassInfo.cpp
editor/libeditor/base/nsEditorEventListener.cpp
embedding/components/find/src/nsFind.cpp
layout/base/nsPresShell.cpp
layout/xul/base/src/nsResizerFrame.cpp
toolkit/mozapps/plugins/content/pluginProblem.xml
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -30,18 +30,18 @@ enum nsLinkState {
   eLinkState_Unknown    = 0,
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID \
-{ 0x98fb308d, 0xc6dd, 0x4c6d, \
-  { 0xb7, 0x7c, 0x91, 0x18, 0x0c, 0xf0, 0x6f, 0x23 } }
+{ 0xe2985850, 0x81ca, 0x4b5d, \
+  { 0xb0, 0xf3, 0xe3, 0x95, 0xd5, 0x0d, 0x85, 0x64 } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
   typedef mozilla::widget::IMEState IMEState;
@@ -172,31 +172,37 @@ public:
   {
     NS_ASSERTION(!HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) ||
                  (HasFlag(NODE_IS_ANONYMOUS) &&
                   HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE)),
                  "Some flags seem to be missing!");
     return HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT);
   }
 
+  bool IsRootOfChromeAccessOnlySubtree() const
+  {
+    return HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT |
+                   NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS);
+  }
+
   /**
    * Makes this content anonymous
    * @see nsIAnonymousContentCreator
    */
   void SetNativeAnonymous()
   {
     SetFlags(NODE_IS_ANONYMOUS | NODE_IS_IN_ANONYMOUS_SUBTREE |
              NODE_IS_NATIVE_ANONYMOUS_ROOT);
   }
 
   /**
-   * Returns |this| if it is not native anonymous, otherwise
-   * first non native anonymous ancestor.
+   * Returns |this| if it is not chrome-only/native anonymous, otherwise
+   * first non chrome-only/native anonymous ancestor.
    */
-  virtual nsIContent* FindFirstNonNativeAnonymous() const;
+  virtual nsIContent* FindFirstNonChromeOnlyAccessContent() const;
 
   /**
    * Returns true if and only if this node has a parent, but is not in
    * its parent's child list.
    */
   bool IsRootOfAnonymousSubtree() const
   {
     NS_ASSERTION(!IsRootOfNativeAnonymousSubtree() ||
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -150,18 +150,22 @@ enum {
   NODE_HAS_DIRECTION_RTL =                NODE_FLAG_BIT(20),
 
   // Set if the node has left-to-right directionality
   NODE_HAS_DIRECTION_LTR =                NODE_FLAG_BIT(21),
 
   NODE_ALL_DIRECTION_FLAGS =              NODE_HAS_DIRECTION_LTR |
                                           NODE_HAS_DIRECTION_RTL,
 
+  NODE_CHROME_ONLY_ACCESS =               NODE_FLAG_BIT(22),
+
+  NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS =    NODE_FLAG_BIT(23),
+
   // Remaining bits are node type specific.
-  NODE_TYPE_SPECIFIC_BITS_OFFSET =        22
+  NODE_TYPE_SPECIFIC_BITS_OFFSET =        24
 };
 
 /**
  * Class used to detect unexpected mutations. To use the class create an
  * nsMutationGuard on the stack before unexpected mutations could occur.
  * You can then at any time call Mutated to check if any unexpected mutations
  * have occurred.
  *
@@ -234,18 +238,18 @@ private:
 // Categories of node properties
 // 0 is global.
 #define DOM_USER_DATA         1
 #define DOM_USER_DATA_HANDLER 2
 #define SMIL_MAPPED_ATTR_ANIMVAL 3
 
 // IID for the nsINode interface
 #define NS_INODE_IID \
-{ 0xf73e3890, 0xe4ab, 0x453e, \
-  { 0x8c, 0x78, 0x2d, 0x1f, 0xa4, 0x0b, 0x48, 0x00 } }
+{ 0x9aede57e, 0xe39e, 0x42e8, \
+  { 0x8d, 0x33, 0x7a, 0xc3, 0xd0, 0xbb, 0x5b, 0xf9 } }
 
 /**
  * An internal interface that abstracts some DOMNode-related parts that both
  * nsIContent and nsIDocument share.  An instance of this interface has a list
  * of nsIContent children and provides access to them.
  */
 class nsINode : public nsIDOMEventTarget,
                 public nsWrapperCache
@@ -906,17 +910,18 @@ public:
 
   void SetFlags(uint32_t aFlagsToSet)
   {
     NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS |
                                   NODE_IS_NATIVE_ANONYMOUS_ROOT |
                                   NODE_IS_IN_ANONYMOUS_SUBTREE |
                                   NODE_ATTACH_BINDING_ON_POSTCREATE |
                                   NODE_DESCENDANTS_NEED_FRAMES |
-                                  NODE_NEEDS_FRAME)) ||
+                                  NODE_NEEDS_FRAME |
+                                  NODE_CHROME_ONLY_ACCESS)) ||
                  IsNodeOfType(eCONTENT),
                  "Flag only permitted on nsIContent nodes");
     mFlags |= aFlagsToSet;
   }
 
   void UnsetFlags(uint32_t aFlagsToUnset)
   {
     NS_ASSERTION(!(aFlagsToUnset &
@@ -957,16 +962,23 @@ public:
     }
     CheckNotNativeAnonymous();
     return false;
 #else
     return HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE);
 #endif
   }
 
+  // True for native anonymous content and for XBL content if the binging
+  // has chromeOnlyContent="true".
+  bool ChromeOnlyAccess() const
+  {
+    return HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE | NODE_CHROME_ONLY_ACCESS);
+  }
+
   /**
    * Returns true if |this| node is the common ancestor of the start/end
    * nodes of a Range in a Selection or a descendant of such a common ancestor.
    * This node is definitely not selected when |false| is returned, but it may
    * or may not be selected when |true| is returned.
    */
   bool IsSelectionDescendant() const
   {
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -130,22 +130,22 @@ using namespace mozilla::dom;
 
 NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
 
 int32_t nsIContent::sTabFocusModel = eTabFocus_any;
 bool nsIContent::sTabFocusModelAppliesToXUL = false;
 uint32_t nsMutationGuard::sMutationCount = 0;
 
 nsIContent*
-nsIContent::FindFirstNonNativeAnonymous() const
+nsIContent::FindFirstNonChromeOnlyAccessContent() const
 {
   // This handles also nested native anonymous content.
   for (const nsIContent *content = this; content;
        content = content->GetBindingParent()) {
-    if (!content->IsInNativeAnonymousSubtree()) {
+    if (!content->ChromeOnlyAccess()) {
       // Oops, this function signature allows casting const to
       // non-const.  (Then again, so does GetChildAt(0)->GetParent().)
       return const_cast<nsIContent*>(content);
     }
   }
   return nullptr;
 }
 
@@ -846,72 +846,72 @@ FragmentOrElement::GetChildren(uint32_t 
   }
 
   nsINodeList* returnList = nullptr;
   list.forget(&returnList);
   return returnList;
 }
 
 static nsIContent*
-FindNativeAnonymousSubtreeOwner(nsIContent* aContent)
+FindChromeAccessOnlySubtreeOwner(nsIContent* aContent)
 {
-  if (aContent->IsInNativeAnonymousSubtree()) {
-    bool isNativeAnon = false;
-    while (aContent && !isNativeAnon) {
-      isNativeAnon = aContent->IsRootOfNativeAnonymousSubtree();
+  if (aContent->ChromeOnlyAccess()) {
+    bool chromeAccessOnly = false;
+    while (aContent && !chromeAccessOnly) {
+      chromeAccessOnly = aContent->IsRootOfChromeAccessOnlySubtree();
       aContent = aContent->GetParent();
     }
   }
   return aContent;
 }
 
 nsresult
 nsIContent::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   //FIXME! Document how this event retargeting works, Bug 329124.
   aVisitor.mCanHandle = true;
   aVisitor.mMayHaveListenerManager = HasListenerManager();
 
   // Don't propagate mouseover and mouseout events when mouse is moving
-  // inside native anonymous content.
-  bool isAnonForEvents = IsRootOfNativeAnonymousSubtree();
+  // inside chrome access only content.
+  bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree();
   if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
        aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) &&
       // Check if we should stop event propagation when event has just been
       // dispatched or when we're about to propagate from
-      // native anonymous subtree.
+      // chrome access only subtree.
       ((this == aVisitor.mEvent->originalTarget &&
-        !IsInNativeAnonymousSubtree()) || isAnonForEvents)) {
+        !ChromeOnlyAccess()) || isAnonForEvents)) {
      nsCOMPtr<nsIContent> relatedTarget =
        do_QueryInterface(static_cast<nsMouseEvent*>
                                     (aVisitor.mEvent)->relatedTarget);
     if (relatedTarget &&
         relatedTarget->OwnerDoc() == OwnerDoc()) {
 
       // If current target is anonymous for events or we know that related
       // target is descendant of an element which is anonymous for events,
       // we may want to stop event propagation.
       // If this is the original target, aVisitor.mRelatedTargetIsInAnon
       // must be updated.
       if (isAnonForEvents || aVisitor.mRelatedTargetIsInAnon ||
           (aVisitor.mEvent->originalTarget == this &&
            (aVisitor.mRelatedTargetIsInAnon =
-            relatedTarget->IsInNativeAnonymousSubtree()))) {
-        nsIContent* anonOwner = FindNativeAnonymousSubtreeOwner(this);
+            relatedTarget->ChromeOnlyAccess()))) {
+        nsIContent* anonOwner = FindChromeAccessOnlySubtreeOwner(this);
         if (anonOwner) {
           nsIContent* anonOwnerRelated =
-            FindNativeAnonymousSubtreeOwner(relatedTarget);
+            FindChromeAccessOnlySubtreeOwner(relatedTarget);
           if (anonOwnerRelated) {
             // Note, anonOwnerRelated may still be inside some other
             // native anonymous subtree. The case where anonOwner is still
             // inside native anonymous subtree will be handled when event
             // propagates up in the DOM tree.
             while (anonOwner != anonOwnerRelated &&
-                   anonOwnerRelated->IsInNativeAnonymousSubtree()) {
-              anonOwnerRelated = FindNativeAnonymousSubtreeOwner(anonOwnerRelated);
+                   anonOwnerRelated->ChromeOnlyAccess()) {
+              anonOwnerRelated = FindChromeAccessOnlySubtreeOwner(anonOwnerRelated);
             }
             if (anonOwner == anonOwnerRelated) {
 #ifdef DEBUG_smaug
               nsCOMPtr<nsIContent> originalTarget =
                 do_QueryInterface(aVisitor.mEvent->originalTarget);
               nsAutoString ot, ct, rt;
               if (originalTarget) {
                 originalTarget->Tag()->ToString(ot);
@@ -922,23 +922,24 @@ nsIContent::PreHandleEvent(nsEventChainP
                      "\n\toriginalTarget=%s \n\tcurrentTarget=%s %s"
                      "\n\trelatedTarget=%s %s \n%s",
                      (aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH)
                        ? "mouseover" : "mouseout",
                      NS_ConvertUTF16toUTF8(ot).get(),
                      NS_ConvertUTF16toUTF8(ct).get(),
                      isAnonForEvents
                        ? "(is native anonymous)"
-                       : (IsInNativeAnonymousSubtree()
+                       : (ChromeOnlyAccess()
                            ? "(is in native anonymous subtree)" : ""),
                      NS_ConvertUTF16toUTF8(rt).get(),
-                     relatedTarget->IsInNativeAnonymousSubtree()
+                     relatedTarget->ChromeOnlyAccess()
                        ? "(is in native anonymous subtree)" : "",
-                     (originalTarget && relatedTarget->FindFirstNonNativeAnonymous() ==
-                       originalTarget->FindFirstNonNativeAnonymous())
+                     (originalTarget &&
+                      relatedTarget->FindFirstNonChromeOnlyAccessContent() ==
+                        originalTarget->FindFirstNonChromeOnlyAccessContent())
                        ? "" : "Wrong event propagation!?!\n");
 #endif
               aVisitor.mParentTarget = nullptr;
               // Event should not propagate to non-anon content.
               aVisitor.mCanHandle = isAnonForEvents;
               return NS_OK;
             }
           }
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3821,17 +3821,17 @@ nsContentUtils::HasMutationListeners(nsI
   nsPIDOMWindow* window = doc->GetInnerWindow();
   // This relies on nsEventListenerManager::AddEventListener, which sets
   // all mutation bits when there is a listener for DOMSubtreeModified event.
   if (window && !window->HasMutationListeners(aType)) {
     return false;
   }
 
   if (aNode->IsNodeOfType(nsINode::eCONTENT) &&
-      static_cast<nsIContent*>(aNode)->IsInNativeAnonymousSubtree()) {
+      static_cast<nsIContent*>(aNode)->ChromeOnlyAccess()) {
     return false;
   }
 
   doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
 
   // If we have a window, we can check it for mutation listeners now.
   if (aNode->IsInDoc()) {
     nsCOMPtr<nsIDOMEventTarget> piTarget(do_QueryInterface(window));
--- a/content/base/src/nsDOMMutationObserver.cpp
+++ b/content/base/src/nsDOMMutationObserver.cpp
@@ -171,17 +171,17 @@ void
 nsMutationReceiver::AttributeWillChange(nsIDocument* aDocument,
                                         mozilla::dom::Element* aElement,
                                         int32_t aNameSpaceID,
                                         nsIAtom* aAttribute,
                                         int32_t aModType)
 {
   if (nsAutoMutationBatch::IsBatching() ||
       !ObservesAttr(aElement, aNameSpaceID, aAttribute) ||
-      aElement->IsInNativeAnonymousSubtree()) {
+      aElement->ChromeOnlyAccess()) {
     return;
   }
 
   nsDOMMutationRecord* m =
     Observer()->CurrentRecord(NS_LITERAL_STRING("attributes"));
 
   NS_ASSERTION(!m->mTarget || m->mTarget == aElement,
                "Wrong target!");
@@ -208,17 +208,17 @@ nsMutationReceiver::AttributeWillChange(
 
 void
 nsMutationReceiver::CharacterDataWillChange(nsIDocument *aDocument,
                                             nsIContent* aContent,
                                             CharacterDataChangeInfo* aInfo)
 {
   if (nsAutoMutationBatch::IsBatching() ||
       !CharacterData() || !(Subtree() || aContent == Target()) ||
-      aContent->IsInNativeAnonymousSubtree()) {
+      aContent->ChromeOnlyAccess()) {
     return;
   }
   
   nsDOMMutationRecord* m =
     Observer()->CurrentRecord(NS_LITERAL_STRING("characterData"));
  
   NS_ASSERTION(!m->mTarget || m->mTarget == aContent,
                "Wrong target!");
@@ -234,17 +234,17 @@ nsMutationReceiver::CharacterDataWillCha
 void
 nsMutationReceiver::ContentAppended(nsIDocument* aDocument,
                                     nsIContent* aContainer,
                                     nsIContent* aFirstNewContent,
                                     int32_t aNewIndexInContainer)
 {
   nsINode* parent = NODE_FROM(aContainer, aDocument);
   bool wantsChildList = ChildList() && (Subtree() || parent == Target());
-  if (!wantsChildList || aFirstNewContent->IsInNativeAnonymousSubtree()) {
+  if (!wantsChildList || aFirstNewContent->ChromeOnlyAccess()) {
     return;
   }
 
   if (nsAutoMutationBatch::IsBatching()) {
     if (parent == nsAutoMutationBatch::GetBatchTarget()) {
       nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList);
     }
     return;
@@ -272,17 +272,17 @@ nsMutationReceiver::ContentAppended(nsID
 void
 nsMutationReceiver::ContentInserted(nsIDocument* aDocument,
                                     nsIContent* aContainer,
                                     nsIContent* aChild,
                                     int32_t aIndexInContainer)
 {
   nsINode* parent = NODE_FROM(aContainer, aDocument);
   bool wantsChildList = ChildList() && (Subtree() || parent == Target());
-  if (!wantsChildList || aChild->IsInNativeAnonymousSubtree()) {
+  if (!wantsChildList || aChild->ChromeOnlyAccess()) {
     return;
   }
 
   if (nsAutoMutationBatch::IsBatching()) {
     if (parent == nsAutoMutationBatch::GetBatchTarget()) {
       nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList);
     }
     return;
@@ -303,17 +303,17 @@ nsMutationReceiver::ContentInserted(nsID
 
 void
 nsMutationReceiver::ContentRemoved(nsIDocument* aDocument,
                                    nsIContent* aContainer,
                                    nsIContent* aChild,
                                    int32_t aIndexInContainer,
                                    nsIContent* aPreviousSibling)
 {
-  if (aChild->IsInNativeAnonymousSubtree()) {
+  if (aChild->ChromeOnlyAccess()) {
     return;
   }
 
   nsINode* parent = NODE_FROM(aContainer, aDocument);
   if (nsAutoMutationBatch::IsBatching()) {
     if (nsAutoMutationBatch::IsRemovalDone()) {
       // This can happen for example if HTML parser parses to
       // context node, but needs to move elements around.
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2854,18 +2854,18 @@ nsDocument::GetActiveElement(nsIDOMEleme
   nsCOMPtr<nsPIDOMWindow> window = GetWindow();
   if (window) {
     nsCOMPtr<nsPIDOMWindow> focusedWindow;
     nsIContent* focusedContent =
       nsFocusManager::GetFocusedDescendant(window, false,
                                            getter_AddRefs(focusedWindow));
     // be safe and make sure the element is from this document
     if (focusedContent && focusedContent->OwnerDoc() == this) {
-      if (focusedContent->IsInNativeAnonymousSubtree()) {
-        focusedContent = focusedContent->FindFirstNonNativeAnonymous();
+      if (focusedContent->ChromeOnlyAccess()) {
+        focusedContent = focusedContent->FindFirstNonChromeOnlyAccessContent();
       }
       if (focusedContent) {
         CallQueryInterface(focusedContent, aElement);
         return NS_OK;
       }
     }
   }
 
@@ -7578,17 +7578,17 @@ nsDocument::MutationEventDispatched(nsIN
       mSubtreeModifiedTargets.Clear();
       return;
     }
 
     nsCOMArray<nsINode> realTargets;
     for (int32_t i = 0; i < count; ++i) {
       nsINode* possibleTarget = mSubtreeModifiedTargets[i];
       nsCOMPtr<nsIContent> content = do_QueryInterface(possibleTarget);
-      if (content && content->IsInNativeAnonymousSubtree()) {
+      if (content && content->ChromeOnlyAccess()) {
         continue;
       }
 
       nsINode* commonAncestor = nullptr;
       int32_t realTargetCount = realTargets.Count();
       for (int32_t j = 0; j < realTargetCount; ++j) {
         commonAncestor =
           nsContentUtils::GetCommonAncestor(possibleTarget, realTargets[j]);
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -462,16 +462,19 @@ nsGenericDOMDataNode::BindToTree(nsIDocu
                  !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
                  (aParent && aParent->IsInNativeAnonymousSubtree()),
                  "Trying to re-bind content from native anonymous subtree to "
                  "non-native anonymous parent!");
     DataSlots()->mBindingParent = aBindingParent; // Weak, so no addref happens.
     if (aParent->IsInNativeAnonymousSubtree()) {
       SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
     }
+    if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) {
+      SetFlags(NODE_CHROME_ONLY_ACCESS);
+    }
   }
 
   // Set parent
   if (aParent) {
     if (!GetParent()) {
       NS_ADDREF(aParent);
     }
     mParent = aParent;
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1295,18 +1295,23 @@ nsGenericElement::BindToTree(nsIDocument
       slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
     }
   }
   NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() ||
                !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
                (aParent && aParent->IsInNativeAnonymousSubtree()),
                "Trying to re-bind content from native anonymous subtree to "
                "non-native anonymous parent!");
-  if (aParent && aParent->IsInNativeAnonymousSubtree()) {
-    SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
+  if (aParent) {
+    if (aParent->IsInNativeAnonymousSubtree()) {
+      SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
+    }
+    if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) {
+      SetFlags(NODE_CHROME_ONLY_ACCESS);
+    }
   }
 
   bool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
 
   // Now set the parent and set the "Force attach xbl" flag if needed.
   if (aParent) {
     if (!GetParent()) {
       NS_ADDREF(aParent);
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -167,16 +167,17 @@ GK_ATOM(charcode, "charcode")
 GK_ATOM(charoff, "charoff")
 GK_ATOM(charset, "charset")
 GK_ATOM(checkbox, "checkbox")
 GK_ATOM(checked, "checked")
 GK_ATOM(child, "child")
 GK_ATOM(children, "children")
 GK_ATOM(choose, "choose")
 GK_ATOM(chromemargin, "chromemargin")
+GK_ATOM(chromeOnlyContent, "chromeOnlyContent")
 GK_ATOM(circ, "circ")
 GK_ATOM(circle, "circle")
 GK_ATOM(cite, "cite")
 GK_ATOM(_class, "class")
 GK_ATOM(classid, "classid")
 GK_ATOM(clear, "clear")
 GK_ATOM(click, "click")
 GK_ATOM(clickcount, "clickcount")
--- a/content/events/src/nsDOMMouseEvent.cpp
+++ b/content/events/src/nsDOMMouseEvent.cpp
@@ -256,19 +256,19 @@ nsDOMMouseEvent::GetRelatedTarget(nsIDOM
       relatedTarget = static_cast<nsMouseEvent_base*>(mEvent)->relatedTarget;
       break;
     default:
       break;
   }
 
   if (relatedTarget) {
     nsCOMPtr<nsIContent> content = do_QueryInterface(relatedTarget);
-    if (content && content->IsInNativeAnonymousSubtree() &&
+    if (content && content->ChromeOnlyAccess() &&
         !nsContentUtils::CanAccessNativeAnon()) {
-      relatedTarget = content->FindFirstNonNativeAnonymous();
+      relatedTarget = content->FindFirstNonChromeOnlyAccessContent();
       if (!relatedTarget) {
         return NS_OK;
       }
     }
 
     CallQueryInterface(relatedTarget, aRelatedTarget);
   }
   return NS_OK;
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -249,17 +249,17 @@ nsDOMUIEvent::GetRangeParent(nsIDOMNode*
 
   *aRangeParent = nullptr;
 
   if (targetFrame) {
     nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent,
                                                               targetFrame);
     nsCOMPtr<nsIContent> parent = targetFrame->GetContentOffsetsFromPoint(pt).content;
     if (parent) {
-      if (parent->IsInNativeAnonymousSubtree() &&
+      if (parent->ChromeOnlyAccess() &&
           !nsContentUtils::CanAccessNativeAnon()) {
         return NS_OK;
       }
       return CallQueryInterface(parent, aRangeParent);
     }
   }
 
   return NS_OK;
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -463,17 +463,17 @@ nsEventDispatcher::Dispatch(nsISupports*
   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(aTarget);
 
   bool retargeted = false;
 
   if (aEvent->flags & NS_EVENT_RETARGET_TO_NON_NATIVE_ANONYMOUS) {
     nsCOMPtr<nsIContent> content = do_QueryInterface(target);
     if (content && content->IsInNativeAnonymousSubtree()) {
       nsCOMPtr<nsPIDOMEventTarget> newTarget =
-        do_QueryInterface(content->FindFirstNonNativeAnonymous());
+        do_QueryInterface(content->FindFirstNonChromeOnlyAccessContent());
       NS_ENSURE_STATE(newTarget);
 
       aEvent->originalTarget = target;
       target = newTarget;
       retargeted = true;
     }
   }
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -3931,26 +3931,26 @@ public:
                             nsIContent* aTarget, nsIContent* aRelatedTarget,
                             nsGUIEvent* aEvent, uint32_t aType)
   : mESM(aESM), mEvent(aEvent), mType(aType)
   {
     nsPIDOMWindow* win =
       aTarget ? aTarget->OwnerDoc()->GetInnerWindow() : nullptr;
     if (win && win->HasMouseEnterLeaveEventListeners()) {
       mRelatedTarget = aRelatedTarget ?
-        aRelatedTarget->FindFirstNonNativeAnonymous() : nullptr;
+        aRelatedTarget->FindFirstNonChromeOnlyAccessContent() : nullptr;
       nsINode* commonParent = nullptr;
       if (aTarget && aRelatedTarget) {
         commonParent =
           nsContentUtils::GetCommonAncestor(aTarget, aRelatedTarget);
       }
       nsIContent* current = aTarget;
       // Note, it is ok if commonParent is null!
       while (current && current != commonParent) {
-        if (!current->IsInNativeAnonymousSubtree()) {
+        if (!current->ChromeOnlyAccess()) {
           mTargets.AppendObject(current);
         }
         // mouseenter/leave is fired only on elements.
         current = current->GetParent();
       }
     }
   }
 
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -460,17 +460,18 @@ nsXBLBinding::SetBaseBinding(nsXBLBindin
     NS_ERROR("Base XBL binding is already defined!");
     return;
   }
 
   mNextBinding = aBinding; // Comptr handles rel/add
 }
 
 void
-nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement)
+nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement,
+                                      bool aChromeOnlyContent)
 {
   // We need to ensure two things.
   // (1) The anonymous content should be fooled into thinking it's in the bound
   // element's document, assuming that the bound element is in a document
   // Note that we don't change the current doc of aAnonParent here, since that
   // quite simply does not matter.  aAnonParent is just a way of keeping refs
   // to all its kids, which are anonymous content from the point of view of
   // aElement.
@@ -479,16 +480,20 @@ nsXBLBinding::InstallAnonymousContent(ns
   nsIDocument* doc = aElement->GetCurrentDoc();
   bool allowScripts = AllowScripts();
 
   nsAutoScriptBlocker scriptBlocker;
   for (nsIContent* child = aAnonParent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     child->UnbindFromTree();
+    if (aChromeOnlyContent) {
+      child->SetFlags(NODE_CHROME_ONLY_ACCESS |
+                      NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS);
+    }
     nsresult rv =
       child->BindToTree(doc, aElement, mBoundElement, allowScripts);
     if (NS_FAILED(rv)) {
       // Oh, well... Just give up.
       // XXXbz This really shouldn't be a void method!
       child->UnbindFromTree();
       return;
     }        
@@ -688,17 +693,19 @@ RealizeDefaultContent(nsISupports* aKey,
         nsCOMPtr<nsIDOMNode> clonedNode;
         nsCOMArray<nsINode> nodesWithProperties;
         nsNodeUtils::Clone(defContent, true, document->NodeInfoManager(),
                            nodesWithProperties, getter_AddRefs(clonedNode));
 
         // Now that we have the cloned content, install the default content as
         // if it were additional anonymous content.
         nsCOMPtr<nsIContent> clonedContent(do_QueryInterface(clonedNode));
-        binding->InstallAnonymousContent(clonedContent, insParent);
+        binding->InstallAnonymousContent(clonedContent, insParent,
+                                         binding->PrototypeBinding()->
+                                           ChromeOnlyContent());
 
         // Cache the clone so that it can be properly destroyed if/when our
         // other anonymous content is destroyed.
         currPoint->SetDefaultContent(clonedContent);
 
         // Now make sure the kids of the clone are added to the insertion point as
         // children.
         for (nsIContent* child = clonedContent->GetFirstChild();
@@ -800,17 +807,18 @@ nsXBLBinding::GenerateAnonymousContent()
 
     if (hasContent || hasInsertionPoints) {
       nsCOMPtr<nsIDOMNode> clonedNode;
       nsCOMArray<nsINode> nodesWithProperties;
       nsNodeUtils::Clone(content, true, doc->NodeInfoManager(),
                          nodesWithProperties, getter_AddRefs(clonedNode));
 
       mContent = do_QueryInterface(clonedNode);
-      InstallAnonymousContent(mContent, mBoundElement);
+      InstallAnonymousContent(mContent, mBoundElement,
+                              mPrototypeBinding->ChromeOnlyContent());
 
       if (hasInsertionPoints) {
         // Now check and see if we have a single insertion point 
         // or multiple insertion points.
       
         // Enumerate the prototype binding's insertion table to build
         // our table of instantiated insertion points.
         mPrototypeBinding->InstantiateInsertionPoints(this);
--- a/content/xbl/src/nsXBLBinding.h
+++ b/content/xbl/src/nsXBLBinding.h
@@ -64,17 +64,18 @@ public:
   void MarkForDeath();
   bool MarkedForDeath() const { return mMarkedForDeath; }
 
   bool HasStyleSheets() const;
   bool InheritsStyle() const;
   bool ImplementsInterface(REFNSIID aIID) const;
 
   void GenerateAnonymousContent();
-  void InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement);
+  void InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement,
+                               bool aNativeAnon);
   static void UninstallAnonymousContent(nsIDocument* aDocument,
                                         nsIContent* aAnonParent);
   void InstallEventHandlers();
   nsresult InstallImplementation();
 
   void ExecuteAttachedHandler();
   void ExecuteDetachedHandler();
   void UnhookEventHandlers();
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -269,16 +269,17 @@ static const int32_t kInsInitialSize = s
 
 // Constructors/Destructors
 nsXBLPrototypeBinding::nsXBLPrototypeBinding()
 : mImplementation(nullptr),
   mBaseBinding(nullptr),
   mInheritStyle(true), 
   mCheckedBaseProto(false),
   mKeyHandlersRegistered(false),
+  mChromeOnlyContent(false),
   mResources(nullptr),
   mAttributeTable(nullptr),
   mInsertionPointTable(nullptr),
   mInterfaceTable(nullptr),
   mBaseNameSpaceID(kNameSpaceID_None)
 {
   MOZ_COUNT_CTOR(nsXBLPrototypeBinding);
   gRefCnt++;
@@ -437,16 +438,21 @@ nsXBLPrototypeBinding::GetBindingElement
 
 void
 nsXBLPrototypeBinding::SetBindingElement(nsIContent* aElement)
 {
   mBinding = aElement;
   if (mBinding->AttrValueIs(kNameSpaceID_None, nsGkAtoms::inheritstyle,
                             nsGkAtoms::_false, eCaseMatters))
     mInheritStyle = false;
+
+  mChromeOnlyContent = IsChrome() &&
+                       mBinding->AttrValueIs(kNameSpaceID_None,
+                                             nsGkAtoms::chromeOnlyContent,
+                                             nsGkAtoms::_true, eCaseMatters);
 }
 
 bool
 nsXBLPrototypeBinding::GetAllowScripts()
 {
   return mXBLDocInfoWeak->GetScriptAccess();
 }
 
@@ -1461,16 +1467,18 @@ public:
 
 nsresult
 nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
                             nsXBLDocumentInfo* aDocInfo,
                             nsIDocument* aDocument,
                             uint8_t aFlags)
 {
   mInheritStyle = (aFlags & XBLBinding_Serialize_InheritStyle) ? true : false;
+  mChromeOnlyContent =
+    (aFlags & XBLBinding_Serialize_ChromeOnlyContent) ? true : false;
 
   // nsXBLContentSink::ConstructBinding doesn't create a binding with an empty
   // id, so we don't here either.
   nsAutoCString id;
   nsresult rv = aStream->ReadCString(id);
 
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(!id.IsEmpty(), NS_ERROR_FAILURE);
@@ -1671,16 +1679,20 @@ nsXBLPrototypeBinding::Write(nsIObjectOu
 
   uint8_t flags = mInheritStyle ? XBLBinding_Serialize_InheritStyle : 0;
 
   // mAlternateBindingURI is only set on the first binding.
   if (mAlternateBindingURI) {
     flags |= XBLBinding_Serialize_IsFirstBinding;
   }
 
+  if (mChromeOnlyContent) {
+    flags |= XBLBinding_Serialize_ChromeOnlyContent;
+  }
+
   nsresult rv = aStream->Write8(flags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString id;
   mBindingURI->GetRef(id);
   rv = aStream->WriteStringZ(id.get());
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/xbl/src/nsXBLPrototypeBinding.h
+++ b/content/xbl/src/nsXBLPrototypeBinding.h
@@ -187,16 +187,18 @@ public:
   }
 
   /**
    * Read this binding from the stream aStream into the xbl document aDocument.
    * aDocInfo should be the xbl document info for the binding document.
    * aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that
    * mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding
    * to indicate the first binding in a document.
+   * XBLBinding_Serialize_ChromeOnlyContent indicates that
+   * nsXBLPrototypeBinding::mChromeOnlyContent should be true.
    */
   nsresult Read(nsIObjectInputStream* aStream,
                 nsXBLDocumentInfo* aDocInfo,
                 nsIDocument* aDocument,
                 uint8_t aFlags);
 
   /**
    * Write this binding to the stream.
@@ -296,16 +298,17 @@ public:
    * has the localname given by aTag and is in the XBL namespace.
    */
   nsIContent* GetImmediateChild(nsIAtom* aTag);
   nsIContent* LocateInstance(nsIContent* aBoundElt,
                              nsIContent* aTemplRoot,
                              nsIContent* aCopyRoot,
                              nsIContent* aTemplChild);
 
+  bool ChromeOnlyContent() { return mChromeOnlyContent; }
 protected:
   // Ensure that mAttributeTable has been created.
   void EnsureAttributeTable();
   // Ad an entry to the attribute table
   void AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag,
                            int32_t aDestNamespaceID, nsIAtom* aDestTag,
                            nsIContent* aContent);
   void ConstructAttributeTable(nsIContent* aElement);
@@ -327,16 +330,17 @@ protected:
 
   nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
                                    // the constructor, and the destructor).
 
   nsXBLPrototypeBinding* mBaseBinding; // Weak.  The docinfo will own our base binding.
   bool mInheritStyle;
   bool mCheckedBaseProto;
   bool mKeyHandlersRegistered;
+  bool mChromeOnlyContent;
  
   nsXBLPrototypeResources* mResources; // If we have any resources, this will be non-null.
                                       
   nsXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info.  Weak, since it owns us.
 
   nsObjectHashtable* mAttributeTable; // A table for attribute containers. Namespace IDs are used as
                                       // keys in the table. Containers are nsObjectHashtables.
                                       // This table is used to efficiently handle attribute changes.
--- a/content/xbl/src/nsXBLSerialize.h
+++ b/content/xbl/src/nsXBLSerialize.h
@@ -20,16 +20,19 @@ typedef uint8_t XBLBindingSerializeDetai
 #define XBLBinding_Serialize_Version 0x00000001
 
 // Set for the first binding in a document
 #define XBLBinding_Serialize_IsFirstBinding 1
 
 // Set to indicate that nsXBLPrototypeBinding::mInheritStyle should be true
 #define XBLBinding_Serialize_InheritStyle 2
 
+// Set to indicate that nsXBLPrototypeBinding::mChromeOnlyContent should be true
+#define XBLBinding_Serialize_ChromeOnlyContent 4
+
 // Appears at the end of the serialized data to indicate that no more bindings
 // are present for this document.
 #define XBLBinding_Serialize_NoMoreBindings 0x80
 
 // Implementation member types. The serialized value for each member contains one
 // of these values, combined with the read-only flag XBLBinding_Serialize_ReadOnly.
 // Use XBLBinding_Serialize_Mask to filter out the read-only flag and check for
 // just the member type.
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -7853,29 +7853,29 @@ nsNodeSH::PreCreate(nsISupports *nativeO
     else {
       // No global object reachable from this document, use the
       // global object that was passed to this method.
 
       *parentObj = globalObj;
     }
 
     // No slim wrappers for a document's scope object.
-    return node->IsInNativeAnonymousSubtree() ?
+    return node->ChromeOnlyAccess() ?
       NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
   }
 
   // XXXjst: Maybe we need to find the global to use from the
   // nsIScriptGlobalObject that's reachable from the node we're about
   // to wrap here? But that's not always reachable, let's use
   // globalObj for now...
 
   nsresult rv = WrapNativeParent(cx, globalObj, native_parent, parentObj);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return node->IsInNativeAnonymousSubtree() ?
+  return node->ChromeOnlyAccess() ?
     NS_SUCCESS_CHROME_ACCESS_ONLY : NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
 }
 
 NS_IMETHODIMP
 nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                       JSObject *obj, jsid id, jsval *vp, bool *_retval)
 {
   nsNodeSH::PreserveWrapper(GetNative(wrapper, obj));
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -973,18 +973,18 @@ nsEditorEventListener::SpellCheckIfNeede
     mEditor->SetFlags(currentFlags);
   }
 }
 
 bool
 nsEditorEventListener::IsFileControlTextBox()
 {
   dom::Element* root = mEditor->GetRoot();
-  if (root && root->IsInNativeAnonymousSubtree()) {
-    nsIContent* parent = root->FindFirstNonNativeAnonymous();
+  if (root && root->ChromeOnlyAccess()) {
+    nsIContent* parent = root->FindFirstNonChromeOnlyAccessContent();
     if (parent && parent->IsHTML(nsGkAtoms::input)) {
       nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(parent);
       MOZ_ASSERT(formControl);
       return formControl->GetType() == NS_FORM_INPUT_FILE;
     }
   }
   return false;
 }
--- a/embedding/components/find/src/nsFind.cpp
+++ b/embedding/components/find/src/nsFind.cpp
@@ -243,23 +243,23 @@ nsFindContentIterator::Reset()
   mEndOuterContent = nullptr;
 
   // As a consequence of searching through text controls, we may have been
   // initialized with a selection inside a <textarea> or a text <input>.
 
   // see if the start node is an anonymous text node inside a text control
   nsCOMPtr<nsIContent> startContent(do_QueryInterface(mStartNode));
   if (startContent) {
-    mStartOuterContent = startContent->FindFirstNonNativeAnonymous();
+    mStartOuterContent = startContent->FindFirstNonChromeOnlyAccessContent();
   }
 
   // see if the end node is an anonymous text node inside a text control
   nsCOMPtr<nsIContent> endContent(do_QueryInterface(mEndNode));
   if (endContent) {
-    mEndOuterContent = endContent->FindFirstNonNativeAnonymous();
+    mEndOuterContent = endContent->FindFirstNonChromeOnlyAccessContent();
   }
 
   // Note: OK to just set up the outer iterator here; if our range has a native
   // anonymous endpoint we'll end up setting up an inner iterator, and
   // reset the outer one in the process.
   nsCOMPtr<nsIDOMRange> range = nsFind::CreateRange();
   range->SetStart(mStartNode, mStartOffset);
   range->SetEnd(mEndNode, mEndOffset);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6757,17 +6757,17 @@ PresShell::PrepareToUseCaretPosition(nsI
   // note: frames are not refcounted
   nsIFrame* frame = nullptr; // may be NULL
   nsCOMPtr<nsIDOMNode> node;
   rv = domSelection->GetFocusNode(getter_AddRefs(node));
   NS_ENSURE_SUCCESS(rv, false);
   NS_ENSURE_TRUE(node, false);
   nsCOMPtr<nsIContent> content(do_QueryInterface(node));
   if (content) {
-    nsIContent* nonNative = content->FindFirstNonNativeAnonymous();
+    nsIContent* nonNative = content->FindFirstNonChromeOnlyAccessContent();
     content = nonNative;
   }
 
   if (content) {
     // It seems like ScrollSelectionIntoView should be enough, but it's
     // not. The problem is that scrolling the selection into view when it is
     // below the current viewport will align the top line of the frame exactly
     // with the bottom of the window. This is fine, BUT, the popup event causes
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -344,17 +344,17 @@ nsResizerFrame::GetContentToResize(nsIPr
       int32_t type = -1;
       isChromeShell = (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
                        type == nsIDocShellTreeItem::typeChrome);
     }
 
     if (!isChromeShell) {
       // don't allow resizers in content shells, except for the viewport
       // scrollbar which doesn't have a parent
-      nsIContent* nonNativeAnon = mContent->FindFirstNonNativeAnonymous();
+      nsIContent* nonNativeAnon = mContent->FindFirstNonChromeOnlyAccessContent();
       if (!nonNativeAnon || nonNativeAnon->GetParent()) {
         return nullptr;
       }
     }
 
     // get the document and the window - should this be cached?
     nsPIDOMWindow *domWindow = aPresShell->GetDocument()->GetWindow();
     if (domWindow) {
@@ -370,17 +370,17 @@ nsResizerFrame::GetContentToResize(nsIPr
     }
 
     return nullptr;
   }
 
   if (elementid.EqualsLiteral("_parent")) {
     // return the parent, but skip over native anonymous content
     nsIContent* parent = mContent->GetParent();
-    return parent ? parent->FindFirstNonNativeAnonymous() : nullptr;
+    return parent ? parent->FindFirstNonChromeOnlyAccessContent() : nullptr;
   }
 
   return aPresShell->GetDocument()->GetElementById(elementid);
 }
 
 void
 nsResizerFrame::AdjustDimensions(int32_t* aPos, int32_t* aSize,
                                  int32_t aMinSize, int32_t aMaxSize,
--- a/toolkit/mozapps/plugins/content/pluginProblem.xml
+++ b/toolkit/mozapps/plugins/content/pluginProblem.xml
@@ -10,17 +10,17 @@
   %globalDTD;
   %brandDTD;
 ]>
 
 <bindings id="pluginBindings"
               xmlns="http://www.mozilla.org/xbl"
               xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
               xmlns:html="http://www.w3.org/1999/xhtml">
-<binding id="pluginProblem" inheritstyle="false">
+<binding id="pluginProblem" inheritstyle="false" chromeOnlyContent="true">
     <resources>
         <stylesheet src="chrome://mozapps/content/plugins/pluginProblemContent.css"/>
         <stylesheet src="chrome://mozapps/skin/plugins/pluginProblem.css"/>
     </resources>
 
     <content>
         <xul:vbox class="mainBox" flex="1" chromedir="&locale.dir;">
             <xul:spacer flex="1"/>