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 nsresult rv
= nullPrin
->Init(aOriginAttributes
, aIsFirstParty
);
57 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
= new NullPrincipalURI();
92 nsAutoCString originNoSuffix
;
93 DebugOnly
<nsresult
> rv
= mURI
->GetSpec(originNoSuffix
);
94 MOZ_ASSERT(NS_SUCCEEDED(rv
));
96 FinishInit(originNoSuffix
, aOriginAttributes
);
101 nsresult
NullPrincipal::Init(const OriginAttributes
& aOriginAttributes
,
102 bool aIsFirstParty
, nsIURI
* aURI
) {
104 nsAutoCString scheme
;
105 nsresult rv
= aURI
->GetScheme(scheme
);
106 NS_ENSURE_SUCCESS(rv
, rv
);
108 NS_ENSURE_TRUE(scheme
.EqualsLiteral(NS_NULLPRINCIPAL_SCHEME
),
109 NS_ERROR_NOT_AVAILABLE
);
113 mURI
= new NullPrincipalURI();
116 nsAutoCString originNoSuffix
;
117 DebugOnly
<nsresult
> rv
= mURI
->GetSpec(originNoSuffix
);
118 MOZ_ASSERT(NS_SUCCEEDED(rv
));
121 rv
= mURI
->GetPathQueryRef(path
);
122 MOZ_ASSERT(NS_SUCCEEDED(rv
));
124 OriginAttributes
attrs(aOriginAttributes
);
126 // remove the '{}' characters from both ends.
127 path
.Mid(path
, 1, path
.Length() - 2);
128 path
.AppendLiteral(".mozilla");
129 attrs
.SetFirstPartyDomain(true, path
);
132 FinishInit(originNoSuffix
, attrs
);
137 nsresult
NullPrincipal::GetScriptLocation(nsACString
& aStr
) {
138 return mURI
->GetSpec(aStr
);
142 * nsIPrincipal implementation
145 uint32_t NullPrincipal::GetHashValue() { return (NS_PTR_TO_INT32(this) >> 2); }
148 NullPrincipal::GetURI(nsIURI
** aURI
) {
149 nsCOMPtr
<nsIURI
> uri
= mURI
;
154 NullPrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult
) {
160 NullPrincipal::GetDomain(nsIURI
** aDomain
) {
161 nsCOMPtr
<nsIURI
> uri
= mURI
;
167 NullPrincipal::SetDomain(nsIURI
* aDomain
) {
168 // I think the right thing to do here is to just throw... Silently failing
169 // seems counterproductive.
170 return NS_ERROR_NOT_AVAILABLE
;
173 bool NullPrincipal::MayLoadInternal(nsIURI
* aURI
) {
174 // Also allow the load if we are the principal of the URI being checked.
175 nsCOMPtr
<nsIPrincipal
> blobPrincipal
;
176 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
177 aURI
, getter_AddRefs(blobPrincipal
))) {
178 MOZ_ASSERT(blobPrincipal
);
179 return SubsumesInternal(blobPrincipal
,
180 BasePrincipal::ConsiderDocumentDomain
);
187 NullPrincipal::GetBaseDomain(nsACString
& aBaseDomain
) {
188 // For a null principal, we use our unique uuid as the base domain.
189 return mURI
->GetPathQueryRef(aBaseDomain
);
193 NullPrincipal::GetAddonId(nsAString
& aAddonId
) {
199 * nsISerializable implementation
202 NullPrincipal::Read(nsIObjectInputStream
* aStream
) {
203 // Note - NullPrincipal use NS_GENERIC_FACTORY_CONSTRUCTOR_INIT, which means
204 // that the Init() method has already been invoked by the time we deserialize.
205 // This is in contrast to ContentPrincipal, which uses
206 // NS_GENERIC_FACTORY_CONSTRUCTOR, in which case ::Read needs to invoke
210 nsresult rv
= aStream
->ReadCString(spec
);
211 NS_ENSURE_SUCCESS(rv
, rv
);
213 nsCOMPtr
<nsIURI
> uri
;
214 rv
= NS_NewURI(getter_AddRefs(uri
), spec
);
215 NS_ENSURE_SUCCESS(rv
, rv
);
217 nsAutoCString suffix
;
218 rv
= aStream
->ReadCString(suffix
);
219 NS_ENSURE_SUCCESS(rv
, rv
);
221 OriginAttributes attrs
;
222 bool ok
= attrs
.PopulateFromSuffix(suffix
);
223 NS_ENSURE_TRUE(ok
, NS_ERROR_FAILURE
);
225 return Init(attrs
, uri
);
229 NullPrincipal::Write(nsIObjectOutputStream
* aStream
) {
230 // Read is used still for legacy principals
231 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
235 nsresult
NullPrincipal::PopulateJSONObject(Json::Value
& aObject
) {
236 nsAutoCString principalURI
;
237 nsresult rv
= mURI
->GetSpec(principalURI
);
238 NS_ENSURE_SUCCESS(rv
, rv
);
239 MOZ_ASSERT(principalURI
.Length() ==
240 nsLiteralCString(NS_NULLPRINCIPAL_SCHEME
":").Length() +
242 "Length of the URI should be: (scheme, uuid, - nullptr)");
243 aObject
[std::to_string(eSpec
)] = principalURI
.get();
245 nsAutoCString suffix
;
246 OriginAttributesRef().CreateSuffix(suffix
);
247 if (suffix
.Length() > 0) {
248 aObject
[std::to_string(eSuffix
)] = suffix
.get();
254 already_AddRefed
<BasePrincipal
> NullPrincipal::FromProperties(
255 nsTArray
<NullPrincipal::KeyVal
>& aFields
) {
256 MOZ_ASSERT(aFields
.Length() == eMax
+ 1, "Must have all the keys");
258 nsCOMPtr
<nsIURI
> uri
;
259 OriginAttributes attrs
;
261 // The odd structure here is to make the code to not compile
262 // if all the switch enum cases haven't been codified
263 for (const auto& field
: aFields
) {
265 case NullPrincipal::eSpec
:
266 if (!field
.valueWasSerialized
) {
268 "Null principals require a spec URI in serialized JSON");
271 rv
= NS_NewURI(getter_AddRefs(uri
), field
.value
);
272 NS_ENSURE_SUCCESS(rv
, nullptr);
274 case NullPrincipal::eSuffix
:
275 bool ok
= attrs
.PopulateFromSuffix(field
.value
);
284 MOZ_ASSERT(false, "No URI deserialized");
288 RefPtr
<NullPrincipal
> nullPrincipal
= new NullPrincipal();
289 rv
= nullPrincipal
->Init(attrs
, uri
);
293 return nullPrincipal
.forget();