Bug 1345094 - make http redirects to file:// uris work under e10s. r?mayhemer
MozReview-Commit-ID: J4IheswoeMZ
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -228,16 +228,30 @@ NeckoChild::AllocPDataChannelChild(const
bool
NeckoChild::DeallocPDataChannelChild(PDataChannelChild* child)
{
// NB: See DataChannelChild::ActorDestroy.
return true;
}
+PFileChannelChild*
+NeckoChild::AllocPFileChannelChild(const uint32_t& channelId)
+{
+ MOZ_ASSERT_UNREACHABLE("Should never get here");
+ return nullptr;
+}
+
+bool
+NeckoChild::DeallocPFileChannelChild(PFileChannelChild* child)
+{
+ // NB: See FileChannelChild::ActorDestroy.
+ return true;
+}
+
PRtspControllerChild*
NeckoChild::AllocPRtspControllerChild()
{
NS_NOTREACHED("AllocPRtspController should not be called");
return nullptr;
}
bool
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -64,16 +64,18 @@ protected:
virtual bool DeallocPUDPSocketChild(PUDPSocketChild*) override;
virtual PDNSRequestChild* AllocPDNSRequestChild(const nsCString& aHost,
const OriginAttributes& aOriginAttributes,
const uint32_t& aFlags,
const nsCString& aNetworkInterface) override;
virtual bool DeallocPDNSRequestChild(PDNSRequestChild*) override;
virtual PDataChannelChild* AllocPDataChannelChild(const uint32_t& channelId) override;
virtual bool DeallocPDataChannelChild(PDataChannelChild* child) override;
+ virtual PFileChannelChild* AllocPFileChannelChild(const uint32_t& channelId) override;
+ virtual bool DeallocPFileChannelChild(PFileChannelChild* child) override;
virtual PRtspControllerChild* AllocPRtspControllerChild() override;
virtual bool DeallocPRtspControllerChild(PRtspControllerChild*) override;
virtual PRtspChannelChild*
AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs)
override;
virtual bool DeallocPRtspChannelChild(PRtspChannelChild*) override;
virtual PChannelDiverterChild*
AllocPChannelDiverterChild(const ChannelDiverterArgs& channel) override;
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -13,16 +13,17 @@
#include "mozilla/net/CookieServiceParent.h"
#include "mozilla/net/WyciwygChannelParent.h"
#include "mozilla/net/FTPChannelParent.h"
#include "mozilla/net/WebSocketChannelParent.h"
#include "mozilla/net/WebSocketEventListenerParent.h"
#include "mozilla/net/DataChannelParent.h"
#include "mozilla/net/AltDataOutputStreamParent.h"
#include "mozilla/Unused.h"
+#include "mozilla/net/FileChannelParent.h"
#ifdef NECKO_PROTOCOL_rtsp
#include "mozilla/net/RtspControllerParent.h"
#include "mozilla/net/RtspChannelParent.h"
#endif
#include "mozilla/net/DNSRequestParent.h"
#include "mozilla/net/ChannelDiverterParent.h"
#include "mozilla/net/IPCTransportProvider.h"
#ifdef MOZ_WEBRTC
@@ -520,16 +521,40 @@ NeckoParent::RecvPDataChannelConstructor
const uint32_t& channelId)
{
DataChannelParent* p = static_cast<DataChannelParent*>(actor);
DebugOnly<bool> rv = p->Init(channelId);
MOZ_ASSERT(rv);
return IPC_OK();
}
+PFileChannelParent*
+NeckoParent::AllocPFileChannelParent(const uint32_t &channelId)
+{
+ RefPtr<FileChannelParent> p = new FileChannelParent();
+ return p.forget().take();
+}
+
+bool
+NeckoParent::DeallocPFileChannelParent(PFileChannelParent* actor)
+{
+ RefPtr<FileChannelParent> p = dont_AddRef(static_cast<FileChannelParent*>(actor));
+ return true;
+}
+
+mozilla::ipc::IPCResult
+NeckoParent::RecvPFileChannelConstructor(PFileChannelParent* actor,
+ const uint32_t& channelId)
+{
+ FileChannelParent* p = static_cast<FileChannelParent*>(actor);
+ DebugOnly<bool> rv = p->Init(channelId);
+ MOZ_ASSERT(rv);
+ return IPC_OK();
+}
+
PRtspControllerParent*
NeckoParent::AllocPRtspControllerParent()
{
#ifdef NECKO_PROTOCOL_rtsp
RtspControllerParent* p = new RtspControllerParent();
p->AddRef();
return p;
#else
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -178,16 +178,23 @@ protected:
virtual PDataChannelParent*
AllocPDataChannelParent(const uint32_t& channelId) override;
virtual bool DeallocPDataChannelParent(PDataChannelParent* parent) override;
virtual mozilla::ipc::IPCResult RecvPDataChannelConstructor(PDataChannelParent* aActor,
const uint32_t& channelId) override;
+ virtual PFileChannelParent*
+ AllocPFileChannelParent(const uint32_t& channelId) override;
+ virtual bool DeallocPFileChannelParent(PFileChannelParent* parent) override;
+
+ virtual mozilla::ipc::IPCResult RecvPFileChannelConstructor(PFileChannelParent* aActor,
+ const uint32_t& channelId) override;
+
virtual PRtspControllerParent* AllocPRtspControllerParent() override;
virtual bool DeallocPRtspControllerParent(PRtspControllerParent*) override;
virtual PRtspChannelParent*
AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs)
override;
virtual mozilla::ipc::IPCResult
RecvPRtspChannelConstructor(PRtspChannelParent* aActor,
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/PFileChannel.ipdl
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 sts=2 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 {
+
+/* Used to facilitate http redirects to file:// - see
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=1345094
+ */
+async protocol PFileChannel
+{
+ manager PNecko;
+
+parent:
+ // Note: channels are opened during construction, so no open method here:
+ // see PNecko.ipdl
+ async __delete__();
+};
+
+} // namespace net
+} // namespace mozilla
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -20,16 +20,17 @@ include protocol PDNSRequest;
include protocol PChannelDiverter;
include protocol PBlob; //FIXME: bug #792908
include protocol PFileDescriptorSet;
include protocol PDataChannel;
include protocol PTransportProvider;
include protocol PChildToParentStream; //FIXME: bug #792908
include protocol PParentToChildStream; //FIXME: bug #792908
include protocol PStunAddrsRequest;
+include protocol PFileChannel;
include protocol PRtspController;
include protocol PRtspChannel;
include URIParams;
include NeckoChannelParams;
include PBrowserOrId;
include protocol PAltDataOutputStream;
@@ -50,16 +51,17 @@ nested(upto inside_cpow) sync protocol P
manages PFTPChannel;
manages PWebSocket;
manages PWebSocketEventListener;
manages PTCPSocket;
manages PTCPServerSocket;
manages PUDPSocket;
manages PDNSRequest;
manages PDataChannel;
+ manages PFileChannel;
manages PRtspController;
manages PRtspChannel;
manages PChannelDiverter;
manages PTransportProvider;
manages PAltDataOutputStream;
manages PStunAddrsRequest;
parent:
@@ -98,16 +100,18 @@ parent:
uint16_t flags, nsresult reason);
/**
* channelId is used to establish a connection between redirect channels in
* the parent and the child when we're redirecting to a data: URI.
*/
async PDataChannel(uint32_t channelId);
+ async PFileChannel(uint32_t channelId);
+
async PRtspController();
async PRtspChannel(RtspChannelConnectArgs args);
async PChannelDiverter(ChannelDiverterArgs channel);
/**
* These are called from the child with the results of the auth prompt.
* callbackId is the id that was passed in PBrowser::AsyncAuthPrompt,
* corresponding to an nsIAuthPromptCallback
--- a/netwerk/ipc/moz.build
+++ b/netwerk/ipc/moz.build
@@ -18,16 +18,17 @@ UNIFIED_SOURCES += [
'NeckoCommon.cpp',
'NeckoParent.cpp',
]
IPDL_SOURCES = [
'NeckoChannelParams.ipdlh',
'PChannelDiverter.ipdl',
'PDataChannel.ipdl',
+ 'PFileChannel.ipdl',
'PNecko.ipdl',
'PRtspChannel.ipdl',
'PRtspController.ipdl',
]
# needed so --disable-webrtc builds work (yes, a bit messy)
if not CONFIG['MOZ_WEBRTC']:
IPDL_SOURCES += [
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/file/FileChannelChild.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 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 "FileChannelChild.h"
+
+#include "mozilla/Unused.h"
+#include "mozilla/net/NeckoChild.h"
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS_INHERITED(FileChannelChild, nsFileChannel, nsIChildChannel)
+
+FileChannelChild::FileChannelChild(nsIURI *uri)
+ : nsFileChannel(uri)
+ , mIPCOpen(false)
+{
+}
+
+NS_IMETHODIMP
+FileChannelChild::ConnectParent(uint32_t id)
+{
+ if (!gNeckoChild->SendPFileChannelConstructor(this, id)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ AddIPDLReference();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileChannelChild::CompleteRedirectSetup(nsIStreamListener *listener,
+ nsISupports *ctx)
+{
+ nsresult rv;
+
+ if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+ MOZ_ASSERT(!ctx, "Context should be null");
+ rv = AsyncOpen2(listener);
+ } else {
+ rv = AsyncOpen(listener, ctx);
+ }
+
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (mIPCOpen) {
+ Unused << Send__delete__(this);
+ }
+
+ return NS_OK;
+}
+
+void
+FileChannelChild::AddIPDLReference()
+{
+ AddRef();
+ mIPCOpen = true;
+}
+
+void
+FileChannelChild::ActorDestroy(ActorDestroyReason why)
+{
+ MOZ_ASSERT(mIPCOpen);
+ mIPCOpen = false;
+ Release();
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/file/FileChannelChild.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 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 mozilla__net__FileChannelChild_h
+#define mozilla__net__FileChannelChild_h
+
+#include "nsFileChannel.h"
+#include "nsIChildChannel.h"
+#include "nsISupportsImpl.h"
+
+#include "mozilla/net/PFileChannelChild.h"
+
+namespace mozilla {
+namespace net {
+
+class FileChannelChild : public nsFileChannel
+ , public nsIChildChannel
+ , public PFileChannelChild
+{
+public:
+ explicit FileChannelChild(nsIURI *uri);
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSICHILDCHANNEL
+
+protected:
+ virtual void ActorDestroy(ActorDestroyReason why) override;
+
+private:
+ ~FileChannelChild() { };
+
+ void AddIPDLReference();
+
+ bool mIPCOpen;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif /* mozilla__net__FileChannelChild_h */
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/file/FileChannelParent.cpp
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 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 "FileChannelParent.h"
+#include "mozilla/Assertions.h"
+#include "nsNetUtil.h"
+#include "nsIChannel.h"
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS(FileChannelParent, nsIParentChannel, nsIStreamListener)
+
+FileChannelParent::~FileChannelParent()
+{
+}
+
+bool
+FileChannelParent::Init(const uint32_t &channelId)
+{
+ nsCOMPtr<nsIChannel> channel;
+ MOZ_ALWAYS_SUCCEEDS(
+ NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel)));
+
+ return true;
+}
+
+NS_IMETHODIMP
+FileChannelParent::SetParentListener(HttpChannelParentListener* aListener)
+{
+ // Nothing to do.
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileChannelParent::NotifyTrackingProtectionDisabled()
+{
+ // Nothing to do.
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileChannelParent::NotifyTrackingResource()
+{
+ // Nothing to do.
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
+ const nsACString& aProvider,
+ const nsACString& aPrefix)
+{
+ // nothing to do
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileChannelParent::Delete()
+{
+ // Nothing to do.
+ return NS_OK;
+}
+
+void
+FileChannelParent::ActorDestroy(ActorDestroyReason why)
+{
+}
+
+NS_IMETHODIMP
+FileChannelParent::OnStartRequest(nsIRequest *aRequest,
+ nsISupports *aContext)
+{
+ // We don't have a way to prevent nsBaseChannel from calling AsyncOpen on
+ // the created nsDataChannel. We don't have anywhere to send the data in the
+ // parent, so abort the binding.
+ return NS_BINDING_ABORTED;
+}
+
+NS_IMETHODIMP
+FileChannelParent::OnStopRequest(nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsresult aStatusCode)
+{
+ // See above.
+ MOZ_ASSERT(NS_FAILED(aStatusCode));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileChannelParent::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
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/file/FileChannelParent.h
@@ -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 mozilla__net__FileChannelParent_h
+#define mozilla__net__FileChannelParent_h
+
+#include "nsIParentChannel.h"
+#include "nsISupportsImpl.h"
+
+#include "mozilla/net/PFileChannelParent.h"
+
+namespace mozilla {
+namespace net {
+
+// In order to support HTTP redirects to file:, we need to implement the HTTP
+// redirection API, which requires a class that implements nsIParentChannel
+// and which calls NS_LinkRedirectChannels.
+class FileChannelParent : public nsIParentChannel
+ , public PFileChannelParent
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPARENTCHANNEL
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+
+ MOZ_MUST_USE bool Init(const uint32_t& aArgs);
+
+private:
+ ~FileChannelParent();
+
+ virtual void ActorDestroy(ActorDestroyReason why) override;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif /* mozilla__net__FileChannelParent_h */
--- a/netwerk/protocol/file/moz.build
+++ b/netwerk/protocol/file/moz.build
@@ -3,31 +3,36 @@
# 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/.
with Files('**'):
BUG_COMPONENT = ('Core', 'Networking: File')
EXPORTS.mozilla.net += [
+ 'FileChannelParent.h',
'nsFileProtocolHandler.h',
]
XPIDL_SOURCES += [
'nsIFileChannel.idl',
'nsIFileProtocolHandler.idl',
]
XPIDL_MODULE = 'necko_file'
UNIFIED_SOURCES += [
+ 'FileChannelChild.cpp',
+ 'FileChannelParent.cpp',
'nsFileChannel.cpp',
'nsFileProtocolHandler.cpp',
]
+include('/ipc/chromium/chromium-config.mozbuild')
+
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/netwerk/base',
]
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']
--- a/netwerk/protocol/file/nsFileProtocolHandler.cpp
+++ b/netwerk/protocol/file/nsFileProtocolHandler.cpp
@@ -7,16 +7,18 @@
#include "nsIFile.h"
#include "nsFileProtocolHandler.h"
#include "nsFileChannel.h"
#include "nsStandardURL.h"
#include "nsURLHelper.h"
#include "nsNetUtil.h"
+#include "FileChannelChild.h"
+
// URL file handling, copied and modified from xpfe/components/bookmarks/src/nsBookmarksService.cpp
#ifdef XP_WIN
#include <shlobj.h>
#include <intshcut.h>
#include "nsIFileURL.h"
#ifdef CompareString
#undef CompareString
#endif
@@ -183,17 +185,22 @@ nsFileProtocolHandler::NewURI(const nsAC
return CallQueryInterface(url, result);
}
NS_IMETHODIMP
nsFileProtocolHandler::NewChannel2(nsIURI* uri,
nsILoadInfo* aLoadInfo,
nsIChannel** result)
{
- nsFileChannel *chan = new nsFileChannel(uri);
+ nsFileChannel *chan;
+ if (IsNeckoChild()) {
+ chan = new mozilla::net::FileChannelChild(uri);
+ } else {
+ chan = new nsFileChannel(uri);
+ }
if (!chan)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(chan);
nsresult rv = chan->Init();
if (NS_FAILED(rv)) {
NS_RELEASE(chan);
return rv;