static void
MarkChildMessageManagers(ChromeMessageBroadcaster* aMM)
{
  aMM->MarkForCC();

  uint32_t tabChildCount = aMM->ChildCount();
  for (uint32_t j = 0; j < tabChildCount; ++j) {
    RefPtr<MessageListenerManager> childMM = aMM->GetChildAt(j);
    if (!childMM) {
      continue;
    }

    RefPtr<ChromeMessageBroadcaster> strongNonLeafMM =
      ChromeMessageBroadcaster::From(childMM);
    ChromeMessageBroadcaster* nonLeafMM = strongNonLeafMM;

    MessageListenerManager* tabMM = childMM;

    strongNonLeafMM = nullptr;
    childMM = nullptr;

    if (nonLeafMM) {
      MarkChildMessageManagers(nonLeafMM);
      continue;
    }

    tabMM->MarkForCC();

    //XXX hack warning, but works, since we know that
    //    callback is frameloader.
    mozilla::dom::ipc::MessageManagerCallback* cb = tabMM->GetCallback();
    if (cb) {
      nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
      EventTarget* et = fl->GetTabChildGlobalAsEventTarget();
      if (!et) {
        continue;
      }
      static_cast<nsInProcessTabChildGlobal*>(et)->MarkForCC();
      EventListenerManager* elm = et->GetExistingListenerManager();
      if (elm) {
        elm->MarkForCC();
      }
    }
  }
}
static void
MarkMessageManagers()
{
  if (nsFrameMessageManager::GetChildProcessManager()) {
    // ContentProcessMessageManager's MarkForCC also marks ChildProcessManager.
    ContentProcessMessageManager* pg = ContentProcessMessageManager::Get();
    if (pg) {
      pg->MarkForCC();
    }
  }

  // The global message manager only exists in the root process.
  if (!XRE_IsParentProcess()) {
    return;
  }
  RefPtr<ChromeMessageBroadcaster> strongGlobalMM =
    nsFrameMessageManager::GetGlobalMessageManager();
  if (!strongGlobalMM) {
    return;
  }
  ChromeMessageBroadcaster* globalMM = strongGlobalMM;
  strongGlobalMM = nullptr;
  MarkChildMessageManagers(globalMM);

  if (nsFrameMessageManager::sParentProcessManager) {
    nsFrameMessageManager::sParentProcessManager->MarkForCC();
    uint32_t childCount = nsFrameMessageManager::sParentProcessManager->ChildCount();
    for (uint32_t i = 0; i < childCount; ++i) {
      RefPtr<MessageListenerManager> childMM =
        nsFrameMessageManager::sParentProcessManager->GetChildAt(i);
      if (!childMM) {
        continue;
      }
      MessageListenerManager* child = childMM;
      childMM = nullptr;
      child->MarkForCC();
    }
  }
  if (nsFrameMessageManager::sSameProcessParentManager) {
    nsFrameMessageManager::sSameProcessParentManager->MarkForCC();
  }
}