summaryrefslogtreecommitdiffstats
path: root/xpfe/appshell/nsAppShellWindowEnumerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xpfe/appshell/nsAppShellWindowEnumerator.cpp')
-rw-r--r--xpfe/appshell/nsAppShellWindowEnumerator.cpp495
1 files changed, 495 insertions, 0 deletions
diff --git a/xpfe/appshell/nsAppShellWindowEnumerator.cpp b/xpfe/appshell/nsAppShellWindowEnumerator.cpp
new file mode 100644
index 000000000..dc5fc120a
--- /dev/null
+++ b/xpfe/appshell/nsAppShellWindowEnumerator.cpp
@@ -0,0 +1,495 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsAppShellWindowEnumerator.h"
+
+#include "nsIContentViewer.h"
+#include "nsIDocShell.h"
+#include "nsIDocument.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMWindow.h"
+#include "nsIFactory.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIXULWindow.h"
+
+#include "nsWindowMediator.h"
+
+//
+// static helper functions
+//
+
+static nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell);
+static void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
+ nsAString &outValue);
+static void GetWindowType(nsIXULWindow* inWindow, nsString &outType);
+
+nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell)
+{
+ nsCOMPtr<nsIDOMNode> node;
+
+ nsCOMPtr<nsIContentViewer> cv;
+ aShell->GetContentViewer(getter_AddRefs(cv));
+ if (cv) {
+ nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(cv->GetDocument()));
+ if (domdoc) {
+ nsCOMPtr<nsIDOMElement> element;
+ domdoc->GetDocumentElement(getter_AddRefs(element));
+ if (element)
+ node = element;
+ }
+ }
+
+ return node;
+}
+
+// generic "retrieve the value of a XUL attribute" function
+void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
+ nsAString &outValue)
+{
+ nsCOMPtr<nsIDocShell> shell;
+ if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) {
+ nsCOMPtr<nsIDOMNode> node(GetDOMNodeFromDocShell(shell));
+ if (node) {
+ nsCOMPtr<nsIDOMElement> webshellElement(do_QueryInterface(node));
+ if (webshellElement)
+ webshellElement->GetAttribute(inAttribute, outValue);
+ }
+ }
+}
+
+// retrieve the window type, stored as the value of a particular
+// attribute in its XUL window tag
+void GetWindowType(nsIXULWindow* aWindow, nsString &outType)
+{
+ GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType);
+}
+
+//
+// nsWindowInfo
+//
+
+nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp) :
+ mWindow(inWindow),mTimeStamp(inTimeStamp),mZLevel(nsIXULWindow::normalZ)
+{
+ ReferenceSelf(true, true);
+}
+
+nsWindowInfo::~nsWindowInfo()
+{
+}
+
+// return true if the window described by this WindowInfo has a type
+// equal to the given type
+bool nsWindowInfo::TypeEquals(const nsAString &aType)
+{
+ nsAutoString rtnString;
+ GetWindowType(mWindow, rtnString);
+ return rtnString == aType;
+}
+
+// insert the struct into their two linked lists, in position after the
+// given (independent) method arguments
+void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher)
+{
+ if (inOlder) {
+ mOlder = inOlder;
+ mYounger = inOlder->mYounger;
+ mOlder->mYounger = this;
+ if (mOlder->mOlder == mOlder)
+ mOlder->mOlder = this;
+ mYounger->mOlder = this;
+ if (mYounger->mYounger == mYounger)
+ mYounger->mYounger = this;
+ }
+ if (inHigher) {
+ mHigher = inHigher;
+ mLower = inHigher->mLower;
+ mHigher->mLower = this;
+ if (mHigher->mHigher == mHigher)
+ mHigher->mHigher = this;
+ mLower->mHigher = this;
+ if (mLower->mLower == mLower)
+ mLower->mLower = this;
+ }
+}
+
+// remove the struct from its linked lists
+void nsWindowInfo::Unlink(bool inAge, bool inZ)
+{
+ if (inAge) {
+ mOlder->mYounger = mYounger;
+ mYounger->mOlder = mOlder;
+ }
+ if (inZ) {
+ mLower->mHigher = mHigher;
+ mHigher->mLower = mLower;
+ }
+ ReferenceSelf(inAge, inZ);
+}
+
+// initialize the struct to be a valid linked list of one element
+void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ)
+{
+ if (inAge) {
+ mYounger = this;
+ mOlder = this;
+ }
+ if (inZ) {
+ mLower = this;
+ mHigher = this;
+ }
+}
+
+//
+// nsAppShellWindowEnumerator
+//
+
+NS_IMPL_ISUPPORTS(nsAppShellWindowEnumerator, nsISimpleEnumerator)
+
+nsAppShellWindowEnumerator::nsAppShellWindowEnumerator(
+ const char16_t* aTypeString,
+ nsWindowMediator& aMediator) :
+ mWindowMediator(&aMediator), mType(aTypeString), mCurrentPosition(nullptr)
+{
+ mWindowMediator->AddEnumerator(this);
+ NS_ADDREF(mWindowMediator);
+}
+
+nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator()
+{
+ mWindowMediator->RemoveEnumerator(this);
+ NS_RELEASE(mWindowMediator);
+}
+
+// after mCurrentPosition has been initialized to point to the beginning
+// of the appropriate list, adjust it if necessary
+void nsAppShellWindowEnumerator::AdjustInitialPosition()
+{
+ if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType))
+ mCurrentPosition = FindNext();
+}
+
+NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool *retval)
+{
+ if (!retval)
+ return NS_ERROR_INVALID_ARG;
+
+ *retval = mCurrentPosition ? true : false;
+ return NS_OK;
+}
+
+// if a window is being removed adjust the iterator's current position
+void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo)
+{
+ if (mCurrentPosition == inInfo)
+ mCurrentPosition = FindNext();
+}
+
+//
+// nsASDOMWindowEnumerator
+//
+
+nsASDOMWindowEnumerator::nsASDOMWindowEnumerator(
+ const char16_t* aTypeString,
+ nsWindowMediator& aMediator) :
+ nsAppShellWindowEnumerator(aTypeString, aMediator)
+{
+}
+
+nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator()
+{
+}
+
+NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval)
+{
+ if (!retval)
+ return NS_ERROR_INVALID_ARG;
+
+ *retval = nullptr;
+ while (mCurrentPosition) {
+ nsCOMPtr<nsPIDOMWindowOuter> domWindow;
+ nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow);
+ mCurrentPosition = FindNext();
+ if (domWindow)
+ return CallQueryInterface(domWindow, retval);
+ }
+ return NS_OK;
+}
+
+//
+// nsASXULWindowEnumerator
+//
+
+nsASXULWindowEnumerator::nsASXULWindowEnumerator(
+ const char16_t* aTypeString,
+ nsWindowMediator& aMediator) :
+ nsAppShellWindowEnumerator(aTypeString, aMediator)
+{
+}
+
+nsASXULWindowEnumerator::~nsASXULWindowEnumerator()
+{
+}
+
+NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval)
+{
+ if (!retval)
+ return NS_ERROR_INVALID_ARG;
+
+ *retval = nullptr;
+ if (mCurrentPosition) {
+ CallQueryInterface(mCurrentPosition->mWindow, retval);
+ mCurrentPosition = FindNext();
+ }
+ return NS_OK;
+}
+
+//
+// nsASDOMWindowEarlyToLateEnumerator
+//
+
+nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator(
+ const char16_t *aTypeString,
+ nsWindowMediator &aMediator) :
+ nsASDOMWindowEnumerator(aTypeString, aMediator)
+{
+ mCurrentPosition = aMediator.mOldestWindow;
+ AdjustInitialPosition();
+}
+
+nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator()
+{
+}
+
+nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext()
+{
+ nsWindowInfo *info,
+ *listEnd;
+ bool allWindows = mType.IsEmpty();
+
+ // see nsXULWindowEarlyToLateEnumerator::FindNext
+ if (!mCurrentPosition)
+ return nullptr;
+
+ info = mCurrentPosition->mYounger;
+ listEnd = mWindowMediator->mOldestWindow;
+
+ while (info != listEnd) {
+ if (allWindows || info->TypeEquals(mType))
+ return info;
+ info = info->mYounger;
+ }
+
+ return nullptr;
+}
+
+//
+// nsASXULWindowEarlyToLateEnumerator
+//
+
+nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator(
+ const char16_t *aTypeString,
+ nsWindowMediator &aMediator) :
+ nsASXULWindowEnumerator(aTypeString, aMediator)
+{
+ mCurrentPosition = aMediator.mOldestWindow;
+ AdjustInitialPosition();
+}
+
+nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator()
+{
+}
+
+nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext()
+{
+ nsWindowInfo *info,
+ *listEnd;
+ bool allWindows = mType.IsEmpty();
+
+ /* mCurrentPosition null is assumed to mean that the enumerator has run
+ its course and is now basically useless. It could also be interpreted
+ to mean that it was created at a time when there were no windows. In
+ that case it would probably be more appropriate to check to see whether
+ windows have subsequently been added. But it's not guaranteed that we'll
+ pick up newly added windows anyway (if they occurred previous to our
+ current position) so we just don't worry about that. */
+ if (!mCurrentPosition)
+ return nullptr;
+
+ info = mCurrentPosition->mYounger;
+ listEnd = mWindowMediator->mOldestWindow;
+
+ while (info != listEnd) {
+ if (allWindows || info->TypeEquals(mType))
+ return info;
+ info = info->mYounger;
+ }
+
+ return nullptr;
+}
+
+//
+// nsASDOMWindowFrontToBackEnumerator
+//
+
+nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator(
+ const char16_t *aTypeString,
+ nsWindowMediator &aMediator) :
+ nsASDOMWindowEnumerator(aTypeString, aMediator)
+{
+ mCurrentPosition = aMediator.mTopmostWindow;
+ AdjustInitialPosition();
+}
+
+nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator()
+{
+}
+
+nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext()
+{
+ nsWindowInfo *info,
+ *listEnd;
+ bool allWindows = mType.IsEmpty();
+
+ // see nsXULWindowEarlyToLateEnumerator::FindNext
+ if (!mCurrentPosition)
+ return nullptr;
+
+ info = mCurrentPosition->mLower;
+ listEnd = mWindowMediator->mTopmostWindow;
+
+ while (info != listEnd) {
+ if (allWindows || info->TypeEquals(mType))
+ return info;
+ info = info->mLower;
+ }
+
+ return nullptr;
+}
+
+//
+// nsASXULWindowFrontToBackEnumerator
+//
+
+nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator(
+ const char16_t *aTypeString,
+ nsWindowMediator &aMediator) :
+ nsASXULWindowEnumerator(aTypeString, aMediator)
+{
+ mCurrentPosition = aMediator.mTopmostWindow;
+ AdjustInitialPosition();
+}
+
+nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator()
+{
+}
+
+nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext()
+{
+ nsWindowInfo *info,
+ *listEnd;
+ bool allWindows = mType.IsEmpty();
+
+ // see nsXULWindowEarlyToLateEnumerator::FindNext
+ if (!mCurrentPosition)
+ return nullptr;
+
+ info = mCurrentPosition->mLower;
+ listEnd = mWindowMediator->mTopmostWindow;
+
+ while (info != listEnd) {
+ if (allWindows || info->TypeEquals(mType))
+ return info;
+ info = info->mLower;
+ }
+
+ return nullptr;
+}
+
+//
+// nsASDOMWindowBackToFrontEnumerator
+//
+
+nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator(
+ const char16_t *aTypeString,
+ nsWindowMediator &aMediator) :
+ nsASDOMWindowEnumerator(aTypeString, aMediator)
+{
+ mCurrentPosition = aMediator.mTopmostWindow ?
+ aMediator.mTopmostWindow->mHigher : nullptr;
+ AdjustInitialPosition();
+}
+
+nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator()
+{
+}
+
+nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext()
+{
+ nsWindowInfo *info,
+ *listEnd;
+ bool allWindows = mType.IsEmpty();
+
+ // see nsXULWindowEarlyToLateEnumerator::FindNext
+ if (!mCurrentPosition)
+ return nullptr;
+
+ info = mCurrentPosition->mHigher;
+ listEnd = mWindowMediator->mTopmostWindow;
+ if (listEnd)
+ listEnd = listEnd->mHigher;
+
+ while (info != listEnd) {
+ if (allWindows || info->TypeEquals(mType))
+ return info;
+ info = info->mHigher;
+ }
+
+ return nullptr;
+}
+
+//
+// nsASXULWindowBackToFrontEnumerator
+//
+
+nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator(
+ const char16_t *aTypeString,
+ nsWindowMediator &aMediator) :
+ nsASXULWindowEnumerator(aTypeString, aMediator)
+{
+ mCurrentPosition = aMediator.mTopmostWindow ?
+ aMediator.mTopmostWindow->mHigher : nullptr;
+ AdjustInitialPosition();
+}
+
+nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator()
+{
+}
+
+nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext()
+{
+ nsWindowInfo *info,
+ *listEnd;
+ bool allWindows = mType.IsEmpty();
+
+ // see nsXULWindowEarlyToLateEnumerator::FindNext
+ if (!mCurrentPosition)
+ return nullptr;
+
+ info = mCurrentPosition->mHigher;
+ listEnd = mWindowMediator->mTopmostWindow;
+ if (listEnd)
+ listEnd = listEnd->mHigher;
+
+ while (info != listEnd) {
+ if (allWindows || info->TypeEquals(mType))
+ return info;
+ info = info->mHigher;
+ }
+
+ return nullptr;
+}