fune/netwerk/protocol/http/InterceptedHttpChannel.h
Brindusan Cristian f42618c99d Backed out 6 changesets (bug 1416879) for bc permafailures on windows on browser_multie10s_update.js r=backout a=backout
Backed out changeset 840a6e04bcea (bug 1416879)
Backed out changeset 994dc643a2ab (bug 1416879)
Backed out changeset 8e4fd74e7f5e (bug 1416879)
Backed out changeset 5453b8a58f0c (bug 1416879)
Backed out changeset d156f6b687e1 (bug 1416879)
Backed out changeset 714d3942fb10 (bug 1416879)
2018-01-07 11:55:44 +02:00

201 lines
6.9 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_net_InterceptedHttpChannel_h
#define mozilla_net_InterceptedHttpChannel_h
#include "HttpBaseChannel.h"
#include "nsINetworkInterceptController.h"
#include "nsIInputStream.h"
#include "nsICacheInfoChannel.h"
#include "nsIChannelWithDivertableParentListener.h"
#include "nsIThreadRetargetableRequest.h"
namespace mozilla {
namespace net {
// This class represents an http channel that is being intercepted by a
// ServiceWorker. This means that when the channel is opened a FetchEvent
// will be fired on the ServiceWorker thread. The channel will complete
// depending on what the worker does. The options are:
//
// 1. If the ServiceWorker does not handle the FetchEvent or does not call
// FetchEvent.respondWith(), then the channel needs to fall back to a
// normal request. When this happens ResetInterception() is called and
// the channel will perform an internal redirect back to an nsHttpChannel.
//
// 2. If the ServiceWorker provides a Response to FetchEvent.respondWith()
// then the status, headers, and body must be synthesized. When
// FinishSynthesizedResponse() is called the synthesized data must be
// reported back to the channel listener. This is handled in a few
// different ways:
// a. If a redirect was synthesized, then we perform the redirect to
// a new nsHttpChannel. This new channel might trigger yet another
// interception.
// b. If a same-origin or CORS Response was synthesized, then we simply
// crate an nsInputStreamPump to process it and call back to the
// listener.
// c. If an opaque Response was synthesized, then we perform an internal
// redirect to a new InterceptedHttpChannel using the cross-origin URL.
// When this new channel is opened, it then creates a pump as in case
// (b). The extra redirect here is to make sure the various listeners
// treat the result as unsafe cross-origin data.
//
// 3. If an error occurs, such as the ServiceWorker passing garbage to
// FetchEvent.respondWith(), then CancelInterception() is called. This is
// handled the same as a normal nsIChannel::Cancel() call. We abort the
// channel and end up calling OnStopRequest() with an error code.
class InterceptedHttpChannel final : public HttpBaseChannel
, public HttpAsyncAborter<InterceptedHttpChannel>
, public nsIInterceptedChannel
, public nsICacheInfoChannel
, public nsIAsyncVerifyRedirectCallback
, public nsIStreamListener
, public nsIChannelWithDivertableParentListener
, public nsIThreadRetargetableRequest
, public nsIThreadRetargetableStreamListener
{
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIINTERCEPTEDCHANNEL
NS_DECL_NSICACHEINFOCHANNEL
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSICHANNELWITHDIVERTABLEPARENTLISTENER
NS_DECL_NSITHREADRETARGETABLEREQUEST
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
private:
friend class HttpAsyncAborter<InterceptedHttpChannel>;
UniquePtr<nsHttpResponseHead> mSynthesizedResponseHead;
nsCOMPtr<nsIChannel> mRedirectChannel;
nsCOMPtr<nsIInputStream> mBodyReader;
nsCOMPtr<nsISupports> mReleaseHandle;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIInterceptedBodyCallback> mBodyCallback;
nsCOMPtr<nsICacheInfoChannel> mSynthesizedCacheInfo;
RefPtr<nsInputStreamPump> mPump;
RefPtr<ADivertableParentChannel> mParentChannel;
TimeStamp mFinishResponseStart;
TimeStamp mFinishResponseEnd;
Atomic<int64_t> mProgress;
int64_t mProgressReported;
int64_t mSynthesizedStreamLength;
uint64_t mResumeStartPos;
nsCString mResumeEntityId;
nsString mStatusHost;
enum {
Invalid = 0,
Synthesized,
Reset
} mSynthesizedOrReset;
Atomic<bool> mCallingStatusAndProgress;
bool mDiverting;
InterceptedHttpChannel(PRTime aCreationTime,
const TimeStamp& aCreationTimestamp,
const TimeStamp& aAsyncOpenTimestamp);
~InterceptedHttpChannel() = default;
virtual void
ReleaseListeners() override;
virtual MOZ_MUST_USE nsresult
SetupReplacementChannel(nsIURI *aURI, nsIChannel *aChannel,
bool aPreserveMethod,
uint32_t aRedirectFlags) override;
void
AsyncOpenInternal();
bool
ShouldRedirect() const;
nsresult
FollowSyntheticRedirect();
// If the response's URL is different from the request's then do a service
// worker redirect. If Response.redirected is false we do an internal
// redirect. Otherwise, if Response.redirect is true do a non-internal
// redirect so end consumers detect the redirected state.
nsresult
RedirectForResponseURL(nsIURI* aResponseURI, bool aResponseRedirected);
nsresult
StartPump();
nsresult
OpenRedirectChannel();
void
MaybeCallStatusAndProgress();
void
MaybeCallBodyCallback();
public:
static already_AddRefed<InterceptedHttpChannel>
CreateForInterception(PRTime aCreationTime, const TimeStamp& aCreationTimestamp,
const TimeStamp& aAsyncOpenTimestamp);
static already_AddRefed<InterceptedHttpChannel>
CreateForSynthesis(const nsHttpResponseHead* aHead, nsIInputStream* aBody,
nsIInterceptedBodyCallback* aBodyCallback,
PRTime aCreationTime,
const TimeStamp& aCreationTimestamp,
const TimeStamp& aAsyncOpenTimestamp);
NS_IMETHOD
Cancel(nsresult aStatus) override;
NS_IMETHOD
Suspend(void) override;
NS_IMETHOD
Resume(void) override;
NS_IMETHOD
GetSecurityInfo(nsISupports * *aSecurityInfo) override;
NS_IMETHOD
AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) override;
NS_IMETHOD
AsyncOpen2(nsIStreamListener *aListener) override;
NS_IMETHOD
LogBlockedCORSRequest(const nsAString & aMessage) override;
NS_IMETHOD
SetupFallbackChannel(const char * aFallbackKey) override;
NS_IMETHOD
GetResponseSynthesized(bool *aResponseSynthesized) override;
NS_IMETHOD
SetPriority(int32_t aPriority) override;
NS_IMETHOD
SetClassFlags(uint32_t aClassFlags) override;
NS_IMETHOD
ClearClassFlags(uint32_t flags) override;
NS_IMETHOD
AddClassFlags(uint32_t flags) override;
NS_IMETHOD
ResumeAt(uint64_t startPos, const nsACString & entityID) override;
void
DoNotifyListenerCleanup() override;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_InterceptedHttpChannel_h