Bug 530952: Electrolysis HTTP Channel implementation. author=jduell, r=bsmedberg, sr=bz
- Supports only primitive xpcshell HTTP requests which don't set/get HTTP
headers, don't do redirects, observers, load groups, or anything else other
than basic things like looking at the reply body, Content-type, Content-length, etc.
- Tested with network/test/unit_ipc/test_simple_wrap.js (patch @
bug 521922)
- Only used if "NECKO_E10S_HTTP" set in environment.
- Force http.h to get #included before any IPDL files, to centralize #define
handling of LOG and to make sure FORCE_PR_LOGGING is set if needed (
bug
545995)
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -33,16 +33,17 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "necko-config.h"
#ifdef MOZ_IPC
+#define ALLOW_LATE_NSHTTP_H_INCLUDE 1
#include "base/basictypes.h"
#endif
#include "nsCOMPtr.h"
#include "nsIModule.h"
#include "nsIClassInfoImpl.h"
#include "nsIGenericFactory.h"
#include "nsIComponentManager.h"
--- a/netwerk/ipc/Makefile.in
+++ b/netwerk/ipc/Makefile.in
@@ -48,18 +48,24 @@ LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
EXPORTS_NAMESPACES = mozilla/net
EXPORTS_mozilla/net = \
NeckoParent.h \
NeckoChild.h \
+ NeckoCommon.h \
$(NULL)
CPPSRCS = \
NeckoChild.cpp \
NeckoParent.cpp \
$(NULL)
+LOCAL_INCLUDES += \
+ -I$(srcdir)/../protocol/http/src \
+ -I$(srcdir)/../base/src \
+ $(NULL)
+
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -33,16 +33,17 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+#include "nsHttp.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/dom/ContentProcessChild.h"
#include "mozilla/net/HttpChannelChild.h"
namespace mozilla {
namespace net {
PNeckoChild *gNeckoChild = nsnull;
@@ -53,32 +54,54 @@ NeckoChild::NeckoChild()
}
NeckoChild::~NeckoChild()
{
}
void NeckoChild::InitNeckoChild()
{
- if (XRE_GetProcessType() == GeckoProcessType_Content) {
+ NS_ABORT_IF_FALSE(IsNeckoChild(), "InitNeckoChild called by non-child!");
+
+ if (!gNeckoChild) {
mozilla::dom::ContentProcessChild * cpc =
mozilla::dom::ContentProcessChild::GetSingleton();
NS_ASSERTION(cpc, "Content Protocol is NULL!");
gNeckoChild = cpc->SendPNeckoConstructor();
NS_ASSERTION(gNeckoChild, "PNecko Protocol init failed!");
}
}
+// Note: not actually called; has some lifespan as child process, so
+// automatically destroyed at exit.
+void NeckoChild::DestroyNeckoChild()
+{
+ NS_ABORT_IF_FALSE(IsNeckoChild(), "DestroyNeckoChild called by non-child!");
+ static bool alreadyDestroyed = false;
+ NS_ABORT_IF_FALSE(!alreadyDestroyed, "DestroyNeckoChild already called!");
+
+ if (!alreadyDestroyed) {
+ Send__delete__(gNeckoChild);
+ gNeckoChild = nsnull;
+ alreadyDestroyed = true;
+ }
+}
+
PHttpChannelChild*
NeckoChild::AllocPHttpChannel()
{
- return new HttpChannelChild();
+ // We don't allocate here: see HttpChannelChild::AsyncOpen()
+ NS_RUNTIMEABORT("AllocPHttpChannel should not be called");
+ return nsnull;
}
bool
NeckoChild::DeallocPHttpChannel(PHttpChannelChild* channel)
{
- delete channel;
+ NS_ABORT_IF_FALSE(IsNeckoChild(), "DeallocPHttpChannel called by non-child!");
+
+ HttpChannelChild *p = static_cast<HttpChannelChild*>(channel);
+ p->Release();
return true;
}
}} // mozilla::net
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -37,46 +37,39 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_NeckoChild_h
#define mozilla_net_NeckoChild_h
#include "mozilla/net/PNeckoChild.h"
-#include "mozilla/net/HttpChannelChild.h"
-#include "nsXULAppAPI.h"
+#include "mozilla/net/NeckoCommon.h"
namespace mozilla {
namespace net {
// Header file contents
class NeckoChild :
public PNeckoChild
{
public:
NeckoChild();
virtual ~NeckoChild();
static void InitNeckoChild();
+ static void DestroyNeckoChild();
+protected:
virtual PHttpChannelChild* AllocPHttpChannel();
virtual bool DeallocPHttpChannel(PHttpChannelChild*);
-
-protected:
};
/**
* Reference to the PNecko Child protocol.
* Null if this is not a content process.
*/
extern PNeckoChild *gNeckoChild;
-static inline PRBool
-IsNeckoChild()
-{
- return XRE_GetProcessType() == GeckoProcessType_Content;
-}
-
} // namespace net
} // namespace mozilla
#endif // mozilla_net_NeckoChild_h
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/NeckoCommon.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jason Duell <jduell.mcbugs@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_net_NeckoCommon_h
+#define mozilla_net_NeckoCommon_h
+
+#include "nsXULAppAPI.h"
+
+// Temporary: use while we figure out which XPCOM interfaces (from list
+// copied from nsHttpChannel) HttpChannel{Child|Parent}, etc., actually need to
+// implement. I.e., implement interfaces as we need them, and if we never hit a
+// given interface, figure out if we can stop advertising it.
+
+#define DROP_DEAD() \
+ do { \
+ fprintf(stderr, \
+ "*&*&*&*&*&*&*&**&*&&*& FATAL ERROR: '%s' UNIMPLEMENTED: %s +%d", \
+ __FUNCTION__, __FILE__, __LINE__); \
+ NS_ABORT(); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+ } while (0)
+
+
+namespace mozilla {
+namespace net {
+
+inline bool
+IsNeckoChild()
+{
+ // TODO: remove env var check eventually.
+ // - For now: if unset, necko works with full stack in each process,
+ // i.e. no IPC.
+ static bool didCheck = false;
+ static bool amChild = false;
+
+ if (!didCheck) {
+ const char * e = PR_GetEnv("NECKO_E10S_HTTP");
+ if (e && *e)
+ amChild = (XRE_GetProcessType() == GeckoProcessType_Content);
+ didCheck = true;
+ }
+ return amChild;
+}
+
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_NeckoCommon_h
+
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -33,16 +33,17 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+#include "nsHttp.h"
#include "mozilla/net/NeckoParent.h"
#include "mozilla/net/HttpChannelParent.h"
namespace mozilla {
namespace net {
// C++ file contents
NeckoParent::NeckoParent()
@@ -51,21 +52,24 @@ NeckoParent::NeckoParent()
NeckoParent::~NeckoParent()
{
}
PHttpChannelParent*
NeckoParent::AllocPHttpChannel()
{
- return new HttpChannelParent();
+ HttpChannelParent *p = new HttpChannelParent();
+ p->AddRef();
+ return p;
}
bool
NeckoParent::DeallocPHttpChannel(PHttpChannelParent* channel)
{
- delete channel;
+ HttpChannelParent *p = static_cast<HttpChannelParent *>(channel);
+ p->Release();
return true;
}
}} // mozilla::net
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -34,17 +34,17 @@
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/net/PNeckoParent.h"
-#include "mozilla/net/HttpChannelChild.h"
+#include "mozilla/net/NeckoCommon.h"
#ifndef mozilla_net_NeckoParent_h
#define mozilla_net_NeckoParent_h
namespace mozilla {
namespace net {
// Header file contents
--- a/netwerk/protocol/http/src/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/src/HttpChannelChild.cpp
@@ -33,25 +33,1091 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+#include "nsHttp.h"
+#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/HttpChannelChild.h"
-#include "mozilla/dom/ContentProcessChild.h"
+
+#include "nsStringStream.h"
+#include "nsHttpHandler.h"
+#include "nsMimeTypes.h"
+#include "nsNetUtil.h"
+
+// - TODO: Can we add these checks to nsHttpChannel.cpp too?
+#define ENSURE_CALLED_BEFORE_ASYNC_OPEN() \
+ if (mIsPending) \
+ DROP_DEAD(); \
+ if (mWasOpened) \
+ DROP_DEAD(); \
+ NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); \
+ NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
+
namespace mozilla {
namespace net {
// C++ file contents
HttpChannelChild::HttpChannelChild()
+ : mState(HCC_NEW)
+ // FIELDS COPIED FROM nsHttpChannel.h
+ , mLoadFlags(LOAD_NORMAL)
+ , mStatus(NS_OK)
+ , mIsPending(PR_FALSE)
+ , mWasOpened(PR_FALSE)
{
+ LOG(("Creating HttpChannelChild @%x\n", this));
+
+ // grab a reference to the handler to ensure that it doesn't go away.
+ NS_ADDREF(gHttpHandler);
}
HttpChannelChild::~HttpChannelChild()
{
+ LOG(("Destroying HttpChannelChild @%x\n", this));
+
+ // release our reference to the handler
+ NS_RELEASE(gHttpHandler);
+}
+
+nsresult
+HttpChannelChild::Init(nsIURI *uri)
+{
+ /**
+ * COPIED from nsHttpChannel and tweaked: merge into base class?
+ */
+ LOG(("HttpChannelChild::Init [this=%x]\n", this));
+
+ NS_PRECONDITION(uri, "null uri");
+
+ nsresult rv = nsHashPropertyBag::Init();
+ if (NS_FAILED(rv))
+ return rv;
+
+ mURI = uri;
+ mOriginalURI = uri;
+ mDocumentURI = nsnull;
+// mCaps = caps;
+
+ //
+ // Construct connection info object
+ //
+ nsCAutoString host;
+ PRInt32 port = -1;
+ PRBool usingSSL = PR_FALSE;
+
+ rv = mURI->SchemeIs("https", &usingSSL);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mURI->GetAsciiHost(host);
+ if (NS_FAILED(rv)) return rv;
+
+ // reject the URL if it doesn't specify a host
+ if (host.IsEmpty())
+ return NS_ERROR_MALFORMED_URI;
+
+ rv = mURI->GetPort(&port);
+ if (NS_FAILED(rv)) return rv;
+
+ LOG(("host=%s port=%d\n", host.get(), port));
+
+ rv = mURI->GetAsciiSpec(mSpec);
+ if (NS_FAILED(rv)) return rv;
+ LOG(("uri=%s\n", mSpec.get()));
+
+#if 0
+ // Not yet clear that we need this in child
+ mConnectionInfo = new nsHttpConnectionInfo(host, port,
+ proxyInfo, usingSSL);
+ if (!mConnectionInfo)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(mConnectionInfo);
+#endif
+
+ // Set default request method
+ mRequestHead.SetMethod(nsHttp::Get);
+
+#if 0
+ // FIXME (bug 541017): split this out into a separate function so we can share
+ // with nsHttpChannel.
+ // - Make sure not to set any headers twice on parent.
+
+ //
+ // Set request headers
+ //
+ nsCAutoString hostLine;
+ if (strchr(host.get(), ':')) {
+ // host is an IPv6 address literal and must be encapsulated in []'s
+ hostLine.Assign('[');
+ // scope id is not needed for Host header.
+ int scopeIdPos = host.FindChar('%');
+ if (scopeIdPos == kNotFound)
+ hostLine.Append(host);
+ else if (scopeIdPos > 0)
+ hostLine.Append(Substring(host, 0, scopeIdPos));
+ else
+ return NS_ERROR_MALFORMED_URI;
+ hostLine.Append(']');
+ }
+ else
+ hostLine.Assign(host);
+ if (port != -1) {
+ hostLine.Append(':');
+ hostLine.AppendInt(port);
+ }
+
+ rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = gHttpHandler->
+ AddStandardRequestHeaders(&mRequestHead.Headers(), caps,
+ !mConnectionInfo->UsingSSL() &&
+ mConnectionInfo->UsingHttpProxy());
+#endif /* 0 */
+
+ return rv;
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsISupports
+//-----------------------------------------------------------------------------
+
+NS_IMPL_ADDREF_INHERITED(HttpChannelChild, nsHashPropertyBag)
+NS_IMPL_RELEASE_INHERITED(HttpChannelChild, nsHashPropertyBag)
+
+NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
+ NS_INTERFACE_MAP_ENTRY(nsIRequest)
+ NS_INTERFACE_MAP_ENTRY(nsIChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
+ NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+ NS_INTERFACE_MAP_ENTRY(nsICachingChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
+ NS_INTERFACE_MAP_ENTRY(nsICacheListener)
+ NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
+ NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
+ NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
+ NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)
+ NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
+ NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
+ NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIAuthPromptCallback)
+NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::PHttpChannelChild
+//-----------------------------------------------------------------------------
+
+bool
+HttpChannelChild::RecvOnStartRequest(const PRInt32& HACK_ContentLength,
+ const nsCString& HACK_ContentType,
+ const PRUint32& HACK_Status,
+ const nsCString& HACK_StatusText)
+{
+ LOG(("HttpChannelChild::RecvOnStartRequest [this=%x]\n", this));
+
+ mState = HCC_ONSTART;
+
+ mContentLength_HACK = HACK_ContentLength;
+ mContentType_HACK = HACK_ContentType;
+ mResponseStatus_HACK = HACK_Status;
+ mResponseStatusText_HACK = HACK_StatusText;
+
+ nsresult rv = mChildListener->OnStartRequest(this, mChildListenerContext);
+ if (!NS_SUCCEEDED(rv)) {
+ // TODO: Cancel request:
+ // - Send Cancel msg to parent
+ // - drop any in flight OnDataAvail msgs we receive
+ // - make sure we do call OnStopRequest eventually
+ // - return true here, not false
+ return false;
+ }
+ return true;
+}
+
+bool
+HttpChannelChild::RecvOnDataAvailable(const nsCString& data,
+ const PRUint32& offset,
+ const PRUint32& count)
+{
+ LOG(("HttpChannelChild::RecvOnDataAvailable [this=%x]\n", this));
+
+ mState = HCC_ONDATA;
+
+ // 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),
+ data.get(),
+ count,
+ NS_ASSIGNMENT_DEPEND);
+ if (!NS_SUCCEEDED(rv)) {
+ // TODO: what to do here? Cancel request? Very unlikely to fail.
+ return false;
+ }
+ rv = mChildListener->OnDataAvailable(this, mChildListenerContext,
+ stringStream, offset, count);
+ stringStream->Close();
+ if (!NS_SUCCEEDED(rv)) {
+ // TODO: Cancel request: see notes in OnStartRequest
+ return false;
+ }
+ return true;
+}
+
+bool
+HttpChannelChild::RecvOnStopRequest(const nsresult& statusCode)
+{
+ LOG(("HttpChannelChild::RecvOnStopRequest [this=%x status=%u]\n",
+ this, statusCode));
+
+ mState = HCC_ONSTOP;
+
+ mIsPending = PR_FALSE;
+ mStatus = statusCode;
+ nsresult rv = mChildListener->OnStopRequest(this, mChildListenerContext,
+ statusCode);
+ mChildListener = 0;
+ mChildListenerContext = 0;
+ if (!NS_SUCCEEDED(rv)) {
+ // TODO: Cancel request: see notes in OnStartRequest
+ return false;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIRequest
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetName(nsACString& aName)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::IsPending(PRBool *retval)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_ENSURE_ARG_POINTER(retval);
+ *retval = mIsPending;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetStatus(nsresult *aStatus)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_ENSURE_ARG_POINTER(aStatus);
+ *aStatus = mStatus;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::Cancel(nsresult aStatus)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::Suspend()
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::Resume()
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetLoadGroup(nsILoadGroup **aLoadGroup)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetLoadGroup(nsILoadGroup *aLoadGroup)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetLoadFlags(nsLoadFlags *aLoadFlags)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_ENSURE_ARG_POINTER(aLoadFlags);
+ *aLoadFlags = mLoadFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+ ENSURE_CALLED_BEFORE_ASYNC_OPEN();
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ mLoadFlags = aLoadFlags;
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetOriginalURI(nsIURI **originalURI)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_ENSURE_ARG_POINTER(originalURI);
+ *originalURI = mOriginalURI;
+ NS_ADDREF(*originalURI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetOriginalURI(nsIURI *originalURI)
+{
+ ENSURE_CALLED_BEFORE_ASYNC_OPEN();
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_ENSURE_ARG_POINTER(originalURI);
+ mOriginalURI = originalURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetURI(nsIURI **URI)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_ENSURE_ARG_POINTER(URI);
+ *URI = mURI;
+ NS_IF_ADDREF(*URI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetOwner(nsISupports **aOwner)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetOwner(nsISupports *aOwner)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetNotificationCallbacks(nsIInterfaceRequestor **callbacks)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_IF_ADDREF(*callbacks = mCallbacks);
+ return NS_OK;
+}
+NS_IMETHODIMP
+HttpChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor *callbacks)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ mCallbacks = callbacks;
+ mProgressSink = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetContentType(nsACString& value)
+{
+ if (mState < HCC_ONSTART) {
+ value.Truncate();
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ if (mContentType_HACK.IsEmpty()) {
+ value.AssignLiteral(UNKNOWN_CONTENT_TYPE);
+ } else {
+ value = mContentType_HACK;
+ }
+ return NS_OK;
+}
+NS_IMETHODIMP
+HttpChannelChild::SetContentType(const nsACString& aContentType)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetContentCharset(nsACString& aContentCharset)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetContentCharset(const nsACString& aContentCharset)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetContentLength(PRInt32 *aContentLength)
+{
+ *aContentLength = mContentLength_HACK;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetContentLength(PRInt32 aContentLength)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::Open(nsIInputStream **retval)
+{
+ NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
+ return NS_ImplementChannelOpen(this, retval);
+}
+
+NS_IMETHODIMP
+HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
+{
+ LOG(("HttpChannelChild::AsyncOpen [this=%x uri=%s]\n", this, mSpec.get()));
+
+ NS_ENSURE_TRUE(gNeckoChild != nsnull, 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.
+ nsresult rv;
+ rv = NS_CheckPortSafety(mURI);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // This corresponds to Release() in DeallocPHttpChannel
+ this->AddRef();
+
+ // TODO: Combine constructor and AsyncOpen to save one IPC msg
+ if (!gNeckoChild->SendPHttpChannelConstructor(this)) {
+ // TODO: currently means "this" has been deleted! bug 529693
+ DROP_DEAD();
+ }
+ mChildListener = listener;
+ mChildListenerContext = aContext;
+
+ // TODO: need to dupe cookies logic from nsHttpChannel.cpp?
+
+ // TODO: need to notify (child-side) http-on-modify-req observers
+
+ // TODO: add self to loadgroup?
+
+ // TODO: smartest way to pass nsURI == (spec, charset)?
+ nsCAutoString charset;
+ mURI->GetOriginCharset(charset);
+ nsCAutoString originalSpec;
+ mOriginalURI->GetSpec(originalSpec);
+ nsCAutoString originalCharset;
+ mOriginalURI->GetOriginCharset(originalCharset);
+
+ nsCAutoString docSpec;
+ nsCAutoString docCharset;
+ if (mDocumentURI) {
+ mDocumentURI->GetSpec(docSpec);
+ mDocumentURI->GetOriginCharset(docCharset);
+ }
+
+ if (!SendAsyncOpen(mSpec, charset, originalSpec, originalCharset,
+ docSpec, docCharset, mLoadFlags)) {
+ // IPDL error: our destructor will be called automatically
+ // -- TODO: verify that that's the case :)
+ mChildListener = 0;
+ mChildListenerContext = 0;
+ return NS_ERROR_FAILURE;
+ }
+
+ mIsPending = PR_TRUE;
+ mWasOpened = PR_TRUE;
+ mState = HCC_OPENED;
+
+ return NS_OK;
}
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIHttpChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetRequestMethod(nsACString& method)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ method = mRequestHead.Method();
+ return NS_OK;
+}
+NS_IMETHODIMP
+HttpChannelChild::SetRequestMethod(const nsACString& method)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ * - TODO: pass along to parent in AsyncOpen
+ */
+ NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
+
+ const nsCString& flatMethod = PromiseFlatCString(method);
+
+ // Method names are restricted to valid HTTP tokens.
+ if (!nsHttp::IsValidToken(flatMethod))
+ return NS_ERROR_INVALID_ARG;
+
+ nsHttpAtom atom = nsHttp::ResolveAtom(flatMethod.get());
+ if (!atom)
+ return NS_ERROR_FAILURE;
+
+ mRequestHead.SetMethod(atom);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetReferrer(nsIURI **aReferrer)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetReferrer(nsIURI *aReferrer)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetRequestHeader(const nsACString& hdr, nsACString& val)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetRequestHeader(const nsACString& aHeader,
+ const nsACString& aValue,
+ PRBool aMerge)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::VisitRequestHeaders(nsIHttpHeaderVisitor *aVisitor)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetAllowPipelining(PRBool *aAllowPipelining)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetAllowPipelining(PRBool aAllowPipelining)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetRedirectionLimit(PRUint32 *aRedirectionLimit)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetRedirectionLimit(PRUint32 aRedirectionLimit)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetResponseStatus(PRUint32 *value)
+{
+ NS_ENSURE_ARG_POINTER(value);
+ if (mState < HCC_ONSTART)
+ return NS_ERROR_NOT_AVAILABLE;
+ *value = mResponseStatus_HACK;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetResponseStatusText(nsACString& value)
+{
+ if (mState < HCC_ONSTART)
+ return NS_ERROR_NOT_AVAILABLE;
+ value = mResponseStatusText_HACK;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetRequestSucceeded(PRBool *value)
+{
+ NS_PRECONDITION(value, "Don't ever pass a null arg to this function");
+ if (mState < HCC_ONSTART)
+ return NS_ERROR_NOT_AVAILABLE;
+ PRUint32 status = mResponseStatus_HACK;
+ *value = (status / 100 == 2);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetResponseHeader(const nsACString& header, nsACString& val)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetResponseHeader(const nsACString& header,
+ const nsACString& value,
+ PRBool merge)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::VisitResponseHeaders(nsIHttpHeaderVisitor *aVisitor)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::IsNoStoreResponse(PRBool *retval)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::IsNoCacheResponse(PRBool *retval)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIHttpChannelInternal
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetDocumentURI(nsIURI **aDocumentURI)
+{
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ NS_ENSURE_ARG_POINTER(aDocumentURI);
+ *aDocumentURI = mDocumentURI;
+ NS_IF_ADDREF(*aDocumentURI);
+ return NS_OK;
+}
+NS_IMETHODIMP
+HttpChannelChild::SetDocumentURI(nsIURI *aDocumentURI)
+{
+ ENSURE_CALLED_BEFORE_ASYNC_OPEN();
+ /**
+ * COPIED from nsHttpChannel.cpp: move to shared base class?
+ */
+ mDocumentURI = aDocumentURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetRequestVersion(PRUint32 *major, PRUint32 *minor)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetResponseVersion(PRUint32 *major, PRUint32 *minor)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetCookie(const char *aCookieHeader)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetForceAllowThirdPartyCookie(PRBool *force)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetForceAllowThirdPartyCookie(PRBool force)
+{
+ DROP_DEAD();
+}
+
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIRequestObserver
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::OnStopRequest(nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsresult aStatusCode)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIStreamListener
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::OnDataAvailable(nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsIInputStream *aInputStream,
+ PRUint32 aOffset,
+ PRUint32 aCount)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsICachingChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetCacheToken(nsISupports **aCacheToken)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetCacheToken(nsISupports *aCacheToken)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetOfflineCacheToken(nsISupports **aOfflineCacheToken)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetOfflineCacheToken(nsISupports *aOfflineCacheToken)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetCacheKey(nsISupports **aCacheKey)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetCacheKey(nsISupports *aCacheKey)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetCacheAsFile(PRBool *aCacheAsFile)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetCacheAsFile(PRBool aCacheAsFile)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetCacheForOfflineUse(PRBool *aCacheForOfflineUse)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetCacheForOfflineUse(PRBool aCacheForOfflineUse)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetOfflineCacheClientID(nsACString& id)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetOfflineCacheClientID(const nsACString& id)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetCacheFile(nsIFile **aCacheFile)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::IsFromCache(PRBool *retval)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIUploadChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::SetUploadStream(nsIInputStream *aStream,
+ const nsACString& aContentType,
+ PRInt32 aContentLength)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetUploadStream(nsIInputStream **aUploadStream)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIUploadChannel2
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::ExplicitSetUploadStream(nsIInputStream *aStream,
+ const nsACString& aContentType,
+ PRInt64 aContentLength,
+ const nsACString& aMethod,
+ PRBool aStreamHasHeaders)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsICacheListener
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::OnCacheEntryAvailable(nsICacheEntryDescriptor *descriptor,
+ nsCacheAccessMode accessGranted,
+ nsresult status)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIEncodedChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetContentEncodings(nsIUTF8StringEnumerator **result)
+{
+ DROP_DEAD();
+}
+
+/* attribute boolean applyConversion; */
+NS_IMETHODIMP
+HttpChannelChild::GetApplyConversion(PRBool *aApplyConversion)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::SetApplyConversion(PRBool aApplyConversion)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsITransportEventSink
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::OnTransportStatus(nsITransport *aTransport,
+ nsresult aStatus,
+ PRUint64 aProgress,
+ PRUint64 aProgressMax)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIResumableChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::ResumeAt(PRUint64 startPos, const nsACString& entityID)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetEntityID(nsACString& aEntityID)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsISupportsPriority
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetPriority(PRInt32 *aPriority)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetPriority(PRInt32 aPriority)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::AdjustPriority(PRInt32 delta)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIProtocolProxyCallback
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::OnProxyAvailable(nsICancelable *aRequest,
+ nsIURI *aURI,
+ nsIProxyInfo *aProxyInfo,
+ nsresult aStatus)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIProxiedChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetProxyInfo(nsIProxyInfo **aProxyInfo)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsITraceableChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::SetNewListener(nsIStreamListener *listener,
+ nsIStreamListener **oldListener)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIApplicationCacheContainer
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetApplicationCache(nsIApplicationCache **aApplicationCache)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetApplicationCache(nsIApplicationCache *aApplicationCache)
+{
+ DROP_DEAD();
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIApplicationCacheChannel
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::GetLoadedFromApplicationCache(PRBool *retval)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetInheritApplicationCache(PRBool *aInheritApplicationCache)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetInheritApplicationCache(PRBool aInheritApplicationCache)
+{
+ // FIXME: Browser calls this early, so stub OK for now. Fix in bug 536295.
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelChild::GetChooseApplicationCache(PRBool *aChooseApplicationCache)
+{
+ DROP_DEAD();
+}
+NS_IMETHODIMP
+HttpChannelChild::SetChooseApplicationCache(PRBool aChooseApplicationCache)
+{
+ // FIXME: Browser calls this early, so stub OK for now. Fix in bug 536295.
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelChild::nsIAuthPromptCallback
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelChild::OnAuthAvailable(nsISupports *context,
+ nsIAuthInformation *aAuthInfo)
+{
+ DROP_DEAD();
+}
+
+NS_IMETHODIMP
+HttpChannelChild::OnAuthCancelled(nsISupports *aContext, PRBool userCancel)
+{
+ DROP_DEAD();
+}
+
+
+//------------------------------------------------------------------------------
}} // mozilla::net
--- a/netwerk/protocol/http/src/HttpChannelChild.h
+++ b/netwerk/protocol/http/src/HttpChannelChild.h
@@ -37,29 +37,147 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_HttpChannelChild_h
#define mozilla_net_HttpChannelChild_h
#include "mozilla/net/PHttpChannelChild.h"
-#include "nsXULAppAPI.h"
+#include "mozilla/net/NeckoCommon.h"
+
+#include "nsHttpRequestHead.h"
+#include "nsHashPropertyBag.h"
+#include "nsIHttpChannel.h"
+#include "nsIHttpChannelInternal.h"
+#include "nsIStreamListener.h"
+#include "nsIURI.h"
+#include "nsILoadGroup.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIProgressEventSink.h"
+#include "nsICachingChannel.h"
+#include "nsICacheListener.h"
+#include "nsIApplicationCache.h"
+#include "nsIApplicationCacheChannel.h"
+#include "nsIEncodedChannel.h"
+#include "nsITransport.h"
+#include "nsIUploadChannel.h"
+#include "nsIUploadChannel2.h"
+#include "nsIResumableChannel.h"
+#include "nsISupportsPriority.h"
+#include "nsIProtocolProxyCallback.h"
+#include "nsIProxiedChannel.h"
+#include "nsITraceableChannel.h"
+#include "nsIAuthPromptCallback.h"
+
namespace mozilla {
namespace net {
+// TODO: replace with IPDL states
+enum HttpChannelChildState {
+ HCC_NEW,
+ HCC_OPENED,
+ HCC_ONSTART,
+ HCC_ONDATA,
+ HCC_ONSTOP
+};
+
// Header file contents
-class HttpChannelChild :
- public PHttpChannelChild
+class HttpChannelChild : public PHttpChannelChild
+ , public nsIHttpChannel
+ , public nsHashPropertyBag
+ , public nsIHttpChannelInternal
+ , public nsIStreamListener
+ , public nsICachingChannel
+ , public nsIUploadChannel
+ , public nsIUploadChannel2
+ , public nsICacheListener
+ , public nsIEncodedChannel
+ , public nsITransportEventSink
+ , public nsIResumableChannel
+ , public nsISupportsPriority
+ , public nsIProtocolProxyCallback
+ , public nsIProxiedChannel
+ , public nsITraceableChannel
+ , public nsIApplicationCacheChannel
+ , public nsIAuthPromptCallback
{
public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIREQUEST
+ NS_DECL_NSICHANNEL
+ NS_DECL_NSIHTTPCHANNEL
+ NS_DECL_NSIHTTPCHANNELINTERNAL
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSICACHINGCHANNEL
+ NS_DECL_NSIUPLOADCHANNEL
+ NS_DECL_NSIUPLOADCHANNEL2
+ NS_DECL_NSICACHELISTENER
+ NS_DECL_NSIENCODEDCHANNEL
+ NS_DECL_NSITRANSPORTEVENTSINK
+ NS_DECL_NSIRESUMABLECHANNEL
+ NS_DECL_NSISUPPORTSPRIORITY
+ NS_DECL_NSIPROTOCOLPROXYCALLBACK
+ NS_DECL_NSIPROXIEDCHANNEL
+ NS_DECL_NSITRACEABLECHANNEL
+ NS_DECL_NSIAPPLICATIONCACHECONTAINER
+ NS_DECL_NSIAPPLICATIONCACHECHANNEL
+ NS_DECL_NSIAUTHPROMPTCALLBACK
+
HttpChannelChild();
virtual ~HttpChannelChild();
+ nsresult Init(nsIURI *uri);
+
protected:
+ bool RecvOnStartRequest(const PRInt32& HACK_ContentLength,
+ const nsCString& HACK_ContentType,
+ const PRUint32& HACK_Status,
+ const nsCString& HACK_StatusText);
+ bool RecvOnDataAvailable(const nsCString& data,
+ const PRUint32& offset,
+ const PRUint32& count);
+ bool RecvOnStopRequest(const nsresult& statusCode);
+
+private:
+ nsCOMPtr<nsIStreamListener> mChildListener;
+ nsCOMPtr<nsISupports> mChildListenerContext;
+
+ // FIXME: copy full ResponseHead (bug 536283)
+ PRInt32 mContentLength_HACK;
+ nsCString mContentType_HACK;
+ PRUint32 mResponseStatus_HACK;
+ nsCString mResponseStatusText_HACK;
+
+ // FIXME: replace with IPDL states (bug 536319)
+ enum HttpChannelChildState mState;
+
+ /**
+ * fields copied from nsHttpChannel.h
+ */
+ nsCOMPtr<nsIURI> mOriginalURI;
+ nsCOMPtr<nsIURI> mURI;
+ nsCOMPtr<nsIURI> mDocumentURI;
+
+ nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
+ nsCOMPtr<nsIProgressEventSink> mProgressSink;
+
+ nsHttpRequestHead mRequestHead;
+
+ nsCString mSpec; // ASCII encoded URL spec
+
+ PRUint32 mLoadFlags;
+ PRUint32 mStatus;
+
+ // state flags
+ PRUint32 mIsPending : 1;
+ PRUint32 mWasOpened : 1;
+
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_HttpChannelChild_h
--- a/netwerk/protocol/http/src/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/src/HttpChannelParent.cpp
@@ -33,32 +33,199 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
+#include "nsHttp.h"
#include "mozilla/net/HttpChannelParent.h"
+#include "nsHttpChannel.h"
+#include "nsNetUtil.h"
namespace mozilla {
namespace net {
// C++ file contents
HttpChannelParent::HttpChannelParent()
{
}
HttpChannelParent::~HttpChannelParent()
{
}
//-----------------------------------------------------------------------------
-//
-bool HttpChannelParent::RecvasyncOpen(const nsCString& uri)
+// HttpChannelParent::nsISupports
+//-----------------------------------------------------------------------------
+
+NS_IMPL_ISUPPORTS3(HttpChannelParent,
+ nsIRequestObserver,
+ nsIStreamListener,
+ nsIInterfaceRequestor);
+
+//-----------------------------------------------------------------------------
+// HttpChannelParent::PHttpChannelParent
+//-----------------------------------------------------------------------------
+
+bool
+HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec,
+ const nsCString& charset,
+ const nsCString& originalUriSpec,
+ const nsCString& originalCharset,
+ const nsCString& docUriSpec,
+ const nsCString& docCharset,
+ const PRUint32& loadFlags)
{
- puts("[HttpChannelParent] got asyncOpen msg");
+ nsresult rv;
+
+ nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
+ if (NS_FAILED(rv))
+ return false; // TODO: send fail msg to child, return true
+
+ nsCOMPtr<nsIURI> uri;
+ rv = NS_NewURI(getter_AddRefs(uri), uriSpec, charset.get(), nsnull, ios);
+ if (NS_FAILED(rv))
+ return false; // TODO: send fail msg to child, return true
+
+ // Delay log to here, as gHttpLog may not exist in parent until we init
+ // gHttpHandler via above call to NS_NewURI. Avoids segfault :)
+ LOG(("HttpChannelParent RecvAsyncOpen [this=%x uri=%s (%s)]\n",
+ this, uriSpec.get(), charset.get()));
+
+ nsCOMPtr<nsIChannel> chan;
+ rv = NS_NewChannel(getter_AddRefs(chan), uri, ios, nsnull, nsnull, loadFlags);
+ if (NS_FAILED(rv))
+ return false; // TODO: send fail msg to child, return true
+
+ if (!originalUriSpec.IsEmpty()) {
+ nsCOMPtr<nsIURI> originalUri;
+ rv = NS_NewURI(getter_AddRefs(originalUri), originalUriSpec,
+ originalCharset.get(), nsnull, ios);
+ if (!NS_FAILED(rv))
+ chan->SetOriginalURI(originalUri);
+ }
+ if (!docUriSpec.IsEmpty()) {
+ nsCOMPtr<nsIURI> docUri;
+ rv = NS_NewURI(getter_AddRefs(docUri), docUriSpec,
+ docCharset.get(), nsnull, ios);
+ if (!NS_FAILED(rv)) {
+ nsCOMPtr<nsIHttpChannelInternal> iChan(do_QueryInterface(chan));
+ if (iChan)
+ iChan->SetDocumentURI(docUri);
+ }
+ }
+ if (loadFlags != nsIRequest::LOAD_NORMAL)
+ chan->SetLoadFlags(loadFlags);
+
+ // TODO: implement needed interfaces, and either proxy calls back to child
+ // process, or rig up appropriate hacks.
+// chan->SetNotificationCallbacks(this);
+
+ rv = chan->AsyncOpen(this, nsnull);
+ if (NS_FAILED(rv))
+ return false; // TODO: send fail msg to child, return true
+
return true;
}
+
+//-----------------------------------------------------------------------------
+// HttpChannelParent::nsIRequestObserver
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
+{
+ LOG(("HttpChannelParent::OnStartRequest [this=%x]\n", this));
+
+ nsCOMPtr<nsIHttpChannel> chan(do_QueryInterface(aRequest));
+ NS_ENSURE_TRUE(chan, NS_ERROR_FAILURE);
+
+ /*
+ * - TODO: Need to send all or most of mResponseHead
+ * - TODO: if getting vals fails, still need to call OnStartRequest on child,
+ * not just fail here?
+ */
+ PRInt32 contentLength_HACK;
+ chan->GetContentLength(&contentLength_HACK);
+ nsCAutoString contentType_HACK;
+ chan->GetContentType(contentType_HACK);
+ PRUint32 status_HACK;
+ chan->GetResponseStatus(&status_HACK);
+ nsCAutoString statusText_HACK;
+ chan->GetResponseStatusText(statusText_HACK);
+
+ if (!SendOnStartRequest(contentLength_HACK, contentType_HACK,
+ status_HACK, statusText_HACK))
+ {
+ // IPDL error--child dead/dying & our own destructor will be called
+ // automatically
+ // -- TODO: verify that that's the case :)
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsresult aStatusCode)
+{
+ LOG(("HttpChannelParent::OnStopRequest: [this=%x status=%ul]\n",
+ this, aStatusCode));
+
+ if (!SendOnStopRequest(aStatusCode)) {
+ // IPDL error--child dead/dying & our own destructor will be called
+ // automatically
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelParent::nsIStreamListener
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
+ nsISupports *aContext,
+ nsIInputStream *aInputStream,
+ PRUint32 aOffset,
+ PRUint32 aCount)
+{
+ LOG(("HttpChannelParent::OnDataAvailable [this=%x]\n", this));
+
+ nsresult rv;
+
+ nsCString data;
+ data.SetLength(aCount);
+ char * p = data.BeginWriting();
+ PRUint32 bytesRead;
+ rv = aInputStream->Read(p, aCount, &bytesRead);
+ data.EndWriting();
+ if (!NS_SUCCEEDED(rv) || bytesRead != aCount) {
+ return rv; // TODO: figure out error handling
+ }
+
+ if (!SendOnDataAvailable(data, aOffset, bytesRead)) {
+ // IPDL error--child dead/dying & our own destructor will be called
+ // automatically
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// HttpChannelParent::nsIInterfaceRequestor
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+HttpChannelParent::GetInterface(const nsIID& uuid, void **result)
+{
+ DROP_DEAD();
+}
+
+
}} // mozilla::net
--- a/netwerk/protocol/http/src/HttpChannelParent.h
+++ b/netwerk/protocol/http/src/HttpChannelParent.h
@@ -36,29 +36,45 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_HttpChannelParent_h
#define mozilla_net_HttpChannelParent_h
+#include "nsHttp.h"
#include "mozilla/net/PHttpChannelParent.h"
+#include "mozilla/net/NeckoCommon.h"
+#include "nsIStreamListener.h"
+#include "nsIInterfaceRequestor.h"
namespace mozilla {
namespace net {
// Header file contents
-class HttpChannelParent :
- public PHttpChannelParent
+class HttpChannelParent : public PHttpChannelParent
+ , public nsIStreamListener
+ , public nsIInterfaceRequestor
{
public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIINTERFACEREQUESTOR
+
HttpChannelParent();
virtual ~HttpChannelParent();
protected:
- virtual bool RecvasyncOpen(const nsCString& uri);
+ virtual bool RecvAsyncOpen(const nsCString& uriSpec,
+ const nsCString& originCharset,
+ const nsCString& originalUriSpec,
+ const nsCString& originalCharset,
+ const nsCString& docUriSpec,
+ const nsCString& docCharset,
+ const PRUint32& loadFlags);
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_HttpChannelParent_h
--- a/netwerk/protocol/http/src/Makefile.in
+++ b/netwerk/protocol/http/src/Makefile.in
@@ -78,17 +78,20 @@ CPPSRCS = \
ifdef MOZ_IPC
CPPSRCS += \
HttpChannelParent.cpp \
HttpChannelChild.cpp \
$(NULL)
endif
-LOCAL_INCLUDES=-I$(srcdir)/../../../base/src -I$(topsrcdir)/xpcom/ds
+LOCAL_INCLUDES += \
+ -I$(srcdir)/../../../base/src \
+ -I$(topsrcdir)/xpcom/ds \
+ $(NULL)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
--- a/netwerk/protocol/http/src/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/src/PHttpChannel.ipdl
@@ -38,24 +38,45 @@
*
* ***** END LICENSE BLOCK ***** */
include protocol "PNecko.ipdl";
namespace mozilla {
namespace net {
-
//-------------------------------------------------------------------
protocol PHttpChannel
{
manager PNecko;
parent:
__delete__();
- asyncOpen(nsCString uri);
+ AsyncOpen(nsCString uriSpec,
+ nsCString originCharset,
+ // - TODO: unclear if any HTTP channel clients ever set
+ // originalURI != uri (about:credits?); also not clear if chrome
+ // channel would ever need to know. Can we get rid of next two
+ // args?
+ nsCString originalUriSpec,
+ nsCString originalCharset,
+ nsCString documentUriSpec,
+ nsCString documentCharset,
+ PRUint32 loadFlags);
+
+child:
+ OnStartRequest(PRInt32 HACK_ContentLength,
+ nsCString HACK_ContentType,
+ PRUint32 HACK_Status,
+ nsCString HACK_StatusText);
+
+ OnDataAvailable(nsCString data,
+ PRUint32 offset,
+ PRUint32 count);
+
+ OnStopRequest(nsresult statusCode);
};
} // namespace net
} // namespace mozilla
--- a/netwerk/protocol/http/src/nsHttp.h
+++ b/netwerk/protocol/http/src/nsHttp.h
@@ -40,18 +40,32 @@
#ifndef nsHttp_h__
#define nsHttp_h__
#if defined(MOZ_LOGGING)
#define FORCE_PR_LOG
#endif
#ifdef MOZ_IPC
+// e10s mess: IPDL-generatd headers include chromium which both #includes
+// prlog.h, and #defines LOG in conflict with this file.
+// Solution: (as described in bug 545995)
+// 1) ensure that this file is #included before any IPDL-generated files and
+// anything else that #includes prlog.h, so that we can make sure prlog.h
+// sees FORCE_PR_LOG if needed.
+// 2) #include IPDL boilerplate, and then undef LOG so our LOG wins.
+// 3) nsNetModule.cpp does its own crazy stuff with #including prlog.h
+// multiple times; allow it to define ALLOW_LATE_NSHTTP_H_INCLUDE to bypass
+// check.
+#if defined(PR_LOG) && !defined(ALLOW_LATE_NSHTTP_H_INCLUDE)
+#error "If nsHttp.h #included it must come before any IPDL-generated files or other files that #include prlog.h"
+#endif
#include "mozilla/net/NeckoChild.h"
-#endif
+#undef LOG
+#endif // MOZ_IPC
#include "plstr.h"
#include "prlog.h"
#include "prtime.h"
#include "nsISupportsUtils.h"
#include "nsPromiseFlatString.h"
#include "nsURLHelper.h"
#include "netCore.h"
@@ -66,17 +80,16 @@
// set NSPR_LOG_FILE=http.log
//
// this enables PR_LOG_ALWAYS level information and places all output in
// the file http.log
//
extern PRLogModuleInfo *gHttpLog;
#endif
-#undef LOG
// http logging
#define LOG1(args) PR_LOG(gHttpLog, 1, args)
#define LOG2(args) PR_LOG(gHttpLog, 2, args)
#define LOG3(args) PR_LOG(gHttpLog, 3, args)
#define LOG4(args) PR_LOG(gHttpLog, 4, args)
#define LOG(args) LOG4(args)
#define LOG1_ENABLED() PR_LOG_TEST(gHttpLog, 1)
--- a/netwerk/protocol/http/src/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/src/nsHttpHandler.cpp
@@ -72,16 +72,20 @@
#include "prprf.h"
#include "nsReadableUtils.h"
#include "nsQuickSort.h"
#include "nsNetUtil.h"
#include "nsIOService.h"
#include "nsIXULAppInfo.h"
+#ifdef MOZ_IPC
+#include "mozilla/net/NeckoChild.h"
+#endif
+
#if defined(XP_UNIX) || defined(XP_BEOS)
#include <sys/utsname.h>
#endif
#if defined(XP_WIN)
#include <windows.h>
#endif
@@ -92,16 +96,17 @@
#if defined(XP_OS2)
#define INCL_DOSMISC
#include <os2.h>
#endif
//-----------------------------------------------------------------------------
#ifdef MOZ_IPC
using namespace mozilla::net;
+#include "mozilla/net/HttpChannelChild.h"
#endif
#ifdef DEBUG
// defined by the socket transport service while active
extern PRThread *gSocketThread;
#endif
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
@@ -203,16 +208,19 @@ nsHttpHandler::~nsHttpHandler()
LOG(("Deleting nsHttpHandler [this=%x]\n", this));
// make sure the connection manager is shutdown
if (mConnMgr) {
mConnMgr->Shutdown();
NS_RELEASE(mConnMgr);
}
+ // Note: don't call NeckoChild::DestroyNeckoChild() here, as it's too late
+ // and it'll segfault. NeckoChild will get cleaned up by process exit.
+
nsHttp::DestroyAtomTable();
gHttpHandler = nsnull;
}
nsresult
nsHttpHandler::Init()
{
@@ -226,17 +234,17 @@ nsHttpHandler::Init()
mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
NS_WARNING("unable to continue without io service");
return rv;
}
#ifdef MOZ_IPC
- if (IsNeckoChild() && !gNeckoChild)
+ if (IsNeckoChild())
NeckoChild::InitNeckoChild();
#endif // MOZ_IPC
InitUserAgentComponents();
// monitor some preference changes
nsCOMPtr<nsIPrefBranch2> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefBranch) {
@@ -1492,16 +1500,42 @@ nsHttpHandler::NewProxiedChannel(nsIURI
NS_ENSURE_ARG(proxyInfo);
}
PRBool https;
nsresult rv = uri->SchemeIs("https", &https);
if (NS_FAILED(rv))
return rv;
+#if MOZ_IPC
+ if (IsNeckoChild()) {
+ LOG(("NECKO_E10S_HTTP set: using experimental interprocess HTTP\n"));
+ // TODO_JCD:
+ // - Create a common BaseHttpChannel so can share logic?
+ HttpChannelChild *childChannel = nsnull;
+ NS_NEWXPCOM(childChannel, HttpChannelChild);
+ if (!childChannel)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(childChannel);
+ // TODO: Just ignore HTTPS and proxying for now
+ if (https)
+ DROP_DEAD();
+ if (givenProxyInfo)
+ DROP_DEAD();
+ // TODO: Init caps, etc, as below?
+ rv = childChannel->Init(uri);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(childChannel);
+ return rv;
+ }
+ *result = childChannel;
+ return NS_OK;
+ }
+#endif
+
NS_NEWXPCOM(httpChannel, nsHttpChannel);
if (!httpChannel)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(httpChannel);
// select proxy caps if using a non-transparent proxy. SSL tunneling
// should not use proxy settings.
PRInt8 caps;