mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1351231 - FetchService integration for PFetch. r=dom-worker-reviewers,jesup
Depends on D142436 Differential Revision: https://phabricator.services.mozilla.com/D142437
This commit is contained in:
parent
22c302924c
commit
2ca58b8fde
@ -39,6 +39,7 @@
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/PerformanceStorage.h"
|
||||
#include "mozilla/dom/PerformanceTiming.h"
|
||||
#include "mozilla/dom/ServiceWorkerInterceptController.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
#include "mozilla/dom/WorkerCommon.h"
|
||||
#include "mozilla/PreloaderBase.h"
|
||||
@ -319,7 +320,8 @@ AlternativeDataStreamListener::CheckListenerChain() { return NS_OK; }
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS(FetchDriver, nsIStreamListener, nsIChannelEventSink,
|
||||
nsIInterfaceRequestor, nsIThreadRetargetableStreamListener)
|
||||
nsIInterfaceRequestor, nsIThreadRetargetableStreamListener,
|
||||
nsINetworkInterceptController)
|
||||
|
||||
FetchDriver::FetchDriver(SafeRefPtr<InternalRequest> aRequest,
|
||||
nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup,
|
||||
@ -1464,6 +1466,55 @@ void FetchDriver::FinishOnStopRequest(
|
||||
Unfollow();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FetchDriver::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
|
||||
bool* aShouldIntercept) {
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
if (mInterceptController) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
|
||||
aShouldIntercept);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINetworkInterceptController> controller;
|
||||
NS_QueryNotificationCallbacks(nullptr, mLoadGroup,
|
||||
NS_GET_IID(nsINetworkInterceptController),
|
||||
getter_AddRefs(controller));
|
||||
if (controller) {
|
||||
return controller->ShouldPrepareForIntercept(aURI, aChannel,
|
||||
aShouldIntercept);
|
||||
}
|
||||
|
||||
*aShouldIntercept = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FetchDriver::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
|
||||
if (mInterceptController) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
return mInterceptController->ChannelIntercepted(aChannel);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINetworkInterceptController> controller;
|
||||
NS_QueryNotificationCallbacks(nullptr, mLoadGroup,
|
||||
NS_GET_IID(nsINetworkInterceptController),
|
||||
getter_AddRefs(controller));
|
||||
if (controller) {
|
||||
return controller->ChannelIntercepted(aChannel);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void FetchDriver::EnableNetworkInterceptControl() {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mInterceptController);
|
||||
mInterceptController = new ServiceWorkerInterceptController();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel, uint32_t aFlags,
|
||||
@ -1577,7 +1628,9 @@ void FetchDriver::SetController(
|
||||
PerformanceTimingData* FetchDriver::GetPerformanceTimingData(
|
||||
nsAString& aInitiatorType, nsAString& aEntryName) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(mChannel);
|
||||
if (!mChannel) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(mChannel);
|
||||
if (!timedChannel) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "mozilla/ConsoleReportCollector.h"
|
||||
@ -92,6 +93,7 @@ class AlternativeDataStreamListener;
|
||||
class FetchDriver final : public nsIStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsINetworkInterceptController,
|
||||
public nsIThreadRetargetableStreamListener,
|
||||
public AbortFollower {
|
||||
public:
|
||||
@ -100,6 +102,7 @@ class FetchDriver final : public nsIStreamListener,
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSINETWORKINTERCEPTCONTROLLER
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
|
||||
FetchDriver(SafeRefPtr<InternalRequest> aRequest, nsIPrincipal* aPrincipal,
|
||||
@ -133,6 +136,8 @@ class FetchDriver final : public nsIStreamListener,
|
||||
void RunAbortAlgorithm() override;
|
||||
void FetchDriverAbortActions(AbortSignalImpl* aSignalImpl);
|
||||
|
||||
void EnableNetworkInterceptControl();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
@ -181,6 +186,7 @@ class FetchDriver final : public nsIStreamListener,
|
||||
bool mResponseAvailableCalled;
|
||||
bool mFetchCalled;
|
||||
#endif
|
||||
nsCOMPtr<nsINetworkInterceptController> mInterceptController;
|
||||
|
||||
friend class AlternativeDataStreamListener;
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "FetchLog.h"
|
||||
#include "FetchParent.h"
|
||||
#include "FetchService.h"
|
||||
#include "InternalRequest.h"
|
||||
#include "InternalResponse.h"
|
||||
#include "mozilla/SchedulerGroup.h"
|
||||
@ -79,8 +80,7 @@ FetchParent::FetchParent() : mID(nsID::GenerateUUID()) {
|
||||
|
||||
FetchParent::~FetchParent() {
|
||||
FETCH_LOG(("FetchParent::~FetchParent [%p]", this));
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(!mBackgroundEventTarget);
|
||||
// MOZ_ASSERT(!mBackgroundEventTarget);
|
||||
MOZ_ASSERT(!mResponsePromises);
|
||||
MOZ_ASSERT(mActorDestroyed && mIsDone);
|
||||
}
|
||||
@ -101,6 +101,7 @@ IPCResult FetchParent::RecvFetchOp(FetchOpArgs&& aArgs) {
|
||||
if (aArgs.controller().isSome()) {
|
||||
mController = Some(ServiceWorkerDescriptor(aArgs.controller().ref()));
|
||||
}
|
||||
mCookieJarSettings = aArgs.cookieJarSettings();
|
||||
mNeedOnDataAvailable = aArgs.needOnDataAvailable();
|
||||
mHasCSPEventListener = aArgs.hasCSPEventListener();
|
||||
|
||||
@ -119,8 +120,18 @@ IPCResult FetchParent::RecvFetchOp(FetchOpArgs&& aArgs) {
|
||||
FETCH_LOG(
|
||||
("FetchParent::RecvFetchOp [%p] Success Callback", self.get()));
|
||||
AssertIsOnBackgroundThread();
|
||||
self->mPromise = nullptr;
|
||||
if (self->mIsDone) {
|
||||
FETCH_LOG(("FetchParent::RecvFetchOp [%p] Fetch has already aborted",
|
||||
self.get()));
|
||||
if (!self->mActorDestroyed) {
|
||||
Unused << NS_WARN_IF(
|
||||
!self->Send__delete__(self, NS_ERROR_DOM_ABORT_ERR));
|
||||
}
|
||||
return;
|
||||
}
|
||||
self->mIsDone = true;
|
||||
if (!self->mActorDestroyed) {
|
||||
if (!self->mActorDestroyed && !self->mExtendForCSPEventListener) {
|
||||
FETCH_LOG(("FetchParent::RecvFetchOp [%p] Send__delete__(NS_OK)",
|
||||
self.get()));
|
||||
Unused << NS_WARN_IF(!self->Send__delete__(self, NS_OK));
|
||||
@ -131,6 +142,7 @@ IPCResult FetchParent::RecvFetchOp(FetchOpArgs&& aArgs) {
|
||||
("FetchParent::RecvFetchOp [%p] Failure Callback", self.get()));
|
||||
AssertIsOnBackgroundThread();
|
||||
self->mIsDone = true;
|
||||
self->mPromise = nullptr;
|
||||
if (!self->mActorDestroyed) {
|
||||
FETCH_LOG(("FetchParent::RecvFetchOp [%p] Send__delete__(aErr)",
|
||||
self.get()));
|
||||
@ -138,7 +150,7 @@ IPCResult FetchParent::RecvFetchOp(FetchOpArgs&& aArgs) {
|
||||
}
|
||||
});
|
||||
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(__func__, [self]() mutable {
|
||||
RefPtr<nsIRunnable> r = NS_NewRunnableFunction(__func__, [self]() mutable {
|
||||
FETCH_LOG(
|
||||
("FetchParent::RecvFetchOp [%p], Main Thread Runnable", self.get()));
|
||||
AssertIsOnMainThread();
|
||||
@ -152,8 +164,31 @@ IPCResult FetchParent::RecvFetchOp(FetchOpArgs&& aArgs) {
|
||||
self->mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
|
||||
return;
|
||||
}
|
||||
// TODO: Initialize a fetch through FetchService::Fetch, and saving
|
||||
// returned promises into mResponsePromises
|
||||
RefPtr<FetchService> fetchService = FetchService::GetInstance();
|
||||
MOZ_ASSERT(fetchService);
|
||||
MOZ_ASSERT(!self->mResponsePromises);
|
||||
self->mResponsePromises =
|
||||
fetchService->Fetch(AsVariant(FetchService::WorkerFetchArgs(
|
||||
{self->mRequest.clonePtr(), self->mPrincipalInfo,
|
||||
self->mWorkerScript, self->mClientInfo, self->mController,
|
||||
self->mCookieJarSettings, self->mNeedOnDataAvailable,
|
||||
self->mCSPEventListener, self->mBackgroundEventTarget,
|
||||
self->mID})));
|
||||
|
||||
self->mResponsePromises->GetResponseEndPromise()->Then(
|
||||
self->mBackgroundEventTarget, __func__,
|
||||
[self](ResponseEndArgs&& aArgs) mutable {
|
||||
MOZ_ASSERT(self->mPromise);
|
||||
self->mPromise->Resolve(true, __func__);
|
||||
self->mResponsePromises = nullptr;
|
||||
self->mPromise = nullptr;
|
||||
},
|
||||
[self](CopyableErrorResult&& aErr) mutable {
|
||||
MOZ_ASSERT(self->mPromise);
|
||||
self->mPromise->Reject(aErr.StealNSResult(), __func__);
|
||||
self->mResponsePromises = nullptr;
|
||||
self->mPromise = nullptr;
|
||||
});
|
||||
});
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
@ -172,29 +207,90 @@ IPCResult FetchParent::RecvAbortFetchOp() {
|
||||
}
|
||||
mIsDone = true;
|
||||
|
||||
if (mResponsePromises) {
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
__func__, [promises = std::move(mResponsePromises)]() mutable {
|
||||
FETCH_LOG(("FetchParent::RecvAbortFetchOp Runnable"));
|
||||
AssertIsOnMainThread();
|
||||
RefPtr<FetchParent> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
__func__, [self]() mutable {
|
||||
FETCH_LOG(("FetchParent::RecvAbortFetchOp Runnable"));
|
||||
AssertIsOnMainThread();
|
||||
if (self->mResponsePromises) {
|
||||
RefPtr<FetchService> fetchService = FetchService::GetInstance();
|
||||
MOZ_ASSERT(fetchService);
|
||||
fetchService->CancelFetch(std::move(promises));
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
SchedulerGroup::Dispatch(TaskCategory::Other, r.forget()));
|
||||
}
|
||||
fetchService->CancelFetch(std::move(self->mResponsePromises));
|
||||
}
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
SchedulerGroup::Dispatch(TaskCategory::Other, r.forget()));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void FetchParent::OnResponseAvailableInternal(
|
||||
SafeRefPtr<InternalResponse>&& aResponse) {
|
||||
FETCH_LOG(("FetchParent::OnResponseAvailableInternal [%p]", this));
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aResponse);
|
||||
MOZ_ASSERT(!mActorDestroyed);
|
||||
|
||||
if (mIsDone && aResponse->Type() != ResponseType::Error) {
|
||||
FETCH_LOG(
|
||||
("FetchParent::OnResponseAvailableInternal [%p] "
|
||||
"Fetch has already aborted",
|
||||
this));
|
||||
return;
|
||||
}
|
||||
|
||||
// To monitor the stream status between processes, response's body can not be
|
||||
// serialized as RemoteLazyInputStream. Such that stream close can be
|
||||
// propagated to FetchDriver in the parent process.
|
||||
aResponse->SetSerializeAsLazy(false);
|
||||
|
||||
// CSP violation notification is asynchronous. Extending the FetchParent's
|
||||
// life cycle for the notificaiton.
|
||||
if (aResponse->Type() == ResponseType::Error &&
|
||||
aResponse->GetErrorCode() == NS_ERROR_CONTENT_BLOCKED &&
|
||||
mCSPEventListener) {
|
||||
FETCH_LOG(
|
||||
("FetchParent::OnResponseAvailableInternal [%p] "
|
||||
"NS_ERROR_CONTENT_BLOCKED",
|
||||
this));
|
||||
mExtendForCSPEventListener = true;
|
||||
}
|
||||
|
||||
Unused << SendOnResponseAvailableInternal(
|
||||
aResponse->ToParentToChildInternalResponse(WrapNotNull(Manager())));
|
||||
}
|
||||
|
||||
void FetchParent::OnResponseEnd(const ResponseEndArgs& aArgs) {
|
||||
FETCH_LOG(("FetchParent::OnResponseEnd [%p]", this));
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(!mActorDestroyed);
|
||||
|
||||
if (mIsDone && aArgs.endReason() != FetchDriverObserver::eAborted) {
|
||||
FETCH_LOG(
|
||||
("FetchParent::OnResponseEnd [%p] "
|
||||
"Fetch has already aborted",
|
||||
this));
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << SendOnResponseEnd(aArgs);
|
||||
}
|
||||
|
||||
void FetchParent::OnDataAvailable() {
|
||||
FETCH_LOG(("FetchParent::OnDataAvailable [%p]", this));
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(!mActorDestroyed);
|
||||
|
||||
Unused << SendOnDataAvailable();
|
||||
}
|
||||
|
||||
void FetchParent::OnFlushConsoleReport(
|
||||
nsTArray<net::ConsoleReportCollected>&& aReports) {
|
||||
const nsTArray<net::ConsoleReportCollected>& aReports) {
|
||||
FETCH_LOG(("FetchParent::OnFlushConsoleReport [%p]", this));
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(!mActorDestroyed);
|
||||
|
||||
Unused << SendOnFlushConsoleReport(std::move(aReports));
|
||||
Unused << SendOnFlushConsoleReport(aReports);
|
||||
}
|
||||
|
||||
void FetchParent::ActorDestroy(ActorDestroyReason aReason) {
|
||||
@ -209,7 +305,7 @@ void FetchParent::ActorDestroy(ActorDestroyReason aReason) {
|
||||
// Force to abort the existing fetch.
|
||||
// Actor can be destoried by shutdown when still fetching.
|
||||
RecvAbortFetchOp();
|
||||
mBackgroundEventTarget = nullptr;
|
||||
// mBackgroundEventTarget = nullptr;
|
||||
}
|
||||
|
||||
nsICSPEventListener* FetchParent::GetCSPEventListener() {
|
||||
|
@ -7,19 +7,23 @@
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/FetchService.h"
|
||||
#include "mozilla/dom/PFetchParent.h"
|
||||
#include "mozilla/dom/SafeRefPtr.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/net/NeckoChannelParams.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsID.h"
|
||||
#include "nsISerialEventTarget.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTHashMap.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class ClientInfo;
|
||||
class FetchServicePromises;
|
||||
class InternalRequest;
|
||||
class InternalResponse;
|
||||
class ServiceWorkerDescriptor;
|
||||
@ -38,7 +42,14 @@ class FetchParent final : public PFetchParent {
|
||||
|
||||
static RefPtr<FetchParent> GetActorByID(const nsID& aID);
|
||||
|
||||
void OnFlushConsoleReport(nsTArray<net::ConsoleReportCollected>&& aReports);
|
||||
void OnResponseAvailableInternal(SafeRefPtr<InternalResponse>&& aResponse);
|
||||
|
||||
void OnResponseEnd(const ResponseEndArgs& aArgs);
|
||||
|
||||
void OnDataAvailable();
|
||||
|
||||
void OnFlushConsoleReport(
|
||||
const nsTArray<net::ConsoleReportCollected>& aReports);
|
||||
|
||||
class FetchParentCSPEventListener final : public nsICSPEventListener {
|
||||
public:
|
||||
@ -76,9 +87,11 @@ class FetchParent final : public PFetchParent {
|
||||
nsCString mWorkerScript;
|
||||
Maybe<ClientInfo> mClientInfo;
|
||||
Maybe<ServiceWorkerDescriptor> mController;
|
||||
RefPtr<FetchParentCSPEventListener> mCSPEventListener;
|
||||
Maybe<CookieJarSettingsArgs> mCookieJarSettings;
|
||||
nsCOMPtr<nsICSPEventListener> mCSPEventListener;
|
||||
bool mNeedOnDataAvailable{false};
|
||||
bool mHasCSPEventListener{false};
|
||||
bool mExtendForCSPEventListener{false};
|
||||
|
||||
Atomic<bool> mIsDone{false};
|
||||
Atomic<bool> mActorDestroyed{false};
|
||||
|
@ -3,7 +3,9 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FetchLog.h"
|
||||
#include "FetchParent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsICookieJarSettings.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsILoadInfo.h"
|
||||
@ -16,14 +18,18 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/SchedulerGroup.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/dom/ClientInfo.h"
|
||||
#include "mozilla/dom/FetchService.h"
|
||||
#include "mozilla/dom/InternalRequest.h"
|
||||
#include "mozilla/dom/InternalResponse.h"
|
||||
#include "mozilla/dom/PerformanceStorage.h"
|
||||
#include "mozilla/dom/PerformanceTiming.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/net/CookieJarSettings.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
@ -33,8 +39,9 @@ mozilla::LazyLogModule gFetchLog("Fetch");
|
||||
|
||||
FetchServicePromises::FetchServicePromises()
|
||||
: mAvailablePromise(
|
||||
new FetchServiceResponseAvailablePromise::Private(__func__)),
|
||||
mEndPromise(new FetchServiceResponseEndPromise::Private(__func__)) {
|
||||
MakeRefPtr<FetchServiceResponseAvailablePromise::Private>(__func__)),
|
||||
mEndPromise(
|
||||
MakeRefPtr<FetchServiceResponseEndPromise::Private>(__func__)) {
|
||||
mAvailablePromise->UseSynchronousTaskDispatch(__func__);
|
||||
mEndPromise->UseSynchronousTaskDispatch(__func__);
|
||||
}
|
||||
@ -79,25 +86,26 @@ void FetchServicePromises::RejectResponseEndPromise(
|
||||
|
||||
// FetchInstance
|
||||
|
||||
FetchService::FetchInstance::FetchInstance(SafeRefPtr<InternalRequest> aRequest)
|
||||
: mRequest(std::move(aRequest)) {}
|
||||
|
||||
FetchService::FetchInstance::~FetchInstance() = default;
|
||||
|
||||
nsresult FetchService::FetchInstance::Initialize(nsIChannel* aChannel) {
|
||||
nsresult FetchService::FetchInstance::Initialize(FetchArgs&& aArgs) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aArgs.is<UnknownArgs>() && mArgs.is<UnknownArgs>());
|
||||
|
||||
mArgs = std::move(aArgs);
|
||||
|
||||
// Get needed information for FetchDriver from passed-in channel.
|
||||
if (aChannel) {
|
||||
FETCH_LOG(("FetchInstance::Initialize [%p] aChannel[%p]", this, aChannel));
|
||||
if (mArgs.is<NavigationPreloadArgs>()) {
|
||||
mRequest = mArgs.as<NavigationPreloadArgs>().mRequest.clonePtr();
|
||||
nsIChannel* channel = mArgs.as<NavigationPreloadArgs>().mChannel;
|
||||
FETCH_LOG(("FetchInstance::Initialize [%p] request[%p], channel[%p]", this,
|
||||
mRequest.unsafeGetRawPtr(), channel));
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
MOZ_ASSERT(loadInfo);
|
||||
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
rv = aChannel->GetURI(getter_AddRefs(channelURI));
|
||||
rv = channel->GetURI(getter_AddRefs(channelURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -105,7 +113,7 @@ nsresult FetchService::FetchInstance::Initialize(nsIChannel* aChannel) {
|
||||
nsIScriptSecurityManager* securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
if (securityManager) {
|
||||
securityManager->GetChannelResultPrincipal(aChannel,
|
||||
securityManager->GetChannelResultPrincipal(channel,
|
||||
getter_AddRefs(mPrincipal));
|
||||
}
|
||||
|
||||
@ -114,7 +122,7 @@ nsresult FetchService::FetchInstance::Initialize(nsIChannel* aChannel) {
|
||||
}
|
||||
|
||||
// Get loadGroup from channel
|
||||
rv = aChannel->GetLoadGroup(getter_AddRefs(mLoadGroup));
|
||||
rv = channel->GetLoadGroup(getter_AddRefs(mLoadGroup));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -134,10 +142,28 @@ nsresult FetchService::FetchInstance::Initialize(nsIChannel* aChannel) {
|
||||
// Get PerformanceStorage from channel
|
||||
mPerformanceStorage = loadInfo->GetPerformanceStorage();
|
||||
} else {
|
||||
// TODO:
|
||||
// Get information from InternalRequest and PFetch IPC parameters.
|
||||
// This will be implemented in bug 1351231.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
mIsWorkerFetch = true;
|
||||
mRequest = mArgs.as<WorkerFetchArgs>().mRequest.clonePtr();
|
||||
|
||||
FETCH_LOG(("FetchInstance::Initialize [%p] request[%p]", this,
|
||||
mRequest.unsafeGetRawPtr()));
|
||||
|
||||
auto principalOrErr =
|
||||
PrincipalInfoToPrincipal(mArgs.as<WorkerFetchArgs>().mPrincipalInfo);
|
||||
if (principalOrErr.isErr()) {
|
||||
return principalOrErr.unwrapErr();
|
||||
}
|
||||
mPrincipal = principalOrErr.unwrap();
|
||||
nsresult rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), mPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mArgs.as<WorkerFetchArgs>().mCookieJarSettings.isSome()) {
|
||||
net::CookieJarSettings::Deserialize(
|
||||
mArgs.as<WorkerFetchArgs>().mCookieJarSettings.ref(),
|
||||
getter_AddRefs(mCookieJarSettings));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -170,6 +196,21 @@ RefPtr<FetchServicePromises> FetchService::FetchInstance::Fetch() {
|
||||
false // IsTrackingFetch
|
||||
);
|
||||
|
||||
if (mIsWorkerFetch) {
|
||||
auto& args = mArgs.as<WorkerFetchArgs>();
|
||||
mFetchDriver->SetWorkerScript(args.mWorkerScript);
|
||||
MOZ_ASSERT(args.mClientInfo.isSome());
|
||||
mFetchDriver->SetClientInfo(args.mClientInfo.ref());
|
||||
mFetchDriver->SetController(args.mController);
|
||||
if (args.mCSPEventListener) {
|
||||
mFetchDriver->SetCSPEventListener(args.mCSPEventListener);
|
||||
}
|
||||
}
|
||||
|
||||
mFetchDriver->EnableNetworkInterceptControl();
|
||||
|
||||
mPromises = MakeRefPtr<FetchServicePromises>();
|
||||
|
||||
// Call FetchDriver::Fetch to start fetching.
|
||||
// Pass AbortSignalImpl as nullptr since we no need support AbortSignalImpl
|
||||
// with FetchService. AbortSignalImpl related information should be passed
|
||||
@ -182,8 +223,6 @@ RefPtr<FetchServicePromises> FetchService::FetchInstance::Fetch() {
|
||||
return FetchService::NetworkErrorResponse(rv);
|
||||
}
|
||||
|
||||
mPromises = MakeRefPtr<FetchServicePromises>();
|
||||
|
||||
return mPromises;
|
||||
}
|
||||
|
||||
@ -197,74 +236,157 @@ void FetchService::FetchInstance::Cancel() {
|
||||
mFetchDriver->RunAbortAlgorithm();
|
||||
}
|
||||
|
||||
if (mPromises) {
|
||||
mPromises->ResolveResponseAvailablePromise(
|
||||
InternalResponse::NetworkError(NS_ERROR_DOM_ABORT_ERR), __func__);
|
||||
MOZ_ASSERT(mPromises);
|
||||
|
||||
mPromises->ResolveResponseEndPromise(
|
||||
ResponseEndArgs(FetchDriverObserver::eAborted, Nothing()), __func__);
|
||||
mPromises = nullptr;
|
||||
}
|
||||
mPromises->ResolveResponseAvailablePromise(
|
||||
InternalResponse::NetworkError(NS_ERROR_DOM_ABORT_ERR), __func__);
|
||||
|
||||
mPromises->ResolveResponseEndPromise(
|
||||
ResponseEndArgs(FetchDriverObserver::eAborted, Nothing()), __func__);
|
||||
}
|
||||
|
||||
void FetchService::FetchInstance::OnResponseEnd(
|
||||
FetchDriverObserver::EndReason aReason,
|
||||
JS::Handle<JS::Value> aReasonDetails) {
|
||||
FETCH_LOG(("FetchInstance::OnResponseEnd [%p]", this));
|
||||
if (aReason == eAborted) {
|
||||
FETCH_LOG(("FetchInstance::OnResponseEnd end with eAborted"));
|
||||
if (mPromises) {
|
||||
mPromises->ResolveResponseEndPromise(
|
||||
ResponseEndArgs(FetchDriverObserver::eAborted, Nothing()), __func__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mPromises) {
|
||||
// Remove the FetchInstance from FetchInstanceTable
|
||||
RefPtr<FetchService> fetchService = FetchService::GetInstance();
|
||||
MOZ_ASSERT(fetchService);
|
||||
auto entry = fetchService->mFetchInstanceTable.Lookup(mPromises);
|
||||
MOZ_ASSERT(entry);
|
||||
entry.Remove();
|
||||
FETCH_LOG(
|
||||
("FetchInstance::OnResponseEnd entry[%p] of FetchInstance[%p] is "
|
||||
"removed",
|
||||
mPromises.get(), this));
|
||||
FETCH_LOG(("FetchInstance::OnResponseEnd [%p] %s", this,
|
||||
aReason == eAborted ? "eAborted" : "eNetworking"));
|
||||
|
||||
// Get PerformanceTimingData from FetchDriver.
|
||||
// Get response timing form FetchDriver
|
||||
Maybe<ResponseTiming> responseTiming;
|
||||
if (aReason != eAborted) {
|
||||
ResponseTiming timing;
|
||||
UniquePtr<PerformanceTimingData> performanceTiming(
|
||||
mFetchDriver->GetPerformanceTimingData(timing.initiatorType(),
|
||||
timing.entryName()));
|
||||
if (performanceTiming != nullptr) {
|
||||
timing.timingData() = performanceTiming->ToIPC();
|
||||
if (!mIsWorkerFetch) {
|
||||
// Force replace initiatorType for ServiceWorkerNavgationPreload.
|
||||
timing.initiatorType() = u"navigation"_ns;
|
||||
}
|
||||
responseTiming = Some(timing);
|
||||
}
|
||||
}
|
||||
|
||||
timing.initiatorType() = u"navigation"_ns;
|
||||
if (mIsWorkerFetch) {
|
||||
FlushConsoleReport();
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
__func__, [endArgs = ResponseEndArgs(aReason, responseTiming),
|
||||
actorID = mArgs.as<WorkerFetchArgs>().mActorID]() {
|
||||
FETCH_LOG(("FetchInstance::OnResponseEnd, Runnable"));
|
||||
RefPtr<FetchParent> actor = FetchParent::GetActorByID(actorID);
|
||||
if (actor) {
|
||||
actor->OnResponseEnd(std::move(endArgs));
|
||||
}
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(mArgs.as<WorkerFetchArgs>().mEventTarget->Dispatch(
|
||||
r, nsIThread::DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
// Resolve the ResponseEndPromise
|
||||
mPromises->ResolveResponseEndPromise(ResponseEndArgs(aReason, Some(timing)),
|
||||
__func__);
|
||||
// Release promises
|
||||
mPromises = nullptr;
|
||||
MOZ_ASSERT(mPromises);
|
||||
|
||||
// Resolve the ResponseEndPromise
|
||||
mPromises->ResolveResponseEndPromise(ResponseEndArgs(aReason, responseTiming),
|
||||
__func__);
|
||||
|
||||
if (aReason == eAborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the FetchInstance from FetchInstanceTable
|
||||
RefPtr<FetchService> fetchService = FetchService::GetInstance();
|
||||
MOZ_ASSERT(fetchService);
|
||||
auto entry = fetchService->mFetchInstanceTable.Lookup(mPromises);
|
||||
if (entry) {
|
||||
entry.Remove();
|
||||
FETCH_LOG(
|
||||
("FetchInstance::OnResponseEnd entry of responsePromise[%p] is "
|
||||
"removed",
|
||||
mPromises.get()));
|
||||
}
|
||||
}
|
||||
|
||||
void FetchService::FetchInstance::OnResponseAvailableInternal(
|
||||
SafeRefPtr<InternalResponse> aResponse) {
|
||||
FETCH_LOG(("FetchInstance::OnResponseAvailableInternal [%p]", this));
|
||||
if (mPromises) {
|
||||
// Resolve the ResponseAvailablePromise
|
||||
mPromises->ResolveResponseAvailablePromise(std::move(aResponse), __func__);
|
||||
mResponse = std::move(aResponse);
|
||||
|
||||
nsCOMPtr<nsIInputStream> body;
|
||||
mResponse->GetUnfilteredBody(getter_AddRefs(body));
|
||||
FETCH_LOG(
|
||||
("FetchInstance::OnResponseAvailableInternal [%p] response body: %p",
|
||||
this, body.get()));
|
||||
|
||||
if (mIsWorkerFetch) {
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
__func__, [response = mResponse.clonePtr(),
|
||||
actorID = mArgs.as<WorkerFetchArgs>().mActorID]() mutable {
|
||||
FETCH_LOG(("FetchInstance::OnResponseAvailableInternal Runnable"));
|
||||
RefPtr<FetchParent> actor = FetchParent::GetActorByID(actorID);
|
||||
if (actor) {
|
||||
actor->OnResponseAvailableInternal(std::move(response));
|
||||
}
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(mArgs.as<WorkerFetchArgs>().mEventTarget->Dispatch(
|
||||
r, nsIThread::DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPromises);
|
||||
|
||||
// Resolve the ResponseAvailablePromise
|
||||
mPromises->ResolveResponseAvailablePromise(mResponse.clonePtr(), __func__);
|
||||
}
|
||||
|
||||
bool FetchService::FetchInstance::NeedOnDataAvailable() {
|
||||
if (mArgs.is<WorkerFetchArgs>()) {
|
||||
return mArgs.as<WorkerFetchArgs>().mNeedOnDataAvailable;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FetchService::FetchInstance::OnDataAvailable() {
|
||||
FETCH_LOG(("FetchInstance::OnDataAvailable [%p]", this));
|
||||
|
||||
if (!NeedOnDataAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsWorkerFetch) {
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
__func__, [actorID = mArgs.as<WorkerFetchArgs>().mActorID]() {
|
||||
FETCH_LOG(("FetchInstance::OnDataAvailable, Runnable"));
|
||||
RefPtr<FetchParent> actor = FetchParent::GetActorByID(actorID);
|
||||
if (actor) {
|
||||
actor->OnDataAvailable();
|
||||
}
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(mArgs.as<WorkerFetchArgs>().mEventTarget->Dispatch(
|
||||
r, nsIThread::DISPATCH_NORMAL));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Following methods would not be used for navigation preload, but would be used
|
||||
// with PFetch. They will be implemented in bug 1351231.
|
||||
bool FetchService::FetchInstance::NeedOnDataAvailable() { return false; }
|
||||
void FetchService::FetchInstance::OnDataAvailable() {}
|
||||
void FetchService::FetchInstance::FlushConsoleReport() {}
|
||||
void FetchService::FetchInstance::FlushConsoleReport() {
|
||||
FETCH_LOG(("FetchInstance::FlushConsoleReport [%p]", this));
|
||||
|
||||
if (mIsWorkerFetch) {
|
||||
if (!mReporter) {
|
||||
return;
|
||||
}
|
||||
nsTArray<net::ConsoleReportCollected> reports;
|
||||
mReporter->StealConsoleReports(reports);
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||
__func__, [actorID = mArgs.as<WorkerFetchArgs>().mActorID,
|
||||
consoleReports = std::move(reports)]() {
|
||||
FETCH_LOG(("FetchInstance::FlushConsolReport, Runnable"));
|
||||
RefPtr<FetchParent> actor = FetchParent::GetActorByID(actorID);
|
||||
if (actor) {
|
||||
actor->OnFlushConsoleReport(std::move(consoleReports));
|
||||
}
|
||||
});
|
||||
MOZ_ALWAYS_SUCCEEDS(mArgs.as<WorkerFetchArgs>().mEventTarget->Dispatch(
|
||||
r, nsIThread::DISPATCH_NORMAL));
|
||||
}
|
||||
}
|
||||
|
||||
// FetchService
|
||||
|
||||
@ -382,31 +504,30 @@ NS_IMETHODIMP FetchService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<FetchServicePromises> FetchService::Fetch(
|
||||
SafeRefPtr<InternalRequest> aRequest, nsIChannel* aChannel) {
|
||||
RefPtr<FetchServicePromises> FetchService::Fetch(FetchArgs&& aArgs) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
FETCH_LOG(("FetchService::Fetch aRequest[%p], aChannel[%p], mOffline: %s",
|
||||
aRequest.unsafeGetRawPtr(), aChannel,
|
||||
mOffline ? "true" : "false"));
|
||||
|
||||
FETCH_LOG(("FetchService::Fetch (%s)", aArgs.is<NavigationPreloadArgs>()
|
||||
? "NavigationPreload"
|
||||
: "WorkerFetch"));
|
||||
if (mOffline) {
|
||||
FETCH_LOG(("FetchService::Fetch network offline"));
|
||||
return NetworkErrorResponse(NS_ERROR_OFFLINE);
|
||||
}
|
||||
|
||||
// Create FetchInstance
|
||||
RefPtr<FetchInstance> fetch = MakeRefPtr<FetchInstance>(aRequest.clonePtr());
|
||||
RefPtr<FetchInstance> fetch = MakeRefPtr<FetchInstance>();
|
||||
|
||||
// Call FetchInstance::Initialize() to get needed information for FetchDriver,
|
||||
nsresult rv = fetch->Initialize(aChannel);
|
||||
nsresult rv = fetch->Initialize(std::move(aArgs));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NetworkErrorResponse(rv);
|
||||
}
|
||||
|
||||
// Call FetchInstance::Fetch() to start an asynchronous fetching.
|
||||
RefPtr<FetchServicePromises> promises = fetch->Fetch();
|
||||
MOZ_ASSERT(promises);
|
||||
|
||||
if (!promises->GetResponseAvailablePromise()->IsResolved()) {
|
||||
// Insert the created FetchInstance into FetchInstanceTable.
|
||||
@ -427,7 +548,7 @@ RefPtr<FetchServicePromises> FetchService::Fetch(
|
||||
return promises;
|
||||
}
|
||||
|
||||
void FetchService::CancelFetch(RefPtr<FetchServicePromises>&& aPromises) {
|
||||
void FetchService::CancelFetch(const RefPtr<FetchServicePromises>&& aPromises) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aPromises);
|
||||
@ -438,7 +559,6 @@ void FetchService::CancelFetch(RefPtr<FetchServicePromises>&& aPromises) {
|
||||
// Notice any modifications here before entry.Remove() probably should be
|
||||
// reflected to Observe() offline case.
|
||||
entry.Data()->Cancel();
|
||||
|
||||
entry.Remove();
|
||||
FETCH_LOG(
|
||||
("FetchService::CancelFetch entry [%p] removed", aPromises.get()));
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "mozilla/dom/FetchTypes.h"
|
||||
#include "mozilla/dom/PerformanceTimingTypes.h"
|
||||
#include "mozilla/dom/SafeRefPtr.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/net/NeckoChannelParams.h"
|
||||
|
||||
class nsILoadGroup;
|
||||
class nsIPrincipal;
|
||||
@ -24,6 +26,8 @@ namespace mozilla::dom {
|
||||
|
||||
class InternalRequest;
|
||||
class InternalResponse;
|
||||
class ClientInfo;
|
||||
class ServiceWorkerDescriptor;
|
||||
|
||||
using FetchServiceResponse = SafeRefPtr<InternalResponse>;
|
||||
using FetchServiceResponseAvailablePromise =
|
||||
@ -69,8 +73,31 @@ class FetchServicePromises final {
|
||||
*/
|
||||
class FetchService final : public nsIObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS;
|
||||
NS_DECL_NSIOBSERVER;
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
struct NavigationPreloadArgs {
|
||||
SafeRefPtr<InternalRequest> mRequest;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
struct WorkerFetchArgs {
|
||||
SafeRefPtr<InternalRequest> mRequest;
|
||||
mozilla::ipc::PrincipalInfo mPrincipalInfo;
|
||||
nsCString mWorkerScript;
|
||||
Maybe<ClientInfo> mClientInfo;
|
||||
Maybe<ServiceWorkerDescriptor> mController;
|
||||
Maybe<net::CookieJarSettingsArgs> mCookieJarSettings;
|
||||
bool mNeedOnDataAvailable;
|
||||
nsCOMPtr<nsICSPEventListener> mCSPEventListener;
|
||||
nsCOMPtr<nsISerialEventTarget> mEventTarget;
|
||||
nsID mActorID;
|
||||
};
|
||||
|
||||
struct UnknownArgs {};
|
||||
|
||||
using FetchArgs =
|
||||
Variant<NavigationPreloadArgs, WorkerFetchArgs, UnknownArgs>;
|
||||
|
||||
static already_AddRefed<FetchService> GetInstance();
|
||||
|
||||
@ -80,10 +107,9 @@ class FetchService final : public nsIObserver {
|
||||
|
||||
// This method creates a FetchInstance to trigger fetch.
|
||||
// The created FetchInstance is saved in mFetchInstanceTable
|
||||
RefPtr<FetchServicePromises> Fetch(SafeRefPtr<InternalRequest> aRequest,
|
||||
nsIChannel* aChannel = nullptr);
|
||||
RefPtr<FetchServicePromises> Fetch(FetchArgs&& aArgs);
|
||||
|
||||
void CancelFetch(RefPtr<FetchServicePromises>&& aPromises);
|
||||
void CancelFetch(const RefPtr<FetchServicePromises>&& aPromises);
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -94,22 +120,15 @@ class FetchService final : public nsIObserver {
|
||||
* FetchInstance triggers fetch by instancing a FetchDriver with proper
|
||||
* initialization. The general usage flow of FetchInstance is as follows
|
||||
*
|
||||
* RefPtr<FetchInstance> fetch = MakeRefPtr<FetchInstance>(aResquest);
|
||||
* fetch->Initialize();
|
||||
* RefPtr<FetchInstance> fetch = MakeRefPtr<FetchInstance>();
|
||||
* fetch->Initialize(FetchArgs args);
|
||||
* RefPtr<FetchServicePromises> fetch->Fetch();
|
||||
*/
|
||||
class FetchInstance final : public FetchDriverObserver {
|
||||
public:
|
||||
explicit FetchInstance(SafeRefPtr<InternalRequest> aRequest);
|
||||
FetchInstance() = default;
|
||||
|
||||
// This method is used for initialize the fetch.
|
||||
// It accepts a nsIChannel for initialization, this is for the navigation
|
||||
// preload case since there has already been an intercepted channel for
|
||||
// dispatching fetch event, and needed information can be gotten from the
|
||||
// intercepted channel.
|
||||
// For other case, the fetch needed information be created according to the
|
||||
// mRequest
|
||||
nsresult Initialize(nsIChannel* aChannel = nullptr);
|
||||
nsresult Initialize(FetchArgs&& aArgs);
|
||||
|
||||
RefPtr<FetchServicePromises> Fetch();
|
||||
|
||||
@ -125,17 +144,18 @@ class FetchService final : public nsIObserver {
|
||||
void FlushConsoleReport() override;
|
||||
|
||||
private:
|
||||
~FetchInstance();
|
||||
~FetchInstance() = default;
|
||||
|
||||
SafeRefPtr<InternalRequest> mRequest;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
|
||||
RefPtr<PerformanceStorage> mPerformanceStorage;
|
||||
FetchArgs mArgs{AsVariant(FetchService::UnknownArgs())};
|
||||
RefPtr<FetchDriver> mFetchDriver;
|
||||
SafeRefPtr<InternalResponse> mResponse;
|
||||
|
||||
RefPtr<FetchServicePromises> mPromises;
|
||||
bool mIsWorkerFetch{false};
|
||||
};
|
||||
|
||||
~FetchService();
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mozilla/RemoteLazyInputStreamStorage.h"
|
||||
#include "mozilla/dom/FetchTypes.h"
|
||||
#include "mozilla/dom/IPCBlob.h"
|
||||
#include "mozilla/ipc/IPCStreamUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
@ -34,7 +35,12 @@ NotNull<nsCOMPtr<nsIInputStream>> ToInputStream(
|
||||
NotNull<nsCOMPtr<nsIInputStream>> ToInputStream(
|
||||
const ParentToChildStream& aStream) {
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
nsCOMPtr<nsIInputStream> result = aStream.stream();
|
||||
nsCOMPtr<nsIInputStream> result;
|
||||
if (aStream.type() == ParentToChildStream::TRemoteLazyInputStream) {
|
||||
result = aStream.get_RemoteLazyInputStream();
|
||||
} else {
|
||||
result = DeserializeIPCStream(aStream.get_IPCStream());
|
||||
}
|
||||
return WrapNotNull(result);
|
||||
}
|
||||
|
||||
@ -50,11 +56,20 @@ ParentToParentStream ToParentToParentStream(
|
||||
|
||||
ParentToChildStream ToParentToChildStream(
|
||||
const NotNull<nsCOMPtr<nsIInputStream>>& aStream, int64_t aStreamSize,
|
||||
NotNull<mozilla::ipc::PBackgroundParent*> aBackgroundParent) {
|
||||
NotNull<mozilla::ipc::PBackgroundParent*> aBackgroundParent,
|
||||
bool aSerializeAsLazy) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
ParentToChildStream result;
|
||||
result.stream() = RemoteLazyInputStream::WrapStream(aStream.get());
|
||||
if (aSerializeAsLazy) {
|
||||
result = RemoteLazyInputStream::WrapStream(aStream.get());
|
||||
} else {
|
||||
nsCOMPtr<nsIInputStream> stream(aStream.get());
|
||||
mozilla::ipc::IPCStream ipcStream;
|
||||
Unused << NS_WARN_IF(
|
||||
!mozilla::ipc::SerializeIPCStream(stream.forget(), ipcStream, false));
|
||||
result = ipcStream;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,8 @@ ParentToParentStream ToParentToParentStream(
|
||||
// process. Can only be called in the parent process.
|
||||
ParentToChildStream ToParentToChildStream(
|
||||
const NotNull<nsCOMPtr<nsIInputStream>>& aStream, int64_t aStreamSize,
|
||||
NotNull<mozilla::ipc::PBackgroundParent*> aBackgroundParent);
|
||||
NotNull<mozilla::ipc::PBackgroundParent*> aBackgroundParent,
|
||||
bool aSerializeAsLazy = true);
|
||||
|
||||
// Convert a ParentToParentStream to a ParentToChildStream. Can only be called
|
||||
// in the parent process.
|
||||
|
@ -35,8 +35,9 @@ struct ParentToParentStream {
|
||||
nsID uuid;
|
||||
};
|
||||
|
||||
struct ParentToChildStream {
|
||||
RemoteLazyInputStream stream;
|
||||
union ParentToChildStream {
|
||||
RemoteLazyInputStream;
|
||||
IPCStream;
|
||||
};
|
||||
|
||||
struct ChildToParentStream {
|
||||
@ -86,6 +87,9 @@ struct InternalResponseMetadata {
|
||||
nsCString alternativeDataType;
|
||||
nsITransportSecurityInfo securityInfo;
|
||||
PrincipalInfo? principalInfo;
|
||||
nsCString bodyBlobURISpec;
|
||||
nsString bodyLocalPath;
|
||||
RequestCredentials credentialsMode;
|
||||
};
|
||||
|
||||
struct ParentToParentInternalResponse {
|
||||
|
@ -193,7 +193,7 @@ InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
|
||||
if (!XRE_IsParentProcess()) {
|
||||
if (body) {
|
||||
MOZ_ASSERT(body->type() == BodyStreamVariant::TParentToChildStream);
|
||||
mBodyStream = body->get_ParentToChildStream().stream();
|
||||
mBodyStream = body->get_ParentToChildStream().get_RemoteLazyInputStream();
|
||||
}
|
||||
} else {
|
||||
if (body) {
|
||||
|
@ -90,6 +90,13 @@ template <typename T>
|
||||
aIPCResponse.metadata().principalInfo().ref()));
|
||||
}
|
||||
|
||||
nsAutoCString bodyBlobURISpec(aIPCResponse.metadata().bodyBlobURISpec());
|
||||
response->SetBodyBlobURISpec(bodyBlobURISpec);
|
||||
nsAutoString bodyLocalPath(aIPCResponse.metadata().bodyLocalPath());
|
||||
response->SetBodyLocalPath(bodyLocalPath);
|
||||
|
||||
response->mCredentialsMode = aIPCResponse.metadata().credentialsMode();
|
||||
|
||||
switch (aIPCResponse.metadata().type()) {
|
||||
case ResponseType::Basic:
|
||||
response = response->BasicResponse();
|
||||
@ -124,13 +131,17 @@ InternalResponseMetadata InternalResponse::GetMetadata() {
|
||||
Maybe<mozilla::ipc::PrincipalInfo> principalInfo =
|
||||
mPrincipalInfo ? Some(*mPrincipalInfo) : Nothing();
|
||||
|
||||
nsAutoCString bodyBlobURISpec(BodyBlobURISpec());
|
||||
nsAutoString bodyLocalPath(BodyLocalPath());
|
||||
|
||||
// Note: all the arguments are copied rather than moved, which would be more
|
||||
// efficient, because there's no move-friendly constructor generated.
|
||||
nsCOMPtr<nsITransportSecurityInfo> securityInfo(mChannelInfo.SecurityInfo());
|
||||
return InternalResponseMetadata(
|
||||
mType, GetUnfilteredURLList(), GetUnfilteredStatus(),
|
||||
GetUnfilteredStatusText(), headersGuard, headers, mErrorCode,
|
||||
GetAlternativeDataType(), securityInfo, principalInfo);
|
||||
GetAlternativeDataType(), securityInfo, principalInfo, bodyBlobURISpec,
|
||||
bodyLocalPath, GetCredentialsMode());
|
||||
}
|
||||
|
||||
void InternalResponse::ToChildToParentInternalResponse(
|
||||
@ -196,15 +207,16 @@ ParentToChildInternalResponse InternalResponse::ToParentToChildInternalResponse(
|
||||
GetUnfilteredBody(getter_AddRefs(body), &bodySize);
|
||||
|
||||
if (body) {
|
||||
result.body() = Some(
|
||||
ToParentToChildStream(WrapNotNull(body), bodySize, aBackgroundParent));
|
||||
result.body() = Some(ToParentToChildStream(
|
||||
WrapNotNull(body), bodySize, aBackgroundParent, mSerializeAsLazy));
|
||||
result.bodySize() = bodySize;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> alternativeBody = TakeAlternativeBody();
|
||||
if (alternativeBody) {
|
||||
result.alternativeBody() = Some(ToParentToChildStream(
|
||||
WrapNotNull(alternativeBody), UNKNOWN_BODY_SIZE, aBackgroundParent));
|
||||
result.alternativeBody() = Some(
|
||||
ToParentToChildStream(WrapNotNull(alternativeBody), UNKNOWN_BODY_SIZE,
|
||||
aBackgroundParent, mSerializeAsLazy));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -311,6 +311,9 @@ class InternalResponse final : public AtomicSafeRefCounted<InternalResponse> {
|
||||
|
||||
bool HasBeenCloned() const { return mCloned; }
|
||||
|
||||
void SetSerializeAsLazy(bool aAllow) { mSerializeAsLazy = aAllow; }
|
||||
bool CanSerializeAsLazy() const { return mSerializeAsLazy; }
|
||||
|
||||
void InitChannelInfo(nsIChannel* aChannel) {
|
||||
mChannelInfo.InitFromChannel(aChannel);
|
||||
}
|
||||
@ -342,6 +345,13 @@ class InternalResponse final : public AtomicSafeRefCounted<InternalResponse> {
|
||||
|
||||
InternalResponseMetadata GetMetadata();
|
||||
|
||||
RequestCredentials GetCredentialsMode() const {
|
||||
if (mWrappedResponse) {
|
||||
return mWrappedResponse->GetCredentialsMode();
|
||||
}
|
||||
return mCredentialsMode;
|
||||
}
|
||||
|
||||
~InternalResponse();
|
||||
|
||||
private:
|
||||
@ -380,6 +390,7 @@ class InternalResponse final : public AtomicSafeRefCounted<InternalResponse> {
|
||||
nsCOMPtr<nsIInputStream> mAlternativeBody;
|
||||
nsMainThreadPtrHandle<nsICacheInfoChannel> mCacheInfoChannel;
|
||||
bool mCloned;
|
||||
bool mSerializeAsLazy{true};
|
||||
|
||||
public:
|
||||
static constexpr int64_t UNKNOWN_BODY_SIZE = -1;
|
||||
|
@ -160,7 +160,7 @@ ParentToParentFetchEventRespondWithResult ToParentToParent(
|
||||
RemoteLazyInputStream::WrapStream(aBodyStream);
|
||||
MOZ_DIAGNOSTIC_ASSERT(stream);
|
||||
|
||||
copyRequest.body().ref().get_ParentToChildStream().stream() = stream;
|
||||
copyRequest.body().ref().get_ParentToChildStream() = stream;
|
||||
}
|
||||
|
||||
Unused << aManager->SendPFetchEventOpProxyConstructor(actor, copyArgs);
|
||||
|
@ -1566,7 +1566,8 @@ RefPtr<FetchServicePromises> ServiceWorkerPrivate::SetupNavigationPreload(
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
aChannel->GetChannel(getter_AddRefs(underlyingChannel)));
|
||||
RefPtr<FetchService> fetchService = FetchService::GetInstance();
|
||||
return fetchService->Fetch(std::move(preloadRequest), underlyingChannel);
|
||||
return fetchService->Fetch(AsVariant(FetchService::NavigationPreloadArgs{
|
||||
std::move(preloadRequest), underlyingChannel}));
|
||||
}
|
||||
return FetchService::NetworkErrorResponse(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user