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 "nsDocShell.h"
16 #include "NullPrincipal.h"
17 #include "NullPrincipalURI.h"
19 #include "nsIClassInfoImpl.h"
22 #include "ContentPrincipal.h"
23 #include "nsScriptSecurityManager.h"
26 #include "json/json.h"
28 using namespace mozilla
;
30 NS_IMPL_CLASSINFO(NullPrincipal
, nullptr, nsIClassInfo::MAIN_THREAD_ONLY
,
32 NS_IMPL_QUERY_INTERFACE_CI(NullPrincipal
, nsIPrincipal
, nsISerializable
)
33 NS_IMPL_CI_INTERFACE_GETTER(NullPrincipal
, nsIPrincipal
, nsISerializable
)
36 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
37 nsIPrincipal
* aInheritFrom
) {
38 MOZ_ASSERT(aInheritFrom
);
39 return CreateWithInheritedAttributes(
40 Cast(aInheritFrom
)->OriginAttributesRef(), false);
44 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
45 nsIDocShell
* aDocShell
, bool aIsFirstParty
) {
46 MOZ_ASSERT(aDocShell
);
48 OriginAttributes attrs
= nsDocShell::Cast(aDocShell
)->GetOriginAttributes();
49 return CreateWithInheritedAttributes(attrs
, aIsFirstParty
);
53 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
54 const OriginAttributes
& aOriginAttributes
, bool aIsFirstParty
) {
55 RefPtr
<NullPrincipal
> nullPrin
= new NullPrincipal();
56 nullPrin
->Init(aOriginAttributes
, aIsFirstParty
);
57 return nullPrin
.forget();
61 already_AddRefed
<NullPrincipal
> NullPrincipal::Create(
62 const OriginAttributes
& aOriginAttributes
, nsIURI
* aURI
) {
63 RefPtr
<NullPrincipal
> nullPrin
= new NullPrincipal();
64 nsresult rv
= nullPrin
->Init(aOriginAttributes
, aURI
);
65 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv
));
67 return nullPrin
.forget();
71 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithoutOriginAttributes() {
72 return NullPrincipal::Create(OriginAttributes(), nullptr);
75 nsresult
NullPrincipal::Init(const OriginAttributes
& aOriginAttributes
,
79 nsresult rv
= aURI
->GetScheme(scheme
);
80 NS_ENSURE_SUCCESS(rv
, rv
);
82 NS_ENSURE_TRUE(scheme
.EqualsLiteral(NS_NULLPRINCIPAL_SCHEME
),
83 NS_ERROR_NOT_AVAILABLE
);
87 mURI
= new NullPrincipalURI();
90 nsAutoCString originNoSuffix
;
91 DebugOnly
<nsresult
> rv
= mURI
->GetSpec(originNoSuffix
);
92 MOZ_ASSERT(NS_SUCCEEDED(rv
));
94 FinishInit(originNoSuffix
, aOriginAttributes
);
99 void NullPrincipal::Init(const OriginAttributes
& aOriginAttributes
,
100 bool aIsFirstParty
) {
101 mURI
= new NullPrincipalURI();
103 nsAutoCString originNoSuffix
;
104 DebugOnly
<nsresult
> rv
= mURI
->GetSpec(originNoSuffix
);
105 MOZ_ASSERT(NS_SUCCEEDED(rv
));
108 rv
= mURI
->GetPathQueryRef(path
);
109 MOZ_ASSERT(NS_SUCCEEDED(rv
));
111 OriginAttributes
attrs(aOriginAttributes
);
113 // remove the '{}' characters from both ends.
114 path
.Mid(path
, 1, path
.Length() - 2);
115 path
.AppendLiteral(".mozilla");
116 attrs
.SetFirstPartyDomain(true, path
);
119 FinishInit(originNoSuffix
, attrs
);
122 nsresult
NullPrincipal::GetScriptLocation(nsACString
& aStr
) {
123 return mURI
->GetSpec(aStr
);
127 * nsIPrincipal implementation
130 uint32_t NullPrincipal::GetHashValue() { return (NS_PTR_TO_INT32(this) >> 2); }
133 NullPrincipal::GetURI(nsIURI
** aURI
) {
134 nsCOMPtr
<nsIURI
> uri
= mURI
;
139 NullPrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult
) {
145 NullPrincipal::GetDomain(nsIURI
** aDomain
) {
146 nsCOMPtr
<nsIURI
> uri
= mURI
;
152 NullPrincipal::SetDomain(nsIURI
* aDomain
) {
153 // I think the right thing to do here is to just throw... Silently failing
154 // seems counterproductive.
155 return NS_ERROR_NOT_AVAILABLE
;
158 bool NullPrincipal::MayLoadInternal(nsIURI
* aURI
) {
159 // Also allow the load if we are the principal of the URI being checked.
160 nsCOMPtr
<nsIPrincipal
> blobPrincipal
;
161 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
162 aURI
, getter_AddRefs(blobPrincipal
))) {
163 MOZ_ASSERT(blobPrincipal
);
164 return SubsumesInternal(blobPrincipal
,
165 BasePrincipal::ConsiderDocumentDomain
);
172 NullPrincipal::GetBaseDomain(nsACString
& aBaseDomain
) {
173 // For a null principal, we use our unique uuid as the base domain.
174 return mURI
->GetPathQueryRef(aBaseDomain
);
178 NullPrincipal::GetAddonId(nsAString
& aAddonId
) {
184 * nsISerializable implementation
187 NullPrincipal::Read(nsIObjectInputStream
* aStream
) {
188 // Note - NullPrincipal use NS_GENERIC_FACTORY_CONSTRUCTOR_INIT, which means
189 // that the Init() method has already been invoked by the time we deserialize.
190 // This is in contrast to ContentPrincipal, which uses
191 // NS_GENERIC_FACTORY_CONSTRUCTOR, in which case ::Read needs to invoke
195 nsresult rv
= aStream
->ReadCString(spec
);
196 NS_ENSURE_SUCCESS(rv
, rv
);
198 nsCOMPtr
<nsIURI
> uri
;
199 rv
= NS_NewURI(getter_AddRefs(uri
), spec
);
200 NS_ENSURE_SUCCESS(rv
, rv
);
202 nsAutoCString suffix
;
203 rv
= aStream
->ReadCString(suffix
);
204 NS_ENSURE_SUCCESS(rv
, rv
);
206 OriginAttributes attrs
;
207 bool ok
= attrs
.PopulateFromSuffix(suffix
);
208 NS_ENSURE_TRUE(ok
, NS_ERROR_FAILURE
);
210 return Init(attrs
, uri
);
214 NullPrincipal::Write(nsIObjectOutputStream
* aStream
) {
215 // Read is used still for legacy principals
216 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
220 nsresult
NullPrincipal::PopulateJSONObject(Json::Value
& aObject
) {
221 nsAutoCString principalURI
;
222 nsresult rv
= mURI
->GetSpec(principalURI
);
223 NS_ENSURE_SUCCESS(rv
, rv
);
224 MOZ_ASSERT(principalURI
.Length() ==
225 NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME
":").Length() +
227 "Length of the URI should be: (scheme, uuid, - nullptr)");
228 aObject
[std::to_string(eSpec
)] = principalURI
.get();
230 nsAutoCString suffix
;
231 OriginAttributesRef().CreateSuffix(suffix
);
232 if (suffix
.Length() > 0) {
233 aObject
[std::to_string(eSuffix
)] = suffix
.get();
239 already_AddRefed
<BasePrincipal
> NullPrincipal::FromProperties(
240 nsTArray
<NullPrincipal::KeyVal
>& aFields
) {
241 MOZ_ASSERT(aFields
.Length() == eMax
+ 1, "Must have all the keys");
243 nsCOMPtr
<nsIURI
> uri
;
244 OriginAttributes attrs
;
246 // The odd structure here is to make the code to not compile
247 // if all the switch enum cases haven't been codified
248 for (const auto& field
: aFields
) {
250 case NullPrincipal::eSpec
:
251 if (!field
.valueWasSerialized
) {
253 "Null principals require a spec URI in serialized JSON");
256 rv
= NS_NewURI(getter_AddRefs(uri
), field
.value
);
257 NS_ENSURE_SUCCESS(rv
, nullptr);
259 case NullPrincipal::eSuffix
:
260 bool ok
= attrs
.PopulateFromSuffix(field
.value
);
269 MOZ_ASSERT(false, "No URI deserialized");
273 RefPtr
<NullPrincipal
> nullPrincipal
= new NullPrincipal();
274 rv
= nullPrincipal
->Init(attrs
, uri
);
278 return nullPrincipal
.forget();