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 "nsIScriptSecurityManager.h"
23 #include "ContentPrincipal.h"
24 #include "nsScriptSecurityManager.h"
27 #include "json/json.h"
29 using namespace mozilla
;
31 NS_IMPL_CLASSINFO(NullPrincipal
, nullptr, nsIClassInfo::MAIN_THREAD_ONLY
,
33 NS_IMPL_QUERY_INTERFACE_CI(NullPrincipal
, nsIPrincipal
, nsISerializable
)
34 NS_IMPL_CI_INTERFACE_GETTER(NullPrincipal
, nsIPrincipal
, nsISerializable
)
37 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
38 nsIPrincipal
* aInheritFrom
) {
39 MOZ_ASSERT(aInheritFrom
);
40 return CreateWithInheritedAttributes(
41 Cast(aInheritFrom
)->OriginAttributesRef(), false);
45 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
46 nsIDocShell
* aDocShell
, bool aIsFirstParty
) {
47 MOZ_ASSERT(aDocShell
);
49 OriginAttributes attrs
= nsDocShell::Cast(aDocShell
)->GetOriginAttributes();
50 return CreateWithInheritedAttributes(attrs
, aIsFirstParty
);
54 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithInheritedAttributes(
55 const OriginAttributes
& aOriginAttributes
, bool aIsFirstParty
) {
56 RefPtr
<NullPrincipal
> nullPrin
= new NullPrincipal();
57 nsresult rv
= nullPrin
->Init(aOriginAttributes
, aIsFirstParty
);
58 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv
));
59 return nullPrin
.forget();
63 already_AddRefed
<NullPrincipal
> NullPrincipal::Create(
64 const OriginAttributes
& aOriginAttributes
, nsIURI
* aURI
) {
65 RefPtr
<NullPrincipal
> nullPrin
= new NullPrincipal();
66 nsresult rv
= nullPrin
->Init(aOriginAttributes
, aURI
);
67 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv
));
69 return nullPrin
.forget();
73 already_AddRefed
<NullPrincipal
> NullPrincipal::CreateWithoutOriginAttributes() {
74 return NullPrincipal::Create(OriginAttributes(), nullptr);
77 nsresult
NullPrincipal::Init(const OriginAttributes
& aOriginAttributes
,
81 nsresult rv
= aURI
->GetScheme(scheme
);
82 NS_ENSURE_SUCCESS(rv
, rv
);
84 NS_ENSURE_TRUE(scheme
.EqualsLiteral(NS_NULLPRINCIPAL_SCHEME
),
85 NS_ERROR_NOT_AVAILABLE
);
89 mURI
= NullPrincipalURI::Create();
90 NS_ENSURE_TRUE(mURI
, NS_ERROR_NOT_AVAILABLE
);
93 nsAutoCString originNoSuffix
;
94 DebugOnly
<nsresult
> rv
= mURI
->GetSpec(originNoSuffix
);
95 MOZ_ASSERT(NS_SUCCEEDED(rv
));
97 FinishInit(originNoSuffix
, aOriginAttributes
);
102 nsresult
NullPrincipal::Init(const OriginAttributes
& aOriginAttributes
,
103 bool aIsFirstParty
) {
104 mURI
= NullPrincipalURI::Create();
105 NS_ENSURE_TRUE(mURI
, NS_ERROR_NOT_AVAILABLE
);
107 nsAutoCString originNoSuffix
;
108 DebugOnly
<nsresult
> rv
= mURI
->GetSpec(originNoSuffix
);
109 MOZ_ASSERT(NS_SUCCEEDED(rv
));
112 rv
= mURI
->GetPathQueryRef(path
);
113 MOZ_ASSERT(NS_SUCCEEDED(rv
));
115 OriginAttributes
attrs(aOriginAttributes
);
117 // remove the '{}' characters from both ends.
118 path
.Mid(path
, 1, path
.Length() - 2);
119 path
.AppendLiteral(".mozilla");
120 attrs
.SetFirstPartyDomain(true, path
);
123 FinishInit(originNoSuffix
, attrs
);
128 nsresult
NullPrincipal::GetScriptLocation(nsACString
& aStr
) {
129 return mURI
->GetSpec(aStr
);
133 * nsIPrincipal implementation
136 uint32_t NullPrincipal::GetHashValue() { return (NS_PTR_TO_INT32(this) >> 2); }
139 NullPrincipal::GetURI(nsIURI
** aURI
) {
140 nsCOMPtr
<nsIURI
> uri
= mURI
;
146 NullPrincipal::GetDomain(nsIURI
** aDomain
) {
147 nsCOMPtr
<nsIURI
> uri
= mURI
;
153 NullPrincipal::SetDomain(nsIURI
* aDomain
) {
154 // I think the right thing to do here is to just throw... Silently failing
155 // seems counterproductive.
156 return NS_ERROR_NOT_AVAILABLE
;
159 bool NullPrincipal::MayLoadInternal(nsIURI
* aURI
) {
160 // Also allow the load if we are the principal of the URI being checked.
161 nsCOMPtr
<nsIPrincipal
> blobPrincipal
;
162 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
163 aURI
, getter_AddRefs(blobPrincipal
))) {
164 MOZ_ASSERT(blobPrincipal
);
165 return SubsumesInternal(blobPrincipal
,
166 BasePrincipal::ConsiderDocumentDomain
);
173 NullPrincipal::GetBaseDomain(nsACString
& aBaseDomain
) {
174 // For a null principal, we use our unique uuid as the base domain.
175 return mURI
->GetPathQueryRef(aBaseDomain
);
179 NullPrincipal::GetAddonId(nsAString
& aAddonId
) {
185 * nsISerializable implementation
188 NullPrincipal::Read(nsIObjectInputStream
* aStream
) {
189 // Note - NullPrincipal use NS_GENERIC_FACTORY_CONSTRUCTOR_INIT, which means
190 // that the Init() method has already been invoked by the time we deserialize.
191 // This is in contrast to ContentPrincipal, which uses
192 // NS_GENERIC_FACTORY_CONSTRUCTOR, in which case ::Read needs to invoke
196 nsresult rv
= aStream
->ReadCString(spec
);
197 NS_ENSURE_SUCCESS(rv
, rv
);
199 nsCOMPtr
<nsIURI
> uri
;
200 rv
= NS_NewURI(getter_AddRefs(uri
), spec
);
201 NS_ENSURE_SUCCESS(rv
, rv
);
203 nsAutoCString suffix
;
204 rv
= aStream
->ReadCString(suffix
);
205 NS_ENSURE_SUCCESS(rv
, rv
);
207 OriginAttributes attrs
;
208 bool ok
= attrs
.PopulateFromSuffix(suffix
);
209 NS_ENSURE_TRUE(ok
, NS_ERROR_FAILURE
);
211 return Init(attrs
, uri
);
215 NullPrincipal::Write(nsIObjectOutputStream
* aStream
) {
216 // Read is used still for legacy principals
217 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
221 nsresult
NullPrincipal::PopulateJSONObject(Json::Value
& aObject
) {
222 nsAutoCString principalURI
;
223 nsresult rv
= mURI
->GetSpec(principalURI
);
224 NS_ENSURE_SUCCESS(rv
, rv
);
225 MOZ_ASSERT(principalURI
.Length() ==
226 NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME
":").Length() +
228 "Length of the URI should be: (scheme, uuid, - nullptr)");
229 aObject
[std::to_string(eSpec
)] = principalURI
.get();
231 nsAutoCString suffix
;
232 OriginAttributesRef().CreateSuffix(suffix
);
233 if (suffix
.Length() > 0) {
234 aObject
[std::to_string(eSuffix
)] = suffix
.get();
240 already_AddRefed
<BasePrincipal
> NullPrincipal::FromProperties(
241 nsTArray
<NullPrincipal::KeyVal
>& aFields
) {
242 MOZ_ASSERT(aFields
.Length() == eMax
+ 1, "Must have all the keys");
244 nsCOMPtr
<nsIURI
> uri
;
245 OriginAttributes attrs
;
247 // The odd structure here is to make the code to not compile
248 // if all the switch enum cases haven't been codified
249 for (const auto& field
: aFields
) {
251 case NullPrincipal::eSpec
:
252 if (!field
.valueWasSerialized
) {
254 "Null principals require a spec URI in serialized JSON");
257 rv
= NS_NewURI(getter_AddRefs(uri
), field
.value
);
258 NS_ENSURE_SUCCESS(rv
, nullptr);
260 case NullPrincipal::eSuffix
:
261 bool ok
= attrs
.PopulateFromSuffix(field
.value
);
270 MOZ_ASSERT(false, "No URI deserialized");
274 RefPtr
<NullPrincipal
> nullPrincipal
= new NullPrincipal();
275 rv
= nullPrincipal
->Init(attrs
, uri
);
279 return nullPrincipal
.forget();