Bug 1647268 [wpt PR 24278] - Python 3: port xhr tests [part 6], a=testonly
[gecko.git] / caps / DomainPolicy.cpp
blobc4c9118dbe04a959cc5846d72aaf24a4fcfcfc16
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/. */
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"
13 namespace mozilla {
15 using namespace ipc;
16 using namespace dom;
18 NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
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.");
26 nsTArray<ContentParent*> parents;
27 ContentParent::GetAll(parents);
28 if (!parents.Length()) {
29 return NS_OK;
32 for (uint32_t i = 0; i < parents.Length(); i++) {
33 Unused << parents[i]->SendDomainSetChanged(aSetType, aChangeType, aDomain);
35 return NS_OK;
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);
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);
55 NS_IMETHODIMP
56 DomainPolicy::GetBlocklist(nsIDomainSet** aSet) {
57 nsCOMPtr<nsIDomainSet> set = mBlocklist.get();
58 set.forget(aSet);
59 return NS_OK;
62 NS_IMETHODIMP
63 DomainPolicy::GetSuperBlocklist(nsIDomainSet** aSet) {
64 nsCOMPtr<nsIDomainSet> set = mSuperBlocklist.get();
65 set.forget(aSet);
66 return NS_OK;
69 NS_IMETHODIMP
70 DomainPolicy::GetAllowlist(nsIDomainSet** aSet) {
71 nsCOMPtr<nsIDomainSet> set = mAllowlist.get();
72 set.forget(aSet);
73 return NS_OK;
76 NS_IMETHODIMP
77 DomainPolicy::GetSuperAllowlist(nsIDomainSet** aSet) {
78 nsCOMPtr<nsIDomainSet> set = mSuperAllowlist.get();
79 set.forget(aSet);
80 return NS_OK;
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();
92 // Null them out.
93 mBlocklist = nullptr;
94 mSuperBlocklist = nullptr;
95 mAllowlist = nullptr;
96 mSuperAllowlist = nullptr;
98 // Inform the SSM.
99 nsScriptSecurityManager* ssm =
100 nsScriptSecurityManager::GetScriptSecurityManager();
101 if (ssm) {
102 ssm->DeactivateDomainPolicy();
104 if (XRE_IsParentProcess()) {
105 BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
107 return NS_OK;
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());
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;
124 aSet->Add(aDomains[i]);
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);
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();
145 NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
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);
156 return NS_OK;
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);
168 return NS_OK;
171 NS_IMETHODIMP
172 DomainSet::Clear() {
173 mHashTable.Clear();
174 if (XRE_IsParentProcess()) {
175 return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);
178 return NS_OK;
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;
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;
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);
214 // No match.
215 return NS_OK;
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);
225 } /* namespace mozilla */