Bug 1847324 - Add use counter for rewritable YouTube flash embeds r=emilio
[gecko.git] / caps / DomainPolicy.cpp
blob65ad3d8df4e5fe59e362687d633977a382917abb
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 "nsIURIMutator.h"
12 #include "nsScriptSecurityManager.h"
14 namespace mozilla {
16 using namespace ipc;
17 using namespace dom;
19 NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
21 static nsresult BroadcastDomainSetChange(DomainSetType aSetType,
22 DomainSetChangeType aChangeType,
23 nsIURI* aDomain = nullptr) {
24 MOZ_ASSERT(XRE_IsParentProcess(),
25 "DomainPolicy should only be exposed to the chrome process.");
27 nsTArray<ContentParent*> parents;
28 ContentParent::GetAll(parents);
29 if (!parents.Length()) {
30 return NS_OK;
33 for (uint32_t i = 0; i < parents.Length(); i++) {
34 Unused << parents[i]->SendDomainSetChanged(aSetType, aChangeType, aDomain);
36 return NS_OK;
39 DomainPolicy::DomainPolicy()
40 : mBlocklist(new DomainSet(BLOCKLIST)),
41 mSuperBlocklist(new DomainSet(SUPER_BLOCKLIST)),
42 mAllowlist(new DomainSet(ALLOWLIST)),
43 mSuperAllowlist(new DomainSet(SUPER_ALLOWLIST)) {
44 if (XRE_IsParentProcess()) {
45 BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
49 DomainPolicy::~DomainPolicy() {
50 // The SSM holds a strong ref to the DomainPolicy until Deactivate() is
51 // invoked, so we should never hit the destructor until that happens.
52 MOZ_ASSERT(!mBlocklist && !mSuperBlocklist && !mAllowlist &&
53 !mSuperAllowlist);
56 NS_IMETHODIMP
57 DomainPolicy::GetBlocklist(nsIDomainSet** aSet) {
58 nsCOMPtr<nsIDomainSet> set = mBlocklist.get();
59 set.forget(aSet);
60 return NS_OK;
63 NS_IMETHODIMP
64 DomainPolicy::GetSuperBlocklist(nsIDomainSet** aSet) {
65 nsCOMPtr<nsIDomainSet> set = mSuperBlocklist.get();
66 set.forget(aSet);
67 return NS_OK;
70 NS_IMETHODIMP
71 DomainPolicy::GetAllowlist(nsIDomainSet** aSet) {
72 nsCOMPtr<nsIDomainSet> set = mAllowlist.get();
73 set.forget(aSet);
74 return NS_OK;
77 NS_IMETHODIMP
78 DomainPolicy::GetSuperAllowlist(nsIDomainSet** aSet) {
79 nsCOMPtr<nsIDomainSet> set = mSuperAllowlist.get();
80 set.forget(aSet);
81 return NS_OK;
84 NS_IMETHODIMP
85 DomainPolicy::Deactivate() {
86 // Clear the hashtables first to free up memory, since script might
87 // hold the doomed sets alive indefinitely.
88 mBlocklist->Clear();
89 mSuperBlocklist->Clear();
90 mAllowlist->Clear();
91 mSuperAllowlist->Clear();
93 // Null them out.
94 mBlocklist = nullptr;
95 mSuperBlocklist = nullptr;
96 mAllowlist = nullptr;
97 mSuperAllowlist = nullptr;
99 // Inform the SSM.
100 nsScriptSecurityManager* ssm =
101 nsScriptSecurityManager::GetScriptSecurityManager();
102 if (ssm) {
103 ssm->DeactivateDomainPolicy();
105 if (XRE_IsParentProcess()) {
106 BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
108 return NS_OK;
111 void DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone) {
112 aClone->active() = true;
113 mBlocklist->CloneSet(&aClone->blocklist());
114 mSuperBlocklist->CloneSet(&aClone->superBlocklist());
115 mAllowlist->CloneSet(&aClone->allowlist());
116 mSuperAllowlist->CloneSet(&aClone->superAllowlist());
119 static void CopyURIs(const nsTArray<RefPtr<nsIURI>>& aDomains,
120 nsIDomainSet* aSet) {
121 for (uint32_t i = 0; i < aDomains.Length(); i++) {
122 if (NS_WARN_IF(!aDomains[i])) {
123 continue;
125 aSet->Add(aDomains[i]);
129 void DomainPolicy::ApplyClone(const DomainPolicyClone* aClone) {
130 CopyURIs(aClone->blocklist(), mBlocklist);
131 CopyURIs(aClone->allowlist(), mAllowlist);
132 CopyURIs(aClone->superBlocklist(), mSuperBlocklist);
133 CopyURIs(aClone->superAllowlist(), mSuperAllowlist);
136 static already_AddRefed<nsIURI> GetCanonicalClone(nsIURI* aURI) {
137 nsCOMPtr<nsIURI> clone;
138 nsresult rv =
139 NS_MutateURI(aURI).SetUserPass(""_ns).SetPathQueryRef(""_ns).Finalize(
140 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.Insert(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.Remove(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 AppendToArray(*aDomains, mHashTable);
222 } /* namespace mozilla */