зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1497301
part 4. Simplify Location::CheckURL. r=bholley
The main change is to just use the principal bindings pass us to do our CheckLoadURI check. If we do that, we don't have to care about the current JSContext.
This commit is contained in:
Родитель
f99994ef07
Коммит
5a0e236dba
|
@ -61,92 +61,94 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Location, mInnerWindow)
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Location)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Location)
|
||||
|
||||
nsresult
|
||||
Location::CheckURL(nsIURI* aURI, nsDocShellLoadInfo** aLoadInfo)
|
||||
already_AddRefed<nsDocShellLoadInfo>
|
||||
Location::CheckURL(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
*aLoadInfo = nullptr;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_NOT_AVAILABLE);
|
||||
if (NS_WARN_IF(!docShell)) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
|
||||
nsCOMPtr<nsIURI> sourceURI;
|
||||
net::ReferrerPolicy referrerPolicy = net::RP_Unset;
|
||||
|
||||
if (JSContext *cx = nsContentUtils::GetCurrentJSContext()) {
|
||||
// No cx means that there's no JS running, or at least no JS that
|
||||
// was run through code that properly pushed a context onto the
|
||||
// context stack (as all code that runs JS off of web pages
|
||||
// does). We won't bother with security checks in this case, but
|
||||
// we need to create the loadinfo etc.
|
||||
// Get security manager.
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
if (NS_WARN_IF(!ssm)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get security manager.
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
NS_ENSURE_STATE(ssm);
|
||||
// Check to see if URI is allowed.
|
||||
nsresult rv = ssm->CheckLoadURIWithPrincipal(&aSubjectPrincipal, aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
nsAutoCString spec;
|
||||
aURI->GetSpec(spec);
|
||||
aRv.ThrowTypeError<MSG_URL_NOT_LOADABLE>(NS_ConvertUTF8toUTF16(spec));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check to see if URI is allowed.
|
||||
nsresult rv = ssm->CheckLoadURIFromScript(cx, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Make the load's referrer reflect changes to the document's URI caused by
|
||||
// push/replaceState, if possible. First, get the document corresponding to
|
||||
// fp. If the document's original URI (i.e. its URI before
|
||||
// push/replaceState) matches the principal's URI, use the document's
|
||||
// current URI as the referrer. If they don't match, use the principal's
|
||||
// URI.
|
||||
//
|
||||
// The triggering principal for this load should be the principal of the
|
||||
// incumbent document (which matches where the referrer information is
|
||||
// coming from) when there is an incumbent document, and the subject
|
||||
// principal otherwise. Note that the URI in the triggering principal
|
||||
// may not match the referrer URI in various cases, notably including
|
||||
// the cases when the incumbent document's document URI was modified
|
||||
// after the document was loaded.
|
||||
|
||||
// Make the load's referrer reflect changes to the document's URI caused by
|
||||
// push/replaceState, if possible. First, get the document corresponding to
|
||||
// fp. If the document's original URI (i.e. its URI before
|
||||
// push/replaceState) matches the principal's URI, use the document's
|
||||
// current URI as the referrer. If they don't match, use the principal's
|
||||
// URI.
|
||||
//
|
||||
// The triggering principal for this load should be the principal of the
|
||||
// incumbent document (which matches where the referrer information is
|
||||
// coming from) when there is an incumbent document, and the subject
|
||||
// principal otherwise. Note that the URI in the triggering principal
|
||||
// may not match the referrer URI in various cases, notably including
|
||||
// the cases when the incumbent document's document URI was modified
|
||||
// after the document was loaded.
|
||||
nsCOMPtr<nsPIDOMWindowInner> incumbent =
|
||||
do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
|
||||
nsCOMPtr<nsIDocument> doc = incumbent ? incumbent->GetDoc() : nullptr;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> incumbent =
|
||||
do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
|
||||
nsCOMPtr<nsIDocument> doc = incumbent ? incumbent->GetDoc() : nullptr;
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI, principalURI;
|
||||
docOriginalURI = doc->GetOriginalURI();
|
||||
docCurrentURI = doc->GetDocumentURI();
|
||||
rv = doc->NodePrincipal()->GetURI(getter_AddRefs(principalURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI, principalURI;
|
||||
docOriginalURI = doc->GetOriginalURI();
|
||||
docCurrentURI = doc->GetDocumentURI();
|
||||
rv = doc->NodePrincipal()->GetURI(getter_AddRefs(principalURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
triggeringPrincipal = doc->NodePrincipal();
|
||||
referrerPolicy = doc->GetReferrerPolicy();
|
||||
|
||||
triggeringPrincipal = doc->NodePrincipal();
|
||||
referrerPolicy = doc->GetReferrerPolicy();
|
||||
|
||||
bool urisEqual = false;
|
||||
if (docOriginalURI && docCurrentURI && principalURI) {
|
||||
principalURI->Equals(docOriginalURI, &urisEqual);
|
||||
}
|
||||
if (urisEqual) {
|
||||
sourceURI = docCurrentURI;
|
||||
}
|
||||
else {
|
||||
// Use principalURI as long as it is not an NullPrincipalURI. We
|
||||
// could add a method such as GetReferrerURI to principals to make this
|
||||
// cleaner, but given that we need to start using Source Browsing
|
||||
// Context for referrer (see Bug 960639) this may be wasted effort at
|
||||
// this stage.
|
||||
if (principalURI) {
|
||||
bool isNullPrincipalScheme;
|
||||
rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME,
|
||||
&isNullPrincipalScheme);
|
||||
if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
|
||||
sourceURI = principalURI;
|
||||
}
|
||||
bool urisEqual = false;
|
||||
if (docOriginalURI && docCurrentURI && principalURI) {
|
||||
principalURI->Equals(docOriginalURI, &urisEqual);
|
||||
}
|
||||
if (urisEqual) {
|
||||
sourceURI = docCurrentURI;
|
||||
}
|
||||
else {
|
||||
// Use principalURI as long as it is not an NullPrincipalURI. We
|
||||
// could add a method such as GetReferrerURI to principals to make this
|
||||
// cleaner, but given that we need to start using Source Browsing
|
||||
// Context for referrer (see Bug 960639) this may be wasted effort at
|
||||
// this stage.
|
||||
if (principalURI) {
|
||||
bool isNullPrincipalScheme;
|
||||
rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME,
|
||||
&isNullPrincipalScheme);
|
||||
if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
|
||||
sourceURI = principalURI;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No document; determine triggeringPrincipal by quering the
|
||||
// subjectPrincipal, wich is the principal of the current JS
|
||||
// compartment, or a null principal in case there is no
|
||||
// compartment yet.
|
||||
triggeringPrincipal = nsContentUtils::SubjectPrincipal();
|
||||
}
|
||||
} else {
|
||||
// No document; just use our subject principal as the triggering principal.
|
||||
triggeringPrincipal = &aSubjectPrincipal;
|
||||
}
|
||||
|
||||
// Create load info
|
||||
|
@ -159,9 +161,7 @@ Location::CheckURL(nsIURI* aURI, nsDocShellLoadInfo** aLoadInfo)
|
|||
loadInfo->SetReferrerPolicy(referrerPolicy);
|
||||
}
|
||||
|
||||
loadInfo.swap(*aLoadInfo);
|
||||
|
||||
return NS_OK;
|
||||
return loadInfo.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -207,14 +207,14 @@ Location::GetURI(nsIURI** aURI, bool aGetInnermostURI)
|
|||
}
|
||||
|
||||
void
|
||||
Location::SetURI(nsIURI* aURI, ErrorResult& aRv, bool aReplace)
|
||||
Location::SetURI(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv, bool aReplace)
|
||||
{
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
|
||||
if (docShell) {
|
||||
RefPtr<nsDocShellLoadInfo> loadInfo;
|
||||
|
||||
if (NS_FAILED(CheckURL(aURI, getter_AddRefs(loadInfo)))) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
RefPtr<nsDocShellLoadInfo> loadInfo =
|
||||
CheckURL(aURI, aSubjectPrincipal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -308,7 +308,7 @@ Location::SetHash(const nsAString& aHash,
|
|||
return;
|
||||
}
|
||||
|
||||
SetURI(uri, aRv);
|
||||
SetURI(uri, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -362,7 +362,7 @@ Location::SetHost(const nsAString& aHost,
|
|||
return;
|
||||
}
|
||||
|
||||
SetURI(uri, aRv);
|
||||
SetURI(uri, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -407,7 +407,7 @@ Location::SetHostname(const nsAString& aHostname,
|
|||
return;
|
||||
}
|
||||
|
||||
SetURI(uri, aRv);
|
||||
SetURI(uri, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -433,21 +433,24 @@ Location::GetHref(nsAString& aHref)
|
|||
|
||||
void
|
||||
Location::SetHref(const nsAString& aHref,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
DoSetHref(aHref, false, aRv);
|
||||
DoSetHref(aHref, aSubjectPrincipal, false, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
Location::DoSetHref(const nsAString& aHref, bool aReplace, ErrorResult& aRv)
|
||||
Location::DoSetHref(const nsAString& aHref, nsIPrincipal& aSubjectPrincipal,
|
||||
bool aReplace, ErrorResult& aRv)
|
||||
{
|
||||
// Get the source of the caller
|
||||
nsCOMPtr<nsIURI> base = GetSourceBaseURL();
|
||||
SetHrefWithBase(aHref, base, aReplace, aRv);
|
||||
SetHrefWithBase(aHref, base, aSubjectPrincipal, aReplace, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
Location::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
bool aReplace, ErrorResult& aRv)
|
||||
{
|
||||
nsresult result;
|
||||
|
@ -490,7 +493,7 @@ Location::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
|
|||
}
|
||||
}
|
||||
|
||||
SetURI(newUri, aRv, aReplace || inScriptTag);
|
||||
SetURI(newUri, aSubjectPrincipal, aRv, aReplace || inScriptTag);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -575,7 +578,7 @@ Location::SetPathname(const nsAString& aPathname,
|
|||
return;
|
||||
}
|
||||
|
||||
SetURI(uri, aRv);
|
||||
SetURI(uri, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -644,7 +647,7 @@ Location::SetPort(const nsAString& aPort,
|
|||
return;
|
||||
}
|
||||
|
||||
SetURI(uri, aRv);
|
||||
SetURI(uri, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -741,7 +744,7 @@ Location::SetProtocol(const nsAString& aProtocol,
|
|||
return;
|
||||
}
|
||||
|
||||
SetURI(uri, aRv);
|
||||
SetURI(uri, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -806,7 +809,7 @@ Location::SetSearch(const nsAString& aSearch,
|
|||
return;
|
||||
}
|
||||
|
||||
SetURI(uri, aRv);
|
||||
SetURI(uri, aSubjectPrincipal, aRv);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -862,7 +865,7 @@ Location::Replace(const nsAString& aUrl,
|
|||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
DoSetHref(aUrl, true, aRv);
|
||||
DoSetHref(aUrl, aSubjectPrincipal, true, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -875,7 +878,7 @@ Location::Assign(const nsAString& aUrl,
|
|||
return;
|
||||
}
|
||||
|
||||
DoSetHref(aUrl, false, aRv);
|
||||
DoSetHref(aUrl, aSubjectPrincipal, false, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI>
|
||||
|
|
|
@ -68,6 +68,7 @@ public:
|
|||
}
|
||||
|
||||
void SetHref(const nsAString& aHref,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aError);
|
||||
|
||||
void GetOrigin(nsAString& aOrigin,
|
||||
|
@ -166,17 +167,27 @@ protected:
|
|||
// Note, this method can return NS_OK with a null value for aURL. This happens
|
||||
// if the docShell is null.
|
||||
nsresult GetURI(nsIURI** aURL, bool aGetInnermostURI = false);
|
||||
void SetURI(nsIURI* aURL, ErrorResult& aRv, bool aReplace = false);
|
||||
void SetURI(nsIURI* aURL, nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv, bool aReplace = false);
|
||||
void SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
bool aReplace, ErrorResult& aRv);
|
||||
|
||||
// Helper for Assign/SetHref/Replace
|
||||
void DoSetHref(const nsAString& aHref, bool aReplace, ErrorResult& aRv);
|
||||
void DoSetHref(const nsAString& aHref, nsIPrincipal& aSubjectPrincipal,
|
||||
bool aReplace, ErrorResult& aRv);
|
||||
|
||||
// Get the base URL we should be using for our relative URL
|
||||
// resolution for SetHref/Assign/Replace.
|
||||
already_AddRefed<nsIURI> GetSourceBaseURL();
|
||||
nsresult CheckURL(nsIURI *url, nsDocShellLoadInfo** aLoadInfo);
|
||||
|
||||
// Check whether it's OK to load the given url with the given subject
|
||||
// principal, and if so construct the right nsDocShellLoadInfo for the load
|
||||
// and return it.
|
||||
already_AddRefed<nsDocShellLoadInfo> CheckURL(nsIURI *url,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool CallerSubsumes(nsIPrincipal* aSubjectPrincipal);
|
||||
|
||||
nsString mCachedHash;
|
||||
|
|
|
@ -116,3 +116,4 @@ MSG_DEF(MSG_INVALID_PANNERNODE_REFDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The refDis
|
|||
MSG_DEF(MSG_INVALID_PANNERNODE_MAXDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The maxDistance value passed to PannerNode must be positive.")
|
||||
MSG_DEF(MSG_INVALID_PANNERNODE_ROLLOFF_ERROR, 0, JSEXN_RANGEERR, "The rolloffFactor value passed to PannerNode must not be negative.")
|
||||
MSG_DEF(MSG_NOT_ARRAY_NOR_UNDEFINED, 1, JSEXN_TYPEERR, "{0} is neither an array nor undefined.")
|
||||
MSG_DEF(MSG_URL_NOT_LOADABLE, 1, JSEXN_TYPEERR, "Access to '{0}' from script denied.")
|
||||
|
|
|
@ -20,7 +20,7 @@ interface Location {
|
|||
[Throws, NeedsSubjectPrincipal]
|
||||
stringifier;
|
||||
|
||||
[Throws, CrossOriginWritable, GetterNeedsSubjectPrincipal]
|
||||
[Throws, CrossOriginWritable, NeedsSubjectPrincipal]
|
||||
attribute USVString href;
|
||||
[Throws, NeedsSubjectPrincipal]
|
||||
readonly attribute USVString origin;
|
||||
|
|
|
@ -5,36 +5,24 @@
|
|||
[XHR: file://example:1/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[Location's href: file://example:1/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[URL's href: file://example:test/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[XHR: file://example:test/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[Location's href: file://example:test/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[URL's href: file://example%/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[XHR: file://example%/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[Location's href: file://example%/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[URL's href: file://[example\]/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[XHR: file://[example\]/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[Location's href: file://[example\]/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
[Location's href: http://user:pass@/ should throw]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче