icecat: add release icecat-140.10.1-1gnu1 for ecne

This commit is contained in:
Ark74 2026-05-04 16:58:41 -06:00
parent a5f93cb214
commit ff85d7c623
1256 changed files with 63469 additions and 24141 deletions

View file

@ -1,457 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=4 sw=2 sts=2 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 "mozilla/net/NeckoChild.h"
#include "GIOChannelChild.h"
#include "nsGIOProtocolHandler.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/BrowserChild.h"
#include "nsContentUtils.h"
#include "nsIBrowserChild.h"
#include "nsStringStream.h"
#include "nsNetUtil.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/URIUtils.h"
#include "SerializedLoadContext.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "nsIURIMutator.h"
#include "nsContentSecurityManager.h"
#include "SerializedLoadContext.h"
#include "mozilla/Logging.h"
using mozilla::dom::ContentChild;
namespace mozilla {
#undef LOG
#define LOG(args) MOZ_LOG(gGIOLog, mozilla::LogLevel::Debug, args)
namespace net {
GIOChannelChild::GIOChannelChild(nsIURI* aUri)
: mEventQ(new ChannelEventQueue(static_cast<nsIChildChannel*>(this))) {
SetURI(aUri);
// We could support thread retargeting, but as long as we're being driven by
// IPDL on the main thread it doesn't buy us anything.
DisallowThreadRetargeting();
}
void GIOChannelChild::AddIPDLReference() {
MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference");
mIPCOpen = true;
AddRef();
}
void GIOChannelChild::ReleaseIPDLReference() {
MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference");
mIPCOpen = false;
Release();
}
//-----------------------------------------------------------------------------
// GIOChannelChild::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED(GIOChannelChild, nsBaseChannel, nsIChildChannel)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
GIOChannelChild::AsyncOpen(nsIStreamListener* aListener) {
nsCOMPtr<nsIStreamListener> listener = aListener;
nsresult rv =
nsContentSecurityManager::doContentSecurityCheck(this, listener);
NS_ENSURE_SUCCESS(rv, rv);
LOG(("GIOChannelChild::AsyncOpen [this=%p]\n", this));
NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
NS_ENSURE_TRUE(
!static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(),
NS_ERROR_FAILURE);
NS_ENSURE_ARG_POINTER(listener);
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
// Port checked in parent, but duplicate here so we can return with error
// immediately, as we've done since before e10s.
rv = NS_CheckPortSafety(nsBaseChannel::URI()); // Need to disambiguate,
// because in the child ipdl,
// a typedef URI is defined...
if (NS_FAILED(rv)) {
return rv;
}
mozilla::dom::BrowserChild* browserChild = nullptr;
nsCOMPtr<nsIBrowserChild> iBrowserChild;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsIBrowserChild),
getter_AddRefs(iBrowserChild));
GetCallback(iBrowserChild);
if (iBrowserChild) {
browserChild =
static_cast<mozilla::dom::BrowserChild*>(iBrowserChild.get());
}
mListener = listener;
// add ourselves to the load group.
if (mLoadGroup) {
mLoadGroup->AddRequest(this, nullptr);
}
Maybe<mozilla::ipc::IPCStream> ipcStream;
mozilla::ipc::SerializeIPCStream(do_AddRef(mUploadStream), ipcStream,
/* aAllowLazy */ false);
uint32_t loadFlags = 0;
GetLoadFlags(&loadFlags);
GIOChannelOpenArgs openArgs;
SerializeURI(nsBaseChannel::URI(), openArgs.uri());
openArgs.startPos() = mStartPos;
openArgs.entityID() = mEntityID;
openArgs.uploadStream() = ipcStream;
openArgs.loadFlags() = loadFlags;
nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
rv = mozilla::ipc::LoadInfoToLoadInfoArgs(loadInfo, &openArgs.loadInfo());
NS_ENSURE_SUCCESS(rv, rv);
// This must happen before the constructor message is sent.
SetupNeckoTarget();
// The socket transport layer in the chrome process now has a logical ref to
// us until OnStopRequest is called.
AddIPDLReference();
if (!gNeckoChild->SendPGIOChannelConstructor(
this, browserChild, IPC::SerializedLoadContext(this), openArgs)) {
return NS_ERROR_FAILURE;
}
mIsPending = true;
mWasOpened = true;
return rv;
}
NS_IMETHODIMP
GIOChannelChild::IsPending(bool* aResult) {
*aResult = mIsPending;
return NS_OK;
}
nsresult GIOChannelChild::OpenContentStream(bool aAsync,
nsIInputStream** aStream,
nsIChannel** aChannel) {
MOZ_CRASH("GIOChannel*Child* should never have OpenContentStream called!");
return NS_OK;
}
mozilla::ipc::IPCResult GIOChannelChild::RecvOnStartRequest(
const nsresult& aChannelStatus, const int64_t& aContentLength,
const nsACString& aContentType, const nsACString& aEntityID,
const URIParams& aURI) {
LOG(("GIOChannelChild::RecvOnStartRequest [this=%p]\n", this));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<GIOChannelChild>(this), aChannelStatus,
aContentLength, aContentType = nsCString(aContentType),
aEntityID = nsCString(aEntityID), aURI]() {
self->DoOnStartRequest(aChannelStatus, aContentLength, aContentType,
aEntityID, aURI);
}));
return IPC_OK();
}
void GIOChannelChild::DoOnStartRequest(const nsresult& aChannelStatus,
const int64_t& aContentLength,
const nsACString& aContentType,
const nsACString& aEntityID,
const URIParams& aURI) {
LOG(("GIOChannelChild::DoOnStartRequest [this=%p]\n", this));
if (!mCanceled && NS_SUCCEEDED(mStatus)) {
mStatus = aChannelStatus;
}
mContentLength = aContentLength;
SetContentType(aContentType);
mEntityID = aEntityID;
nsCString spec;
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
nsresult rv = uri->GetSpec(spec);
if (NS_SUCCEEDED(rv)) {
// Changes nsBaseChannel::URI()
rv = NS_MutateURI(mURI).SetSpec(spec).Finalize(mURI);
}
if (NS_FAILED(rv)) {
Cancel(rv);
}
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
rv = mListener->OnStartRequest(this);
if (NS_FAILED(rv)) {
Cancel(rv);
}
}
mozilla::ipc::IPCResult GIOChannelChild::RecvOnDataAvailable(
const nsresult& aChannelStatus, const nsACString& aData,
const uint64_t& aOffset, const uint32_t& aCount) {
LOG(("GIOChannelChild::RecvOnDataAvailable [this=%p]\n", this));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<GIOChannelChild>(this), aChannelStatus,
aData = nsCString(aData), aOffset, aCount]() {
self->DoOnDataAvailable(aChannelStatus, aData, aOffset, aCount);
}));
return IPC_OK();
}
void GIOChannelChild::DoOnDataAvailable(const nsresult& aChannelStatus,
const nsACString& aData,
const uint64_t& aOffset,
const uint32_t& aCount) {
LOG(("GIOChannelChild::DoOnDataAvailable [this=%p]\n", this));
if (!mCanceled && NS_SUCCEEDED(mStatus)) {
mStatus = aChannelStatus;
}
if (mCanceled) {
return;
}
// NOTE: the OnDataAvailable contract requires the client to read all the data
// in the inputstream. This code relies on that ('data' will go away after
// this function). Apparently the previous, non-e10s behavior was to actually
// support only reading part of the data, allowing later calls to read the
// rest.
nsCOMPtr<nsIInputStream> stringStream;
nsresult rv =
NS_NewByteInputStream(getter_AddRefs(stringStream),
Span(aData).To(aCount), NS_ASSIGNMENT_DEPEND);
if (NS_FAILED(rv)) {
Cancel(rv);
return;
}
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
rv = mListener->OnDataAvailable(this, stringStream, aOffset, aCount);
if (NS_FAILED(rv)) {
Cancel(rv);
}
stringStream->Close();
}
mozilla::ipc::IPCResult GIOChannelChild::RecvOnStopRequest(
const nsresult& aChannelStatus) {
LOG(("GIOChannelChild::RecvOnStopRequest [this=%p status=%" PRIx32 "]\n",
this, static_cast<uint32_t>(aChannelStatus)));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<GIOChannelChild>(this), aChannelStatus]() {
self->DoOnStopRequest(aChannelStatus);
}));
return IPC_OK();
}
void GIOChannelChild::DoOnStopRequest(const nsresult& aChannelStatus) {
LOG(("GIOChannelChild::DoOnStopRequest [this=%p status=%" PRIx32 "]\n", this,
static_cast<uint32_t>(aChannelStatus)));
if (!mCanceled) {
mStatus = aChannelStatus;
}
{ // Ensure that all queued ipdl events are dispatched before
// we initiate protocol deletion below.
mIsPending = false;
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
(void)mListener->OnStopRequest(this, aChannelStatus);
mListener = nullptr;
if (mLoadGroup) {
mLoadGroup->RemoveRequest(this, nullptr, aChannelStatus);
}
}
// This calls NeckoChild::DeallocPGIOChannelChild(), which deletes |this| if
// IPDL holds the last reference. Don't rely on |this| existing after here!
Send__delete__(this);
}
mozilla::ipc::IPCResult GIOChannelChild::RecvFailedAsyncOpen(
const nsresult& aStatusCode) {
LOG(("GIOChannelChild::RecvFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
this, static_cast<uint32_t>(aStatusCode)));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<GIOChannelChild>(this), aStatusCode]() {
self->DoFailedAsyncOpen(aStatusCode);
}));
return IPC_OK();
}
void GIOChannelChild::DoFailedAsyncOpen(const nsresult& aStatusCode) {
LOG(("GIOChannelChild::DoFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
this, static_cast<uint32_t>(aStatusCode)));
mStatus = aStatusCode;
if (mLoadGroup) {
mLoadGroup->RemoveRequest(this, nullptr, aStatusCode);
}
if (mListener) {
mListener->OnStartRequest(this);
mIsPending = false;
mListener->OnStopRequest(this, aStatusCode);
} else {
mIsPending = false;
}
mListener = nullptr;
if (mIPCOpen) {
Send__delete__(this);
}
}
mozilla::ipc::IPCResult GIOChannelChild::RecvDeleteSelf() {
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this,
[self = UnsafePtr<GIOChannelChild>(this)]() { self->DoDeleteSelf(); }));
return IPC_OK();
}
void GIOChannelChild::DoDeleteSelf() {
if (mIPCOpen) {
Send__delete__(this);
}
}
//-----------------------------------------------------------------------------
// GIOChannelChild::nsIResumableChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
GIOChannelChild::Cancel(nsresult aStatus) {
LOG(("GIOChannelChild::Cancel [this=%p]\n", this));
if (mCanceled) {
return NS_OK;
}
mCanceled = true;
mStatus = aStatus;
if (mIPCOpen) {
SendCancel(aStatus);
}
return NS_OK;
}
NS_IMETHODIMP
GIOChannelChild::Suspend() {
NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
LOG(("GIOChannelChild::Suspend [this=%p]\n", this));
// SendSuspend only once, when suspend goes from 0 to 1.
if (!mSuspendCount++) {
SendSuspend();
mSuspendSent = true;
}
mEventQ->Suspend();
return NS_OK;
}
NS_IMETHODIMP
GIOChannelChild::Resume() {
NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
LOG(("GIOChannelChild::Resume [this=%p]\n", this));
// SendResume only once, when suspend count drops to 0.
if (!--mSuspendCount && mSuspendSent) {
SendResume();
}
mEventQ->Resume();
return NS_OK;
}
//-----------------------------------------------------------------------------
// GIOChannelChild::nsIChildChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
GIOChannelChild::ConnectParent(uint32_t aId) {
NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
NS_ENSURE_TRUE(
!static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(),
NS_ERROR_FAILURE);
LOG(("GIOChannelChild::ConnectParent [this=%p]\n", this));
mozilla::dom::BrowserChild* browserChild = nullptr;
nsCOMPtr<nsIBrowserChild> iBrowserChild;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsIBrowserChild),
getter_AddRefs(iBrowserChild));
GetCallback(iBrowserChild);
if (iBrowserChild) {
browserChild =
static_cast<mozilla::dom::BrowserChild*>(iBrowserChild.get());
}
// This must happen before the constructor message is sent.
SetupNeckoTarget();
// The socket transport in the chrome process now holds a logical ref to us
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
AddIPDLReference();
GIOChannelConnectArgs connectArgs(aId);
if (!gNeckoChild->SendPGIOChannelConstructor(
this, browserChild, IPC::SerializedLoadContext(this), connectArgs)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
GIOChannelChild::CompleteRedirectSetup(nsIStreamListener* aListener) {
LOG(("GIOChannelChild::CompleteRedirectSetup [this=%p]\n", this));
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
mIsPending = true;
mWasOpened = true;
mListener = aListener;
// add ourselves to the load group.
if (mLoadGroup) {
mLoadGroup->AddRequest(this, nullptr);
}
// We already have an open IPDL connection to the parent. If on-modify-request
// listeners or load group observers canceled us, let the parent handle it
// and send it back to us naturally.
return NS_OK;
}
void GIOChannelChild::SetupNeckoTarget() {
if (mNeckoTarget) {
return;
}
mNeckoTarget = GetMainThreadSerialEventTarget();
}
} // namespace net
} // namespace mozilla

