Source code

Revision control

Other Tools

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/BrowserParent.h"
26
#include "mozilla/dom/HTMLTextAreaElement.h"
27
#include "mozilla/dom/HTMLInputElement.h"
28
#include "mozilla/dom/JSWindowActorService.h"
29
30
#ifdef MOZ_XUL
31
# include "nsXULElement.h"
32
#endif
33
34
using namespace mozilla;
35
using namespace mozilla::dom;
36
37
nsWindowRoot::nsWindowRoot(nsPIDOMWindowOuter* aWindow) {
38
mWindow = aWindow;
39
mShowFocusRings = StaticPrefs::browser_display_show_focus_rings();
40
}
41
42
nsWindowRoot::~nsWindowRoot() {
43
if (mListenerManager) {
44
mListenerManager->Disconnect();
45
}
46
47
if (XRE_IsContentProcess()) {
48
JSWindowActorService::UnregisterChromeEventTarget(this);
49
}
50
}
51
52
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsWindowRoot, mWindow, mListenerManager,
53
mParent)
54
55
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsWindowRoot)
56
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
57
NS_INTERFACE_MAP_ENTRY(nsISupports)
58
NS_INTERFACE_MAP_ENTRY(nsPIWindowRoot)
59
NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
60
NS_INTERFACE_MAP_END
61
62
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWindowRoot)
63
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWindowRoot)
64
65
bool nsWindowRoot::DispatchEvent(Event& aEvent, CallerType aCallerType,
66
ErrorResult& aRv) {
67
nsEventStatus status = nsEventStatus_eIgnore;
68
nsresult rv = EventDispatcher::DispatchDOMEvent(
69
static_cast<EventTarget*>(this), nullptr, &aEvent, nullptr, &status);
70
bool retval = !aEvent.DefaultPrevented(aCallerType);
71
if (NS_FAILED(rv)) {
72
aRv.Throw(rv);
73
}
74
return retval;
75
}
76
77
bool nsWindowRoot::ComputeDefaultWantsUntrusted(ErrorResult& aRv) {
78
return false;
79
}
80
81
EventListenerManager* nsWindowRoot::GetOrCreateListenerManager() {
82
if (!mListenerManager) {
83
mListenerManager =
84
new EventListenerManager(static_cast<EventTarget*>(this));
85
}
86
87
return mListenerManager;
88
}
89
90
EventListenerManager* nsWindowRoot::GetExistingListenerManager() const {
91
return mListenerManager;
92
}
93
94
void nsWindowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
95
aVisitor.mCanHandle = true;
96
aVisitor.mForceContentDispatch = true; // FIXME! Bug 329119
97
// To keep mWindow alive
98
aVisitor.mItemData = static_cast<nsISupports*>(mWindow);
99
aVisitor.SetParentTarget(mParent, false);
100
}
101
102
nsresult nsWindowRoot::PostHandleEvent(EventChainPostVisitor& aVisitor) {
103
return NS_OK;
104
}
105
106
nsPIDOMWindowOuter* nsWindowRoot::GetOwnerGlobalForBindingsInternal() {
107
return mWindow;
108
}
109
110
nsIGlobalObject* nsWindowRoot::GetOwnerGlobal() const {
111
nsCOMPtr<nsIGlobalObject> global =
112
do_QueryInterface(mWindow->GetCurrentInnerWindow());
113
// We're still holding a ref to it, so returning the raw pointer is ok...
114
return global;
115
}
116
117
nsPIDOMWindowOuter* nsWindowRoot::GetWindow() { return mWindow; }
118
119
nsresult nsWindowRoot::GetControllers(bool aForVisibleWindow,
120
nsIControllers** aResult) {
121
*aResult = nullptr;
122
123
// XXX: we should fix this so there's a generic interface that
124
// describes controllers, so this code would have no special
125
// knowledge of what object might have controllers.
126
127
nsFocusManager::SearchRange searchRange =
128
aForVisibleWindow ? nsFocusManager::eIncludeVisibleDescendants
129
: nsFocusManager::eIncludeAllDescendants;
130
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
131
nsIContent* focusedContent = nsFocusManager::GetFocusedDescendant(
132
mWindow, searchRange, getter_AddRefs(focusedWindow));
133
if (focusedContent) {
134
#ifdef MOZ_XUL
135
RefPtr<nsXULElement> xulElement = nsXULElement::FromNode(focusedContent);
136
if (xulElement) {
137
ErrorResult rv;
138
*aResult = xulElement->GetControllers(rv);
139
NS_IF_ADDREF(*aResult);
140
return rv.StealNSResult();
141
}
142
#endif
143
144
HTMLTextAreaElement* htmlTextArea =
145
HTMLTextAreaElement::FromNode(focusedContent);
146
if (htmlTextArea) return htmlTextArea->GetControllers(aResult);
147
148
HTMLInputElement* htmlInputElement =
149
HTMLInputElement::FromNode(focusedContent);
150
if (htmlInputElement) return htmlInputElement->GetControllers(aResult);
151
152
if (focusedContent->IsEditable() && focusedWindow)
153
return focusedWindow->GetControllers(aResult);
154
} else {
155
return focusedWindow->GetControllers(aResult);
156
}
157
158
return NS_OK;
159
}
160
161
nsresult nsWindowRoot::GetControllerForCommand(const char* aCommand,
162
bool aForVisibleWindow,
163
nsIController** _retval) {
164
NS_ENSURE_ARG_POINTER(_retval);
165
*_retval = nullptr;
166
167
{
168
nsCOMPtr<nsIControllers> controllers;
169
GetControllers(aForVisibleWindow, getter_AddRefs(controllers));
170
if (controllers) {
171
nsCOMPtr<nsIController> controller;
172
controllers->GetControllerForCommand(aCommand,
173
getter_AddRefs(controller));
174
if (controller) {
175
controller.forget(_retval);
176
return NS_OK;
177
}
178
}
179
}
180
181
nsFocusManager::SearchRange searchRange =
182
aForVisibleWindow ? nsFocusManager::eIncludeVisibleDescendants
183
: nsFocusManager::eIncludeAllDescendants;
184
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
185
nsFocusManager::GetFocusedDescendant(mWindow, searchRange,
186
getter_AddRefs(focusedWindow));
187
while (focusedWindow) {
188
nsCOMPtr<nsIControllers> controllers;
189
focusedWindow->GetControllers(getter_AddRefs(controllers));
190
if (controllers) {
191
nsCOMPtr<nsIController> controller;
192
controllers->GetControllerForCommand(aCommand,
193
getter_AddRefs(controller));
194
if (controller) {
195
controller.forget(_retval);
196
return NS_OK;
197
}
198
}
199
200
// XXXndeakin P3 is this casting safe?
201
nsGlobalWindowOuter* win = nsGlobalWindowOuter::Cast(focusedWindow);
202
focusedWindow = win->GetPrivateParent();
203
}
204
205
return NS_OK;
206
}
207
208
void nsWindowRoot::GetEnabledDisabledCommandsForControllers(
209
nsIControllers* aControllers,
210
nsTHashtable<nsCStringHashKey>& aCommandsHandled,
211
nsTArray<nsCString>& aEnabledCommands,
212
nsTArray<nsCString>& aDisabledCommands) {
213
uint32_t controllerCount;
214
aControllers->GetControllerCount(&controllerCount);
215
for (uint32_t c = 0; c < controllerCount; c++) {
216
nsCOMPtr<nsIController> controller;
217
aControllers->GetControllerAt(c, getter_AddRefs(controller));
218
219
nsCOMPtr<nsICommandController> commandController(
220
do_QueryInterface(controller));
221
if (commandController) {
222
// All of our default command controllers have 20-60 commands. Let's just
223
// leave enough space here for all of them so we probably don't need to
224
// heap-allocate.
225
AutoTArray<nsCString, 64> commands;
226
if (NS_SUCCEEDED(commandController->GetSupportedCommands(commands))) {
227
for (auto& commandStr : commands) {
228
// Use a hash to determine which commands have already been handled by
229
// earlier controllers, as the earlier controller's result should get
230
// priority.
231
if (aCommandsHandled.EnsureInserted(commandStr)) {
232
// We inserted a new entry into aCommandsHandled.
233
bool enabled = false;
234
controller->IsCommandEnabled(commandStr.get(), &enabled);
235
236
if (enabled) {
237
aEnabledCommands.AppendElement(commandStr);
238
} else {
239
aDisabledCommands.AppendElement(commandStr);
240
}
241
}
242
}
243
}
244
}
245
}
246
}
247
248
void nsWindowRoot::GetEnabledDisabledCommands(
249
nsTArray<nsCString>& aEnabledCommands,
250
nsTArray<nsCString>& aDisabledCommands) {
251
nsTHashtable<nsCStringHashKey> commandsHandled;
252
253
nsCOMPtr<nsIControllers> controllers;
254
GetControllers(false, getter_AddRefs(controllers));
255
if (controllers) {
256
GetEnabledDisabledCommandsForControllers(
257
controllers, commandsHandled, aEnabledCommands, aDisabledCommands);
258
}
259
260
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
261
nsFocusManager::GetFocusedDescendant(mWindow,
262
nsFocusManager::eIncludeAllDescendants,
263
getter_AddRefs(focusedWindow));
264
while (focusedWindow) {
265
focusedWindow->GetControllers(getter_AddRefs(controllers));
266
if (controllers) {
267
GetEnabledDisabledCommandsForControllers(
268
controllers, commandsHandled, aEnabledCommands, aDisabledCommands);
269
}
270
271
nsGlobalWindowOuter* win = nsGlobalWindowOuter::Cast(focusedWindow);
272
focusedWindow = win->GetPrivateParent();
273
}
274
}
275
276
already_AddRefed<nsINode> nsWindowRoot::GetPopupNode() {
277
nsCOMPtr<nsINode> popupNode = do_QueryReferent(mPopupNode);
278
return popupNode.forget();
279
}
280
281
void nsWindowRoot::SetPopupNode(nsINode* aNode) {
282
mPopupNode = do_GetWeakReference(aNode);
283
}
284
285
nsIGlobalObject* nsWindowRoot::GetParentObject() {
286
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
287
}
288
289
JSObject* nsWindowRoot::WrapObject(JSContext* aCx,
290
JS::Handle<JSObject*> aGivenProto) {
291
return mozilla::dom::WindowRoot_Binding::Wrap(aCx, this, aGivenProto);
292
}
293
294
void nsWindowRoot::AddBrowser(nsIRemoteTab* aBrowser) {
295
nsWeakPtr weakBrowser = do_GetWeakReference(aBrowser);
296
mWeakBrowsers.PutEntry(weakBrowser);
297
}
298
299
void nsWindowRoot::RemoveBrowser(nsIRemoteTab* aBrowser) {
300
nsWeakPtr weakBrowser = do_GetWeakReference(aBrowser);
301
mWeakBrowsers.RemoveEntry(weakBrowser);
302
}
303
304
void nsWindowRoot::EnumerateBrowsers(BrowserEnumerator aEnumFunc, void* aArg) {
305
// Collect strong references to all browsers in a separate array in
306
// case aEnumFunc alters mWeakBrowsers.
307
nsTArray<nsCOMPtr<nsIRemoteTab>> remoteTabs;
308
for (auto iter = mWeakBrowsers.ConstIter(); !iter.Done(); iter.Next()) {
309
nsCOMPtr<nsIRemoteTab> remoteTab(do_QueryReferent(iter.Get()->GetKey()));
310
if (remoteTab) {
311
remoteTabs.AppendElement(remoteTab);
312
}
313
}
314
315
for (uint32_t i = 0; i < remoteTabs.Length(); ++i) {
316
aEnumFunc(remoteTabs[i], aArg);
317
}
318
}
319
320
///////////////////////////////////////////////////////////////////////////////////
321
322
already_AddRefed<EventTarget> NS_NewWindowRoot(nsPIDOMWindowOuter* aWindow) {
323
nsCOMPtr<EventTarget> result = new nsWindowRoot(aWindow);
324
325
if (XRE_IsContentProcess()) {
326
RefPtr<JSWindowActorService> wasvc = JSWindowActorService::GetSingleton();
327
wasvc->RegisterChromeEventTarget(result);
328
}
329
330
return result.forget();
331
}