forked from mirrors/gecko-dev
Backed out changeset f41ac122a801 (bug 1646899) Backed out changeset 86a5e0827050 (bug 1646899) Backed out changeset d2fd0f955e24 (bug 1646899) Backed out changeset 7a7194146fe1 (bug 1646899) Backed out changeset 4731d76dae88 (bug 1646899)
440 lines
13 KiB
C++
440 lines
13 KiB
C++
/* -*- 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 "DocumentChannel.h"
|
|
|
|
#include "SerializedLoadContext.h"
|
|
#include "mozIThirdPartyUtil.h"
|
|
#include "mozilla/LoadInfo.h"
|
|
#include "mozilla/StaticPrefs_browser.h"
|
|
#include "mozilla/dom/BrowserChild.h"
|
|
#include "mozilla/dom/ContentChild.h"
|
|
#include "mozilla/dom/nsCSPContext.h"
|
|
#include "mozilla/extensions/StreamFilterParent.h"
|
|
#include "mozilla/ipc/IPCStreamUtils.h"
|
|
#include "mozilla/ipc/URIUtils.h"
|
|
#include "mozilla/net/DocumentChannelChild.h"
|
|
#include "mozilla/net/HttpChannelChild.h"
|
|
#include "mozilla/net/NeckoChild.h"
|
|
#include "mozilla/net/ParentProcessDocumentChannel.h"
|
|
#include "mozilla/net/UrlClassifierCommon.h"
|
|
#include "nsContentSecurityManager.h"
|
|
#include "nsDocShell.h"
|
|
#include "nsDocShellLoadState.h"
|
|
#include "nsHttpHandler.h"
|
|
#include "nsIInputStreamChannel.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsQueryObject.h"
|
|
#include "nsSerializationHelper.h"
|
|
#include "nsStreamListenerWrapper.h"
|
|
#include "nsStringStream.h"
|
|
#include "nsURLHelper.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(nsITraceableChannel)
|
|
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 aIsXFOError)
|
|
: mAsyncOpenTime(TimeStamp::Now()),
|
|
mLoadState(aLoadState),
|
|
mCacheKey(aCacheKey),
|
|
mLoadFlags(aLoadFlags),
|
|
mURI(aLoadState->URI()),
|
|
mLoadInfo(aLoadInfo),
|
|
mUriModified(aUriModified),
|
|
mIsXFOError(aIsXFOError) {
|
|
LOG(("DocumentChannel ctor [this=%p, uri=%s]", this,
|
|
aLoadState->URI()->GetSpecOrDefault().get()));
|
|
RefPtr<nsHttpHandler> handler = nsHttpHandler::GetInstance();
|
|
uint64_t channelId;
|
|
Unused << handler->NewChannelId(channelId);
|
|
mChannelId = channelId;
|
|
}
|
|
|
|
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!
|
|
if (listener) {
|
|
listener->OnStopRequest(this, aStatusCode);
|
|
}
|
|
mListener = nullptr;
|
|
mCallbacks = nullptr;
|
|
|
|
if (mLoadGroup) {
|
|
mLoadGroup->RemoveRequest(this, nullptr, aStatusCode);
|
|
mLoadGroup = nullptr;
|
|
}
|
|
|
|
DeleteIPDL();
|
|
}
|
|
|
|
void DocumentChannel::DisconnectChildListeners(
|
|
const nsresult& aStatus, const nsresult& aLoadGroupStatus) {
|
|
MOZ_ASSERT(NS_FAILED(aStatus));
|
|
mStatus = aLoadGroupStatus;
|
|
// Make sure we remove from the load group before
|
|
// setting mStatus, as existing tests expect the
|
|
// status to be successful when we disconnect.
|
|
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);
|
|
}
|
|
|
|
// Changes here should also be made in
|
|
// E10SUtils.documentChannelPermittedForURI().
|
|
static bool URIUsesDocChannel(nsIURI* aURI) {
|
|
if (SchemeIsJavascript(aURI) || NS_IsAboutBlank(aURI)) {
|
|
return false;
|
|
}
|
|
|
|
nsCString spec = aURI->GetSpecOrDefault();
|
|
return !spec.EqualsLiteral("about:printpreview") &&
|
|
!spec.EqualsLiteral("about:crashcontent");
|
|
}
|
|
|
|
bool DocumentChannel::CanUseDocumentChannel(nsDocShellLoadState* aLoadState) {
|
|
MOZ_ASSERT(aLoadState);
|
|
|
|
if (XRE_IsParentProcess() &&
|
|
!StaticPrefs::browser_tabs_documentchannel_ppdc()) {
|
|
return false;
|
|
}
|
|
|
|
// We want to use DocumentChannel if we're using a supported scheme. Sandboxed
|
|
// srcdoc loads break due to failing assertions after changing processes, and
|
|
// non-sandboxed srcdoc loads need to share the same principal object as their
|
|
// outer document (and must load in the same process), which breaks if we
|
|
// serialize to the parent process.
|
|
return StaticPrefs::browser_tabs_documentchannel() &&
|
|
!aLoadState->HasLoadFlags(nsDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC) &&
|
|
URIUsesDocChannel(aLoadState->URI());
|
|
}
|
|
|
|
/* static */
|
|
already_AddRefed<DocumentChannel> DocumentChannel::CreateDocumentChannel(
|
|
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
|
|
nsLoadFlags aLoadFlags, nsIInterfaceRequestor* aNotificationCallbacks,
|
|
uint32_t aCacheKey, bool aUriModified, bool aIsXFOError) {
|
|
RefPtr<DocumentChannel> channel;
|
|
if (XRE_IsContentProcess()) {
|
|
channel = new DocumentChannelChild(aLoadState, aLoadInfo, aLoadFlags,
|
|
aCacheKey, aUriModified, aIsXFOError);
|
|
} else {
|
|
channel =
|
|
new ParentProcessDocumentChannel(aLoadState, aLoadInfo, aLoadFlags,
|
|
aCacheKey, aUriModified, aIsXFOError);
|
|
}
|
|
channel->SetNotificationCallbacks(aNotificationCallbacks);
|
|
return channel.forget();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// DocumentChannel::nsITraceableChannel
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
DocumentChannel::SetNewListener(nsIStreamListener* aListener,
|
|
nsIStreamListener** _retval) {
|
|
NS_ENSURE_ARG_POINTER(aListener);
|
|
|
|
nsCOMPtr<nsIStreamListener> wrapper = new nsStreamListenerWrapper(mListener);
|
|
|
|
wrapper.forget(_retval);
|
|
mListener = aListener;
|
|
return NS_OK;
|
|
}
|
|
|
|
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) {
|
|
NS_ERROR(
|
|
"DocumentChannel::SetLoadFlags: "
|
|
"Don't set flags after creation");
|
|
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(nsISupports** aSecurityInfo) {
|
|
*aSecurityInfo = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP DocumentChannel::GetContentType(nsACString& aContentType) {
|
|
MOZ_CRASH("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::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;
|
|
}
|
|
|
|
} // namespace net
|
|
} // namespace mozilla
|
|
|
|
#undef LOG
|