View file

@ -1,111 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=4 sw=2 sts=2 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/. */
#ifndef NS_GIOCHANNELCHILD_H
#define NS_GIOCHANNELCHILD_H
#include "mozilla/net/PGIOChannelChild.h"
#include "mozilla/net/ChannelEventQueue.h"
#include "nsBaseChannel.h"
#include "nsIUploadChannel.h"
#include "nsIProxiedChannel.h"
#include "nsIResumableChannel.h"
#include "nsIChildChannel.h"
#include "nsIEventTarget.h"
#include "nsIStreamListener.h"
class nsIEventTarget;
namespace mozilla {
namespace net {
class GIOChannelChild final : public PGIOChannelChild,
public nsBaseChannel,
public nsIChildChannel {
public:
using nsIStreamListener = ::nsIStreamListener;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICHILDCHANNEL
NS_IMETHOD Cancel(nsresult aStatus) override;
NS_IMETHOD Suspend() override;
NS_IMETHOD Resume() override;
explicit GIOChannelChild(nsIURI* uri);
void AddIPDLReference();
void ReleaseIPDLReference();
NS_IMETHOD AsyncOpen(nsIStreamListener* aListener) override;
// Note that we handle this ourselves, overriding the nsBaseChannel
// default behavior, in order to be e10s-friendly.
NS_IMETHOD IsPending(bool* aResult) override;
nsresult OpenContentStream(bool aAsync, nsIInputStream** aStream,
nsIChannel** aChannel) override;
bool IsSuspended() const;
protected:
virtual ~GIOChannelChild() = default;
mozilla::ipc::IPCResult RecvOnStartRequest(const nsresult& aChannelStatus,
const int64_t& aContentLength,
const nsACString& aContentType,
const nsACString& aEntityID,
const URIParams& aURI) override;
mozilla::ipc::IPCResult RecvOnDataAvailable(const nsresult& aChannelStatus,
const nsACString& aData,
const uint64_t& aOffset,
const uint32_t& aCount) override;
mozilla::ipc::IPCResult RecvOnStopRequest(
const nsresult& aChannelStatus) override;
mozilla::ipc::IPCResult RecvFailedAsyncOpen(
const nsresult& aStatusCode) override;
mozilla::ipc::IPCResult RecvDeleteSelf() override;
void DoOnStartRequest(const nsresult& aChannelStatus,
const int64_t& aContentLength,
const nsACString& aContentType,
const nsACString& aEntityID, const URIParams& aURI);
void DoOnDataAvailable(const nsresult& aChannelStatus,
const nsACString& aData, const uint64_t& aOffset,
const uint32_t& aCount);
void DoOnStopRequest(const nsresult& aChannelStatus);
void DoFailedAsyncOpen(const nsresult& aStatusCode);
void DoDeleteSelf();
void SetupNeckoTarget() override;
friend class NeckoTargetChannelFunctionEvent;
private:
nsCOMPtr<nsIInputStream> mUploadStream;
bool mIPCOpen = false;
const RefPtr<ChannelEventQueue> mEventQ;
bool mCanceled = false;
uint32_t mSuspendCount = 0;
;
bool mIsPending = false;
uint64_t mStartPos = 0;
nsCString mEntityID;
// Set if SendSuspend is called. Determines if SendResume is needed when
// diverting callbacks to parent.
bool mSuspendSent = false;
};
inline bool GIOChannelChild::IsSuspended() const { return mSuspendCount != 0; }
} // namespace net
} // namespace mozilla
#endif /* NS_GIOCHANNELCHILD_H */

