Bug 1528152 [wpt PR 15381] - Quirks: move vertical-align-in-quirks.html to historical...
[gecko.git] / caps / BasePrincipal.cpp
blob8a3a334acb1d343f215ad4fec6a87cde96dc33ca
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=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/. */
7 #include "mozilla/BasePrincipal.h"
9 #include "nsDocShell.h"
10 #include "nsIContentSecurityPolicy.h"
11 #include "nsIObjectInputStream.h"
12 #include "nsIObjectOutputStream.h"
13 #include "nsIStandardURL.h"
15 #include "ExpandedPrincipal.h"
16 #include "nsNetUtil.h"
17 #include "nsIURIWithSpecialOrigin.h"
18 #include "nsScriptSecurityManager.h"
19 #include "nsServiceManagerUtils.h"
21 #include "mozilla/ContentPrincipal.h"
22 #include "mozilla/NullPrincipal.h"
23 #include "mozilla/dom/BlobURLProtocolHandler.h"
24 #include "mozilla/dom/ChromeUtils.h"
25 #include "mozilla/dom/CSPDictionariesBinding.h"
26 #include "mozilla/dom/nsCSPContext.h"
27 #include "mozilla/dom/ToJSValue.h"
29 namespace mozilla {
31 BasePrincipal::BasePrincipal(PrincipalKind aKind)
32 : mKind(aKind), mHasExplicitDomain(false), mInitialized(false) {}
34 BasePrincipal::~BasePrincipal() {}
36 NS_IMETHODIMP
37 BasePrincipal::GetOrigin(nsACString& aOrigin) {
38 MOZ_ASSERT(mInitialized);
40 nsresult rv = GetOriginNoSuffix(aOrigin);
41 NS_ENSURE_SUCCESS(rv, rv);
43 nsAutoCString suffix;
44 rv = GetOriginSuffix(suffix);
45 NS_ENSURE_SUCCESS(rv, rv);
46 aOrigin.Append(suffix);
47 return NS_OK;
50 NS_IMETHODIMP
51 BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
52 MOZ_ASSERT(mInitialized);
53 mOriginNoSuffix->ToUTF8String(aOrigin);
54 return NS_OK;
57 NS_IMETHODIMP
58 BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
59 MOZ_ASSERT(mInitialized);
60 return GetOrigin(aSiteOrigin);
63 bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
64 DocumentDomainConsideration aConsideration) {
65 MOZ_ASSERT(aOther);
66 MOZ_ASSERT_IF(Kind() == eCodebasePrincipal, mOriginSuffix);
68 // Expanded principals handle origin attributes for each of their
69 // sub-principals individually, null principals do only simple checks for
70 // pointer equality, and system principals are immune to origin attributes
71 // checks, so only do this check for codebase principals.
72 if (Kind() == eCodebasePrincipal &&
73 mOriginSuffix != Cast(aOther)->mOriginSuffix) {
74 return false;
77 return SubsumesInternal(aOther, aConsideration);
80 NS_IMETHODIMP
81 BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
82 NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
84 *aResult = FastEquals(aOther);
86 return NS_OK;
89 NS_IMETHODIMP
90 BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
91 NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
93 *aResult = FastEqualsConsideringDomain(aOther);
95 return NS_OK;
98 NS_IMETHODIMP
99 BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
100 NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
102 *aResult = FastSubsumes(aOther);
104 return NS_OK;
107 NS_IMETHODIMP
108 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
109 NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
111 *aResult = FastSubsumesConsideringDomain(aOther);
113 return NS_OK;
116 NS_IMETHODIMP
117 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
118 bool* aResult) {
119 NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
121 *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
123 return NS_OK;
126 NS_IMETHODIMP
127 BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport,
128 bool aAllowIfInheritsPrincipal) {
129 // Check the internal method first, which allows us to quickly approve loads
130 // for the System Principal.
131 if (MayLoadInternal(aURI)) {
132 return NS_OK;
135 nsresult rv;
136 if (aAllowIfInheritsPrincipal) {
137 // If the caller specified to allow loads of URIs that inherit
138 // our principal, allow the load if this URI inherits its principal.
139 bool doesInheritSecurityContext;
140 rv = NS_URIChainHasFlags(aURI,
141 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
142 &doesInheritSecurityContext);
143 if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
144 return NS_OK;
148 bool fetchableByAnyone;
149 rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
150 &fetchableByAnyone);
151 if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
152 return NS_OK;
155 if (aReport) {
156 nsCOMPtr<nsIURI> prinURI;
157 rv = GetURI(getter_AddRefs(prinURI));
158 if (NS_SUCCEEDED(rv) && prinURI) {
159 nsScriptSecurityManager::ReportError(
160 "CheckSameOriginError", prinURI, aURI,
161 mOriginAttributes.mPrivateBrowsingId > 0);
165 return NS_ERROR_DOM_BAD_URI;
168 NS_IMETHODIMP
169 BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) {
170 NS_IF_ADDREF(*aCsp = mCSP);
171 return NS_OK;
174 NS_IMETHODIMP
175 BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
176 // Never destroy an existing CSP on the principal.
177 // This method should only be called in rare cases.
179 MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
180 if (mCSP) {
181 return NS_ERROR_ALREADY_INITIALIZED;
184 mCSP = aCsp;
185 return NS_OK;
188 NS_IMETHODIMP
189 BasePrincipal::EnsureCSP(dom::Document* aDocument,
190 nsIContentSecurityPolicy** aCSP) {
191 if (mCSP) {
192 // if there is a CSP already associated with this principal
193 // then just return that - do not overwrite it!!!
194 NS_IF_ADDREF(*aCSP = mCSP);
195 return NS_OK;
198 nsresult rv = NS_OK;
199 mCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
200 NS_ENSURE_SUCCESS(rv, rv);
202 // Store the request context for violation reports
203 rv = aDocument ? mCSP->SetRequestContext(aDocument, nullptr)
204 : mCSP->SetRequestContext(nullptr, this);
205 NS_ENSURE_SUCCESS(rv, rv);
206 NS_IF_ADDREF(*aCSP = mCSP);
207 return NS_OK;
210 NS_IMETHODIMP
211 BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) {
212 NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
213 return NS_OK;
216 NS_IMETHODIMP
217 BasePrincipal::EnsurePreloadCSP(dom::Document* aDocument,
218 nsIContentSecurityPolicy** aPreloadCSP) {
219 if (mPreloadCSP) {
220 // if there is a speculative CSP already associated with this principal
221 // then just return that - do not overwrite it!!!
222 NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
223 return NS_OK;
226 nsresult rv = NS_OK;
227 mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
228 NS_ENSURE_SUCCESS(rv, rv);
230 // Store the request context for violation reports
231 rv = aDocument ? mPreloadCSP->SetRequestContext(aDocument, nullptr)
232 : mPreloadCSP->SetRequestContext(nullptr, this);
233 NS_ENSURE_SUCCESS(rv, rv);
234 NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
235 return NS_OK;
238 NS_IMETHODIMP
239 BasePrincipal::GetCspJSON(nsAString& outCSPinJSON) {
240 outCSPinJSON.Truncate();
241 dom::CSPPolicies jsonPolicies;
243 if (!mCSP) {
244 jsonPolicies.ToJSON(outCSPinJSON);
245 return NS_OK;
247 return mCSP->ToJSON(outCSPinJSON);
250 NS_IMETHODIMP
251 BasePrincipal::GetIsNullPrincipal(bool* aResult) {
252 *aResult = Kind() == eNullPrincipal;
253 return NS_OK;
256 NS_IMETHODIMP
257 BasePrincipal::GetIsCodebasePrincipal(bool* aResult) {
258 *aResult = Kind() == eCodebasePrincipal;
259 return NS_OK;
262 NS_IMETHODIMP
263 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
264 *aResult = Kind() == eExpandedPrincipal;
265 return NS_OK;
268 NS_IMETHODIMP
269 BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
270 *aResult = IsSystemPrincipal();
271 return NS_OK;
274 NS_IMETHODIMP
275 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
276 *aResult = AddonPolicy() || ContentScriptAddonPolicy();
277 return NS_OK;
280 NS_IMETHODIMP
281 BasePrincipal::GetOriginAttributes(JSContext* aCx,
282 JS::MutableHandle<JS::Value> aVal) {
283 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
284 return NS_ERROR_FAILURE;
286 return NS_OK;
289 NS_IMETHODIMP
290 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
291 MOZ_ASSERT(mOriginSuffix);
292 mOriginSuffix->ToUTF8String(aOriginAttributes);
293 return NS_OK;
296 NS_IMETHODIMP
297 BasePrincipal::GetAppId(uint32_t* aAppId) {
298 if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
299 MOZ_ASSERT(false);
300 *aAppId = nsIScriptSecurityManager::NO_APP_ID;
301 return NS_OK;
304 *aAppId = AppId();
305 return NS_OK;
308 NS_IMETHODIMP
309 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
310 *aUserContextId = UserContextId();
311 return NS_OK;
314 NS_IMETHODIMP
315 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
316 *aPrivateBrowsingId = PrivateBrowsingId();
317 return NS_OK;
320 NS_IMETHODIMP
321 BasePrincipal::GetIsInIsolatedMozBrowserElement(
322 bool* aIsInIsolatedMozBrowserElement) {
323 *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
324 return NS_OK;
327 nsresult BasePrincipal::GetAddonPolicy(nsISupports** aResult) {
328 RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
329 policy.forget(aResult);
330 return NS_OK;
333 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
334 if (Is<ContentPrincipal>()) {
335 return As<ContentPrincipal>()->AddonPolicy();
337 return nullptr;
340 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
341 if (auto policy = AddonPolicy()) {
342 return policy->HasPermission(aPerm);
344 return false;
347 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
348 if (Is<ExpandedPrincipal>()) {
349 return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
351 return this;
354 already_AddRefed<BasePrincipal> BasePrincipal::CreateCodebasePrincipal(
355 nsIURI* aURI, const OriginAttributes& aAttrs) {
356 MOZ_ASSERT(aURI);
358 nsAutoCString originNoSuffix;
359 nsresult rv =
360 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
361 if (NS_FAILED(rv)) {
362 // If the generation of the origin fails, we still want to have a valid
363 // principal. Better to return a null principal here.
364 return NullPrincipal::Create(aAttrs);
367 return CreateCodebasePrincipal(aURI, aAttrs, originNoSuffix);
370 already_AddRefed<BasePrincipal> BasePrincipal::CreateCodebasePrincipal(
371 nsIURI* aURI, const OriginAttributes& aAttrs,
372 const nsACString& aOriginNoSuffix) {
373 MOZ_ASSERT(aURI);
374 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
376 // If the URI is supposed to inherit the security context of whoever loads it,
377 // we shouldn't make a codebase principal for it.
378 bool inheritsPrincipal;
379 nsresult rv = NS_URIChainHasFlags(
380 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
381 &inheritsPrincipal);
382 if (NS_FAILED(rv) || inheritsPrincipal) {
383 return NullPrincipal::Create(aAttrs);
386 // Check whether the URI knows what its principal is supposed to be.
387 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
388 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
389 do_QueryInterface(aURI);
390 if (uriWithSpecialOrigin) {
391 nsCOMPtr<nsIURI> origin;
392 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
393 if (NS_WARN_IF(NS_FAILED(rv))) {
394 return nullptr;
396 MOZ_ASSERT(origin);
397 OriginAttributes attrs;
398 RefPtr<BasePrincipal> principal = CreateCodebasePrincipal(origin, attrs);
399 return principal.forget();
401 #endif
403 nsCOMPtr<nsIPrincipal> blobPrincipal;
404 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
405 aURI, getter_AddRefs(blobPrincipal))) {
406 MOZ_ASSERT(blobPrincipal);
407 RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
408 return principal.forget();
411 // Mint a codebase principal.
412 RefPtr<ContentPrincipal> codebase = new ContentPrincipal();
413 rv = codebase->Init(aURI, aAttrs, aOriginNoSuffix);
414 NS_ENSURE_SUCCESS(rv, nullptr);
415 return codebase.forget();
418 already_AddRefed<BasePrincipal> BasePrincipal::CreateCodebasePrincipal(
419 const nsACString& aOrigin) {
420 MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
421 "CreateCodebasePrincipal does not support System and Expanded "
422 "principals");
424 MOZ_ASSERT(!StringBeginsWith(aOrigin,
425 NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
426 "CreateCodebasePrincipal does not support NullPrincipal");
428 nsAutoCString originNoSuffix;
429 OriginAttributes attrs;
430 if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
431 return nullptr;
434 nsCOMPtr<nsIURI> uri;
435 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
436 NS_ENSURE_SUCCESS(rv, nullptr);
438 return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
441 already_AddRefed<BasePrincipal>
442 BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain() {
443 OriginAttributes attrs = OriginAttributesRef();
444 attrs.StripAttributes(OriginAttributes::STRIP_USER_CONTEXT_ID |
445 OriginAttributes::STRIP_FIRST_PARTY_DOMAIN);
447 nsAutoCString originNoSuffix;
448 nsresult rv = GetOriginNoSuffix(originNoSuffix);
449 NS_ENSURE_SUCCESS(rv, nullptr);
451 nsCOMPtr<nsIURI> uri;
452 rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
453 NS_ENSURE_SUCCESS(rv, nullptr);
455 return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
458 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
459 if (!Is<ExpandedPrincipal>()) {
460 return nullptr;
463 auto expanded = As<ExpandedPrincipal>();
464 for (auto& prin : expanded->AllowList()) {
465 if (auto policy = BasePrincipal::Cast(prin)->AddonPolicy()) {
466 return policy;
470 return nullptr;
473 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
474 bool aExplicit /* = false */) {
475 if (Is<ExpandedPrincipal>()) {
476 return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
478 if (auto policy = AddonPolicy()) {
479 return policy->CanAccessURI(aURI, aExplicit);
481 return false;
484 void BasePrincipal::FinishInit(const nsACString& aOriginNoSuffix,
485 const OriginAttributes& aOriginAttributes) {
486 mInitialized = true;
487 mOriginAttributes = aOriginAttributes;
489 // First compute the origin suffix since it's infallible.
490 nsAutoCString originSuffix;
491 mOriginAttributes.CreateSuffix(originSuffix);
492 mOriginSuffix = NS_Atomize(originSuffix);
494 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
495 mOriginNoSuffix = NS_Atomize(aOriginNoSuffix);
498 void BasePrincipal::FinishInit(BasePrincipal* aOther,
499 const OriginAttributes& aOriginAttributes) {
500 mInitialized = true;
501 mOriginAttributes = aOriginAttributes;
503 // First compute the origin suffix since it's infallible.
504 nsAutoCString originSuffix;
505 mOriginAttributes.CreateSuffix(originSuffix);
506 mOriginSuffix = NS_Atomize(originSuffix);
508 mOriginNoSuffix = aOther->mOriginNoSuffix;
509 mHasExplicitDomain = aOther->mHasExplicitDomain;
511 if (aOther->mPreloadCSP) {
512 mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1");
513 nsCSPContext* preloadCSP = static_cast<nsCSPContext*>(mPreloadCSP.get());
514 preloadCSP->InitFromOther(
515 static_cast<nsCSPContext*>(aOther->mPreloadCSP.get()), nullptr, this);
518 if (aOther->mCSP) {
519 mCSP = do_CreateInstance("@mozilla.org/cspcontext;1");
520 nsCSPContext* csp = static_cast<nsCSPContext*>(mCSP.get());
521 csp->InitFromOther(static_cast<nsCSPContext*>(aOther->mCSP.get()), nullptr,
522 this);
526 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
527 MOZ_ASSERT(IsInitialized());
528 MOZ_ASSERT(aOther.IsInitialized());
529 return mPrincipal->FastEquals(aOther.mPrincipal);
532 } // namespace mozilla