DocumentChannelParent.cpp (6269B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set sw=2 ts=8 et tw=80 : */ 3 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/. */ 7 8 #include "DocumentChannelParent.h" 9 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" 16 17 extern mozilla::LazyLogModule gDocumentChannelLog; 18 #define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt) 19 20 using namespace mozilla::dom; 21 22 namespace mozilla { 23 namespace net { 24 25 DocumentChannelParent::DocumentChannelParent() { 26 LOG(("DocumentChannelParent ctor [this=%p]", this)); 27 } 28 29 DocumentChannelParent::~DocumentChannelParent() { 30 LOG(("DocumentChannelParent dtor [this=%p]", this)); 31 } 32 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); 42 } 43 44 ContentParent* contentParent = 45 static_cast<ContentParent*>(Manager()->Manager()); 46 47 RefPtr<DocumentLoadListener::OpenPromise> promise; 48 if (loadState->GetChannelInitialized()) { 49 promise = DocumentLoadListener::ClaimParentLoad( 50 getter_AddRefs(mDocumentLoadListener), loadState->GetLoadIdentifier(), 51 Some(aArgs.channelId())); 52 } 53 if (!promise) { 54 bool isDocumentLoad = 55 aArgs.elementCreationArgs().type() == 56 DocumentChannelElementCreationArgs::TDocumentCreationArgs; 57 mDocumentLoadListener = new DocumentLoadListener(aContext, isDocumentLoad); 58 59 Maybe<ClientInfo> clientInfo; 60 if (aArgs.initialClientInfo().isSome()) { 61 clientInfo.emplace(ClientInfo(aArgs.initialClientInfo().ref())); 62 } 63 64 nsresult rv = NS_ERROR_UNEXPECTED; 65 66 if (isDocumentLoad) { 67 const DocumentCreationArgs& docArgs = aArgs.elementCreationArgs(); 68 69 promise = mDocumentLoadListener->OpenDocument( 70 loadState, docArgs.loadFlags(), aArgs.cacheKey(), 71 Some(aArgs.channelId()), aArgs.asyncOpenTime(), aArgs.timing(), 72 std::move(clientInfo), docArgs.uriModified(), 73 Some(docArgs.isEmbeddingBlockedError()), contentParent, &rv); 74 } else { 75 const ObjectCreationArgs& objectArgs = aArgs.elementCreationArgs(); 76 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); 83 } 84 85 if (NS_FAILED(rv)) { 86 MOZ_ASSERT(!promise); 87 return SendFailedAsyncOpen(rv); 88 } 89 } 90 91 RefPtr<DocumentChannelParent> self = this; 92 promise->Then( 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; 106 }, 107 [self](DocumentLoadListener::OpenPromiseFailedType&& aRejectValue) { 108 if (self->CanSend()) { 109 (void)self->SendDisconnectChildListeners( 110 aRejectValue.mStatus, aRejectValue.mLoadGroupStatus, 111 aRejectValue.mContinueNavigating); 112 } 113 self->mDocumentLoadListener = nullptr; 114 }); 115 116 return true; 117 } 118 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, 127 __func__); 128 } 129 130 return ObjectUpgradePromise::CreateAndResolve( 131 aValue.ResolveValue().get_canonical(), __func__); 132 }); 133 } 134 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) { 140 if (!CanSend()) { 141 return PDocumentChannelParent::RedirectToRealChannelPromise:: 142 CreateAndReject(ResponseRejectReason::ChannelClosed, __func__); 143 } 144 145 ContentParent* cp = static_cast<ContentParent*>(Manager()->Manager()); 146 nsTArray<EarlyHintConnectArgs> earlyHints; 147 mDocumentLoadListener->RegisterEarlyHintLinksAndGetConnectArgs(cp->ChildID(), 148 earlyHints); 149 150 RedirectToRealChannelArgs args; 151 mDocumentLoadListener->SerializeRedirectData( 152 args, false, aRedirectFlags, aLoadFlags, std::move(earlyHints), 153 aEarlyHintLinkType); 154 return SendRedirectToRealChannel(args, std::move(aStreamFilterEndpoints)); 155 } 156 157 } // namespace net 158 } // namespace mozilla 159 160 #undef LOG