summaryrefslogtreecommitdiffstats
path: root/netwerk/ipc/DocumentChannelParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/ipc/DocumentChannelParent.cpp')
-rw-r--r--netwerk/ipc/DocumentChannelParent.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/netwerk/ipc/DocumentChannelParent.cpp b/netwerk/ipc/DocumentChannelParent.cpp
new file mode 100644
index 0000000000..302c1ed54c
--- /dev/null
+++ b/netwerk/ipc/DocumentChannelParent.cpp
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et 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/. */
+
+#include "DocumentChannelParent.h"
+
+#include "mozilla/dom/BrowserParent.h"
+#include "mozilla/dom/CanonicalBrowsingContext.h"
+#include "mozilla/dom/ClientInfo.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/net/NeckoChannelParams.h"
+#include "nsDocShellLoadState.h"
+
+extern mozilla::LazyLogModule gDocumentChannelLog;
+#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
+
+using namespace mozilla::dom;
+
+namespace mozilla {
+namespace net {
+
+DocumentChannelParent::DocumentChannelParent() {
+ LOG(("DocumentChannelParent ctor [this=%p]", this));
+}
+
+DocumentChannelParent::~DocumentChannelParent() {
+ LOG(("DocumentChannelParent dtor [this=%p]", this));
+}
+
+bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext* aContext,
+ const DocumentChannelCreationArgs& aArgs) {
+ RefPtr<nsDocShellLoadState> loadState = aArgs.loadState();
+ LOG(("DocumentChannelParent Init [this=%p, uri=%s]", this,
+ loadState->URI()->GetSpecOrDefault().get()));
+ if (aArgs.parentInitiatedNavigationEpoch() <
+ aContext->GetParentInitiatedNavigationEpoch()) {
+ nsresult rv = NS_BINDING_ABORTED;
+ return SendFailedAsyncOpen(rv);
+ }
+
+ ContentParent* contentParent =
+ static_cast<ContentParent*>(Manager()->Manager());
+
+ RefPtr<DocumentLoadListener::OpenPromise> promise;
+ if (loadState->GetChannelInitialized()) {
+ promise = DocumentLoadListener::ClaimParentLoad(
+ getter_AddRefs(mDocumentLoadListener), loadState->GetLoadIdentifier(),
+ Some(aArgs.channelId()));
+ }
+ if (!promise) {
+ bool isDocumentLoad =
+ aArgs.elementCreationArgs().type() ==
+ DocumentChannelElementCreationArgs::TDocumentCreationArgs;
+ mDocumentLoadListener = new DocumentLoadListener(aContext, isDocumentLoad);
+
+ Maybe<ClientInfo> clientInfo;
+ if (aArgs.initialClientInfo().isSome()) {
+ clientInfo.emplace(ClientInfo(aArgs.initialClientInfo().ref()));
+ }
+
+ nsresult rv = NS_ERROR_UNEXPECTED;
+
+ if (isDocumentLoad) {
+ const DocumentCreationArgs& docArgs = aArgs.elementCreationArgs();
+
+ promise = mDocumentLoadListener->OpenDocument(
+ loadState, aArgs.cacheKey(), Some(aArgs.channelId()),
+ aArgs.asyncOpenTime(), aArgs.timing(), std::move(clientInfo),
+ Some(docArgs.uriModified()), Some(docArgs.isXFOError()),
+ contentParent, &rv);
+ } else {
+ const ObjectCreationArgs& objectArgs = aArgs.elementCreationArgs();
+
+ promise = mDocumentLoadListener->OpenObject(
+ loadState, aArgs.cacheKey(), Some(aArgs.channelId()),
+ aArgs.asyncOpenTime(), aArgs.timing(), std::move(clientInfo),
+ objectArgs.embedderInnerWindowId(), objectArgs.loadFlags(),
+ objectArgs.contentPolicyType(), objectArgs.isUrgentStart(),
+ contentParent, this /* ObjectUpgradeHandler */, &rv);
+ }
+
+ if (NS_FAILED(rv)) {
+ MOZ_ASSERT(!promise);
+ return SendFailedAsyncOpen(rv);
+ }
+ }
+
+ RefPtr<DocumentChannelParent> self = this;
+ promise->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [self](DocumentLoadListener::OpenPromiseSucceededType&& aResolveValue) {
+ // The DLL is waiting for us to resolve the
+ // PDocumentChannel::RedirectToRealChannelPromise given as parameter.
+ auto promise = self->RedirectToRealChannel(
+ std::move(aResolveValue.mStreamFilterEndpoints),
+ aResolveValue.mRedirectFlags, aResolveValue.mLoadFlags,
+ aResolveValue.mEarlyHintLinkType);
+ // We chain the promise the DLL is waiting on to the one returned by
+ // RedirectToRealChannel. As soon as the promise returned is resolved
+ // or rejected, so will the DLL's promise.
+ promise->ChainTo(aResolveValue.mPromise.forget(), __func__);
+ self->mDocumentLoadListener = nullptr;
+ },
+ [self](DocumentLoadListener::OpenPromiseFailedType&& aRejectValue) {
+ if (self->CanSend()) {
+ Unused << self->SendDisconnectChildListeners(
+ aRejectValue.mStatus, aRejectValue.mLoadGroupStatus,
+ aRejectValue.mContinueNavigating);
+ }
+ self->mDocumentLoadListener = nullptr;
+ });
+
+ return true;
+}
+
+auto DocumentChannelParent::UpgradeObjectLoad()
+ -> RefPtr<ObjectUpgradePromise> {
+ return SendUpgradeObjectLoad()->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [](const UpgradeObjectLoadPromise::ResolveOrRejectValue& aValue) {
+ if (!aValue.IsResolve() || aValue.ResolveValue().IsNullOrDiscarded()) {
+ LOG(("DocumentChannelParent object load upgrade failed"));
+ return ObjectUpgradePromise::CreateAndReject(NS_ERROR_FAILURE,
+ __func__);
+ }
+
+ return ObjectUpgradePromise::CreateAndResolve(
+ aValue.ResolveValue().get_canonical(), __func__);
+ });
+}
+
+RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise>
+DocumentChannelParent::RedirectToRealChannel(
+ nsTArray<ipc::Endpoint<extensions::PStreamFilterParent>>&&
+ aStreamFilterEndpoints,
+ uint32_t aRedirectFlags, uint32_t aLoadFlags, uint32_t aEarlyHintLinkType) {
+ if (!CanSend()) {
+ return PDocumentChannelParent::RedirectToRealChannelPromise::
+ CreateAndReject(ResponseRejectReason::ChannelClosed, __func__);
+ }
+
+ ContentParent* cp = static_cast<ContentParent*>(Manager()->Manager());
+ nsTArray<EarlyHintConnectArgs> earlyHints;
+ mDocumentLoadListener->RegisterEarlyHintLinksAndGetConnectArgs(cp->ChildID(),
+ earlyHints);
+
+ RedirectToRealChannelArgs args;
+ mDocumentLoadListener->SerializeRedirectData(
+ args, false, aRedirectFlags, aLoadFlags, cp, std::move(earlyHints),
+ aEarlyHintLinkType);
+ return SendRedirectToRealChannel(args, std::move(aStreamFilterEndpoints));
+}
+
+} // namespace net
+} // namespace mozilla
+
+#undef LOG