View file

@ -1,324 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=4 sw=2 sts=2 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 "GIOChannelParent.h"
#include "nsGIOProtocolHandler.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/net/NeckoParent.h"
#include "nsNetUtil.h"
#include "nsIChannel.h"
#include "mozilla/net/NeckoChannelParams.h"
#include "nsIAuthPrompt.h"
#include "nsIAuthPromptProvider.h"
#include "nsISecureBrowserUI.h"
#include "nsQueryObject.h"
#include "mozilla/Logging.h"
#include "mozilla/net/ChannelEventQueue.h"
#include "mozilla/ipc/URIUtils.h"
using namespace mozilla::dom;
using namespace mozilla::ipc;
namespace mozilla {
#undef LOG
#define LOG(args) MOZ_LOG(gGIOLog, mozilla::LogLevel::Debug, args)
namespace net {
GIOChannelParent::GIOChannelParent(dom::BrowserParent* aIframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus)
: mLoadContext(aLoadContext),
mPBOverride(aOverrideStatus),
mBrowserParent(aIframeEmbedding) {
mEventQ = new ChannelEventQueue(static_cast<nsIParentChannel*>(this));
}
void GIOChannelParent::ActorDestroy(ActorDestroyReason why) {
// We may still have refcount>0 if the channel hasn't called OnStopRequest
// yet, but we must not send any more msgs to child.
mIPCClosed = true;
}
//-----------------------------------------------------------------------------
// GIOChannelParent::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(GIOChannelParent, nsIStreamListener, nsIParentChannel,
nsIInterfaceRequestor, nsIRequestObserver)
//-----------------------------------------------------------------------------
// GIOChannelParent methods
//-----------------------------------------------------------------------------
bool GIOChannelParent::Init(const GIOChannelCreationArgs& aOpenArgs) {
switch (aOpenArgs.type()) {
case GIOChannelCreationArgs::TGIOChannelOpenArgs: {
const GIOChannelOpenArgs& a = aOpenArgs.get_GIOChannelOpenArgs();
return DoAsyncOpen(a.uri(), a.startPos(), a.entityID(), a.uploadStream(),
a.loadInfo(), a.loadFlags());
}
case GIOChannelCreationArgs::TGIOChannelConnectArgs: {
const GIOChannelConnectArgs& cArgs =
aOpenArgs.get_GIOChannelConnectArgs();
return ConnectChannel(cArgs.channelId());
}
default:
MOZ_ASSERT_UNREACHABLE("unknown open type");
return false;
}
}
bool GIOChannelParent::DoAsyncOpen(const URIParams& aURI,
const uint64_t& aStartPos,
const nsCString& aEntityID,
const Maybe<IPCStream>& aUploadStream,
const LoadInfoArgs& aLoadInfoArgs,
const uint32_t& aLoadFlags) {
nsresult rv;
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
if (!uri) {
return false;
}
#ifdef DEBUG
LOG(("GIOChannelParent DoAsyncOpen [this=%p uri=%s]\n", this,
uri->GetSpecOrDefault().get()));
#endif
nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
nsAutoCString remoteType;
rv = GetRemoteType(remoteType);
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsILoadInfo> loadInfo;
rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs, remoteType,
getter_AddRefs(loadInfo));
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
OriginAttributes attrs;
rv = loadInfo->GetOriginAttributes(&attrs);
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsIChannel> chan;
rv = NS_NewChannelInternal(getter_AddRefs(chan), uri, loadInfo, nullptr,
nullptr, nullptr, aLoadFlags, ios);
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
mChannel = chan;
nsIChannel* gioChan = static_cast<nsIChannel*>(mChannel.get());
rv = gioChan->AsyncOpen(this);
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
return true;
}
bool GIOChannelParent::ConnectChannel(const uint64_t& channelId) {
nsresult rv;
LOG(("Looking for a registered channel [this=%p, id=%" PRIx64 "]", this,
channelId));
nsCOMPtr<nsIChannel> channel;
rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel));
if (NS_SUCCEEDED(rv)) {
mChannel = channel;
}
LOG((" found channel %p, rv=%08" PRIx32, mChannel.get(),
static_cast<uint32_t>(rv)));
return true;
}
mozilla::ipc::IPCResult GIOChannelParent::RecvCancel(const nsresult& status) {
if (mChannel) {
mChannel->Cancel(status);
}
return IPC_OK();
}
mozilla::ipc::IPCResult GIOChannelParent::RecvSuspend() {
if (mChannel) {
mChannel->Suspend();
}
return IPC_OK();
}
mozilla::ipc::IPCResult GIOChannelParent::RecvResume() {
if (mChannel) {
mChannel->Resume();
}
return IPC_OK();
}
//-----------------------------------------------------------------------------
// GIOChannelParent::nsIRequestObserver
//-----------------------------------------------------------------------------
NS_IMETHODIMP
GIOChannelParent::OnStartRequest(nsIRequest* aRequest) {
LOG(("GIOChannelParent::OnStartRequest [this=%p]\n", this));
nsCOMPtr<nsIChannel> chan = do_QueryInterface(aRequest);
MOZ_ASSERT(chan);
NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED);
int64_t contentLength;
chan->GetContentLength(&contentLength);
nsCString contentType;
chan->GetContentType(contentType);
nsresult channelStatus = NS_OK;
chan->GetStatus(&channelStatus);
nsCString entityID;
URIParams uriparam;
nsCOMPtr<nsIURI> uri;
chan->GetURI(getter_AddRefs(uri));
SerializeURI(uri, uriparam);
if (mIPCClosed || !SendOnStartRequest(channelStatus, contentLength,
contentType, entityID, uriparam)) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
NS_IMETHODIMP
GIOChannelParent::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
LOG(("GIOChannelParent::OnStopRequest: [this=%p status=%" PRIu32 "]\n", this,
static_cast<uint32_t>(aStatusCode)));
if (mIPCClosed || !SendOnStopRequest(aStatusCode)) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// GIOChannelParent::nsIStreamListener
//-----------------------------------------------------------------------------
NS_IMETHODIMP
GIOChannelParent::OnDataAvailable(nsIRequest* aRequest,
nsIInputStream* aInputStream,
uint64_t aOffset, uint32_t aCount) {
LOG(("GIOChannelParent::OnDataAvailable [this=%p]\n", this));
nsCString data;
nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
if (NS_FAILED(rv)) {
return rv;
}
nsresult channelStatus = NS_OK;
mChannel->GetStatus(&channelStatus);
if (mIPCClosed ||
!SendOnDataAvailable(channelStatus, data, aOffset, aCount)) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// GIOChannelParent::nsIParentChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
GIOChannelParent::SetParentListener(ParentChannelListener* aListener) {
// Do not need ptr to ParentChannelListener.
return NS_OK;
}
NS_IMETHODIMP
GIOChannelParent::NotifyClassificationFlags(uint32_t aClassificationFlags,
bool aIsThirdParty) {
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
GIOChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
const nsACString& aProvider,
const nsACString& aFullHash) {
// nothing to do
return NS_OK;
}
NS_IMETHODIMP
GIOChannelParent::SetClassifierMatchedTrackingInfo(
const nsACString& aLists, const nsACString& aFullHashes) {
// nothing to do
return NS_OK;
}
NS_IMETHODIMP
GIOChannelParent::Delete() {
if (mIPCClosed || !SendDeleteSelf()) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
NS_IMETHODIMP
GIOChannelParent::GetRemoteType(nsACString& aRemoteType) {
if (!CanSend()) {
return NS_ERROR_UNEXPECTED;
}
dom::PContentParent* pcp = Manager()->Manager();
aRemoteType = static_cast<dom::ContentParent*>(pcp)->GetRemoteType();
return NS_OK;
}
//-----------------------------------------------------------------------------
// GIOChannelParent::nsIInterfaceRequestor
//-----------------------------------------------------------------------------
NS_IMETHODIMP
GIOChannelParent::GetInterface(const nsIID& uuid, void** result) {
if (uuid.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
uuid.Equals(NS_GET_IID(nsISecureBrowserUI))) {
if (mBrowserParent) {
return mBrowserParent->QueryInterface(uuid, result);
}
}
// Only support nsILoadContext if child channel's callbacks did too
if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
nsCOMPtr<nsILoadContext> copy = mLoadContext;
copy.forget(result);
return NS_OK;
}
return QueryInterface(uuid, result);
}
//---------------------
} // namespace net
} // namespace mozilla

