Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/nsWindowRoot.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/BasicEvents.h"
8
#include "mozilla/EventDispatcher.h"
9
#include "mozilla/EventListenerManager.h"
10
#include "mozilla/dom/WindowRootBinding.h"
11
#include "nsCOMPtr.h"
12
#include "nsWindowRoot.h"
13
#include "nsPIDOMWindow.h"
14
#include "nsPresContext.h"
15
#include "nsLayoutCID.h"
16
#include "nsContentCID.h"
17
#include "nsString.h"
18
#include "nsGlobalWindow.h"
19
#include "nsFocusManager.h"
20
#include "nsIContent.h"
21
#include "nsIControllers.h"
22
#include "nsIController.h"
23
#include "xpcpublic.h"
24
#include "nsCycleCollectionParticipant.h"
25
#include "mozilla/dom/TabParent.h"
26
#include "mozilla/dom/HTMLTextAreaElement.h"
27
#include "mozilla/dom/HTMLInputElement.h"
28
29
#ifdef MOZ_XUL
30
#include "nsXULElement.h"
31
#endif
32
33
using namespace mozilla;
34
using namespace mozilla::dom;
35
36
nsWindowRoot::nsWindowRoot(nsPIDOMWindowOuter* aWindow)
37
0
{
38
0
  mWindow = aWindow;
39
0
40
0
  // Keyboard indicators are not shown on Mac by default.
41
#if defined(XP_MACOSX)
42
  mShowAccelerators = false;
43
  mShowFocusRings = false;
44
#else
45
  mShowAccelerators = true;
46
0
  mShowFocusRings = true;
47
0
#endif
48
0
}
49
50
nsWindowRoot::~nsWindowRoot()
51
0
{
52
0
  if (mListenerManager) {
53
0
    mListenerManager->Disconnect();
54
0
  }
55
0
}
56
57
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsWindowRoot,
58
                                      mWindow,
59
                                      mListenerManager,
60
                                      mParent)
61
62
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsWindowRoot)
63
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
64
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
65
0
  NS_INTERFACE_MAP_ENTRY(nsPIWindowRoot)
66
0
  NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
67
0
NS_INTERFACE_MAP_END
68
69
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWindowRoot)
70
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWindowRoot)
71
72
bool
73
nsWindowRoot::DispatchEvent(Event& aEvent, CallerType aCallerType,
74
                            ErrorResult& aRv)
75
0
{
76
0
  nsEventStatus status = nsEventStatus_eIgnore;
77
0
  nsresult rv =  EventDispatcher::DispatchDOMEvent(
78
0
    static_cast<EventTarget*>(this), nullptr, &aEvent, nullptr, &status);
79
0
  bool retval = !aEvent.DefaultPrevented(aCallerType);
80
0
  if (NS_FAILED(rv)) {
81
0
    aRv.Throw(rv);
82
0
  }
83
0
  return retval;
84
0
}
85
86
bool
87
nsWindowRoot::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
88
0
{
89
0
  return false;
90
0
}
91
92
EventListenerManager*
93
nsWindowRoot::GetOrCreateListenerManager()
94
0
{
95
0
  if (!mListenerManager) {
96
0
    mListenerManager =
97
0
      new EventListenerManager(static_cast<EventTarget*>(this));
98
0
  }
99
0
100
0
  return mListenerManager;
101
0
}
102
103
EventListenerManager*
104
nsWindowRoot::GetExistingListenerManager() const
105
0
{
106
0
  return mListenerManager;
107
0
}
108
109
void
110
nsWindowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor)
111
0
{
112
0
  aVisitor.mCanHandle = true;
113
0
  aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
114
0
  // To keep mWindow alive
115
0
  aVisitor.mItemData = static_cast<nsISupports *>(mWindow);
116
0
  aVisitor.SetParentTarget(mParent, false);
117
0
}
118
119
nsresult
120
nsWindowRoot::PostHandleEvent(EventChainPostVisitor& aVisitor)
121
0
{
122
0
  return NS_OK;
123
0
}
124
125
nsPIDOMWindowOuter*
126
nsWindowRoot::GetOwnerGlobalForBindings()
127
0
{
128
0
  return GetWindow();
129
0
}
130
131
nsIGlobalObject*
132
nsWindowRoot::GetOwnerGlobal() const
133
0
{
134
0
  nsCOMPtr<nsIGlobalObject> global =
135
0
    do_QueryInterface(mWindow->GetCurrentInnerWindow());
136
0
  // We're still holding a ref to it, so returning the raw pointer is ok...
137
0
  return global;
138
0
}
139
140
nsPIDOMWindowOuter*
141
nsWindowRoot::GetWindow()
142
0
{
143
0
  return mWindow;
144
0
}
145
146
nsresult
147
nsWindowRoot::GetControllers(bool aForVisibleWindow,
148
                             nsIControllers** aResult)
