1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 sts=2 ts=2 et 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/. */
8 * This is the principal that has no rights and can't be accessed by
9 * anything other than itself and chrome; null principals are not
10 * same-origin with anything but themselves.
13 #include "mozilla/ArrayUtils.h"
15 #include "mozilla/dom/BlobURLProtocolHandler.h"
16 #include "mozilla/StaticPrefs_network.h"
17 #include "nsDocShell.h"
18 #include "NullPrincipal.h"
19 #include "DefaultURI.h"
20 #include "nsSimpleURI.h"
22 #include "nsIClassInfoImpl.h"
25 #include "ContentPrincipal.h"
26 #include "nsScriptSecurityManager.h"
28 #include "nsIObjectInputStream.h"
29 #include "mozilla/GkRustUtils.h"
31 #include "json/json.h"
33 using namespace mozilla
;
35 NS_IMPL_CLASSINFO(NullPrincipal
, nullptr, nsIClassInfo::MAIN_THREAD_ONLY
,
37 NS_IMPL_QUERY_INTERFACE_CI(NullPrincipal
, nsIPrincipal
)
38 NS_IMPL_CI_INTERFACE_GETTER(NullPrincipal
, nsIPrincipal
)
40 NullPrincipal::NullPrincipal(nsIURI
* aURI
, const nsACString
& aOriginNoSuffix
,
41 const OriginAttributes
& aOriginAttributes
)
42 : BasePrincipal(eNullPrincipal
, aOriginNoSuffix
, aOriginAttributes
),
46 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
47 nsIPrincipal
* aInheritFrom
) {
48 MOZ_ASSERT(aInheritFrom
);
49 return CreateInternal(Cast(aInheritFrom
)->OriginAttributesRef(), false,
50 nullptr, aInheritFrom
);
54 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
55 nsIDocShell
* aDocShell
, bool aIsFirstParty
) {
56 MOZ_ASSERT(aDocShell
);
58 OriginAttributes attrs
= nsDocShell::Cast(aDocShell
)->GetOriginAttributes();
59 return CreateWithInheritedAttributes(attrs
, aIsFirstParty
);
63 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
64 const OriginAttributes
& aOriginAttributes
, bool aIsFirstParty
) {
65 return CreateInternal(aOriginAttributes
, aIsFirstParty
);
69 already_AddRefed
<NullPrincipal
> NullPrincipal::Create(
70 const OriginAttributes
& aOriginAttributes
, nsIURI
* aURI
) {
71 return CreateInternal(aOriginAttributes
, false, aURI
);
75 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithoutOriginAttributes() {
76 return NullPrincipal::Create(OriginAttributes(), nullptr);
79 already_AddRefed
<nsIURI
> NullPrincipal::CreateURI(
80 nsIPrincipal
* aPrecursor
, const nsID
* aNullPrincipalID
) {
81 nsCOMPtr
<nsIURIMutator
> iMutator
;
82 if (StaticPrefs::network_url_useDefaultURI()) {
83 iMutator
= new mozilla::net::DefaultURI::Mutator();
85 iMutator
= new mozilla::net::nsSimpleURI::Mutator();
88 nsAutoCStringN
<NSID_LENGTH
> uuid
;
89 if (aNullPrincipalID
) {
90 // FIXME: When D119267 lands, clean this up on top of those changes.
91 aNullPrincipalID
->ToProvidedString(*reinterpret_cast<char(*)[NSID_LENGTH
]>(
92 uuid
.GetMutableData(NSID_LENGTH
- 1).data()));
94 GkRustUtils::GenerateUUID(uuid
);
97 NS_MutateURI
mutator(iMutator
);
98 mutator
.SetSpec(NS_NULLPRINCIPAL_SCHEME
":"_ns
+ uuid
);
100 // If there's a precursor URI, encode it in the null principal URI's query.
102 nsAutoCString precursorOrigin
;
103 switch (BasePrincipal::Cast(aPrecursor
)->Kind()) {
105 // If the precursor null principal has a precursor, inherit it.
106 if (nsCOMPtr
<nsIURI
> nullPrecursorURI
= aPrecursor
->GetURI()) {
107 MOZ_ALWAYS_SUCCEEDS(nullPrecursorURI
->GetQuery(precursorOrigin
));
110 case eContentPrincipal
:
111 MOZ_ALWAYS_SUCCEEDS(aPrecursor
->GetOriginNoSuffix(precursorOrigin
));
114 // For now, we won't track expanded or system principal precursors. We may
115 // want to track expanded principal precursors in the future, but it's
116 // unlikely we'll want to track system principal precursors.
117 case eExpandedPrincipal
:
118 case eSystemPrincipal
:
121 if (!precursorOrigin
.IsEmpty()) {
122 mutator
.SetQuery(precursorOrigin
);
126 nsCOMPtr
<nsIURI
> uri
;
127 MOZ_ALWAYS_SUCCEEDS(mutator
.Finalize(getter_AddRefs(uri
)));
131 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateInternal(
132 const OriginAttributes
& aOriginAttributes
, bool aIsFirstParty
, nsIURI
* aURI
,
133 nsIPrincipal
* aPrecursor
) {
134 MOZ_ASSERT_IF(aPrecursor
, !aURI
);
135 nsCOMPtr
<nsIURI
> uri
= aURI
;
137 uri
= NullPrincipal::CreateURI(aPrecursor
);
140 MOZ_RELEASE_ASSERT(uri
->SchemeIs(NS_NULLPRINCIPAL_SCHEME
));
142 nsAutoCString originNoSuffix
;
143 DebugOnly
<nsresult
> rv
= uri
->GetSpec(originNoSuffix
);
144 MOZ_ASSERT(NS_SUCCEEDED(rv
));
146 OriginAttributes
attrs(aOriginAttributes
);
148 // The FirstPartyDomain attribute will not include information about the
151 rv
= uri
->GetFilePath(path
);
152 MOZ_ASSERT(NS_SUCCEEDED(rv
));
154 // remove the '{}' characters from both ends.
155 path
.Mid(path
, 1, path
.Length() - 2);
156 path
.AppendLiteral(".mozilla");
157 attrs
.SetFirstPartyDomain(true, path
);
160 RefPtr
<NullPrincipal
> nullPrin
=
161 new NullPrincipal(uri
, originNoSuffix
, attrs
);
162 return nullPrin
.forget();
165 nsresult
NullPrincipal::GetScriptLocation(nsACString
& aStr
) {
166 return mURI
->GetSpec(aStr
);
170 * nsIPrincipal implementation
173 uint32_t NullPrincipal::GetHashValue() { return (NS_PTR_TO_INT32(this) >> 2); }
176 NullPrincipal::GetURI(nsIURI
** aURI
) {
177 nsCOMPtr
<nsIURI
> uri
= mURI
;
182 NullPrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult
) {
188 NullPrincipal::GetDomain(nsIURI
** aDomain
) {
189 nsCOMPtr
<nsIURI
> uri
= mURI
;
195 NullPrincipal::SetDomain(nsIURI
* aDomain
) {
196 // I think the right thing to do here is to just throw... Silently failing
197 // seems counterproductive.
198 return NS_ERROR_NOT_AVAILABLE
;
201 bool NullPrincipal::MayLoadInternal(nsIURI
* aURI
) {
202 // Also allow the load if we are the principal of the URI being checked.
203 nsCOMPtr
<nsIPrincipal
> blobPrincipal
;
204 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
205 aURI
, getter_AddRefs(blobPrincipal
))) {
206 MOZ_ASSERT(blobPrincipal
);
207 return SubsumesInternal(blobPrincipal
,
208 BasePrincipal::ConsiderDocumentDomain
);
215 NullPrincipal::GetBaseDomain(nsACString
& aBaseDomain
) {
216 // For a null principal, we use our unique uuid as the base domain.
217 return mURI
->GetPathQueryRef(aBaseDomain
);
221 NullPrincipal::GetAddonId(nsAString
& aAddonId
) {
227 * nsISerializable implementation
230 NullPrincipal::Deserializer::Read(nsIObjectInputStream
* aStream
) {
232 nsresult rv
= aStream
->ReadCString(spec
);
233 NS_ENSURE_SUCCESS(rv
, rv
);
235 nsCOMPtr
<nsIURI
> uri
;
236 rv
= NS_NewURI(getter_AddRefs(uri
), spec
);
237 NS_ENSURE_SUCCESS(rv
, rv
);
239 nsAutoCString suffix
;
240 rv
= aStream
->ReadCString(suffix
);
241 NS_ENSURE_SUCCESS(rv
, rv
);
243 OriginAttributes attrs
;
244 bool ok
= attrs
.PopulateFromSuffix(suffix
);
245 NS_ENSURE_TRUE(ok
, NS_ERROR_FAILURE
);
247 mPrincipal
= NullPrincipal::Create(attrs
, uri
);
248 NS_ENSURE_TRUE(mPrincipal
, NS_ERROR_FAILURE
);
253 nsresult
NullPrincipal::PopulateJSONObject(Json::Value
& aObject
) {
254 nsAutoCString principalURI
;
255 nsresult rv
= mURI
->GetSpec(principalURI
);
256 NS_ENSURE_SUCCESS(rv
, rv
);
257 aObject
[std::to_string(eSpec
)] = principalURI
.get();
259 nsAutoCString suffix
;
260 OriginAttributesRef().CreateSuffix(suffix
);
261 if (suffix
.Length() > 0) {
262 aObject
[std::to_string(eSuffix
)] = suffix
.get();
268 already_AddRefed
<BasePrincipal
> NullPrincipal::FromProperties(
269 nsTArray
<NullPrincipal::KeyVal
>& aFields
) {
270 MOZ_ASSERT(aFields
.Length() == eMax
+ 1, "Must have all the keys");
272 nsCOMPtr
<nsIURI
> uri
;
273 OriginAttributes attrs
;
275 // The odd structure here is to make the code to not compile
276 // if all the switch enum cases haven't been codified
277 for (const auto& field
: aFields
) {
279 case NullPrincipal::eSpec
:
280 if (!field
.valueWasSerialized
) {
282 "Null principals require a spec URI in serialized JSON");
285 rv
= NS_NewURI(getter_AddRefs(uri
), field
.value
);
286 NS_ENSURE_SUCCESS(rv
, nullptr);
288 case NullPrincipal::eSuffix
:
289 bool ok
= attrs
.PopulateFromSuffix(field
.value
);
298 MOZ_ASSERT(false, "No URI deserialized");
302 return NullPrincipal::Create(attrs
, uri
);
306 NullPrincipal::GetPrecursorPrincipal(nsIPrincipal
** aPrincipal
) {
307 *aPrincipal
= nullptr;
310 if (NS_FAILED(mURI
->GetQuery(query
)) || query
.IsEmpty()) {
314 nsCOMPtr
<nsIURI
> precursorURI
;
315 if (NS_FAILED(NS_NewURI(getter_AddRefs(precursorURI
), query
))) {
316 MOZ_ASSERT_UNREACHABLE(
317 "Failed to parse precursor from nullprincipal query");
321 // If our precursor is another null principal, re-construct it. This can
322 // happen if a null principal without a precursor causes another principal to
324 if (precursorURI
->SchemeIs(NS_NULLPRINCIPAL_SCHEME
)) {
326 nsAutoCString precursorQuery
;
327 precursorURI
->GetQuery(precursorQuery
);
328 MOZ_ASSERT(precursorQuery
.IsEmpty(),
329 "Null principal with nested precursors?");
332 NullPrincipal::Create(OriginAttributesRef(), precursorURI
).take();
336 RefPtr
<BasePrincipal
> contentPrincipal
=
337 BasePrincipal::CreateContentPrincipal(precursorURI
,
338 OriginAttributesRef());
339 // If `CreateContentPrincipal` failed, it will create a new NullPrincipal and
340 // return that instead. We only want to return real content principals here.
341 if (!contentPrincipal
|| !contentPrincipal
->Is
<ContentPrincipal
>()) {
344 contentPrincipal
.forget(aPrincipal
);