View file

@ -1,80 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=4 sw=2 sts=2 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/. */
#ifndef NS_GIOCHANNELPARENT_H
#define NS_GIOCHANNELPARENT_H
#include "mozilla/net/PGIOChannelParent.h"
#include "mozilla/net/NeckoParent.h"
#include "nsIParentChannel.h"
#include "nsIInterfaceRequestor.h"
class nsILoadContext;
namespace mozilla {
namespace dom {
class BrowserParent;
} // namespace dom
namespace net {
class ChannelEventQueue;
class GIOChannelParent final : public PGIOChannelParent,
public nsIParentChannel,
public nsIInterfaceRequestor {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPARENTCHANNEL
NS_DECL_NSIINTERFACEREQUESTOR
GIOChannelParent(dom::BrowserParent* aIframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus);
bool Init(const GIOChannelCreationArgs& aOpenArgs);
protected:
virtual ~GIOChannelParent() = default;
bool DoAsyncOpen(const URIParams& aURI, const uint64_t& aStartPos,
const nsCString& aEntityID,
const Maybe<mozilla::ipc::IPCStream>& aUploadStream,
const LoadInfoArgs& aLoadInfoArgs,
const uint32_t& aLoadFlags);
// used to connect redirected-to channel in parent with just created
// ChildChannel. Used during HTTP->FTP redirects.
bool ConnectChannel(const uint64_t& channelId);
virtual mozilla::ipc::IPCResult RecvCancel(const nsresult& status) override;
virtual mozilla::ipc::IPCResult RecvSuspend() override;
virtual mozilla::ipc::IPCResult RecvResume() override;
virtual void ActorDestroy(ActorDestroyReason why) override;
nsCOMPtr<nsIChannel> mChannel;
bool mIPCClosed = false;
nsCOMPtr<nsILoadContext> mLoadContext;
PBOverrideStatus mPBOverride;
// Set to the canceled status value if the main channel was canceled.
nsresult mStatus = NS_OK;
RefPtr<mozilla::dom::BrowserParent> mBrowserParent;
RefPtr<ChannelEventQueue> mEventQ;
};
} // namespace net
} // namespace mozilla
#endif /* NS_GIOCHANNELPARENT_H */

View file

@ -1,51 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
/* 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 protocol PNecko;
include URIParams;
//FIXME: bug #792908 (NeckoChannelParams already included by PNecko)
include NeckoChannelParams;
using PRTime from "prtime.h";
namespace mozilla {
namespace net {
[ManualDealloc, ChildImpl=virtual, ParentImpl=virtual]
async protocol PGIOChannel
{
manager PNecko;
parent:
// Note: channels are opened during construction, so no open method here:
// see PNecko.ipdl
async __delete__();
async Cancel(nsresult status);
async Suspend();
async Resume();
child:
async OnStartRequest(nsresult aChannelStatus,
int64_t aContentLength,
nsCString aContentType,
nsCString aEntityID,
URIParams aURI);
async OnDataAvailable(nsresult channelStatus,
nsCString data,
uint64_t offset,
uint32_t count);
async OnStopRequest(nsresult channelStatus);
async FailedAsyncOpen(nsresult statusCode);
async DeleteSelf();
};
} // namespace net
} // namespace mozilla

View file

@ -1,24 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
Classes = [
{
'cid': '{ee706783-3af8-4d19-9e84-e2ebfe213480}',
'contract_ids': ['@mozilla.org/network/protocol;1?name=moz-gio'],
'singleton': True,
'type': 'nsGIOProtocolHandler',
'headers': ['nsGIOProtocolHandler.h'],
'constructor': 'nsGIOProtocolHandler::GetSingleton',
'categories': { 'xpcom-startup': 'nsGIOProtocolHandler' },
'protocol_config': {
'scheme': 'moz-gio',
'flags': [
'URI_STD',
'URI_DANGEROUS_TO_LOAD',
],
},
},
]

View file

@ -1,42 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPCOM_MANIFESTS += [
"components.conf",
]
EXPORTS += [
"nsGIOProtocolHandler.h",
]
EXPORTS.mozilla.net += [
"GIOChannelChild.h",
"GIOChannelParent.h",
]
UNIFIED_SOURCES += [
"GIOChannelChild.cpp",
"GIOChannelParent.cpp",
"nsGIOProtocolHandler.cpp",
]
IPDL_SOURCES = [
"PGIOChannel.ipdl",
]
include("/ipc/chromium/chromium-config.mozbuild")
LOCAL_INCLUDES += [
"/netwerk/base",
]
FINAL_LIBRARY = "xul"
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"]
with Files("**"):
BUG_COMPONENT = ("Core", "Widget: Gtk")

File diff suppressed because it is too large Load diff

View file

@ -1,38 +0,0 @@
/* 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/. */
#ifndef nsGIOProtocolHandler_h___
#define nsGIOProtocolHandler_h___
#include "nsIProtocolHandler.h"
#include "nsIObserver.h"
#include "nsIPrefBranch.h"
#include "nsStringFwd.h"
#include "mozilla/Logging.h"
extern mozilla::LazyLogModule gGIOLog;
class nsGIOProtocolHandler final : public nsIProtocolHandler,
public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
NS_DECL_NSIOBSERVER
static already_AddRefed<nsGIOProtocolHandler> GetSingleton();
bool IsSupportedProtocol(const nsCString& aScheme);
protected:
~nsGIOProtocolHandler() = default;
private:
nsresult Init();
void InitSupportedProtocolsPref(nsIPrefBranch* prefs);
static mozilla::StaticRefPtr<nsGIOProtocolHandler> sSingleton;
nsTArray<nsCString> mSupportedProtocols;
};
#endif // nsGIOProtocolHandler_h___

View file

