mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
b752598495
In order to handle the content script case correctly we must expose the contentScriptAddonPolicy to JavaScript. With that we can always see what extension is trying to perform an action and use its name rather than internal ID in the dialog. Differential Revision: https://phabricator.services.mozilla.com/D161282
1535 lines
44 KiB
C++
1535 lines
44 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=2 sw=2 et tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/BasePrincipal.h"
|
|
|
|
#include "nsDocShell.h"
|
|
|
|
#include "ExpandedPrincipal.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsIOService.h"
|
|
#include "nsIURIWithSpecialOrigin.h"
|
|
#include "nsScriptSecurityManager.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsAboutProtocolUtils.h"
|
|
#include "ThirdPartyUtil.h"
|
|
#include "mozilla/ContentPrincipal.h"
|
|
#include "mozilla/ExtensionPolicyService.h"
|
|
#include "mozilla/NullPrincipal.h"
|
|
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
|
#include "mozilla/dom/ChromeUtils.h"
|
|
#include "mozilla/dom/ReferrerInfo.h"
|
|
#include "mozilla/dom/ToJSValue.h"
|
|
#include "mozilla/dom/nsMixedContentBlocker.h"
|
|
#include "mozilla/Components.h"
|
|
#include "mozilla/dom/StorageUtils.h"
|
|
#include "mozilla/dom/StorageUtils.h"
|
|
#include "nsIURL.h"
|
|
#include "nsEffectiveTLDService.h"
|
|
#include "nsIURIMutator.h"
|
|
#include "mozilla/StaticPrefs_permissions.h"
|
|
#include "nsIURIMutator.h"
|
|
#include "nsMixedContentBlocker.h"
|
|
#include "prnetdb.h"
|
|
#include "nsIURIFixup.h"
|
|
#include "mozilla/dom/StorageUtils.h"
|
|
#include "mozilla/StorageAccess.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include "nsIURIMutator.h"
|
|
#include "mozilla/PermissionManager.h"
|
|
|
|
#include "json/json.h"
|
|
#include "nsSerializationHelper.h"
|
|
|
|
namespace mozilla {
|
|
|
|
BasePrincipal::BasePrincipal(PrincipalKind aKind,
|
|
const nsACString& aOriginNoSuffix,
|
|
const OriginAttributes& aOriginAttributes)
|
|
: mOriginNoSuffix(NS_Atomize(aOriginNoSuffix)),
|
|
mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
|
|
mOriginAttributes(aOriginAttributes),
|
|
mKind(aKind),
|
|
mHasExplicitDomain(false) {}
|
|
|
|
BasePrincipal::BasePrincipal(BasePrincipal* aOther,
|
|
const OriginAttributes& aOriginAttributes)
|
|
: mOriginNoSuffix(aOther->mOriginNoSuffix),
|
|
mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
|
|
mOriginAttributes(aOriginAttributes),
|
|
mKind(aOther->mKind),
|
|
mHasExplicitDomain(aOther->mHasExplicitDomain.load()) {}
|
|
|
|
BasePrincipal::~BasePrincipal() = default;
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetOrigin(nsACString& aOrigin) {
|
|
nsresult rv = GetOriginNoSuffix(aOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString suffix;
|
|
rv = GetOriginSuffix(suffix);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
aOrigin.Append(suffix);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetAsciiOrigin(nsACString& aOrigin) {
|
|
aOrigin.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
return nsContentUtils::GetASCIIOrigin(prinURI, aOrigin);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetHostPort(nsACString& aRes) {
|
|
aRes.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->GetHostPort(aRes);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetHost(nsACString& aRes) {
|
|
aRes.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->GetHost(aRes);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
|
|
mOriginNoSuffix->ToUTF8String(aOrigin);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
|
|
nsresult rv = GetSiteOriginNoSuffix(aSiteOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString suffix;
|
|
rv = GetOriginSuffix(suffix);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
aSiteOrigin.Append(suffix);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) {
|
|
return GetOriginNoSuffix(aSiteOrigin);
|
|
}
|
|
|
|
// Returns the inner Json::value of the serialized principal
|
|
// Example input and return values:
|
|
// Null principal:
|
|
// {"0":{"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}} ->
|
|
// {"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}
|
|
//
|
|
// Content principal:
|
|
// {"1":{"0":"https://mozilla.com"}} -> {"0":"https://mozilla.com"}
|
|
//
|
|
// Expanded principal:
|
|
// {"2":{"0":"<base64principal1>,<base64principal2>"}} ->
|
|
// {"0":"<base64principal1>,<base64principal2>"}
|
|
//
|
|
// System principal:
|
|
// {"3":{}} -> {}
|
|
// The aKey passed in also returns the corresponding PrincipalKind enum
|
|
//
|
|
// Warning: The Json::Value* pointer is into the aRoot object
|
|
static const Json::Value* GetPrincipalObject(const Json::Value& aRoot,
|
|
int& aOutPrincipalKind) {
|
|
const Json::Value::Members members = aRoot.getMemberNames();
|
|
// We only support one top level key in the object
|
|
if (members.size() != 1) {
|
|
return nullptr;
|
|
}
|
|
// members[0] here is the "0", "1", "2", "3" principalKind
|
|
// that is the top level of the serialized JSON principal
|
|
const std::string stringPrincipalKind = members[0];
|
|
|
|
// Next we take the string value from the JSON
|
|
// and convert it into the int for the BasePrincipal::PrincipalKind enum
|
|
|
|
// Verify that the key is within the valid range
|
|
int principalKind = std::stoi(stringPrincipalKind);
|
|
MOZ_ASSERT(BasePrincipal::eNullPrincipal == 0,
|
|
"We need to rely on 0 being a bounds check for the first "
|
|
"principal kind.");
|
|
if (principalKind < 0 || principalKind > BasePrincipal::eKindMax) {
|
|
return nullptr;
|
|
}
|
|
MOZ_ASSERT(principalKind == BasePrincipal::eNullPrincipal ||
|
|
principalKind == BasePrincipal::eContentPrincipal ||
|
|
principalKind == BasePrincipal::eExpandedPrincipal ||
|
|
principalKind == BasePrincipal::eSystemPrincipal);
|
|
aOutPrincipalKind = principalKind;
|
|
|
|
if (!aRoot[stringPrincipalKind].isObject()) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Return the inner value of the principal object
|
|
return &aRoot[stringPrincipalKind];
|
|
}
|
|
|
|
// Accepts the JSON inner object without the wrapping principalKind
|
|
// (See GetPrincipalObject for the inner object response examples)
|
|
// Creates an array of KeyVal objects that are all defined on the principal
|
|
// Each principal type (null, content, expanded) has a KeyVal that stores the
|
|
// fields of the JSON
|
|
//
|
|
// This simplifies deserializing elsewhere as we do the checking for presence
|
|
// and string values here for the complete set of serializable keys that the
|
|
// corresponding principal supports.
|
|
//
|
|
// The KeyVal object has the following fields:
|
|
// - valueWasSerialized: is true if the deserialized JSON contained a string
|
|
// value
|
|
// - value: The string that was serialized for this key
|
|
// - key: an SerializableKeys enum value specific to the principal.
|
|
// For example content principal is an enum of: eURI, eDomain,
|
|
// eSuffix, eCSP
|
|
//
|
|
//
|
|
// Given an inner content principal:
|
|
// {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}
|
|
// | | | |
|
|
// ----------------------------- |
|
|
// | | |
|
|
// Key ----------------------
|
|
// |
|
|
// Value
|
|
//
|
|
// They Key "0" corresponds to ContentPrincipal::eURI
|
|
// They Key "1" corresponds to ContentPrincipal::eSuffix
|
|
template <typename T>
|
|
static nsTArray<typename T::KeyVal> GetJSONKeys(const Json::Value* aInput) {
|
|
int size = T::eMax + 1;
|
|
nsTArray<typename T::KeyVal> fields;
|
|
for (int i = 0; i != size; i++) {
|
|
typename T::KeyVal* field = fields.AppendElement();
|
|
// field->valueWasSerialized returns if the field was found in the
|
|
// deserialized code. This simplifies the consumers from having to check
|
|
// length.
|
|
field->valueWasSerialized = false;
|
|
field->key = static_cast<typename T::SerializableKeys>(i);
|
|
const std::string key = std::to_string(field->key);
|
|
if (aInput->isMember(key)) {
|
|
const Json::Value& val = (*aInput)[key];
|
|
if (val.isString()) {
|
|
field->value.Append(nsDependentCString(val.asCString()));
|
|
field->valueWasSerialized = true;
|
|
}
|
|
}
|
|
}
|
|
return fields;
|
|
}
|
|
|
|
// Takes a JSON string and parses it turning it into a principal of the
|
|
// corresponding type
|
|
//
|
|
// Given a content principal:
|
|
//
|
|
// inner JSON object
|
|
// |
|
|
// ---------------------------------------------------------
|
|
// | |
|
|
// {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
|
|
// | | | | |
|
|
// | ----------------------------- |
|
|
// | | | |
|
|
// PrincipalKind | | |
|
|
// | ----------------------------
|
|
// SerializableKeys |
|
|
// Value
|
|
//
|
|
// The string is first deserialized with jsoncpp to get the Json::Value of the
|
|
// object. The inner JSON object is parsed with GetPrincipalObject which returns
|
|
// a KeyVal array of the inner object's fields. PrincipalKind is returned by
|
|
// GetPrincipalObject which is then used to decide which principal
|
|
// implementation of FromProperties to call. The corresponding FromProperties
|
|
// call takes the KeyVal fields and turns it into a principal.
|
|
already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
|
|
const nsACString& aJSON) {
|
|
Json::Value root;
|
|
Json::CharReaderBuilder builder;
|
|
std::unique_ptr<Json::CharReader> const reader(builder.newCharReader());
|
|
bool parseSuccess =
|
|
reader->parse(aJSON.BeginReading(), aJSON.EndReading(), &root, nullptr);
|
|
if (!parseSuccess) {
|
|
MOZ_ASSERT(false,
|
|
"Unable to parse string as JSON to deserialize as a principal");
|
|
return nullptr;
|
|
}
|
|
|
|
int principalKind = -1;
|
|
const Json::Value* value = GetPrincipalObject(root, principalKind);
|
|
if (!value) {
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "Unexpected JSON principal %s\n",
|
|
root.toStyledString().c_str());
|
|
#endif
|
|
MOZ_ASSERT(false, "Unexpected JSON to deserialize as a principal");
|
|
|
|
return nullptr;
|
|
}
|
|
MOZ_ASSERT(principalKind != -1,
|
|
"PrincipalKind should always be >=0 by this point");
|
|
|
|
if (principalKind == eSystemPrincipal) {
|
|
RefPtr<BasePrincipal> principal =
|
|
BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
|
|
return principal.forget();
|
|
}
|
|
|
|
if (principalKind == eNullPrincipal) {
|
|
nsTArray<NullPrincipal::KeyVal> res = GetJSONKeys<NullPrincipal>(value);
|
|
return NullPrincipal::FromProperties(res);
|
|
}
|
|
|
|
if (principalKind == eContentPrincipal) {
|
|
nsTArray<ContentPrincipal::KeyVal> res =
|
|
GetJSONKeys<ContentPrincipal>(value);
|
|
return ContentPrincipal::FromProperties(res);
|
|
}
|
|
|
|
if (principalKind == eExpandedPrincipal) {
|
|
nsTArray<ExpandedPrincipal::KeyVal> res =
|
|
GetJSONKeys<ExpandedPrincipal>(value);
|
|
return ExpandedPrincipal::FromProperties(res);
|
|
}
|
|
|
|
MOZ_RELEASE_ASSERT(false, "Unexpected enum to deserialize as a principal");
|
|
}
|
|
|
|
nsresult BasePrincipal::PopulateJSONObject(Json::Value& aObject) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Returns a JSON representation of the principal.
|
|
// Calling BasePrincipal::FromJSON will deserialize the JSON into
|
|
// the corresponding principal type.
|
|
nsresult BasePrincipal::ToJSON(nsACString& aResult) {
|
|
MOZ_ASSERT(aResult.IsEmpty(), "ToJSON only supports an empty result input");
|
|
aResult.Truncate();
|
|
|
|
Json::StreamWriterBuilder builder;
|
|
builder["indentation"] = "";
|
|
Json::Value innerJSONObject = Json::objectValue;
|
|
|
|
nsresult rv = PopulateJSONObject(innerJSONObject);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
Json::Value root = Json::objectValue;
|
|
std::string key = std::to_string(Kind());
|
|
root[key] = innerJSONObject;
|
|
std::string result = Json::writeString(builder, root);
|
|
aResult.Append(result);
|
|
if (aResult.Length() == 0) {
|
|
MOZ_ASSERT(false, "JSON writer failed to output a principal serialization");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
bool BasePrincipal::FastSubsumesIgnoringFPD(
|
|
nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) {
|
|
MOZ_ASSERT(aOther);
|
|
|
|
if (Kind() == eContentPrincipal &&
|
|
!dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
|
|
mOriginAttributes, Cast(aOther)->mOriginAttributes)) {
|
|
return false;
|
|
}
|
|
|
|
return SubsumesInternal(aOther, aConsideration);
|
|
}
|
|
|
|
bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
|
|
DocumentDomainConsideration aConsideration) {
|
|
MOZ_ASSERT(aOther);
|
|
MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix);
|
|
|
|
// Expanded principals handle origin attributes for each of their
|
|
// sub-principals individually, null principals do only simple checks for
|
|
// pointer equality, and system principals are immune to origin attributes
|
|
// checks, so only do this check for content principals.
|
|
if (Kind() == eContentPrincipal &&
|
|
mOriginSuffix != Cast(aOther)->mOriginSuffix) {
|
|
return false;
|
|
}
|
|
|
|
return SubsumesInternal(aOther, aConsideration);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
|
|
NS_ENSURE_ARG_POINTER(aOther);
|
|
|
|
*aResult = FastEquals(aOther);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::EqualsForPermission(nsIPrincipal* aOther, bool aExactHost,
|
|
bool* aResult) {
|
|
*aResult = false;
|
|
NS_ENSURE_ARG_POINTER(aOther);
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
auto* other = Cast(aOther);
|
|
if (Kind() != other->Kind()) {
|
|
// Principals of different kinds can't be equal.
|
|
return NS_OK;
|
|
}
|
|
|
|
if (Kind() == eSystemPrincipal) {
|
|
*aResult = this == other;
|
|
return NS_OK;
|
|
}
|
|
|
|
if (Kind() == eNullPrincipal) {
|
|
// We don't store permissions for NullPrincipals.
|
|
return NS_OK;
|
|
}
|
|
|
|
MOZ_ASSERT(Kind() == eExpandedPrincipal || Kind() == eContentPrincipal);
|
|
|
|
// Certain origin attributes should not be used to isolate permissions.
|
|
// Create a stripped copy of both OA sets to compare.
|
|
mozilla::OriginAttributes ourAttrs = mOriginAttributes;
|
|
PermissionManager::MaybeStripOriginAttributes(false, ourAttrs);
|
|
mozilla::OriginAttributes theirAttrs = aOther->OriginAttributesRef();
|
|
PermissionManager::MaybeStripOriginAttributes(false, theirAttrs);
|
|
|
|
if (ourAttrs != theirAttrs) {
|
|
return NS_OK;
|
|
}
|
|
|
|
if (mOriginNoSuffix == other->mOriginNoSuffix) {
|
|
*aResult = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
// If we are matching with an exact host, we're done now - the permissions
|
|
// don't match otherwise, we need to start comparing subdomains!
|
|
if (aExactHost) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> ourURI;
|
|
nsresult rv = GetURI(getter_AddRefs(ourURI));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
// Some principal types may indicate success, but still return nullptr for
|
|
// URI.
|
|
NS_ENSURE_TRUE(ourURI, NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsIURI> otherURI;
|
|
rv = other->GetURI(getter_AddRefs(otherURI));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_TRUE(otherURI, NS_ERROR_FAILURE);
|
|
|
|
// Compare schemes
|
|
nsAutoCString otherScheme;
|
|
rv = otherURI->GetScheme(otherScheme);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString ourScheme;
|
|
rv = ourURI->GetScheme(ourScheme);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (otherScheme != ourScheme) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Compare ports
|
|
int32_t otherPort;
|
|
rv = otherURI->GetPort(&otherPort);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
int32_t ourPort;
|
|
rv = ourURI->GetPort(&ourPort);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (otherPort != ourPort) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Check if the host or any subdomain of their host matches.
|
|
nsAutoCString otherHost;
|
|
rv = otherURI->GetHost(otherHost);
|
|
if (NS_FAILED(rv) || otherHost.IsEmpty()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString ourHost;
|
|
rv = ourURI->GetHost(ourHost);
|
|
if (NS_FAILED(rv) || ourHost.IsEmpty()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIEffectiveTLDService> tldService =
|
|
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
|
|
if (!tldService) {
|
|
NS_ERROR("Should have a tld service!");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// This loop will not loop forever, as GetNextSubDomain will eventually fail
|
|
// with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
|
|
while (otherHost != ourHost) {
|
|
rv = tldService->GetNextSubDomain(otherHost, otherHost);
|
|
if (NS_FAILED(rv)) {
|
|
if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
|
|
return NS_OK;
|
|
}
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
*aResult = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
|
|
NS_ENSURE_ARG_POINTER(aOther);
|
|
|
|
*aResult = FastEqualsConsideringDomain(aOther);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) {
|
|
*aResult = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->EqualsExceptRef(aOtherURI, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
|
|
NS_ENSURE_ARG_POINTER(aOther);
|
|
|
|
*aResult = FastSubsumes(aOther);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
|
|
NS_ENSURE_ARG_POINTER(aOther);
|
|
|
|
*aResult = FastSubsumesConsideringDomain(aOther);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
|
|
bool* aResult) {
|
|
NS_ENSURE_ARG_POINTER(aOther);
|
|
|
|
*aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) {
|
|
AssertIsOnMainThread();
|
|
return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
|
|
bool aAllowIfInheritsPrincipal,
|
|
uint64_t aInnerWindowID) {
|
|
AssertIsOnMainThread();
|
|
return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
|
|
aInnerWindowID);
|
|
}
|
|
|
|
nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
|
|
bool aAllowIfInheritsPrincipal,
|
|
bool aReport,
|
|
uint64_t aInnerWindowID) {
|
|
AssertIsOnMainThread(); // Accesses non-threadsafe URI flags and the
|
|
// non-threadsafe ExtensionPolicyService
|
|
NS_ENSURE_ARG_POINTER(aURI);
|
|
MOZ_ASSERT(
|
|
aReport || aInnerWindowID == 0,
|
|
"Why do we have an inner window id if we're not supposed to report?");
|
|
|
|
// Check the internal method first, which allows us to quickly approve loads
|
|
// for the System Principal.
|
|
if (MayLoadInternal(aURI)) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult rv;
|
|
if (aAllowIfInheritsPrincipal) {
|
|
// If the caller specified to allow loads of URIs that inherit
|
|
// our principal, allow the load if this URI inherits its principal.
|
|
bool doesInheritSecurityContext;
|
|
rv = NS_URIChainHasFlags(aURI,
|
|
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
|
&doesInheritSecurityContext);
|
|
if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
// Web Accessible Resources in MV2 Extensions are marked with
|
|
// URI_FETCHABLE_BY_ANYONE
|
|
bool fetchableByAnyone;
|
|
rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
|
|
&fetchableByAnyone);
|
|
if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Get the principal uri for the last flag check or error.
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
rv = GetURI(getter_AddRefs(prinURI));
|
|
if (!(NS_SUCCEEDED(rv) && prinURI)) {
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
}
|
|
|
|
// If MV3 Extension uris are web accessible by this principal it is allowed to
|
|
// load.
|
|
bool maybeWebAccessible = false;
|
|
NS_URIChainHasFlags(aURI, nsIProtocolHandler::WEBEXT_URI_WEB_ACCESSIBLE,
|
|
&maybeWebAccessible);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (maybeWebAccessible) {
|
|
bool isWebAccessible = false;
|
|
rv = ExtensionPolicyService::GetSingleton().SourceMayLoadExtensionURI(
|
|
prinURI, aURI, &isWebAccessible);
|
|
if (NS_SUCCEEDED(rv) && isWebAccessible) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
if (aReport) {
|
|
nsScriptSecurityManager::ReportError(
|
|
"CheckSameOriginError", prinURI, aURI,
|
|
mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
|
|
}
|
|
|
|
return NS_ERROR_DOM_BAD_URI;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
|
|
if (IsSystemPrincipal() || (AddonPolicyCore() && AddonAllowsLoad(aURI))) {
|
|
*aRes = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
*aRes = true;
|
|
// If we do not have a URI its always 3rd party.
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
|
|
return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
|
|
*aRes = true;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return aPrin->IsThirdPartyURI(prinURI, aRes);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::IsThirdPartyChannel(nsIChannel* aChan, bool* aRes) {
|
|
AssertIsOnMainThread();
|
|
if (IsSystemPrincipal()) {
|
|
// Nothing is 3rd party to the system principal.
|
|
*aRes = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
GetURI(getter_AddRefs(prinURI));
|
|
ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
|
|
return thirdPartyUtil->IsThirdPartyChannel(aChan, prinURI, aRes);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::IsSameOrigin(nsIURI* aURI, bool* aRes) {
|
|
*aRes = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
// Note that expanded and system principals return here, because they have
|
|
// no URI.
|
|
return NS_OK;
|
|
}
|
|
*aRes = nsScriptSecurityManager::SecurityCompareURIs(prinURI, aURI);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) {
|
|
AssertIsOnMainThread(); // URI_DANGEROUS_TO_LOAD is not threadsafe to query.
|
|
*aRes = false;
|
|
|
|
if (nsContentUtils::IsErrorPage(aURI)) {
|
|
*aRes = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
// The system principal is always allowed.
|
|
if (IsSystemPrincipal()) {
|
|
*aRes = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = GetURI(getter_AddRefs(uri));
|
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
|
|
|
bool hasFlags;
|
|
|
|
// Allow access to uris that cannot be loaded by web content.
|
|
rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
|
|
&hasFlags);
|
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
|
if (hasFlags) {
|
|
*aRes = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
// UI resources also get access.
|
|
rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
|
&hasFlags);
|
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
|
if (hasFlags) {
|
|
*aRes = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
auto policy = AddonPolicyCore();
|
|
*aRes = (policy && policy->IsPrivileged());
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::AllowsRelaxStrictFileOriginPolicy(nsIURI* aURI, bool* aRes) {
|
|
*aRes = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
*aRes = NS_RelaxStrictFileOriginPolicy(aURI, prinURI);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetPrefLightCacheKey(nsIURI* aURI, bool aWithCredentials,
|
|
const OriginAttributes& aOriginAttributes,
|
|
nsACString& _retval) {
|
|
_retval.Truncate();
|
|
constexpr auto space = " "_ns;
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = GetURI(getter_AddRefs(uri));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString scheme, host, port;
|
|
if (uri) {
|
|
uri->GetScheme(scheme);
|
|
uri->GetHost(host);
|
|
port.AppendInt(NS_GetRealPort(uri));
|
|
}
|
|
|
|
if (aWithCredentials) {
|
|
_retval.AssignLiteral("cred");
|
|
} else {
|
|
_retval.AssignLiteral("nocred");
|
|
}
|
|
|
|
nsAutoCString spec;
|
|
rv = aURI->GetSpec(spec);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString originAttributesSuffix;
|
|
aOriginAttributes.CreateSuffix(originAttributesSuffix);
|
|
|
|
_retval.Append(space + scheme + space + host + space + port + space + spec +
|
|
space + originAttributesSuffix);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow* aCheckWindow,
|
|
uint32_t* aRejectedReason,
|
|
bool* aOutAllowed) {
|
|
AssertIsOnMainThread();
|
|
*aRejectedReason = 0;
|
|
*aOutAllowed = false;
|
|
|
|
nsPIDOMWindowInner* win = nsPIDOMWindowInner::From(aCheckWindow);
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = GetURI(getter_AddRefs(uri));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aOutAllowed = ShouldAllowAccessFor(win, uri, aRejectedReason);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsNullPrincipal(bool* aResult) {
|
|
*aResult = Kind() == eNullPrincipal;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsContentPrincipal(bool* aResult) {
|
|
*aResult = Kind() == eContentPrincipal;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
|
|
*aResult = Kind() == eExpandedPrincipal;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
|
|
aSpec.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->GetAsciiSpec(aSpec);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetSpec(nsACString& aSpec) {
|
|
aSpec.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->GetSpec(aSpec);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetAsciiHost(nsACString& aHost) {
|
|
aHost.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->GetAsciiHost(aHost);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
|
|
aPrepath.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(prinURI);
|
|
return exposableURI->GetDisplayPrePath(aPrepath);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetExposableSpec(nsACString& aSpec) {
|
|
aSpec.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
nsCOMPtr<nsIURI> clone;
|
|
rv = NS_MutateURI(prinURI)
|
|
.SetQuery(""_ns)
|
|
.SetRef(""_ns)
|
|
.SetUserPass(""_ns)
|
|
.Finalize(clone);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return clone->GetAsciiSpec(aSpec);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetPrePath(nsACString& aPath) {
|
|
aPath.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->GetPrePath(aPath);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetFilePath(nsACString& aPath) {
|
|
aPath.Truncate();
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
return prinURI->GetFilePath(aPath);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
|
|
*aResult = IsSystemPrincipal();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
|
|
*aResult = AddonPolicyCore() || ContentScriptAddonPolicyCore();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
|
|
*aIsOnion = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString host;
|
|
rv = prinURI->GetHost(host);
|
|
if (NS_FAILED(rv)) {
|
|
return NS_OK;
|
|
}
|
|
*aIsOnion = StringEndsWith(host, ".onion"_ns);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP BasePrincipal::GetIsIpAddress(bool* aIsIpAddress) {
|
|
*aIsIpAddress = false;
|
|
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString host;
|
|
rv = prinURI->GetHost(host);
|
|
if (NS_FAILED(rv)) {
|
|
return NS_OK;
|
|
}
|
|
|
|
PRNetAddr prAddr;
|
|
memset(&prAddr, 0, sizeof(prAddr));
|
|
|
|
if (PR_StringToNetAddr(host.get(), &prAddr) == PR_SUCCESS) {
|
|
*aIsIpAddress = true;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress) {
|
|
*aIsIpAddress = false;
|
|
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
|
|
if (NS_FAILED(rv) || !ioService) {
|
|
return NS_OK;
|
|
}
|
|
rv = ioService->HostnameIsLocalIPAddress(prinURI, aIsIpAddress);
|
|
if (NS_FAILED(rv)) {
|
|
*aIsIpAddress = false;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetScheme(nsACString& aScheme) {
|
|
aScheme.Truncate();
|
|
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
|
|
return prinURI->GetScheme(aScheme);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
|
|
*aResult = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_WARN_IF(NS_FAILED(rv)) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
*aResult = prinURI->SchemeIs(aScheme);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
|
|
AssertIsOnMainThread();
|
|
*aResult = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
*aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::IsURIInList(const nsACString& aList, bool* aResult) {
|
|
*aResult = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
|
|
*aResult = nsContentUtils::IsURIInList(prinURI, nsCString(aList));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
|
|
AssertIsOnMainThread();
|
|
*aResult = false;
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = GetURI(getter_AddRefs(uri));
|
|
if (NS_FAILED(rv) || !uri) {
|
|
return NS_OK;
|
|
}
|
|
|
|
*aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsLoopbackHost(bool* aRes) {
|
|
AssertIsOnMainThread();
|
|
*aRes = false;
|
|
nsAutoCString host;
|
|
nsresult rv = GetHost(host);
|
|
// Swallow potential failure as this method is infallible.
|
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
|
|
|
*aRes = nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(host);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
|
|
AssertIsOnMainThread();
|
|
*flags = 0;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
if (!prinURI->SchemeIs("about")) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIAboutModule> aboutModule;
|
|
rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
|
|
if (NS_FAILED(rv) || !aboutModule) {
|
|
return rv;
|
|
}
|
|
return aboutModule->GetURIFlags(prinURI, flags);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetOriginAttributes(JSContext* aCx,
|
|
JS::MutableHandle<JS::Value> aVal) {
|
|
if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
|
|
MOZ_ASSERT(mOriginSuffix);
|
|
mOriginSuffix->ToUTF8String(aOriginAttributes);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
|
|
*aUserContextId = UserContextId();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
|
|
*aPrivateBrowsingId = PrivateBrowsingId();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsInIsolatedMozBrowserElement(
|
|
bool* aIsInIsolatedMozBrowserElement) {
|
|
*aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult BasePrincipal::GetAddonPolicy(
|
|
extensions::WebExtensionPolicy** aResult) {
|
|
AssertIsOnMainThread();
|
|
RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
|
|
policy.forget(aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult BasePrincipal::GetContentScriptAddonPolicy(
|
|
extensions::WebExtensionPolicy** aResult) {
|
|
RefPtr<extensions::WebExtensionPolicy> policy(ContentScriptAddonPolicy());
|
|
policy.forget(aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
|
|
AssertIsOnMainThread();
|
|
RefPtr<extensions::WebExtensionPolicyCore> core = AddonPolicyCore();
|
|
return core ? core->GetMainThreadPolicy() : nullptr;
|
|
}
|
|
|
|
RefPtr<extensions::WebExtensionPolicyCore> BasePrincipal::AddonPolicyCore() {
|
|
if (Is<ContentPrincipal>()) {
|
|
return As<ContentPrincipal>()->AddonPolicyCore();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
|
|
if (auto policy = AddonPolicyCore()) {
|
|
return policy->HasPermission(aPerm);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
|
|
if (Is<ExpandedPrincipal>()) {
|
|
return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
bool BasePrincipal::OverridesCSP(nsIPrincipal* aDocumentPrincipal) {
|
|
MOZ_ASSERT(aDocumentPrincipal);
|
|
|
|
// Expanded principals override CSP if and only if they subsume the document
|
|
// principal.
|
|
if (mKind == eExpandedPrincipal) {
|
|
return FastSubsumes(aDocumentPrincipal);
|
|
}
|
|
// Extension principals always override the CSP of non-extension principals.
|
|
// This is primarily for the sake of their stylesheets, which are usually
|
|
// loaded from channels and cannot have expanded principals.
|
|
return (AddonPolicyCore() &&
|
|
!BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicyCore());
|
|
}
|
|
|
|
already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
|
|
nsIURI* aURI, const OriginAttributes& aAttrs, nsIURI* aInitialDomain) {
|
|
MOZ_ASSERT(aURI);
|
|
|
|
nsAutoCString originNoSuffix;
|
|
nsresult rv =
|
|
ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
|
|
if (NS_FAILED(rv)) {
|
|
// If the generation of the origin fails, we still want to have a valid
|
|
// principal. Better to return a null principal here.
|
|
return NullPrincipal::Create(aAttrs);
|
|
}
|
|
|
|
return CreateContentPrincipal(aURI, aAttrs, originNoSuffix, aInitialDomain);
|
|
}
|
|
|
|
already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
|
|
nsIURI* aURI, const OriginAttributes& aAttrs,
|
|
const nsACString& aOriginNoSuffix, nsIURI* aInitialDomain) {
|
|
MOZ_ASSERT(aURI);
|
|
MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
|
|
|
|
// If the URI is supposed to inherit the security context of whoever loads it,
|
|
// we shouldn't make a content principal for it.
|
|
bool inheritsPrincipal;
|
|
nsresult rv = NS_URIChainHasFlags(
|
|
aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
|
&inheritsPrincipal);
|
|
if (NS_FAILED(rv) || inheritsPrincipal) {
|
|
return NullPrincipal::Create(aAttrs);
|
|
}
|
|
|
|
// Check whether the URI knows what its principal is supposed to be.
|
|
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
|
|
nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
|
|
do_QueryInterface(aURI);
|
|
if (uriWithSpecialOrigin) {
|
|
nsCOMPtr<nsIURI> origin;
|
|
rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return nullptr;
|
|
}
|
|
MOZ_ASSERT(origin);
|
|
OriginAttributes attrs;
|
|
RefPtr<BasePrincipal> principal =
|
|
CreateContentPrincipal(origin, attrs, aInitialDomain);
|
|
return principal.forget();
|
|
}
|
|
#endif
|
|
|
|
nsCOMPtr<nsIPrincipal> blobPrincipal;
|
|
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
|
|
aURI, getter_AddRefs(blobPrincipal))) {
|
|
MOZ_ASSERT(blobPrincipal);
|
|
MOZ_ASSERT(!aInitialDomain,
|
|
"an initial domain for a blob URI makes no sense");
|
|
RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
|
|
return principal.forget();
|
|
}
|
|
|
|
// Mint a content principal.
|
|
RefPtr<ContentPrincipal> principal =
|
|
new ContentPrincipal(aURI, aAttrs, aOriginNoSuffix, aInitialDomain);
|
|
return principal.forget();
|
|
}
|
|
|
|
already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
|
|
const nsACString& aOrigin) {
|
|
MOZ_ASSERT(!StringBeginsWith(aOrigin, "["_ns),
|
|
"CreateContentPrincipal does not support System and Expanded "
|
|
"principals");
|
|
|
|
MOZ_ASSERT(
|
|
!StringBeginsWith(aOrigin, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME ":")),
|
|
"CreateContentPrincipal does not support NullPrincipal");
|
|
|
|
nsAutoCString originNoSuffix;
|
|
OriginAttributes attrs;
|
|
if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
|
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
|
|
|
return BasePrincipal::CreateContentPrincipal(uri, attrs);
|
|
}
|
|
|
|
already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
|
|
const OriginAttributes& aOriginAttributes) {
|
|
if (NS_WARN_IF(!IsContentPrincipal())) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsAutoCString originNoSuffix;
|
|
nsresult rv = GetOriginNoSuffix(originNoSuffix);
|
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
MOZ_ALWAYS_SUCCEEDS(GetURI(getter_AddRefs(uri)));
|
|
|
|
// XXX: This does not copy over the domain. Should it?
|
|
RefPtr<ContentPrincipal> copy =
|
|
new ContentPrincipal(uri, aOriginAttributes, originNoSuffix, nullptr);
|
|
return copy.forget();
|
|
}
|
|
|
|
extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
|
|
AssertIsOnMainThread();
|
|
RefPtr<extensions::WebExtensionPolicyCore> core =
|
|
ContentScriptAddonPolicyCore();
|
|
return core ? core->GetMainThreadPolicy() : nullptr;
|
|
}
|
|
|
|
RefPtr<extensions::WebExtensionPolicyCore>
|
|
BasePrincipal::ContentScriptAddonPolicyCore() {
|
|
if (!Is<ExpandedPrincipal>()) {
|
|
return nullptr;
|
|
}
|
|
|
|
auto* expanded = As<ExpandedPrincipal>();
|
|
for (const auto& prin : expanded->AllowList()) {
|
|
if (RefPtr<extensions::WebExtensionPolicyCore> policy =
|
|
BasePrincipal::Cast(prin)->AddonPolicyCore()) {
|
|
return policy;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
|
|
bool aExplicit /* = false */) {
|
|
if (Is<ExpandedPrincipal>()) {
|
|
return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
|
|
}
|
|
if (auto policy = AddonPolicyCore()) {
|
|
return policy->CanAccessURI(aURI, aExplicit);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) {
|
|
aKey.Truncate();
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = GetURI(getter_AddRefs(uri));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
|
|
|
// The special handling of the file scheme should be consistent with
|
|
// GetStorageOriginKey.
|
|
|
|
nsAutoCString baseDomain;
|
|
rv = uri->GetAsciiHost(baseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (baseDomain.IsEmpty() && uri->SchemeIs("file")) {
|
|
nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = url->GetDirectory(baseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
} else {
|
|
nsCOMPtr<nsIEffectiveTLDService> eTLDService(
|
|
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString eTLDplusOne;
|
|
rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
baseDomain = eTLDplusOne;
|
|
} else if (rv == NS_ERROR_HOST_IS_IP_ADDRESS ||
|
|
rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
|
|
rv = NS_OK;
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
OriginAttributesRef().CreateSuffix(aKey);
|
|
|
|
nsAutoCString subdomainsDBKey;
|
|
rv = dom::StorageUtils::CreateReversedDomain(baseDomain, subdomainsDBKey);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
aKey.Append(':');
|
|
aKey.Append(subdomainsDBKey);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetNextSubDomainPrincipal(
|
|
nsIPrincipal** aNextSubDomainPrincipal) {
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = GetURI(getter_AddRefs(uri));
|
|
if (NS_FAILED(rv) || !uri) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString host;
|
|
rv = uri->GetHost(host);
|
|
if (NS_FAILED(rv) || host.IsEmpty()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCString subDomain;
|
|
rv = nsEffectiveTLDService::GetInstance()->GetNextSubDomain(host, subDomain);
|
|
|
|
if (NS_FAILED(rv) || subDomain.IsEmpty()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> subDomainURI;
|
|
rv = NS_MutateURI(uri).SetHost(subDomain).Finalize(subDomainURI);
|
|
if (NS_FAILED(rv) || !subDomainURI) {
|
|
return NS_OK;
|
|
}
|
|
// Copy the attributes over
|
|
mozilla::OriginAttributes attrs = OriginAttributesRef();
|
|
|
|
if (!StaticPrefs::permissions_isolateBy_userContext()) {
|
|
// Disable userContext for permissions.
|
|
attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
|
|
}
|
|
RefPtr<nsIPrincipal> principal =
|
|
mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI, attrs);
|
|
|
|
if (!principal) {
|
|
return NS_OK;
|
|
}
|
|
principal.forget(aNextSubDomainPrincipal);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) {
|
|
aOriginKey.Truncate();
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = GetURI(getter_AddRefs(uri));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
|
|
|
// The special handling of the file scheme should be consistent with
|
|
// GetLocalStorageQuotaKey.
|
|
|
|
nsAutoCString domainOrigin;
|
|
rv = uri->GetAsciiHost(domainOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (domainOrigin.IsEmpty()) {
|
|
// For the file:/// protocol use the exact directory as domain.
|
|
if (uri->SchemeIs("file")) {
|
|
nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = url->GetDirectory(domainOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
|
|
// Append reversed domain
|
|
nsAutoCString reverseDomain;
|
|
rv = dom::StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
aOriginKey.Append(reverseDomain);
|
|
|
|
// Append scheme
|
|
nsAutoCString scheme;
|
|
rv = uri->GetScheme(scheme);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
aOriginKey.Append(':');
|
|
aOriginKey.Append(scheme);
|
|
|
|
// Append port if any
|
|
int32_t port = NS_GetRealPort(uri);
|
|
if (port != -1) {
|
|
aOriginKey.Append(nsPrintfCString(":%d", port));
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) {
|
|
AssertIsOnMainThread();
|
|
*aIsScriptAllowedByPolicy = false;
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
return NS_OK;
|
|
}
|
|
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
|
if (!ssm) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy);
|
|
}
|
|
|
|
bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
|
|
MOZ_ASSERT(IsInitialized());
|
|
MOZ_ASSERT(aOther.IsInitialized());
|
|
return mPrincipal->FastEquals(aOther.mPrincipal);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy,
|
|
nsIReferrerInfo** _retval) {
|
|
nsCOMPtr<nsIURI> prinURI;
|
|
RefPtr<dom::ReferrerInfo> info;
|
|
nsresult rv = GetURI(getter_AddRefs(prinURI));
|
|
if (NS_FAILED(rv) || !prinURI) {
|
|
info = new dom::ReferrerInfo(nullptr);
|
|
info.forget(_retval);
|
|
return NS_OK;
|
|
}
|
|
info = new dom::ReferrerInfo(prinURI, aReferrerPolicy);
|
|
info.forget(_retval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::GetPrecursorPrincipal(nsIPrincipal** aPrecursor) {
|
|
*aPrecursor = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_ADDREF(BasePrincipal::Deserializer)
|
|
NS_IMPL_RELEASE(BasePrincipal::Deserializer)
|
|
|
|
NS_INTERFACE_MAP_BEGIN(BasePrincipal::Deserializer)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
NS_INTERFACE_MAP_ENTRY(nsISerializable)
|
|
if (mPrincipal) {
|
|
return mPrincipal->QueryInterface(aIID, aInstancePtr);
|
|
} else
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMETHODIMP
|
|
BasePrincipal::Deserializer::Write(nsIObjectOutputStream* aStream) {
|
|
// Read is used still for legacy principals
|
|
MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla
|