bool
WindowNamedPropertiesHandler::getOwnPropertyNames(JSContext* aCx,
                                                  JS::Handle<JSObject*> aProxy,
                                                  JS::AutoIdVector& aProps)
{
  // Grab the DOM window.
  JSObject* global = JS_GetGlobalForObject(aCx, aProxy);
  XPCWrappedNative* wrapper = XPCWrappedNative::Get(global);
  nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrappedNative(wrapper);
  MOZ_ASSERT(piWin);
  nsGlobalWindow* win = static_cast<nsGlobalWindow*>(piWin.get());
  nsTArray<nsString> names;
  win->GetSupportedNames(names);
  if (!AppendNamedPropertyIds(aCx, aProxy, names, false, aProps)) {
    return false;
  }

  names.Clear();
  nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc());
  if (!htmlDoc) {
    return true;
  }
  nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get());
  document->GetSupportedNames(names);

  JS::AutoIdVector docProps(aCx);
  if (!AppendNamedPropertyIds(aCx, aProxy, names, false, docProps)) {
    return false;
  }

  return js::AppendUnique(aCx, aProps, docProps);
}
bool
WindowNamedPropertiesHandler::ownPropNames(JSContext* aCx,
                                           JS::Handle<JSObject*> aProxy,
                                           unsigned flags,
                                           JS::AutoIdVector& aProps) const
{
  if (!(flags & JSITER_HIDDEN)) {
    // None of our named properties are enumerable.
    return true;
  }

  // Grab the DOM window.
  nsGlobalWindow* win = xpc::WindowOrNull(JS_GetGlobalForObject(aCx, aProxy));
  nsTArray<nsString> names;
  win->GetSupportedNames(names);
  // Filter out the ones we wouldn't expose from getOwnPropertyDescriptor.
  // We iterate backwards so we can remove things from the list easily.
  for (size_t i = names.Length(); i > 0; ) {
    --i; // Now we're pointing at the next name we want to look at
    nsIDOMWindow* childWin = win->GetChildWindow(names[i]);
    if (!childWin || !ShouldExposeChildWindow(names[i], childWin)) {
      names.RemoveElementAt(i);
    }
  }
  if (!AppendNamedPropertyIds(aCx, aProxy, names, false, aProps)) {
    return false;
  }

  names.Clear();
  nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc());
  if (!htmlDoc) {
    return true;
  }
  nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get());
  document->GetSupportedNames(flags, names);

  JS::AutoIdVector docProps(aCx);
  if (!AppendNamedPropertyIds(aCx, aProxy, names, false, docProps)) {
    return false;
  }

  return js::AppendUnique(aCx, aProps, docProps);
}
bool
WindowNamedPropertiesHandler::ownPropNames(JSContext* aCx,
                                           JS::Handle<JSObject*> aProxy,
                                           unsigned flags,
                                           JS::AutoIdVector& aProps) const
{
  if (!(flags & JSITER_HIDDEN)) {
    // None of our named properties are enumerable.
    return true;
  }

  // Grab the DOM window.
  nsGlobalWindow* win = xpc::WindowOrNull(JS_GetGlobalForObject(aCx, aProxy));
  nsTArray<nsString> names;
  // The names live on the outer window, which might be null
  nsGlobalWindow* outer = win->GetOuterWindowInternal();
  if (outer) {
    nsDOMWindowList* childWindows = outer->GetWindowList();
    if (childWindows) {
      uint32_t length = childWindows->GetLength();
      for (uint32_t i = 0; i < length; ++i) {
        nsCOMPtr<nsIDocShellTreeItem> item =
          childWindows->GetDocShellTreeItemAt(i);
        // This is a bit silly, since we could presumably just do
        // item->GetWindow().  But it's not obvious whether this does the same
        // thing as GetChildWindow() with the item's name (due to the complexity
        // of FindChildWithName).  Since GetChildWindow is what we use in
        // getOwnPropDescriptor, let's try to be consistent.
        nsString name;
        item->GetName(name);
        if (!names.Contains(name)) {
          // Make sure we really would expose it from getOwnPropDescriptor.
          nsCOMPtr<nsPIDOMWindowOuter> childWin = win->GetChildWindow(name);
          if (childWin && ShouldExposeChildWindow(name, childWin)) {
            names.AppendElement(name);
          }
        }
      }
    }
  }
  if (!AppendNamedPropertyIds(aCx, aProxy, names, false, aProps)) {
    return false;
  }

  names.Clear();
  nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc());
  if (!htmlDoc) {
    return true;
  }
  nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get());
  // Document names are enumerable, so we want to get them no matter what flags
  // is.
  document->GetSupportedNames(names);

  JS::AutoIdVector docProps(aCx);
  if (!AppendNamedPropertyIds(aCx, aProxy, names, false, docProps)) {
    return false;
  }

  return js::AppendUnique(aCx, aProps, docProps);
}