Coverage Report

Created: 2018-09-25 14:53

/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
}