@ -34,7 +34,7 @@ BackgroundChannelRegistrar::~BackgroundChannelRegistrar() {
}
// static
already_AddRefed<nsIBackgroundChannelRegistrar>
already_AddRefed<BackgroundChannelRegistrar>
BackgroundChannelRegistrar::GetOrCreate() {
if (!gSingleton) {
gSingleton = new BackgroundChannelRegistrar();
@ -57,8 +57,22 @@ void BackgroundChannelRegistrar::NotifyChannelLinked(
void BackgroundChannelRegistrar::DeleteChannel(uint64_t aKey) {
MOZ_ASSERT(NS_IsMainThread());
mChannels.Remove(aKey);
mBgChannels.Remove(aKey);
RefPtr<HttpChannelParent> channel;
mChannels.Remove(aKey, getter_AddRefs(channel));
RefPtr<HttpBackgroundChannelParent> bgChannel;
mBgChannels.Remove(aKey, getter_AddRefs(bgChannel));
}
void BackgroundChannelRegistrar::DeleteChannelIfMatches(
uint64_t aKey, HttpChannelParent* aExpected) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<HttpChannelParent> channel;
if (mChannels.GetWeak(aKey) == aExpected) {
mChannels.Remove(aKey, getter_AddRefs(channel));
}
RefPtr<HttpBackgroundChannelParent> bgChannel;
mBgChannels.Remove(aKey, getter_AddRefs(bgChannel));
}
void BackgroundChannelRegistrar::LinkHttpChannel(uint64_t aKey,

View file

@ -29,12 +29,19 @@ class BackgroundChannelRegistrar final : public nsIBackgroundChannelRegistrar {
explicit BackgroundChannelRegistrar();
// Singleton accessor
static already_AddRefed<nsIBackgroundChannelRegistrar> GetOrCreate();
// Singleton accessors
static already_AddRefed<BackgroundChannelRegistrar> GetOrCreate();
private:
virtual ~BackgroundChannelRegistrar();
// Like DeleteChannel, but only removes the mChannels entry if it matches
// aExpected. Use this in preference to DeleteChannel when the caller knows
// which HttpChannelParent it registered, to avoid accidentally removing an
// entry belonging to a different object that shares the same channel Id.
void DeleteChannelIfMatches(uint64_t aKey, HttpChannelParent* aExpected);
friend class HttpChannelParent;
// A helper function for BackgroundChannelRegistrar itself to callback
// HttpChannelParent and HttpBackgroundChannelParent when both objects are
// ready. aChannelParent and aBgParent is the pair of HttpChannelParent and

View file

@ -10,11 +10,7 @@ namespace mozilla {
namespace net {
BackgroundDataBridgeParent::BackgroundDataBridgeParent(uint64_t aChannelID)
: mChannelID(aChannelID), mBackgroundThread(GetCurrentSerialEventTarget()) {
if (SocketProcessChild* child = SocketProcessChild::GetSingleton()) {
child->AddDataBridgeToMap(aChannelID, this);
}
}
: mChannelID(aChannelID), mBackgroundThread(GetCurrentSerialEventTarget()) {}
void BackgroundDataBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
if (SocketProcessChild* child = SocketProcessChild::GetSingleton()) {
@ -22,6 +18,16 @@ void BackgroundDataBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
}
}
already_AddRefed<BackgroundDataBridgeParent>
BackgroundDataBridgeParent::Create(uint64_t aChannelID) {
RefPtr<BackgroundDataBridgeParent> actor =
new BackgroundDataBridgeParent(aChannelID);
if (SocketProcessChild* child = SocketProcessChild::GetSingleton()) {
child->AddDataBridgeToMap(aChannelID, actor);
}
return actor.forget();
}
already_AddRefed<nsISerialEventTarget>
BackgroundDataBridgeParent::GetBackgroundThread() {
return do_AddRef(mBackgroundThread);

View file

@ -14,7 +14,7 @@ class BackgroundDataBridgeParent final : public PBackgroundDataBridgeParent {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BackgroundDataBridgeParent, override)
explicit BackgroundDataBridgeParent(uint64_t aChannelID);
static already_AddRefed<BackgroundDataBridgeParent> Create(uint64_t aChannelID);
void ActorDestroy(ActorDestroyReason aWhy) override;
already_AddRefed<nsISerialEventTarget> GetBackgroundThread();
void Destroy();
@ -24,6 +24,7 @@ class BackgroundDataBridgeParent final : public PBackgroundDataBridgeParent {
const TimeStamp& aOnStopRequestStart);
private:
explicit BackgroundDataBridgeParent(uint64_t aChannelID);
virtual ~BackgroundDataBridgeParent() = default;
uint64_t mChannelID;

View file

@ -271,12 +271,15 @@ void HttpChannelParent::CleanupBackgroundChannel() {
}
// This HttpChannelParent might still have a reference from
// BackgroundChannelRegistrar.
nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
// BackgroundChannelRegistrar. Only remove our own entry; another
// HttpChannelParent may have been registered under the same channel Id
// (e.g. after a redirect), and we must not remove that entry.
RefPtr<BackgroundChannelRegistrar> registrar =
BackgroundChannelRegistrar::GetOrCreate();
MOZ_ASSERT(registrar);
registrar->DeleteChannel(mChannel->ChannelId());
if (registrar) {
registrar->DeleteChannelIfMatches(mChannel->ChannelId(), this);
}
// If mAsyncOpenBarrier is greater than zero, it means AsyncOpen procedure
// is still on going. we need to abort AsyncOpen with failure to destroy
@ -980,6 +983,11 @@ HttpChannelParent::ContinueVerification(
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aCallback);
if (mIPCClosed) {
aCallback->ReadyToVerify(NS_ERROR_FAILURE);
return NS_OK;
}
// Continue the verification procedure if background channel is ready.
if (mBgParent) {
aCallback->ReadyToVerify(NS_OK);

View file

@ -18,6 +18,7 @@
#include "nsIThreadRetargetableStreamListener.h"
#include "nsITransportSecurityInfo.h"
#include "nsNetUtil.h"
#include "nsProxyRelease.h"
#include "nsQueryObject.h"
#include "nsSerializationHelper.h"
#include "nsStreamUtils.h"
@ -36,11 +37,31 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP_(MozExternalRefCountType) HttpTransactionParent::Release(void) {
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
if (!NS_IsMainThread()) {
// Use DecrementWithLimit to atomically decrement only while count > 2.
// This ensures a background thread never drops the count to 1 or 0,
// avoiding the race where the main thread frees the object (via
// ActorDisconnected) between our decrement and the count==1 handling.
auto [success, count] = mRefCnt.DecrementWithLimit<2>();
if (success) {
NS_LOG_RELEASE(this, count, "HttpTransactionParent");
return count;
}
// mRefCnt <= 2: the next decrement could trigger Send__delete__ or
// deletion, both of which must happen on the main thread. Transfer
// our reference there without decrementing.
NS_ProxyRelease("HttpTransactionParent::Release",
GetMainThreadSerialEventTarget(),
dont_AddRef(static_cast<nsIRequest*>(this)));
return 1;
}
nsrefcnt count = --mRefCnt;
NS_LOG_RELEASE(this, count, "HttpTransactionParent");
if (count == 0) {
mRefCnt = 1; /* stabilize */
delete (this);
delete this;
return 0;
}
@ -48,17 +69,7 @@ NS_IMETHODIMP_(MozExternalRefCountType) HttpTransactionParent::Release(void) {
// we are done with this transaction. We should send a delete message
// to delete the transaction child in socket process.
if (count == 1 && CanSend()) {
if (!NS_IsMainThread()) {
RefPtr<HttpTransactionParent> self = this;
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(
NS_NewRunnableFunction("HttpTransactionParent::Release", [self]() {
mozilla::Unused << self->Send__delete__(self);
// Make sure we can not send IPC after Send__delete__().
MOZ_ASSERT(!self->CanSend());
})));
} else {
mozilla::Unused << Send__delete__(this);
}
mozilla::Unused << Send__delete__(this);
return 1;
}
return count;

View file

@ -525,6 +525,9 @@ NS_IMETHODIMP
ObliviousHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
LOG(("ObliviousHttpChannel::AsyncOpen [this=%p, listener=%p]", this,
aListener));
if (mStreamListener) {
return NS_ERROR_ALREADY_OPENED;
}
mStreamListener = aListener;
nsresult rv = mInnerChannel->SetRequestMethod("POST"_ns);
if (NS_FAILED(rv)) {
@ -728,7 +731,8 @@ nsresult ObliviousHttpChannel::ProcessOnStopRequest() {
getter_AddRefs(mBinaryHttpResponse));
}
void ObliviousHttpChannel::EmitOnDataAvailable() {
void ObliviousHttpChannel::EmitOnDataAvailable(
nsIStreamListener* aStreamListener) {
if (!mBinaryHttpResponse) {
return;
}
@ -749,7 +753,7 @@ void ObliviousHttpChannel::EmitOnDataAvailable() {
if (NS_FAILED(rv)) {
return;
}
rv = mStreamListener->OnDataAvailable(this, contentStream, 0, contentLength);
rv = aStreamListener->OnDataAvailable(this, contentStream, 0, contentLength);
Unused << rv;
}
@ -759,8 +763,7 @@ ObliviousHttpChannel::OnStopRequest(nsIRequest* aRequest,
LOG(("ObliviousHttpChannel::OnStopRequest [this=%p, request=%p, status=%u]",
this, aRequest, (uint32_t)aStatusCode));
auto releaseStreamListener = MakeScopeExit(
[self = RefPtr{this}]() mutable { self->mStreamListener = nullptr; });
nsCOMPtr<nsIStreamListener> listener = std::move(mStreamListener);
if (NS_SUCCEEDED(aStatusCode)) {
bool requestSucceeded;
@ -769,11 +772,11 @@ ObliviousHttpChannel::OnStopRequest(nsIRequest* aRequest,
aStatusCode = ProcessOnStopRequest();
}
}
Unused << mStreamListener->OnStartRequest(this);
Unused << listener->OnStartRequest(this);
if (NS_SUCCEEDED(aStatusCode)) {
EmitOnDataAvailable();
EmitOnDataAvailable(listener);
}
Unused << mStreamListener->OnStopRequest(this, aStatusCode);
Unused << listener->OnStopRequest(this, aStatusCode);
return NS_OK;
}

View file

@ -47,7 +47,7 @@ class ObliviousHttpChannel final : public nsIObliviousHttpChannel,
~ObliviousHttpChannel();
nsresult ProcessOnStopRequest();
void EmitOnDataAvailable();
void EmitOnDataAvailable(nsIStreamListener*);
nsCOMPtr<nsIURI> mTargetURI;
nsTArray<uint8_t> mEncodedConfig;

View file

@ -53,12 +53,18 @@ ReplacedHttpResponse::SetResponseBody(const nsACString& aResponseBody) {
NS_IMETHODIMP
ReplacedHttpResponse::SetResponseHeader(const nsACString& header,
const nsACString& value, bool merge) {
if (mInVisitHeaders) {
return NS_ERROR_FAILURE;
}
return mResponseHeaders.SetHeader(header, value, merge,
nsHttpHeaderArray::eVarietyResponse);
}
NS_IMETHODIMP
ReplacedHttpResponse::VisitResponseHeaders(nsIHttpHeaderVisitor* visitor) {
return mResponseHeaders.VisitHeaders(visitor);
mInVisitHeaders = true;
nsresult rv = mResponseHeaders.VisitHeaders(visitor);
mInVisitHeaders = false;
return rv;
}
} // namespace mozilla::net

View file

@ -7,6 +7,7 @@
#include "nsString.h"
#include "nsHttpHeaderArray.h"
#include "nsIReplacedHttpResponse.h"
#include "mozilla/Atomics.h"
namespace mozilla::net {
@ -24,6 +25,7 @@ class ReplacedHttpResponse : nsIReplacedHttpResponse {
nsCString mResponseStatusText;
nsCString mResponseBody;
nsHttpHeaderArray mResponseHeaders;
Atomic<bool> mInVisitHeaders{false};
};
} // namespace mozilla::net

View file

@ -508,8 +508,16 @@ TLSTransportLayer::OpenOutputStream(uint32_t aFlags, uint32_t aSegmentSize,
NS_IMETHODIMP
TLSTransportLayer::Close(nsresult aReason) {
LOG(("TLSTransportLayer::Close [this=%p reason=%" PRIx32 "]\n", this,
static_cast<uint32_t>(aReason)));
bool onSocketThread = OnSocketThread();
LOG(("TLSTransportLayer::Close [this=%p reason=%" PRIx32 "] sts=%d", this,
static_cast<uint32_t>(aReason), onSocketThread));
if (!onSocketThread) {
gSocketTransportService->Dispatch(NS_NewRunnableFunction(
"TLSTransportLayer::Close",
[self = RefPtr{this}, aReason] { self->Close(aReason); }));
return NS_OK;
}
mInputCallback = nullptr;
mOutputCallback = nullptr;

View file

@ -33,6 +33,7 @@ nsHttpActivityDistributor::ObserveActivity(nsISupports* aHttpChannel,
uint64_t aExtraSizeData,
const nsACString& aExtraStringData) {
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
RefPtr<nsHttpActivityDistributor> self(this);
for (size_t i = 0; i < mObservers.Length(); i++) {
Unused << mObservers[i]->ObserveActivity(aHttpChannel, aActivityType,
@ -48,6 +49,7 @@ nsHttpActivityDistributor::ObserveConnectionActivity(
bool aIsHttp3, uint32_t aActivityType, uint32_t aActivitySubtype,
PRTime aTimestamp, const nsACString& aExtraStringData) {
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
RefPtr<nsHttpActivityDistributor> self(this);
for (size_t i = 0; i < mObservers.Length(); i++) {
Unused << mObservers[i]->ObserveConnectionActivity(

View file

@ -354,6 +354,7 @@ nsHttpChannel::nsHttpChannel() : HttpAsyncAborter<nsHttpChannel>(this) {
}
nsHttpChannel::~nsHttpChannel() {
MOZ_ASSERT(NS_IsMainThread(), "Must be released on main thread");
PROFILER_MARKER("~nsHttpChannel", NETWORK, {}, TerminatingFlowMarker,
Flow::FromPointer(this));
LOG(("Destroying nsHttpChannel [this=%p, nsIChannel=%p]\n", this,
@ -373,42 +374,11 @@ nsHttpChannel::~nsHttpChannel() {
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
ReleaseMainThreadOnlyReferences();
if (gHttpHandler) {
gHttpHandler->RemoveHttpChannel(mChannelId);
}
}
void nsHttpChannel::ReleaseMainThreadOnlyReferences() {
if (NS_IsMainThread()) {
// Already on main thread, let dtor to
// take care of releasing references
return;
}
nsTArray<nsCOMPtr<nsISupports>> arrayToRelease;
arrayToRelease.AppendElement(mAuthProvider.forget());
arrayToRelease.AppendElement(mRedirectChannel.forget());
arrayToRelease.AppendElement(mPreflightChannel.forget());
arrayToRelease.AppendElement(mDNSPrefetch.forget());
MOZ_DIAGNOSTIC_ASSERT(
!mEarlyHintObserver,
"Early hint observer should have been released in ReleaseListeners()");
arrayToRelease.AppendElement(mEarlyHintObserver.forget());
MOZ_DIAGNOSTIC_ASSERT(
!mChannelClassifier,
"Channel classifier should have been released in ReleaseListeners()");
arrayToRelease.AppendElement(
mChannelClassifier.forget().downcast<nsIURIClassifierCallback>());
MOZ_DIAGNOSTIC_ASSERT(
!mWarningReporter,
"Warning reporter should have been released in ReleaseListeners()");
arrayToRelease.AppendElement(mWarningReporter.forget());
NS_DispatchToMainThread(new ProxyReleaseRunnable(std::move(arrayToRelease)));
}
nsresult nsHttpChannel::Init(nsIURI* uri, uint32_t caps, nsProxyInfo* proxyInfo,
uint32_t proxyResolveFlags, nsIURI* proxyURI,
uint64_t channelId,
@ -6229,7 +6199,29 @@ NS_IMETHODIMP nsHttpChannel::ConnectionRestartable(bool aRestartable) {
//-----------------------------------------------------------------------------
NS_IMPL_ADDREF_INHERITED(nsHttpChannel, HttpBaseChannel)
NS_IMPL_RELEASE_INHERITED(nsHttpChannel, HttpBaseChannel)
bool nsHttpChannel::DispatchRelease() {
if (NS_IsMainThread()) {
return false;
}
NS_DispatchToMainThread(
NewNonOwningRunnableMethod("net::nsHttpChannel::Release", this,
&nsHttpChannel::Release),
NS_DISPATCH_NORMAL);
return true;
}
NS_IMETHODIMP_(MozExternalRefCountType)
nsHttpChannel::Release() {
nsrefcnt count = mRefCnt - 1;
if (DispatchRelease()) {
// Redispatched to the main thread.
return count;
}
NS_IMPL_RELEASE_INHERITED_GUTS(nsHttpChannel, HttpBaseChannel);
}
NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
@ -6661,6 +6653,10 @@ nsHttpChannel::GetSecurityInfo(nsITransportSecurityInfo** securityInfo) {
// any error.
NS_IMETHODIMP
nsHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
// doContentSecurityCheck and OnOpeningRequest fire observers that may
// spin nested event loops; hold a strong ref to this.
RefPtr<nsHttpChannel> self(this);
AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpen", NETWORK,
Flow::FromPointer(this));
nsCOMPtr<nsIStreamListener> listener = aListener;
@ -11322,9 +11318,11 @@ nsHttpChannel::EarlyHint(const nsACString& aLinkHeader,
const nsACString& aCspHeader) {
LOG(("nsHttpChannel::EarlyHint.\n"));
if (mEarlyHintObserver && nsContentUtils::ComputeIsSecureContext(this)) {
LOG(("nsHttpChannel::EarlyHint propagated.\n"));
mEarlyHintObserver->EarlyHint(aLinkHeader, aReferrerPolicy, aCspHeader);
if (nsCOMPtr<nsIEarlyHintObserver> obs = mEarlyHintObserver) {
if (nsContentUtils::ComputeIsSecureContext(this)) {
LOG(("nsHttpChannel::EarlyHint propagated.\n"));
obs->EarlyHint(aLinkHeader, aReferrerPolicy, aCspHeader);
}
}
return NS_OK;
}

View file

@ -306,6 +306,7 @@ class nsHttpChannel final : public HttpBaseChannel,
// Based on the proxy configuration determine the strategy for resolving the
// end server host name.
ProxyDNSStrategy GetProxyDNSStrategy();
bool DispatchRelease();
// We might synchronously or asynchronously call BeginConnect,
// which includes DNS prefetch and speculative connection, according to
@ -521,8 +522,9 @@ class nsHttpChannel final : public HttpBaseChannel,
void SetCachedContentType();
private:
// this section is for main-thread-only object
// all the references need to be proxy released on main thread.
// --- MAIN THREAD ONLY OBJECTS ---
// this section is for main-thread-only objects
// all the references need to be released on main thread.
// auth specific data
nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
nsCOMPtr<nsIURI> mRedirectURI;
@ -537,8 +539,7 @@ class nsHttpChannel final : public HttpBaseChannel,
// state of whether tracking protection is enabled or not.
RefPtr<nsChannelClassifier> mChannelClassifier;
// Proxy release all members above on main thread.
void ReleaseMainThreadOnlyReferences();
// --- END OF MAIN THREAD ONLY OBJECTS SECTION ---
// Called after the channel is made aware of its tracking status in order
// to readjust the referrer if needed according to the referrer default
@ -851,7 +852,7 @@ class nsHttpChannel final : public HttpBaseChannel,
private: // cache telemetry
bool mDidReval{false};
RefPtr<nsIEarlyHintObserver> mEarlyHintObserver;
nsCOMPtr<nsIEarlyHintObserver> mEarlyHintObserver;
Maybe<nsCString> mOpenerCallingScriptLocation;
RefPtr<WebTransportSessionEventListener> mWebTransportSessionEventListener;
nsMainThreadPtrHandle<nsIReplacedHttpResponse> mOverrideResponse;

View file

@ -616,7 +616,8 @@ nsresult nsHttpConnection::Activate(nsAHttpTransaction* trans, uint32_t caps,
rv = OnOutputStreamReady(mSocketOut);
if (NS_SUCCEEDED(rv) && mContinueHandshakeDone) {
mContinueHandshakeDone();
auto continuation = std::move(mContinueHandshakeDone);
continuation();
}
mContinueHandshakeDone = nullptr;

View file

@ -2688,13 +2688,13 @@ void nsHttpHandler::ExcludeHttp2OrHttp3Internal(
MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(), OnSocketThread());
if (ci->IsHttp3()) {
if (!mExcludedHttp3Origins.Contains(ci->GetRoutedHost())) {
{
MutexAutoLock lock(mHttpExclusionLock);
mExcludedHttp3Origins.Insert(ci->GetRoutedHost());
}
mConnMgr->ExcludeHttp3(ci);
} else {
if (!mExcludedHttp2Origins.Contains(ci->GetOrigin())) {
{
MutexAutoLock lock(mHttpExclusionLock);
mExcludedHttp2Origins.Insert(ci->GetOrigin());
}

View file

@ -803,7 +803,7 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
"nsHttpConnectionMgr::LastActiveTabLoadOptimization"};
TimeStamp mLastActiveTabLoadOptimizationHit;
Mutex mHttpExclusionLock MOZ_UNANNOTATED{"nsHttpHandler::HttpExclusion"};
Mutex mHttpExclusionLock{"nsHttpHandler::HttpExclusion"};
public:
[[nodiscard]] nsresult NewChannelId(uint64_t& channelId);
@ -826,8 +826,10 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
#endif
private:
nsTHashSet<nsCString> mExcludedHttp2Origins;
nsTHashSet<nsCString> mExcludedHttp3Origins;
nsTHashSet<nsCString> mExcludedHttp2Origins
MOZ_GUARDED_BY(mHttpExclusionLock);
nsTHashSet<nsCString> mExcludedHttp3Origins
MOZ_GUARDED_BY(mHttpExclusionLock);
nsTHashSet<nsCString> mExcluded0RttTcpOrigins;
// A set of hosts that we should not upgrade to HTTPS with HTTPS RR.
nsTHashSet<nsCString> mExcludedHostsForHTTPSRRUpgrade;

View file

@ -208,8 +208,8 @@ nsresult nsHttpTransaction::Init(
if (NS_FAILED(rv)) return rv;
mConnInfo = cinfo;
mFinalizedConnInfo = cinfo;
mConnInfo = cinfo->Clone();
mFinalizedConnInfo = mConnInfo;
mCallbacks = callbacks;
mConsumerTarget = target;
mCaps = caps;

View file

@ -4,7 +4,13 @@
# 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/.
DIRS += ["about", "data", "file"]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
DIRS += ["gio"]
DIRS += ["http", "res", "viewsource", "websocket", "webtransport"]
DIRS += [
"about",
"data",
"file",
"http",
"res",
"viewsource",
"websocket",
"webtransport",
]

View file

@ -9,6 +9,8 @@
#include "mozilla/BinarySearch.h"
#include "mozilla/Components.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/StaticMutex.h"
#include "nsThreadUtils.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Promise-inl.h"
#include "mozilla/ExtensionPolicyService.h"
@ -20,6 +22,7 @@
#include "mozilla/Omnijar.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/Try.h"
#include "FileDescriptorFile.h"
@ -385,9 +388,24 @@ NS_IMPL_RELEASE_INHERITED(ExtensionProtocolHandler, SubstitutingProtocolHandler)
already_AddRefed<ExtensionProtocolHandler>
ExtensionProtocolHandler::GetSingleton() {
static StaticMutex sMutex;
StaticMutexAutoLock lock(sMutex);
if (!sSingleton) {
sSingleton = new ExtensionProtocolHandler();
ClearOnShutdown(&sSingleton);
if (NS_IsMainThread()) {
sSingleton = new ExtensionProtocolHandler();
ClearOnShutdown(&sSingleton);
} else {
StaticMutexAutoUnlock unlock(sMutex);
RefPtr<nsIRunnable> r = NS_NewRunnableFunction(
"ExtensionProtocolHandler::GetSingleton", []() {
StaticMutexAutoLock lock(sMutex);
if (!sSingleton) {
sSingleton = new ExtensionProtocolHandler();
ClearOnShutdown(&sSingleton);
}
});
SyncRunnable::DispatchToThread(GetMainThreadSerialEventTarget(), r);
}
}
return do_AddRef(sSingleton);
}

View file

@ -6,6 +6,7 @@
#include "mozilla/ModuleUtils.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Omnijar.h"
#include "nsThreadUtils.h"
#include "MozSrcProtocolHandler.h"
@ -19,16 +20,31 @@ NS_IMPL_QUERY_INTERFACE(MozSrcProtocolHandler, nsISubstitutingProtocolHandler,
NS_IMPL_ADDREF_INHERITED(MozSrcProtocolHandler, SubstitutingProtocolHandler)
NS_IMPL_RELEASE_INHERITED(MozSrcProtocolHandler, SubstitutingProtocolHandler)
mozilla::StaticMutex MozSrcProtocolHandler::sMutex;
mozilla::StaticRefPtr<MozSrcProtocolHandler> MozSrcProtocolHandler::sSingleton;
already_AddRefed<MozSrcProtocolHandler> MozSrcProtocolHandler::GetSingleton() {
StaticMutexAutoLock lock(sMutex);
if (!sSingleton) {
RefPtr<MozSrcProtocolHandler> handler = new MozSrcProtocolHandler();
if (NS_WARN_IF(NS_FAILED(handler->Init()))) {
return nullptr;
}
sSingleton = handler;
ClearOnShutdown(&sSingleton);
auto prevent_shutdown_race = [] {
StaticMutexAutoLock lock(sMutex);
sSingleton = nullptr;
};
if (NS_IsMainThread()) {
RunOnShutdown(std::move(prevent_shutdown_race));
} else {
NS_DispatchToMainThread(NS_NewRunnableFunction(
"MozSrcProtocolHandler::RunOnShutdown",
[prevent_shutdown_race =
std::move(prevent_shutdown_race)]() mutable {
RunOnShutdown(std::move(prevent_shutdown_race));
}));
}
}
return do_AddRef(sSingleton);
}

View file

@ -8,6 +8,7 @@
#include "nsIProtocolHandler.h"
#include "nsISubstitutingProtocolHandler.h"
#include "mozilla/StaticMutex.h"
#include "SubstitutingProtocolHandler.h"
namespace mozilla {
@ -37,7 +38,9 @@ class MozSrcProtocolHandler final : public nsISubstitutingProtocolHandler,
nsIURI** aResult) override;
private:
static mozilla::StaticRefPtr<MozSrcProtocolHandler> sSingleton;
static mozilla::StaticMutex sMutex;
static mozilla::StaticRefPtr<MozSrcProtocolHandler> sSingleton
MOZ_GUARDED_BY(sMutex);
nsresult Init();
nsCString mGREURI;

View file

@ -27,6 +27,7 @@ using mozilla::dom::ContentParent;
mozilla::StaticRefPtr<nsResProtocolHandler> nsResProtocolHandler::sSingleton;
already_AddRefed<nsResProtocolHandler> nsResProtocolHandler::GetSingleton() {
MOZ_ASSERT(NS_IsMainThread() || sSingleton);
if (!sSingleton) {
RefPtr<nsResProtocolHandler> handler = new nsResProtocolHandler();
if (NS_WARN_IF(NS_FAILED(handler->Init()))) {

View file

@ -29,20 +29,20 @@ NS_IMPL_ADDREF(WebSocketChannelChild)
NS_IMETHODIMP_(MozExternalRefCountType) WebSocketChannelChild::Release() {
MOZ_ASSERT(0 != mRefCnt, "dup release");
--mRefCnt;
nsrefcnt count = --mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "WebSocketChannelChild");
if (mRefCnt == 1) {
if (count == 1) {
MaybeReleaseIPCObject();
return mRefCnt;
}
if (mRefCnt == 0) {
if (count == 0) {
mRefCnt = 1; /* stabilize */
delete this;
return 0;
}
return mRefCnt;
return count;
}
NS_INTERFACE_MAP_BEGIN(WebSocketChannelChild)
@ -95,15 +95,6 @@ void WebSocketChannelChild::ReleaseIPDLReference() {
}
void WebSocketChannelChild::MaybeReleaseIPCObject() {
{
MutexAutoLock lock(mMutex);
if (mIPCState != Opened) {
return;
}
mIPCState = Closing;
}
if (!NS_IsMainThread()) {
nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
MOZ_ALWAYS_SUCCEEDS(target->Dispatch(
@ -113,6 +104,15 @@ void WebSocketChannelChild::MaybeReleaseIPCObject() {
return;
}
{
MutexAutoLock lock(mMutex);
if (mIPCState != Opened) {
return;
}
mIPCState = Closing;
}
SendDeleteSelf();
}

View file

@ -220,17 +220,29 @@ WebTransportSessionProxy::CloseSession(uint32_t status,
case WebTransportSessionProxyState::INIT:
case WebTransportSessionProxyState::DONE:
return NS_ERROR_NOT_INITIALIZED;
case WebTransportSessionProxyState::NEGOTIATING:
mChannel->Cancel(NS_ERROR_ABORT);
case WebTransportSessionProxyState::NEGOTIATING: {
nsCOMPtr<nsIChannel> channel = mChannel;
mChannel = nullptr;
ChangeState(WebTransportSessionProxyState::DONE);
NS_DispatchToMainThread(NS_NewRunnableFunction(
"WebTransportSessionProxy::CancelChannel",
[channel = std::move(channel)]() {
channel->Cancel(NS_ERROR_ABORT);
}));
break;
case WebTransportSessionProxyState::NEGOTIATING_SUCCEEDED:
mChannel->Cancel(NS_ERROR_ABORT);
}
case WebTransportSessionProxyState::NEGOTIATING_SUCCEEDED: {
nsCOMPtr<nsIChannel> channel = mChannel;
mChannel = nullptr;
ChangeState(WebTransportSessionProxyState::SESSION_CLOSE_PENDING);
NS_DispatchToMainThread(NS_NewRunnableFunction(
"WebTransportSessionProxy::CancelChannel",
[channel = std::move(channel)]() {
channel->Cancel(NS_ERROR_ABORT);
}));
CloseSessionInternal();
break;
}
case WebTransportSessionProxyState::ACTIVE:
ChangeState(WebTransportSessionProxyState::SESSION_CLOSE_PENDING);
CloseSessionInternal();