void nsOuterDocAccessible::CacheChildren(PRBool aWalkAnonContent)
{  
  // An outer doc accessible usually has 1 nsDocAccessible child,
  // but could have none if we can't get to the inner documnet
  if (!mWeakShell) {
    mAccChildCount = eChildCountUninitialized;
    return;   // This outer doc node has been shut down
  }
  if (mAccChildCount != eChildCountUninitialized) {
    return;
  }

  mAccChildCount = 0;
  SetFirstChild(nsnull);

  // In these variable names, "outer" relates to the nsOuterDocAccessible
  // as opposed to the nsDocAccessibleWrap which is "inner".
  // The outer node is a something like a <browser>, <frame>, <iframe>, <page> or
  // <editor> tag, whereas the inner node corresponds to the inner document root.

  nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
  NS_ASSERTION(content, "No nsIContent for <browser>/<iframe>/<editor> dom node");

  nsCOMPtr<nsIDocument> outerDoc = content->GetDocument();
  if (!outerDoc) {
    return;
  }

  nsIDocument *innerDoc = outerDoc->GetSubDocumentFor(content);
  nsCOMPtr<nsIDOMNode> innerNode(do_QueryInterface(innerDoc));
  if (!innerNode) {
    return;
  }

  nsCOMPtr<nsIAccessible> innerAccessible;
  nsCOMPtr<nsIAccessibilityService> accService = 
    do_GetService("@mozilla.org/accessibilityService;1");
  accService->GetAccessibleFor(innerNode, getter_AddRefs(innerAccessible));
  nsCOMPtr<nsPIAccessible> privateInnerAccessible = 
    do_QueryInterface(innerAccessible);
  if (!privateInnerAccessible) {
    return;
  }

  // Success getting inner document as first child -- now we cache it.
  mAccChildCount = 1;
  SetFirstChild(innerAccessible); // weak ref
  privateInnerAccessible->SetParent(this);
  privateInnerAccessible->SetNextSibling(nsnull);
}
void nsHTMLComboboxTextFieldAccessible::CacheChildren()
{
  // Allow single text anonymous child, so that nsHyperTextAccessible can operate correctly
  // We must override this otherwise we get the dropdown button as a child of the textfield,
  // and at least for now we want to keep it as a sibling
  if (!mWeakShell) {
    // This node has been shut down
    mAccChildCount = eChildCountUninitialized;
    return;
  }

  // Allows only 1 child
  if (mAccChildCount == eChildCountUninitialized) {
    mAccChildCount = 0; // Prevent reentry
    nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
    // Seed the frame hint early while we're still on a container node.
    // This is better than doing the GetPrimaryFrameFor() later on
    // a text node, because text nodes aren't in the frame map.
    walker.mState.frame = GetFrame();

    walker.GetFirstChild();
    SetFirstChild(walker.mState.accessible);
    nsRefPtr<nsAccessible> child =
      nsAccUtils::QueryAccessible(walker.mState.accessible);
    child->SetParent(this);
    child->SetNextSibling(nsnull);
    mAccChildCount = 1;
  }
}
void nsHTMLSelectOptGroupAccessible::CacheChildren()
{
  if (!mWeakShell) {
    // This node has been shut down
    mAccChildCount = eChildCountUninitialized;
    return;
  }

  if (mAccChildCount == eChildCountUninitialized) {
    // XXX To do (bug 378612) - create text child for the anonymous attribute content, so that
    // nsIAccessibleText is supported for the <optgroup> as it is for an <option>
    // Attribute content is what layout creates for the label="foo" on the <optgroup>
    // See eStyleContentType_Attr and CreateAttributeContent() in nsCSSFrameConstructor
    mAccChildCount = 0;
    SetFirstChild(nsnull);
  }
}
void nsHTMLComboboxAccessible::CacheChildren()
{
  if (!mWeakShell) {
    // This node has been shut down
    mAccChildCount = eChildCountUninitialized;
    return;
  }

  if (mAccChildCount == eChildCountUninitialized) {
    mAccChildCount = 0;
#ifdef COMBO_BOX_WITH_THREE_CHILDREN
    // We no longer create textfield and button accessible, in order to have
    // harmonization between IAccessible2, ATK/AT-SPI and OS X
    nsHTMLComboboxTextFieldAccessible* textFieldAccessible = 
      new nsHTMLComboboxTextFieldAccessible(this, mDOMNode, mWeakShell);
    SetFirstChild(textFieldAccessible);
    if (!textFieldAccessible) {
      return;
    }
    textFieldAccessible->SetParent(this);
    textFieldAccessible->Init();
    mAccChildCount = 1;  // Textfield accessible child successfully added

    nsHTMLComboboxButtonAccessible* buttonAccessible =
      new nsHTMLComboboxButtonAccessible(mParent, mDOMNode, mWeakShell);
    textFieldAccessible->SetNextSibling(buttonAccessible);
    if (!buttonAccessible) {
      return;
    }

    buttonAccessible->SetParent(this);
    buttonAccessible->Init();
    mAccChildCount = 2; // Button accessible child successfully added
#endif

    nsIFrame *frame = GetFrame();
    if (!frame) {
      return;
    }
    nsIComboboxControlFrame *comboFrame = do_QueryFrame(frame);
    if (!comboFrame) {
      return;
    }
    nsIFrame *listFrame = comboFrame->GetDropDown();
    if (!listFrame) {
      return;
    }

    if (!mListAccessible) {
      mListAccessible = 
        new nsHTMLComboboxListAccessible(mParent, mDOMNode, mWeakShell);
      if (!mListAccessible)
        return;

      mListAccessible->Init();
    }

#ifdef COMBO_BOX_WITH_THREE_CHILDREN
    buttonAccessible->SetNextSibling(mListAccessible);
#else
    SetFirstChild(mListAccessible);
#endif

    mListAccessible->SetParent(this);
    mListAccessible->SetNextSibling(nsnull);

    ++ mAccChildCount;  // List accessible child successfully added
  }
}