149
0
{
150
0
  *aResult = nullptr;
151
0
152
0
  // XXX: we should fix this so there's a generic interface that
153
0
  // describes controllers, so this code would have no special
154
0
  // knowledge of what object might have controllers.
155
0
156
0
  nsFocusManager::SearchRange searchRange =
157
0
    aForVisibleWindow ? nsFocusManager::eIncludeVisibleDescendants :
158
0
                        nsFocusManager::eIncludeAllDescendants;
159
0
  nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
160
0
  nsIContent* focusedContent =
161
0
    nsFocusManager::GetFocusedDescendant(mWindow, searchRange,
162
0
                                         getter_AddRefs(focusedWindow));
163
0
  if (focusedContent) {
164
0
#ifdef MOZ_XUL
165
0
    RefPtr<nsXULElement> xulElement = nsXULElement::FromNode(focusedContent);
166
0
    if (xulElement) {
167
0
      ErrorResult rv;
168
0
      *aResult = xulElement->GetControllers(rv);
169
0
      NS_IF_ADDREF(*aResult);
170
0
      return rv.StealNSResult();
171
0
    }
172
0
#endif
173
0
174
0
    HTMLTextAreaElement* htmlTextArea =
175
0
      HTMLTextAreaElement::FromNode(focusedContent);
176
0
    if (htmlTextArea)
177
0
      return htmlTextArea->GetControllers(aResult);
178
0
179
0
    HTMLInputElement* htmlInputElement =
180
0
      HTMLInputElement::FromNode(focusedContent);
181
0
    if (htmlInputElement)
182
0
      return htmlInputElement->GetControllers(aResult);
183
0
184
0
    if (focusedContent->IsEditable() && focusedWindow)
185
0
      return focusedWindow->GetControllers(aResult);
186
0
  }
187
0
  else {
188
0
    return focusedWindow->GetControllers(aResult);
189
0
  }
190
0
191
0
  return NS_OK;
192
0
}
193
194
nsresult
195
nsWindowRoot::GetControllerForCommand(const char* aCommand,
196
                                      bool aForVisibleWindow,
197
                                      nsIController** _retval)
198
0
{
199
0
  NS_ENSURE_ARG_POINTER(_retval);
200
0
  *_retval = nullptr;
201
0
202
0
  {
203
0
    nsCOMPtr<nsIControllers> controllers;
204
0
    GetControllers(aForVisibleWindow, getter_AddRefs(controllers));
205
0
    if (controllers) {
206
0
      nsCOMPtr<nsIController> controller;
207
0
      controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
208
0
      if (controller) {
209
0
        controller.forget(_retval);
210
0
        return NS_OK;
211
0
      }
212
0
    }
213
0
  }
214
0
215
0
  nsFocusManager::SearchRange searchRange =
216
0
    aForVisibleWindow ? nsFocusManager::eIncludeVisibleDescendants :
217
0
                        nsFocusManager::eIncludeAllDescendants;
218
0
  nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
219
0
  nsFocusManager::GetFocusedDescendant(mWindow, searchRange,
220
0
                                       getter_AddRefs(focusedWindow));
221
0
  while (focusedWindow) {
222
0
    nsCOMPtr<nsIControllers> controllers;
223
0
    focusedWindow->GetControllers(getter_AddRefs(controllers));
224
0
    if (controllers) {
225
0
      nsCOMPtr<nsIController> controller;
226
0
      controllers->GetControllerForCommand(aCommand,
227
0
                                           getter_AddRefs(controller));
228
0
      if (controller) {
229
0
        controller.forget(_retval);
230
0
        return NS_OK;
231
0
      }
232
0
    }
233
0
234
0
    // XXXndeakin P3 is this casting safe?
235
0
    nsGlobalWindowOuter *win = nsGlobalWindowOuter::Cast(focusedWindow);
236
0
    focusedWindow = win->GetPrivateParent();
237
0
  }
238
0
239
0
  return NS_OK;
240
0
}
241
242
void
243
nsWindowRoot::GetEnabledDisabledCommandsForControllers(nsIControllers* aControllers,
244
                                                       nsTHashtable<nsCharPtrHashKey>& aCommandsHandled,
245
                                                       nsTArray<nsCString>& aEnabledCommands,
246
                                                       nsTArray<nsCString>& aDisabledCommands)
