diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 48e9612f457b..d6f2faf92e04 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -52,7 +52,6 @@ #include "nsIAuthPrompt2.h" #include "nsIChannelEventSink.h" #include "nsIAsyncVerifyRedirectCallback.h" -#include "nsIServiceWorkerManager.h" #include "nsIScriptSecurityManager.h" #include "nsIScriptObjectPrincipal.h" #include "nsIScrollableFrame.h" @@ -1042,7 +1041,6 @@ NS_INTERFACE_MAP_BEGIN(nsDocShell) NS_INTERFACE_MAP_ENTRY(nsILinkHandler) NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands) NS_INTERFACE_MAP_ENTRY(nsIDOMStorageManager) - NS_INTERFACE_MAP_ENTRY(nsINetworkInterceptController) NS_INTERFACE_MAP_END_INHERITING(nsDocLoader) ///***************************************************************************** @@ -13923,52 +13921,6 @@ nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider, #endif } -NS_IMETHODIMP -nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate, bool* aShouldIntercept) -{ - *aShouldIntercept = false; - nsCOMPtr swm = mozilla::services::GetServiceWorkerManager(); - if (!swm) { - return NS_OK; - } - - if (aIsNavigate) { - return swm->IsAvailableForURI(aURI, aShouldIntercept); - } - - nsCOMPtr doc = GetDocument(); - if (!doc) { - return NS_ERROR_NOT_AVAILABLE; - } - - return swm->IsControlled(doc, aShouldIntercept); -} - -NS_IMETHODIMP -nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) -{ - nsCOMPtr swm = mozilla::services::GetServiceWorkerManager(); - if (!swm) { - aChannel->Cancel(); - return NS_OK; - } - - bool isNavigation = false; - nsresult rv = aChannel->GetIsNavigation(&isNavigation); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr doc; - - if (!isNavigation) { - doc = GetDocument(); - if (!doc) { - return NS_ERROR_NOT_AVAILABLE; - } - } - - return swm->DispatchFetchEvent(doc, aChannel); -} - NS_IMETHODIMP nsDocShell::SetPaymentRequestId(const nsAString& aPaymentRequestId) { diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 9b5094f2715f..d1a8ad2088a1 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -12,7 +12,6 @@ #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIBaseWindow.h" -#include "nsINetworkInterceptController.h" #include "nsIScrollable.h" #include "nsITextScroll.h" #include "nsIContentViewerContainer.h" @@ -153,7 +152,6 @@ class nsDocShell MOZ_FINAL , public nsILinkHandler , public nsIClipboardCommands , public nsIDOMStorageManager - , public nsINetworkInterceptController , public mozilla::SupportsWeakPtr { friend class nsDSURIContentListener; @@ -184,7 +182,6 @@ public: NS_DECL_NSIAUTHPROMPTPROVIDER NS_DECL_NSICLIPBOARDCOMMANDS NS_DECL_NSIWEBSHELLSERVICES - NS_DECL_NSINETWORKINTERCEPTCONTROLLER NS_FORWARD_SAFE_NSIDOMSTORAGEMANAGER(TopSessionStorageManager()) NS_IMETHOD Stop() MOZ_OVERRIDE { diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 3cbd872af6be..2b3269416500 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -622,7 +622,7 @@ protected: DECL_SHIM(nsIApplicationCacheContainer, NSIAPPLICATIONCACHECONTAINER) #undef DECL_SHIM }; - + /** * Add an ExternalResource for aURI. aViewer and aLoadGroup might be null * when this is called if the URI didn't result in an XML document. This diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 6555867e4241..3d3390fc2ac6 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -418,14 +418,6 @@ DOMInterfaces = { 'nativeType': 'mozilla::dom::workers::ExtendableEvent', }, -'FetchEvent': { - 'headerFile': 'ServiceWorkerEvents.h', - 'nativeType': 'mozilla::dom::workers::FetchEvent', - 'binaryNames': { - 'request': 'request_' - }, -}, - 'FileList': { 'headerFile': 'mozilla/dom/File.h', }, diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index ce1e7c822c55..9abbd7824c3e 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -866,11 +866,6 @@ FetchBody::FetchBody(); template FetchBody::FetchBody(); -template -FetchBody::~FetchBody() -{ -} - // Returns true if addref succeeded. // Always succeeds on main thread. // May fail on worker if RegisterFeature() fails. In that case, it will release diff --git a/dom/fetch/Fetch.h b/dom/fetch/Fetch.h index 6b86f0d444af..d3090fea1a5e 100644 --- a/dom/fetch/Fetch.h +++ b/dom/fetch/Fetch.h @@ -135,12 +135,6 @@ public: void CancelPump(); - void - SetBodyUsed() - { - mBodyUsed = true; - } - // Always set whenever the FetchBody is created on the worker thread. workers::WorkerPrivate* mWorkerPrivate; @@ -151,7 +145,15 @@ public: protected: FetchBody(); - virtual ~FetchBody(); + virtual ~FetchBody() + { + } + + void + SetBodyUsed() + { + mBodyUsed = true; + } void SetMimeType(ErrorResult& aRv); diff --git a/dom/interfaces/base/nsIServiceWorkerManager.idl b/dom/interfaces/base/nsIServiceWorkerManager.idl index 2cec7919a442..acd45e9d5182 100644 --- a/dom/interfaces/base/nsIServiceWorkerManager.idl +++ b/dom/interfaces/base/nsIServiceWorkerManager.idl @@ -6,7 +6,6 @@ #include "domstubs.idl" interface nsIDocument; -interface nsIInterceptedChannel; interface nsIPrincipal; interface nsIURI; @@ -19,7 +18,7 @@ interface nsIServiceWorkerUnregisterCallback : nsISupports [noscript] void UnregisterFailed(); }; -[builtinclass, uuid(464882c8-81c0-4620-b9c4-44c12085b65b)] +[builtinclass, uuid(861b55e9-d6ac-47cf-a528-8590e9b44de6)] interface nsIServiceWorkerManager : nsISupports { /** @@ -52,15 +51,6 @@ interface nsIServiceWorkerManager : nsISupports // Remove ready pending Promise void removeReadyPromise(in nsIDOMWindow aWindow); - // Returns true if a ServiceWorker is available for the scope of aURI. - bool isAvailableForURI(in nsIURI aURI); - - // Returns true if a given document is currently controlled by a ServiceWorker - bool isControlled(in nsIDocument aDocument); - - // Cause a fetch event to be dispatched to the worker global associated with the given document. - void dispatchFetchEvent(in nsIDocument aDoc, in nsIInterceptedChannel aChannel); - // aTarget MUST be a ServiceWorkerRegistration. [noscript] void AddRegistrationEventListener(in DOMString aScope, in nsIDOMEventTarget aTarget); [noscript] void RemoveRegistrationEventListener(in DOMString aScope, in nsIDOMEventTarget aTarget); diff --git a/dom/webidl/FetchEvent.webidl b/dom/webidl/FetchEvent.webidl deleted file mode 100644 index 20c378176743..000000000000 --- a/dom/webidl/FetchEvent.webidl +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * For more information on this interface, please see - * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html - */ - -[Constructor(DOMString type, optional FetchEventInit eventInitDict), - Func="mozilla::dom::workers::ServiceWorkerVisible", - Exposed=(ServiceWorker)] -interface FetchEvent : Event { - readonly attribute Request request; - readonly attribute ServiceWorkerClient client; // The window issuing the request. - readonly attribute boolean isReload; - - [Throws] void respondWith(Promise r); - Promise forwardTo(USVString url); - Promise default(); -}; - -dictionary FetchEventInit : EventInit { - Request request; - ServiceWorkerClient client; - boolean isReload; -}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 4cdf32fcff68..6cd53553419c 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -132,7 +132,6 @@ WEBIDL_FILES = [ 'EventTarget.webidl', 'ExtendableEvent.webidl', 'Fetch.webidl', - 'FetchEvent.webidl', 'File.webidl', 'FileList.webidl', 'FileMode.webidl', diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp index 6199f3b5f405..2e53e4d6d598 100644 --- a/dom/workers/ServiceWorkerEvents.cpp +++ b/dom/workers/ServiceWorkerEvents.cpp @@ -5,20 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ServiceWorkerEvents.h" -#include "ServiceWorkerClient.h" -#include "nsINetworkInterceptController.h" -#include "nsIOutputStream.h" #include "nsContentUtils.h" -#include "nsComponentManagerUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsStreamUtils.h" -#include "nsNetCID.h" -#include "mozilla/dom/FetchEventBinding.h" -#include "mozilla/dom/PromiseNativeHandler.h" -#include "mozilla/dom/Request.h" -#include "mozilla/dom/Response.h" #include "mozilla/dom/WorkerScope.h" #include "mozilla/dom/workers/bindings/ServiceWorker.h" @@ -26,271 +15,6 @@ using namespace mozilla::dom; BEGIN_WORKERS_NAMESPACE -FetchEvent::FetchEvent(EventTarget* aOwner) -: Event(aOwner, nullptr, nullptr) -, mWindowId(0) -, mIsReload(false) -, mWaitToRespond(false) -{ -} - -FetchEvent::~FetchEvent() -{ -} - -void -FetchEvent::PostInit(nsMainThreadPtrHandle& aChannel, - nsMainThreadPtrHandle& aServiceWorker, - uint64_t aWindowId) -{ - mChannel = aChannel; - mServiceWorker = aServiceWorker; - mWindowId = aWindowId; -} - -/*static*/ already_AddRefed -FetchEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const FetchEventInit& aOptions, - ErrorResult& aRv) -{ - nsRefPtr owner = do_QueryObject(aGlobal.GetAsSupports()); - MOZ_ASSERT(owner); - nsRefPtr e = new FetchEvent(owner); - bool trusted = e->Init(owner); - e->InitEvent(aType, aOptions.mBubbles, aOptions.mCancelable); - e->SetTrusted(trusted); - e->mRequest = aOptions.mRequest.WasPassed() ? - &aOptions.mRequest.Value() : nullptr; - e->mIsReload = aOptions.mIsReload.WasPassed() ? - aOptions.mIsReload.Value() : false; - e->mClient = aOptions.mClient.WasPassed() ? - &aOptions.mClient.Value() : nullptr; - return e.forget(); -} - -namespace { - -class CancelChannelRunnable MOZ_FINAL : public nsRunnable -{ - nsMainThreadPtrHandle mChannel; -public: - explicit CancelChannelRunnable(nsMainThreadPtrHandle& aChannel) - : mChannel(aChannel) - { - } - - NS_IMETHOD Run() - { - MOZ_ASSERT(NS_IsMainThread()); - nsresult rv = mChannel->Cancel(); - NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; - } -}; - -class FinishResponse MOZ_FINAL : public nsRunnable -{ - nsMainThreadPtrHandle mChannel; -public: - explicit FinishResponse(nsMainThreadPtrHandle& aChannel) - : mChannel(aChannel) - { - } - - NS_IMETHOD - Run() - { - AssertIsOnMainThread(); - nsresult rv = mChannel->FinishSynthesizedResponse(); - NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to finish synthesized response"); - return rv; - } -}; - -class RespondWithHandler MOZ_FINAL : public PromiseNativeHandler -{ - nsMainThreadPtrHandle mInterceptedChannel; - nsMainThreadPtrHandle mServiceWorker; -public: - RespondWithHandler(nsMainThreadPtrHandle& aChannel, - nsMainThreadPtrHandle& aServiceWorker) - : mInterceptedChannel(aChannel) - , mServiceWorker(aServiceWorker) - { - } - - void ResolvedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE; - - void RejectedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE; - - void CancelRequest(); -}; - -struct RespondWithClosure -{ - nsMainThreadPtrHandle mInterceptedChannel; - - explicit RespondWithClosure(nsMainThreadPtrHandle& aChannel) - : mInterceptedChannel(aChannel) - { - } -}; - -void RespondWithCopyComplete(void* aClosure, nsresult aStatus) -{ - nsAutoPtr data(static_cast(aClosure)); - nsCOMPtr event; - if (NS_SUCCEEDED(aStatus)) { - event = new FinishResponse(data->mInterceptedChannel); - } else { - event = new CancelChannelRunnable(data->mInterceptedChannel); - } - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(event))); -} - -class MOZ_STACK_CLASS AutoCancel -{ - nsRefPtr mOwner; - -public: - explicit AutoCancel(RespondWithHandler* aOwner) - : mOwner(aOwner) - { - } - - ~AutoCancel() - { - if (mOwner) { - mOwner->CancelRequest(); - } - } - - void Reset() - { - mOwner = nullptr; - } -}; - -void -RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle aValue) -{ - AutoCancel autoCancel(this); - - if (!aValue.isObject()) { - return; - } - - nsRefPtr response; - nsresult rv = UNWRAP_OBJECT(Response, &aValue.toObject(), response); - if (NS_FAILED(rv)) { - return; - } - - nsCOMPtr body; - response->GetBody(getter_AddRefs(body)); - if (NS_WARN_IF(!body) || NS_WARN_IF(response->BodyUsed())) { - return; - } - response->SetBodyUsed(); - - nsCOMPtr responseBody; - rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - nsAutoPtr closure(new RespondWithClosure(mInterceptedChannel)); - - nsCOMPtr stsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); - if (NS_WARN_IF(!stsThread)) { - return; - } - rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_READSEGMENTS, 4096, - RespondWithCopyComplete, closure.forget()); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - autoCancel.Reset(); -} - -void -RespondWithHandler::RejectedCallback(JSContext* aCx, JS::Handle aValue) -{ - CancelRequest(); -} - -void -RespondWithHandler::CancelRequest() -{ - nsCOMPtr runnable = new CancelChannelRunnable(mInterceptedChannel); - NS_DispatchToMainThread(runnable); -} - -} // anonymous namespace - -void -FetchEvent::RespondWith(Promise& aPromise, ErrorResult& aRv) -{ - if (mWaitToRespond) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - - mWaitToRespond = true; - nsRefPtr handler = new RespondWithHandler(mChannel, mServiceWorker); - aPromise.AppendNativeHandler(handler); -} - -already_AddRefed -FetchEvent::Client() -{ - if (!mClient) { - mClient = new ServiceWorkerClient(GetParentObject(), mWindowId); - } - nsRefPtr client = mClient; - return client.forget(); -} - -already_AddRefed -FetchEvent::ForwardTo(const nsAString& aUrl) -{ - nsCOMPtr global = do_QueryInterface(GetParentObject()); - MOZ_ASSERT(global); - ErrorResult result; - nsRefPtr promise = Promise::Create(global, result); - if (NS_WARN_IF(result.Failed())) { - return nullptr; - } - - promise->MaybeReject(NS_ERROR_NOT_AVAILABLE); - return promise.forget(); -} - -already_AddRefed -FetchEvent::Default() -{ - nsCOMPtr global = do_QueryInterface(GetParentObject()); - MOZ_ASSERT(global); - ErrorResult result; - nsRefPtr promise = Promise::Create(global, result); - if (result.Failed()) { - return nullptr; - } - - promise->MaybeReject(NS_ERROR_NOT_AVAILABLE); - return promise.forget(); -} - -NS_IMPL_ADDREF_INHERITED(FetchEvent, Event) -NS_IMPL_RELEASE_INHERITED(FetchEvent, Event) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FetchEvent) -NS_INTERFACE_MAP_END_INHERITING(Event) - -NS_IMPL_CYCLE_COLLECTION_INHERITED(FetchEvent, Event, mRequest, mClient) - ExtendableEvent::ExtendableEvent(EventTarget* aOwner) : Event(aOwner, nullptr, nullptr) { diff --git a/dom/workers/ServiceWorkerEvents.h b/dom/workers/ServiceWorkerEvents.h index 7a20cc87995c..04f30ccef88c 100644 --- a/dom/workers/ServiceWorkerEvents.h +++ b/dom/workers/ServiceWorkerEvents.h @@ -8,87 +8,12 @@ #include "mozilla/dom/Event.h" #include "mozilla/dom/ExtendableEventBinding.h" -#include "mozilla/dom/FetchEventBinding.h" #include "mozilla/dom/InstallEventBinding.h" #include "mozilla/dom/Promise.h" -#include "nsProxyRelease.h" - -class nsIInterceptedChannel; - -namespace mozilla { -namespace dom { - class Request; -} // namespace dom -} // namespace mozilla BEGIN_WORKERS_NAMESPACE class ServiceWorker; -class ServiceWorkerClient; - -class FetchEvent MOZ_FINAL : public Event -{ - nsMainThreadPtrHandle mChannel; - nsMainThreadPtrHandle mServiceWorker; - nsRefPtr mClient; - nsRefPtr mRequest; - uint64_t mWindowId; - bool mIsReload; - bool mWaitToRespond; -protected: - explicit FetchEvent(EventTarget* aOwner); - ~FetchEvent(); - -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchEvent, Event) - NS_FORWARD_TO_EVENT - - virtual JSObject* WrapObjectInternal(JSContext* aCx) MOZ_OVERRIDE - { - return FetchEventBinding::Wrap(aCx, this); - } - - void PostInit(nsMainThreadPtrHandle& aChannel, - nsMainThreadPtrHandle& aServiceWorker, - uint64_t aWindowId); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const FetchEventInit& aOptions, - ErrorResult& aRv); - - bool - WaitToRespond() const - { - return mWaitToRespond; - } - - Request* - Request_() const - { - return mRequest; - } - - already_AddRefed - Client(); - - bool - IsReload() const - { - return mIsReload; - } - - void - RespondWith(Promise& aPromise, ErrorResult& aRv); - - already_AddRefed - ForwardTo(const nsAString& aUrl); - - already_AddRefed - Default(); -}; class ExtendableEvent : public Event { diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 208a8144d055..c1dd85644f23 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -11,10 +11,7 @@ #include "nsIStreamLoader.h" #include "nsIHttpChannel.h" #include "nsIHttpChannelInternal.h" -#include "nsIHttpHeaderVisitor.h" -#include "nsINetworkInterceptController.h" #include "nsPIDOMWindow.h" -#include "nsDebug.h" #include "jsapi.h" @@ -22,13 +19,9 @@ #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/DOMError.h" #include "mozilla/dom/ErrorEvent.h" -#include "mozilla/dom/Headers.h" #include "mozilla/dom/InstallEventBinding.h" -#include "mozilla/dom/InternalHeaders.h" #include "mozilla/dom/Navigator.h" #include "mozilla/dom/PromiseNativeHandler.h" -#include "mozilla/dom/Request.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/PBackgroundChild.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" @@ -2128,267 +2121,6 @@ ServiceWorkerManager::GetServiceWorkerForScope(nsIDOMWindow* aWindow, return NS_OK; } -class FetchEventRunnable : public WorkerRunnable - , public nsIHttpHeaderVisitor { - nsMainThreadPtrHandle mInterceptedChannel; - nsMainThreadPtrHandle mServiceWorker; - nsTArray mHeaderNames; - nsTArray mHeaderValues; - uint64_t mWindowId; - nsCString mSpec; - nsCString mMethod; - bool mIsReload; -public: - FetchEventRunnable(WorkerPrivate* aWorkerPrivate, - nsMainThreadPtrHandle& aChannel, - nsMainThreadPtrHandle& aServiceWorker, - uint64_t aWindowId) - : WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount) - , mInterceptedChannel(aChannel) - , mServiceWorker(aServiceWorker) - , mWindowId(aWindowId) - { - MOZ_ASSERT(aWorkerPrivate); - } - - NS_DECL_ISUPPORTS_INHERITED - - NS_IMETHOD - VisitHeader(const nsACString& aHeader, const nsACString& aValue) - { - mHeaderNames.AppendElement(aHeader); - mHeaderValues.AppendElement(aValue); - return NS_OK; - } - - nsresult - Init() - { - nsCOMPtr channel; - nsresult rv = mInterceptedChannel->GetChannel(getter_AddRefs(channel)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr uri; - rv = channel->GetURI(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = uri->GetSpec(mSpec); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr httpChannel = do_QueryInterface(channel); - NS_ENSURE_TRUE(httpChannel, NS_ERROR_NOT_AVAILABLE); - - rv = httpChannel->GetRequestMethod(mMethod); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t loadFlags; - rv = channel->GetLoadFlags(&loadFlags); - NS_ENSURE_SUCCESS(rv, rv); - - //TODO(jdm): we should probably include reload-ness in the loadinfo or as a separate load flag - mIsReload = false; - - rv = httpChannel->VisitRequestHeaders(this); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; - } - - bool - WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) - { - MOZ_ASSERT(aWorkerPrivate); - return DispatchFetchEvent(aCx, aWorkerPrivate); - } - -private: - ~FetchEventRunnable() {} - - class ResumeRequest MOZ_FINAL : public nsRunnable { - nsMainThreadPtrHandle mChannel; - public: - explicit ResumeRequest(nsMainThreadPtrHandle& aChannel) - : mChannel(aChannel) - { - } - - NS_IMETHOD Run() - { - AssertIsOnMainThread(); - nsresult rv = mChannel->ResetInterception(); - NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to resume intercepted network request"); - return rv; - } - }; - - bool - DispatchFetchEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate) - { - MOZ_ASSERT(aCx); - MOZ_ASSERT(aWorkerPrivate); - MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); - GlobalObject globalObj(aCx, aWorkerPrivate->GlobalScope()->GetWrapper()); - - RequestOrUSVString requestInfo; - *requestInfo.SetAsUSVString().ToAStringPtr() = NS_ConvertUTF8toUTF16(mSpec); - - RootedDictionary reqInit(aCx); - reqInit.mMethod.Construct(mMethod); - - nsRefPtr internalHeaders = new InternalHeaders(HeadersGuardEnum::Request); - MOZ_ASSERT(mHeaderNames.Length() == mHeaderValues.Length()); - for (uint32_t i = 0; i < mHeaderNames.Length(); i++) { - ErrorResult rv; - internalHeaders->Set(mHeaderNames[i], mHeaderValues[i], rv); - if (NS_WARN_IF(rv.Failed())) { - return false; - } - } - - nsRefPtr headers = new Headers(globalObj.GetAsSupports(), internalHeaders); - reqInit.mHeaders.Construct(); - reqInit.mHeaders.Value().SetAsHeaders() = headers; - - //TODO(jdm): set request body - //TODO(jdm): set request same-origin mode and credentials - - ErrorResult rv; - nsRefPtr request = Request::Constructor(globalObj, requestInfo, reqInit, rv); - if (NS_WARN_IF(rv.Failed())) { - return false; - } - - RootedDictionary init(aCx); - init.mRequest.Construct(); - init.mRequest.Value() = request; - init.mBubbles = false; - init.mCancelable = true; - init.mIsReload.Construct(mIsReload); - nsRefPtr event = - FetchEvent::Constructor(globalObj, NS_LITERAL_STRING("fetch"), init, rv); - if (NS_WARN_IF(rv.Failed())) { - return false; - } - - event->PostInit(mInterceptedChannel, mServiceWorker, mWindowId); - event->SetTrusted(true); - - nsRefPtr target = do_QueryObject(aWorkerPrivate->GlobalScope()); - nsresult rv2 = target->DispatchDOMEvent(nullptr, event, nullptr, nullptr); - if (NS_WARN_IF(NS_FAILED(rv2)) || !event->WaitToRespond()) { - nsCOMPtr runnable = new ResumeRequest(mInterceptedChannel); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable))); - } - return true; - } -}; - -NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVisitor) - -NS_IMETHODIMP -ServiceWorkerManager::DispatchFetchEvent(nsIDocument* aDoc, nsIInterceptedChannel* aChannel) -{ - MOZ_ASSERT(aChannel); - nsCOMPtr serviceWorker; - - bool isNavigation = false; - nsresult rv = aChannel->GetIsNavigation(&isNavigation); - NS_ENSURE_SUCCESS(rv, rv); - - if (!isNavigation) { - MOZ_ASSERT(aDoc); - rv = GetDocumentController(aDoc->GetWindow(), getter_AddRefs(serviceWorker)); - } else { - nsCOMPtr internalChannel; - rv = aChannel->GetChannel(getter_AddRefs(internalChannel)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr uri; - rv = internalChannel->GetURI(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr registration = - GetServiceWorkerRegistrationInfo(uri); - // This should only happen if IsAvailableForURI() returned true. - MOZ_ASSERT(registration); - MOZ_ASSERT(registration->mActiveWorker); - - nsRefPtr sw; - rv = CreateServiceWorker(registration->mPrincipal, - registration->mActiveWorker->ScriptSpec(), - registration->mScope, - getter_AddRefs(sw)); - serviceWorker = sw.forget(); - } - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsMainThreadPtrHandle handle( - new nsMainThreadPtrHolder(aChannel, false)); - - uint64_t windowId = aDoc ? aDoc->GetInnerWindow()->WindowID() : 0; - - nsRefPtr sw = static_cast(serviceWorker.get()); - nsMainThreadPtrHandle serviceWorkerHandle( - new nsMainThreadPtrHolder(sw)); - - nsRefPtr event = - new FetchEventRunnable(sw->GetWorkerPrivate(), handle, serviceWorkerHandle, windowId); - rv = event->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - AutoJSAPI api; - api.Init(); - if (NS_WARN_IF(!event->Dispatch(api.cx()))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -NS_IMETHODIMP -ServiceWorkerManager::IsAvailableForURI(nsIURI* aURI, bool* aIsAvailable) -{ - MOZ_ASSERT(aURI); - MOZ_ASSERT(aIsAvailable); - nsRefPtr registration = - GetServiceWorkerRegistrationInfo(aURI); - *aIsAvailable = registration && registration->mActiveWorker; - return NS_OK; -} - -NS_IMETHODIMP -ServiceWorkerManager::IsControlled(nsIDocument* aDoc, bool* aIsControlled) -{ - MOZ_ASSERT(aDoc); - MOZ_ASSERT(aIsControlled); - nsRefPtr registration; - nsresult rv = GetDocumentRegistration(aDoc, getter_AddRefs(registration)); - NS_ENSURE_SUCCESS(rv, rv); - *aIsControlled = !!registration; - return NS_OK; -} - -nsresult -ServiceWorkerManager::GetDocumentRegistration(nsIDocument* aDoc, - ServiceWorkerRegistrationInfo** aRegistrationInfo) -{ - nsRefPtr registration; - if (!mControlledDocuments.Get(aDoc, getter_AddRefs(registration))) { - return NS_ERROR_FAILURE; - } - - // If the document is controlled, the current worker MUST be non-null. - if (!registration->mActiveWorker) { - return NS_ERROR_NOT_AVAILABLE; - } - - registration.forget(aRegistrationInfo); - return NS_OK; -} - /* * The .controller is for the registration associated with the document when * the document was loaded. @@ -2405,16 +2137,21 @@ ServiceWorkerManager::GetDocumentController(nsIDOMWindow* aWindow, nsISupports** nsCOMPtr doc = window->GetExtantDoc(); nsRefPtr registration; - nsresult rv = GetDocumentRegistration(doc, getter_AddRefs(registration)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; + if (!mControlledDocuments.Get(doc, getter_AddRefs(registration))) { + return NS_ERROR_FAILURE; } + // If the document is controlled, the current worker MUST be non-null. + if (!registration->mActiveWorker) { + return NS_ERROR_NOT_AVAILABLE; + } + + nsRefPtr serviceWorker; - rv = CreateServiceWorkerForWindow(window, - registration->mActiveWorker->ScriptSpec(), - registration->mScope, - getter_AddRefs(serviceWorker)); + nsresult rv = CreateServiceWorkerForWindow(window, + registration->mActiveWorker->ScriptSpec(), + registration->mScope, + getter_AddRefs(serviceWorker)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } diff --git a/dom/workers/ServiceWorkerManager.h b/dom/workers/ServiceWorkerManager.h index c5f8ff5c8b17..e642e08ed9c9 100644 --- a/dom/workers/ServiceWorkerManager.h +++ b/dom/workers/ServiceWorkerManager.h @@ -399,9 +399,6 @@ private: nsresult Update(ServiceWorkerRegistrationInfo* aRegistration); - nsresult - GetDocumentRegistration(nsIDocument* aDoc, ServiceWorkerRegistrationInfo** aRegistrationInfo); - NS_IMETHOD CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow, const nsACString& aScriptSpec, diff --git a/dom/workers/test/serviceworkers/fetch/fetch_tests.js b/dom/workers/test/serviceworkers/fetch/fetch_tests.js deleted file mode 100644 index e6900b6860d3..000000000000 --- a/dom/workers/test/serviceworkers/fetch/fetch_tests.js +++ /dev/null @@ -1,54 +0,0 @@ -function fetch(name, onload, onerror, headers) { - expectAsyncResult(); - - onload = onload || function() { - my_ok(false, "XHR load should not complete successfully"); - finish(); - }; - onerror = onerror || function() { - my_ok(false, "XHR load should be intercepted successfully"); - finish(); - }; - - var x = new XMLHttpRequest(); - x.open('GET', name, true); - x.onload = function() { onload(x) }; - x.onerror = function() { onerror(x) }; - headers = headers || []; - headers.forEach(function(header) { - x.setRequestHeader(header[0], header[1]); - }); - x.send(); -} - -fetch('synthesized.txt', function(xhr) { - my_ok(xhr.status == 200, "load should be successful"); - my_ok(xhr.responseText == "synthesized response body", "load should have synthesized response"); - finish(); -}); - -fetch('ignored.txt', function(xhr) { - my_ok(xhr.status == 404, "load should be uninterrupted"); - finish(); -}); - -fetch('rejected.txt', null, function(xhr) { - my_ok(xhr.status == 0, "load should not complete"); - finish(); -}); - -fetch('nonresponse.txt', null, function(xhr) { - my_ok(xhr.status == 0, "load should not complete"); - finish(); -}); - -fetch('nonresponse2.txt', null, function(xhr) { - my_ok(xhr.status == 0, "load should not complete"); - finish(); -}); - -fetch('headers.txt', function(xhr) { - my_ok(xhr.status == 200, "load should be successful"); - my_ok(xhr.responseText == "1", "request header checks should have passed"); - finish(); -}, null, [["X-Test1", "header1"], ["X-Test2", "header2"]]); diff --git a/dom/workers/test/serviceworkers/fetch/fetch_worker_script.js b/dom/workers/test/serviceworkers/fetch/fetch_worker_script.js deleted file mode 100644 index 61efb647c8f9..000000000000 --- a/dom/workers/test/serviceworkers/fetch/fetch_worker_script.js +++ /dev/null @@ -1,29 +0,0 @@ -function my_ok(v, msg) { - postMessage({type: "ok", value: v, msg: msg}); -} - -function finish() { - postMessage('finish'); -} - -function expectAsyncResult() { - postMessage('expect'); -} - -expectAsyncResult(); -try { - var success = false; - importScripts("nonexistent_imported_script.js"); -} catch(x) { -} - -my_ok(success, "worker imported script should be intercepted"); -finish(); - -function check_intercepted_script() { - success = true; -} - -importScripts('fetch_tests.js') - -finish(); //corresponds to the gExpected increment before creating this worker diff --git a/dom/workers/test/serviceworkers/fetch/index.html b/dom/workers/test/serviceworkers/fetch/index.html deleted file mode 100644 index 88962f798956..000000000000 --- a/dom/workers/test/serviceworkers/fetch/index.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - Bug 94048 - test install event. - - - - -

