diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:14:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:14:29 +0000 |
commit | fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 (patch) | |
tree | 4c1ccaf5486d4f2009f9a338a98a83e886e29c97 /layout/style/StreamLoader.cpp | |
parent | Releasing progress-linux version 124.0.1-1~progress7.99u1. (diff) | |
download | firefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.tar.xz firefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.zip |
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | layout/style/StreamLoader.cpp | 114 |
1 files changed, 93 insertions, 21 deletions
diff --git a/layout/style/StreamLoader.cpp b/layout/style/StreamLoader.cpp index 3e8bd37d76..3c614d7d0c 100644 --- a/layout/style/StreamLoader.cpp +++ b/layout/style/StreamLoader.cpp @@ -5,8 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/css/StreamLoader.h" - +#include "mozilla/StaticPrefs_network.h" #include "mozilla/Encoding.h" +#include "mozilla/glean/GleanMetrics.h" #include "mozilla/TaskQueue.h" #include "nsContentUtils.h" #include "nsIChannel.h" @@ -14,16 +15,21 @@ #include "nsIThreadRetargetableRequest.h" #include "nsIStreamTransportService.h" #include "nsNetCID.h" +#include "nsNetUtil.h" +#include "nsProxyRelease.h" #include "nsServiceManagerUtils.h" namespace mozilla::css { StreamLoader::StreamLoader(SheetLoadData& aSheetLoadData) - : mSheetLoadData(&aSheetLoadData), mStatus(NS_OK) {} + : mSheetLoadData(&aSheetLoadData), + mStatus(NS_OK), + mMainThreadSheetLoadData(new nsMainThreadPtrHolder<SheetLoadData>( + "StreamLoader::SheetLoadData", mSheetLoadData, false)) {} StreamLoader::~StreamLoader() { #ifdef NIGHTLY_BUILD - MOZ_RELEASE_ASSERT(mOnStopRequestCalled || mChannelOpenFailed); + MOZ_RELEASE_ASSERT(mOnStopProcessingDone || mChannelOpenFailed); #endif } @@ -34,6 +40,7 @@ NS_IMPL_ISUPPORTS(StreamLoader, nsIStreamListener, NS_IMETHODIMP StreamLoader::OnStartRequest(nsIRequest* aRequest) { MOZ_ASSERT(aRequest); + mRequest = aRequest; mSheetLoadData->NotifyStart(aRequest); // It's kinda bad to let Web content send a number that results @@ -52,6 +59,12 @@ StreamLoader::OnStartRequest(nsIRequest* aRequest) { return (mStatus = NS_ERROR_OUT_OF_MEMORY); } } + NS_GetFinalChannelURI(channel, getter_AddRefs(mFinalChannelURI)); + nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); + // we dont return on error here as the error is handled in + // SheetLoadData::VerifySheetReadyToParse + Unused << secMan->GetChannelResultPrincipal( + channel, getter_AddRefs(mChannelResultPrincipal)); } if (nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(aRequest)) { nsCOMPtr<nsIEventTarget> sts = @@ -73,6 +86,13 @@ StreamLoader::OnStartRequest(nsIRequest* aRequest) { return *info.mExpirationTime; }(); + // We need to block block resolution of parse promise until we receive + // OnStopRequest on Main thread. This is necessary because parse promise + // resolution fires OnLoad event OnLoad event must not be dispatched until + // OnStopRequest in main thread is processed, for stuff like performance + // resource entries. + mSheetLoadData->mSheet->BlockParsePromise(); + return NS_OK; } @@ -81,39 +101,80 @@ StreamLoader::CheckListenerChain() { return NS_OK; } NS_IMETHODIMP StreamLoader::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) { -#ifdef NIGHTLY_BUILD - MOZ_RELEASE_ASSERT(!mOnStopRequestCalled); - mOnStopRequestCalled = true; -#endif + MOZ_ASSERT_IF(!StaticPrefs::network_send_OnDataFinished_cssLoader(), + !mOnStopProcessingDone); + + // StreamLoader::OnStopRequest can get triggered twice for a request. + // Once from the path + // nsIThreadRetargetableStreamListener::OnDataFinished->StreamLoader::OnDataFinished + // (non-main thread) and + // once from nsIRequestObserver::OnStopRequest path (main thread). It is + // guaranteed that we will always get + // nsIThreadRetargetableStreamListener::OnDataFinished trigger first and this + // is always followed by nsIRequestObserver::OnStopRequest + + // If we are executing OnStopRequest OMT, we need to block resolution of parse + // promise and unblock again if we are executing this in main thread. + // Resolution of parse promise fires onLoadEvent and this should not happen + // before main thread OnStopRequest is dispatched. + if (NS_IsMainThread()) { + if (mOnDataFinishedTime) { + // collect telemetry for the delta between OnDataFinished and + // OnStopRequest + TimeDuration delta = (TimeStamp::Now() - mOnDataFinishedTime); + glean::networking::http_content_cssloader_ondatafinished_to_onstop_delay + .AccumulateRawDuration(delta); + } + mSheetLoadData->mSheet->UnblockParsePromise(); + } + + if (mOnStopProcessingDone) { + return NS_OK; + } + mOnStopProcessingDone = true; nsresult rv = mStatus; // Decoded data nsCString utf8String; { - // Hold the nsStringBuffer for the bytes from the stack to ensure release - // no matter which return branch is taken. - nsCString bytes = std::move(mBytes); - nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); if (NS_FAILED(mStatus)) { - mSheetLoadData->VerifySheetReadyToParse(mStatus, ""_ns, ""_ns, channel); + mSheetLoadData->VerifySheetReadyToParse(mStatus, ""_ns, ""_ns, channel, + mFinalChannelURI, + mChannelResultPrincipal); + + if (!NS_IsMainThread()) { + // When processing OMT, we have code paths in VerifySheetReadyToParse + // that are main-thread only. We bail on such scenarios and continue + // processing them on main thread OnStopRequest. + mOnStopProcessingDone = false; + } return mStatus; } - rv = mSheetLoadData->VerifySheetReadyToParse(aStatus, mBOMBytes, bytes, - channel); + rv = mSheetLoadData->VerifySheetReadyToParse(aStatus, mBOMBytes, mBytes, + channel, mFinalChannelURI, + mChannelResultPrincipal); if (rv != NS_OK_PARSE_SHEET) { + if (!NS_IsMainThread()) { + mOnStopProcessingDone = false; + } return rv; } - // BOM detection generally happens during the write callback, but that won't - // have happened if fewer than three bytes were received. + // At this point all the conditions that requires us to run on main + // are checked in VerifySheetReadyToParse + + // BOM detection generally happens during the write callback, but that + // won't have happened if fewer than three bytes were received. if (mEncodingFromBOM.isNothing()) { HandleBOM(); MOZ_ASSERT(mEncodingFromBOM.isSome()); } - + // Hold the nsStringBuffer for the bytes from the stack to ensure release + // after its scope ends + nsCString bytes = std::move(mBytes); // The BOM handling has happened, but we still may not have an encoding if // there was no BOM. Ensure we have one. const Encoding* encoding = mEncodingFromBOM.value(); @@ -142,9 +203,11 @@ StreamLoader::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) { // For reasons I don't understand, factoring the below lines into // a method on SheetLoadData resulted in a linker error. Hence, // accessing fields of mSheetLoadData from here. - mSheetLoadData->mLoader->ParseSheet(utf8String, *mSheetLoadData, + mSheetLoadData->mLoader->ParseSheet(utf8String, mMainThreadSheetLoadData, Loader::AllowAsyncParse::Yes); + mRequest = nullptr; + return NS_OK; } @@ -159,9 +222,6 @@ StreamLoader::OnDataAvailable(nsIRequest*, nsIInputStream* aInputStream, return aInputStream->ReadSegments(WriteSegmentFun, this, aCount, &dummy); } -NS_IMETHODIMP -StreamLoader::OnDataFinished(nsresult aStatus) { return NS_OK; } - void StreamLoader::HandleBOM() { MOZ_ASSERT(mEncodingFromBOM.isNothing()); MOZ_ASSERT(mBytes.IsEmpty()); @@ -176,6 +236,18 @@ void StreamLoader::HandleBOM() { mBOMBytes.Truncate(bomLength); } +NS_IMETHODIMP +StreamLoader::OnDataFinished(nsresult aResult) { + if (StaticPrefs::network_send_OnDataFinished_cssLoader()) { + MOZ_ASSERT(mOnDataFinishedTime.IsNull(), + "OnDataFinished should only be called once"); + mOnDataFinishedTime = TimeStamp::Now(); + return OnStopRequest(mRequest, aResult); + } + + return NS_OK; +} + nsresult StreamLoader::WriteSegmentFun(nsIInputStream*, void* aClosure, const char* aSegment, uint32_t, uint32_t aCount, uint32_t* aWriteCount) { |