DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (2b8364cfdb04)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set expandtab ts=2 sw=2 sts=2 cin: */
/* 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 InterceptedChannel_h
#define InterceptedChannel_h

#include "nsINetworkInterceptController.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Maybe.h"

class nsICacheEntry;
class nsInputStreamPump;
class nsIStreamListener;

namespace mozilla {
namespace net {

class nsHttpChannel;
class HttpChannelChild;
class nsHttpResponseHead;
class InterceptStreamListener;

// An object representing a channel that has been intercepted. This avoids
// complicating the actual channel implementation with the details of
// synthesizing responses.
class InterceptedChannelBase : public nsIInterceptedChannel {
 protected:
  // The interception controller to notify about the successful channel
  // interception
  nsCOMPtr<nsINetworkInterceptController> mController;

  // Response head for use when synthesizing
  Maybe<nsAutoPtr<nsHttpResponseHead>> mSynthesizedResponseHead;

  nsCOMPtr<nsIConsoleReportCollector> mReportCollector;
  nsCOMPtr<nsISupports> mReleaseHandle;

  bool mClosed;

  void EnsureSynthesizedResponse();
  void DoNotifyController();
  MOZ_MUST_USE nsresult DoSynthesizeStatus(uint16_t aStatus,
                                           const nsACString& aReason);
  MOZ_MUST_USE nsresult DoSynthesizeHeader(const nsACString& aName,
                                           const nsACString& aValue);

  TimeStamp mLaunchServiceWorkerStart;
  TimeStamp mLaunchServiceWorkerEnd;
  TimeStamp mDispatchFetchEventStart;
  TimeStamp mDispatchFetchEventEnd;
  TimeStamp mHandleFetchEventStart;
  TimeStamp mHandleFetchEventEnd;

  TimeStamp mFinishResponseStart;
  TimeStamp mFinishResponseEnd;
  enum { Invalid = 0, Synthesized, Reset } mSynthesizedOrReset;

  virtual ~InterceptedChannelBase() = default;

 public:
  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 GetConsoleReportCollector(
      nsIConsoleReportCollector** aCollectorOut) override;
  NS_IMETHOD SetReleaseHandle(nsISupports* aHandle) override;

  NS_IMETHODIMP
  SetLaunchServiceWorkerStart(TimeStamp aTimeStamp) override {
    mLaunchServiceWorkerStart = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  GetLaunchServiceWorkerStart(TimeStamp* aTimeStamp) override {
    MOZ_DIAGNOSTIC_ASSERT(aTimeStamp);
    *aTimeStamp = mLaunchServiceWorkerStart;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetLaunchServiceWorkerEnd(TimeStamp aTimeStamp) override {
    mLaunchServiceWorkerEnd = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  GetLaunchServiceWorkerEnd(TimeStamp* aTimeStamp) override {
    MOZ_DIAGNOSTIC_ASSERT(aTimeStamp);
    *aTimeStamp = mLaunchServiceWorkerEnd;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetDispatchFetchEventStart(TimeStamp aTimeStamp) override {
    mDispatchFetchEventStart = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetDispatchFetchEventEnd(TimeStamp aTimeStamp) override {
    mDispatchFetchEventEnd = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetHandleFetchEventStart(TimeStamp aTimeStamp) override {
    mHandleFetchEventStart = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetHandleFetchEventEnd(TimeStamp aTimeStamp) override {
    mHandleFetchEventEnd = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetFinishResponseStart(TimeStamp aTimeStamp) override {
    mFinishResponseStart = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetFinishSynthesizedResponseEnd(TimeStamp aTimeStamp) override {
    MOZ_ASSERT(mSynthesizedOrReset == Invalid);
    mSynthesizedOrReset = Synthesized;
    mFinishResponseEnd = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP
  SetChannelResetEnd(TimeStamp aTimeStamp) override {
    MOZ_ASSERT(mSynthesizedOrReset == Invalid);
    mSynthesizedOrReset = Reset;
    mFinishResponseEnd = aTimeStamp;
    return NS_OK;
  }

  NS_IMETHODIMP SaveTimeStamps() override;

  static already_AddRefed<nsIURI> SecureUpgradeChannelURI(nsIChannel* aChannel);
};

class InterceptedChannelContent : public InterceptedChannelBase {
  // The actual channel being intercepted.
  RefPtr<HttpChannelChild> mChannel;

  // Listener for the synthesized response to fix up the notifications before
  // they reach the actual channel.
  RefPtr<InterceptStreamListener> mStreamListener;

  // Set for intercepted channels that have gone through a secure upgrade.
  bool mSecureUpgrade;

 public:
  InterceptedChannelContent(HttpChannelChild* aChannel,
                            nsINetworkInterceptController* aController,
                            InterceptStreamListener* aListener,
                            bool aSecureUpgrade);

  NS_IMETHOD ResetInterception() override;
  NS_IMETHOD StartSynthesizedResponse(nsIInputStream* aBody,
                                      nsIInterceptedBodyCallback* aBodyCallback,
                                      nsICacheInfoChannel* aChannel,
                                      const nsACString& aFinalURLSpec,
                                      bool aResponseRedirected) override;
  NS_IMETHOD FinishSynthesizedResponse() override;
  NS_IMETHOD GetChannel(nsIChannel** aChannel) override;
  NS_IMETHOD GetSecureUpgradedChannelURI(nsIURI** aURI) override;
  NS_IMETHOD SynthesizeStatus(uint16_t aStatus,
                              const nsACString& aReason) override;
  NS_IMETHOD SynthesizeHeader(const nsACString& aName,
                              const nsACString& aValue) override;
  NS_IMETHOD CancelInterception(nsresult aStatus) override;
  NS_IMETHOD SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo) override;
  NS_IMETHOD GetInternalContentPolicyType(
      nsContentPolicyType* aInternalContentPolicyType) override;

  virtual void NotifyController() override;
};

}  // namespace net
}  // namespace mozilla

#endif  // InterceptedChannel_h