diff options
Diffstat (limited to 'netwerk')
31 files changed, 704 insertions, 164 deletions
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 42fdea4a1..ede825b8f 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/TabChild.h" #include "mozilla/dom/ToJSValue.h" #include "mozIThirdPartyUtil.h" #include "nsFrameLoader.h" @@ -47,12 +48,14 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, aTriggeringPrincipal : mLoadingPrincipal.get()) , mPrincipalToInherit(nullptr) , mLoadingContext(do_GetWeakReference(aLoadingContext)) + , mContextForTopLevelLoad(nullptr) , mSecurityFlags(aSecurityFlags) , mInternalContentPolicyType(aContentPolicyType) , mTainting(LoadTainting::Basic) , mUpgradeInsecureRequests(false) , mVerifySignedContent(false) , mEnforceSRI(false) + , mForceAllowDataURI(false) , mForceInheritPrincipalDropped(false) , mInnerWindowID(0) , mOuterWindowID(0) @@ -63,6 +66,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mIsThirdPartyContext(false) , mForcePreflight(false) , mIsPreflight(false) + , mLoadTriggeredFromExternal(false) , mForceHSTSPriming(false) , mMixedContentWouldBlock(false) { @@ -215,16 +219,19 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, */ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, nsIPrincipal* aTriggeringPrincipal, + nsISupports* aContextForTopLevelLoad, nsSecurityFlags aSecurityFlags) : mLoadingPrincipal(nullptr) , mTriggeringPrincipal(aTriggeringPrincipal) , mPrincipalToInherit(nullptr) + , mContextForTopLevelLoad(do_GetWeakReference(aContextForTopLevelLoad)) , mSecurityFlags(aSecurityFlags) , mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT) , mTainting(LoadTainting::Basic) , mUpgradeInsecureRequests(false) , mVerifySignedContent(false) , mEnforceSRI(false) + , mForceAllowDataURI(false) , mForceInheritPrincipalDropped(false) , mInnerWindowID(0) , mOuterWindowID(0) @@ -235,6 +242,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, , mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party. , mForcePreflight(false) , mIsPreflight(false) + , mLoadTriggeredFromExternal(false) , mForceHSTSPriming(false) , mMixedContentWouldBlock(false) { @@ -276,12 +284,14 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) , mTriggeringPrincipal(rhs.mTriggeringPrincipal) , mPrincipalToInherit(rhs.mPrincipalToInherit) , mLoadingContext(rhs.mLoadingContext) + , mContextForTopLevelLoad(rhs.mContextForTopLevelLoad) , mSecurityFlags(rhs.mSecurityFlags) , mInternalContentPolicyType(rhs.mInternalContentPolicyType) , mTainting(rhs.mTainting) , mUpgradeInsecureRequests(rhs.mUpgradeInsecureRequests) , mVerifySignedContent(rhs.mVerifySignedContent) , mEnforceSRI(rhs.mEnforceSRI) + , mForceAllowDataURI(rhs.mForceAllowDataURI) , mForceInheritPrincipalDropped(rhs.mForceInheritPrincipalDropped) , mInnerWindowID(rhs.mInnerWindowID) , mOuterWindowID(rhs.mOuterWindowID) @@ -297,6 +307,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) , mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders) , mForcePreflight(rhs.mForcePreflight) , mIsPreflight(rhs.mIsPreflight) + , mLoadTriggeredFromExternal(rhs.mLoadTriggeredFromExternal) , mForceHSTSPriming(rhs.mForceHSTSPriming) , mMixedContentWouldBlock(rhs.mMixedContentWouldBlock) { @@ -311,6 +322,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, bool aUpgradeInsecureRequests, bool aVerifySignedContent, bool aEnforceSRI, + bool aForceAllowDataURI, bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, @@ -325,6 +337,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, const nsTArray<nsCString>& aCorsUnsafeHeaders, bool aForcePreflight, bool aIsPreflight, + bool aLoadTriggeredFromExternal, bool aForceHSTSPriming, bool aMixedContentWouldBlock) : mLoadingPrincipal(aLoadingPrincipal) @@ -336,6 +349,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mUpgradeInsecureRequests(aUpgradeInsecureRequests) , mVerifySignedContent(aVerifySignedContent) , mEnforceSRI(aEnforceSRI) + , mForceAllowDataURI(aForceAllowDataURI) , mForceInheritPrincipalDropped(aForceInheritPrincipalDropped) , mInnerWindowID(aInnerWindowID) , mOuterWindowID(aOuterWindowID) @@ -348,6 +362,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mCorsUnsafeHeaders(aCorsUnsafeHeaders) , mForcePreflight(aForcePreflight) , mIsPreflight(aIsPreflight) + , mLoadTriggeredFromExternal(aLoadTriggeredFromExternal) , mForceHSTSPriming (aForceHSTSPriming) , mMixedContentWouldBlock(aMixedContentWouldBlock) { @@ -477,6 +492,17 @@ LoadInfo::LoadingNode() return node; } +nsISupports* +LoadInfo::ContextForTopLevelLoad() +{ + // Most likely you want to query LoadingNode() instead of + // ContextForTopLevelLoad() if this assertion fires. + MOZ_ASSERT(mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT, + "should only query this context for top level document loads"); + nsCOMPtr<nsISupports> context = do_QueryReferent(mContextForTopLevelLoad); + return context; +} + NS_IMETHODIMP LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult) { @@ -648,6 +674,23 @@ LoadInfo::GetEnforceSRI(bool* aResult) } NS_IMETHODIMP +LoadInfo::SetForceAllowDataURI(bool aForceAllowDataURI) +{ + MOZ_ASSERT(!mForceAllowDataURI || + mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT, + "can only allow data URI navigation for TYPE_DOCUMENT"); + mForceAllowDataURI = aForceAllowDataURI; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetForceAllowDataURI(bool* aForceAllowDataURI) +{ + *aForceAllowDataURI = mForceAllowDataURI; + return NS_OK; +} + +NS_IMETHODIMP LoadInfo::GetForceInheritPrincipalDropped(bool* aResult) { *aResult = mForceInheritPrincipalDropped; @@ -873,6 +916,23 @@ LoadInfo::GetIsPreflight(bool* aIsPreflight) } NS_IMETHODIMP +LoadInfo::SetLoadTriggeredFromExternal(bool aLoadTriggeredFromExternal) +{ + MOZ_ASSERT(!aLoadTriggeredFromExternal || + mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT, + "can only set load triggered from external for TYPE_DOCUMENT"); + mLoadTriggeredFromExternal = aLoadTriggeredFromExternal; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetLoadTriggeredFromExternal(bool* aLoadTriggeredFromExternal) +{ + *aLoadTriggeredFromExternal = mLoadTriggeredFromExternal; + return NS_OK; +} + +NS_IMETHODIMP LoadInfo::GetForceHSTSPriming(bool* aForceHSTSPriming) { *aForceHSTSPriming = mForceHSTSPriming; diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 3e1b92ff4..0ae6061b3 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -59,10 +59,12 @@ public: nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType); - // Constructor used for TYPE_DOCUMENT loads which have no reasonable - // loadingNode or loadingPrincipal + // Constructor used for TYPE_DOCUMENT loads which have a different + // loadingContext than other loads. This ContextForTopLevelLoad is + // only used for content policy checks. LoadInfo(nsPIDOMWindowOuter* aOuterWindow, nsIPrincipal* aTriggeringPrincipal, + nsISupports* aContextForTopLevelLoad, nsSecurityFlags aSecurityFlags); // create an exact copy of the loadinfo @@ -94,6 +96,7 @@ private: bool aUpgradeInsecureRequests, bool aVerifySignedContent, bool aEnforceSRI, + bool aForceAllowDataURI, bool aForceInheritPrincipalDropped, uint64_t aInnerWindowID, uint64_t aOuterWindowID, @@ -108,6 +111,7 @@ private: const nsTArray<nsCString>& aUnsafeHeaders, bool aForcePreflight, bool aIsPreflight, + bool aLoadTriggeredFromExternal, bool aForceHSTSPriming, bool aMixedContentWouldBlock); LoadInfo(const LoadInfo& rhs); @@ -132,12 +136,14 @@ private: nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; nsCOMPtr<nsIPrincipal> mPrincipalToInherit; nsWeakPtr mLoadingContext; + nsWeakPtr mContextForTopLevelLoad; nsSecurityFlags mSecurityFlags; nsContentPolicyType mInternalContentPolicyType; LoadTainting mTainting; bool mUpgradeInsecureRequests; bool mVerifySignedContent; bool mEnforceSRI; + bool mForceAllowDataURI; bool mForceInheritPrincipalDropped; uint64_t mInnerWindowID; uint64_t mOuterWindowID; @@ -152,6 +158,7 @@ private: nsTArray<nsCString> mCorsUnsafeHeaders; bool mForcePreflight; bool mIsPreflight; + bool mLoadTriggeredFromExternal; bool mForceHSTSPriming : 1; bool mMixedContentWouldBlock : 1; diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index 3b731db10..5de1eea81 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -132,7 +132,6 @@ XPIDL_SOURCES += [ 'nsIURIClassifier.idl', 'nsIURIWithBlobImpl.idl', 'nsIURIWithPrincipal.idl', - 'nsIURIWithQuery.idl', 'nsIURL.idl', 'nsIURLParser.idl', 'nsPILoadGroupInternal.idl', diff --git a/netwerk/base/nsBufferedStreams.h b/netwerk/base/nsBufferedStreams.h index 93a770beb..fee55695a 100644 --- a/netwerk/base/nsBufferedStreams.h +++ b/netwerk/base/nsBufferedStreams.h @@ -88,10 +88,10 @@ protected: //////////////////////////////////////////////////////////////////////////////// -class nsBufferedOutputStream final : public nsBufferedStream, - public nsISafeOutputStream, - public nsIBufferedOutputStream, - public nsIStreamBufferAccess +class nsBufferedOutputStream : public nsBufferedStream, + public nsISafeOutputStream, + public nsIBufferedOutputStream, + public nsIStreamBufferAccess { public: NS_DECL_ISUPPORTS_INHERITED diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 78433c8b8..4ec29b972 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -324,6 +324,16 @@ interface nsILoadInfo : nsISupports nsINode binaryLoadingNode(); /** + * A C++ friendly version of the loadingContext for toplevel loads. + * Most likely you want to query the ownerDocument or LoadingNode + * and not this context only available for TYPE_DOCUMENT loads. + * Please note that except for loads of TYPE_DOCUMENT, this + * ContextForTopLevelLoad will always return null. + */ + [noscript, notxpcom, nostdcall, binaryname(ContextForTopLevelLoad)] + nsISupports binaryContextForTopLevelLoad(); + + /** * The securityFlags of that channel. */ readonly attribute nsSecurityFlags securityFlags; @@ -470,6 +480,11 @@ interface nsILoadInfo : nsISupports [infallible] attribute boolean enforceSRI; /** + * If true, toplevel data: URI navigation is allowed + */ + [infallible] attribute boolean forceAllowDataURI; + + /** * The SEC_FORCE_INHERIT_PRINCIPAL flag may be dropped when a load info * object is created. Specifically, it will be dropped if the SEC_SANDBOXED * flag is also present. This flag is set if SEC_FORCE_INHERIT_PRINCIPAL was @@ -575,6 +590,13 @@ interface nsILoadInfo : nsISupports [infallible] attribute boolean initialSecurityCheckDone; /** + * Returns true if the load was triggered from an external application + * (e.g. Thunderbird). Please note that this flag will only ever be true + * if the load is of TYPE_DOCUMENT. + */ + [infallible] attribute boolean loadTriggeredFromExternal; + + /** * Whenever a channel gets redirected, append the principal of the * channel [before the channels got redirected] to the loadinfo, * so that at every point this array lets us reason about all the diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl index 17d27de42..721b7a334 100644 --- a/netwerk/base/nsINetworkInterceptController.idl +++ b/netwerk/base/nsINetworkInterceptController.idl @@ -14,12 +14,16 @@ interface nsIURI; %{C++ #include "nsIConsoleReportCollector.h" namespace mozilla { +class TimeStamp; + namespace dom { class ChannelInfo; } } %} +native TimeStamp(mozilla::TimeStamp); + [ptr] native ChannelInfo(mozilla::dom::ChannelInfo); /** @@ -97,6 +101,30 @@ interface nsIInterceptedChannel : nsISupports [noscript] readonly attribute nsIConsoleReportCollector consoleReportCollector; + /** + * Save the timestamps of various service worker interception phases. + */ + [noscript] + void SetLaunchServiceWorkerStart(in TimeStamp aTimeStamp); + + [noscript] + void SetLaunchServiceWorkerEnd(in TimeStamp aTimeStamp); + + [noscript] + void SetDispatchFetchEventStart(in TimeStamp aTimeStamp); + + [noscript] + void SetDispatchFetchEventEnd(in TimeStamp aTimeStamp); + + [noscript] + void SetHandleFetchEventStart(in TimeStamp aTimeStamp); + + [noscript] + void SetHandleFetchEventEnd(in TimeStamp aTimeStamp); + + [noscript] + void SaveTimeStampsToUnderlyingChannel(); + %{C++ already_AddRefed<nsIConsoleReportCollector> GetConsoleReportCollector() diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp index 0da79c18a..8b7f31f99 100644 --- a/netwerk/base/nsIOService.cpp +++ b/netwerk/base/nsIOService.cpp @@ -173,6 +173,8 @@ uint32_t nsIOService::gDefaultSegmentCount = 24; bool nsIOService::sTelemetryEnabled = false; +bool nsIOService::sBlockToplevelDataUriNavigations = false; + //////////////////////////////////////////////////////////////////////////////// nsIOService::nsIOService() @@ -251,6 +253,8 @@ nsIOService::Init() NS_WARNING("failed to get observer service"); Preferences::AddBoolVarCache(&sTelemetryEnabled, "toolkit.telemetry.enabled", false); + Preferences::AddBoolVarCache(&sBlockToplevelDataUriNavigations, + "security.data_uri.block_toplevel_data_uri_navigations", false); Preferences::AddBoolVarCache(&mOfflineMirrorsConnectivity, OFFLINE_MIRRORS_CONNECTIVITY, true); gIOService = this; @@ -1876,5 +1880,11 @@ nsIOService::SpeculativeAnonymousConnect2(nsIURI *aURI, return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true); } +/*static*/ bool +nsIOService::BlockToplevelDataUriNavigations() +{ + return sBlockToplevelDataUriNavigations; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h index 7ac23b791..e592c4d1c 100644 --- a/netwerk/base/nsIOService.h +++ b/netwerk/base/nsIOService.h @@ -95,6 +95,8 @@ public: bool IsLinkUp(); + static bool BlockToplevelDataUriNavigations(); + // Used to trigger a recheck of the captive portal status nsresult RecheckCaptivePortal(); private: @@ -176,6 +178,8 @@ private: static bool sTelemetryEnabled; + static bool sBlockToplevelDataUriNavigations; + // These timestamps are needed for collecting telemetry on PR_Connect, // PR_ConnectContinue and PR_Close blocking time. If we spend very long // time in any of these functions we want to know if and what network diff --git a/netwerk/base/nsITimedChannel.idl b/netwerk/base/nsITimedChannel.idl index 13b65e7b8..83670a11e 100644 --- a/netwerk/base/nsITimedChannel.idl +++ b/netwerk/base/nsITimedChannel.idl @@ -21,7 +21,8 @@ interface nsITimedChannel : nsISupports { attribute boolean timingEnabled; // The number of redirects - attribute uint16_t redirectCount; + attribute uint8_t redirectCount; + attribute uint8_t internalRedirectCount; [noscript] readonly attribute TimeStamp channelCreation; [noscript] readonly attribute TimeStamp asyncOpen; @@ -37,6 +38,15 @@ interface nsITimedChannel : nsISupports { [noscript] readonly attribute TimeStamp responseStart; [noscript] readonly attribute TimeStamp responseEnd; + // The following are only set when the request is intercepted by a service + // worker no matter the response is synthesized. + [noscript] attribute TimeStamp launchServiceWorkerStart; + [noscript] attribute TimeStamp launchServiceWorkerEnd; + [noscript] attribute TimeStamp dispatchFetchEventStart; + [noscript] attribute TimeStamp dispatchFetchEventEnd; + [noscript] attribute TimeStamp handleFetchEventStart; + [noscript] attribute TimeStamp handleFetchEventEnd; + // The redirect attributes timings must be writeble, se we can transfer // the data from one channel to the redirected channel. [noscript] attribute TimeStamp redirectStart; @@ -67,6 +77,12 @@ interface nsITimedChannel : nsISupports { // All following are PRTime versions of the above. readonly attribute PRTime channelCreationTime; readonly attribute PRTime asyncOpenTime; + readonly attribute PRTime launchServiceWorkerStartTime; + readonly attribute PRTime launchServiceWorkerEndTime; + readonly attribute PRTime dispatchFetchEventStartTime; + readonly attribute PRTime dispatchFetchEventEndTime; + readonly attribute PRTime handleFetchEventStartTime; + readonly attribute PRTime handleFetchEventEndTime; readonly attribute PRTime domainLookupStartTime; readonly attribute PRTime domainLookupEndTime; readonly attribute PRTime connectStartTime; diff --git a/netwerk/base/nsIURI.idl b/netwerk/base/nsIURI.idl index 2384c5fd9..ef163813a 100644 --- a/netwerk/base/nsIURI.idl +++ b/netwerk/base/nsIURI.idl @@ -10,18 +10,18 @@ * provides accessors to set and query the most basic components of an URI. * Subclasses, including nsIURL, impose greater structure on the URI. * - * This interface follows Tim Berners-Lee's URI spec (RFC2396) [1], where the + * This interface follows Tim Berners-Lee's URI spec (RFC3986) [1], where the * basic URI components are defined as such: * <pre> - * ftp://username:password@hostname:portnumber/pathname#ref - * \ / \ / \ / \ /\ \ / - * - --------------- ------ -------- | - - * | | | | | | - * | | | | | Ref - * | | | Port \ / - * | | Host / -------- - * | UserPass / | - * Scheme / Path + * ftp://username:password@hostname:portnumber/pathname?query#ref + * \ / \ / \ / \ /\ / \ / \ / + * - --------------- ------ -------- ------- --- - + * | | | | | | | + * | | | | FilePath Query Ref + * | | | Port \ / + * | | Host / ------------ + * | UserPass / | + * Scheme / Path * \ / * -------------------------------- * | @@ -30,13 +30,9 @@ * The definition of the URI components has been extended to allow for * internationalized domain names [2] and the more generic IRI structure [3]. * - * Note also that the RFC defines #-separated fragment identifiers as being - * "not part of the URI". Despite this, we bundle them as part of the URI, for - * convenience. - * - * [1] http://www.ietf.org/rfc/rfc2396.txt - * [2] http://www.ietf.org/internet-drafts/draft-ietf-idn-idna-06.txt - * [3] http://www.ietf.org/internet-drafts/draft-masinter-url-i18n-08.txt + * [1] https://tools.ietf.org/html/rfc3986 + * [2] https://tools.ietf.org/html/rfc5890 + * [3] https://tools.ietf.org/html/rfc3987 */ %{C++ @@ -116,7 +112,7 @@ interface nsIURI : nsISupports /** * The Scheme is the protocol to which this URI refers. The scheme is - * restricted to the US-ASCII charset per RFC2396. Setting this is + * restricted to the US-ASCII charset per RFC3986. Setting this is * highly discouraged outside of a protocol handler implementation, since * that will generally lead to incorrect results. */ @@ -174,6 +170,9 @@ interface nsIURI : nsISupports * empty, depending on the protocol). * * Some characters may be escaped. + * + * This attribute contains query and ref parts for historical reasons. + * Use the 'filePath' attribute if you do not want those parts included. */ attribute AUTF8String path; @@ -281,10 +280,31 @@ interface nsIURI : nsISupports /** * returns a string for the current URI with the ref element cleared. */ - readonly attribute AUTF8String specIgnoringRef; + readonly attribute AUTF8String specIgnoringRef; /** * Returns if there is a reference portion (the part after the "#") of the URI. */ - readonly attribute boolean hasRef; + readonly attribute boolean hasRef; + + /************************************************************************ + * Additional attributes added for .query support: + */ + + /** + * Returns a path including the directory and file portions of a + * URL. For example, the filePath of "http://host/foo/bar.html#baz" + * is "/foo/bar.html". + * + * Some characters may be escaped. + */ + attribute AUTF8String filePath; + + /** + * Returns the query portion (the part after the "?") of the URL. + * If there isn't one, an empty string is returned. + * + * Some characters may be escaped. + */ + attribute AUTF8String query; }; diff --git a/netwerk/base/nsIURIWithQuery.idl b/netwerk/base/nsIURIWithQuery.idl deleted file mode 100644 index 749b2773d..000000000 --- a/netwerk/base/nsIURIWithQuery.idl +++ /dev/null @@ -1,30 +0,0 @@ -/* 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 "nsIURI.idl" - -/** - * nsIURIWithQuery is implemented by URIs which have a query parameter. - * This is useful for the URL API. - */ -[scriptable, uuid(367510ee-8556-435a-8f99-b5fd357e08cc)] -interface nsIURIWithQuery : nsIURI -{ - /** - * Returns a path including the directory and file portions of a - * URL. For example, the filePath of "http://host/foo/bar.html#baz" - * is "/foo/bar.html". - * - * Some characters may be escaped. - */ - attribute AUTF8String filePath; - - /** - * Returns the query portion (the part after the "?") of the URL. - * If there isn't one, an empty string is returned. - * - * Some characters may be escaped. - */ - attribute AUTF8String query; -}; diff --git a/netwerk/base/nsIURL.idl b/netwerk/base/nsIURL.idl index aeaa3f694..9ff6c3dcd 100644 --- a/netwerk/base/nsIURL.idl +++ b/netwerk/base/nsIURL.idl @@ -3,7 +3,7 @@ * 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 "nsIURIWithQuery.idl" +#include "nsIURI.idl" /** * The nsIURL interface provides convenience methods that further @@ -20,7 +20,7 @@ * filePath */ [scriptable, uuid(86adcd89-0b70-47a2-b0fe-5bb2c5f37e31)] -interface nsIURL : nsIURIWithQuery +interface nsIURL : nsIURI { /************************************************************************* * The URL path is broken down into the following principal components: @@ -28,7 +28,7 @@ interface nsIURL : nsIURIWithQuery * attribute AUTF8String filePath; * attribute AUTF8String query; * - * These are inherited from nsIURIWithQuery. + * These are inherited from nsIURI. */ /************************************************************************* diff --git a/netwerk/base/nsSimpleURI.cpp b/netwerk/base/nsSimpleURI.cpp index ae5c51a1e..dbc0dc817 100644 --- a/netwerk/base/nsSimpleURI.cpp +++ b/netwerk/base/nsSimpleURI.cpp @@ -48,7 +48,7 @@ nsSimpleURI::~nsSimpleURI() NS_IMPL_ADDREF(nsSimpleURI) NS_IMPL_RELEASE(nsSimpleURI) NS_INTERFACE_TABLE_HEAD(nsSimpleURI) -NS_INTERFACE_TABLE(nsSimpleURI, nsIURI, nsIURIWithQuery, nsISerializable, +NS_INTERFACE_TABLE(nsSimpleURI, nsIURI, nsISerializable, nsIClassInfo, nsIMutable, nsIIPCSerializableURI) NS_INTERFACE_TABLE_TO_MAP_SEGUE if (aIID.Equals(kThisSimpleURIImplementationCID)) @@ -784,10 +784,6 @@ nsSimpleURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } -//---------------------------------------------------------------------------- -// nsSimpleURI::nsIURIWithQuery -//---------------------------------------------------------------------------- - NS_IMETHODIMP nsSimpleURI::GetFilePath(nsACString& aFilePath) { diff --git a/netwerk/base/nsSimpleURI.h b/netwerk/base/nsSimpleURI.h index 29bc9b313..842136ed6 100644 --- a/netwerk/base/nsSimpleURI.h +++ b/netwerk/base/nsSimpleURI.h @@ -8,7 +8,6 @@ #include "mozilla/MemoryReporting.h" #include "nsIURI.h" -#include "nsIURIWithQuery.h" #include "nsISerializable.h" #include "nsString.h" #include "nsIClassInfo.h" @@ -28,7 +27,7 @@ namespace net { } class nsSimpleURI - : public nsIURIWithQuery + : public nsIURI , public nsISerializable , public nsIClassInfo , public nsIMutable @@ -41,7 +40,6 @@ protected: public: NS_DECL_ISUPPORTS NS_DECL_NSIURI - NS_DECL_NSIURIWITHQUERY NS_DECL_NSISERIALIZABLE NS_DECL_NSICLASSINFO NS_DECL_NSIMUTABLE diff --git a/netwerk/base/nsStandardURL.cpp b/netwerk/base/nsStandardURL.cpp index bc1350f28..e2a290e4d 100644 --- a/netwerk/base/nsStandardURL.cpp +++ b/netwerk/base/nsStandardURL.cpp @@ -781,11 +781,13 @@ nsStandardURL::BuildNormalizedSpec(const char *spec) i = AppendSegmentToBuf(buf, i, spec, username, mUsername, &encUsername, useEncUsername, &diff); ShiftFromPassword(diff); - if (password.mLen >= 0) { + if (password.mLen > 0) { buf[i++] = ':'; i = AppendSegmentToBuf(buf, i, spec, password, mPassword, &encPassword, useEncPassword, &diff); ShiftFromHost(diff); + } else { + mPassword.mLen = -1; } buf[i++] = '@'; } @@ -1180,7 +1182,6 @@ NS_IMPL_RELEASE(nsStandardURL) NS_INTERFACE_MAP_BEGIN(nsStandardURL) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStandardURL) NS_INTERFACE_MAP_ENTRY(nsIURI) - NS_INTERFACE_MAP_ENTRY(nsIURIWithQuery) NS_INTERFACE_MAP_ENTRY(nsIURL) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFileURL, mSupportsFileURL) NS_INTERFACE_MAP_ENTRY(nsIStandardURL) @@ -1483,6 +1484,11 @@ nsStandardURL::SetSpec(const nsACString &input) rv = BuildNormalizedSpec(spec); } + // Make sure that a URLTYPE_AUTHORITY has a non-empty hostname. + if (mURLType == URLTYPE_AUTHORITY && mHost.mLen == -1) { + rv = NS_ERROR_MALFORMED_URI; + } + if (NS_FAILED(rv)) { Clear(); // If parsing the spec has failed, restore the old URL @@ -1616,7 +1622,7 @@ nsStandardURL::SetUserPass(const nsACString &input) usernameLen), esc_Username | esc_AlwaysCopy, buf, ignoredOut); - if (passwordLen >= 0) { + if (passwordLen > 0) { buf.Append(':'); passwordLen = encoder.EncodeSegmentCount(userpass.get(), URLSegment(passwordPos, @@ -1624,6 +1630,8 @@ nsStandardURL::SetUserPass(const nsACString &input) esc_Password | esc_AlwaysCopy, buf, ignoredOut); + } else { + passwordLen = -1; } if (mUsername.mLen < 0) buf.Append('@'); @@ -1654,8 +1662,10 @@ nsStandardURL::SetUserPass(const nsACString &input) // update positions and lengths mUsername.mLen = usernameLen; mPassword.mLen = passwordLen; - if (passwordLen) + if (passwordLen > 0) { mPassword.mPos = mUsername.mPos + mUsername.mLen + 1; + } + return NS_OK; } @@ -3092,20 +3102,26 @@ nsStandardURL::SetFile(nsIFile *file) rv = net_GetURLSpecFromFile(file, url); if (NS_FAILED(rv)) return rv; - SetSpec(url); + uint32_t oldURLType = mURLType; + uint32_t oldDefaultPort = mDefaultPort; + rv = Init(nsIStandardURL::URLTYPE_NO_AUTHORITY, -1, url, nullptr, nullptr); - rv = Init(mURLType, mDefaultPort, url, nullptr, nullptr); + if (NS_FAILED(rv)) { + // Restore the old url type and default port if the call to Init fails. + mURLType = oldURLType; + mDefaultPort = oldDefaultPort; + return rv; + } // must clone |file| since its value is not guaranteed to remain constant - if (NS_SUCCEEDED(rv)) { - InvalidateCache(); - if (NS_FAILED(file->Clone(getter_AddRefs(mFile)))) { - NS_WARNING("nsIFile::Clone failed"); - // failure to clone is not fatal (GetFile will generate mFile) - mFile = nullptr; - } + InvalidateCache(); + if (NS_FAILED(file->Clone(getter_AddRefs(mFile)))) { + NS_WARNING("nsIFile::Clone failed"); + // failure to clone is not fatal (GetFile will generate mFile) + mFile = nullptr; } - return rv; + + return NS_OK; } //---------------------------------------------------------------------------- @@ -3425,10 +3441,29 @@ ToIPCSegment(const nsStandardURL::URLSegment& aSegment) } inline -nsStandardURL::URLSegment -FromIPCSegment(const ipc::StandardURLSegment& aSegment) +MOZ_MUST_USE bool +FromIPCSegment(const nsACString& aSpec, const ipc::StandardURLSegment& aSegment, nsStandardURL::URLSegment& aTarget) { - return nsStandardURL::URLSegment(aSegment.position(), aSegment.length()); + // This seems to be just an empty segment. + if (aSegment.length() == -1) { + aTarget = nsStandardURL::URLSegment(); + return true; + } + + // A value of -1 means an empty segment, but < -1 is undefined. + if (NS_WARN_IF(aSegment.length() < -1)) { + return false; + } + + // Make sure the segment does not extend beyond the spec. + if (NS_WARN_IF(aSegment.position() + aSegment.length() > aSpec.Length())) { + return false; + } + + aTarget.mPos = aSegment.position(); + aTarget.mLen = aSegment.length(); + + return true; } void @@ -3503,23 +3538,38 @@ nsStandardURL::Deserialize(const URIParams& aParams) mPort = params.port(); mDefaultPort = params.defaultPort(); mSpec = params.spec(); - mScheme = FromIPCSegment(params.scheme()); - mAuthority = FromIPCSegment(params.authority()); - mUsername = FromIPCSegment(params.username()); - mPassword = FromIPCSegment(params.password()); - mHost = FromIPCSegment(params.host()); - mPath = FromIPCSegment(params.path()); - mFilepath = FromIPCSegment(params.filePath()); - mDirectory = FromIPCSegment(params.directory()); - mBasename = FromIPCSegment(params.baseName()); - mExtension = FromIPCSegment(params.extension()); - mQuery = FromIPCSegment(params.query()); - mRef = FromIPCSegment(params.ref()); + + NS_ENSURE_TRUE(mSpec.Length() <= (uint32_t) net_GetURLMaxLength(), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.scheme(), mScheme), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.authority(), mAuthority), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.username(), mUsername), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.password(), mPassword), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.host(), mHost), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.path(), mPath), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.filePath(), mFilepath), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.directory(), mDirectory), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.baseName(), mBasename), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.extension(), mExtension), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.query(), mQuery), false); + NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.ref(), mRef), false); + mOriginCharset = params.originCharset(); mMutable = params.isMutable(); mSupportsFileURL = params.supportsFileURL(); mHostEncoding = params.hostEncoding(); + // Some sanity checks + NS_ENSURE_TRUE(mScheme.mPos == 0, false); + NS_ENSURE_TRUE(mScheme.mLen > 0, false); + // Make sure scheme is followed by :// (3 characters) + NS_ENSURE_TRUE(mScheme.mLen < INT32_MAX - 3, false); // avoid overflow + NS_ENSURE_TRUE(mSpec.Length() >= (uint32_t) mScheme.mLen + 3, false); + NS_ENSURE_TRUE(nsDependentCSubstring(mSpec, mScheme.mLen, 3).EqualsLiteral("://"), false); + NS_ENSURE_TRUE(mPath.mLen != -1 && mSpec.CharAt(mPath.mPos) == '/', false); + NS_ENSURE_TRUE(mPath.mPos == mFilepath.mPos, false); + NS_ENSURE_TRUE(mQuery.mLen == -1 || mSpec.CharAt(mQuery.mPos - 1) == '?', false); + NS_ENSURE_TRUE(mRef.mLen == -1 || mSpec.CharAt(mRef.mPos - 1) == '#', false); + // mSpecEncoding and mHostA are just caches that can be recovered as needed. return true; } diff --git a/netwerk/base/nsStandardURL.h b/netwerk/base/nsStandardURL.h index 90f7f7db2..0ca345572 100644 --- a/netwerk/base/nsStandardURL.h +++ b/netwerk/base/nsStandardURL.h @@ -54,7 +54,6 @@ protected: public: NS_DECL_ISUPPORTS NS_DECL_NSIURI - NS_DECL_NSIURIWITHQUERY NS_DECL_NSIURL NS_DECL_NSIFILEURL NS_DECL_NSISTANDARDURL diff --git a/netwerk/base/security-prefs.js b/netwerk/base/security-prefs.js index d1b56ce35..329a4c6b7 100644 --- a/netwerk/base/security-prefs.js +++ b/netwerk/base/security-prefs.js @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ pref("security.tls.version.min", 1); -pref("security.tls.version.max", 4); +pref("security.tls.version.max", 3); pref("security.tls.version.fallback-limit", 3); pref("security.tls.insecure_fallback_hosts", ""); pref("security.tls.unrestricted_rc4_fallback", false); diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 9365397d1..bb7562c64 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -20,6 +20,7 @@ using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h"; using struct nsHttpAtom from "nsHttp.h"; using class nsHttpResponseHead from "nsHttpResponseHead.h"; +using class mozilla::TimeStamp from "mozilla/TimeStamp.h"; namespace mozilla { namespace net { @@ -39,6 +40,7 @@ struct LoadInfoArgs bool upgradeInsecureRequests; bool verifySignedContent; bool enforceSRI; + bool forceAllowDataURI; bool forceInheritPrincipalDropped; uint64_t innerWindowID; uint64_t outerWindowID; @@ -53,6 +55,7 @@ struct LoadInfoArgs nsCString[] corsUnsafeHeaders; bool forcePreflight; bool isPreflight; + bool loadTriggeredFromExternal; bool forceHSTSPriming; bool mixedContentWouldBlock; }; @@ -132,6 +135,12 @@ struct HttpChannelOpenArgs nsCString channelId; uint64_t contentWindowId; nsCString preferredAlternativeType; + TimeStamp launchServiceWorkerStart; + TimeStamp launchServiceWorkerEnd; + TimeStamp dispatchFetchEventStart; + TimeStamp dispatchFetchEventEnd; + TimeStamp handleFetchEventStart; + TimeStamp handleFetchEventEnd; }; struct HttpChannelConnectArgs diff --git a/netwerk/ipc/NeckoMessageUtils.h b/netwerk/ipc/NeckoMessageUtils.h index 778691369..1633b82b6 100644 --- a/netwerk/ipc/NeckoMessageUtils.h +++ b/netwerk/ipc/NeckoMessageUtils.h @@ -14,11 +14,6 @@ #include "mozilla/net/DNS.h" #include "TimingStruct.h" -#ifdef MOZ_CRASHREPORTER -#include "nsExceptionHandler.h" -#include "nsPrintfCString.h" -#endif - namespace IPC { // nsIPermissionManager utilities @@ -102,12 +97,6 @@ struct ParamTraits<mozilla::net::NetAddr> aMsg->WriteBytes(aParam.local.path, sizeof(aParam.local.path)); #endif } else { -#ifdef MOZ_CRASHREPORTER - if (XRE_IsParentProcess()) { - nsPrintfCString msg("%d", aParam.raw.family); - CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Unknown NetAddr socket family"), msg); - } -#endif NS_RUNTIMEABORT("Unknown socket family"); } } diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 278c94db0..d161f9a43 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -105,6 +105,7 @@ HttpBaseChannel::HttpBaseChannel() , mHttpHandler(gHttpHandler) , mReferrerPolicy(REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE) , mRedirectCount(0) + , mInternalRedirectCount(0) , mForcePending(false) , mCorsIncludeCredentials(false) , mCorsMode(nsIHttpChannelInternal::CORS_MODE_NO_CORS) @@ -3128,12 +3129,6 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI, // convey the mAllowPipelining and mAllowSTS flags httpChannel->SetAllowPipelining(mAllowPipelining); httpChannel->SetAllowSTS(mAllowSTS); - // convey the new redirection limit - // make sure we don't underflow - uint32_t redirectionLimit = mRedirectionLimit - ? mRedirectionLimit - 1 - : 0; - httpChannel->SetRedirectionLimit(redirectionLimit); // convey the Accept header value { @@ -3215,23 +3210,40 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI, do_QueryInterface(static_cast<nsIHttpChannel*>(this))); if (oldTimedChannel && newTimedChannel) { newTimedChannel->SetTimingEnabled(mTimingEnabled); - newTimedChannel->SetRedirectCount(mRedirectCount + 1); + + if (redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) { + int8_t newCount = mInternalRedirectCount + 1; + newTimedChannel->SetInternalRedirectCount( + std::max(newCount, mInternalRedirectCount)); + } else { + int8_t newCount = mRedirectCount + 1; + newTimedChannel->SetRedirectCount( + std::max(newCount, mRedirectCount)); + } // If the RedirectStart is null, we will use the AsyncOpen value of the // previous channel (this is the first redirect in the redirects chain). if (mRedirectStartTimeStamp.IsNull()) { - TimeStamp asyncOpen; - oldTimedChannel->GetAsyncOpen(&asyncOpen); - newTimedChannel->SetRedirectStart(asyncOpen); - } - else { + // Only do this for real redirects. Internal redirects should be hidden. + if (!(redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) { + TimeStamp asyncOpen; + oldTimedChannel->GetAsyncOpen(&asyncOpen); + newTimedChannel->SetRedirectStart(asyncOpen); + } + } else { newTimedChannel->SetRedirectStart(mRedirectStartTimeStamp); } - // The RedirectEnd timestamp is equal to the previous channel response end. - TimeStamp prevResponseEnd; - oldTimedChannel->GetResponseEnd(&prevResponseEnd); - newTimedChannel->SetRedirectEnd(prevResponseEnd); + // For internal redirects just propagate the last redirect end time + // forward. Otherwise the new redirect end time is the last response + // end time. + TimeStamp newRedirectEnd; + if (redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) { + oldTimedChannel->GetRedirectEnd(&newRedirectEnd); + } else { + oldTimedChannel->GetResponseEnd(&newRedirectEnd); + } + newTimedChannel->SetRedirectEnd(newRedirectEnd); nsAutoString initiatorType; oldTimedChannel->GetInitiatorType(initiatorType); @@ -3253,6 +3265,16 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI, mAllRedirectsPassTimingAllowCheck && oldTimedChannel->TimingAllowCheck(principal)); } + + // Propagate service worker measurements across redirects. The + // PeformanceResourceTiming.workerStart API expects to see the + // worker start time after a redirect. + newTimedChannel->SetLaunchServiceWorkerStart(mLaunchServiceWorkerStart); + newTimedChannel->SetLaunchServiceWorkerEnd(mLaunchServiceWorkerEnd); + newTimedChannel->SetDispatchFetchEventStart(mDispatchFetchEventStart); + newTimedChannel->SetDispatchFetchEventEnd(mDispatchFetchEventEnd); + newTimedChannel->SetHandleFetchEventStart(mHandleFetchEventStart); + newTimedChannel->SetHandleFetchEventEnd(mHandleFetchEventEnd); } // Pass the preferred alt-data type on to the new channel. @@ -3318,20 +3340,34 @@ HttpBaseChannel::GetAsyncOpen(TimeStamp* _retval) { * redirects. This check must be done by the consumers. */ NS_IMETHODIMP -HttpBaseChannel::GetRedirectCount(uint16_t *aRedirectCount) +HttpBaseChannel::GetRedirectCount(uint8_t *aRedirectCount) { *aRedirectCount = mRedirectCount; return NS_OK; } NS_IMETHODIMP -HttpBaseChannel::SetRedirectCount(uint16_t aRedirectCount) +HttpBaseChannel::SetRedirectCount(uint8_t aRedirectCount) { mRedirectCount = aRedirectCount; return NS_OK; } NS_IMETHODIMP +HttpBaseChannel::GetInternalRedirectCount(uint8_t *aRedirectCount) +{ + *aRedirectCount = mInternalRedirectCount; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::SetInternalRedirectCount(uint8_t aRedirectCount) +{ + mInternalRedirectCount = aRedirectCount; + return NS_OK; +} + +NS_IMETHODIMP HttpBaseChannel::GetRedirectStart(TimeStamp* _retval) { *_retval = mRedirectStartTimeStamp; @@ -3431,6 +3467,84 @@ HttpBaseChannel::TimingAllowCheck(nsIPrincipal *aOrigin, bool *_retval) } NS_IMETHODIMP +HttpBaseChannel::GetLaunchServiceWorkerStart(TimeStamp* _retval) { + MOZ_ASSERT(_retval); + *_retval = mLaunchServiceWorkerStart; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::SetLaunchServiceWorkerStart(TimeStamp aTimeStamp) { + mLaunchServiceWorkerStart = aTimeStamp; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::GetLaunchServiceWorkerEnd(TimeStamp* _retval) { + MOZ_ASSERT(_retval); + *_retval = mLaunchServiceWorkerEnd; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::SetLaunchServiceWorkerEnd(TimeStamp aTimeStamp) { + mLaunchServiceWorkerEnd = aTimeStamp; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::GetDispatchFetchEventStart(TimeStamp* _retval) { + MOZ_ASSERT(_retval); + *_retval = mDispatchFetchEventStart; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::SetDispatchFetchEventStart(TimeStamp aTimeStamp) { + mDispatchFetchEventStart = aTimeStamp; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::GetDispatchFetchEventEnd(TimeStamp* _retval) { + MOZ_ASSERT(_retval); + *_retval = mDispatchFetchEventEnd; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::SetDispatchFetchEventEnd(TimeStamp aTimeStamp) { + mDispatchFetchEventEnd = aTimeStamp; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::GetHandleFetchEventStart(TimeStamp* _retval) { + MOZ_ASSERT(_retval); + *_retval = mHandleFetchEventStart; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::SetHandleFetchEventStart(TimeStamp aTimeStamp) { + mHandleFetchEventStart = aTimeStamp; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::GetHandleFetchEventEnd(TimeStamp* _retval) { + MOZ_ASSERT(_retval); + *_retval = mHandleFetchEventEnd; + return NS_OK; +} + +NS_IMETHODIMP +HttpBaseChannel::SetHandleFetchEventEnd(TimeStamp aTimeStamp) { + mHandleFetchEventEnd = aTimeStamp; + return NS_OK; +} + +NS_IMETHODIMP HttpBaseChannel::GetDomainLookupStart(TimeStamp* _retval) { *_retval = mTransactionTimings.domainLookupStart; return NS_OK; @@ -3520,6 +3634,12 @@ HttpBaseChannel::Get##name##Time(PRTime* _retval) { \ IMPL_TIMING_ATTR(ChannelCreation) IMPL_TIMING_ATTR(AsyncOpen) +IMPL_TIMING_ATTR(LaunchServiceWorkerStart) +IMPL_TIMING_ATTR(LaunchServiceWorkerEnd) +IMPL_TIMING_ATTR(DispatchFetchEventStart) +IMPL_TIMING_ATTR(DispatchFetchEventEnd) +IMPL_TIMING_ATTR(HandleFetchEventStart) +IMPL_TIMING_ATTR(HandleFetchEventEnd) IMPL_TIMING_ATTR(DomainLookupStart) IMPL_TIMING_ATTR(DomainLookupEnd) IMPL_TIMING_ATTR(ConnectStart) diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index c8184a601..9aa696a70 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -506,7 +506,9 @@ protected: // the HTML file. nsString mInitiatorType; // Number of redirects that has occurred. - int16_t mRedirectCount; + int8_t mRedirectCount; + // Number of internal redirects that has occurred. + int8_t mInternalRedirectCount; // A time value equal to the starting time of the fetch that initiates the // redirect. mozilla::TimeStamp mRedirectStartTimeStamp; @@ -519,6 +521,12 @@ protected: TimeStamp mAsyncOpenTime; TimeStamp mCacheReadStart; TimeStamp mCacheReadEnd; + TimeStamp mLaunchServiceWorkerStart; + TimeStamp mLaunchServiceWorkerEnd; + TimeStamp mDispatchFetchEventStart; + TimeStamp mDispatchFetchEventEnd; + TimeStamp mHandleFetchEventStart; + TimeStamp mHandleFetchEventEnd; // copied from the transaction before we null out mTransaction // so that the timing can still be queried from OnStopRequest TimingStruct mTransactionTimings; diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index f0b9e2136..6d09135c4 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -2132,6 +2132,13 @@ HttpChannelChild::ContinueAsyncOpen() return NS_ERROR_FAILURE; } + openArgs.launchServiceWorkerStart() = mLaunchServiceWorkerStart; + openArgs.launchServiceWorkerEnd() = mLaunchServiceWorkerEnd; + openArgs.dispatchFetchEventStart() = mDispatchFetchEventStart; + openArgs.dispatchFetchEventEnd() = mDispatchFetchEventEnd; + openArgs.handleFetchEventStart() = mHandleFetchEventStart; + openArgs.handleFetchEventEnd() = mHandleFetchEventEnd; + // The socket transport in the chrome process now holds a logical ref to us // until OnStopRequest, or we do a redirect, or we hit an IPDL error. AddIPDLReference(); diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 5f0859f28..90ed597a6 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -130,7 +130,13 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs) a.initialRwin(), a.blockAuthPrompt(), a.suspendAfterSynthesizeResponse(), a.allowStaleCacheContent(), a.contentTypeHint(), - a.channelId(), a.contentWindowId(), a.preferredAlternativeType()); + a.channelId(), a.contentWindowId(), a.preferredAlternativeType(), + a.launchServiceWorkerStart(), + a.launchServiceWorkerEnd(), + a.dispatchFetchEventStart(), + a.dispatchFetchEventEnd(), + a.handleFetchEventStart(), + a.handleFetchEventEnd()); } case HttpChannelCreationArgs::THttpChannelConnectArgs: { @@ -329,7 +335,13 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI, const nsCString& aContentTypeHint, const nsCString& aChannelId, const uint64_t& aContentWindowId, - const nsCString& aPreferredAlternativeType) + const nsCString& aPreferredAlternativeType, + const TimeStamp& aLaunchServiceWorkerStart, + const TimeStamp& aLaunchServiceWorkerEnd, + const TimeStamp& aDispatchFetchEventStart, + const TimeStamp& aDispatchFetchEventEnd, + const TimeStamp& aHandleFetchEventStart, + const TimeStamp& aHandleFetchEventEnd) { nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); if (!uri) { @@ -534,6 +546,13 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI, mChannel->SetInitialRwin(aInitialRwin); mChannel->SetBlockAuthPrompt(aBlockAuthPrompt); + mChannel->SetLaunchServiceWorkerStart(aLaunchServiceWorkerStart); + mChannel->SetLaunchServiceWorkerEnd(aLaunchServiceWorkerEnd); + mChannel->SetDispatchFetchEventStart(aDispatchFetchEventStart); + mChannel->SetDispatchFetchEventEnd(aDispatchFetchEventEnd); + mChannel->SetHandleFetchEventStart(aHandleFetchEventStart); + mChannel->SetHandleFetchEventEnd(aHandleFetchEventEnd); + nsCOMPtr<nsIApplicationCacheChannel> appCacheChan = do_QueryObject(mChannel); nsCOMPtr<nsIApplicationCacheService> appCacheService = @@ -1159,7 +1178,7 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) nsCString secInfoSerialization; UpdateAndSerializeSecurityInfo(secInfoSerialization); - uint16_t redirectCount = 0; + uint8_t redirectCount = 0; chan->GetRedirectCount(&redirectCount); nsCOMPtr<nsISupports> cacheKey; diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h index a3b377d49..56854bb55 100644 --- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -143,7 +143,13 @@ protected: const nsCString& aContentTypeHint, const nsCString& aChannelId, const uint64_t& aContentWindowId, - const nsCString& aPreferredAlternativeType); + const nsCString& aPreferredAlternativeType, + const TimeStamp& aLaunchServiceWorkerStart, + const TimeStamp& aLaunchServiceWorkerEnd, + const TimeStamp& aDispatchFetchEventStart, + const TimeStamp& aDispatchFetchEventEnd, + const TimeStamp& aHandleFetchEventStart, + const TimeStamp& aHandleFetchEventEnd); virtual bool RecvSetPriority(const uint16_t& priority) override; virtual bool RecvSetClassOfService(const uint32_t& cos) override; diff --git a/netwerk/protocol/http/InterceptedChannel.cpp b/netwerk/protocol/http/InterceptedChannel.cpp index 9e38e2734..2dadbe760 100644 --- a/netwerk/protocol/http/InterceptedChannel.cpp +++ b/netwerk/protocol/http/InterceptedChannel.cpp @@ -10,6 +10,7 @@ #include "nsInputStreamPump.h" #include "nsIPipe.h" #include "nsIStreamListener.h" +#include "nsITimedChannel.h" #include "nsHttpChannel.h" #include "HttpChannelChild.h" #include "nsHttpResponseHead.h" @@ -134,6 +135,40 @@ InterceptedChannelBase::SetReleaseHandle(nsISupports* aHandle) return NS_OK; } +NS_IMETHODIMP +InterceptedChannelBase::SaveTimeStampsToUnderlyingChannel() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr<nsIChannel> underlyingChannel; + nsresult rv = GetChannel(getter_AddRefs(underlyingChannel)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + nsCOMPtr<nsITimedChannel> timedChannel = + do_QueryInterface(underlyingChannel); + MOZ_ASSERT(timedChannel); + + rv = timedChannel->SetLaunchServiceWorkerStart(mLaunchServiceWorkerStart); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + rv = timedChannel->SetLaunchServiceWorkerEnd(mLaunchServiceWorkerEnd); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + rv = timedChannel->SetDispatchFetchEventStart(mDispatchFetchEventStart); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + rv = timedChannel->SetDispatchFetchEventEnd(mDispatchFetchEventEnd); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + rv = timedChannel->SetHandleFetchEventStart(mHandleFetchEventStart); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + rv = timedChannel->SetHandleFetchEventEnd(mHandleFetchEventEnd); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + return rv; +} + /* static */ already_AddRefed<nsIURI> InterceptedChannelBase::SecureUpgradeChannelURI(nsIChannel* aChannel) diff --git a/netwerk/protocol/http/InterceptedChannel.h b/netwerk/protocol/http/InterceptedChannel.h index 688f211de..efab7abca 100644 --- a/netwerk/protocol/http/InterceptedChannel.h +++ b/netwerk/protocol/http/InterceptedChannel.h @@ -46,6 +46,13 @@ protected: nsresult DoSynthesizeStatus(uint16_t aStatus, const nsACString& aReason); nsresult DoSynthesizeHeader(const nsACString& aName, const nsACString& aValue); + TimeStamp mLaunchServiceWorkerStart; + TimeStamp mLaunchServiceWorkerEnd; + TimeStamp mDispatchFetchEventStart; + TimeStamp mDispatchFetchEventEnd; + TimeStamp mHandleFetchEventStart; + TimeStamp mHandleFetchEventEnd; + virtual ~InterceptedChannelBase(); public: explicit InterceptedChannelBase(nsINetworkInterceptController* aController); @@ -60,6 +67,50 @@ public: NS_IMETHOD GetConsoleReportCollector(nsIConsoleReportCollector** aCollectorOut) override; NS_IMETHOD SetReleaseHandle(nsISupports* aHandle) override; + NS_IMETHODIMP + SetLaunchServiceWorkerStart(TimeStamp aTimeStamp) override + { + mLaunchServiceWorkerStart = aTimeStamp; + return NS_OK; + } + + NS_IMETHODIMP + SetLaunchServiceWorkerEnd(TimeStamp aTimeStamp) override + { + mLaunchServiceWorkerEnd = aTimeStamp; + return NS_OK; + } + + NS_IMETHODIMP + SetDispatchFetchEventStart(TimeStamp aTimeStamp) override + { + mDispatchFetchEventStart = aTimeStamp; + return NS_OK; + } + + NS_IMETHODIMP + SetDispatchFetchEventEnd(TimeStamp aTimeStamp) override + { + mDispatchFetchEventEnd = aTimeStamp; + return NS_OK; + } + + NS_IMETHODIMP + SetHandleFetchEventStart(TimeStamp aTimeStamp) override + { + mHandleFetchEventStart = aTimeStamp; + return NS_OK; + } + + NS_IMETHODIMP + SetHandleFetchEventEnd(TimeStamp aTimeStamp) override + { + mHandleFetchEventEnd = aTimeStamp; + return NS_OK; + } + + NS_IMETHODIMP SaveTimeStampsToUnderlyingChannel() override; + static already_AddRefed<nsIURI> SecureUpgradeChannelURI(nsIChannel* aChannel); }; diff --git a/netwerk/protocol/http/NullHttpChannel.cpp b/netwerk/protocol/http/NullHttpChannel.cpp index 61efe3956..2954006ad 100644 --- a/netwerk/protocol/http/NullHttpChannel.cpp +++ b/netwerk/protocol/http/NullHttpChannel.cpp @@ -539,13 +539,25 @@ NullHttpChannel::SetTimingEnabled(bool aTimingEnabled) } NS_IMETHODIMP -NullHttpChannel::GetRedirectCount(uint16_t *aRedirectCount) +NullHttpChannel::GetRedirectCount(uint8_t *aRedirectCount) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -NullHttpChannel::SetRedirectCount(uint16_t aRedirectCount) +NullHttpChannel::SetRedirectCount(uint8_t aRedirectCount) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +NullHttpChannel::GetInternalRedirectCount(uint8_t *aRedirectCount) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +NullHttpChannel::SetInternalRedirectCount(uint8_t aRedirectCount) { return NS_ERROR_NOT_IMPLEMENTED; } @@ -565,6 +577,90 @@ NullHttpChannel::GetAsyncOpen(mozilla::TimeStamp *aAsyncOpen) } NS_IMETHODIMP +NullHttpChannel::GetLaunchServiceWorkerStart(mozilla::TimeStamp *_retval) +{ + MOZ_ASSERT(_retval); + *_retval = mAsyncOpenTime; + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::SetLaunchServiceWorkerStart(mozilla::TimeStamp aTimeStamp) +{ + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::GetLaunchServiceWorkerEnd(mozilla::TimeStamp *_retval) +{ + MOZ_ASSERT(_retval); + *_retval = mAsyncOpenTime; + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::SetLaunchServiceWorkerEnd(mozilla::TimeStamp aTimeStamp) +{ + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::GetDispatchFetchEventStart(mozilla::TimeStamp *_retval) +{ + MOZ_ASSERT(_retval); + *_retval = mAsyncOpenTime; + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::SetDispatchFetchEventStart(mozilla::TimeStamp aTimeStamp) +{ + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::GetDispatchFetchEventEnd(mozilla::TimeStamp *_retval) +{ + MOZ_ASSERT(_retval); + *_retval = mAsyncOpenTime; + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::SetDispatchFetchEventEnd(mozilla::TimeStamp aTimeStamp) +{ + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::GetHandleFetchEventStart(mozilla::TimeStamp *_retval) +{ + MOZ_ASSERT(_retval); + *_retval = mAsyncOpenTime; + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::SetHandleFetchEventStart(mozilla::TimeStamp aTimeStamp) +{ + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::GetHandleFetchEventEnd(mozilla::TimeStamp *_retval) +{ + MOZ_ASSERT(_retval); + *_retval = mAsyncOpenTime; + return NS_OK; +} + +NS_IMETHODIMP +NullHttpChannel::SetHandleFetchEventEnd(mozilla::TimeStamp aTimeStamp) +{ + return NS_OK; +} + +NS_IMETHODIMP NullHttpChannel::GetDomainLookupStart(mozilla::TimeStamp *aDomainLookupStart) { *aDomainLookupStart = mAsyncOpenTime; @@ -761,6 +857,12 @@ NullHttpChannel::Get##name##Time(PRTime* _retval) { \ IMPL_TIMING_ATTR(ChannelCreation) IMPL_TIMING_ATTR(AsyncOpen) +IMPL_TIMING_ATTR(LaunchServiceWorkerStart) +IMPL_TIMING_ATTR(LaunchServiceWorkerEnd) +IMPL_TIMING_ATTR(DispatchFetchEventStart) +IMPL_TIMING_ATTR(DispatchFetchEventEnd) +IMPL_TIMING_ATTR(HandleFetchEventStart) +IMPL_TIMING_ATTR(HandleFetchEventEnd) IMPL_TIMING_ATTR(DomainLookupStart) IMPL_TIMING_ATTR(DomainLookupEnd) IMPL_TIMING_ATTR(ConnectStart) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index ce0f45dab..05699df62 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -1152,7 +1152,7 @@ ProcessXCTO(nsIURI* aURI, nsHttpResponseHead* aResponseHead, nsILoadInfo* aLoadI } if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SCRIPT) { - if (nsContentUtils::IsScriptType(contentType)) { + if (nsContentUtils::IsJavascriptMIMEType(NS_ConvertUTF8toUTF16(contentType))) { return NS_OK; } ReportTypeBlocking(aURI, aLoadInfo, "MimeTypeMismatch"); @@ -5402,7 +5402,7 @@ nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) if (NS_EscapeURL(location.get(), -1, esc_OnlyNonASCII, locationBuf)) location = locationBuf; - if (mRedirectionLimit == 0) { + if (mRedirectCount >= mRedirectionLimit || mInternalRedirectCount >= mRedirectionLimit) { LOG(("redirection limit reached!\n")); return NS_ERROR_REDIRECT_LOOP; } diff --git a/netwerk/protocol/http/nsHttpHandler.h b/netwerk/protocol/http/nsHttpHandler.h index d51662db9..35b14a511 100644 --- a/netwerk/protocol/http/nsHttpHandler.h +++ b/netwerk/protocol/http/nsHttpHandler.h @@ -489,8 +489,8 @@ private: nsCString mCompatGecko; bool mCompatGeckoEnabled; nsCString mCompatFirefox; - nsCString mCompatFirefoxVersion; bool mCompatFirefoxEnabled; + nsCString mCompatFirefoxVersion; nsXPIDLCString mCompatDevice; nsCString mDeviceModelId; diff --git a/netwerk/test/unit/test_URIs.js b/netwerk/test/unit/test_URIs.js index b68c4f787..1cad7768f 100644 --- a/netwerk/test/unit/test_URIs.js +++ b/netwerk/test/unit/test_URIs.js @@ -92,18 +92,6 @@ var gTests = [ ref: "", relativeURI: "data/text/plain,2", nsIURL: true, nsINestedURI: false }, - { spec: "ftp://", - scheme: "ftp", - prePath: "ftp://", - path: "/", - ref: "", - nsIURL: true, nsINestedURI: false }, - { spec: "ftp:///", - scheme: "ftp", - prePath: "ftp://", - path: "/", - ref: "", - nsIURL: true, nsINestedURI: false }, { spec: "ftp://ftp.mozilla.org/pub/mozilla.org/README", scheme: "ftp", prePath: "ftp://ftp.mozilla.org", @@ -121,7 +109,7 @@ var gTests = [ nsIURL: true, nsINestedURI: false }, { spec: "ftp://foo:@ftp.mozilla.org:100/pub/mozilla.org/README", scheme: "ftp", - prePath: "ftp://foo:@ftp.mozilla.org:100", + prePath: "ftp://foo@ftp.mozilla.org:100", port: 100, username: "foo", password: "", @@ -135,18 +123,6 @@ var gTests = [ path: "//mozilla.org/", ref: "", nsIURL: false, nsINestedURI: false }, - { spec: "http://", - scheme: "http", - prePath: "http://", - path: "/", - ref: "", - nsIURL: true, nsINestedURI: false }, - { spec: "http:///", - scheme: "http", - prePath: "http://", - path: "/", - ref: "", - nsIURL: true, nsINestedURI: false }, { spec: "http://www.example.com/", scheme: "http", prePath: "http://www.example.com", diff --git a/netwerk/test/unit/test_standardurl.js b/netwerk/test/unit/test_standardurl.js index c4d44f41f..4cc2f393e 100644 --- a/netwerk/test/unit/test_standardurl.js +++ b/netwerk/test/unit/test_standardurl.js @@ -251,6 +251,17 @@ add_test(function test_escapeBrackets() run_next_test(); }); +add_test(function test_escapeQuote() +{ + var url = stringToURL("http://example.com/#'"); + do_check_eq(url.spec, "http://example.com/#'"); + do_check_eq(url.ref, "'"); + url.ref = "test'test"; + do_check_eq(url.spec, "http://example.com/#test'test"); + do_check_eq(url.ref, "test'test"); + run_next_test(); +}); + add_test(function test_apostropheEncoding() { // For now, single quote is escaped everywhere _except_ the path. @@ -335,6 +346,14 @@ add_test(function test_backslashReplacement() run_next_test(); }); +add_test(function test_authority_host() +{ + Assert.throws(() => { stringToURL("http:"); }, "TYPE_AUTHORITY should have host"); + Assert.throws(() => { stringToURL("http:///"); }, "TYPE_AUTHORITY should have host"); + + run_next_test(); +}); + add_test(function test_trim_C0_and_space() { var url = stringToURL("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f http://example.com/ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f "); @@ -453,3 +472,23 @@ add_test(function test_invalidHostChars() { // hostname separators, so there is no way to set them and fail. run_next_test(); }); + +add_test(function test_emptyPassword() { + var url = stringToURL("http://a:@example.com"); + do_check_eq(url.spec, "http://a@example.com/"); + url.password = "pp"; + do_check_eq(url.spec, "http://a:pp@example.com/"); + url.password = ""; + do_check_eq(url.spec, "http://a@example.com/"); + url.userPass = "xxx:"; + do_check_eq(url.spec, "http://xxx@example.com/"); + url.password = "zzzz"; + do_check_eq(url.spec, "http://xxx:zzzz@example.com/"); + url.userPass = "xxxxx:yyyyyy"; + do_check_eq(url.spec, "http://xxxxx:yyyyyy@example.com/"); + url.userPass = "z:"; + do_check_eq(url.spec, "http://z@example.com/"); + url.password = "ppppppppppp"; + do_check_eq(url.spec, "http://z:ppppppppppp@example.com/"); + run_next_test(); +}); |