1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "DocumentChannelParent.h"
10 #include "mozilla/dom/BrowserParent.h"
11 #include "mozilla/dom/CanonicalBrowsingContext.h"
12 #include "mozilla/dom/ClientInfo.h"
13 #include "mozilla/dom/ContentParent.h"
14 #include "mozilla/net/NeckoChannelParams.h"
15 #include "nsDocShellLoadState.h"
17 extern mozilla::LazyLogModule gDocumentChannelLog
;
18 #define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
20 using namespace mozilla::dom
;
25 DocumentChannelParent::DocumentChannelParent() {
26 LOG(("DocumentChannelParent ctor [this=%p]", this));
29 DocumentChannelParent::~DocumentChannelParent() {
30 LOG(("DocumentChannelParent dtor [this=%p]", this));
33 bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext
* aContext
,
34 const DocumentChannelCreationArgs
& aArgs
) {
35 RefPtr
<nsDocShellLoadState
> loadState
= aArgs
.loadState();
36 LOG(("DocumentChannelParent Init [this=%p, uri=%s]", this,
37 loadState
->URI()->GetSpecOrDefault().get()));
38 if (aArgs
.parentInitiatedNavigationEpoch() <
39 aContext
->GetParentInitiatedNavigationEpoch()) {
40 nsresult rv
= NS_BINDING_ABORTED
;
41 return SendFailedAsyncOpen(rv
);
44 ContentParent
* contentParent
=
45 static_cast<ContentParent
*>(Manager()->Manager());
47 RefPtr
<DocumentLoadListener::OpenPromise
> promise
;
48 if (loadState
->GetChannelInitialized()) {
49 promise
= DocumentLoadListener::ClaimParentLoad(
50 getter_AddRefs(mDocumentLoadListener
), loadState
->GetLoadIdentifier(),
51 Some(aArgs
.channelId()));
55 aArgs
.elementCreationArgs().type() ==
56 DocumentChannelElementCreationArgs::TDocumentCreationArgs
;
57 mDocumentLoadListener
= new DocumentLoadListener(aContext
, isDocumentLoad
);
59 Maybe
<ClientInfo
> clientInfo
;
60 if (aArgs
.initialClientInfo().isSome()) {
61 clientInfo
.emplace(ClientInfo(aArgs
.initialClientInfo().ref()));
64 nsresult rv
= NS_ERROR_UNEXPECTED
;
67 const DocumentCreationArgs
& docArgs
= aArgs
.elementCreationArgs();
69 promise
= mDocumentLoadListener
->OpenDocument(
70 loadState
, aArgs
.cacheKey(), Some(aArgs
.channelId()),
71 aArgs
.asyncOpenTime(), aArgs
.timing(), std::move(clientInfo
),
72 docArgs
.uriModified(), Some(docArgs
.isEmbeddingBlockedError()),
75 const ObjectCreationArgs
& objectArgs
= aArgs
.elementCreationArgs();
77 promise
= mDocumentLoadListener
->OpenObject(
78 loadState
, aArgs
.cacheKey(), Some(aArgs
.channelId()),
79 aArgs
.asyncOpenTime(), aArgs
.timing(), std::move(clientInfo
),
80 objectArgs
.embedderInnerWindowId(), objectArgs
.loadFlags(),
81 objectArgs
.contentPolicyType(), objectArgs
.isUrgentStart(),
82 contentParent
, this /* ObjectUpgradeHandler */, &rv
);
87 return SendFailedAsyncOpen(rv
);
91 RefPtr
<DocumentChannelParent
> self
= this;
93 GetCurrentSerialEventTarget(), __func__
,
94 [self
](DocumentLoadListener::OpenPromiseSucceededType
&& aResolveValue
) {
95 // The DLL is waiting for us to resolve the
96 // PDocumentChannel::RedirectToRealChannelPromise given as parameter.
97 auto promise
= self
->RedirectToRealChannel(
98 std::move(aResolveValue
.mStreamFilterEndpoints
),
99 aResolveValue
.mRedirectFlags
, aResolveValue
.mLoadFlags
,
100 aResolveValue
.mEarlyHintLinkType
);
101 // We chain the promise the DLL is waiting on to the one returned by
102 // RedirectToRealChannel. As soon as the promise returned is resolved
103 // or rejected, so will the DLL's promise.
104 promise
->ChainTo(aResolveValue
.mPromise
.forget(), __func__
);
105 self
->mDocumentLoadListener
= nullptr;
107 [self
](DocumentLoadListener::OpenPromiseFailedType
&& aRejectValue
) {
108 if (self
->CanSend()) {
109 Unused
<< self
->SendDisconnectChildListeners(
110 aRejectValue
.mStatus
, aRejectValue
.mLoadGroupStatus
,
111 aRejectValue
.mContinueNavigating
);
113 self
->mDocumentLoadListener
= nullptr;
119 auto DocumentChannelParent::UpgradeObjectLoad()
120 -> RefPtr
<ObjectUpgradePromise
> {
121 return SendUpgradeObjectLoad()->Then(
122 GetCurrentSerialEventTarget(), __func__
,
123 [](const UpgradeObjectLoadPromise::ResolveOrRejectValue
& aValue
) {
124 if (!aValue
.IsResolve() || aValue
.ResolveValue().IsNullOrDiscarded()) {
125 LOG(("DocumentChannelParent object load upgrade failed"));
126 return ObjectUpgradePromise::CreateAndReject(NS_ERROR_FAILURE
,
130 return ObjectUpgradePromise::CreateAndResolve(
131 aValue
.ResolveValue().get_canonical(), __func__
);
135 RefPtr
<PDocumentChannelParent::RedirectToRealChannelPromise
>
136 DocumentChannelParent::RedirectToRealChannel(
137 nsTArray
<ipc::Endpoint
<extensions::PStreamFilterParent
>>&&
138 aStreamFilterEndpoints
,
139 uint32_t aRedirectFlags
, uint32_t aLoadFlags
, uint32_t aEarlyHintLinkType
) {
141 return PDocumentChannelParent::RedirectToRealChannelPromise::
142 CreateAndReject(ResponseRejectReason::ChannelClosed
, __func__
);
145 ContentParent
* cp
= static_cast<ContentParent
*>(Manager()->Manager());
146 nsTArray
<EarlyHintConnectArgs
> earlyHints
;
147 mDocumentLoadListener
->RegisterEarlyHintLinksAndGetConnectArgs(cp
->ChildID(),
150 RedirectToRealChannelArgs args
;
151 mDocumentLoadListener
->SerializeRedirectData(
152 args
, false, aRedirectFlags
, aLoadFlags
, std::move(earlyHints
),
154 return SendRedirectToRealChannel(args
, std::move(aStreamFilterEndpoints
));
158 } // namespace mozilla