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