Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/netwerk/ipc/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 15 kB image not shown  

Quelle  DocumentChannel.cpp   Sprache: C

 

/* 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 "mozilla/net/DocumentChannel.h"

#include <inttypes.h>
#include "mozIDOMWindow.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Assertions.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/Logging.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/ParentProcessChannelHandle.h"
#include "mozilla/net/DocumentChannelChild.h"
#include "mozilla/net/ParentProcessDocumentChannel.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsDocShell.h"
#include "nsDocShellLoadState.h"
#include "nsHttpHandler.h"
#include "nsIContentPolicy.h"
#include "nsIInterfaceRequestor.h"
#include "nsILoadContext.h"
#include "nsILoadGroup.h"
#include "nsILoadInfo.h"
#include "nsIStreamListener.h"
#include "nsIURI.h"
#include "nsLoadGroup.h"
#include "nsMimeTypes.h"
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsPIDOMWindowInlines.h"
#include "nsStringFwd.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "nscore.h"

using namespace mozilla::dom;
using namespace mozilla::ipc;

extern mozilla::LazyLogModule gDocumentChannelLog;
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)

namespace mozilla {
namespace net {

//-----------------------------------------------------------------------------
// DocumentChannel::nsISupports

NS_IMPL_ADDREF(DocumentChannel)
NS_IMPL_RELEASE(DocumentChannel)

NS_INTERFACE_MAP_BEGIN(DocumentChannel)
  NS_INTERFACE_MAP_ENTRY(nsIRequest)
  NS_INTERFACE_MAP_ENTRY(nsIChannel)
  NS_INTERFACE_MAP_ENTRY(nsIIdentChannel)
  NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentChannel)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequest)
NS_INTERFACE_MAP_END

DocumentChannel::DocumentChannel(nsDocShellLoadState* aLoadState,
                                 net::LoadInfo* aLoadInfo,
                                 nsLoadFlags aLoadFlags, uint32_t aCacheKey,
                                 bool aUriModified,
                                 bool aIsEmbeddingBlockedError)
    : mLoadState(aLoadState),
      mCacheKey(aCacheKey),
      mLoadFlags(aLoadFlags),
      mURI(aLoadState->URI()),
      mLoadInfo(aLoadInfo),
      mUriModified(aUriModified),
      mIsEmbeddingBlockedError(aIsEmbeddingBlockedError) {
  LOG(("DocumentChannel ctor [this=%p, uri=%s]", this,
       aLoadState->URI()->GetSpecOrDefault().get()));
  RefPtr<nsHttpHandler> handler = nsHttpHandler::GetInstance();
  mChannelId = handler->NewChannelId();
}

DocumentChannel::~DocumentChannel() = default;

NS_IMETHODIMP
DocumentChannel::AsyncOpen(nsIStreamListener* aListener) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

void DocumentChannel::ShutdownListeners(nsresult aStatusCode) {
  LOG(("DocumentChannel ShutdownListeners [this=%p, status=%" PRIx32 "]", this,
       static_cast<uint32_t>(aStatusCode)));
  mStatus = aStatusCode;

  nsCOMPtr<nsIStreamListener> listener = mListener;
  if (listener) {
    listener->OnStartRequest(this);
  }

  mIsPending = false;

  listener = mListener;  // it might have changed!
  nsCOMPtr<nsILoadGroup> loadGroup = mLoadGroup;

  mListener = nullptr;
  mLoadGroup = nullptr;
  mCallbacks = nullptr;

  NS_DispatchToMainThread(NS_NewRunnableFunction(
      "DocumentChannel::ShutdownListeners", [=, self = RefPtr{this}] {
        if (listener) {
          listener->OnStopRequest(self, aStatusCode);
        }

        if (loadGroup) {
          loadGroup->RemoveRequest(self, nullptr, aStatusCode);
        }
      }));

  DeleteIPDL();
}

void DocumentChannel::DisconnectChildListeners(
    const nsresult& aStatus, const nsresult& aLoadGroupStatus) {
  MOZ_ASSERT(NS_FAILED(aStatus));

  // In the case where the channel was redirected to be downloaded by the
  // nsExternalHelperAppService in the parent process, we'll be called with a
  // different aLoadGroupStatus and aStatus.
  //
  // Before DocumentChannel was implemented, the channel would have been removed
  // from the load group by the nsExternalHelperAppService. This simulates that
  // behaviour by removing the load group when the channel is no longer in use.
  //
  // We cannot unconditionally remove the channel from the load group here, as
  // that may unblock load events too early if new navigations will be started
  // by channel listeners. See bug 1961008.
  if (aStatus != aLoadGroupStatus) {
    MOZ_ASSERT(aStatus == NS_BINDING_RETARGETED);
    MOZ_ASSERT(NS_SUCCEEDED(aLoadGroupStatus));

    mStatus = aLoadGroupStatus;
    if (mLoadGroup) {
      mLoadGroup->RemoveRequest(this, nullptr, aStatus);
      mLoadGroup = nullptr;
    }
  }

  ShutdownListeners(aStatus);
}

nsDocShell* DocumentChannel::GetDocShell() {
  nsCOMPtr<nsILoadContext> loadContext;
  NS_QueryNotificationCallbacks(this, loadContext);
  if (!loadContext) {
    return nullptr;
  }
  nsCOMPtr<mozIDOMWindowProxy> domWindow;
  loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
  if (!domWindow) {
    return nullptr;
  }
  auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
  nsIDocShell* docshell = pDomWindow->GetDocShell();
  return nsDocShell::Cast(docshell);
}

static bool URIUsesDocChannel(nsIURI* aURI) {
  if (aURI->SchemeIs("javascript")) {
    return false;
  }

  nsCString spec = aURI->GetSpecOrDefault();
  return
#ifdef MOZ_WIDGET_ANDROID
      !spec.EqualsLiteral("about:crashcontentjava") &&
#endif
      !spec.EqualsLiteral("about:crashcontent");
}

bool DocumentChannel::CanUseDocumentChannel(nsIURI* aURI) {
  // We want to use DocumentChannel if we're using a supported scheme.
  return URIUsesDocChannel(aURI);
}

/* static */
already_AddRefed<DocumentChannel> DocumentChannel::CreateForDocument(
    nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
    nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
    uint32_t aCacheKey, bool aUriModified, bool aIsEmbeddingBlockedError) {
  RefPtr<DocumentChannel> channel;
  if (XRE_IsContentProcess()) {
    channel =
        new DocumentChannelChild(aLoadState, aLoadInfo, aLoadFlags, aCacheKey,
                                 aUriModified, aIsEmbeddingBlockedError);
  } else {
    channel = new ParentProcessDocumentChannel(
        aLoadState, aLoadInfo, aLoadFlags, aCacheKey, aUriModified,
        aIsEmbeddingBlockedError);
  }
  channel->SetNotificationCallbacks(aNotificationCallbacks);
  return channel.forget();
}