- -
-

-
-
-
-
-
-
diff --git a/dom/workers/test/serviceworkers/fetch_event_worker.js b/dom/workers/test/serviceworkers/fetch_event_worker.js
deleted file mode 100644
index 107544828397..000000000000
--- a/dom/workers/test/serviceworkers/fetch_event_worker.js
+++ /dev/null
@@ -1,86 +0,0 @@
-onfetch = function(ev) {
-  if (ev.request.url.contains("synthesized.txt")) {
-    var p = new Promise(function(resolve) {
-      var r = new Response("synthesized response body", {});
-      resolve(r);
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("ignored.txt")) {
-  }
-
-  else if (ev.request.url.contains("rejected.txt")) {
-    var p = new Promise(function(resolve, reject) {
-      reject();
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("nonresponse.txt")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve(5);
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("nonresponse2.txt")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve({});
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("headers.txt")) {
-    var p = new Promise(function(resolve, reject) {
-      var ok = true;
-      ok &= ev.request.headers.get("X-Test1") == "header1";
-      ok &= ev.request.headers.get("X-Test2") == "header2";
-      var r = new Response(ok.toString(), {});
-      resolve(r);
-    });
-    ev.respondWith(p);    
-  }
-
-  else if (ev.request.url.contains("nonexistent_image.gif")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve(new Response(atob("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs"), {}));
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("nonexistent_script.js")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve(new Response("check_intercepted_script();", {}));
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("nonexistent_stylesheet.css")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve(new Response("#style-test { background-color: black !important; }", {}));
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("nonexistent_page.html")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve(new Response("", {}));
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("nonexistent_worker_script.js")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve(new Response("postMessage('worker-intercept-success')", {}));
-    });
-    ev.respondWith(p);
-  }
-
-  else if (ev.request.url.contains("nonexistent_imported_script.js")) {
-    var p = new Promise(function(resolve, reject) {
-      resolve(new Response("check_intercepted_script();", {}));
-    });
-    ev.respondWith(p);
-  }
-}
diff --git a/dom/workers/test/serviceworkers/mochitest.ini b/dom/workers/test/serviceworkers/mochitest.ini
index 074cba12d1d7..edc7d06c7420 100644
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -4,7 +4,6 @@ support-files =
   worker.js
   worker2.js
   worker3.js
-  fetch_event_worker.js
   parse_error_worker.js
   activate_event_error_worker.js
   install_event_worker.js
@@ -21,14 +20,10 @@ support-files =
   worker_unregister.js
   worker_update.js
   message_posting_worker.js
-  fetch/index.html
-  fetch/fetch_worker_script.js
-  fetch/fetch_tests.js
 
 [test_unregister.html]
 skip-if = true # Bug 1133805
 [test_installation_simple.html]
-[test_fetch_event.html]
 [test_get_serviced.html]
 [test_install_event.html]
 [test_navigator.html]
diff --git a/dom/workers/test/serviceworkers/test_fetch_event.html b/dom/workers/test/serviceworkers/test_fetch_event.html
deleted file mode 100644
index 090e6e4faf68..000000000000
--- a/dom/workers/test/serviceworkers/test_fetch_event.html
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-  Bug 94048 - test install event.
-  
-  
-
-
-

- -

-
-
-
-
-
diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
index 576082c24557..766e2cd9266a 100644
--- a/netwerk/base/nsINetworkInterceptController.idl
+++ b/netwerk/base/nsINetworkInterceptController.idl
@@ -5,7 +5,7 @@
 
 #include "nsISupports.idl"
 
-interface nsIChannel;
+interface nsIHttpChannelInternal;
 interface nsIOutputStream;
 interface nsIURI;
 
@@ -16,7 +16,7 @@ interface nsIURI;
  * which do not implement nsIChannel.
  */
 
-[scriptable, uuid(9d127b63-dfad-484d-a0e1-cb82697a095b)]
+[scriptable, uuid(0b5f82a7-5824-4a0d-bf5c-8a8a7684c0c8)]
 interface nsIInterceptedChannel : nsISupports
 {
     /**
@@ -37,28 +37,6 @@ interface nsIInterceptedChannel : nsISupports
      * after this point.
      */
     void finishSynthesizedResponse();
-
-    /**
-     * Cancel the pending intercepted request.
-     * @return NS_ERROR_FAILURE if the response has already been synthesized or
-     *         the original request has been instructed to continue.
-     */
-    void cancel();
-
-    /**
-     * The synthesized response body to be produced.
-     */
-    readonly attribute nsIOutputStream responseBody;
-
-    /**
-     * The underlying channel object that was intercepted.
-     */
-    readonly attribute nsIChannel channel;
-
-    /**
-     * True if the underlying request was caused by a navigation attempt.
-     */
-    readonly attribute bool isNavigation;
 };
 
 /**
@@ -67,7 +45,7 @@ interface nsIInterceptedChannel : nsISupports
  * request should be intercepted before any network request is initiated.
  */
 
-[scriptable, uuid(69150b77-b561-43a2-bfba-7301dd5a35d0)]
+[scriptable, uuid(b3ad3e9b-91d8-44d0-a0c5-dc2e9374f599)]
 interface nsINetworkInterceptController : nsISupports
 {
     /**
@@ -75,15 +53,15 @@ interface nsINetworkInterceptController : nsISupports
      * requests until specifically instructed to do so.
      *
      * @param aURI the URI being requested by a channel
-     * @param aIsNavigate True if the request is for a navigation, false for a fetch.
      */
-    bool shouldPrepareForIntercept(in nsIURI aURI, in bool aIsNavigate);
+    bool shouldPrepareForIntercept(in nsIURI aURI);
 
     /**
      * Notification when a given intercepted channel is prepared to accept a synthesized
      * response via the provided stream.
      *
      * @param aChannel the controlling interface for a channel that has been intercepted
+     * @param aStream a stream directly into the channel's synthesized response body
      */
-    void channelIntercepted(in nsIInterceptedChannel aChannel);
+    void channelIntercepted(in nsIInterceptedChannel aChannel, in nsIOutputStream aStream);
 };
diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
index 69a3594179e0..a8786f2c6ed6 100644
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1933,12 +1933,6 @@ HttpBaseChannel::GetURIPrincipal()
   return mPrincipal;
 }
 
-bool
-HttpBaseChannel::IsNavigation()
-{
-  return mLoadFlags & LOAD_DOCUMENT_URI;
-}
-
 bool
 HttpBaseChannel::ShouldIntercept()
 {
@@ -1946,9 +1940,7 @@ HttpBaseChannel::ShouldIntercept()
   GetCallback(controller);
   bool shouldIntercept = false;
   if (controller && !mForceNoIntercept) {
-    nsresult rv = controller->ShouldPrepareForIntercept(mURI,
-                                                        IsNavigation(),
-                                                        &shouldIntercept);
+    nsresult rv = controller->ShouldPrepareForIntercept(mURI, &shouldIntercept);
     NS_ENSURE_SUCCESS(rv, false);
   }
   return shouldIntercept;
diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h
index de7d0ba26553..a26bc2df96e6 100644
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -241,7 +241,7 @@ public:
     const NetAddr& GetPeerAddr() { return mPeerAddr; }
 
 public: /* Necko internal use only... */
-    bool IsNavigation();
+
 
     // Return whether upon a redirect code of httpStatus for method, the
     // request method should be rewritten to GET.
diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp
index 944894343dac..741d0e4ae007 100644
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -56,111 +56,6 @@ static_assert(FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE == 250,
 
 }
 
-// A stream listener interposed between the nsInputStreamPump used for intercepted channels
-// and this channel's original listener. This is only used to ensure the original listener
-// sees the channel as the request object, and to synthesize OnStatus and OnProgress notifications.
-class InterceptStreamListener : public nsIStreamListener
-                              , public nsIProgressEventSink
-{
-  nsRefPtr mOwner;
-  nsCOMPtr mContext;
-  virtual ~InterceptStreamListener() {}
- public:
-  InterceptStreamListener(HttpChannelChild* aOwner, nsISupports* aContext)
-  : mOwner(aOwner)
-  , mContext(aContext)
-  {
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIREQUESTOBSERVER
-  NS_DECL_NSISTREAMLISTENER
-  NS_DECL_NSIPROGRESSEVENTSINK
-
-  void Cleanup();
-};
-
-NS_IMPL_ISUPPORTS(InterceptStreamListener,
-                  nsIStreamListener,
-                  nsIRequestObserver,
-                  nsIProgressEventSink)
-
-NS_IMETHODIMP
-InterceptStreamListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
-{
-  if (mOwner) {
-    mOwner->DoOnStartRequest(mOwner, mContext);
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptStreamListener::OnStatus(nsIRequest* aRequest, nsISupports* aContext,
-                                  nsresult status, const char16_t* aStatusArg)
-{
-  if (mOwner) {
-    mOwner->DoOnStatus(mOwner, status);
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptStreamListener::OnProgress(nsIRequest* aRequest, nsISupports* aContext,
-                                    int64_t aProgress, int64_t aProgressMax)
-{
-  if (mOwner) {
-    mOwner->DoOnProgress(mOwner, aProgress, aProgressMax);
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptStreamListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
-                                         nsIInputStream* aInputStream, uint64_t aOffset,
-                                         uint32_t aCount)
-{
-  if (!mOwner) {
-    return NS_OK;
-  }
-
-  uint32_t loadFlags;
-  mOwner->GetLoadFlags(&loadFlags);
-
-  if (!(loadFlags & HttpBaseChannel::LOAD_BACKGROUND)) {
-    nsCOMPtr uri;
-    mOwner->GetURI(getter_AddRefs(uri));
-
-    nsAutoCString host;
-    uri->GetHost(host);
-
-    OnStatus(mOwner, aContext, NS_NET_STATUS_READING, NS_ConvertUTF8toUTF16(host).get());
-
-    int64_t progress = aOffset + aCount;
-    OnProgress(mOwner, aContext, progress, mOwner->GetResponseHead()->ContentLength());
-  }
-
-  mOwner->DoOnDataAvailable(mOwner, mContext, aInputStream, aOffset, aCount);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptStreamListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatusCode)
-{
-  if (mOwner) {
-    mOwner->DoPreOnStopRequest(aStatusCode);
-    mOwner->DoOnStopRequest(mOwner, mContext);
-  }
-  Cleanup();
-  return NS_OK;
-}
-
-void
-InterceptStreamListener::Cleanup()
-{
-  mOwner = nullptr;
-  mContext = nullptr;
-}
-
 //-----------------------------------------------------------------------------
 // HttpChannelChild
 //-----------------------------------------------------------------------------
@@ -957,10 +852,6 @@ HttpChannelChild::DoNotifyListenerCleanup()
   LOG(("HttpChannelChild::DoNotifyListenerCleanup [this=%p]\n", this));
   if (mIPCOpen)
     PHttpChannelChild::Send__delete__(this);
-  if (mInterceptListener) {
-    mInterceptListener->Cleanup();
-    mInterceptListener = nullptr;
-  }
 }
 
 class DeleteSelfEvent : public ChannelEvent
@@ -1346,10 +1237,6 @@ HttpChannelChild::Cancel(nsresult status)
     mStatus = status;
     if (RemoteChannelExists())
       SendCancel(status);
-    if (mSynthesizedResponsePump) {
-      mSynthesizedResponsePump->Cancel(status);
-    }
-    mInterceptListener = nullptr;
   }
   return NS_OK;
 }
@@ -1456,6 +1343,89 @@ HttpChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
   return NS_OK;
 }
 
+// A stream listener interposed between the nsInputStreamPump used for intercepted channels
+// and this channel's original listener. This is only used to ensure the original listener
+// sees the channel as the request object, and to synthesize OnStatus and OnProgress notifications.
+class InterceptStreamListener : public nsIStreamListener
+                              , public nsIProgressEventSink
+{
+  nsRefPtr mOwner;
+  nsCOMPtr mContext;
+  virtual ~InterceptStreamListener() {}
+public:
+  InterceptStreamListener(HttpChannelChild* aOwner, nsISupports* aContext)
+  : mOwner(aOwner)
+  , mContext(aContext)
+  {
+  }
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIREQUESTOBSERVER
+  NS_DECL_NSISTREAMLISTENER
+  NS_DECL_NSIPROGRESSEVENTSINK
+};
+
+NS_IMPL_ISUPPORTS(InterceptStreamListener,
+                  nsIStreamListener,
+                  nsIRequestObserver,
+                  nsIProgressEventSink)
+
+NS_IMETHODIMP
+InterceptStreamListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
+{
+  mOwner->DoOnStartRequest(mOwner, mContext);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptStreamListener::OnStatus(nsIRequest* aRequest, nsISupports* aContext,
+                                  nsresult status, const char16_t* aStatusArg)
+{
+  mOwner->DoOnStatus(mOwner, status);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptStreamListener::OnProgress(nsIRequest* aRequest, nsISupports* aContext,
+                                    int64_t aProgress, int64_t aProgressMax)
+{
+  mOwner->DoOnProgress(mOwner, aProgress, aProgressMax);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptStreamListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
+                                         nsIInputStream* aInputStream, uint64_t aOffset,
+                                         uint32_t aCount)
+{
+  uint32_t loadFlags;
+  mOwner->GetLoadFlags(&loadFlags);
+
+  if (!(loadFlags & HttpBaseChannel::LOAD_BACKGROUND)) {
+    nsCOMPtr uri;
+    mOwner->GetURI(getter_AddRefs(uri));
+
+    nsAutoCString host;
+    uri->GetHost(host);
+
+    OnStatus(mOwner, aContext, NS_NET_STATUS_READING, NS_ConvertUTF8toUTF16(host).get());
+
+    int64_t progress = aOffset + aCount;
+    OnProgress(mOwner, aContext, progress, mOwner->GetResponseHead()->ContentLength());
+  }
+
+  mOwner->DoOnDataAvailable(mOwner, mContext, aInputStream, aOffset, aCount);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+InterceptStreamListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatusCode)
+{
+  mOwner->DoPreOnStopRequest(aStatusCode);
+  mOwner->DoOnStopRequest(mOwner, mContext);
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
 {
@@ -2073,7 +2043,6 @@ HttpChannelChild::DivertToParent(ChannelDiverterChild **aChild)
 void
 HttpChannelChild::ResetInterception()
 {
-  mInterceptListener->Cleanup();
   mInterceptListener = nullptr;
 
   // Continue with the original cross-process request
@@ -2082,7 +2051,7 @@ HttpChannelChild::ResetInterception()
 }
 
 void
-HttpChannelChild::OverrideWithSynthesizedResponse(nsAutoPtr& aResponseHead,
+HttpChannelChild::OverrideWithSynthesizedResponse(nsHttpResponseHead* aResponseHead,
                                                   nsInputStreamPump* aPump)
 {
   mSynthesizedResponsePump = aPump;
@@ -2094,10 +2063,6 @@ HttpChannelChild::OverrideWithSynthesizedResponse(nsAutoPtr&
     nsresult rv = mSynthesizedResponsePump->Suspend();
     NS_ENSURE_SUCCESS_VOID(rv);
   }
-
-  if (mCanceled) {
-    mSynthesizedResponsePump->Cancel(mStatus);
-  }
 }
 
 }} // mozilla::net
diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h
index 4bca9eaa1282..53857a54169a 100644
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -159,7 +159,7 @@ private:
 
   // Override this channel's pending response with a synthesized one. The content will be
   // asynchronously read from the pump.
-  void OverrideWithSynthesizedResponse(nsAutoPtr& aResponseHead, nsInputStreamPump* aPump);
+  void OverrideWithSynthesizedResponse(nsHttpResponseHead* aResponseHead, nsInputStreamPump* aPump);
 
   RequestHeaderTuples mClientSetRequestHeaders;
   nsCOMPtr mRedirectChannelChild;
diff --git a/netwerk/protocol/http/InterceptedChannel.cpp b/netwerk/protocol/http/InterceptedChannel.cpp
index 9cc4ead8b476..7f5f8e38ad14 100644
--- a/netwerk/protocol/http/InterceptedChannel.cpp
+++ b/netwerk/protocol/http/InterceptedChannel.cpp
@@ -26,10 +26,8 @@ DoAddCacheEntryHeaders(nsHttpChannel *self,
 
 NS_IMPL_ISUPPORTS(InterceptedChannelBase, nsIInterceptedChannel)
 
-InterceptedChannelBase::InterceptedChannelBase(nsINetworkInterceptController* aController,
-                                               bool aIsNavigation)
+InterceptedChannelBase::InterceptedChannelBase(nsINetworkInterceptController* aController)
 : mController(aController)
-, mIsNavigation(aIsNavigation)
 {
 }
 
@@ -37,36 +35,21 @@ InterceptedChannelBase::~InterceptedChannelBase()
 {
 }
 
-NS_IMETHODIMP
-InterceptedChannelBase::GetResponseBody(nsIOutputStream** aStream)
-{
-  NS_IF_ADDREF(*aStream = mResponseBody);
-  return NS_OK;
-}
-
 void
 InterceptedChannelBase::EnsureSynthesizedResponse()
 {
   if (mSynthesizedResponseHead.isNothing()) {
-    mSynthesizedResponseHead.emplace(new nsHttpResponseHead());
+    mSynthesizedResponseHead.emplace();
   }
 }
 
 void
-InterceptedChannelBase::DoNotifyController()
+InterceptedChannelBase::DoNotifyController(nsIOutputStream* aOut)
 {
-    nsresult rv = mController->ChannelIntercepted(this);
-    mController = nullptr;
+    nsresult rv = mController->ChannelIntercepted(this, aOut);
     NS_ENSURE_SUCCESS_VOID(rv);
 }
 
-NS_IMETHODIMP
-InterceptedChannelBase::GetIsNavigation(bool* aIsNavigation)
-{
-  *aIsNavigation = mIsNavigation;
-  return NS_OK;
-}
-
 nsresult
 InterceptedChannelBase::DoSynthesizeHeader(const nsACString& aName, const nsACString& aValue)
 {
@@ -74,7 +57,7 @@ InterceptedChannelBase::DoSynthesizeHeader(const nsACString& aName, const nsACSt
 
     nsAutoCString header = aName + NS_LITERAL_CSTRING(": ") + aValue;
     // Overwrite any existing header.
-    nsresult rv = (*mSynthesizedResponseHead)->ParseHeaderLine(header.get());
+    nsresult rv = mSynthesizedResponseHead->ParseHeaderLine(header.get());
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
 }
@@ -82,7 +65,7 @@ InterceptedChannelBase::DoSynthesizeHeader(const nsACString& aName, const nsACSt
 InterceptedChannelChrome::InterceptedChannelChrome(nsHttpChannel* aChannel,
                                                    nsINetworkInterceptController* aController,
                                                    nsICacheEntry* aEntry)
-: InterceptedChannelBase(aController, aChannel->IsNavigation())
+: InterceptedChannelBase(aController)
 , mChannel(aChannel)
 , mSynthesizedCacheEntry(aEntry)
 {
@@ -93,17 +76,10 @@ InterceptedChannelChrome::NotifyController()
 {
   nsCOMPtr out;
 
-  nsresult rv = mSynthesizedCacheEntry->OpenOutputStream(0, getter_AddRefs(mResponseBody));
+  nsresult rv = mSynthesizedCacheEntry->OpenOutputStream(0, getter_AddRefs(out));
   NS_ENSURE_SUCCESS_VOID(rv);
 
-  DoNotifyController();
-}
-
-NS_IMETHODIMP
-InterceptedChannelChrome::GetChannel(nsIChannel** aChannel)
-{
-  NS_IF_ADDREF(*aChannel = mChannel);
-  return NS_OK;
+  DoNotifyController(out);
 }
 
 NS_IMETHODIMP
@@ -156,7 +132,7 @@ InterceptedChannelChrome::FinishSynthesizedResponse()
 
   rv = DoAddCacheEntryHeaders(mChannel, mSynthesizedCacheEntry,
                               mChannel->GetRequestHead(),
-                              mSynthesizedResponseHead.ref(), securityInfo);
+                              mSynthesizedResponseHead.ptr(), securityInfo);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr uri;
@@ -180,24 +156,10 @@ InterceptedChannelChrome::FinishSynthesizedResponse()
   return NS_OK;
 }
 
-NS_IMETHODIMP
-InterceptedChannelChrome::Cancel()
-{
-  if (!mChannel) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // we need to use AsyncAbort instead of Cancel since there's no active pump
-  // to cancel which will provide OnStart/OnStopRequest to the channel.
-  nsresult rv = mChannel->AsyncAbort(NS_BINDING_ABORTED);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return NS_OK;
-}
-
 InterceptedChannelContent::InterceptedChannelContent(HttpChannelChild* aChannel,
                                                      nsINetworkInterceptController* aController,
                                                      nsIStreamListener* aListener)
-: InterceptedChannelBase(aController, aChannel->IsNavigation())
+: InterceptedChannelBase(aController)
 , mChannel(aChannel)
 , mStreamListener(aListener)
 {
@@ -207,18 +169,11 @@ void
 InterceptedChannelContent::NotifyController()
 {
   nsresult rv = NS_NewPipe(getter_AddRefs(mSynthesizedInput),
-                           getter_AddRefs(mResponseBody),
+                           getter_AddRefs(mSynthesizedOutput),
                            0, UINT32_MAX, true, true);
   NS_ENSURE_SUCCESS_VOID(rv);
 
-  DoNotifyController();
-}
-
-NS_IMETHODIMP
-InterceptedChannelContent::GetChannel(nsIChannel** aChannel)
-{
-  NS_IF_ADDREF(*aChannel = mChannel);
-  return NS_OK;
+  DoNotifyController(mSynthesizedOutput);
 }
 
 NS_IMETHODIMP
@@ -228,7 +183,7 @@ InterceptedChannelContent::ResetInterception()
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  mResponseBody = nullptr;
+  mSynthesizedOutput = nullptr;
   mSynthesizedInput = nullptr;
 
   mChannel->ResetInterception();
@@ -239,7 +194,7 @@ InterceptedChannelContent::ResetInterception()
 NS_IMETHODIMP
 InterceptedChannelContent::SynthesizeHeader(const nsACString& aName, const nsACString& aValue)
 {
-  if (!mResponseBody) {
+  if (!mSynthesizedOutput) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
@@ -249,7 +204,7 @@ InterceptedChannelContent::SynthesizeHeader(const nsACString& aName, const nsACS
 NS_IMETHODIMP
 InterceptedChannelContent::FinishSynthesizedResponse()
 {
-  if (NS_WARN_IF(!mChannel)) {
+  if (!mChannel) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
@@ -257,36 +212,19 @@ InterceptedChannelContent::FinishSynthesizedResponse()
 
   nsresult rv = nsInputStreamPump::Create(getter_AddRefs(mStoragePump), mSynthesizedInput,
                                           int64_t(-1), int64_t(-1), 0, 0, true);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
+  if (NS_FAILED(rv)) {
     mSynthesizedInput->Close();
     return rv;
   }
 
-  mResponseBody = nullptr;
+  mSynthesizedOutput = nullptr;
 
   rv = mStoragePump->AsyncRead(mStreamListener, nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  mChannel->OverrideWithSynthesizedResponse(mSynthesizedResponseHead.ref(), mStoragePump);
+  mChannel->OverrideWithSynthesizedResponse(mSynthesizedResponseHead.ptr(), mStoragePump);
 
   mChannel = nullptr;
-  mStreamListener = nullptr;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-InterceptedChannelContent::Cancel()
-{
-  if (!mChannel) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // we need to use AsyncAbort instead of Cancel since there's no active pump
-  // to cancel which will provide OnStart/OnStopRequest to the channel.
-  nsresult rv = mChannel->AsyncAbort(NS_BINDING_ABORTED);
-  NS_ENSURE_SUCCESS(rv, rv);
-  mChannel = nullptr;
-  mStreamListener = nullptr;
   return NS_OK;
 }
 
diff --git a/netwerk/protocol/http/InterceptedChannel.h b/netwerk/protocol/http/InterceptedChannel.h
index 30da2551216a..695f5d5befa3 100644
--- a/netwerk/protocol/http/InterceptedChannel.h
+++ b/netwerk/protocol/http/InterceptedChannel.h
@@ -30,32 +30,22 @@ protected:
   // The interception controller to notify about the successful channel interception
   nsCOMPtr mController;
 
-  // The stream to write the body of the synthesized response
-  nsCOMPtr mResponseBody;
-
   // Response head for use when synthesizing
-  Maybe> mSynthesizedResponseHead;
-
-  // Whether this intercepted channel was performing a navigation.
-  bool mIsNavigation;
+  Maybe mSynthesizedResponseHead;
 
   void EnsureSynthesizedResponse();
-  void DoNotifyController();
+  void DoNotifyController(nsIOutputStream* aOut);
   nsresult DoSynthesizeHeader(const nsACString& aName, const nsACString& aValue);
 
   virtual ~InterceptedChannelBase();
 public:
-  InterceptedChannelBase(nsINetworkInterceptController* aController,
-                         bool aIsNavigation);
+  explicit InterceptedChannelBase(nsINetworkInterceptController* aController);
 
   // Notify the interception controller that the channel has been intercepted
   // and prepare the response body output stream.
   virtual void NotifyController() = 0;
 
   NS_DECL_ISUPPORTS
-
-  NS_IMETHOD GetResponseBody(nsIOutputStream** aOutput) MOZ_OVERRIDE;
-  NS_IMETHOD GetIsNavigation(bool* aIsNavigation) MOZ_OVERRIDE;
 };
 
 class InterceptedChannelChrome : public InterceptedChannelBase
@@ -70,11 +60,7 @@ public:
                            nsINetworkInterceptController* aController,
                            nsICacheEntry* aEntry);
 
-  NS_IMETHOD ResetInterception() MOZ_OVERRIDE;
-  NS_IMETHOD FinishSynthesizedResponse() MOZ_OVERRIDE;
-  NS_IMETHOD GetChannel(nsIChannel** aChannel) MOZ_OVERRIDE;
-  NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) MOZ_OVERRIDE;
-  NS_IMETHOD Cancel() MOZ_OVERRIDE;
+  NS_DECL_NSIINTERCEPTEDCHANNEL
 
   virtual void NotifyController() MOZ_OVERRIDE;
 };
@@ -84,7 +70,8 @@ class InterceptedChannelContent : public InterceptedChannelBase
   // The actual channel being intercepted.
   nsRefPtr mChannel;
 
-  // Reader-side of the response body when synthesizing in a child proces
+  // Writeable buffer for use when synthesizing a response in a child process
+  nsCOMPtr mSynthesizedOutput;
   nsCOMPtr mSynthesizedInput;
 
   // Pump to read the synthesized body in child processes
@@ -98,11 +85,7 @@ public:
                             nsINetworkInterceptController* aController,
                             nsIStreamListener* aListener);
 
-  NS_IMETHOD ResetInterception() MOZ_OVERRIDE;
-  NS_IMETHOD FinishSynthesizedResponse() MOZ_OVERRIDE;
-  NS_IMETHOD GetChannel(nsIChannel** aChannel) MOZ_OVERRIDE;
-  NS_IMETHOD SynthesizeHeader(const nsACString& aName, const nsACString& aValue) MOZ_OVERRIDE;
-  NS_IMETHOD Cancel() MOZ_OVERRIDE;
+  NS_DECL_NSIINTERCEPTEDCHANNEL
 
   virtual void NotifyController() MOZ_OVERRIDE;
 };
diff --git a/netwerk/test/unit/test_synthesized_response.js b/netwerk/test/unit/test_synthesized_response.js
index 47b70f1b8061..00d489387aa8 100644
--- a/netwerk/test/unit/test_synthesized_response.js
+++ b/netwerk/test/unit/test_synthesized_response.js
@@ -55,19 +55,19 @@ function make_channel(url, body, cb) {
       this.numChecks++;
       return true;
     },
-    channelIntercepted: function(channel) {
+    channelIntercepted: function(channel, stream) {
       channel.QueryInterface(Ci.nsIInterceptedChannel);
       if (body) {
         var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
                             .createInstance(Ci.nsIStringInputStream);
         synthesized.data = body;
 
-        NetUtil.asyncCopy(synthesized, channel.responseBody, function() {
+        NetUtil.asyncCopy(synthesized, stream, function() {
           channel.finishSynthesizedResponse();
         });
       }
       if (cb) {
-        cb(channel);
+        cb(channel, stream);
       }
     },
   };
@@ -143,12 +143,12 @@ add_test(function() {
 
 // ensure that the channel waits for a decision and synthesizes headers correctly
 add_test(function() {
-  var chan = make_channel(URL + '/body', null, function(channel) {
+  var chan = make_channel(URL + '/body', null, function(channel, stream) {
     do_timeout(100, function() {
       var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
                           .createInstance(Ci.nsIStringInputStream);
       synthesized.data = NON_REMOTE_BODY;
-      NetUtil.asyncCopy(synthesized, channel.responseBody, function() {
+      NetUtil.asyncCopy(synthesized, stream, function() {
         channel.synthesizeHeader("Content-Length", NON_REMOTE_BODY.length);
         channel.finishSynthesizedResponse();
       });
@@ -169,12 +169,12 @@ add_test(function() {
 
 // ensure that the intercepted channel supports suspend/resume
 add_test(function() {
-  var chan = make_channel(URL + '/body', null, function(intercepted) {
+  var chan = make_channel(URL + '/body', null, function(intercepted, stream) {
     var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
                         .createInstance(Ci.nsIStringInputStream);
     synthesized.data = NON_REMOTE_BODY;
 
-    NetUtil.asyncCopy(synthesized, intercepted.responseBody, function() {
+    NetUtil.asyncCopy(synthesized, stream, function() {
       // set the content-type to ensure that the stream converter doesn't hold up notifications
       // and cause the test to fail
       intercepted.synthesizeHeader("Content-Type", "text/plain");
@@ -185,65 +185,6 @@ add_test(function() {
 				     CL_ALLOW_UNKNOWN_CL | CL_SUSPEND | CL_EXPECT_3S_DELAY), null);
 });
 
-// ensure that the intercepted channel can be cancelled
-add_test(function() {
-  var chan = make_channel(URL + '/body', null, function(intercepted) {
-    intercepted.cancel();
-  });
-  chan.asyncOpen(new ChannelListener(run_next_test, null,
-				     CL_EXPECT_FAILURE), null);
-});
-
-// ensure that the channel can't be cancelled via nsIInterceptedChannel after making a decision
-add_test(function() {
-  var chan = make_channel(URL + '/body', null, function(chan) {
-    chan.resetInterception();
-    do_timeout(0, function() {
-      var gotexception = false;
-      try {
-        chan.cancel();
-      } catch (x) {
-        gotexception = true;
-      }
-      do_check_true(gotexception);
-    });
-  });
-  chan.asyncOpen(new ChannelListener(handle_remote_response, null), null);
-});
-
-// ensure that the intercepted channel can be canceled during the response
-add_test(function() {
-  var chan = make_channel(URL + '/body', null, function(intercepted) {
-    var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
-                        .createInstance(Ci.nsIStringInputStream);
-    synthesized.data = NON_REMOTE_BODY;
-
-    NetUtil.asyncCopy(synthesized, intercepted.responseBody, function() {
-      let channel = intercepted.channel;
-      intercepted.finishSynthesizedResponse();
-      channel.cancel(Cr.NS_BINDING_ABORTED);
-    });
-  });
-  chan.asyncOpen(new ChannelListener(run_next_test, null,
-                                     CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL), null);
-});
-
-// ensure that the intercepted channel can be canceled before the response
-add_test(function() {
-  var chan = make_channel(URL + '/body', null, function(intercepted) {
-    var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
-                        .createInstance(Ci.nsIStringInputStream);
-    synthesized.data = NON_REMOTE_BODY;
-
-    NetUtil.asyncCopy(synthesized, intercepted.responseBody, function() {
-      intercepted.channel.cancel(Cr.NS_BINDING_ABORTED);
-      intercepted.finishSynthesizedResponse();
-    });
-  });
-  chan.asyncOpen(new ChannelListener(run_next_test, null,
-                                     CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL), null);
-});
-
 add_test(function() {
   httpServer.stop(run_next_test);
 });