1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpfe/appshell/src/nsAppShellWindowEnumerator.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,495 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsAppShellWindowEnumerator.h" 1.10 + 1.11 +#include "nsIContentViewer.h" 1.12 +#include "nsIDocShell.h" 1.13 +#include "nsIDocument.h" 1.14 +#include "nsIDOMDocument.h" 1.15 +#include "nsIDOMElement.h" 1.16 +#include "nsIDOMWindow.h" 1.17 +#include "nsIFactory.h" 1.18 +#include "nsIInterfaceRequestor.h" 1.19 +#include "nsIInterfaceRequestorUtils.h" 1.20 +#include "nsIXULWindow.h" 1.21 + 1.22 +#include "nsWindowMediator.h" 1.23 + 1.24 +// 1.25 +// static helper functions 1.26 +// 1.27 + 1.28 +static nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell); 1.29 +static void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute, 1.30 + nsAString &outValue); 1.31 +static void GetWindowType(nsIXULWindow* inWindow, nsString &outType); 1.32 + 1.33 +nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell) 1.34 +{ 1.35 + nsCOMPtr<nsIDOMNode> node; 1.36 + 1.37 + nsCOMPtr<nsIContentViewer> cv; 1.38 + aShell->GetContentViewer(getter_AddRefs(cv)); 1.39 + if (cv) { 1.40 + nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(cv->GetDocument())); 1.41 + if (domdoc) { 1.42 + nsCOMPtr<nsIDOMElement> element; 1.43 + domdoc->GetDocumentElement(getter_AddRefs(element)); 1.44 + if (element) 1.45 + node = element; 1.46 + } 1.47 + } 1.48 + 1.49 + return node; 1.50 +} 1.51 + 1.52 +// generic "retrieve the value of a XUL attribute" function 1.53 +void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute, 1.54 + nsAString &outValue) 1.55 +{ 1.56 + nsCOMPtr<nsIDocShell> shell; 1.57 + if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) { 1.58 + nsCOMPtr<nsIDOMNode> node(GetDOMNodeFromDocShell(shell)); 1.59 + if (node) { 1.60 + nsCOMPtr<nsIDOMElement> webshellElement(do_QueryInterface(node)); 1.61 + if (webshellElement) 1.62 + webshellElement->GetAttribute(inAttribute, outValue); 1.63 + } 1.64 + } 1.65 +} 1.66 + 1.67 +// retrieve the window type, stored as the value of a particular 1.68 +// attribute in its XUL window tag 1.69 +void GetWindowType(nsIXULWindow* aWindow, nsString &outType) 1.70 +{ 1.71 + GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType); 1.72 +} 1.73 + 1.74 +// 1.75 +// nsWindowInfo 1.76 +// 1.77 + 1.78 +nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp) : 1.79 + mWindow(inWindow),mTimeStamp(inTimeStamp),mZLevel(nsIXULWindow::normalZ) 1.80 +{ 1.81 + ReferenceSelf(true, true); 1.82 +} 1.83 + 1.84 +nsWindowInfo::~nsWindowInfo() 1.85 +{ 1.86 +} 1.87 + 1.88 +// return true if the window described by this WindowInfo has a type 1.89 +// equal to the given type 1.90 +bool nsWindowInfo::TypeEquals(const nsAString &aType) 1.91 +{ 1.92 + nsAutoString rtnString; 1.93 + GetWindowType(mWindow, rtnString); 1.94 + return rtnString == aType; 1.95 +} 1.96 + 1.97 +// insert the struct into their two linked lists, in position after the 1.98 +// given (independent) method arguments 1.99 +void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher) 1.100 +{ 1.101 + if (inOlder) { 1.102 + mOlder = inOlder; 1.103 + mYounger = inOlder->mYounger; 1.104 + mOlder->mYounger = this; 1.105 + if (mOlder->mOlder == mOlder) 1.106 + mOlder->mOlder = this; 1.107 + mYounger->mOlder = this; 1.108 + if (mYounger->mYounger == mYounger) 1.109 + mYounger->mYounger = this; 1.110 + } 1.111 + if (inHigher) { 1.112 + mHigher = inHigher; 1.113 + mLower = inHigher->mLower; 1.114 + mHigher->mLower = this; 1.115 + if (mHigher->mHigher == mHigher) 1.116 + mHigher->mHigher = this; 1.117 + mLower->mHigher = this; 1.118 + if (mLower->mLower == mLower) 1.119 + mLower->mLower = this; 1.120 + } 1.121 +} 1.122 + 1.123 +// remove the struct from its linked lists 1.124 +void nsWindowInfo::Unlink(bool inAge, bool inZ) 1.125 +{ 1.126 + if (inAge) { 1.127 + mOlder->mYounger = mYounger; 1.128 + mYounger->mOlder = mOlder; 1.129 + } 1.130 + if (inZ) { 1.131 + mLower->mHigher = mHigher; 1.132 + mHigher->mLower = mLower; 1.133 + } 1.134 + ReferenceSelf(inAge, inZ); 1.135 +} 1.136 + 1.137 +// initialize the struct to be a valid linked list of one element 1.138 +void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ) 1.139 +{ 1.140 + if (inAge) { 1.141 + mYounger = this; 1.142 + mOlder = this; 1.143 + } 1.144 + if (inZ) { 1.145 + mLower = this; 1.146 + mHigher = this; 1.147 + } 1.148 +} 1.149 + 1.150 +// 1.151 +// nsAppShellWindowEnumerator 1.152 +// 1.153 + 1.154 +NS_IMPL_ISUPPORTS(nsAppShellWindowEnumerator, nsISimpleEnumerator) 1.155 + 1.156 +nsAppShellWindowEnumerator::nsAppShellWindowEnumerator( 1.157 + const char16_t* aTypeString, 1.158 + nsWindowMediator& aMediator) : 1.159 + mWindowMediator(&aMediator), mType(aTypeString), mCurrentPosition(nullptr) 1.160 +{ 1.161 + mWindowMediator->AddEnumerator(this); 1.162 + NS_ADDREF(mWindowMediator); 1.163 +} 1.164 + 1.165 +nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator() 1.166 +{ 1.167 + mWindowMediator->RemoveEnumerator(this); 1.168 + NS_RELEASE(mWindowMediator); 1.169 +} 1.170 + 1.171 +// after mCurrentPosition has been initialized to point to the beginning 1.172 +// of the appropriate list, adjust it if necessary 1.173 +void nsAppShellWindowEnumerator::AdjustInitialPosition() 1.174 +{ 1.175 + if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType)) 1.176 + mCurrentPosition = FindNext(); 1.177 +} 1.178 + 1.179 +NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool *retval) 1.180 +{ 1.181 + if (!retval) 1.182 + return NS_ERROR_INVALID_ARG; 1.183 + 1.184 + *retval = mCurrentPosition ? true : false; 1.185 + return NS_OK; 1.186 +} 1.187 + 1.188 +// if a window is being removed adjust the iterator's current position 1.189 +void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo) 1.190 +{ 1.191 + if (mCurrentPosition == inInfo) 1.192 + mCurrentPosition = FindNext(); 1.193 +} 1.194 + 1.195 +// 1.196 +// nsASDOMWindowEnumerator 1.197 +// 1.198 + 1.199 +nsASDOMWindowEnumerator::nsASDOMWindowEnumerator( 1.200 + const char16_t* aTypeString, 1.201 + nsWindowMediator& aMediator) : 1.202 + nsAppShellWindowEnumerator(aTypeString, aMediator) 1.203 +{ 1.204 +} 1.205 + 1.206 +nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator() 1.207 +{ 1.208 +} 1.209 + 1.210 +NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval) 1.211 +{ 1.212 + if (!retval) 1.213 + return NS_ERROR_INVALID_ARG; 1.214 + 1.215 + *retval = nullptr; 1.216 + while (mCurrentPosition) { 1.217 + nsCOMPtr<nsIDOMWindow> domWindow; 1.218 + nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow); 1.219 + mCurrentPosition = FindNext(); 1.220 + if (domWindow) 1.221 + return CallQueryInterface(domWindow, retval); 1.222 + } 1.223 + return NS_OK; 1.224 +} 1.225 + 1.226 +// 1.227 +// nsASXULWindowEnumerator 1.228 +// 1.229 + 1.230 +nsASXULWindowEnumerator::nsASXULWindowEnumerator( 1.231 + const char16_t* aTypeString, 1.232 + nsWindowMediator& aMediator) : 1.233 + nsAppShellWindowEnumerator(aTypeString, aMediator) 1.234 +{ 1.235 +} 1.236 + 1.237 +nsASXULWindowEnumerator::~nsASXULWindowEnumerator() 1.238 +{ 1.239 +} 1.240 + 1.241 +NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval) 1.242 +{ 1.243 + if (!retval) 1.244 + return NS_ERROR_INVALID_ARG; 1.245 + 1.246 + *retval = nullptr; 1.247 + if (mCurrentPosition) { 1.248 + CallQueryInterface(mCurrentPosition->mWindow, retval); 1.249 + mCurrentPosition = FindNext(); 1.250 + } 1.251 + return NS_OK; 1.252 +} 1.253 + 1.254 +// 1.255 +// nsASDOMWindowEarlyToLateEnumerator 1.256 +// 1.257 + 1.258 +nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator( 1.259 + const char16_t *aTypeString, 1.260 + nsWindowMediator &aMediator) : 1.261 + nsASDOMWindowEnumerator(aTypeString, aMediator) 1.262 +{ 1.263 + mCurrentPosition = aMediator.mOldestWindow; 1.264 + AdjustInitialPosition(); 1.265 +} 1.266 + 1.267 +nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator() 1.268 +{ 1.269 +} 1.270 + 1.271 +nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext() 1.272 +{ 1.273 + nsWindowInfo *info, 1.274 + *listEnd; 1.275 + bool allWindows = mType.IsEmpty(); 1.276 + 1.277 + // see nsXULWindowEarlyToLateEnumerator::FindNext 1.278 + if (!mCurrentPosition) 1.279 + return nullptr; 1.280 + 1.281 + info = mCurrentPosition->mYounger; 1.282 + listEnd = mWindowMediator->mOldestWindow; 1.283 + 1.284 + while (info != listEnd) { 1.285 + if (allWindows || info->TypeEquals(mType)) 1.286 + return info; 1.287 + info = info->mYounger; 1.288 + } 1.289 + 1.290 + return nullptr; 1.291 +} 1.292 + 1.293 +// 1.294 +// nsASXULWindowEarlyToLateEnumerator 1.295 +// 1.296 + 1.297 +nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator( 1.298 + const char16_t *aTypeString, 1.299 + nsWindowMediator &aMediator) : 1.300 + nsASXULWindowEnumerator(aTypeString, aMediator) 1.301 +{ 1.302 + mCurrentPosition = aMediator.mOldestWindow; 1.303 + AdjustInitialPosition(); 1.304 +} 1.305 + 1.306 +nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator() 1.307 +{ 1.308 +} 1.309 + 1.310 +nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext() 1.311 +{ 1.312 + nsWindowInfo *info, 1.313 + *listEnd; 1.314 + bool allWindows = mType.IsEmpty(); 1.315 + 1.316 + /* mCurrentPosition null is assumed to mean that the enumerator has run 1.317 + its course and is now basically useless. It could also be interpreted 1.318 + to mean that it was created at a time when there were no windows. In 1.319 + that case it would probably be more appropriate to check to see whether 1.320 + windows have subsequently been added. But it's not guaranteed that we'll 1.321 + pick up newly added windows anyway (if they occurred previous to our 1.322 + current position) so we just don't worry about that. */ 1.323 + if (!mCurrentPosition) 1.324 + return nullptr; 1.325 + 1.326 + info = mCurrentPosition->mYounger; 1.327 + listEnd = mWindowMediator->mOldestWindow; 1.328 + 1.329 + while (info != listEnd) { 1.330 + if (allWindows || info->TypeEquals(mType)) 1.331 + return info; 1.332 + info = info->mYounger; 1.333 + } 1.334 + 1.335 + return nullptr; 1.336 +} 1.337 + 1.338 +// 1.339 +// nsASDOMWindowFrontToBackEnumerator 1.340 +// 1.341 + 1.342 +nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator( 1.343 + const char16_t *aTypeString, 1.344 + nsWindowMediator &aMediator) : 1.345 + nsASDOMWindowEnumerator(aTypeString, aMediator) 1.346 +{ 1.347 + mCurrentPosition = aMediator.mTopmostWindow; 1.348 + AdjustInitialPosition(); 1.349 +} 1.350 + 1.351 +nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator() 1.352 +{ 1.353 +} 1.354 + 1.355 +nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext() 1.356 +{ 1.357 + nsWindowInfo *info, 1.358 + *listEnd; 1.359 + bool allWindows = mType.IsEmpty(); 1.360 + 1.361 + // see nsXULWindowEarlyToLateEnumerator::FindNext 1.362 + if (!mCurrentPosition) 1.363 + return nullptr; 1.364 + 1.365 + info = mCurrentPosition->mLower; 1.366 + listEnd = mWindowMediator->mTopmostWindow; 1.367 + 1.368 + while (info != listEnd) { 1.369 + if (allWindows || info->TypeEquals(mType)) 1.370 + return info; 1.371 + info = info->mLower; 1.372 + } 1.373 + 1.374 + return nullptr; 1.375 +} 1.376 + 1.377 +// 1.378 +// nsASXULWindowFrontToBackEnumerator 1.379 +// 1.380 + 1.381 +nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator( 1.382 + const char16_t *aTypeString, 1.383 + nsWindowMediator &aMediator) : 1.384 + nsASXULWindowEnumerator(aTypeString, aMediator) 1.385 +{ 1.386 + mCurrentPosition = aMediator.mTopmostWindow; 1.387 + AdjustInitialPosition(); 1.388 +} 1.389 + 1.390 +nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator() 1.391 +{ 1.392 +} 1.393 + 1.394 +nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext() 1.395 +{ 1.396 + nsWindowInfo *info, 1.397 + *listEnd; 1.398 + bool allWindows = mType.IsEmpty(); 1.399 + 1.400 + // see nsXULWindowEarlyToLateEnumerator::FindNext 1.401 + if (!mCurrentPosition) 1.402 + return nullptr; 1.403 + 1.404 + info = mCurrentPosition->mLower; 1.405 + listEnd = mWindowMediator->mTopmostWindow; 1.406 + 1.407 + while (info != listEnd) { 1.408 + if (allWindows || info->TypeEquals(mType)) 1.409 + return info; 1.410 + info = info->mLower; 1.411 + } 1.412 + 1.413 + return nullptr; 1.414 +} 1.415 + 1.416 +// 1.417 +// nsASDOMWindowBackToFrontEnumerator 1.418 +// 1.419 + 1.420 +nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator( 1.421 + const char16_t *aTypeString, 1.422 + nsWindowMediator &aMediator) : 1.423 + nsASDOMWindowEnumerator(aTypeString, aMediator) 1.424 +{ 1.425 + mCurrentPosition = aMediator.mTopmostWindow ? 1.426 + aMediator.mTopmostWindow->mHigher : nullptr; 1.427 + AdjustInitialPosition(); 1.428 +} 1.429 + 1.430 +nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator() 1.431 +{ 1.432 +} 1.433 + 1.434 +nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext() 1.435 +{ 1.436 + nsWindowInfo *info, 1.437 + *listEnd; 1.438 + bool allWindows = mType.IsEmpty(); 1.439 + 1.440 + // see nsXULWindowEarlyToLateEnumerator::FindNext 1.441 + if (!mCurrentPosition) 1.442 + return nullptr; 1.443 + 1.444 + info = mCurrentPosition->mHigher; 1.445 + listEnd = mWindowMediator->mTopmostWindow; 1.446 + if (listEnd) 1.447 + listEnd = listEnd->mHigher; 1.448 + 1.449 + while (info != listEnd) { 1.450 + if (allWindows || info->TypeEquals(mType)) 1.451 + return info; 1.452 + info = info->mHigher; 1.453 + } 1.454 + 1.455 + return nullptr; 1.456 +} 1.457 + 1.458 +// 1.459 +// nsASXULWindowBackToFrontEnumerator 1.460 +// 1.461 + 1.462 +nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator( 1.463 + const char16_t *aTypeString, 1.464 + nsWindowMediator &aMediator) : 1.465 + nsASXULWindowEnumerator(aTypeString, aMediator) 1.466 +{ 1.467 + mCurrentPosition = aMediator.mTopmostWindow ? 1.468 + aMediator.mTopmostWindow->mHigher : nullptr; 1.469 + AdjustInitialPosition(); 1.470 +} 1.471 + 1.472 +nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator() 1.473 +{ 1.474 +} 1.475 + 1.476 +nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext() 1.477 +{ 1.478 + nsWindowInfo *info, 1.479 + *listEnd; 1.480 + bool allWindows = mType.IsEmpty(); 1.481 + 1.482 + // see nsXULWindowEarlyToLateEnumerator::FindNext 1.483 + if (!mCurrentPosition) 1.484 + return nullptr; 1.485 + 1.486 + info = mCurrentPosition->mHigher; 1.487 + listEnd = mWindowMediator->mTopmostWindow; 1.488 + if (listEnd) 1.489 + listEnd = listEnd->mHigher; 1.490 + 1.491 + while (info != listEnd) { 1.492 + if (allWindows || info->TypeEquals(mType)) 1.493 + return info; 1.494 + info = info->mHigher; 1.495 + } 1.496 + 1.497 + return nullptr; 1.498 +}