Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
6 #include "nsAppShellWindowEnumerator.h"
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"
19 #include "nsWindowMediator.h"
21 //
22 // static helper functions
23 //
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);
30 nsCOMPtr<nsIDOMNode> GetDOMNodeFromDocShell(nsIDocShell *aShell)
31 {
32 nsCOMPtr<nsIDOMNode> node;
34 nsCOMPtr<nsIContentViewer> cv;
35 aShell->GetContentViewer(getter_AddRefs(cv));
36 if (cv) {
37 nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(cv->GetDocument()));
38 if (domdoc) {
39 nsCOMPtr<nsIDOMElement> element;
40 domdoc->GetDocumentElement(getter_AddRefs(element));
41 if (element)
42 node = element;
43 }
44 }
46 return node;
47 }
49 // generic "retrieve the value of a XUL attribute" function
50 void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute,
51 nsAString &outValue)
52 {
53 nsCOMPtr<nsIDocShell> shell;
54 if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) {
55 nsCOMPtr<nsIDOMNode> node(GetDOMNodeFromDocShell(shell));
56 if (node) {
57 nsCOMPtr<nsIDOMElement> webshellElement(do_QueryInterface(node));
58 if (webshellElement)
59 webshellElement->GetAttribute(inAttribute, outValue);
60 }
61 }
62 }
64 // retrieve the window type, stored as the value of a particular
65 // attribute in its XUL window tag
66 void GetWindowType(nsIXULWindow* aWindow, nsString &outType)
67 {
68 GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType);
69 }
71 //
72 // nsWindowInfo
73 //
75 nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp) :
76 mWindow(inWindow),mTimeStamp(inTimeStamp),mZLevel(nsIXULWindow::normalZ)
77 {
78 ReferenceSelf(true, true);
79 }
81 nsWindowInfo::~nsWindowInfo()
82 {
83 }
85 // return true if the window described by this WindowInfo has a type
86 // equal to the given type
87 bool nsWindowInfo::TypeEquals(const nsAString &aType)
88 {
89 nsAutoString rtnString;
90 GetWindowType(mWindow, rtnString);
91 return rtnString == aType;
92 }
94 // insert the struct into their two linked lists, in position after the
95 // given (independent) method arguments
96 void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher)
97 {
98 if (inOlder) {
99 mOlder = inOlder;
100 mYounger = inOlder->mYounger;
101 mOlder->mYounger = this;
102 if (mOlder->mOlder == mOlder)
103 mOlder->mOlder = this;
104 mYounger->mOlder = this;
105 if (mYounger->mYounger == mYounger)
106 mYounger->mYounger = this;
107 }
108 if (inHigher) {
109 mHigher = inHigher;
110 mLower = inHigher->mLower;
111 mHigher->mLower = this;
112 if (mHigher->mHigher == mHigher)
113 mHigher->mHigher = this;
114 mLower->mHigher = this;
115 if (mLower->mLower == mLower)
116 mLower->mLower = this;
117 }
118 }
120 // remove the struct from its linked lists
121 void nsWindowInfo::Unlink(bool inAge, bool inZ)
122 {
123 if (inAge) {
124 mOlder->mYounger = mYounger;
125 mYounger->mOlder = mOlder;
126 }
127 if (inZ) {
128 mLower->mHigher = mHigher;
129 mHigher->mLower = mLower;
130 }
131 ReferenceSelf(inAge, inZ);
132 }
134 // initialize the struct to be a valid linked list of one element
135 void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ)
136 {
137 if (inAge) {
138 mYounger = this;
139 mOlder = this;
140 }
141 if (inZ) {
142 mLower = this;
143 mHigher = this;
144 }
145 }
147 //
148 // nsAppShellWindowEnumerator
149 //
151 NS_IMPL_ISUPPORTS(nsAppShellWindowEnumerator, nsISimpleEnumerator)
153 nsAppShellWindowEnumerator::nsAppShellWindowEnumerator(
154 const char16_t* aTypeString,
155 nsWindowMediator& aMediator) :
156 mWindowMediator(&aMediator), mType(aTypeString), mCurrentPosition(nullptr)
157 {
158 mWindowMediator->AddEnumerator(this);
159 NS_ADDREF(mWindowMediator);
160 }
162 nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator()
163 {
164 mWindowMediator->RemoveEnumerator(this);
165 NS_RELEASE(mWindowMediator);
166 }
168 // after mCurrentPosition has been initialized to point to the beginning
169 // of the appropriate list, adjust it if necessary
170 void nsAppShellWindowEnumerator::AdjustInitialPosition()
171 {
172 if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType))
173 mCurrentPosition = FindNext();
174 }
176 NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool *retval)
177 {
178 if (!retval)
179 return NS_ERROR_INVALID_ARG;
181 *retval = mCurrentPosition ? true : false;
182 return NS_OK;
183 }
185 // if a window is being removed adjust the iterator's current position
186 void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo)
187 {
188 if (mCurrentPosition == inInfo)
189 mCurrentPosition = FindNext();
190 }
192 //
193 // nsASDOMWindowEnumerator
194 //
196 nsASDOMWindowEnumerator::nsASDOMWindowEnumerator(
197 const char16_t* aTypeString,
198 nsWindowMediator& aMediator) :
199 nsAppShellWindowEnumerator(aTypeString, aMediator)
200 {
201 }
203 nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator()
204 {
205 }
207 NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval)
208 {
209 if (!retval)
210 return NS_ERROR_INVALID_ARG;
212 *retval = nullptr;
213 while (mCurrentPosition) {
214 nsCOMPtr<nsIDOMWindow> domWindow;
215 nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow);
216 mCurrentPosition = FindNext();
217 if (domWindow)
218 return CallQueryInterface(domWindow, retval);
219 }
220 return NS_OK;
221 }
223 //
224 // nsASXULWindowEnumerator
225 //
227 nsASXULWindowEnumerator::nsASXULWindowEnumerator(
228 const char16_t* aTypeString,
229 nsWindowMediator& aMediator) :
230 nsAppShellWindowEnumerator(aTypeString, aMediator)
231 {
232 }
234 nsASXULWindowEnumerator::~nsASXULWindowEnumerator()
235 {
236 }
238 NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval)
239 {
240 if (!retval)
241 return NS_ERROR_INVALID_ARG;
243 *retval = nullptr;
244 if (mCurrentPosition) {
245 CallQueryInterface(mCurrentPosition->mWindow, retval);
246 mCurrentPosition = FindNext();
247 }
248 return NS_OK;
249 }
251 //
252 // nsASDOMWindowEarlyToLateEnumerator
253 //
255 nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator(
256 const char16_t *aTypeString,
257 nsWindowMediator &aMediator) :
258 nsASDOMWindowEnumerator(aTypeString, aMediator)
259 {
260 mCurrentPosition = aMediator.mOldestWindow;
261 AdjustInitialPosition();
262 }
264 nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator()
265 {
266 }
268 nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext()
269 {
270 nsWindowInfo *info,
271 *listEnd;
272 bool allWindows = mType.IsEmpty();
274 // see nsXULWindowEarlyToLateEnumerator::FindNext
275 if (!mCurrentPosition)
276 return nullptr;
278 info = mCurrentPosition->mYounger;
279 listEnd = mWindowMediator->mOldestWindow;
281 while (info != listEnd) {
282 if (allWindows || info->TypeEquals(mType))
283 return info;
284 info = info->mYounger;
285 }
287 return nullptr;
288 }
290 //
291 // nsASXULWindowEarlyToLateEnumerator
292 //
294 nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator(
295 const char16_t *aTypeString,
296 nsWindowMediator &aMediator) :
297 nsASXULWindowEnumerator(aTypeString, aMediator)
298 {
299 mCurrentPosition = aMediator.mOldestWindow;
300 AdjustInitialPosition();
301 }
303 nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator()
304 {
305 }
307 nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext()
308 {
309 nsWindowInfo *info,
310 *listEnd;
311 bool allWindows = mType.IsEmpty();
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 if (!mCurrentPosition)
321 return nullptr;
323 info = mCurrentPosition->mYounger;
324 listEnd = mWindowMediator->mOldestWindow;
326 while (info != listEnd) {
327 if (allWindows || info->TypeEquals(mType))
328 return info;
329 info = info->mYounger;
330 }
332 return nullptr;
333 }
335 //
336 // nsASDOMWindowFrontToBackEnumerator
337 //
339 nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator(
340 const char16_t *aTypeString,
341 nsWindowMediator &aMediator) :
342 nsASDOMWindowEnumerator(aTypeString, aMediator)
343 {
344 mCurrentPosition = aMediator.mTopmostWindow;
345 AdjustInitialPosition();
346 }
348 nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator()
349 {
350 }
352 nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext()
353 {
354 nsWindowInfo *info,
355 *listEnd;
356 bool allWindows = mType.IsEmpty();
358 // see nsXULWindowEarlyToLateEnumerator::FindNext
359 if (!mCurrentPosition)
360 return nullptr;
362 info = mCurrentPosition->mLower;
363 listEnd = mWindowMediator->mTopmostWindow;
365 while (info != listEnd) {
366 if (allWindows || info->TypeEquals(mType))
367 return info;
368 info = info->mLower;
369 }
371 return nullptr;
372 }
374 //
375 // nsASXULWindowFrontToBackEnumerator
376 //
378 nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator(
379 const char16_t *aTypeString,
380 nsWindowMediator &aMediator) :
381 nsASXULWindowEnumerator(aTypeString, aMediator)
382 {
383 mCurrentPosition = aMediator.mTopmostWindow;
384 AdjustInitialPosition();
385 }
387 nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator()
388 {
389 }
391 nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext()
392 {
393 nsWindowInfo *info,
394 *listEnd;
395 bool allWindows = mType.IsEmpty();
397 // see nsXULWindowEarlyToLateEnumerator::FindNext
398 if (!mCurrentPosition)
399 return nullptr;
401 info = mCurrentPosition->mLower;
402 listEnd = mWindowMediator->mTopmostWindow;
404 while (info != listEnd) {
405 if (allWindows || info->TypeEquals(mType))
406 return info;
407 info = info->mLower;
408 }
410 return nullptr;
411 }
413 //
414 // nsASDOMWindowBackToFrontEnumerator
415 //
417 nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator(
418 const char16_t *aTypeString,
419 nsWindowMediator &aMediator) :
420 nsASDOMWindowEnumerator(aTypeString, aMediator)
421 {
422 mCurrentPosition = aMediator.mTopmostWindow ?
423 aMediator.mTopmostWindow->mHigher : nullptr;
424 AdjustInitialPosition();
425 }
427 nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator()
428 {
429 }
431 nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext()
432 {
433 nsWindowInfo *info,
434 *listEnd;
435 bool allWindows = mType.IsEmpty();
437 // see nsXULWindowEarlyToLateEnumerator::FindNext
438 if (!mCurrentPosition)
439 return nullptr;
441 info = mCurrentPosition->mHigher;
442 listEnd = mWindowMediator->mTopmostWindow;
443 if (listEnd)
444 listEnd = listEnd->mHigher;
446 while (info != listEnd) {
447 if (allWindows || info->TypeEquals(mType))
448 return info;
449 info = info->mHigher;
450 }
452 return nullptr;
453 }
455 //
456 // nsASXULWindowBackToFrontEnumerator
457 //
459 nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator(
460 const char16_t *aTypeString,
461 nsWindowMediator &aMediator) :
462 nsASXULWindowEnumerator(aTypeString, aMediator)
463 {
464 mCurrentPosition = aMediator.mTopmostWindow ?
465 aMediator.mTopmostWindow->mHigher : nullptr;
466 AdjustInitialPosition();
467 }
469 nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator()
470 {
471 }
473 nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext()
474 {
475 nsWindowInfo *info,
476 *listEnd;
477 bool allWindows = mType.IsEmpty();
479 // see nsXULWindowEarlyToLateEnumerator::FindNext
480 if (!mCurrentPosition)
481 return nullptr;
483 info = mCurrentPosition->mHigher;
484 listEnd = mWindowMediator->mTopmostWindow;
485 if (listEnd)
486 listEnd = listEnd->mHigher;
488 while (info != listEnd) {
489 if (allWindows || info->TypeEquals(mType))
490 return info;
491 info = info->mHigher;
492 }
494 return nullptr;
495 }