Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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 "nsPrincipal.h"
9 #include "mozIThirdPartyUtil.h"
10 #include "nscore.h"
11 #include "nsScriptSecurityManager.h"
12 #include "nsString.h"
13 #include "nsReadableUtils.h"
14 #include "pratom.h"
15 #include "nsIURI.h"
16 #include "nsJSPrincipals.h"
17 #include "nsIObjectInputStream.h"
18 #include "nsIObjectOutputStream.h"
19 #include "nsIClassInfoImpl.h"
20 #include "nsError.h"
21 #include "nsIContentSecurityPolicy.h"
22 #include "nsCxPusher.h"
23 #include "jswrapper.h"
25 #include "mozilla/Preferences.h"
26 #include "mozilla/HashFunctions.h"
28 #include "nsIAppsService.h"
29 #include "mozIApplication.h"
31 using namespace mozilla;
33 static bool gCodeBasePrincipalSupport = false;
34 static bool gIsObservingCodeBasePrincipalSupport = false;
36 static bool URIIsImmutable(nsIURI* aURI)
37 {
38 nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
39 bool isMutable;
40 return
41 mutableObj &&
42 NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) &&
43 !isMutable;
44 }
46 // Static member variables
47 const char nsBasePrincipal::sInvalid[] = "Invalid";
49 NS_IMETHODIMP_(MozExternalRefCountType)
50 nsBasePrincipal::AddRef()
51 {
52 NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt");
53 // XXXcaa does this need to be threadsafe? See bug 143559.
54 nsrefcnt count = ++refcount;
55 NS_LOG_ADDREF(this, count, "nsBasePrincipal", sizeof(*this));
56 return count;
57 }
59 NS_IMETHODIMP_(MozExternalRefCountType)
60 nsBasePrincipal::Release()
61 {
62 NS_PRECONDITION(0 != refcount, "dup release");
63 nsrefcnt count = --refcount;
64 NS_LOG_RELEASE(this, count, "nsBasePrincipal");
65 if (count == 0) {
66 delete this;
67 }
69 return count;
70 }
72 nsBasePrincipal::nsBasePrincipal()
73 {
74 if (!gIsObservingCodeBasePrincipalSupport) {
75 nsresult rv =
76 Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
77 "signed.applets.codebase_principal_support",
78 false);
79 gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv);
80 NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport,
81 "Installing gCodeBasePrincipalSupport failed!");
82 }
83 }
85 nsBasePrincipal::~nsBasePrincipal(void)
86 {
87 }
89 NS_IMETHODIMP
90 nsBasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
91 {
92 NS_IF_ADDREF(*aCsp = mCSP);
93 return NS_OK;
94 }
96 NS_IMETHODIMP
97 nsBasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
98 {
99 // If CSP was already set, it should not be destroyed! Instead, it should
100 // get set anew when a new principal is created.
101 if (mCSP)
102 return NS_ERROR_ALREADY_INITIALIZED;
104 mCSP = aCsp;
105 return NS_OK;
106 }
108 #ifdef DEBUG
109 void nsPrincipal::dumpImpl()
110 {
111 nsAutoCString str;
112 GetScriptLocation(str);
113 fprintf(stderr, "nsPrincipal (%p) = %s\n", static_cast<void*>(this), str.get());
114 }
115 #endif
117 NS_IMPL_CLASSINFO(nsPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
118 NS_PRINCIPAL_CID)
119 NS_IMPL_QUERY_INTERFACE_CI(nsPrincipal,
120 nsIPrincipal,
121 nsISerializable)
122 NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
123 nsIPrincipal,
124 nsISerializable)
125 NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal)
126 NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal)
128 nsPrincipal::nsPrincipal()
129 : mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
130 , mInMozBrowser(false)
131 , mCodebaseImmutable(false)
132 , mDomainImmutable(false)
133 , mInitialized(false)
134 { }
136 nsPrincipal::~nsPrincipal()
137 { }
139 nsresult
140 nsPrincipal::Init(nsIURI *aCodebase,
141 uint32_t aAppId,
142 bool aInMozBrowser)
143 {
144 NS_ENSURE_STATE(!mInitialized);
145 NS_ENSURE_ARG(aCodebase);
147 mInitialized = true;
149 mCodebase = NS_TryToMakeImmutable(aCodebase);
150 mCodebaseImmutable = URIIsImmutable(mCodebase);
152 mAppId = aAppId;
153 mInMozBrowser = aInMozBrowser;
155 return NS_OK;
156 }
158 void
159 nsPrincipal::GetScriptLocation(nsACString &aStr)
160 {
161 mCodebase->GetSpec(aStr);
162 }
164 /* static */ nsresult
165 nsPrincipal::GetOriginForURI(nsIURI* aURI, char **aOrigin)
166 {
167 if (!aURI) {
168 return NS_ERROR_FAILURE;
169 }
171 *aOrigin = nullptr;
173 nsCOMPtr<nsIURI> origin = NS_GetInnermostURI(aURI);
174 if (!origin) {
175 return NS_ERROR_FAILURE;
176 }
178 nsAutoCString hostPort;
180 // chrome: URLs don't have a meaningful origin, so make
181 // sure we just get the full spec for them.
182 // XXX this should be removed in favor of the solution in
183 // bug 160042.
184 bool isChrome;
185 nsresult rv = origin->SchemeIs("chrome", &isChrome);
186 if (NS_SUCCEEDED(rv) && !isChrome) {
187 rv = origin->GetAsciiHost(hostPort);
188 // Some implementations return an empty string, treat it as no support
189 // for asciiHost by that implementation.
190 if (hostPort.IsEmpty()) {
191 rv = NS_ERROR_FAILURE;
192 }
193 }
195 int32_t port;
196 if (NS_SUCCEEDED(rv) && !isChrome) {
197 rv = origin->GetPort(&port);
198 }
200 if (NS_SUCCEEDED(rv) && !isChrome) {
201 if (port != -1) {
202 hostPort.AppendLiteral(":");
203 hostPort.AppendInt(port, 10);
204 }
206 nsAutoCString scheme;
207 rv = origin->GetScheme(scheme);
208 NS_ENSURE_SUCCESS(rv, rv);
210 *aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort);
211 }
212 else {
213 // Some URIs (e.g., nsSimpleURI) don't support asciiHost. Just
214 // get the full spec.
215 nsAutoCString spec;
216 // XXX nsMozIconURI and nsJARURI don't implement this correctly, they
217 // both fall back to GetSpec. That needs to be fixed.
218 rv = origin->GetAsciiSpec(spec);
219 NS_ENSURE_SUCCESS(rv, rv);
221 *aOrigin = ToNewCString(spec);
222 }
224 return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
225 }
227 NS_IMETHODIMP
228 nsPrincipal::GetOrigin(char **aOrigin)
229 {
230 return GetOriginForURI(mCodebase, aOrigin);
231 }
233 NS_IMETHODIMP
234 nsPrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
235 {
236 *aResult = false;
238 if (!aOther) {
239 NS_WARNING("Need a principal to compare this to!");
240 return NS_OK;
241 }
243 if (aOther == this) {
244 *aResult = true;
245 return NS_OK;
246 }
248 if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) {
249 return NS_OK;
250 }
252 // If either the subject or the object has changed its principal by
253 // explicitly setting document.domain then the other must also have
254 // done so in order to be considered the same origin. This prevents
255 // DNS spoofing based on document.domain (154930)
257 nsCOMPtr<nsIURI> thisURI;
258 this->GetDomain(getter_AddRefs(thisURI));
259 bool thisSetDomain = !!thisURI;
260 if (!thisURI) {
261 this->GetURI(getter_AddRefs(thisURI));
262 }
264 nsCOMPtr<nsIURI> otherURI;
265 aOther->GetDomain(getter_AddRefs(otherURI));
266 bool otherSetDomain = !!otherURI;
267 if (!otherURI) {
268 aOther->GetURI(getter_AddRefs(otherURI));
269 }
271 *aResult = thisSetDomain == otherSetDomain &&
272 nsScriptSecurityManager::SecurityCompareURIs(thisURI, otherURI);
273 return NS_OK;
274 }
276 NS_IMETHODIMP
277 nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
278 {
279 *aResult = false;
281 if (!aOther) {
282 NS_WARNING("Need a principal to compare this to!");
283 return NS_OK;
284 }
286 if (aOther == this) {
287 *aResult = true;
288 return NS_OK;
289 }
291 if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) {
292 return NS_OK;
293 }
295 nsCOMPtr<nsIURI> otherURI;
296 nsresult rv = aOther->GetURI(getter_AddRefs(otherURI));
297 if (NS_FAILED(rv)) {
298 return rv;
299 }
301 NS_ASSERTION(mCodebase,
302 "shouldn't be calling this on principals from preferences");
304 // Compare codebases.
305 *aResult = nsScriptSecurityManager::SecurityCompareURIs(mCodebase,
306 otherURI);
307 return NS_OK;
308 }
310 NS_IMETHODIMP
311 nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
312 {
313 return Equals(aOther, aResult);
314 }
316 NS_IMETHODIMP
317 nsPrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
318 {
319 return EqualsConsideringDomain(aOther, aResult);
320 }
322 NS_IMETHODIMP
323 nsPrincipal::GetURI(nsIURI** aURI)
324 {
325 if (mCodebaseImmutable) {
326 NS_ADDREF(*aURI = mCodebase);
327 return NS_OK;
328 }
330 if (!mCodebase) {
331 *aURI = nullptr;
332 return NS_OK;
333 }
335 return NS_EnsureSafeToReturn(mCodebase, aURI);
336 }
338 NS_IMETHODIMP
339 nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
340 {
341 if (aAllowIfInheritsPrincipal) {
342 // If the caller specified to allow loads of URIs that inherit
343 // our principal, allow the load if this URI inherits its principal
344 if (nsPrincipal::IsPrincipalInherited(aURI)) {
345 return NS_OK;
346 }
347 }
349 if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
350 return NS_OK;
351 }
353 // If strict file origin policy is in effect, local files will always fail
354 // SecurityCompareURIs unless they are identical. Explicitly check file origin
355 // policy, in that case.
356 if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
357 NS_URIIsLocalFile(aURI) &&
358 NS_RelaxStrictFileOriginPolicy(aURI, mCodebase)) {
359 return NS_OK;
360 }
362 if (aReport) {
363 nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
364 }
365 return NS_ERROR_DOM_BAD_URI;
366 }
368 void
369 nsPrincipal::SetURI(nsIURI* aURI)
370 {
371 mCodebase = NS_TryToMakeImmutable(aURI);
372 mCodebaseImmutable = URIIsImmutable(mCodebase);
373 }
375 NS_IMETHODIMP
376 nsPrincipal::GetHashValue(uint32_t* aValue)
377 {
378 NS_PRECONDITION(mCodebase, "Need a codebase");
380 *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this);
381 return NS_OK;
382 }
384 NS_IMETHODIMP
385 nsPrincipal::GetDomain(nsIURI** aDomain)
386 {
387 if (!mDomain) {
388 *aDomain = nullptr;
389 return NS_OK;
390 }
392 if (mDomainImmutable) {
393 NS_ADDREF(*aDomain = mDomain);
394 return NS_OK;
395 }
397 return NS_EnsureSafeToReturn(mDomain, aDomain);
398 }
400 NS_IMETHODIMP
401 nsPrincipal::SetDomain(nsIURI* aDomain)
402 {
403 mDomain = NS_TryToMakeImmutable(aDomain);
404 mDomainImmutable = URIIsImmutable(mDomain);
406 // Recompute all wrappers between compartments using this principal and other
407 // non-chrome compartments.
408 AutoSafeJSContext cx;
409 JSPrincipals *principals = nsJSPrincipals::get(static_cast<nsIPrincipal*>(this));
410 bool success = js::RecomputeWrappers(cx, js::ContentCompartmentsOnly(),
411 js::CompartmentsWithPrincipals(principals));
412 NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
413 success = js::RecomputeWrappers(cx, js::CompartmentsWithPrincipals(principals),
414 js::ContentCompartmentsOnly());
415 NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
417 return NS_OK;
418 }
420 NS_IMETHODIMP
421 nsPrincipal::GetJarPrefix(nsACString& aJarPrefix)
422 {
423 MOZ_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
425 mozilla::GetJarPrefix(mAppId, mInMozBrowser, aJarPrefix);
426 return NS_OK;
427 }
429 NS_IMETHODIMP
430 nsPrincipal::GetAppStatus(uint16_t* aAppStatus)
431 {
432 *aAppStatus = GetAppStatus();
433 return NS_OK;
434 }
436 NS_IMETHODIMP
437 nsPrincipal::GetAppId(uint32_t* aAppId)
438 {
439 if (mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
440 MOZ_ASSERT(false);
441 *aAppId = nsIScriptSecurityManager::NO_APP_ID;
442 return NS_OK;
443 }
445 *aAppId = mAppId;
446 return NS_OK;
447 }
449 NS_IMETHODIMP
450 nsPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
451 {
452 *aIsInBrowserElement = mInMozBrowser;
453 return NS_OK;
454 }
456 NS_IMETHODIMP
457 nsPrincipal::GetUnknownAppId(bool* aUnknownAppId)
458 {
459 *aUnknownAppId = mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID;
460 return NS_OK;
461 }
463 NS_IMETHODIMP
464 nsPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
465 {
466 *aIsNullPrincipal = false;
467 return NS_OK;
468 }
470 NS_IMETHODIMP
471 nsPrincipal::GetBaseDomain(nsACString& aBaseDomain)
472 {
473 // For a file URI, we return the file path.
474 if (NS_URIIsLocalFile(mCodebase)) {
475 nsCOMPtr<nsIURL> url = do_QueryInterface(mCodebase);
477 if (url) {
478 return url->GetFilePath(aBaseDomain);
479 }
480 }
482 // For everything else, we ask the TLD service via
483 // the ThirdPartyUtil.
484 nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
485 do_GetService(THIRDPARTYUTIL_CONTRACTID);
486 if (thirdPartyUtil) {
487 return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain);
488 }
490 return NS_OK;
491 }
493 NS_IMETHODIMP
494 nsPrincipal::Read(nsIObjectInputStream* aStream)
495 {
496 nsCOMPtr<nsISupports> supports;
497 nsCOMPtr<nsIURI> codebase;
498 nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
499 if (NS_FAILED(rv)) {
500 return rv;
501 }
503 codebase = do_QueryInterface(supports);
505 nsCOMPtr<nsIURI> domain;
506 rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
507 if (NS_FAILED(rv)) {
508 return rv;
509 }
511 domain = do_QueryInterface(supports);
513 uint32_t appId;
514 rv = aStream->Read32(&appId);
515 NS_ENSURE_SUCCESS(rv, rv);
517 bool inMozBrowser;
518 rv = aStream->ReadBoolean(&inMozBrowser);
519 NS_ENSURE_SUCCESS(rv, rv);
521 rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
522 NS_ENSURE_SUCCESS(rv, rv);
524 // This may be null.
525 nsCOMPtr<nsIContentSecurityPolicy> csp = do_QueryInterface(supports, &rv);
527 rv = Init(codebase, appId, inMozBrowser);
528 NS_ENSURE_SUCCESS(rv, rv);
530 rv = SetCsp(csp);
531 NS_ENSURE_SUCCESS(rv, rv);
533 // need to link in the CSP context here (link in a reference to this
534 // nsIPrincipal and to the URI of the protected resource).
535 if (csp) {
536 csp->SetRequestContext(codebase, nullptr, this, nullptr);
537 }
539 SetDomain(domain);
541 return NS_OK;
542 }
544 NS_IMETHODIMP
545 nsPrincipal::Write(nsIObjectOutputStream* aStream)
546 {
547 NS_ENSURE_STATE(mCodebase);
549 nsresult rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI),
550 true);
551 if (NS_FAILED(rv)) {
552 return rv;
553 }
555 rv = NS_WriteOptionalCompoundObject(aStream, mDomain, NS_GET_IID(nsIURI),
556 true);
557 if (NS_FAILED(rv)) {
558 return rv;
559 }
561 aStream->Write32(mAppId);
562 aStream->WriteBoolean(mInMozBrowser);
564 rv = NS_WriteOptionalCompoundObject(aStream, mCSP,
565 NS_GET_IID(nsIContentSecurityPolicy),
566 true);
567 if (NS_FAILED(rv)) {
568 return rv;
569 }
571 // mCodebaseImmutable and mDomainImmutable will be recomputed based
572 // on the deserialized URIs in Read().
574 return NS_OK;
575 }
577 uint16_t
578 nsPrincipal::GetAppStatus()
579 {
580 NS_WARN_IF_FALSE(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
581 "Asking for app status on a principal with an unknown app id");
582 // Installed apps have a valid app id (not NO_APP_ID or UNKNOWN_APP_ID)
583 // and they are not inside a mozbrowser.
584 if (mAppId == nsIScriptSecurityManager::NO_APP_ID ||
585 mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID || mInMozBrowser) {
586 return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
587 }
589 nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
590 NS_ENSURE_TRUE(appsService, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
592 nsCOMPtr<mozIApplication> app;
593 appsService->GetAppByLocalId(mAppId, getter_AddRefs(app));
594 NS_ENSURE_TRUE(app, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
596 uint16_t status = nsIPrincipal::APP_STATUS_INSTALLED;
597 NS_ENSURE_SUCCESS(app->GetAppStatus(&status),
598 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
600 nsAutoCString origin;
601 NS_ENSURE_SUCCESS(GetOrigin(getter_Copies(origin)),
602 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
603 nsString appOrigin;
604 NS_ENSURE_SUCCESS(app->GetOrigin(appOrigin),
605 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
607 // We go from string -> nsIURI -> origin to be sure we
608 // compare two punny-encoded origins.
609 nsCOMPtr<nsIURI> appURI;
610 NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(appURI), appOrigin),
611 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
613 nsAutoCString appOriginPunned;
614 NS_ENSURE_SUCCESS(GetOriginForURI(appURI, getter_Copies(appOriginPunned)),
615 nsIPrincipal::APP_STATUS_NOT_INSTALLED);
617 if (!appOriginPunned.Equals(origin)) {
618 return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
619 }
621 return status;
622 }
624 /************************************************************************************************************************/
626 static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
628 NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
629 NS_EXPANDEDPRINCIPAL_CID)
630 NS_IMPL_QUERY_INTERFACE_CI(nsExpandedPrincipal,
631 nsIPrincipal,
632 nsIExpandedPrincipal)
633 NS_IMPL_CI_INTERFACE_GETTER(nsExpandedPrincipal,
634 nsIPrincipal,
635 nsIExpandedPrincipal)
636 NS_IMPL_ADDREF_INHERITED(nsExpandedPrincipal, nsBasePrincipal)
637 NS_IMPL_RELEASE_INHERITED(nsExpandedPrincipal, nsBasePrincipal)
639 nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr <nsIPrincipal> > &aWhiteList)
640 {
641 mPrincipals.AppendElements(aWhiteList);
642 }
644 nsExpandedPrincipal::~nsExpandedPrincipal()
645 { }
647 NS_IMETHODIMP
648 nsExpandedPrincipal::GetDomain(nsIURI** aDomain)
649 {
650 *aDomain = nullptr;
651 return NS_OK;
652 }
654 NS_IMETHODIMP
655 nsExpandedPrincipal::SetDomain(nsIURI* aDomain)
656 {
657 return NS_OK;
658 }
660 NS_IMETHODIMP
661 nsExpandedPrincipal::GetOrigin(char** aOrigin)
662 {
663 *aOrigin = ToNewCString(NS_LITERAL_CSTRING(EXPANDED_PRINCIPAL_SPEC));
664 return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
665 }
667 typedef nsresult (NS_STDCALL nsIPrincipal::*nsIPrincipalMemFn)(nsIPrincipal* aOther,
668 bool* aResult);
669 #define CALL_MEMBER_FUNCTION(THIS,MEM_FN) ((THIS)->*(MEM_FN))
671 // nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsConsideringDomain
672 // shares the same logic. The difference only that Equals requires 'this'
673 // and 'aOther' to Subsume each other while EqualsConsideringDomain requires
674 // bidirectional SubsumesConsideringDomain.
675 static nsresult
676 Equals(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
677 bool* aResult)
678 {
679 // If (and only if) 'aThis' and 'aOther' both Subsume/SubsumesConsideringDomain
680 // each other, then they are Equal.
681 *aResult = false;
682 // Calling the corresponding subsume function on this (aFn).
683 nsresult rv = CALL_MEMBER_FUNCTION(aThis, aFn)(aOther, aResult);
684 NS_ENSURE_SUCCESS(rv, rv);
685 if (!*aResult)
686 return NS_OK;
688 // Calling the corresponding subsume function on aOther (aFn).
689 rv = CALL_MEMBER_FUNCTION(aOther, aFn)(aThis, aResult);
690 NS_ENSURE_SUCCESS(rv, rv);
691 return NS_OK;
692 }
694 NS_IMETHODIMP
695 nsExpandedPrincipal::Equals(nsIPrincipal* aOther, bool* aResult)
696 {
697 return ::Equals(this, &nsIPrincipal::Subsumes, aOther, aResult);
698 }
700 NS_IMETHODIMP
701 nsExpandedPrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult)
702 {
703 return ::Equals(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult);
704 }
706 // nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesConsideringDomain
707 // shares the same logic. The difference only that Subsumes calls are replaced
708 //with SubsumesConsideringDomain calls in the second case.
709 static nsresult
710 Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther,
711 bool* aResult)
712 {
713 nsresult rv;
714 nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther);
715 if (expanded) {
716 // If aOther is an ExpandedPrincipal too, check if all of its
717 // principals are subsumed.
718 nsTArray< nsCOMPtr<nsIPrincipal> >* otherList;
719 expanded->GetWhiteList(&otherList);
720 for (uint32_t i = 0; i < otherList->Length(); ++i){
721 rv = CALL_MEMBER_FUNCTION(aThis, aFn)((*otherList)[i], aResult);
722 NS_ENSURE_SUCCESS(rv, rv);
723 if (!*aResult) {
724 // If we don't subsume at least one principal of aOther, return false.
725 return NS_OK;
726 }
727 }
728 } else {
729 // For a regular aOther, one of our principals must subsume it.
730 nsTArray< nsCOMPtr<nsIPrincipal> >* list;
731 aThis->GetWhiteList(&list);
732 for (uint32_t i = 0; i < list->Length(); ++i){
733 rv = CALL_MEMBER_FUNCTION((*list)[i], aFn)(aOther, aResult);
734 NS_ENSURE_SUCCESS(rv, rv);
735 if (*aResult) {
736 // If one of our principal subsumes it, return true.
737 return NS_OK;
738 }
739 }
740 }
741 return NS_OK;
742 }
744 #undef CALL_MEMBER_FUNCTION
746 NS_IMETHODIMP
747 nsExpandedPrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult)
748 {
749 return ::Subsumes(this, &nsIPrincipal::Subsumes, aOther, aResult);
750 }
752 NS_IMETHODIMP
753 nsExpandedPrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult)
754 {
755 return ::Subsumes(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult);
756 }
758 NS_IMETHODIMP
759 nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
760 {
761 nsresult rv;
762 for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
763 rv = mPrincipals[i]->CheckMayLoad(uri, aReport, aAllowIfInheritsPrincipal);
764 if (NS_SUCCEEDED(rv))
765 return rv;
766 }
768 return NS_ERROR_DOM_BAD_URI;
769 }
771 NS_IMETHODIMP
772 nsExpandedPrincipal::GetHashValue(uint32_t* result)
773 {
774 MOZ_CRASH("extended principal should never be used as key in a hash map");
775 }
777 NS_IMETHODIMP
778 nsExpandedPrincipal::GetURI(nsIURI** aURI)
779 {
780 *aURI = nullptr;
781 return NS_OK;
782 }
784 NS_IMETHODIMP
785 nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList)
786 {
787 *aWhiteList = &mPrincipals;
788 return NS_OK;
789 }
791 NS_IMETHODIMP
792 nsExpandedPrincipal::GetJarPrefix(nsACString& aJarPrefix)
793 {
794 aJarPrefix.Truncate();
795 return NS_OK;
796 }
798 NS_IMETHODIMP
799 nsExpandedPrincipal::GetAppStatus(uint16_t* aAppStatus)
800 {
801 *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
802 return NS_OK;
803 }
805 NS_IMETHODIMP
806 nsExpandedPrincipal::GetAppId(uint32_t* aAppId)
807 {
808 *aAppId = nsIScriptSecurityManager::NO_APP_ID;
809 return NS_OK;
810 }
812 NS_IMETHODIMP
813 nsExpandedPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement)
814 {
815 *aIsInBrowserElement = false;
816 return NS_OK;
817 }
819 NS_IMETHODIMP
820 nsExpandedPrincipal::GetUnknownAppId(bool* aUnknownAppId)
821 {
822 *aUnknownAppId = false;
823 return NS_OK;
824 }
826 NS_IMETHODIMP
827 nsExpandedPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal)
828 {
829 *aIsNullPrincipal = false;
830 return NS_OK;
831 }
833 NS_IMETHODIMP
834 nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
835 {
836 return NS_ERROR_NOT_AVAILABLE;
837 }
839 void
840 nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
841 {
842 // Is that a good idea to list it's principals?
843 aStr.Assign(EXPANDED_PRINCIPAL_SPEC);
844 }
846 #ifdef DEBUG
847 void nsExpandedPrincipal::dumpImpl()
848 {
849 fprintf(stderr, "nsExpandedPrincipal (%p)\n", static_cast<void*>(this));
850 }
851 #endif
853 //////////////////////////////////////////
854 // Methods implementing nsISerializable //
855 //////////////////////////////////////////
857 NS_IMETHODIMP
858 nsExpandedPrincipal::Read(nsIObjectInputStream* aStream)
859 {
860 return NS_ERROR_NOT_IMPLEMENTED;
861 }
863 NS_IMETHODIMP
864 nsExpandedPrincipal::Write(nsIObjectOutputStream* aStream)
865 {
866 return NS_ERROR_NOT_IMPLEMENTED;
867 }