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 "nsIMessageManager.h"
12 #include "nsIURIMutator.h"
13 #include "nsScriptSecurityManager.h"
20 NS_IMPL_ISUPPORTS(DomainPolicy
, nsIDomainPolicy
)
22 static nsresult
BroadcastDomainSetChange(DomainSetType aSetType
,
23 DomainSetChangeType aChangeType
,
24 nsIURI
* aDomain
= nullptr) {
25 MOZ_ASSERT(XRE_IsParentProcess(),
26 "DomainPolicy should only be exposed to the chrome process.");
28 nsTArray
<ContentParent
*> parents
;
29 ContentParent::GetAll(parents
);
30 if (!parents
.Length()) {
35 SerializeURI(aDomain
, uri
);
37 for (uint32_t i
= 0; i
< parents
.Length(); i
++) {
38 Unused
<< parents
[i
]->SendDomainSetChanged(aSetType
, aChangeType
, uri
);
43 DomainPolicy::DomainPolicy()
44 : mBlocklist(new DomainSet(BLOCKLIST
)),
45 mSuperBlocklist(new DomainSet(SUPER_BLOCKLIST
)),
46 mAllowlist(new DomainSet(ALLOWLIST
)),
47 mSuperAllowlist(new DomainSet(SUPER_ALLOWLIST
)) {
48 if (XRE_IsParentProcess()) {
49 BroadcastDomainSetChange(NO_TYPE
, ACTIVATE_POLICY
);
53 DomainPolicy::~DomainPolicy() {
54 // The SSM holds a strong ref to the DomainPolicy until Deactivate() is
55 // invoked, so we should never hit the destructor until that happens.
56 MOZ_ASSERT(!mBlocklist
&& !mSuperBlocklist
&& !mAllowlist
&&
61 DomainPolicy::GetBlocklist(nsIDomainSet
** aSet
) {
62 nsCOMPtr
<nsIDomainSet
> set
= mBlocklist
.get();
68 DomainPolicy::GetSuperBlocklist(nsIDomainSet
** aSet
) {
69 nsCOMPtr
<nsIDomainSet
> set
= mSuperBlocklist
.get();
75 DomainPolicy::GetAllowlist(nsIDomainSet
** aSet
) {
76 nsCOMPtr
<nsIDomainSet
> set
= mAllowlist
.get();
82 DomainPolicy::GetSuperAllowlist(nsIDomainSet
** aSet
) {
83 nsCOMPtr
<nsIDomainSet
> set
= mSuperAllowlist
.get();
89 DomainPolicy::Deactivate() {
90 // Clear the hashtables first to free up memory, since script might
91 // hold the doomed sets alive indefinitely.
93 mSuperBlocklist
->Clear();
95 mSuperAllowlist
->Clear();
99 mSuperBlocklist
= nullptr;
100 mAllowlist
= nullptr;
101 mSuperAllowlist
= nullptr;
104 nsScriptSecurityManager
* ssm
=
105 nsScriptSecurityManager::GetScriptSecurityManager();
107 ssm
->DeactivateDomainPolicy();
109 if (XRE_IsParentProcess()) {
110 BroadcastDomainSetChange(NO_TYPE
, DEACTIVATE_POLICY
);
115 void DomainPolicy::CloneDomainPolicy(DomainPolicyClone
* aClone
) {
116 aClone
->active() = true;
117 mBlocklist
->CloneSet(&aClone
->blocklist());
118 mSuperBlocklist
->CloneSet(&aClone
->superBlocklist());
119 mAllowlist
->CloneSet(&aClone
->allowlist());
120 mSuperAllowlist
->CloneSet(&aClone
->superAllowlist());
123 static void CopyURIs(const InfallibleTArray
<URIParams
>& aDomains
,
124 nsIDomainSet
* aSet
) {
125 for (uint32_t i
= 0; i
< aDomains
.Length(); i
++) {
126 nsCOMPtr
<nsIURI
> uri
= DeserializeURI(aDomains
[i
]);
131 void DomainPolicy::ApplyClone(const DomainPolicyClone
* aClone
) {
132 CopyURIs(aClone
->blocklist(), mBlocklist
);
133 CopyURIs(aClone
->allowlist(), mAllowlist
);
134 CopyURIs(aClone
->superBlocklist(), mSuperBlocklist
);
135 CopyURIs(aClone
->superAllowlist(), mSuperAllowlist
);
138 static already_AddRefed
<nsIURI
> GetCanonicalClone(nsIURI
* aURI
) {
139 nsCOMPtr
<nsIURI
> clone
;
140 nsresult rv
= NS_MutateURI(aURI
)
141 .SetUserPass(EmptyCString())
142 .SetPathQueryRef(EmptyCString())
144 NS_ENSURE_SUCCESS(rv
, nullptr);
145 return clone
.forget();
148 NS_IMPL_ISUPPORTS(DomainSet
, nsIDomainSet
)
151 DomainSet::Add(nsIURI
* aDomain
) {
152 nsCOMPtr
<nsIURI
> clone
= GetCanonicalClone(aDomain
);
153 NS_ENSURE_TRUE(clone
, NS_ERROR_FAILURE
);
154 mHashTable
.PutEntry(clone
);
155 if (XRE_IsParentProcess())
156 return BroadcastDomainSetChange(mType
, ADD_DOMAIN
, aDomain
);
162 DomainSet::Remove(nsIURI
* aDomain
) {
163 nsCOMPtr
<nsIURI
> clone
= GetCanonicalClone(aDomain
);
164 NS_ENSURE_TRUE(clone
, NS_ERROR_FAILURE
);
165 mHashTable
.RemoveEntry(clone
);
166 if (XRE_IsParentProcess())
167 return BroadcastDomainSetChange(mType
, REMOVE_DOMAIN
, aDomain
);
175 if (XRE_IsParentProcess())
176 return BroadcastDomainSetChange(mType
, CLEAR_DOMAINS
);
182 DomainSet::Contains(nsIURI
* aDomain
, bool* aContains
) {
184 nsCOMPtr
<nsIURI
> clone
= GetCanonicalClone(aDomain
);
185 NS_ENSURE_TRUE(clone
, NS_ERROR_FAILURE
);
186 *aContains
= mHashTable
.Contains(clone
);
191 DomainSet::ContainsSuperDomain(nsIURI
* aDomain
, bool* aContains
) {
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
);
199 // Check the current domain.
200 if (mHashTable
.Contains(clone
)) {
205 // Chop off everything before the first dot, or break if there are no
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
);
218 void DomainSet::CloneSet(InfallibleTArray
<URIParams
>* aDomains
) {
219 for (auto iter
= mHashTable
.Iter(); !iter
.Done(); iter
.Next()) {
220 nsIURI
* key
= iter
.Get()->GetKey();
223 SerializeURI(key
, uri
);
225 aDomains
->AppendElement(uri
);
229 } /* namespace mozilla */