/* static */
already_AddRefed<DocumentChannel> DocumentChannel::CreateForObject(
    nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
    nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks) {
  return CreateForDocument(aLoadState, aLoadInfo, aLoadFlags,
                           aNotificationCallbacks, 0, false, false);
}

NS_IMETHODIMP DocumentChannel::SetCanceledReason(const nsACString& aReason) {
  return SetCanceledReasonImpl(aReason);
}

NS_IMETHODIMP DocumentChannel::GetCanceledReason(nsACString& aReason) {
  return GetCanceledReasonImpl(aReason);
}

NS_IMETHODIMP DocumentChannel::CancelWithReason(nsresult aStatus,
                                                const nsACString& aReason) {
  return CancelWithReasonImpl(aStatus, aReason);
}

NS_IMETHODIMP
DocumentChannel::Cancel(nsresult aStatusCode) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
DocumentChannel::Suspend() {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
DocumentChannel::Resume() {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

//-----------------------------------------------------------------------------
// Remainder of nsIRequest/nsIChannel.
//-----------------------------------------------------------------------------

NS_IMETHODIMP DocumentChannel::GetNotificationCallbacks(
    nsIInterfaceRequestor** aCallbacks) {
  nsCOMPtr<nsIInterfaceRequestor> callbacks(mCallbacks);
  callbacks.forget(aCallbacks);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::SetNotificationCallbacks(
    nsIInterfaceRequestor* aNotificationCallbacks) {
  mCallbacks = aNotificationCallbacks;
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
  nsCOMPtr<nsILoadGroup> loadGroup(mLoadGroup);
  loadGroup.forget(aLoadGroup);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
  mLoadGroup = aLoadGroup;
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetStatus(nsresult* aStatus) {
  *aStatus = mStatus;
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetName(nsACString& aResult) {
  if (!mURI) {
    aResult.Truncate();
    return NS_OK;
  }
  nsCString spec;
  nsresult rv = mURI->GetSpec(spec);
  NS_ENSURE_SUCCESS(rv, rv);

  aResult.AssignLiteral("documentchannel:");
  aResult.Append(spec);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::IsPending(bool* aResult) {
  *aResult = mIsPending;
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
  *aLoadFlags = mLoadFlags;
  return NS_OK;
}

NS_IMETHODIMP
DocumentChannel::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
  return GetTRRModeImpl(aTRRMode);
}

NS_IMETHODIMP
DocumentChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
  return SetTRRModeImpl(aTRRMode);
}

NS_IMETHODIMP DocumentChannel::SetLoadFlags(nsLoadFlags aLoadFlags) {
  nsLoadFlags mayChange = 0;
  if (mLoadInfo->GetExternalContentPolicyType() ==
      ExtContentPolicy::TYPE_OBJECT) {
    // Setting load flags for TYPE_OBJECT is OK, so long as the channel to
    // parent isn't opened yet, or we're only setting the `LOAD_DOCUMENT_URI`
    // flag.
    mayChange = mWasOpened ? LOAD_DOCUMENT_URI : ~0u;
  } else if (!mWasOpened) {
    // If we haven't been opened yet, allow the LoadGroup to
    // set cache control flags inherited from the default channel.
    mayChange = nsLoadGroup::kInheritedLoadFlags;
  }

  // Check if we're allowed to adjust these flags.
  if ((mLoadFlags & ~mayChange) == (aLoadFlags & ~mayChange)) {
    mLoadFlags = aLoadFlags;
    return NS_OK;
  }
  MOZ_CRASH_UNSAFE_PRINTF(
      "DocumentChannel::SetLoadFlags: Don't set flags after creation "
      "(differing flags %x != %x)",
      (mLoadFlags ^ aLoadFlags) & mLoadFlags,
      (mLoadFlags ^ aLoadFlags) & aLoadFlags);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetOriginalURI(nsIURI** aOriginalURI) {
  nsCOMPtr<nsIURI> originalURI =
      mLoadState->OriginalURI() ? mLoadState->OriginalURI() : mLoadState->URI();
  originalURI.forget(aOriginalURI);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::SetOriginalURI(nsIURI* aOriginalURI) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetURI(nsIURI** aURI) {
  nsCOMPtr<nsIURI> uri(mURI);
  uri.forget(aURI);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetOwner(nsISupports** aOwner) {
  nsCOMPtr<nsISupports> owner(mOwner);
  owner.forget(aOwner);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::SetOwner(nsISupports* aOwner) {
  mOwner = aOwner;
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetSecurityInfo(
    nsITransportSecurityInfo** aSecurityInfo) {
  *aSecurityInfo = nullptr;
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetContentType(nsACString& aContentType) {
  // We may be trying to load HTML object data, and have determined that we're
  // going to be performing a document load. In that case, fake the "text/html"
  // content type for nsObjectLoadingContent.
  if ((mLoadFlags & nsIRequest::LOAD_HTML_OBJECT_DATA) &&
      (mLoadFlags & nsIChannel::LOAD_DOCUMENT_URI)) {
    aContentType = TEXT_HTML;
    return NS_OK;
  }

  NS_ERROR("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::SetContentType(const nsACString& aContentType) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetContentCharset(nsACString& aContentCharset) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::SetContentCharset(
    const nsACString& aContentCharset) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetContentLength(int64_t* aContentLength) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::SetContentLength(int64_t aContentLength) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::Open(nsIInputStream** aStream) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetContentDisposition(
    uint32_t* aContentDisposition) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::SetContentDisposition(
    uint32_t aContentDisposition) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetContentDispositionFilename(
    nsAString& aContentDispositionFilename) {
  MOZ_CRASH("If we get here, something will be broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::SetContentDispositionFilename(
    const nsAString& aContentDispositionFilename) {
  MOZ_CRASH("If we get here, something will be broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetContentDispositionHeader(
    nsACString& aContentDispositionHeader) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
  nsCOMPtr<nsILoadInfo> loadInfo(mLoadInfo);
  loadInfo.forget(aLoadInfo);
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
  MOZ_CRASH("If we get here, something is broken");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP DocumentChannel::GetParentProcessChannelHandle(
    dom::ParentProcessChannelHandle** aValue) {
  *aValue = do_AddRef(mParentProcessChannelHandle).take();
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::SetParentProcessChannelHandle(
    dom::ParentProcessChannelHandle* aValue) {
  if (XRE_IsParentProcess()) {
    MOZ_ASSERT_UNREACHABLE(
        "SetParentProcessChannelHandle in the parent process would leak");
    return NS_ERROR_NOT_AVAILABLE;
  }

  mParentProcessChannelHandle = aValue;
  return NS_OK;
}

NS_IMETHODIMP DocumentChannel::GetIsDocument(bool* aIsDocument) {
  return NS_GetIsDocumentChannel(this, aIsDocument);
}

NS_IMETHODIMP DocumentChannel::GetCanceled(bool* aCanceled) {
  *aCanceled = mCanceled;
  return NS_OK;
}

//-----------------------------------------------------------------------------
// nsIIdentChannel
//-----------------------------------------------------------------------------

NS_IMETHODIMP
DocumentChannel::GetChannelId(uint64_t* aChannelId) {
  *aChannelId = mChannelId;
  return NS_OK;
}

NS_IMETHODIMP
DocumentChannel::SetChannelId(uint64_t aChannelId) {
  mChannelId = aChannelId;
  return NS_OK;
}

//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------

uint64_t InnerWindowIDForExtantDoc(nsDocShell* docShell) {
  if (!docShell) {
    return 0;
  }

  Document* doc = docShell->GetExtantDocument();
  if (!doc) {
    return 0;
  }

  return doc->InnerWindowID();
}

}  // namespace net
}  // namespace mozilla

#undef LOG

Messung V0.5 in Prozent
C=93 H=96 G=94

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-09-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.