/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
if (reporter) { // NOTE: is appears that `const nsTArray<nsString>&` is required for // nsIConsoleReportCollector::AddConsoleReport to resolve to the correct // overload. const nsTArray<nsString> params = std::move(aParams);
FetchEventOpChild* actor = new FetchEventOpChild(
std::move(aArgs), std::move(aInterceptedChannel),
std::move(aRegistration), std::move(aPreloadResponseReadyPromises),
std::move(aKeepAliveToken));
actor->mWasSent = true;
RefPtr<GenericPromise> promise = actor->mPromiseHolder.Ensure(__func__);
Unused << aManager->SendPFetchEventOpConstructor(actor, actor->mArgs); // NOTE: actor may have been destroyed return promise;
}
FetchEventOpChild::FetchEventOpChild(
ParentToParentServiceWorkerFetchEventOpArgs&& aArgs,
nsCOMPtr<nsIInterceptedChannel>&& aInterceptedChannel,
RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration,
RefPtr<FetchServicePromises>&& aPreloadResponseReadyPromises,
RefPtr<KeepAliveToken>&& aKeepAliveToken)
: mArgs(std::move(aArgs)),
mInterceptedChannel(std::move(aInterceptedChannel)),
mRegistration(std::move(aRegistration)),
mKeepAliveToken(std::move(aKeepAliveToken)),
mPreloadResponseReadyPromises(std::move(aPreloadResponseReadyPromises)) { if (mPreloadResponseReadyPromises) { // This promise should be configured to use synchronous dispatch, so if it's // already resolved when we run this code then the callback will be called // synchronously and pass the preload response with the constructor message. // // Note that it's fine to capture the this pointer in the callbacks because // we disconnect the request in Recv__delete__().
mPreloadResponseReadyPromises->GetResponseAvailablePromise()
->Then(
GetCurrentSerialEventTarget(), __func__,
[this](FetchServiceResponse&& aResponse) { if (!mWasSent) { // The actor wasn't sent yet, we can still send the preload // response with it.
mArgs.preloadResponse() =
Some(aResponse->ToParentToParentInternalResponse());
} else { // It's too late to send the preload response with the actor, we // have to send it in a separate message.
SendPreloadResponse(
aResponse->ToParentToParentInternalResponse());
}
mPreloadResponseAvailablePromiseRequestHolder.Complete();
},
[this](const CopyableErrorResult&) {
mPreloadResponseAvailablePromiseRequestHolder.Complete();
})
->Track(mPreloadResponseAvailablePromiseRequestHolder);
mPreloadResponseReadyPromises->GetResponseTimingPromise()
->Then(
GetCurrentSerialEventTarget(), __func__,
[this](ResponseTiming&& aTiming) { if (!mWasSent) { // The actor wasn't sent yet, we can still send the preload // response timing with it.
mArgs.preloadResponseTiming() = Some(std::move(aTiming));
} else {
SendPreloadResponseTiming(aTiming);
}
mPreloadResponseTimingPromiseRequestHolder.Complete();
},
[this](const CopyableErrorResult&) {
mPreloadResponseTimingPromiseRequestHolder.Complete();
})
->Track(mPreloadResponseTimingPromiseRequestHolder);
mPreloadResponseReadyPromises->GetResponseEndPromise()
->Then(
GetCurrentSerialEventTarget(), __func__,
[this](ResponseEndArgs&& aResponse) { if (!mWasSent) { // The actor wasn't sent yet, we can still send the preload // response end args with it.
mArgs.preloadResponseEndArgs() = Some(std::move(aResponse));
} else { // It's too late to send the preload response end with the // actor, we have to send it in a separate message.
SendPreloadResponseEnd(aResponse);
}
mPreloadResponseReadyPromises = nullptr;
mPreloadResponseEndPromiseRequestHolder.Complete();
},
[this](const CopyableErrorResult&) {
mPreloadResponseReadyPromises = nullptr;
mPreloadResponseEndPromiseRequestHolder.Complete();
})
->Track(mPreloadResponseEndPromiseRequestHolder);
}
}
if (NS_WARN_IF(!mInterceptedChannelHandled)) {
MOZ_ASSERT(NS_FAILED(aResult.rv()));
NS_WARNING( "Failed to handle intercepted network request; canceling " "interception!");
CancelInterception(aResult.rv());
}
mPromiseHolder.ResolveIfExists(true, __func__);
// FetchEvent is completed. // Disconnect preload response related promises and cancel the preload.
mPreloadResponseAvailablePromiseRequestHolder.DisconnectIfExists();
mPreloadResponseTimingPromiseRequestHolder.DisconnectIfExists();
mPreloadResponseEndPromiseRequestHolder.DisconnectIfExists(); if (mPreloadResponseReadyPromises) {
RefPtr<FetchService> fetchService = FetchService::GetInstance();
fetchService->CancelFetch(std::move(mPreloadResponseReadyPromises), false);
}
/** * This corresponds to the "Fire Functional Event" algorithm's step 9: * * "If the time difference in seconds calculated by the current time minus * registration's last update check time is greater than 84600, invoke Soft * Update algorithm with registration." * * TODO: this is probably being called later than it should be; it should be * called ASAP after dispatching the FetchEvent.
*/
mRegistration->MaybeScheduleTimeCheckAndUpdate();
/** * TODO: moving the IPCInternalResponse won't do anything right now because * there isn't a prefect-forwarding or rvalue-ref-parameter overload of * `InternalResponse::FromIPC().`
*/
SafeRefPtr<InternalResponse> response =
InternalResponse::FromIPC(aArgs.internalResponse()); if (NS_WARN_IF(!response)) { return NS_ERROR_FAILURE;
}
auto castLoadInfo = static_cast<mozilla::net::LoadInfo*>(loadInfo.get());
castLoadInfo->SynthesizeServiceWorkerTainting(response->GetTainting());
// Get the preferred alternative data type of the outer channel
nsAutoCString preferredAltDataType(""_ns);
nsCOMPtr<nsICacheInfoChannel> outerChannel =
do_QueryInterface(underlyingChannel); if (outerChannel &&
!outerChannel->PreferredAlternativeDataTypes().IsEmpty()) {
preferredAltDataType.Assign(
outerChannel->PreferredAlternativeDataTypes()[0].type());
}
nsCOMPtr<nsIInputStream> body; if (preferredAltDataType.Equals(response->GetAlternativeDataType())) {
body = response->TakeAlternativeBody();
} if (!body) {
response->GetUnfilteredBody(getter_AddRefs(body));
}
// Propagate the URL to the content if the request mode is not "navigate". // Note that, we only reflect the final URL if the response.redirected is // false. We propagate all the URLs if the response.redirected is true. const IPCInternalRequest& request = mArgs.common().internalRequest();
nsAutoCString responseURL; if (request.requestMode() != RequestMode::Navigate) {
responseURL = response->GetUnfilteredURL();
// Similar to how we apply the request fragment to redirects automatically // we also want to apply it automatically when propagating the response // URL from a service worker interception. Currently response.url strips // the fragment, so this will never conflict with an existing fragment // on the response. In the future we will have to check for a response // fragment and avoid overriding in that case. if (!request.fragment().IsEmpty() && !responseURL.IsEmpty()) {
MOZ_ASSERT(!responseURL.Contains('#'));
responseURL.AppendLiteral("#");
responseURL.Append(request.fragment());
}
}
nsMainThreadPtrHandle<nsIInterceptedChannel> interceptedChannel( new nsMainThreadPtrHolder<nsIInterceptedChannel>( "nsIInterceptedChannel", mInterceptedChannel, false));
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> registration( new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>( "ServiceWorkerRegistrationInfo", mRegistration, false));
nsCString requestURL = request.urlList().LastElement(); if (!request.fragment().IsEmpty()) {
requestURL.AppendLiteral("#");
requestURL.Append(request.fragment());
}
RefPtr<SynthesizeResponseWatcher> watcher = new SynthesizeResponseWatcher(
interceptedChannel, registration,
mArgs.common().isNonSubresourceRequest(), std::move(aArgs.closure()),
NS_ConvertUTF8toUTF16(responseURL));
rv = mInterceptedChannel->StartSynthesizedResponse(
body, watcher, nullptr /* TODO */, responseURL, response->IsRedirected()); if (NS_WARN_IF(NS_FAILED(rv))) { return rv;
}
// Report a navigation fault if this is a navigation (and we have an active // worker, which should be the case in non-shutdown/content-process-crash // situations).
RefPtr<ServiceWorkerInfo> mActive = mRegistration->GetActive(); if (mActive && mArgs.common().isNonSubresourceRequest()) {
mActive->ReportNavigationFault(); // Additional mitigations such as unregistering the registration are handled // in ServiceWorkerRegistrationInfo::MaybeScheduleUpdate which will be // called by MaybeScheduleRegistrationUpdate which gets called by our call // to ResetInterception. if (StaticPrefs::dom_serviceWorkers_mitigations_bypass_on_fault()) {
ResetInterception(true); return;
}
}
/** * This corresponds to the "Handle Fetch" algorithm's steps 20.3, 21.2, and * 22.2: * * "If request is a non-subresource request, or request is a subresource * request and the time difference in seconds calculated by the current time * minus registration's last update check time is greater than 86400, invoke * Soft Update algorithm with registration."
*/ void FetchEventOpChild::MaybeScheduleRegistrationUpdate() const {
AssertIsOnMainThread();
MOZ_ASSERT(mRegistration);
MOZ_ASSERT(mInterceptedChannelHandled);
if (mArgs.common().isNonSubresourceRequest()) {
mRegistration->MaybeScheduleUpdate();
} else {
mRegistration->MaybeScheduleTimeCheckAndUpdate();
}
}
} // namespace mozilla::dom
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.