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::getOwnPropDescriptor(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId, bool /* unused */, JS::MutableHandle<JSPropertyDescriptor> aDesc) const { if (!JSID_IS_STRING(aId)) { // Nothing to do if we're resolving a non-string property. return true; } JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy)); if (HasPropertyOnPrototype(aCx, aProxy, aId)) { return true; } nsAutoJSString str; if (!str.init(aCx, JSID_TO_STRING(aId))) { return false; } // Grab the DOM window. nsGlobalWindow* win = GetWindowFromGlobal(global); if (win->Length() > 0) { nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str); if (childWin && ShouldExposeChildWindow(str, childWin)) { // We found a subframe of the right name. Shadowing via |var foo| in // global scope is still allowed, since |var| only looks up |own| // properties. But unqualified shadowing will fail, per-spec. JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, childWin, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; } } // The rest of this function is for HTML documents only. nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc()); if (!htmlDoc) { return true; } nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get()); Element* element = document->GetElementById(str); if (element) { JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, element, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; } nsWrapperCache* cache; nsISupports* result = document->ResolveName(str, &cache); if (!result) { return true; } JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, result, cache, nullptr, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; }
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); }