diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml
index 0d4df0e40bb5..95fd1aecdaa3 100644
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml
index 05135cfcbfd7..be940c19618e 100644
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml
index a49bf08c8097..d143b68aa0fa 100644
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml
index 0d4df0e40bb5..95fd1aecdaa3 100644
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index f5f01d10c2ad..151dc501e189 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -4,6 +4,6 @@
"branch": "",
"revision": ""
},
- "revision": "82537f452462222ac77bb22f19a6ceb89aeade95",
+ "revision": "1450b977cb8e074f2e9fe2a12049005204febf72",
"repo_path": "/integration/gaia-central"
}
diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml
index 039d52a11665..29bca210d916 100644
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml
index 9d0f10b29fef..c99ab4d393d8 100644
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/inari/sources.xml b/b2g/config/inari/sources.xml
index b03df80d5e1b..63b4a1d4b2f3 100644
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/leo/sources.xml b/b2g/config/leo/sources.xml
index b60f424a700a..8d90319d9371 100644
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/mako/sources.xml b/b2g/config/mako/sources.xml
index 2f8aa7000a90..d501abc42f0a 100644
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml
index 0391f78f55f4..22f03aedba71 100644
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build
index 1e7ec0fcbb82..9757f62b65a1 100644
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -41,7 +41,6 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [
'AppProcessChecker.cpp',
'ColorPickerParent.cpp',
- 'ContentChild.cpp',
'ContentParent.cpp',
'ContentProcess.cpp',
'CrashReporterParent.cpp',
@@ -57,10 +56,12 @@ UNIFIED_SOURCES += [
]
# Blob.cpp cannot be compiled in unified mode because it triggers a fatal gcc warning.
+# ContentChild.cpp cannot be compiled in unified mode because it forces NSPR logging.
# CrashReporterChild.cpp cannot be compiled in unified mode because of name clashes
# in OS X headers.
SOURCES += [
'Blob.cpp',
+ 'ContentChild.cpp',
'CrashReporterChild.cpp',
]
diff --git a/uriloader/exthandler/ExternalHelperAppChild.cpp b/uriloader/exthandler/ExternalHelperAppChild.cpp
index 4cafa692193a..f2d54135af0a 100644
--- a/uriloader/exthandler/ExternalHelperAppChild.cpp
+++ b/uriloader/exthandler/ExternalHelperAppChild.cpp
@@ -5,7 +5,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ExternalHelperAppChild.h"
+#include "mozilla/net/ChannelDiverterChild.h"
+#include "nsIDivertableChannel.h"
#include "nsIInputStream.h"
+#include "nsIFTPChannel.h"
#include "nsIRequest.h"
#include "nsIResumableChannel.h"
#include "nsNetUtil.h"
@@ -57,30 +60,56 @@ ExternalHelperAppChild::OnDataAvailable(nsIRequest *request,
NS_IMETHODIMP
ExternalHelperAppChild::OnStartRequest(nsIRequest *request, nsISupports *ctx)
{
+ nsCOMPtr divertable = do_QueryInterface(request);
+ if (divertable) {
+ return DivertToParent(divertable, request);
+ }
+
nsresult rv = mHandler->OnStartRequest(request, ctx);
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
nsCString entityID;
nsCOMPtr resumable(do_QueryInterface(request));
- if (resumable)
+ if (resumable) {
resumable->GetEntityID(entityID);
+ }
SendOnStartRequest(entityID);
return NS_OK;
}
-
NS_IMETHODIMP
ExternalHelperAppChild::OnStopRequest(nsIRequest *request,
nsISupports *ctx,
nsresult status)
{
- nsresult rv = mHandler->OnStopRequest(request, ctx, status);
- SendOnStopRequest(status);
+ // mHandler can be null if we diverted the request to the parent
+ if (mHandler) {
+ nsresult rv = mHandler->OnStopRequest(request, ctx, status);
+ SendOnStopRequest(status);
+ NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
+ }
- NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
return NS_OK;
}
+nsresult
+ExternalHelperAppChild::DivertToParent(nsIDivertableChannel *divertable, nsIRequest *request)
+{
+ mozilla::net::ChannelDiverterChild *diverter = nullptr;
+ nsresult rv = divertable->DivertToParent(&diverter);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ MOZ_ASSERT(diverter);
+ if (SendDivertToParentUsing(diverter)) {
+ mHandler->DidDivertRequest(request);
+ mHandler = nullptr;
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
bool
ExternalHelperAppChild::RecvCancel(const nsresult& aStatus)
diff --git a/uriloader/exthandler/ExternalHelperAppChild.h b/uriloader/exthandler/ExternalHelperAppChild.h
index 6b58a8b7e3d5..a93cbbc38526 100644
--- a/uriloader/exthandler/ExternalHelperAppChild.h
+++ b/uriloader/exthandler/ExternalHelperAppChild.h
@@ -8,8 +8,11 @@
#define mozilla_dom_ExternalHelperAppChild_h
#include "mozilla/dom/PExternalHelperAppChild.h"
+#include "nsExternalHelperAppService.h"
#include "nsIStreamListener.h"
+class nsIDivertableChannel;
+
namespace mozilla {
namespace dom {
@@ -26,11 +29,13 @@ public:
// Give the listener a real nsExternalAppHandler to complete processing on
// the child.
- void SetHandler(nsIStreamListener *handler) { mHandler = handler; }
+ void SetHandler(nsExternalAppHandler *handler) { mHandler = handler; }
virtual bool RecvCancel(const nsresult& aStatus) MOZ_OVERRIDE;
private:
- nsCOMPtr mHandler;
+ nsresult DivertToParent(nsIDivertableChannel *divertable, nsIRequest *request);
+
+ nsRefPtr mHandler;
nsresult mStatus;
};
diff --git a/uriloader/exthandler/ExternalHelperAppParent.cpp b/uriloader/exthandler/ExternalHelperAppParent.cpp
index 7d89cbcd1e44..a61dc529d9e6 100644
--- a/uriloader/exthandler/ExternalHelperAppParent.cpp
+++ b/uriloader/exthandler/ExternalHelperAppParent.cpp
@@ -18,6 +18,7 @@
#include "mozilla/ipc/URIUtils.h"
#include "nsNetUtil.h"
#include "nsIDocument.h"
+#include "mozilla/net/ChannelDiverterParent.h"
#include "mozilla/unused.h"
@@ -26,18 +27,21 @@ using namespace mozilla::ipc;
namespace mozilla {
namespace dom {
-NS_IMPL_ISUPPORTS_INHERITED4(ExternalHelperAppParent,
+NS_IMPL_ISUPPORTS_INHERITED5(ExternalHelperAppParent,
nsHashPropertyBag,
nsIRequest,
nsIChannel,
nsIMultiPartChannel,
- nsIResumableChannel)
+ nsIResumableChannel,
+ nsIStreamListener)
ExternalHelperAppParent::ExternalHelperAppParent(
const OptionalURIParams& uri,
const int64_t& aContentLength)
: mURI(DeserializeURI(uri))
, mPending(false)
+ , mDiverted(false)
+ , mIPCClosed(false)
, mLoadFlags(0)
, mStatus(NS_OK)
, mContentLength(aContentLength)
@@ -86,9 +90,25 @@ ExternalHelperAppParent::Init(ContentParent *parent,
aForceSave, getter_AddRefs(mListener));
}
+void
+ExternalHelperAppParent::ActorDestroy(ActorDestroyReason why)
+{
+ mIPCClosed = true;
+}
+
+void
+ExternalHelperAppParent::Delete()
+{
+ if (!mIPCClosed) {
+ unused << Send__delete__(this);
+ }
+}
+
bool
ExternalHelperAppParent::RecvOnStartRequest(const nsCString& entityID)
{
+ MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted");
+
mEntityID = entityID;
mPending = true;
mStatus = mListener->OnStartRequest(this, nullptr);
@@ -103,7 +123,9 @@ ExternalHelperAppParent::RecvOnDataAvailable(const nsCString& data,
if (NS_FAILED(mStatus))
return true;
- NS_ASSERTION(mPending, "must be pending!");
+ MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted");
+ MOZ_ASSERT(mPending, "must be pending!");
+
nsCOMPtr stringStream;
DebugOnly rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(), count, NS_ASSIGNMENT_DEPEND);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create dependent string!");
@@ -115,13 +137,59 @@ ExternalHelperAppParent::RecvOnDataAvailable(const nsCString& data,
bool
ExternalHelperAppParent::RecvOnStopRequest(const nsresult& code)
{
+ MOZ_ASSERT(!mDiverted, "child forwarding callbacks after request was diverted");
+
mPending = false;
mListener->OnStopRequest(this, nullptr,
(NS_SUCCEEDED(code) && NS_FAILED(mStatus)) ? mStatus : code);
- unused << Send__delete__(this);
+ Delete();
return true;
}
+bool
+ExternalHelperAppParent::RecvDivertToParentUsing(PChannelDiverterParent* diverter)
+{
+ MOZ_ASSERT(diverter);
+ auto p = static_cast(diverter);
+ p->DivertTo(this);
+ mDiverted = true;
+ unused << p->Send__delete__(p);
+ return true;
+}
+
+//
+// nsIStreamListener
+//
+
+NS_IMETHODIMP
+ExternalHelperAppParent::OnDataAvailable(nsIRequest *request,
+ nsISupports *ctx,
+ nsIInputStream *input,
+ uint64_t offset,
+ uint32_t count)
+{
+ MOZ_ASSERT(mDiverted);
+ return mListener->OnDataAvailable(request, ctx, input, offset, count);
+}
+
+NS_IMETHODIMP
+ExternalHelperAppParent::OnStartRequest(nsIRequest *request, nsISupports *ctx)
+{
+ MOZ_ASSERT(mDiverted);
+ return mListener->OnStartRequest(request, ctx);
+}
+
+NS_IMETHODIMP
+ExternalHelperAppParent::OnStopRequest(nsIRequest *request,
+ nsISupports *ctx,
+ nsresult status)
+{
+ MOZ_ASSERT(mDiverted);
+ nsresult rv = mListener->OnStopRequest(request, ctx, status);
+ Delete();
+ return rv;
+}
+
ExternalHelperAppParent::~ExternalHelperAppParent()
{
}
diff --git a/uriloader/exthandler/ExternalHelperAppParent.h b/uriloader/exthandler/ExternalHelperAppParent.h
index b735d33c034f..a6f6af706124 100644
--- a/uriloader/exthandler/ExternalHelperAppParent.h
+++ b/uriloader/exthandler/ExternalHelperAppParent.h
@@ -8,6 +8,7 @@
#include "nsIChannel.h"
#include "nsIMultiPartChannel.h"
#include "nsIResumableChannel.h"
+#include "nsIStreamListener.h"
#include "nsHashPropertyBag.h"
namespace IPC {
@@ -20,6 +21,10 @@ namespace ipc {
class OptionalURIParams;
} // namespace ipc
+namespace net {
+class PChannelDiverterParent;
+} // namespace net
+
namespace dom {
class ContentParent;
@@ -30,6 +35,7 @@ class ExternalHelperAppParent : public PExternalHelperAppParent
, public nsIChannel
, public nsIMultiPartChannel
, public nsIResumableChannel
+ , public nsIStreamListener
{
typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
@@ -39,6 +45,8 @@ public:
NS_DECL_NSICHANNEL
NS_DECL_NSIMULTIPARTCHANNEL
NS_DECL_NSIRESUMABLECHANNEL
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIREQUESTOBSERVER
bool RecvOnStartRequest(const nsCString& entityID) MOZ_OVERRIDE;
bool RecvOnDataAvailable(const nsCString& data,
@@ -46,6 +54,8 @@ public:
const uint32_t& count) MOZ_OVERRIDE;
bool RecvOnStopRequest(const nsresult& code) MOZ_OVERRIDE;
+ bool RecvDivertToParentUsing(PChannelDiverterParent* diverter) MOZ_OVERRIDE;
+
ExternalHelperAppParent(const OptionalURIParams& uri, const int64_t& contentLength);
void Init(ContentParent *parent,
const nsCString& aMimeContentType,
@@ -57,10 +67,16 @@ public:
PBrowserParent* aBrowser);
virtual ~ExternalHelperAppParent();
+protected:
+ virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+ void Delete();
+
private:
nsCOMPtr mListener;
nsCOMPtr mURI;
bool mPending;
+ DebugOnly mDiverted;
+ bool mIPCClosed;
nsLoadFlags mLoadFlags;
nsresult mStatus;
int64_t mContentLength;
diff --git a/uriloader/exthandler/PExternalHelperApp.ipdl b/uriloader/exthandler/PExternalHelperApp.ipdl
index f120689f8def..914b7cc2ddd1 100644
--- a/uriloader/exthandler/PExternalHelperApp.ipdl
+++ b/uriloader/exthandler/PExternalHelperApp.ipdl
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
+include protocol PChannelDiverter;
namespace mozilla {
namespace dom {
@@ -16,6 +17,8 @@ parent:
OnDataAvailable(nsCString data, uint64_t offset, uint32_t count);
OnStopRequest(nsresult code);
+ DivertToParentUsing(PChannelDiverter diverter);
+
child:
Cancel(nsresult aStatus);
__delete__();
diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build
index 5c0e7dfb7fe3..af950623c405 100644
--- a/uriloader/exthandler/moz.build
+++ b/uriloader/exthandler/moz.build
@@ -56,7 +56,6 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
- 'ExternalHelperAppChild.cpp',
'ExternalHelperAppParent.cpp',
'nsLocalHandlerApp.cpp',
'nsMIMEInfoImpl.cpp',
@@ -64,6 +63,7 @@ UNIFIED_SOURCES += [
# These files can't be built in unified mode because they force NSPR logging.
SOURCES += [
+ 'ExternalHelperAppChild.cpp',
'nsExternalHelperAppService.cpp',
'nsExternalProtocolHandler.cpp',
]
diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
index 39aed0f4e5fa..c30065529e30 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -1202,10 +1202,10 @@ NS_INTERFACE_MAP_BEGIN(nsExternalAppHandler)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
- NS_INTERFACE_MAP_ENTRY(nsIHelperAppLauncher)
+ NS_INTERFACE_MAP_ENTRY(nsIHelperAppLauncher)
NS_INTERFACE_MAP_ENTRY(nsICancelable)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
- NS_INTERFACE_MAP_ENTRY(nsIBackgroundFileSaverObserver)
+ NS_INTERFACE_MAP_ENTRY(nsIBackgroundFileSaverObserver)
NS_INTERFACE_MAP_END_THREADSAFE
nsExternalAppHandler::nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo,
@@ -1271,6 +1271,15 @@ nsExternalAppHandler::~nsExternalAppHandler()
MOZ_ASSERT(!mSaver, "Saver should hold a reference to us until deleted");
}
+void
+nsExternalAppHandler::DidDivertRequest(nsIRequest *request)
+{
+ MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content, "in child process");
+ // Remove our request from the child loadGroup
+ RetargetLoadNotifications(request);
+ MaybeCloseWindow();
+}
+
NS_IMETHODIMP nsExternalAppHandler::SetWebProgressListener(nsIWebProgressListener2 * aWebProgressListener)
{
// This is always called by nsHelperDlg.js. Go ahead and register the
diff --git a/uriloader/exthandler/nsExternalHelperAppService.h b/uriloader/exthandler/nsExternalHelperAppService.h
index b029a59c85a2..8e5ed9948962 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -237,6 +237,11 @@ public:
~nsExternalAppHandler();
+ /**
+ * Clean up after the request was diverted to the parent process.
+ */
+ void DidDivertRequest(nsIRequest *request);
+
protected:
nsCOMPtr mTempFile;
nsCOMPtr mSourceUrl;