diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8c03863994..7116c56c67 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -42,7 +42,6 @@ #include "WindowNamedPropertiesHandler.h" #include "nsFrameSelection.h" #include "nsNetUtil.h" -#include "nsIConsoleService.h" // Helper Classes #include "nsJSUtils.h" @@ -1551,12 +1550,6 @@ nsGlobalWindow::FreeInnerObjects(bool aForDocumentOpen) { NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window"); - // Prune messages related to this window in the console cache - nsCOMPtr console(do_GetService("@mozilla.org/consoleservice;1")); - if (console) { - console->ClearMessagesForWindowID(mWindowID); - } - // Make sure that this is called before we null out the document and // other members that the window destroyed observers could // re-create. diff --git a/dom/canvas/WebGL2ContextTransformFeedback.cpp b/dom/canvas/WebGL2ContextTransformFeedback.cpp index a1db81b78c..258a7d0e8f 100644 --- a/dom/canvas/WebGL2ContextTransformFeedback.cpp +++ b/dom/canvas/WebGL2ContextTransformFeedback.cpp @@ -42,7 +42,7 @@ WebGL2Context::DeleteTransformFeedback(WebGLTransformFeedback* tf) return; if (mBoundTransformFeedback == tf) - BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, tf); + BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, nullptr); tf->RequestDelete(); } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index ec895ed406..7e9b818353 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -4206,13 +4206,14 @@ ContentParent::GetConsoleService() return mConsoleService.get(); } + // XXXkhuey everything about this is terrible. // Get the ConsoleService by CID rather than ContractID, so that we // can cast the returned pointer to an nsConsoleService (rather than // just an nsIConsoleService). This allows us to call the non-idl function // nsConsoleService::LogMessageWithMode. NS_DEFINE_CID(consoleServiceCID, NS_CONSOLESERVICE_CID); - nsCOMPtr consoleService(do_GetService(consoleServiceCID)); - mConsoleService = consoleService; + nsCOMPtr consoleService(do_GetService(consoleServiceCID)); + mConsoleService = static_cast(consoleService.get()); return mConsoleService.get(); } diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties index b47b1f735f..6096defff8 100644 --- a/dom/locales/en-US/chrome/security/security.properties +++ b/dom/locales/en-US/chrome/security/security.properties @@ -6,7 +6,6 @@ BlockMixedActiveContent = Blocked loading mixed active content "%1$S" # CORS # LOCALIZATION NOTE: Do not translate "Access-Control-Allow-Origin", Access-Control-Allow-Credentials, Access-Control-Allow-Methods, Access-Control-Allow-Headers CORSDisabled=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS disabled). -CORSRequestFailed=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS request failed). CORSRequestNotHttp=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS request not http). CORSMissingAllowOrigin=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS header 'Access-Control-Allow-Origin' missing). CORSAllowOriginNotMatchingOrigin=Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at %1$S. (Reason: CORS header 'Access-Control-Allow-Origin' does not match '%2$S'). diff --git a/dom/media/test/test_texttrackcue.html b/dom/media/test/test_texttrackcue.html index 709ca13e25..29fc9b3cf8 100644 --- a/dom/media/test/test_texttrackcue.html +++ b/dom/media/test/test_texttrackcue.html @@ -45,11 +45,13 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.regions.enabled", true]]}, is(cueList.length, 6, "Cue list length should be 6."); // Check that the typedef of TextTrackCue works in Gecko. - is(window.TextTrackCue, undefined, "TextTrackCue should be undefined."); + isnot(window.TextTrackCue, undefined, "TextTrackCue should be defined."); isnot(window.VTTCue, undefined, "VTTCue should be defined."); // Check if first cue was parsed correctly. var cue = cueList[0]; + ok(cue instanceof TextTrackCue, "Cue should be an instanceof TextTrackCue."); + ok(cue instanceof VTTCue, "Cue should be an instanceof VTTCue."); is(cue.id, "1", "Cue's ID should be 1."); is(cue.startTime, 0.5, "Cue's start time should be 0.5."); is(cue.endTime, 0.7, "Cue's end time should be 0.7."); diff --git a/dom/security/nsCORSListenerProxy.cpp b/dom/security/nsCORSListenerProxy.cpp index a3c28cc9fa..d736ce18d5 100644 --- a/dom/security/nsCORSListenerProxy.cpp +++ b/dom/security/nsCORSListenerProxy.cpp @@ -537,14 +537,8 @@ nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest) // Check if the request failed nsresult status; nsresult rv = aRequest->GetStatus(&status); - if (NS_FAILED(rv)) { - LogBlockedRequest(aRequest, "CORSRequestFailed", nullptr); - return rv; - } - if (NS_FAILED(status)) { - LogBlockedRequest(aRequest, "CORSRequestFailed", nullptr); - return status; - } + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_SUCCESS(status, status); // Test that things worked on a HTTP level nsCOMPtr http = do_QueryInterface(aRequest); @@ -1312,6 +1306,12 @@ NS_StartCORSPreflight(nsIChannel* aRequestChannel, rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS")); NS_ENSURE_SUCCESS(rv, rv); + + // Preflight requests should never be intercepted by service workers. + nsCOMPtr preInternal = do_QueryInterface(preflightChannel); + if (preInternal) { + preInternal->ForceNoIntercept(); + } // Set up listener which will start the original channel nsCOMPtr preflightListener = diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 7f359e16c8..a54a670b2b 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -1277,6 +1277,8 @@ var interfaceNamesInGlobalScope = "TextMetrics", // IMPORTANT: Do not change this list without review from a DOM peer! "TextTrack", +// IMPORTANT: Do not change this list without review from a DOM peer! + "TextTrackCue", // IMPORTANT: Do not change this list without review from a DOM peer! "TextTrackCueList", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/TextTrackCue.webidl b/dom/webidl/TextTrackCue.webidl new file mode 100644 index 0000000000..e076fc4215 --- /dev/null +++ b/dom/webidl/TextTrackCue.webidl @@ -0,0 +1,21 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + * + * The origin of this IDL file is + * https://html.spec.whatwg.org/#texttrackcue + */ + +[Pref="media.webvtt.enabled"] +interface TextTrackCue : EventTarget { + readonly attribute TextTrack? track; + + attribute DOMString id; + attribute double startTime; + attribute double endTime; + attribute boolean pauseOnExit; + + attribute EventHandler onenter; + attribute EventHandler onexit; +}; \ No newline at end of file diff --git a/dom/webidl/VTTCue.webidl b/dom/webidl/VTTCue.webidl index 41110ba8dc..be952523de 100644 --- a/dom/webidl/VTTCue.webidl +++ b/dom/webidl/VTTCue.webidl @@ -4,7 +4,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. * * The origin of this IDL file is - * http://www.whatwg.org/specs/web-apps/current-work/#texttrackcue + * http://dev.w3.org/html5/webvtt/#the-vttcue-interface */ enum AutoKeyword { "auto" }; @@ -25,13 +25,7 @@ enum DirectionSetting { [Constructor(double startTime, double endTime, DOMString text), Pref="media.webvtt.enabled"] -interface VTTCue : EventTarget { - readonly attribute TextTrack? track; - - attribute DOMString id; - attribute double startTime; - attribute double endTime; - attribute boolean pauseOnExit; +interface VTTCue : TextTrackCue { [Pref="media.webvtt.regions.enabled"] attribute VTTRegion? region; attribute DirectionSetting vertical; @@ -48,10 +42,6 @@ interface VTTCue : EventTarget { attribute AlignSetting align; attribute DOMString text; DocumentFragment getCueAsHTML(); - - attribute EventHandler onenter; - - attribute EventHandler onexit; }; // Mozilla extensions. diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 4693dded4d..5efa250b9c 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -524,6 +524,7 @@ WEBIDL_FILES = [ 'TextDecoder.webidl', 'TextEncoder.webidl', 'TextTrack.webidl', + 'TextTrackCue.webidl', 'TextTrackCueList.webidl', 'TextTrackList.webidl', 'ThreadSafeChromeUtils.webidl', diff --git a/dom/workers/test/serviceworkers/fetch/fetch_tests.js b/dom/workers/test/serviceworkers/fetch/fetch_tests.js index 1aeaac8c73..1809eab7d0 100644 --- a/dom/workers/test/serviceworkers/fetch/fetch_tests.js +++ b/dom/workers/test/serviceworkers/fetch/fetch_tests.js @@ -140,6 +140,12 @@ fetchXHR('http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_serv finish(); }); +// Test that CORS preflight requests cannot be intercepted +fetchXHR('http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*', null, function(xhr) { + my_ok(xhr.status == 0, "cross origin load with incorrect headers should be a failure"); + finish(); +}, [["X-Unsafe", "unsafe"]]); + // Test that when the page fetches a url the controlling SW forces a redirect to // another location. This other location fetch should also be intercepted by // the SW. diff --git a/dom/workers/test/serviceworkers/fetch_event_worker.js b/dom/workers/test/serviceworkers/fetch_event_worker.js index 1898931251..6b374507dc 100644 --- a/dom/workers/test/serviceworkers/fetch_event_worker.js +++ b/dom/workers/test/serviceworkers/fetch_event_worker.js @@ -7,6 +7,16 @@ onfetch = function(ev) { )); } + else if (ev.request.url.includes('file_CrossSiteXHR_server.sjs')) { + // N.B. this response would break the rules of CORS if it were allowed, but + // this test relies upon the preflight request not being intercepted and + // thus this response should not be used. + if (ev.request.method == 'OPTIONS') { + ev.respondWith(new Response('', {headers: {'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': 'X-Unsafe'}})) + } + } + else if (ev.request.url.includes("synthesized-404.txt")) { ev.respondWith(Promise.resolve( new Response("synthesized response body", { status: 404 }) diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index c546d09b2f..3c775afc58 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -16,8 +16,15 @@ #include "nsNullPrincipal.h" #include "nsServiceManagerUtils.h" #include "nsString.h" +#include "nsTArray.h" namespace mozilla { +namespace net { +class OptionalLoadInfoArgs; +} + +using namespace mozilla::net; + namespace ipc { already_AddRefed @@ -220,66 +227,90 @@ PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, nsresult LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, - mozilla::net::LoadInfoArgs* aLoadInfoArgs) + OptionalLoadInfoArgs* aOptionalLoadInfoArgs) { - nsresult rv = NS_OK; - - if (aLoadInfo) { - rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(), - &aLoadInfoArgs->requestingPrincipalInfo()); - NS_ENSURE_SUCCESS(rv, rv); - rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), - &aLoadInfoArgs->triggeringPrincipalInfo()); - NS_ENSURE_SUCCESS(rv, rv); - aLoadInfoArgs->securityFlags() = aLoadInfo->GetSecurityFlags(); - aLoadInfoArgs->contentPolicyType() = aLoadInfo->InternalContentPolicyType(); - aLoadInfoArgs->upgradeInsecureRequests() = aLoadInfo->GetUpgradeInsecureRequests(); - aLoadInfoArgs->innerWindowID() = aLoadInfo->GetInnerWindowID(); - aLoadInfoArgs->outerWindowID() = aLoadInfo->GetOuterWindowID(); - aLoadInfoArgs->parentOuterWindowID() = aLoadInfo->GetParentOuterWindowID(); + if (!aLoadInfo) { + // if there is no loadInfo, then there is nothing to serialize + *aOptionalLoadInfoArgs = void_t(); return NS_OK; } - // use default values if no loadInfo is provided - rv = PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(), - &aLoadInfoArgs->requestingPrincipalInfo()); + nsresult rv = NS_OK; + PrincipalInfo requestingPrincipalInfo; + rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(), + &requestingPrincipalInfo); NS_ENSURE_SUCCESS(rv, rv); - rv = PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(), - &aLoadInfoArgs->triggeringPrincipalInfo()); - NS_ENSURE_SUCCESS(rv, rv); - aLoadInfoArgs->securityFlags() = nsILoadInfo::SEC_NORMAL; - aLoadInfoArgs->contentPolicyType() = nsIContentPolicy::TYPE_OTHER; - aLoadInfoArgs->upgradeInsecureRequests() = false; - aLoadInfoArgs->innerWindowID() = 0; - aLoadInfoArgs->outerWindowID() = 0; - aLoadInfoArgs->parentOuterWindowID() = 0; + + PrincipalInfo triggeringPrincipalInfo; + rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), + &triggeringPrincipalInfo); + + nsTArray redirectChain; + for (const nsCOMPtr& principal : aLoadInfo->RedirectChain()) { + rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement()); + NS_ENSURE_SUCCESS(rv, rv); + } + + *aOptionalLoadInfoArgs = + LoadInfoArgs( + requestingPrincipalInfo, + triggeringPrincipalInfo, + aLoadInfo->GetSecurityFlags(), + aLoadInfo->InternalContentPolicyType(), + aLoadInfo->GetUpgradeInsecureRequests(), + aLoadInfo->GetInnerWindowID(), + aLoadInfo->GetOuterWindowID(), + aLoadInfo->GetParentOuterWindowID(), + aLoadInfo->GetEnforceSecurity(), + aLoadInfo->GetInitialSecurityCheckDone(), + redirectChain); + return NS_OK; } nsresult -LoadInfoArgsToLoadInfo(const mozilla::net::LoadInfoArgs& aLoadInfoArgs, +LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, nsILoadInfo** outLoadInfo) { + if (aOptionalLoadInfoArgs.type() == OptionalLoadInfoArgs::Tvoid_t) { + *outLoadInfo = nullptr; + return NS_OK; + } + + const LoadInfoArgs& loadInfoArgs = + aOptionalLoadInfoArgs.get_LoadInfoArgs(); + nsresult rv = NS_OK; nsCOMPtr requestingPrincipal = - PrincipalInfoToPrincipal(aLoadInfoArgs.requestingPrincipalInfo(), &rv); + PrincipalInfoToPrincipal(loadInfoArgs.requestingPrincipalInfo(), &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr triggeringPrincipal = - PrincipalInfoToPrincipal(aLoadInfoArgs.triggeringPrincipalInfo(), &rv); + PrincipalInfoToPrincipal(loadInfoArgs.triggeringPrincipalInfo(), &rv); NS_ENSURE_SUCCESS(rv, rv); + nsTArray> redirectChain; + for (const PrincipalInfo& principalInfo : loadInfoArgs.redirectChain()) { + nsCOMPtr redirectedPrincipal = + PrincipalInfoToPrincipal(principalInfo, &rv); + NS_ENSURE_SUCCESS(rv, rv); + redirectChain.AppendElement(redirectedPrincipal.forget()); + } + nsCOMPtr loadInfo = new mozilla::LoadInfo(requestingPrincipal, triggeringPrincipal, - aLoadInfoArgs.securityFlags(), - aLoadInfoArgs.contentPolicyType(), - aLoadInfoArgs.upgradeInsecureRequests(), - aLoadInfoArgs.innerWindowID(), - aLoadInfoArgs.outerWindowID(), - aLoadInfoArgs.parentOuterWindowID()); + loadInfoArgs.securityFlags(), + loadInfoArgs.contentPolicyType(), + loadInfoArgs.upgradeInsecureRequests(), + loadInfoArgs.innerWindowID(), + loadInfoArgs.outerWindowID(), + loadInfoArgs.parentOuterWindowID(), + loadInfoArgs.enforceSecurity(), + loadInfoArgs.initialSecurityCheckDone(), + redirectChain); - loadInfo.forget(outLoadInfo); - return NS_OK; + loadInfo.forget(outLoadInfo); + return NS_OK; } } // namespace ipc diff --git a/ipc/glue/BackgroundUtils.h b/ipc/glue/BackgroundUtils.h index 92644d1712..6e3bff883a 100644 --- a/ipc/glue/BackgroundUtils.h +++ b/ipc/glue/BackgroundUtils.h @@ -35,12 +35,14 @@ struct ParamTraits } }; -} // IPC namespace +} // namespace IPC namespace mozilla { namespace net { -class LoadInfoArgs; -} +class OptionalLoadInfoArgs; +} // namespace net + +using namespace mozilla::net; namespace ipc { @@ -69,17 +71,15 @@ PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, */ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, - mozilla::net::LoadInfoArgs* outLoadInfoArgs); + OptionalLoadInfoArgs* outOptionalLoadInfoArgs); /** * Convert LoadInfoArgs to a LoadInfo. */ nsresult -LoadInfoArgsToLoadInfo(const mozilla::net::LoadInfoArgs& aLoadInfoArgs, +LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, nsILoadInfo** outLoadInfo); - - } // namespace ipc } // namespace mozilla diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 14053148ec..1f41b55149 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -7,6 +7,7 @@ #include "mozilla/LoadInfo.h" #include "mozilla/Assertions.h" +#include "mozilla/dom/ToJSValue.h" #include "nsFrameLoader.h" #include "nsIDocShell.h" #include "nsIDocument.h" @@ -36,6 +37,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mInnerWindowID(0) , mOuterWindowID(0) , mParentOuterWindowID(0) + , mEnforceSecurity(false) + , mInitialSecurityCheckDone(false) , mIsFromProcessingFrameAttributes(false) { MOZ_ASSERT(mLoadingPrincipal); @@ -88,7 +91,10 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, bool aUpgradeInsecureRequests, uint64_t aInnerWindowID, uint64_t aOuterWindowID, - uint64_t aParentOuterWindowID) + uint64_t aParentOuterWindowID, + bool aEnforceSecurity, + bool aInitialSecurityCheckDone, + nsTArray>& aRedirectChain) : mLoadingPrincipal(aLoadingPrincipal) , mTriggeringPrincipal(aTriggeringPrincipal) , mSecurityFlags(aSecurityFlags) @@ -97,10 +103,14 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mInnerWindowID(aInnerWindowID) , mOuterWindowID(aOuterWindowID) , mParentOuterWindowID(aParentOuterWindowID) + , mEnforceSecurity(aEnforceSecurity) + , mInitialSecurityCheckDone(aInitialSecurityCheckDone) , mIsFromProcessingFrameAttributes(false) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); + + mRedirectChain.SwapElements(aRedirectChain); } LoadInfo::~LoadInfo() @@ -168,6 +178,26 @@ LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult) return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetSecurityMode(uint32_t *aFlags) +{ + *aFlags = (mSecurityFlags & + (nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS | + nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED | + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS | + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL | + nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)); + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetRequireCorsWithCredentials(bool* aResult) +{ + *aResult = + (mSecurityFlags & nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetForceInheritPrincipal(bool* aInheritPrincipal) { @@ -183,6 +213,14 @@ LoadInfo::GetLoadingSandboxed(bool* aLoadingSandboxed) return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetAboutBlankInherits(bool* aResult) +{ + *aResult = + (mSecurityFlags & nsILoadInfo::SEC_ABOUT_BLANK_INHERITS); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetExternalContentPolicyType(nsContentPolicyType* aResult) { @@ -252,4 +290,64 @@ LoadInfo::GetIsFromProcessingFrameAttributes(bool *aIsFromProcessingFrameAttribu return NS_OK; } +NS_IMETHODIMP +LoadInfo::SetEnforceSecurity(bool aEnforceSecurity) +{ + // Indicates whether the channel was openend using AsyncOpen2. Once set + // to true, it must remain true throughout the lifetime of the channel. + // Setting it to anything else than true will be discarded. + MOZ_ASSERT(aEnforceSecurity, "aEnforceSecurity must be true"); + mEnforceSecurity = mEnforceSecurity || aEnforceSecurity; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetEnforceSecurity(bool* aResult) +{ + *aResult = mEnforceSecurity; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::SetInitialSecurityCheckDone(bool aInitialSecurityCheckDone) +{ + // Indicates whether the channel was ever evaluated by the + // ContentSecurityManager. Once set to true, this flag must + // remain true throughout the lifetime of the channel. + // Setting it to anything else than true will be discarded. + MOZ_ASSERT(aInitialSecurityCheckDone, "aInitialSecurityCheckDone must be true"); + mInitialSecurityCheckDone = mInitialSecurityCheckDone || aInitialSecurityCheckDone; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetInitialSecurityCheckDone(bool* aResult) +{ + *aResult = mInitialSecurityCheckDone; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::AppendRedirectedPrincipal(nsIPrincipal* aPrincipal) +{ + NS_ENSURE_ARG(aPrincipal); + mRedirectChain.AppendElement(aPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetRedirectChain(JSContext* aCx, JS::MutableHandle aChain) +{ + if (!ToJSValue(aCx, mRedirectChain, aChain)) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +const nsTArray>& +LoadInfo::RedirectChain() +{ + return mRedirectChain; +} + } // namespace mozilla diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index db04f5b613..59a64f3df3 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -12,21 +12,22 @@ #include "nsIPrincipal.h" #include "nsIWeakReferenceUtils.h" // for nsWeakPtr #include "nsIURI.h" +#include "nsTArray.h" class nsINode; namespace mozilla { namespace net { -class LoadInfoArgs; -} +class OptionalLoadInfoArgs; +} // namespace net namespace ipc { // we have to forward declare that function so we can use it as a friend. nsresult -LoadInfoArgsToLoadInfo(const mozilla::net::LoadInfoArgs& aLoadInfoArgs, +LoadInfoArgsToLoadInfo(const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs, nsILoadInfo** outLoadInfo); -} +} // namespace ipc /** * Class that provides an nsILoadInfo implementation. @@ -57,6 +58,7 @@ private: // private constructor that is only allowed to be called from within // HttpChannelParent and FTPChannelParent declared as friends undeneath. // In e10s we can not serialize nsINode, hence we store the innerWindowID. + // Please note that aRedirectChain uses swapElements. LoadInfo(nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal, nsSecurityFlags aSecurityFlags, @@ -64,24 +66,31 @@ private: bool aUpgradeInsecureRequests, uint64_t aInnerWindowID, uint64_t aOuterWindowID, - uint64_t aParentOuterWindowID); + uint64_t aParentOuterWindowID, + bool aEnforceSecurity, + bool aInitialSecurityCheckDone, + nsTArray>& aRedirectChain); friend nsresult - mozilla::ipc::LoadInfoArgsToLoadInfo(const mozilla::net::LoadInfoArgs& aLoadInfoArgs, - nsILoadInfo** outLoadInfo); + mozilla::ipc::LoadInfoArgsToLoadInfo( + const mozilla::net::OptionalLoadInfoArgs& aLoadInfoArgs, + nsILoadInfo** outLoadInfo); ~LoadInfo(); - nsCOMPtr mLoadingPrincipal; - nsCOMPtr mTriggeringPrincipal; - nsWeakPtr mLoadingContext; - nsSecurityFlags mSecurityFlags; - nsContentPolicyType mInternalContentPolicyType; - nsCOMPtr mBaseURI; - bool mUpgradeInsecureRequests; - uint64_t mInnerWindowID; - uint64_t mOuterWindowID; - uint64_t mParentOuterWindowID; + nsCOMPtr mLoadingPrincipal; + nsCOMPtr mTriggeringPrincipal; + nsWeakPtr mLoadingContext; + nsSecurityFlags mSecurityFlags; + nsContentPolicyType mInternalContentPolicyType; + nsCOMPtr mBaseURI; + bool mUpgradeInsecureRequests; + uint64_t mInnerWindowID; + uint64_t mOuterWindowID; + uint64_t mParentOuterWindowID; + bool mEnforceSecurity; + bool mInitialSecurityCheckDone; + nsTArray> mRedirectChain; // Is true if this load was triggered by processing the attributes of the // browsing context container. diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index b7122b00f3..6ec280602b 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -85,7 +85,6 @@ XPIDL_SOURCES += [ 'nsIProxyInfo.idl', 'nsIRandomGenerator.idl', 'nsIRedirectChannelRegistrar.idl', - 'nsIRedirectHistory.idl', 'nsIRedirectResultListener.idl', 'nsIRequest.idl', 'nsIRequestObserver.idl', diff --git a/netwerk/base/nsBaseChannel.cpp b/netwerk/base/nsBaseChannel.cpp index 8994de5c03..d59ebd6d6f 100644 --- a/netwerk/base/nsBaseChannel.cpp +++ b/netwerk/base/nsBaseChannel.cpp @@ -5,10 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsBaseChannel.h" +#include "nsContentUtils.h" #include "nsURLHelper.h" #include "nsNetCID.h" #include "nsMimeTypes.h" #include "nsIContentSniffer.h" +#include "nsIScriptSecurityManager.h" #include "nsMimeTypes.h" #include "nsIHttpEventSink.h" #include "nsIHttpChannel.h" @@ -168,8 +170,15 @@ nsBaseChannel::ContinueRedirect() if (mOpenRedirectChannel) { nsresult rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext); - if (NS_FAILED(rv)) - return rv; + NS_ENSURE_SUCCESS(rv, rv); + // Append the initial uri of the channel to the redirectChain + // after the channel got openend successfully. + if (mLoadInfo) { + nsCOMPtr uriPrincipal; + nsIScriptSecurityManager *sm = nsContentUtils::GetSecurityManager(); + sm->GetChannelURIPrincipal(this, getter_AddRefs(uriPrincipal)); + mLoadInfo->AppendRedirectedPrincipal(uriPrincipal); + } } mRedirectChannel = nullptr; diff --git a/netwerk/base/nsIChannel.idl b/netwerk/base/nsIChannel.idl index 81abd0e72d..63b951df7e 100644 --- a/netwerk/base/nsIChannel.idl +++ b/netwerk/base/nsIChannel.idl @@ -4,12 +4,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIRequest.idl" +#include "nsILoadInfo.idl" interface nsIURI; interface nsIInterfaceRequestor; interface nsIInputStream; interface nsIStreamListener; -interface nsILoadInfo; + +%{C++ +#include "nsCOMPtr.h" +%} /** * The nsIChannel interface allows clients to construct "GET" requests for @@ -309,4 +313,15 @@ interface nsIChannel : nsIRequest * redirects and the like. */ attribute nsILoadInfo loadInfo; + +%{ C++ + inline already_AddRefed GetLoadInfo() + { + nsCOMPtr result; + mozilla::DebugOnly rv = GetLoadInfo(getter_AddRefs(result)); + MOZ_ASSERT(NS_SUCCEEDED(rv) || !result); + return result.forget(); + } +%} + }; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 73b27dc312..854ca1340f 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -12,12 +12,18 @@ interface nsINode; interface nsIPrincipal; interface nsIURI; +%{C++ +#include "nsTArray.h" +%} + +[ref] native const_nsIPrincipalArray(const nsTArray>); + typedef unsigned long nsSecurityFlags; /** * An nsILoadOwner represents per-load information about who started the load. */ -[scriptable, builtinclass, uuid(6b7f8798-3c28-44fc-8b1a-cd613eb826c5)] +[scriptable, builtinclass, uuid(cc51498e-f8f8-469d-85ba-6dcba17027e4)] interface nsILoadInfo : nsISupports { /** @@ -25,6 +31,64 @@ interface nsILoadInfo : nsISupports */ const unsigned long SEC_NORMAL = 0; + /** + * The following five flags determine the security mode and hence what kind of + * security checks should be performed throughout the lifetime of the channel. + * + * * SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS + * * SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED + * * SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS + * * SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL + * * SEC_REQUIRE_CORS_DATA_INHERITS + * + * Exactly one of these flags are required to be set in order to allow + * the channel to perform the correct security checks (SOP, CORS, ...) and + * return the correct result principal. If none or more than one of these + * flags are set AsyncOpen2 will fail. + */ + + /* + * Enforce the same origin policy where data: loads inherit + * the principal. + */ + const unsigned long SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS = (1<<0); + + /* + * Enforce the same origin policy but data: loads are blocked. + */ + const unsigned long SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED = (1<<1); + + /** + * Allow loads from other origins. Loads from data: will inherit + * the principal of the origin that triggered the load. + * Commonly used by plain ,