Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=4 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 "DomainPolicy.h"
8
#include "mozilla/dom/ContentParent.h"
9
#include "mozilla/ipc/URIUtils.h"
10
#include "mozilla/Unused.h"
11
#include "nsScriptSecurityManager.h"
12
13
namespace mozilla {
14
15
using namespace ipc;
16
using namespace dom;
17
18
NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
19
20
static nsresult BroadcastDomainSetChange(DomainSetType aSetType,
21
DomainSetChangeType aChangeType,
22
nsIURI* aDomain = nullptr) {
23
MOZ_ASSERT(XRE_IsParentProcess(),
24
"DomainPolicy should only be exposed to the chrome process.");
25
26
nsTArray<ContentParent*> parents;
27
ContentParent::GetAll(parents);
28
if (!parents.Length()) {
29
return NS_OK;
30
}
31
32
for (uint32_t i = 0; i < parents.Length(); i++) {
33
Unused << parents[i]->SendDomainSetChanged(aSetType, aChangeType, aDomain);
34
}
35
return NS_OK;
36
}
37
38
DomainPolicy::DomainPolicy()
39
: mBlocklist(new DomainSet(BLOCKLIST)),
40
mSuperBlocklist(new DomainSet(SUPER_BLOCKLIST)),
41
mAllowlist(new DomainSet(ALLOWLIST)),
42
mSuperAllowlist(new DomainSet(SUPER_ALLOWLIST)) {
43
if (XRE_IsParentProcess()) {
44
BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
45
}
46
}
47
48
DomainPolicy::~DomainPolicy() {
49
// The SSM holds a strong ref to the DomainPolicy until Deactivate() is
50
// invoked, so we should never hit the destructor until that happens.
51
MOZ_ASSERT(!mBlocklist && !mSuperBlocklist && !mAllowlist &&
52
!mSuperAllowlist);
53
}
54
55
NS_IMETHODIMP
56
DomainPolicy::GetBlocklist(nsIDomainSet** aSet) {
57
nsCOMPtr<nsIDomainSet> set = mBlocklist.get();
58
set.forget(aSet);
59
return NS_OK;
60
}
61
62
NS_IMETHODIMP
63
DomainPolicy::GetSuperBlocklist(nsIDomainSet** aSet) {
64
nsCOMPtr<nsIDomainSet> set = mSuperBlocklist.get();
65
set.forget(aSet);
66
return NS_OK;
67
}
68
69
NS_IMETHODIMP
70
DomainPolicy::GetAllowlist(nsIDomainSet** aSet) {
71
nsCOMPtr<nsIDomainSet> set = mAllowlist.get();
72
set.forget(aSet);
73
return NS_OK;
74
}
75
76
NS_IMETHODIMP
77
DomainPolicy::GetSuperAllowlist(nsIDomainSet** aSet) {
78
nsCOMPtr<nsIDomainSet> set = mSuperAllowlist.get();
79
set.forget(aSet);
80
return NS_OK;
81
}
82
83
NS_IMETHODIMP
84
DomainPolicy::Deactivate() {
85
// Clear the hashtables first to free up memory, since script might
86
// hold the doomed sets alive indefinitely.
87
mBlocklist->Clear();
88
mSuperBlocklist->Clear();
89
mAllowlist->Clear();
90
mSuperAllowlist->Clear();
91
92
// Null them out.
93
mBlocklist = nullptr;
94
mSuperBlocklist = nullptr;
95
mAllowlist = nullptr;
96
mSuperAllowlist = nullptr;
97
98
// Inform the SSM.
99
nsScriptSecurityManager* ssm =
100
nsScriptSecurityManager::GetScriptSecurityManager();
101
if (ssm) {
102
ssm->DeactivateDomainPolicy();
103
}
104
if (XRE_IsParentProcess()) {
105
BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
106
}
107
return NS_OK;
108
}
109
110
void DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone) {
111
aClone->active() = true;
112
mBlocklist->CloneSet(&aClone->blocklist());
113
mSuperBlocklist->CloneSet(&aClone->superBlocklist());
114
mAllowlist->CloneSet(&aClone->allowlist());
115
mSuperAllowlist->CloneSet(&aClone->superAllowlist());
116
}
117
118
static void CopyURIs(const nsTArray<RefPtr<nsIURI>>& aDomains,
119
nsIDomainSet* aSet) {
120
for (uint32_t i = 0; i < aDomains.Length(); i++) {
121
if (NS_WARN_IF(!aDomains[i])) {
122
continue;
123
}
124
aSet->Add(aDomains[i]);
125
}
126
}
127
128
void DomainPolicy::ApplyClone(const DomainPolicyClone* aClone) {
129
CopyURIs(aClone->blocklist(), mBlocklist);
130
CopyURIs(aClone->allowlist(), mAllowlist);
131
CopyURIs(aClone->superBlocklist(), mSuperBlocklist);
132
CopyURIs(aClone->superAllowlist(), mSuperAllowlist);
133
}
134
135
static already_AddRefed<nsIURI> GetCanonicalClone(nsIURI* aURI) {
136
nsCOMPtr<nsIURI> clone;
137
nsresult rv = NS_MutateURI(aURI)
138
.SetUserPass(EmptyCString())
139
.SetPathQueryRef(EmptyCString())
140
.Finalize(clone);
141
NS_ENSURE_SUCCESS(rv, nullptr);
142
return clone.forget();
143
}
144
145
NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
146
147
NS_IMETHODIMP
148
DomainSet::Add(nsIURI* aDomain) {
149
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
150
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
151
mHashTable.PutEntry(clone);
152
if (XRE_IsParentProcess()) {
153
return BroadcastDomainSetChange(mType, ADD_DOMAIN, aDomain);
154
}
155
156
return NS_OK;
157
}
158
159
NS_IMETHODIMP
160
DomainSet::Remove(nsIURI* aDomain) {
161
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
162
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
163
mHashTable.RemoveEntry(clone);
164
if (XRE_IsParentProcess()) {
165
return BroadcastDomainSetChange(mType, REMOVE_DOMAIN, aDomain);
166
}
167
168
return NS_OK;
169
}
170
171
NS_IMETHODIMP
172
DomainSet::Clear() {
173
mHashTable.Clear();
174
if (XRE_IsParentProcess()) {
175
return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);
176
}
177
178
return NS_OK;
179
}
180
181
NS_IMETHODIMP
182
DomainSet::Contains(nsIURI* aDomain, bool* aContains) {
183
*aContains = false;
184
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
185
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
186
*aContains = mHashTable.Contains(clone);
187
return NS_OK;
188
}
189
190
NS_IMETHODIMP
191
DomainSet::ContainsSuperDomain(nsIURI* aDomain, bool* aContains) {
192
*aContains = false;
193
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
194
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
195
nsAutoCString domain;
196
nsresult rv = clone->GetHost(domain);
197
NS_ENSURE_SUCCESS(rv, rv);
198
while (true) {
199
// Check the current domain.
200
if (mHashTable.Contains(clone)) {
201
*aContains = true;
202
return NS_OK;
203
}
204
205
// Chop off everything before the first dot, or break if there are no
206
// dots left.
207
int32_t index = domain.Find(".");
208
if (index == kNotFound) break;
209
domain.Assign(Substring(domain, index + 1));
210
rv = NS_MutateURI(clone).SetHost(domain).Finalize(clone);
211
NS_ENSURE_SUCCESS(rv, rv);
212
}
213
214
// No match.
215
return NS_OK;
216
}
217
218
void DomainSet::CloneSet(nsTArray<RefPtr<nsIURI>>* aDomains) {
219
for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
220
nsIURI* key = iter.Get()->GetKey();
221
aDomains->AppendElement(key);
222
}
223
}
224
225
} /* namespace mozilla */