nsAppShellWindowEnumerator.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsAppShellWindowEnumerator.h"
  6. #include "nsIContentViewer.h"
  7. #include "nsIDocShell.h"
  8. #include "nsIDocument.h"
  9. #include "nsIDOMDocument.h"
  10. #include "nsIDOMElement.h"
  11. #include "nsIDOMWindow.h"
  12. #include "nsIFactory.h"
  13. #include "nsIInterfaceRequestor.h"
  14. #include "nsIInterfaceRequestorUtils.h"
  15. #include "nsIXULWindow.h"
  16. #include "nsWindowMediator.h"
  17. //
  18. // static helper functions
  19. //
  20. static nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell);
  21. static void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
  22. nsAString &outValue);
  23. static void GetWindowType(nsIXULWindow* inWindow, nsString &outType);
  24. nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell)
  25. {
  26. nsCOMPtr<nsIDOMNode> node;
  27. nsCOMPtr<nsIContentViewer> cv;
  28. aShell->GetContentViewer(getter_AddRefs(cv));
  29. if (cv) {
  30. nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(cv->GetDocument()));
  31. if (domdoc) {
  32. nsCOMPtr<nsIDOMElement> element;
  33. domdoc->GetDocumentElement(getter_AddRefs(element));
  34. if (element)
  35. node = element;
  36. }
  37. }
  38. return node;
  39. }
  40. // generic "retrieve the value of a XUL attribute" function
  41. void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
  42. nsAString &outValue)
  43. {
  44. nsCOMPtr<nsIDocShell> shell;
  45. if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) {
  46. nsCOMPtr<nsIDOMNode> node(GetDOMNodeFromDocShell(shell));
  47. if (node) {
  48. nsCOMPtr<nsIDOMElement> webshellElement(do_QueryInterface(node));
  49. if (webshellElement)
  50. webshellElement->GetAttribute(inAttribute, outValue);
  51. }
  52. }
  53. }
  54. // retrieve the window type, stored as the value of a particular
  55. // attribute in its XUL window tag
  56. void GetWindowType(nsIXULWindow* aWindow, nsString &outType)
  57. {
  58. GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType);
  59. }
  60. //
  61. // nsWindowInfo
  62. //
  63. nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp) :
  64. mWindow(inWindow),mTimeStamp(inTimeStamp),mZLevel(nsIXULWindow::normalZ)
  65. {
  66. ReferenceSelf(true, true);
  67. }
  68. nsWindowInfo::~nsWindowInfo()
  69. {
  70. }
  71. // return true if the window described by this WindowInfo has a type
  72. // equal to the given type
  73. bool nsWindowInfo::TypeEquals(const nsAString &aType)
  74. {
  75. nsAutoString rtnString;
  76. GetWindowType(mWindow, rtnString);
  77. return rtnString == aType;
  78. }
  79. // insert the struct into their two linked lists, in position after the
  80. // given (independent) method arguments
  81. void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher)
  82. {
  83. if (inOlder) {
  84. mOlder = inOlder;
  85. mYounger = inOlder->mYounger;
  86. mOlder->mYounger = this;
  87. if (mOlder->mOlder == mOlder)
  88. mOlder->mOlder = this;
  89. mYounger->mOlder = this;
  90. if (mYounger->mYounger == mYounger)
  91. mYounger->mYounger = this;
  92. }
  93. if (inHigher) {
  94. mHigher = inHigher;
  95. mLower = inHigher->mLower;
  96. mHigher->mLower = this;
  97. if (mHigher->mHigher == mHigher)
  98. mHigher->mHigher = this;
  99. mLower->mHigher = this;
  100. if (mLower->mLower == mLower)
  101. mLower->mLower = this;
  102. }
  103. }
  104. // remove the struct from its linked lists
  105. void nsWindowInfo::Unlink(bool inAge, bool inZ)
  106. {
  107. if (inAge) {
  108. mOlder->mYounger = mYounger;
  109. mYounger->mOlder = mOlder;
  110. }
  111. if (inZ) {
  112. mLower->mHigher = mHigher;
  113. mHigher->mLower = mLower;
  114. }
  115. ReferenceSelf(inAge, inZ);
  116. }
  117. // initialize the struct to be a valid linked list of one element
  118. void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ)
  119. {
  120. if (inAge) {
  121. mYounger = this;
  122. mOlder = this;
  123. }
  124. if (inZ) {
  125. mLower = this;
  126. mHigher = this;
  127. }
  128. }
  129. //
  130. // nsAppShellWindowEnumerator
  131. //
  132. NS_IMPL_ISUPPORTS(nsAppShellWindowEnumerator, nsISimpleEnumerator)
  133. nsAppShellWindowEnumerator::nsAppShellWindowEnumerator(
  134. const char16_t* aTypeString,
  135. nsWindowMediator& aMediator) :
  136. mWindowMediator(&aMediator), mType(aTypeString), mCurrentPosition(nullptr)
  137. {
  138. mWindowMediator->AddEnumerator(this);
  139. NS_ADDREF(mWindowMediator);
  140. }
  141. nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator()
  142. {
  143. mWindowMediator->RemoveEnumerator(this);
  144. NS_RELEASE(mWindowMediator);
  145. }
  146. // after mCurrentPosition has been initialized to point to the beginning
  147. // of the appropriate list, adjust it if necessary
  148. void nsAppShellWindowEnumerator::AdjustInitialPosition()
  149. {
  150. if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType))
  151. mCurrentPosition = FindNext();
  152. }
  153. NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool *retval)
  154. {
  155. if (!retval)
  156. return NS_ERROR_INVALID_ARG;
  157. *retval = mCurrentPosition ? true : false;
  158. return NS_OK;
  159. }
  160. // if a window is being removed adjust the iterator's current position
  161. void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo)
  162. {
  163. if (mCurrentPosition == inInfo)
  164. mCurrentPosition = FindNext();
  165. }
  166. //
  167. // nsASDOMWindowEnumerator
  168. //
  169. nsASDOMWindowEnumerator::nsASDOMWindowEnumerator(
  170. const char16_t* aTypeString,
  171. nsWindowMediator& aMediator) :
  172. nsAppShellWindowEnumerator(aTypeString, aMediator)
  173. {
  174. }
  175. nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator()
  176. {
  177. }
  178. NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval)
  179. {
  180. if (!retval)
  181. return NS_ERROR_INVALID_ARG;
  182. *retval = nullptr;
  183. while (mCurrentPosition) {
  184. nsCOMPtr<nsPIDOMWindowOuter> domWindow;
  185. nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow);
  186. mCurrentPosition = FindNext();
  187. if (domWindow)
  188. return CallQueryInterface(domWindow, retval);
  189. }
  190. return NS_OK;
  191. }
  192. //
  193. // nsASXULWindowEnumerator
  194. //
  195. nsASXULWindowEnumerator::nsASXULWindowEnumerator(
  196. const char16_t* aTypeString,
  197. nsWindowMediator& aMediator) :
  198. nsAppShellWindowEnumerator(aTypeString, aMediator)
  199. {
  200. }
  201. nsASXULWindowEnumerator::~nsASXULWindowEnumerator()
  202. {
  203. }
  204. NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval)
  205. {
  206. if (!retval)
  207. return NS_ERROR_INVALID_ARG;
  208. *retval = nullptr;
  209. if (mCurrentPosition) {
  210. CallQueryInterface(mCurrentPosition->mWindow, retval);
  211. mCurrentPosition = FindNext();
  212. }
  213. return NS_OK;
  214. }
  215. //
  216. // nsASDOMWindowEarlyToLateEnumerator
  217. //
  218. nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator(
  219. const char16_t *aTypeString,
  220. nsWindowMediator &aMediator) :
  221. nsASDOMWindowEnumerator(aTypeString, aMediator)
  222. {
  223. mCurrentPosition = aMediator.mOldestWindow;
  224. AdjustInitialPosition();
  225. }
  226. nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator()
  227. {
  228. }
  229. nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext()
  230. {
  231. nsWindowInfo *info,
  232. *listEnd;
  233. bool allWindows = mType.IsEmpty();
  234. // see nsXULWindowEarlyToLateEnumerator::FindNext
  235. if (!mCurrentPosition)
  236. return nullptr;
  237. info = mCurrentPosition->mYounger;
  238. listEnd = mWindowMediator->mOldestWindow;
  239. while (info != listEnd) {
  240. if (allWindows || info->TypeEquals(mType))
  241. return info;
  242. info = info->mYounger;
  243. }
  244. return nullptr;
  245. }
  246. //
  247. // nsASXULWindowEarlyToLateEnumerator
  248. //
  249. nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator(
  250. const char16_t *aTypeString,
  251. nsWindowMediator &aMediator) :
  252. nsASXULWindowEnumerator(aTypeString, aMediator)
  253. {
  254. mCurrentPosition = aMediator.mOldestWindow;
  255. AdjustInitialPosition();
  256. }
  257. nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator()
  258. {
  259. }
  260. nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext()
  261. {
  262. nsWindowInfo *info,
  263. *listEnd;
  264. bool allWindows = mType.IsEmpty();
  265. /* mCurrentPosition null is assumed to mean that the enumerator has run
  266. its course and is now basically useless. It could also be interpreted
  267. to mean that it was created at a time when there were no windows. In
  268. that case it would probably be more appropriate to check to see whether
  269. windows have subsequently been added. But it's not guaranteed that we'll
  270. pick up newly added windows anyway (if they occurred previous to our
  271. current position) so we just don't worry about that. */
  272. if (!mCurrentPosition)
  273. return nullptr;
  274. info = mCurrentPosition->mYounger;
  275. listEnd = mWindowMediator->mOldestWindow;
  276. while (info != listEnd) {
  277. if (allWindows || info->TypeEquals(mType))
  278. return info;
  279. info = info->mYounger;
  280. }
  281. return nullptr;
  282. }
  283. //
  284. // nsASDOMWindowFrontToBackEnumerator
  285. //
  286. nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator(
  287. const char16_t *aTypeString,
  288. nsWindowMediator &aMediator) :
  289. nsASDOMWindowEnumerator(aTypeString, aMediator)
  290. {
  291. mCurrentPosition = aMediator.mTopmostWindow;
  292. AdjustInitialPosition();
  293. }
  294. nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator()
  295. {
  296. }
  297. nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext()
  298. {
  299. nsWindowInfo *info,
  300. *listEnd;
  301. bool allWindows = mType.IsEmpty();
  302. // see nsXULWindowEarlyToLateEnumerator::FindNext
  303. if (!mCurrentPosition)
  304. return nullptr;
  305. info = mCurrentPosition->mLower;
  306. listEnd = mWindowMediator->mTopmostWindow;
  307. while (info != listEnd) {
  308. if (allWindows || info->TypeEquals(mType))
  309. return info;
  310. info = info->mLower;
  311. }
  312. return nullptr;
  313. }
  314. //
  315. // nsASXULWindowFrontToBackEnumerator
  316. //
  317. nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator(
  318. const char16_t *aTypeString,
  319. nsWindowMediator &aMediator) :
  320. nsASXULWindowEnumerator(aTypeString, aMediator)
  321. {
  322. mCurrentPosition = aMediator.mTopmostWindow;
  323. AdjustInitialPosition();
  324. }
  325. nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator()
  326. {
  327. }
  328. nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext()
  329. {
  330. nsWindowInfo *info,
  331. *listEnd;
  332. bool allWindows = mType.IsEmpty();
  333. // see nsXULWindowEarlyToLateEnumerator::FindNext
  334. if (!mCurrentPosition)
  335. return nullptr;
  336. info = mCurrentPosition->mLower;
  337. listEnd = mWindowMediator->mTopmostWindow;
  338. while (info != listEnd) {
  339. if (allWindows || info->TypeEquals(mType))
  340. return info;
  341. info = info->mLower;
  342. }
  343. return nullptr;
  344. }
  345. //
  346. // nsASDOMWindowBackToFrontEnumerator
  347. //
  348. nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator(
  349. const char16_t *aTypeString,
  350. nsWindowMediator &aMediator) :
  351. nsASDOMWindowEnumerator(aTypeString, aMediator)
  352. {
  353. mCurrentPosition = aMediator.mTopmostWindow ?
  354. aMediator.mTopmostWindow->mHigher : nullptr;
  355. AdjustInitialPosition();
  356. }
  357. nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator()
  358. {
  359. }
  360. nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext()
  361. {
  362. nsWindowInfo *info,
  363. *listEnd;
  364. bool allWindows = mType.IsEmpty();
  365. // see nsXULWindowEarlyToLateEnumerator::FindNext
  366. if (!mCurrentPosition)
  367. return nullptr;
  368. info = mCurrentPosition->mHigher;
  369. listEnd = mWindowMediator->mTopmostWindow;
  370. if (listEnd)
  371. listEnd = listEnd->mHigher;
  372. while (info != listEnd) {
  373. if (allWindows || info->TypeEquals(mType))
  374. return info;
  375. info = info->mHigher;
  376. }
  377. return nullptr;
  378. }
  379. //
  380. // nsASXULWindowBackToFrontEnumerator
  381. //
  382. nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator(
  383. const char16_t *aTypeString,
  384. nsWindowMediator &aMediator) :
  385. nsASXULWindowEnumerator(aTypeString, aMediator)
  386. {
  387. mCurrentPosition = aMediator.mTopmostWindow ?
  388. aMediator.mTopmostWindow->mHigher : nullptr;
  389. AdjustInitialPosition();
  390. }
  391. nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator()
  392. {
  393. }
  394. nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext()
  395. {
  396. nsWindowInfo *info,
  397. *listEnd;
  398. bool allWindows = mType.IsEmpty();
  399. // see nsXULWindowEarlyToLateEnumerator::FindNext
  400. if (!mCurrentPosition)
  401. return nullptr;
  402. info = mCurrentPosition->mHigher;
  403. listEnd = mWindowMediator->mTopmostWindow;
  404. if (listEnd)
  405. listEnd = listEnd->mHigher;
  406. while (info != listEnd) {
  407. if (allWindows || info->TypeEquals(mType))
  408. return info;
  409. info = info->mHigher;
  410. }
  411. return nullptr;
  412. }