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