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/dom/WindowContext.h"
8
#include "mozilla/dom/WindowGlobalActorsBinding.h"
9
#include "mozilla/dom/SyncedContextInlines.h"
10
#include "mozilla/dom/BrowsingContext.h"
11
#include "mozilla/StaticPtr.h"
12
#include "mozilla/ClearOnShutdown.h"
13
#include "nsRefPtrHashtable.h"
14
15
namespace mozilla {
16
namespace dom {
17
18
// Explicit specialization of the `Transaction` type. Required by the `extern
19
// template class` declaration in the header.
20
template class syncedcontext::Transaction<WindowContext>;
21
22
static LazyLogModule gWindowContextLog("WindowContext");
23
24
using WindowContextByIdMap = nsDataHashtable<nsUint64HashKey, WindowContext*>;
25
static StaticAutoPtr<WindowContextByIdMap> gWindowContexts;
26
27
/* static */
28
LogModule* WindowContext::GetLog() { return gWindowContextLog; }
29
30
/* static */
31
already_AddRefed<WindowContext> WindowContext::GetById(
32
uint64_t aInnerWindowId) {
33
if (!gWindowContexts) {
34
return nullptr;
35
}
36
return do_AddRef(gWindowContexts->Get(aInnerWindowId));
37
}
38
39
BrowsingContextGroup* WindowContext::Group() const {
40
return mBrowsingContext->Group();
41
}
42
43
WindowGlobalParent* WindowContext::Canonical() {
44
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
45
return static_cast<WindowGlobalParent*>(this);
46
}
47
48
nsIGlobalObject* WindowContext::GetParentObject() const {
49
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
50
}
51
52
void WindowContext::SendCommitTransaction(ContentParent* aParent,
53
const BaseTransaction& aTxn,
54
uint64_t aEpoch) {
55
Unused << aParent->SendCommitWindowContextTransaction(this, aTxn, aEpoch);
56
}
57
58
void WindowContext::SendCommitTransaction(ContentChild* aChild,
59
const BaseTransaction& aTxn,
60
uint64_t aEpoch) {
61
aChild->SendCommitWindowContextTransaction(this, aTxn, aEpoch);
62
}
63
64
already_AddRefed<WindowContext> WindowContext::Create(
65
WindowGlobalChild* aWindow) {
66
MOZ_RELEASE_ASSERT(XRE_IsContentProcess(),
67
"Should be a WindowGlobalParent in the parent");
68
69
FieldTuple init;
70
mozilla::Get<IDX_OuterWindowId>(init) = aWindow->OuterWindowId();
71
RefPtr<WindowContext> context = new WindowContext(
72
aWindow->BrowsingContext(), aWindow->InnerWindowId(), std::move(init));
73
context->Init();
74
return context.forget();
75
}
76
77
void WindowContext::CreateFromIPC(IPCInitializer&& aInit) {
78
MOZ_RELEASE_ASSERT(XRE_IsContentProcess(),
79
"Should be a WindowGlobalParent in the parent");
80
81
RefPtr<BrowsingContext> bc = BrowsingContext::Get(aInit.mBrowsingContextId);
82
MOZ_RELEASE_ASSERT(bc);
83
84
if (bc->IsDiscarded()) {
85
// If we have already closed our browsing context, the
86
// WindowGlobalChild actor is bound to be destroyed soon and it's
87
// safe to ignore creating the WindowContext.
88
return;
89
}
90
91
RefPtr<WindowContext> context =
92
new WindowContext(bc, aInit.mInnerWindowId, std::move(aInit.mFields));
93
context->Init();
94
}
95
96
void WindowContext::Init() {
97
MOZ_LOG(GetLog(), LogLevel::Debug,
98
("Registering 0x%" PRIx64 " (bc=0x%" PRIx64 ")", mInnerWindowId,
99
mBrowsingContext->Id()));
100
101
// Register the WindowContext in the `WindowContextByIdMap`.
102
if (!gWindowContexts) {
103
gWindowContexts = new WindowContextByIdMap();
104
ClearOnShutdown(&gWindowContexts);
105
}
106
auto& entry = gWindowContexts->GetOrInsert(mInnerWindowId);
107
MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowContext for ID!");
108
entry = this;
109
110
// Register this to the browsing context.
111
mBrowsingContext->RegisterWindowContext(this);
112
}
113
114
void WindowContext::Discard() {
115
MOZ_LOG(GetLog(), LogLevel::Debug,
116
("Discarding 0x%" PRIx64 " (bc=0x%" PRIx64 ")", mInnerWindowId,
117
mBrowsingContext->Id()));
118
if (mIsDiscarded) {
119
return;
120
}
121
122
mBrowsingContext->UnregisterWindowContext(this);
123
gWindowContexts->Remove(InnerWindowId());
124
mIsDiscarded = true;
125
}
126
127
WindowContext::WindowContext(BrowsingContext* aBrowsingContext,
128
uint64_t aInnerWindowId, FieldTuple&& aFields)
129
: mFields(std::move(aFields)),
130
mInnerWindowId(aInnerWindowId),
131
mBrowsingContext(aBrowsingContext) {
132
MOZ_ASSERT(mBrowsingContext);
133
MOZ_ASSERT(mInnerWindowId);
134
}
135
136
WindowContext::~WindowContext() {
137
if (gWindowContexts) {
138
gWindowContexts->Remove(InnerWindowId());
139
}
140
}
141
142
JSObject* WindowContext::WrapObject(JSContext* cx,
143
JS::Handle<JSObject*> aGivenProto) {
144
return WindowContext_Binding::Wrap(cx, this, aGivenProto);
145
}
146
147
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowContext)
148
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
149
NS_INTERFACE_MAP_ENTRY(nsISupports)
150
NS_INTERFACE_MAP_END
151
152
NS_IMPL_CYCLE_COLLECTING_ADDREF(WindowContext)
153
NS_IMPL_CYCLE_COLLECTING_RELEASE(WindowContext)
154
155
NS_IMPL_CYCLE_COLLECTION_CLASS(WindowContext)
156
157
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WindowContext)
158
if (gWindowContexts) {
159
gWindowContexts->Remove(tmp->InnerWindowId());
160
}
161
162
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
163
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
164
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
165
166
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WindowContext)
167
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
168
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
169
170
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(WindowContext)
171
172
} // namespace dom
173
174
namespace ipc {
175
176
void IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Write(
177
IPC::Message* aMsg, IProtocol* aActor,
178
const dom::MaybeDiscarded<dom::WindowContext>& aParam) {
179
uint64_t id = aParam.ContextId();
180
WriteIPDLParam(aMsg, aActor, id);
181
}
182
183
bool IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Read(
184
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
185
dom::MaybeDiscarded<dom::WindowContext>* aResult) {
186
uint64_t id = 0;
187
if (!ReadIPDLParam(aMsg, aIter, aActor, &id)) {
188
return false;
189
}
190
191
if (id == 0) {
192
*aResult = nullptr;
193
} else if (RefPtr<dom::WindowContext> wc = dom::WindowContext::GetById(id)) {
194
*aResult = std::move(wc);
195
} else {
196
aResult->SetDiscarded(id);
197
}
198
return true;
199
}
200
201
void IPDLParamTraits<dom::WindowContext::IPCInitializer>::Write(
202
IPC::Message* aMessage, IProtocol* aActor,
203
const dom::WindowContext::IPCInitializer& aInit) {
204
// Write actor ID parameters.
205
WriteIPDLParam(aMessage, aActor, aInit.mInnerWindowId);
206
WriteIPDLParam(aMessage, aActor, aInit.mBrowsingContextId);
207
WriteIPDLParam(aMessage, aActor, aInit.mFields);
208
}
209
210
bool IPDLParamTraits<dom::WindowContext::IPCInitializer>::Read(
211
const IPC::Message* aMessage, PickleIterator* aIterator, IProtocol* aActor,
212
dom::WindowContext::IPCInitializer* aInit) {
213
// Read actor ID parameters.
214
return ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mInnerWindowId) &&
215
ReadIPDLParam(aMessage, aIterator, aActor,
216
&aInit->mBrowsingContextId) &&
217
ReadIPDLParam(aMessage, aIterator, aActor, &aInit->mFields);
218
}
219
220
template struct IPDLParamTraits<dom::WindowContext::BaseTransaction>;
221
222
} // namespace ipc
223
} // namespace mozilla