fune/netwerk/protocol/gio/GIOChannelChild.cpp
Valentin Gosu 1a1f42da37 Bug 1714307 - Run modernize-use-default-member-init --fix check on netwerk r=necko-reviewers,kershaw
This changeset is the result of adding modernize-use-default-member-init to
tools/clang-tidy/config.yaml then proceeding to run
`./mach static-analysis check netwerk/ --fix`
I then went through the resulting fix and manually updated all of the member
variables which were missed due to them having a non-trivial constructor.

Note that the tool was only run on Linux, so code that only runs on some
platforms may have been missed.

The member variables that are still initialized in the contructor definition
are:
  - bitfields (not all currently supported compilers allow default-member-init
  - variables that are initialized via a parameter
  - variables that use code not visible in the header file

There are a few advantages to landing this change:
- fewer lines of code - now declaration is in the same place as initialization
  this also makes it easier to see when looking at the header.
- it makes it harder to miss initializing a member when adding a new contructor
- variables that depend on an include guard look much nicer now

Additionally I removed some unnecessary reinitialization of NetAddr members
(it has a constructor that does that now), and changed nsWifiScannerDBus to
use the thread-safe strtok_r instead of strtok.

Differential Revision: https://phabricator.services.mozilla.com/D116980
2021-06-11 07:10:41 +00:00

462 lines
14 KiB
C++

/* -*- 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 "base/compiler_specific.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);
}
mozilla::ipc::AutoIPCStream autoStream;
autoStream.Serialize(mUploadStream,
static_cast<ContentChild*>(gNeckoChild->Manager()));
uint32_t loadFlags = 0;
GetLoadFlags(&loadFlags);
GIOChannelOpenArgs openArgs;
SerializeURI(nsBaseChannel::URI(), openArgs.uri());
openArgs.startPos() = mStartPos;
openArgs.entityID() = mEntityID;
openArgs.uploadStream() = autoStream.TakeOptionalValue();
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();
gNeckoChild->SendPGIOChannelConstructor(
this, browserChild, IPC::SerializedLoadContext(this), openArgs);
// The socket transport layer in the chrome process now has a logical ref to
// us until OnStopRequest is called.
AddIPDLReference();
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 nsCString& aContentType, const nsCString& aEntityID,
const URIParams& aURI) {
LOG(("GIOChannelChild::RecvOnStartRequest [this=%p]\n", this));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<GIOChannelChild>(this), aChannelStatus,
aContentLength, aContentType, aEntityID, aURI]() {
self->DoOnStartRequest(aChannelStatus, aContentLength, aContentType,
aEntityID, aURI);
}));
return IPC_OK();
}
void GIOChannelChild::DoOnStartRequest(const nsresult& aChannelStatus,
const int64_t& aContentLength,
const nsCString& aContentType,
const nsCString& 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 nsCString& 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,
aOffset, aCount]() {
self->DoOnDataAvailable(aChannelStatus, aData, aOffset, aCount);
}));
return IPC_OK();
}
void GIOChannelChild::DoOnDataAvailable(const nsresult& aChannelStatus,
const nsCString& 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;
}
nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
mNeckoTarget =
nsContentUtils::GetEventTargetByLoadInfo(loadInfo, TaskCategory::Network);
if (!mNeckoTarget) {
return;
}
gNeckoChild->SetEventTargetForActor(this, mNeckoTarget);
}
} // namespace net
} // namespace mozilla