Bug 530952: Electrolysis HTTP Channel implementation. author=jduell, r=bsmedberg, sr=bz
authorJason Duell <jduell.mcbugs@gmail.com>
Tue, 22 Sep 2009 11:55:33 -0700
changeset 46672 959add9a851a4ea8787f5d4fb7fb9e0cb1a1d870
parent 46671 ab07afb8c04ccc8216cd483f6787724860656b72
child 46673 f933d97663859ff5a7b08ac8fb9198da11328d90
push id14210
push userdougt@mozilla.com
push dateThu, 01 Jul 2010 06:28:42 +0000
treeherdermozilla-central@3aff97777291 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, bz
bugs530952, 521922, 545995
milestone1.9.3a2pre
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)
netwerk/build/nsNetModule.cpp
netwerk/ipc/Makefile.in
netwerk/ipc/NeckoChild.cpp
netwerk/ipc/NeckoChild.h
netwerk/ipc/NeckoCommon.h
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/protocol/http/src/HttpChannelChild.cpp
netwerk/protocol/http/src/HttpChannelChild.h
netwerk/protocol/http/src/HttpChannelParent.cpp
netwerk/protocol/http/src/HttpChannelParent.h
netwerk/protocol/http/src/Makefile.in
netwerk/protocol/http/src/PHttpChannel.ipdl
netwerk/protocol/http/src/nsHttp.h
netwerk/protocol/http/src/nsHttpHandler.cpp
--- 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;