forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathExpandedPrincipal.cpp
236 lines (204 loc) · 6.15 KB
/
ExpandedPrincipal.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ExpandedPrincipal.h"
#include "nsIClassInfoImpl.h"
using namespace mozilla;
NS_IMPL_CLASSINFO(ExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
NS_EXPANDEDPRINCIPAL_CID)
NS_IMPL_QUERY_INTERFACE_CI(ExpandedPrincipal,
nsIPrincipal,
nsIExpandedPrincipal)
NS_IMPL_CI_INTERFACE_GETTER(ExpandedPrincipal,
nsIPrincipal,
nsIExpandedPrincipal)
struct OriginComparator
{
bool LessThan(nsIPrincipal* a, nsIPrincipal* b) const
{
nsAutoCString originA;
DebugOnly<nsresult> rv = a->GetOrigin(originA);
MOZ_ASSERT(NS_SUCCEEDED(rv));
nsAutoCString originB;
rv = b->GetOrigin(originB);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return originA < originB;
}
bool Equals(nsIPrincipal* a, nsIPrincipal* b) const
{
nsAutoCString originA;
DebugOnly<nsresult> rv = a->GetOrigin(originA);
MOZ_ASSERT(NS_SUCCEEDED(rv));
nsAutoCString originB;
rv = b->GetOrigin(originB);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return a == b;
}
};
ExpandedPrincipal::ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList)
: BasePrincipal(eExpandedPrincipal)
{
// We force the principals to be sorted by origin so that ExpandedPrincipal
// origins can have a canonical form.
OriginComparator c;
for (size_t i = 0; i < aWhiteList.Length(); ++i) {
mPrincipals.InsertElementSorted(aWhiteList[i], c);
}
}
ExpandedPrincipal::~ExpandedPrincipal()
{ }
already_AddRefed<ExpandedPrincipal>
ExpandedPrincipal::Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList,
const OriginAttributes& aAttrs)
{
RefPtr<ExpandedPrincipal> ep = new ExpandedPrincipal(aWhiteList);
nsAutoCString origin;
origin.AssignLiteral("[Expanded Principal [");
for (size_t i = 0; i < ep->mPrincipals.Length(); ++i) {
if (i != 0) {
origin.AppendLiteral(", ");
}
nsAutoCString subOrigin;
DebugOnly<nsresult> rv = ep->mPrincipals.ElementAt(i)->GetOrigin(subOrigin);
MOZ_ASSERT(NS_SUCCEEDED(rv));
origin.Append(subOrigin);
}
origin.AppendLiteral("]]");
ep->FinishInit(origin, aAttrs);
return ep.forget();
}
NS_IMETHODIMP
ExpandedPrincipal::GetDomain(nsIURI** aDomain)
{
*aDomain = nullptr;
return NS_OK;
}
NS_IMETHODIMP
ExpandedPrincipal::SetDomain(nsIURI* aDomain)
{
return NS_OK;
}
bool
ExpandedPrincipal::SubsumesInternal(nsIPrincipal* aOther,
BasePrincipal::DocumentDomainConsideration aConsideration)
{
// If aOther is an ExpandedPrincipal too, we break it down into its component
// nsIPrincipals, and check subsumes on each one.
if (Cast(aOther)->Is<ExpandedPrincipal>()) {
auto* expanded = Cast(aOther)->As<ExpandedPrincipal>();
for (auto& other : expanded->WhiteList()) {
// Use SubsumesInternal rather than Subsumes here, since OriginAttribute
// checks are only done between non-expanded sub-principals, and we don't
// need to incur the extra virtual call overhead.
if (!SubsumesInternal(other, aConsideration)) {
return false;
}
}
return true;
}
// We're dealing with a regular principal. One of our principals must subsume
// it.
for (uint32_t i = 0; i < mPrincipals.Length(); ++i) {
if (Cast(mPrincipals[i])->Subsumes(aOther, aConsideration)) {
return true;
}
}
return false;
}
bool
ExpandedPrincipal::MayLoadInternal(nsIURI* uri)
{
for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
if (BasePrincipal::Cast(mPrincipals[i])->MayLoadInternal(uri)) {
return true;
}
}
return false;
}
NS_IMETHODIMP
ExpandedPrincipal::GetHashValue(uint32_t* result)
{
MOZ_CRASH("extended principal should never be used as key in a hash map");
}
NS_IMETHODIMP
ExpandedPrincipal::GetURI(nsIURI** aURI)
{
*aURI = nullptr;
return NS_OK;
}
const nsTArray<nsCOMPtr<nsIPrincipal>>&
ExpandedPrincipal::WhiteList()
{
return mPrincipals;
}
NS_IMETHODIMP
ExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
{
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
ExpandedPrincipal::GetAddonId(nsAString& aAddonId)
{
aAddonId.Truncate();
return NS_OK;
};
bool
ExpandedPrincipal::AddonHasPermission(const nsAtom* aPerm)
{
for (size_t i = 0; i < mPrincipals.Length(); ++i) {
if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
return true;
}
}
return false;
}
nsIPrincipal*
ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI)
{
if (aRequestedURI) {
// If a given sub-principal subsumes the given URI, use that principal for
// inheritance. In general, this only happens with certain CORS modes, loads
// with forced principal inheritance, and creation of XML documents from
// XMLHttpRequests or fetch requests. For URIs that normally inherit a
// principal (such as data: URIs), we fall back to the last principal in the
// whitelist.
for (const auto& principal : mPrincipals) {
if (Cast(principal)->MayLoadInternal(aRequestedURI)) {
return principal;
}
}
}
return mPrincipals.LastElement();
}
nsresult
ExpandedPrincipal::GetScriptLocation(nsACString& aStr)
{
aStr.AssignLiteral("[Expanded Principal [");
for (size_t i = 0; i < mPrincipals.Length(); ++i) {
if (i != 0) {
aStr.AppendLiteral(", ");
}
nsAutoCString spec;
nsresult rv =
nsJSPrincipals::get(mPrincipals.ElementAt(i))->GetScriptLocation(spec);
NS_ENSURE_SUCCESS(rv, rv);
aStr.Append(spec);
}
aStr.AppendLiteral("]]");
return NS_OK;
}
//////////////////////////////////////////
// Methods implementing nsISerializable //
//////////////////////////////////////////
NS_IMETHODIMP
ExpandedPrincipal::Read(nsIObjectInputStream* aStream)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ExpandedPrincipal::Write(nsIObjectOutputStream* aStream)
{
return NS_ERROR_NOT_IMPLEMENTED;
}