Backed out changeset 06f41c22f3a6 (bug 1888460) for causing linux xpcshell failures...
[gecko.git] / dom / serviceworkers / FetchEventOpProxyParent.cpp
bloba8c4488a26837857a7d57d8b5b9bc0c4eff02dd8
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "FetchEventOpProxyParent.h"
9 #include <utility>
11 #include "mozilla/dom/FetchTypes.h"
12 #include "mozilla/dom/ServiceWorkerOpArgs.h"
13 #include "nsCOMPtr.h"
14 #include "nsIInputStream.h"
16 #include "mozilla/Assertions.h"
17 #include "mozilla/DebugOnly.h"
18 #include "mozilla/ResultExtensions.h"
19 #include "mozilla/Try.h"
20 #include "mozilla/UniquePtr.h"
21 #include "mozilla/Unused.h"
22 #include "mozilla/dom/InternalResponse.h"
23 #include "mozilla/dom/PRemoteWorkerParent.h"
24 #include "mozilla/dom/PRemoteWorkerControllerParent.h"
25 #include "mozilla/dom/FetchEventOpParent.h"
26 #include "mozilla/ipc/BackgroundParent.h"
27 #include "mozilla/ipc/IPCStreamUtils.h"
28 #include "mozilla/RemoteLazyInputStreamStorage.h"
30 namespace mozilla {
32 using namespace ipc;
34 namespace dom {
36 namespace {
38 nsresult MaybeDeserializeAndWrapForMainThread(
39 const Maybe<ChildToParentStream>& aSource, int64_t aBodyStreamSize,
40 Maybe<ParentToParentStream>& aSink, PBackgroundParent* aManager) {
41 if (aSource.isNothing()) {
42 return NS_OK;
45 nsCOMPtr<nsIInputStream> deserialized =
46 DeserializeIPCStream(aSource->stream());
48 aSink = Some(ParentToParentStream());
49 auto& uuid = aSink->uuid();
51 MOZ_TRY(nsID::GenerateUUIDInPlace(uuid));
53 auto storageOrErr = RemoteLazyInputStreamStorage::Get();
55 if (NS_WARN_IF(storageOrErr.isErr())) {
56 return storageOrErr.unwrapErr();
59 auto storage = storageOrErr.unwrap();
60 storage->AddStream(deserialized, uuid);
61 return NS_OK;
64 ParentToParentInternalResponse ToParentToParent(
65 const ChildToParentInternalResponse& aResponse,
66 NotNull<PBackgroundParent*> aBackgroundParent) {
67 ParentToParentInternalResponse parentToParentResponse(
68 aResponse.metadata(), Nothing(), aResponse.bodySize(), Nothing());
70 MOZ_ALWAYS_SUCCEEDS(MaybeDeserializeAndWrapForMainThread(
71 aResponse.body(), aResponse.bodySize(), parentToParentResponse.body(),
72 aBackgroundParent));
73 MOZ_ALWAYS_SUCCEEDS(MaybeDeserializeAndWrapForMainThread(
74 aResponse.alternativeBody(), InternalResponse::UNKNOWN_BODY_SIZE,
75 parentToParentResponse.alternativeBody(), aBackgroundParent));
77 return parentToParentResponse;
80 ParentToParentSynthesizeResponseArgs ToParentToParent(
81 const ChildToParentSynthesizeResponseArgs& aArgs,
82 NotNull<PBackgroundParent*> aBackgroundParent) {
83 return ParentToParentSynthesizeResponseArgs(
84 ToParentToParent(aArgs.internalResponse(), aBackgroundParent),
85 aArgs.closure(), aArgs.timeStamps());
88 ParentToParentFetchEventRespondWithResult ToParentToParent(
89 const ChildToParentFetchEventRespondWithResult& aResult,
90 NotNull<PBackgroundParent*> aBackgroundParent) {
91 switch (aResult.type()) {
92 case ChildToParentFetchEventRespondWithResult::
93 TChildToParentSynthesizeResponseArgs:
94 return ToParentToParent(aResult.get_ChildToParentSynthesizeResponseArgs(),
95 aBackgroundParent);
97 case ChildToParentFetchEventRespondWithResult::TResetInterceptionArgs:
98 return aResult.get_ResetInterceptionArgs();
100 case ChildToParentFetchEventRespondWithResult::TCancelInterceptionArgs:
101 return aResult.get_CancelInterceptionArgs();
103 default:
104 MOZ_CRASH("Invalid ParentToParentFetchEventRespondWithResult");
108 } // anonymous namespace
110 /* static */ void FetchEventOpProxyParent::Create(
111 PRemoteWorkerParent* aManager,
112 RefPtr<ServiceWorkerFetchEventOpPromise::Private>&& aPromise,
113 const ParentToParentServiceWorkerFetchEventOpArgs& aArgs,
114 RefPtr<FetchEventOpParent> aReal, nsCOMPtr<nsIInputStream> aBodyStream) {
115 AssertIsInMainProcess();
116 AssertIsOnBackgroundThread();
117 MOZ_ASSERT(aManager);
118 MOZ_ASSERT(aReal);
120 ParentToChildServiceWorkerFetchEventOpArgs copyArgs(aArgs.common(), Nothing(),
121 Nothing(), Nothing());
122 if (aArgs.preloadResponse().isSome()) {
123 // Convert the preload response to ParentToChildInternalResponse.
124 copyArgs.preloadResponse() = Some(ToParentToChild(
125 aArgs.preloadResponse().ref(), WrapNotNull(aManager->Manager())));
128 if (aArgs.preloadResponseTiming().isSome()) {
129 copyArgs.preloadResponseTiming() = aArgs.preloadResponseTiming();
132 if (aArgs.preloadResponseEndArgs().isSome()) {
133 copyArgs.preloadResponseEndArgs() = aArgs.preloadResponseEndArgs();
136 RefPtr<FetchEventOpProxyParent> actor =
137 new FetchEventOpProxyParent(std::move(aReal), std::move(aPromise));
139 // As long as the fetch event was pending, the FetchEventOpParent was
140 // responsible for keeping the preload response, if it already arrived. Once
141 // the fetch event starts it gives up the preload response (if any) and we
142 // need to add it to the arguments. Note that we have to make sure that the
143 // arguments don't contain the preload response already, otherwise we'll end
144 // up overwriting it with a Nothing.
145 auto [preloadResponse, preloadResponseEndArgs] =
146 actor->mReal->OnStart(WrapNotNull(actor));
147 if (copyArgs.preloadResponse().isNothing() && preloadResponse.isSome()) {
148 copyArgs.preloadResponse() = Some(ToParentToChild(
149 preloadResponse.ref(), WrapNotNull(aManager->Manager())));
151 if (copyArgs.preloadResponseEndArgs().isNothing() &&
152 preloadResponseEndArgs.isSome()) {
153 copyArgs.preloadResponseEndArgs() = preloadResponseEndArgs;
156 IPCInternalRequest& copyRequest = copyArgs.common().internalRequest();
158 if (aBodyStream) {
159 copyRequest.body() = Some(ParentToChildStream());
161 RefPtr<RemoteLazyInputStream> stream =
162 RemoteLazyInputStream::WrapStream(aBodyStream);
163 MOZ_DIAGNOSTIC_ASSERT(stream);
165 copyRequest.body().ref().get_ParentToChildStream() = stream;
168 Unused << aManager->SendPFetchEventOpProxyConstructor(actor, copyArgs);
171 FetchEventOpProxyParent::~FetchEventOpProxyParent() {
172 AssertIsOnBackgroundThread();
175 FetchEventOpProxyParent::FetchEventOpProxyParent(
176 RefPtr<FetchEventOpParent>&& aReal,
177 RefPtr<ServiceWorkerFetchEventOpPromise::Private>&& aPromise)
178 : mReal(std::move(aReal)), mLifetimePromise(std::move(aPromise)) {}
180 mozilla::ipc::IPCResult FetchEventOpProxyParent::RecvAsyncLog(
181 const nsCString& aScriptSpec, const uint32_t& aLineNumber,
182 const uint32_t& aColumnNumber, const nsCString& aMessageName,
183 nsTArray<nsString>&& aParams) {
184 AssertIsOnBackgroundThread();
185 MOZ_ASSERT(mReal);
187 Unused << mReal->SendAsyncLog(aScriptSpec, aLineNumber, aColumnNumber,
188 aMessageName, aParams);
190 return IPC_OK();
193 mozilla::ipc::IPCResult FetchEventOpProxyParent::RecvRespondWith(
194 const ChildToParentFetchEventRespondWithResult& aResult) {
195 AssertIsOnBackgroundThread();
196 MOZ_ASSERT(mReal);
198 auto manager = WrapNotNull(mReal->Manager());
199 auto backgroundParent = WrapNotNull(manager->Manager());
200 Unused << mReal->SendRespondWith(ToParentToParent(aResult, backgroundParent));
201 return IPC_OK();
204 mozilla::ipc::IPCResult FetchEventOpProxyParent::Recv__delete__(
205 const ServiceWorkerFetchEventOpResult& aResult) {
206 AssertIsOnBackgroundThread();
207 MOZ_ASSERT(mLifetimePromise);
208 MOZ_ASSERT(mReal);
209 mReal->OnFinish();
210 if (mLifetimePromise) {
211 mLifetimePromise->Resolve(aResult, __func__);
212 mLifetimePromise = nullptr;
213 mReal = nullptr;
216 return IPC_OK();
219 void FetchEventOpProxyParent::ActorDestroy(ActorDestroyReason) {
220 AssertIsOnBackgroundThread();
221 if (mLifetimePromise) {
222 mLifetimePromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
223 mLifetimePromise = nullptr;
224 mReal = nullptr;
228 } // namespace dom
229 } // namespace mozilla