247
0
{
248
0
  uint32_t controllerCount;
249
0
  aControllers->GetControllerCount(&controllerCount);
250
0
  for (uint32_t c = 0; c < controllerCount; c++) {
251
0
    nsCOMPtr<nsIController> controller;
252
0
    aControllers->GetControllerAt(c, getter_AddRefs(controller));
253
0
254
0
    nsCOMPtr<nsICommandController> commandController(do_QueryInterface(controller));
255
0
    if (commandController) {
256
0
      uint32_t commandsCount;
257
0
      char** commands;
258
0
      if (NS_SUCCEEDED(commandController->GetSupportedCommands(&commandsCount, &commands))) {
259
0
        for (uint32_t e = 0; e < commandsCount; e++) {
260
0
          // Use a hash to determine which commands have already been handled by
261
0
          // earlier controllers, as the earlier controller's result should get
262
0
          // priority.
263
0
          if (aCommandsHandled.EnsureInserted(commands[e])) {
264
0
            // We inserted a new entry into aCommandsHandled.
265
0
            bool enabled = false;
266
0
            controller->IsCommandEnabled(commands[e], &enabled);
267
0
268
0
            const nsDependentCSubstring commandStr(commands[e], strlen(commands[e]));
269
0
            if (enabled) {
270
0
              aEnabledCommands.AppendElement(commandStr);
271
0
            } else {
272
0
              aDisabledCommands.AppendElement(commandStr);
273
0
            }
274
0
          }
275
0
        }
276
0
277
0
        NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(commandsCount, commands);
278
0
      }
279
0
    }
280
0
  }
281
0
}
282
283
void
284
nsWindowRoot::GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
285
                                         nsTArray<nsCString>& aDisabledCommands)
286
0
{
287
0
  nsTHashtable<nsCharPtrHashKey> commandsHandled;
288
0
289
0
  nsCOMPtr<nsIControllers> controllers;
290
0
  GetControllers(false, getter_AddRefs(controllers));
291
0
  if (controllers) {
292
0
    GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
293
0
                                             aEnabledCommands, aDisabledCommands);
294
0
  }
295
0
296
0
  nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
297
0
  nsFocusManager::GetFocusedDescendant(mWindow,
298
0
                                       nsFocusManager::eIncludeAllDescendants,
299
0
                                       getter_AddRefs(focusedWindow));
300
0
  while (focusedWindow) {
301
0
    focusedWindow->GetControllers(getter_AddRefs(controllers));
302
0
    if (controllers) {
303
0
      GetEnabledDisabledCommandsForControllers(controllers, commandsHandled,
304
0
                                               aEnabledCommands, aDisabledCommands);
305
0
    }
306
0
307
0
    nsGlobalWindowOuter* win = nsGlobalWindowOuter::Cast(focusedWindow);
308
0
    focusedWindow = win->GetPrivateParent();
309
0
  }
310
0
}
311
312
already_AddRefed<nsINode>
313
nsWindowRoot::GetPopupNode()
314
0
{
315
0
  nsCOMPtr<nsINode> popupNode = do_QueryReferent(mPopupNode);
316
0
  return popupNode.forget();
317
0
}
318
319
void
320
nsWindowRoot::SetPopupNode(nsINode* aNode)
321
0
{
322
0
  mPopupNode = do_GetWeakReference(aNode);
323
0
}
324
325
nsIGlobalObject*
326
nsWindowRoot::GetParentObject()
327
0
{
328
0
  return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
329
0
}
330
331
JSObject*
332
nsWindowRoot::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
333
0
{
334
0
  return mozilla::dom::WindowRoot_Binding::Wrap(aCx, this, aGivenProto);
335
0
}
336
337
void
338
nsWindowRoot::AddBrowser(mozilla::dom::TabParent* aBrowser)
339
0
{
340
0
  nsWeakPtr weakBrowser = do_GetWeakReference(static_cast<nsITabParent*>(aBrowser));
341
0
  mWeakBrowsers.PutEntry(weakBrowser);
342
0
}
343
344
void
345
nsWindowRoot::RemoveBrowser(mozilla::dom::TabParent* aBrowser)
346
0
{
347
0
  nsWeakPtr weakBrowser = do_GetWeakReference(static_cast<nsITabParent*>(aBrowser));
348
0
  mWeakBrowsers.RemoveEntry(weakBrowser);
349
0
}
350
351
void
352
nsWindowRoot::EnumerateBrowsers(BrowserEnumerator aEnumFunc, void* aArg)
353
0
{
354
0
  // Collect strong references to all browsers in a separate array in
355
0
  // case aEnumFunc alters mWeakBrowsers.
356
0
  nsTArray<RefPtr<TabParent>> tabParents;
357
0
  for (auto iter = mWeakBrowsers.ConstIter(); !iter.Done(); iter.Next()) {
358
0
    nsCOMPtr<nsITabParent> tabParent(do_QueryReferent(iter.Get()->GetKey()));
359
0
    if (TabParent* tab = TabParent::GetFrom(tabParent)) {
360
0
      tabParents.AppendElement(tab);
361
0
    }
362
0
  }
363
0
364
0
  for (uint32_t i = 0; i < tabParents.Length(); ++i) {
365
0
    aEnumFunc(tabParents[i], aArg);
366
0
  }
367
0
}
368
369
///////////////////////////////////////////////////////////////////////////////////
370
371
already_AddRefed<EventTarget>
372
NS_NewWindowRoot(nsPIDOMWindowOuter* aWindow)
373
0
{
374
0
  nsCOMPtr<EventTarget> result = new nsWindowRoot(aWindow);
375
0
  return result.forget();
376
0
}