Bug 1380186 implement SimpleChannel Parent/Child IPC, r=kmag,mayhemer

MozReview-Commit-ID: 8zgF2MLwdu2

--HG--
extra : rebase_source : a5adcddb0119b8308a7beef74df998263dc8b620
This commit is contained in:
Shane Caraveo 2017-07-27 13:34:54 -07:00
parent 02063c6559
commit 824d3d0d57
12 changed files with 336 additions and 8 deletions

View File

@ -3,10 +3,20 @@
* 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 "SimpleChannel.h"
#include "nsBaseChannel.h"
#include "nsIChannel.h"
#include "nsIChildChannel.h"
#include "nsIInputStream.h"
#include "nsIRequest.h"
#include "SimpleChannel.h"
#include "nsISupportsImpl.h"
#include "nsNetUtil.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/PSimpleChannelChild.h"
namespace mozilla {
namespace net {
@ -22,7 +32,8 @@ namespace net {
(target) = result.unwrap(); \
} while (0)
class SimpleChannel final : public nsBaseChannel
class SimpleChannel : public nsBaseChannel
{
public:
explicit SimpleChannel(UniquePtr<SimpleChannelCallbacks>&& aCallbacks);
@ -78,10 +89,96 @@ SimpleChannel::BeginAsyncRead(nsIStreamListener* listener, nsIRequest** request)
#undef TRY_VAR
class SimpleChannelChild final : public SimpleChannel
, public nsIChildChannel
, public PSimpleChannelChild
{
public:
explicit SimpleChannelChild(UniquePtr<SimpleChannelCallbacks>&& aCallbacks);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICHILDCHANNEL
protected:
virtual void ActorDestroy(ActorDestroyReason why) override;
private:
virtual ~SimpleChannelChild() = default;
void AddIPDLReference();
RefPtr<SimpleChannelChild> mIPDLRef;
};
NS_IMPL_ISUPPORTS_INHERITED(SimpleChannelChild, SimpleChannel, nsIChildChannel)
SimpleChannelChild::SimpleChannelChild(UniquePtr<SimpleChannelCallbacks>&& aCallbacks)
: SimpleChannel(Move(aCallbacks))
, mIPDLRef(nullptr)
{
}
NS_IMETHODIMP
SimpleChannelChild::ConnectParent(uint32_t aId)
{
MOZ_ASSERT(NS_IsMainThread());
mozilla::dom::ContentChild* cc =
static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager());
if (cc->IsShuttingDown()) {
return NS_ERROR_FAILURE;
}
if (!gNeckoChild->SendPSimpleChannelConstructor(this, aId)) {
return NS_ERROR_FAILURE;
}
// IPC now has a ref to us.
mIPDLRef = this;
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelChild::CompleteRedirectSetup(nsIStreamListener* aListener,
nsISupports* aContext)
{
if (mIPDLRef) {
MOZ_ASSERT(NS_IsMainThread());
}
nsresult rv;
if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
MOZ_ASSERT(!aContext, "aContext should be null!");
rv = AsyncOpen2(aListener);
} else {
rv = AsyncOpen(aListener, aContext);
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mIPDLRef) {
Unused << Send__delete__(this);
}
return NS_OK;
}
void
SimpleChannelChild::ActorDestroy(ActorDestroyReason why)
{
MOZ_ASSERT(mIPDLRef);
mIPDLRef = nullptr;
}
already_AddRefed<nsIChannel>
NS_NewSimpleChannelInternal(nsIURI* aURI, nsILoadInfo* aLoadInfo, UniquePtr<SimpleChannelCallbacks>&& aCallbacks)
{
RefPtr<SimpleChannel> chan = new SimpleChannel(Move(aCallbacks));
RefPtr<SimpleChannel> chan;
if (IsNeckoChild()) {
chan = new SimpleChannelChild(Move(aCallbacks));
} else {
chan = new SimpleChannel(Move(aCallbacks));
}
chan->SetURI(aURI);

View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 sw=4 sts=4 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 "SimpleChannelParent.h"
#include "mozilla/Assertions.h"
#include "nsNetUtil.h"
#include "nsIChannel.h"
namespace mozilla {
namespace net {
NS_IMPL_ISUPPORTS(SimpleChannelParent, nsIParentChannel, nsIStreamListener)
bool
SimpleChannelParent::Init(const uint32_t &channelId)
{
nsCOMPtr<nsIChannel> channel;
MOZ_ALWAYS_SUCCEEDS(
NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel)));
return true;
}
NS_IMETHODIMP
SimpleChannelParent::SetParentListener(HttpChannelParentListener* aListener)
{
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelParent::NotifyTrackingProtectionDisabled()
{
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelParent::NotifyTrackingResource()
{
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
const nsACString& aProvider,
const nsACString& aPrefix)
{
// nothing to do
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelParent::Delete()
{
// Nothing to do.
return NS_OK;
}
void
SimpleChannelParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
NS_IMETHODIMP
SimpleChannelParent::OnStartRequest(nsIRequest* aRequest,
nsISupports* aContext)
{
// We don't have a way to prevent nsBaseChannel from calling AsyncOpen on
// the created nsSimpleChannel. We don't have anywhere to send the data in the
// parent, so abort the binding.
return NS_BINDING_ABORTED;
}
NS_IMETHODIMP
SimpleChannelParent::OnStopRequest(nsIRequest* aRequest,
nsISupports* aContext,
nsresult aStatusCode)
{
// See above.
MOZ_ASSERT(NS_FAILED(aStatusCode));
return NS_OK;
}
NS_IMETHODIMP
SimpleChannelParent::OnDataAvailable(nsIRequest* aRequest,
nsISupports* aContext,
nsIInputStream* aInputStream,
uint64_t aOffset,
uint32_t aCount)
{
// See above.
MOZ_CRASH("Should never be called");
}
} // namespace net
} // namespace mozilla

View File

@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 sw=4 sts=4 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_SIMPLECHANNELPARENT_H
#define NS_SIMPLECHANNELPARENT_H
#include "nsIParentChannel.h"
#include "nsISupportsImpl.h"
#include "mozilla/net/PSimpleChannelParent.h"
namespace mozilla {
namespace net {
// In order to support HTTP redirects, we need to implement the HTTP
// redirection API, which requires a class that implements nsIParentChannel
// and which calls NS_LinkRedirectChannels.
class SimpleChannelParent : public nsIParentChannel
, public PSimpleChannelParent
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPARENTCHANNEL
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
MOZ_MUST_USE bool Init(const uint32_t& aArgs);
private:
~SimpleChannelParent() = default;
virtual void ActorDestroy(ActorDestroyReason why) override;
};
} // namespace net
} // namespace mozilla
#endif /* NS_SIMPLECHANNELPARENT_H */

View File

@ -179,6 +179,7 @@ EXPORTS.mozilla.net += [
'MemoryDownloader.h',
'Predictor.h',
'ReferrerPolicy.h',
'SimpleChannelParent.h',
'TCPFastOpen.h',
]
@ -249,6 +250,7 @@ UNIFIED_SOURCES += [
'RequestContextService.cpp',
'SimpleBuffer.cpp',
'SimpleChannel.cpp',
'SimpleChannelParent.cpp',
'StreamingProtocolService.cpp',
'TCPFastOpenLayer.cpp',
'ThrottleQueue.cpp',

View File

@ -261,6 +261,20 @@ NeckoChild::DeallocPFileChannelChild(PFileChannelChild* child)
return true;
}
PSimpleChannelChild*
NeckoChild::AllocPSimpleChannelChild(const uint32_t& channelId)
{
MOZ_ASSERT_UNREACHABLE("Should never get here");
return nullptr;
}
bool
NeckoChild::DeallocPSimpleChannelChild(PSimpleChannelChild* child)
{
// NB: See SimpleChannelChild::ActorDestroy.
return true;
}
PRtspControllerChild*
NeckoChild::AllocPRtspControllerChild()
{

View File

@ -71,6 +71,8 @@ protected:
virtual bool DeallocPDataChannelChild(PDataChannelChild* child) override;
virtual PFileChannelChild* AllocPFileChannelChild(const uint32_t& channelId) override;
virtual bool DeallocPFileChannelChild(PFileChannelChild* child) override;
virtual PSimpleChannelChild* AllocPSimpleChannelChild(const uint32_t& channelId) override;
virtual bool DeallocPSimpleChannelChild(PSimpleChannelChild* child) override;
virtual PRtspControllerChild* AllocPRtspControllerChild() override;
virtual bool DeallocPRtspControllerChild(PRtspControllerChild*) override;
virtual PRtspChannelChild*

View File

@ -18,6 +18,7 @@
#include "mozilla/net/WebSocketChannelParent.h"
#include "mozilla/net/WebSocketEventListenerParent.h"
#include "mozilla/net/DataChannelParent.h"
#include "mozilla/net/SimpleChannelParent.h"
#include "mozilla/net/AltDataOutputStreamParent.h"
#include "mozilla/Unused.h"
#include "mozilla/net/FileChannelParent.h"
@ -530,6 +531,29 @@ NeckoParent::RecvPDataChannelConstructor(PDataChannelParent* actor,
return IPC_OK();
}
PSimpleChannelParent*
NeckoParent::AllocPSimpleChannelParent(const uint32_t &channelId)
{
RefPtr<SimpleChannelParent> p = new SimpleChannelParent();
return p.forget().take();
}
bool
NeckoParent::DeallocPSimpleChannelParent(PSimpleChannelParent* actor)
{
RefPtr<SimpleChannelParent> p = dont_AddRef(actor).downcast<SimpleChannelParent>();
return true;
}
mozilla::ipc::IPCResult
NeckoParent::RecvPSimpleChannelConstructor(PSimpleChannelParent* actor,
const uint32_t& channelId)
{
SimpleChannelParent* p = static_cast<SimpleChannelParent*>(actor);
MOZ_ALWAYS_TRUE(p->Init(channelId));
return IPC_OK();
}
PFileChannelParent*
NeckoParent::AllocPFileChannelParent(const uint32_t &channelId)
{

View File

@ -182,6 +182,13 @@ protected:
virtual mozilla::ipc::IPCResult RecvPDataChannelConstructor(PDataChannelParent* aActor,
const uint32_t& channelId) override;
virtual PSimpleChannelParent*
AllocPSimpleChannelParent(const uint32_t& channelId) override;
virtual bool DeallocPSimpleChannelParent(PSimpleChannelParent* parent) override;
virtual mozilla::ipc::IPCResult RecvPSimpleChannelConstructor(PSimpleChannelParent* aActor,
const uint32_t& channelId) override;
virtual PFileChannelParent*
AllocPFileChannelParent(const uint32_t& channelId) override;
virtual bool DeallocPFileChannelParent(PFileChannelParent* parent) override;

View File

@ -20,6 +20,7 @@ include protocol PDNSRequest;
include protocol PChannelDiverter;
include protocol PFileDescriptorSet;
include protocol PDataChannel;
include protocol PSimpleChannel;
include protocol PTransportProvider;
include protocol PChildToParentStream; //FIXME: bug #792908
include protocol PParentToChildStream; //FIXME: bug #792908
@ -56,6 +57,7 @@ nested(upto inside_cpow) sync protocol PNecko
manages PUDPSocket;
manages PDNSRequest;
manages PDataChannel;
manages PSimpleChannel;
manages PFileChannel;
manages PRtspController;
manages PRtspChannel;
@ -104,7 +106,7 @@ parent:
* the parent and the child when we're redirecting to a data: URI.
*/
async PDataChannel(uint32_t channelId);
async PSimpleChannel(uint32_t channelId);
async PFileChannel(uint32_t channelId);
async PRtspController();

View File

@ -0,0 +1,25 @@
/* -*- 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;
namespace mozilla {
namespace net {
async protocol PSimpleChannel
{
manager PNecko;
parent:
// Note: channels are opened during construction, so no open method here:
// see PNecko.ipdl
async __delete__();
};
} // namespace net
} // namespace mozilla

View File

@ -29,6 +29,7 @@ IPDL_SOURCES = [
'PNecko.ipdl',
'PRtspChannel.ipdl',
'PRtspController.ipdl',
'PSimpleChannel.ipdl',
]
# needed so --disable-webrtc builds work (yes, a bit messy)

View File

@ -55,6 +55,12 @@ function getData(channel) {
return extractFromChannel(channel, key) || attachToChannel(channel, key, {});
}
function getFinalChannelURI(channel) {
let {loadInfo} = channel;
// resultPrincipalURI may be null, but originalURI never will be.
return (loadInfo && loadInfo.resultPrincipalURI) || channel.originalURI;
}
var RequestId = {
count: 1,
create(channel = null) {
@ -753,9 +759,10 @@ HttpObserverManager = {
getRequestData(channel, loadContext, policyType, extraData) {
let {loadInfo} = channel;
let URI = getFinalChannelURI(channel);
let data = {
requestId: RequestId.get(channel),
url: channel.URI.spec,
url: URI.spec,
method: channel.requestMethod,
browser: loadContext && loadContext.topFrameElement,
type: WebRequestCommon.typeForPolicyType(policyType),
@ -831,7 +838,10 @@ HttpObserverManager = {
canModify(channel) {
let {isHostPermitted} = AddonManagerPermissions;
if (isHostPermitted(channel.URI.host)) {
// Bug 1334550 introduced the possibility of having a JAR uri here,
// use the result uri if possible in that case.
let URI = getFinalChannelURI(channel);
if (URI && isHostPermitted(URI.host)) {
return false;
}
@ -872,7 +882,7 @@ HttpObserverManager = {
let canModify = this.canModify(channel);
let commonData = null;
let uri = channel.URI;
let uri = getFinalChannelURI(channel);
let requestBody;
for (let [callback, opts] of this.listeners[kind].entries()) {
if (!this.shouldRunListener(policyType, uri, opts.filter)) {
@ -1055,8 +1065,10 @@ HttpObserverManager = {
},
onChannelReplaced(oldChannel, newChannel) {
// We want originalURI, this will provide a moz-ext rather than jar or file
// uri on redirects.
this.runChannelListener(oldChannel, this.getLoadContext(oldChannel),
"onRedirect", {redirectUrl: newChannel.URI.spec});
"onRedirect", {redirectUrl: newChannel.originalURI.spec});
},
onStartRequest(channel, loadContext) {